]> git.sesse.net Git - vlc/blobdiff - modules/access_output/shout.c
Fix warnings.
[vlc] / modules / access_output / shout.c
index c07e437e23e6bfc23c4dba016f5404a7b3cad749..ad72311c0758d037dac2743e40de8f9ef2be9b56 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>
 
@@ -102,40 +107,40 @@ static void Close( vlc_object_t * );
                            "shoutcast. Requires Ogg streaming for icecast." )
 
 vlc_module_begin();
-    set_description( _("IceCAST output") );
+    set_description( N_("IceCAST output") );
     set_shortname( "Shoutcast" );
     set_capability( "sout access", 50 );
     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 );
+                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
 };
@@ -144,9 +149,8 @@ static const char *ppsz_sout_options[] = {
 /*****************************************************************************
  * Exported prototypes
  *****************************************************************************/
-static int Write( sout_access_out_t *, block_t * );
+static ssize_t Write( sout_access_out_t *, block_t * );
 static int Seek ( sout_access_out_t *, off_t  );
-static int Read ( sout_access_out_t *, block_t * );
 
 struct sout_access_out_sys_t
 {
@@ -180,6 +184,8 @@ static int Open( vlc_object_t *p_this )
     config_ChainParse( p_access, SOUT_CFG_PREFIX, ppsz_sout_options, p_access->p_cfg );
 
     psz_accessname = psz_parser = strdup( p_access->psz_path );
+    if( !psz_parser )
+        return VLC_ENOMEM;
 
     if( !p_access->psz_path )
     {
@@ -208,7 +214,6 @@ static int Open( vlc_object_t *p_this )
     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;
     }
@@ -260,13 +265,13 @@ static int Open( vlc_object_t *p_this )
         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( val.b_bool == true )
         i_ret = shout_set_format( p_shout, SHOUT_FORMAT_MP3 );
     else
         i_ret = shout_set_format( p_shout, SHOUT_FORMAT_OGG );
@@ -352,7 +357,7 @@ static int Open( vlc_object_t *p_this )
         free( val.psz_string );
 
     var_Get( p_access, SOUT_CFG_PREFIX "public", &val );
-    if( val.b_bool == VLC_TRUE )
+    if( val.b_bool == true )
     {
         i_ret = shout_set_public( p_shout, 1 );
         if( i_ret != SHOUTERR_SUCCESS )
@@ -364,17 +369,10 @@ static int Open( vlc_object_t *p_this )
         }
     }
 
-    /* Shoutcast using ICY protocol */
-    i_ret = shout_open( p_shout );
-    if( i_ret == SHOUTERR_SUCCESS )
-    {
-        i_ret = SHOUTERR_CONNECTED;
-        msg_Dbg( p_access, "connected using 'icy' (shoutcast) protocol" );
-    }
-    else
+    /* Connect at startup. Cycle through the possible protocols. */
+    i_ret = shout_get_connected( p_shout );
+    while ( i_ret != SHOUTERR_CONNECTED )
     {
-        msg_Warn( p_access, "failed to connect using 'icy' (shoutcast) protocol" );
-
         /* Shout parameters cannot be changed on an open connection */
         i_ret = shout_close( p_shout );
         if( i_ret == SHOUTERR_SUCCESS )
@@ -382,34 +380,66 @@ static int Open( vlc_object_t *p_this )
             i_ret = SHOUTERR_UNCONNECTED;
         }
 
-        /* IceCAST using HTTP protocol */
-        i_ret = shout_set_protocol( p_shout, SHOUT_PROTOCOL_HTTP );
+        /* Re-initialize for Shoutcast using ICY protocol. Not needed for initial connection
+           but it is when we are reconnecting after other protocol was tried. */
+        i_ret = shout_set_protocol( p_shout, SHOUT_PROTOCOL_ICY );
         if( i_ret != SHOUTERR_SUCCESS )
         {
-            msg_Err( p_access, "failed to set the protocol to 'http'" );
+            msg_Err( p_access, "failed to set the protocol to 'icy'" );
             free( p_access->p_sys );
             free( psz_accessname );
             return VLC_EGENERIC;
         }
-
         i_ret = shout_open( p_shout );
         if( i_ret == SHOUTERR_SUCCESS )
         {
             i_ret = SHOUTERR_CONNECTED;
-            msg_Dbg( p_access, "connected using 'http' (icecast 2.x) protocol" );
+            msg_Dbg( p_access, "connected using 'icy' (shoutcast) protocol" );
         }
         else
-            msg_Warn( p_access, "failed to connect using 'http' (icecast 2.x) protocol " );
-    }
+        {
+            msg_Warn( p_access, "failed to connect using 'icy' (shoutcast) protocol" );
 
+            /* Shout parameters cannot be changed on an open connection */
+            i_ret = shout_close( p_shout );
+            if( i_ret == SHOUTERR_SUCCESS )
+            {
+                i_ret = SHOUTERR_UNCONNECTED;
+            }
+
+            /* IceCAST using HTTP protocol */
+            i_ret = shout_set_protocol( p_shout, SHOUT_PROTOCOL_HTTP );
+            if( i_ret != SHOUTERR_SUCCESS )
+            {
+                msg_Err( p_access, "failed to set the protocol to 'http'" );
+                free( p_access->p_sys );
+                free( psz_accessname );
+                return VLC_EGENERIC;
+            }
+            i_ret = shout_open( p_shout );
+            if( i_ret == SHOUTERR_SUCCESS )
+            {
+                i_ret = SHOUTERR_CONNECTED;
+                msg_Dbg( p_access, "connected using 'http' (icecast 2.x) protocol" );
+            }
+            else
+                msg_Warn( p_access, "failed to connect using 'http' (icecast 2.x) protocol " );
+        }
 /*
-    for non-blocking, use:
-    while( i_ret == SHOUTERR_BUSY )
-    {
-        sleep( 1 );
-        i_ret = shout_get_connected( p_shout );
-    }
+        for non-blocking, use:
+        while( i_ret == SHOUTERR_BUSY )
+        {
+            sleep( 1 );
+            i_ret = shout_get_connected( p_shout );
+        }
 */
+        if ( i_ret != SHOUTERR_CONNECTED )
+       {
+           msg_Warn( p_access, "unable to establish connection, retrying..." );
+            msleep( 30000000 );
+        }
+    }
+
     if( i_ret != SHOUTERR_CONNECTED )
     {
         msg_Err( p_access, "failed to open shout stream to %s:%i/%s: %s",
@@ -420,7 +450,6 @@ static int Open( vlc_object_t *p_this )
     }
 
     p_access->pf_write = Write;
-    p_access->pf_read  = Read;
     p_access->pf_seek  = Seek;
 
     msg_Dbg( p_access, "shout access output opened (%s@%s:%i/%s)",
@@ -460,22 +489,12 @@ static void Close( vlc_object_t * p_this )
     msg_Dbg( p_access, "shout access output closed" );
 }
 
-/*****************************************************************************
- * Read: standard read -- not supported
- *****************************************************************************/
-static int Read( sout_access_out_t *p_access, block_t *p_buffer )
-{
-    msg_Err( p_access, "cannot read from shout" );
-    return VLC_EGENERIC;
-}
-
 /*****************************************************************************
  * Write: standard write
  *****************************************************************************/
-static int Write( sout_access_out_t *p_access, block_t *p_buffer )
+static ssize_t Write( sout_access_out_t *p_access, block_t *p_buffer )
 {
     size_t i_write = 0;
-    long i_ret;
 
     shout_sync( p_access->p_sys->p_shout );
     while( p_buffer )
@@ -493,17 +512,23 @@ static int Write( sout_access_out_t *p_access, block_t *p_buffer )
             msg_Err( p_access, "cannot write to stream: %s",
                      shout_get_error(p_access->p_sys->p_shout) );
 
-            /* This can be caused by a server disconnect. Reconnecting might help... */
+            /* The most common cause seems to be a server disconnect, resulting in a
+               Socket Error which can only be fixed by closing and reconnecting.
+               Since we already began with a working connection, the most feasable
+               approach to get out of this error status is a (timed) reconnect approach. */
             shout_close( p_access->p_sys->p_shout );
-            msg_Warn( p_access, "server unavailable? waiting 30 seconds to reconnect..." );
-            msleep( 30000000 );
+            msg_Warn( p_access, "server unavailable? trying to reconnect..." );
+            /* Re-open the connection (protocol params have already been set) and re-sync */
             if( shout_open( p_access->p_sys->p_shout ) == SHOUTERR_SUCCESS )
             {
+                shout_sync( p_access->p_sys->p_shout );
                 msg_Warn( p_access, "reconnected to server" );
             }
             else
             {
                 msg_Err( p_access, "failed to reconnect to server" );
+                block_ChainRelease (p_buffer);
+                return VLC_EGENERIC;
             }
 
         }