/*****************************************************************************
* raop.c: Remote Audio Output Protocol streaming support
*****************************************************************************
- * Copyright (C) 2008 the VideoLAN team
+ * Copyright (C) 2008 VLC authors and VideoLAN
* $Id$
*
* Author: Michael Hanselmann
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
#include <vlc_network.h>
#include <vlc_strings.h>
#include <vlc_charset.h>
+#include <vlc_fs.h>
#include <vlc_gcrypt.h>
#include <vlc_es.h>
#include <vlc_http.h>
+#include <vlc_memory.h>
#define RAOP_PORT 5000
#define RAOP_USER_AGENT "VLC " VERSION
static int Open( vlc_object_t * );
static void Close( vlc_object_t * );
-static sout_stream_id_t *Add( sout_stream_t *, es_format_t * );
-static int Del( sout_stream_t *, sout_stream_id_t * );
-static int Send( sout_stream_t *, sout_stream_id_t *, block_t* );
+static sout_stream_id_sys_t *Add( sout_stream_t *, es_format_t * );
+static int Del( sout_stream_t *, sout_stream_id_sys_t * );
+static int Send( sout_stream_t *, sout_stream_id_sys_t *, block_t* );
static int VolumeCallback( vlc_object_t *p_this, char const *psz_cmd,
vlc_value_t oldval, vlc_value_t newval,
int i_volume;
/* Plugin status */
- sout_stream_id_t *p_audio_stream;
+ sout_stream_id_sys_t *p_audio_stream;
bool b_alac_warning;
bool b_volume_callback;
uint8_t *p_sendbuf;
};
-struct sout_stream_id_t
+struct sout_stream_id_sys_t
{
es_format_t fmt;
};
add_shortcut( "raop" )
set_category( CAT_SOUT )
set_subcategory( SUBCAT_SOUT_STREAM )
- add_string( SOUT_CFG_PREFIX "host", "", NULL,
+ add_string( SOUT_CFG_PREFIX "host", "",
HOST_TEXT, HOST_LONGTEXT, false )
- add_password( SOUT_CFG_PREFIX "password", NULL, NULL,
+ add_password( SOUT_CFG_PREFIX "password", NULL,
PASSWORD_TEXT, PASSWORD_LONGTEXT, false )
- add_file( SOUT_CFG_PREFIX "password-file", NULL, NULL,
+ add_loadfile( SOUT_CFG_PREFIX "password-file", NULL,
PASSWORD_FILE_TEXT, PASSWORD_FILE_LONGTEXT, false )
- add_integer_with_range( SOUT_CFG_PREFIX "volume", 100, 0, 255, NULL,
+ add_integer_with_range( SOUT_CFG_PREFIX "volume", 100, 0, 255,
VOLUME_TEXT, VOLUME_LONGTEXT, false )
set_callbacks( Open, Close )
vlc_module_end()
free( p_sys );
}
-static void FreeId( sout_stream_id_t *id )
+static void FreeId( sout_stream_id_sys_t *id )
{
free( id );
}
unsigned char ps_padded_key[256];
unsigned char *ps_value;
size_t i_value_size;
- int i_err = VLC_SUCCESS;
+ int i_err;
/* Add RSA-OAES-SHA1 padding */
i_err = AddOaepPadding( p_this,
NULL, 0 );
if ( i_err != VLC_SUCCESS )
goto error;
+ i_err = VLC_EGENERIC;
/* Read public key */
i_gcrypt_err = gcry_mpi_scan( &mpi_pubkey, GCRYMPI_FMT_USG,
ps_raop_rsa_pubkey,
sizeof( ps_raop_rsa_pubkey ) - 1, NULL );
if ( CheckForGcryptError( p_stream, i_gcrypt_err ) )
- {
- i_err = VLC_EGENERIC;
goto error;
- }
/* Read exponent */
i_gcrypt_err = gcry_mpi_scan( &mpi_exp, GCRYMPI_FMT_USG, ps_raop_rsa_exp,
sizeof( ps_raop_rsa_exp ) - 1, NULL );
if ( CheckForGcryptError( p_stream, i_gcrypt_err ) )
- {
- i_err = VLC_EGENERIC;
goto error;
- }
/* If the input data starts with a set bit (0x80), gcrypt thinks it's a
* signed integer and complains. Prefixing it with a zero byte (\0)
ps_padded_key, sizeof( ps_padded_key ),
NULL);
if ( CheckForGcryptError( p_stream, i_gcrypt_err ) )
- {
- i_err = VLC_EGENERIC;
goto error;
- }
/* Build S-expression with RSA parameters */
i_gcrypt_err = gcry_sexp_build( &sexp_rsa_params, NULL,
"(public-key(rsa(n %m)(e %m)))",
mpi_pubkey, mpi_exp );
if ( CheckForGcryptError( p_stream, i_gcrypt_err ) )
- {
- i_err = VLC_EGENERIC;
goto error;
- }
/* Build S-expression for data */
i_gcrypt_err = gcry_sexp_build( &sexp_input, NULL, "(data(value %m))",
mpi_input );
if ( CheckForGcryptError( p_stream, i_gcrypt_err ) )
- {
- i_err = VLC_EGENERIC;
goto error;
- }
/* Encrypt data */
i_gcrypt_err = gcry_pk_encrypt( &sexp_encrypted, sexp_input,
sexp_rsa_params );
if ( CheckForGcryptError( p_stream, i_gcrypt_err ) )
- {
- i_err = VLC_EGENERIC;
goto error;
- }
/* Extract encrypted data */
sexp_token_a = gcry_sexp_find_token( sexp_encrypted, "a", 0 );
if ( !sexp_token_a )
{
msg_Err( p_this , "Token 'a' not found in result S-expression" );
- i_err = VLC_EGENERIC;
goto error;
}
if ( !mpi_output )
{
msg_Err( p_this, "Unable to extract MPI from result" );
- i_err = VLC_EGENERIC;
goto error;
}
mpi_output );
if ( CheckForGcryptError( p_stream, i_gcrypt_err ) )
{
- i_err = VLC_EGENERIC;
goto error;
}
/* Encode in Base64 */
*result = vlc_b64_encode_binary( ps_value, i_value_size );
+ i_err = VLC_SUCCESS;
error:
gcry_sexp_release( sexp_rsa_params );
char *psz_newline;
char ps_buffer[256];
- p_file = utf8_fopen( psz_path, "rt" );
+ p_file = vlc_fopen( psz_path, "rt" );
if ( p_file == NULL )
{
- msg_Err( p_this, "Unable to open password file '%s': %m", psz_path );
+ msg_Err( p_this, "Unable to open password file '%s': %s", psz_path,
+ vlc_strerror_c(errno) );
goto error;
}
{
if ( ferror( p_file ) )
{
- msg_Err( p_this, "Error reading '%s': %m", psz_path );
+ msg_Err( p_this, "Error reading '%s': %s", psz_path,
+ vlc_strerror_c(errno) );
goto error;
}
*psz_newline = '\0';
}
- if ( strlen( ps_buffer ) == 0 ) {
+ if ( *ps_buffer == '\0' ) {
msg_Err( p_this, "No password could be read from '%s'", psz_path );
goto error;
}
char *psz_line = NULL;
char *psz_token;
char *psz_next;
- int i_result;
+ int i_result = VLC_EGENERIC;
p_sys->psz_last_status_line = net_Gets( p_this, p_sys->i_control_fd,
NULL );
if ( !p_sys->psz_last_status_line )
- {
- i_result = VLC_EGENERIC;
goto error;
- }
/* Create working copy */
psz_line = strdup( p_sys->psz_last_status_line );
{
msg_Err( p_this, "Unknown protocol (%s)",
p_sys->psz_last_status_line );
- i_result = VLC_EGENERIC;
goto error;
}
{
msg_Err( p_this, "Request failed (%s)",
p_sys->psz_last_status_line );
- i_result = VLC_EGENERIC;
goto error;
}
/* Our volume is 0..255, RAOP is -144..0 (-144 off, -30..0 on) */
/* Limit range */
- p_sys->i_volume = __MAX( 0, __MIN( p_sys->i_volume, 255 ) );
+ p_sys->i_volume = VLC_CLIP( p_sys->i_volume, 0, 255 );
if ( p_sys->i_volume == 0 )
d_volume = -144.0;
/* Grow in blocks of 4K */
i_realloc_len = (1 + (i_len / 4096)) * 4096;
- p_sys->p_sendbuf = realloc( p_sys->p_sendbuf, i_realloc_len );
+ p_sys->p_sendbuf = realloc_or_free( p_sys->p_sendbuf, i_realloc_len );
if ( p_sys->p_sendbuf == NULL )
goto error;
p_sys = calloc( 1, sizeof( *p_sys ) );
if ( p_sys == NULL )
- {
- i_err = VLC_ENOMEM;
- goto error;
- }
+ return VLC_ENOMEM;
- p_stream->p_sys = p_sys;
p_stream->pf_add = Add;
p_stream->pf_del = Del;
p_stream->pf_send = Send;
- p_stream->p_sout->i_out_pace_nocontrol++;
+ p_stream->p_sys = p_sys;
+ p_stream->pace_nocontrol = true;
p_sys->i_control_fd = -1;
p_sys->i_stream_fd = -1;
RAOP_PORT );
if ( p_sys->i_control_fd < 0 )
{
- msg_Err( p_this, "Cannot establish control connection to %s:%d (%m)",
- p_sys->psz_host, RAOP_PORT );
+ msg_Err( p_this, "Cannot establish control connection to %s:%d (%s)",
+ p_sys->psz_host, RAOP_PORT, vlc_strerror_c(errno) );
i_err = VLC_EGENERIC;
goto error;
}
p_sys->i_server_port );
if ( p_sys->i_stream_fd < 0 )
{
- msg_Err( p_this, "Cannot establish stream connection to %s:%d (%m)",
- p_sys->psz_host, p_sys->i_server_port );
+ msg_Err( p_this, "Cannot establish stream connection to %s:%d (%s)",
+ p_sys->psz_host, p_sys->i_server_port,
+ vlc_strerror_c(errno) );
i_err = VLC_EGENERIC;
goto error;
}
SendTeardown( p_this );
FreeSys( p_this, p_sys );
-
- p_stream->p_sout->i_out_pace_nocontrol--;
}
/*****************************************************************************
* Add:
*****************************************************************************/
-static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
+static sout_stream_id_sys_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
{
sout_stream_sys_t *p_sys = p_stream->p_sys;
- sout_stream_id_t *id = NULL;
+ sout_stream_id_sys_t *id = NULL;
id = calloc( 1, sizeof( *id ) );
if ( id == NULL )
/*****************************************************************************
* Del:
*****************************************************************************/
-static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
+static int Del( sout_stream_t *p_stream, sout_stream_id_sys_t *id )
{
sout_stream_sys_t *p_sys = p_stream->p_sys;
int i_err = VLC_SUCCESS;
/*****************************************************************************
* Send:
*****************************************************************************/
-static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
+static int Send( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
block_t *p_buffer )
{
sout_stream_sys_t *p_sys = p_stream->p_sys;