]> git.sesse.net Git - vlc/blobdiff - modules/access_output/shout.c
access_out_shoutcast: fix memleak.
[vlc] / modules / access_output / shout.c
index d3eea7f894d16444c31dbee29bdb88245aa01fd9..8bf0adaf9483c16c83ee48aa993329d4a4f41d93 100644 (file)
  * Preamble
  *****************************************************************************/
 
-#include <vlc/vlc.h>
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
 #include <vlc_sout.h>
 #include <vlc_block.h>
 
@@ -101,41 +106,41 @@ static void Close( vlc_object_t * );
                            "website. Requires the bitrate information specified for " \
                            "shoutcast. Requires Ogg streaming for icecast." )
 
-vlc_module_begin();
-    set_description( _("IceCAST output") );
-    set_shortname( "Shoutcast" );
-    set_capability( "sout access", 50 );
-    set_category( CAT_SOUT );
-    set_subcategory( SUBCAT_SOUT_ACO );
-    add_shortcut( "shout" );
+vlc_module_begin ()
+    set_description( N_("IceCAST output") )
+    set_shortname( "Shoutcast" )
+    set_capability( "sout access", 0 )
+    set_category( CAT_SOUT )
+    set_subcategory( SUBCAT_SOUT_ACO )
+    add_shortcut( "shout" )
     add_string( SOUT_CFG_PREFIX "name", "VLC media player - Live stream", NULL,
-                NAME_TEXT, NAME_LONGTEXT, VLC_FALSE );
+                NAME_TEXT, NAME_LONGTEXT, false )
     add_string( SOUT_CFG_PREFIX "description",
                  "Live stream from VLC media player", NULL,
-                DESCRIPTION_TEXT, DESCRIPTION_LONGTEXT, VLC_FALSE );
-    add_bool(   SOUT_CFG_PREFIX "mp3", VLC_FALSE, NULL,
-                MP3_TEXT, MP3_LONGTEXT, VLC_TRUE );
+                DESCRIPTION_TEXT, DESCRIPTION_LONGTEXT, false )
+    add_bool(   SOUT_CFG_PREFIX "mp3", false, NULL,
+                MP3_TEXT, MP3_LONGTEXT, true )
     add_string( SOUT_CFG_PREFIX "genre", "Alternative", NULL,
-                GENRE_TEXT, GENRE_LONGTEXT, VLC_FALSE );
+                GENRE_TEXT, GENRE_LONGTEXT, false )
     add_string( SOUT_CFG_PREFIX "url", "http://www.videolan.org/vlc", NULL,
-                URL_TEXT, URL_LONGTEXT, VLC_FALSE );
+                URL_TEXT, URL_LONGTEXT, false )
     add_string( SOUT_CFG_PREFIX "bitrate", "", NULL,
-                BITRATE_TEXT, BITRATE_LONGTEXT, VLC_FALSE );
+                BITRATE_TEXT, BITRATE_LONGTEXT, false )
     add_string( SOUT_CFG_PREFIX "samplerate", "", NULL,
-                SAMPLERATE_TEXT, SAMPLERATE_LONGTEXT, VLC_FALSE );
+                SAMPLERATE_TEXT, SAMPLERATE_LONGTEXT, false )
     add_string( SOUT_CFG_PREFIX "channels", "", NULL,
-                CHANNELS_TEXT, CHANNELS_LONGTEXT, VLC_FALSE );
+                CHANNELS_TEXT, CHANNELS_LONGTEXT, false )
     add_string( SOUT_CFG_PREFIX "quality", "", NULL,
-                QUALITY_TEXT, QUALITY_LONGTEXT, VLC_FALSE );
-    add_bool(   SOUT_CFG_PREFIX "public", VLC_FALSE, NULL,
-                PUBLIC_TEXT, PUBLIC_LONGTEXT, VLC_TRUE );
-    set_callbacks( Open, Close );
-vlc_module_end();
+                QUALITY_TEXT, QUALITY_LONGTEXT, false )
+    add_bool(   SOUT_CFG_PREFIX "public", false, NULL,
+                PUBLIC_TEXT, PUBLIC_LONGTEXT, true )
+    set_callbacks( Open, Close )
+vlc_module_end ()
 
 /*****************************************************************************
  * Exported prototypes
  *****************************************************************************/
-static const char *ppsz_sout_options[] = {
+static const char *const ppsz_sout_options[] = {
     "name", "description", "mp3", "genre", "url", "bitrate", "samplerate",
     "channels", "quality", "public", NULL
 };
@@ -146,6 +151,7 @@ static const char *ppsz_sout_options[] = {
  *****************************************************************************/
 static ssize_t Write( sout_access_out_t *, block_t * );
 static int Seek ( sout_access_out_t *, off_t  );
+static int Control( sout_access_out_t *, int, va_list );
 
 struct sout_access_out_sys_t
 {
@@ -162,24 +168,22 @@ static int Open( vlc_object_t *p_this )
     shout_t *p_shout;
     long i_ret;
     unsigned int i_port;
-    vlc_value_t val;
-
-    char *psz_accessname = NULL;
-    char *psz_parser = NULL;
-    char *psz_user = NULL;
-    char *psz_pass = NULL;
-    char *psz_host = NULL;
-    char *psz_mount = NULL;
-    char *psz_name = NULL;
-    char *psz_description = NULL;
-    char *tmp_port = NULL;
-    char *psz_genre = NULL;
-    char *psz_url = NULL;
+    char *psz_val;
+
+    char *psz_accessname;
+    char *psz_parser;
+    const char *psz_user;
+    const char *psz_pass;
+    const char *psz_host;
+    const char *psz_mount;
+    const char *psz_port;
+    char *psz_name;
+    char *psz_description;
+    char *psz_genre;
+    char *psz_url;
 
     config_ChainParse( p_access, SOUT_CFG_PREFIX, ppsz_sout_options, p_access->p_cfg );
 
-    psz_accessname = psz_parser = strdup( p_access->psz_path );
-
     if( !p_access->psz_path )
     {
         msg_Err( p_access,
@@ -187,6 +191,10 @@ static int Open( vlc_object_t *p_this )
         return VLC_EGENERIC;
     }
 
+    psz_accessname = psz_parser = strdup( p_access->psz_path );
+    if( !psz_parser )
+        return VLC_ENOMEM;
+
     /* Parse connection data user:pwd@host:port/mountpoint */
     psz_user = psz_parser;
     while( psz_parser[0] && psz_parser[0] != ':' ) psz_parser++;
@@ -197,44 +205,24 @@ static int Open( vlc_object_t *p_this )
     psz_host = psz_parser;
     while( psz_parser[0] && psz_parser[0] != ':' ) psz_parser++;
     if( psz_parser[0] ) { psz_parser[0] = 0; psz_parser++; }
-    tmp_port = psz_parser;
+    psz_port = psz_parser;
     while( psz_parser[0] && psz_parser[0] != '/' ) psz_parser++;
     if( psz_parser[0] ) { psz_parser[0] = 0; psz_parser++; }
     psz_mount = psz_parser;
 
-    i_port = atoi( tmp_port );
+    i_port = atoi( psz_port );
 
     p_sys = p_access->p_sys = malloc( sizeof( sout_access_out_sys_t ) );
     if( !p_sys )
     {
-        msg_Err( p_access, "out of memory" );
         free( psz_accessname );
         return VLC_ENOMEM;
     }
 
-    var_Get( p_access, SOUT_CFG_PREFIX "name", &val );
-    if( *val.psz_string )
-        psz_name = val.psz_string;
-    else
-        free( val.psz_string );
-
-    var_Get( p_access, SOUT_CFG_PREFIX "description", &val );
-    if( *val.psz_string )
-        psz_description = val.psz_string;
-    else
-        free( val.psz_string );
-
-    var_Get( p_access, SOUT_CFG_PREFIX "genre", &val );
-    if( *val.psz_string )
-        psz_genre = val.psz_string;
-    else
-        free( val.psz_string );
-
-    var_Get( p_access, SOUT_CFG_PREFIX "url", &val );
-    if( *val.psz_string )
-        psz_url = val.psz_string;
-    else
-        free( val.psz_string );
+    psz_name = var_GetNonEmptyString( p_access, SOUT_CFG_PREFIX "name" );
+    psz_description = var_GetNonEmptyString( p_access, SOUT_CFG_PREFIX "description" );
+    psz_genre = var_GetNonEmptyString( p_access, SOUT_CFG_PREFIX "genre" );
+    psz_url = var_GetNonEmptyString( p_access, SOUT_CFG_PREFIX "url" );
 
     p_shout = p_sys->p_shout = shout_new();
     if( !p_shout
@@ -256,16 +244,19 @@ static int Open( vlc_object_t *p_this )
                  psz_host, i_port, psz_mount );
         free( p_access->p_sys );
         free( psz_accessname );
+        free( psz_name );
+        free( psz_description );
+        free( psz_genre );
+        free( psz_url );
         return VLC_EGENERIC;
     }
 
-    if( psz_name ) free( psz_name );
-    if( psz_description ) free( psz_description );
-    if( psz_genre ) free( psz_genre );
-    if( psz_url ) free( psz_url );
+    free( psz_name );
+    free( psz_description );
+    free( psz_genre );
+    free( psz_url );
 
-    var_Get( p_access, SOUT_CFG_PREFIX "mp3", &val );
-    if( val.b_bool == VLC_TRUE )
+    if( var_GetBool( p_access, SOUT_CFG_PREFIX "mp3" ) )
         i_ret = shout_set_format( p_shout, SHOUT_FORMAT_MP3 );
     else
         i_ret = shout_set_format( p_shout, SHOUT_FORMAT_OGG );
@@ -280,10 +271,11 @@ static int Open( vlc_object_t *p_this )
 
     /* Don't force bitrate to 0 but only use when specified. This will otherwise
        show an empty field on icecast directory listing instead of NA */
-    var_Get( p_access, SOUT_CFG_PREFIX "bitrate", &val );
-    if( *val.psz_string )
+    psz_val = var_GetNonEmptyString( p_access, SOUT_CFG_PREFIX "bitrate" );
+    if( psz_val )
     {
-        i_ret = shout_set_audio_info( p_shout, SHOUT_AI_BITRATE, val.psz_string );
+        i_ret = shout_set_audio_info( p_shout, SHOUT_AI_BITRATE, psz_val );
+        free( psz_val );
         if( i_ret != SHOUTERR_SUCCESS )
         {
             msg_Err( p_access, "failed to set the information about the bitrate" );
@@ -298,17 +290,17 @@ static int Open( vlc_object_t *p_this )
            listings (sorting, stream info etc.) */
         msg_Warn( p_access, "no bitrate information specified (required for listing " \
                             "the server as public on the shoutcast website)" );
-        free( val.psz_string );
     }
 
     /* Information about samplerate, channels and quality will not be propagated
        through the YP protocol for icecast to the public directory listing when
        the icecast server is operating in shoutcast compatibility mode */
 
-    var_Get( p_access, SOUT_CFG_PREFIX "samplerate", &val );
-    if( *val.psz_string )
+    psz_val = var_GetNonEmptyString( p_access, SOUT_CFG_PREFIX "samplerate" );
+    if( psz_val )
     {
-        i_ret = shout_set_audio_info( p_shout, SHOUT_AI_SAMPLERATE, val.psz_string );
+        i_ret = shout_set_audio_info( p_shout, SHOUT_AI_SAMPLERATE, psz_val );
+        free( psz_val );
         if( i_ret != SHOUTERR_SUCCESS )
         {
             msg_Err( p_access, "failed to set the information about the samplerate" );
@@ -317,13 +309,12 @@ static int Open( vlc_object_t *p_this )
             return VLC_EGENERIC;
         }
     }
-    else
-        free( val.psz_string );
 
-    var_Get( p_access, SOUT_CFG_PREFIX "channels", &val );
-    if( *val.psz_string )
+    psz_val = var_GetNonEmptyString( p_access, SOUT_CFG_PREFIX "channels" );
+    if( psz_val )
     {
-        i_ret = shout_set_audio_info( p_shout, SHOUT_AI_CHANNELS, val.psz_string );
+        i_ret = shout_set_audio_info( p_shout, SHOUT_AI_CHANNELS, psz_val );
+        free( psz_val );
         if( i_ret != SHOUTERR_SUCCESS )
         {
             msg_Err( p_access, "failed to set the information about the number of channels" );
@@ -332,13 +323,12 @@ static int Open( vlc_object_t *p_this )
             return VLC_EGENERIC;
         }
     }
-    else
-        free( val.psz_string );
 
-    var_Get( p_access, SOUT_CFG_PREFIX "quality", &val );
-    if( *val.psz_string )
+    psz_val = var_GetNonEmptyString( p_access, SOUT_CFG_PREFIX "quality" );
+    if( psz_val )
     {
-        i_ret = shout_set_audio_info( p_shout, SHOUT_AI_QUALITY, val.psz_string );
+        i_ret = shout_set_audio_info( p_shout, SHOUT_AI_QUALITY, psz_val );
+        free( psz_val );
         if( i_ret != SHOUTERR_SUCCESS )
         {
             msg_Err( p_access, "failed to set the information about Ogg Vorbis quality" );
@@ -347,11 +337,8 @@ static int Open( vlc_object_t *p_this )
             return VLC_EGENERIC;
         }
     }
-    else
-        free( val.psz_string );
 
-    var_Get( p_access, SOUT_CFG_PREFIX "public", &val );
-    if( val.b_bool == VLC_TRUE )
+    if( var_GetBool( p_access, SOUT_CFG_PREFIX "public" ) )
     {
         i_ret = shout_set_public( p_shout, 1 );
         if( i_ret != SHOUTERR_SUCCESS )
@@ -445,16 +432,10 @@ static int Open( vlc_object_t *p_this )
 
     p_access->pf_write = Write;
     p_access->pf_seek  = Seek;
+    p_access->pf_control = Control;
 
     msg_Dbg( p_access, "shout access output opened (%s@%s:%i/%s)",
              psz_user, psz_host, i_port, psz_mount );
-
-    /* Update pace control flag */
-    if( p_access->psz_access && !strcmp( p_access->psz_access, "stream" ) )
-    {
-        p_access->p_sout->i_out_pace_nocontrol++;
-    }
-
     free( psz_accessname );
 
     return VLC_SUCCESS;
@@ -473,14 +454,24 @@ static void Close( vlc_object_t * p_this )
         shout_shutdown();
     }
     free( p_access->p_sys );
+    msg_Dbg( p_access, "shout access output closed" );
+}
 
-    /* Update pace control flag */
-    if( p_access->psz_access && !strcmp( p_access->psz_access, "stream" ) )
+static int Control( sout_access_out_t *p_access, int i_query, va_list args )
+{
+    switch( i_query )
     {
-        p_access->p_sout->i_out_pace_nocontrol--;
-    }
+        case ACCESS_OUT_CONTROLS_PACE:
+        {
+            bool *pb = va_arg( args, bool * );
+            *pb = strcmp( p_access->psz_access, "stream" );
+            break;
+        }
 
-    msg_Dbg( p_access, "shout access output closed" );
+        default:
+            return VLC_EGENERIC;
+    }
+    return VLC_SUCCESS;
 }
 
 /*****************************************************************************
@@ -521,6 +512,8 @@ static ssize_t Write( sout_access_out_t *p_access, block_t *p_buffer )
             else
             {
                 msg_Err( p_access, "failed to reconnect to server" );
+                block_ChainRelease (p_buffer);
+                return VLC_EGENERIC;
             }
 
         }
@@ -539,6 +532,7 @@ static ssize_t Write( sout_access_out_t *p_access, block_t *p_buffer )
  *****************************************************************************/
 static int Seek( sout_access_out_t *p_access, off_t i_pos )
 {
+    VLC_UNUSED(i_pos);
     msg_Err( p_access, "cannot seek on shout" );
     return VLC_EGENERIC;
 }