]> git.sesse.net Git - vlc/blobdiff - modules/misc/audioscrobbler.c
Removes trailing spaces. Removes tabs.
[vlc] / modules / misc / audioscrobbler.c
index cdccc20b891a552c35018477bd6a736e12e89184..15213061c9cc7959f523c30109de844712c3ee55 100644 (file)
@@ -22,7 +22,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
-/* audioscrobbler protocol version: 1.1 
+/* audioscrobbler protocol version: 1.1
  * http://audioscrobbler.net/wiki/Protocol1.1
  * */
 
  * Preamble
  *****************************************************************************/
 
-#define _GNU_SOURCE
-#include <string.h>
 
 #if defined( WIN32 )
 #include <time.h>
 #endif
-/*
- * TODO :
- * check meta_engine's state, and remove delaying of metadata reading
- */
+
 #include <vlc/vlc.h>
 #include <vlc_interface.h>
 #include <vlc_meta.h>
@@ -82,8 +77,7 @@ struct intf_sys_t
     vlc_mutex_t             lock;               /* p_sys mutex            */
 
     /* data about audioscrobbler session */
-    int                     i_interval;         /* last interval recorded */
-    time_t                  time_last_interval; /* when was it recorded ? */
+    time_t                  time_next_exchange; /* when can we send data? */
     char                    *psz_submit_host;   /* where to submit data ? */
     int                     i_submit_port;      /* at which port ?        */
     char                    *psz_submit_file;   /* in which file ?        */
@@ -106,6 +100,7 @@ intf_sys_t *p_sys_global;     /* to retrieve p_sys in Run() thread */
 static int  Open        ( vlc_object_t * );
 static void Close       ( vlc_object_t * );
 static void Run         ( intf_thread_t * );
+static void Main        ( intf_thread_t * );
 static int ItemChange   ( vlc_object_t *, const char *, vlc_value_t,
                                 vlc_value_t, void * );
 static int PlayingChange( vlc_object_t *, const char *, vlc_value_t,
@@ -113,7 +108,6 @@ static int PlayingChange( vlc_object_t *, const char *, vlc_value_t,
 static int AddToQueue   ( intf_thread_t *p_this );
 static int Handshake    ( intf_thread_t *p_sd );
 static int ReadMetaData ( intf_thread_t *p_this );
-static int ReadLocalMetaData( intf_thread_t *p_this, input_thread_t  *p_input );
 void DeleteQueue        ( audioscrobbler_queue_t *p_queue );
 
 /*****************************************************************************
@@ -156,7 +150,7 @@ vlc_module_begin();
     set_description( N_("Audioscrobbler submission Plugin") );
     add_string( "lastfm-username", "", NULL,
                 USERNAME_TEXT, USERNAME_LONGTEXT, VLC_FALSE );
-    add_string( "lastfm-password", "", NULL,
+    add_password( "lastfm-password", "", NULL,
                 PASSWORD_TEXT, PASSWORD_LONGTEXT, VLC_FALSE );
     set_capability( "interface", 0 );
     set_callbacks( Open, Close );
@@ -179,20 +173,20 @@ static int Open( vlc_object_t *p_this )
     free( p_sys ); \
     return VLC_ENOMEM;
 
-
     if( !p_sys )
     {
         MEM_ERROR
     }
 
+    p_intf->p_sys = p_sys;
+
     vlc_mutex_init( p_this, &p_sys->lock );
 
     p_sys_global = p_sys;
     p_sys->psz_submit_host = NULL;
     p_sys->psz_submit_file = NULL;
     p_sys->b_handshaked = VLC_FALSE;
-    p_sys->i_interval = 0;
-    p_sys->time_last_interval = time( NULL );
+    p_sys->time_next_exchange = time( NULL );
     p_sys->psz_username = NULL;
     p_sys->b_paused = VLC_FALSE;
 
@@ -211,6 +205,7 @@ static int Open( vlc_object_t *p_this )
 
     p_sys->p_current_song = malloc( sizeof( audioscrobbler_song_t ) );
     MALLOC_CHECK( p_sys->p_current_song )
+    time( &p_sys->p_current_song->time_playing );
 
     /* queues can't contain more than 10 songs */
     p_sys->p_first_queue->p_queue =
@@ -286,10 +281,19 @@ static void Close( vlc_object_t *p_this )
     free( p_sys );
 }
 
+/****************************************************************************
+ * Run : create Main() thread
+ * **************************************************************************/
+static void Run( intf_thread_t *p_intf )
+{
+    if( vlc_thread_create( p_intf, "Audioscrobbler", Main, 0, VLC_TRUE ) )
+        msg_Err( p_intf, "failed to create Audioscrobbler thread" );
+}
+
 /*****************************************************************************
- * Run : call Handshake() then submit songs
+ * Main : call Handshake() then submit songs
  *****************************************************************************/
-static void Run( intf_thread_t *p_this )
+static void Main( intf_thread_t *p_this )
 {
     char                    *psz_submit         = NULL;
     char                    *psz_submit_song    = NULL;
@@ -300,9 +304,10 @@ static void Run( intf_thread_t *p_this )
     char                    *p_buffer_pos       = NULL;
     audioscrobbler_queue_t  *p_first_queue;
     int                     i_post_socket;
-    /* TODO: remove when meta_engine works */
     time_t                  played_time;
 
+    vlc_thread_ready( p_this );
+
     p_this->p_sys = p_sys_global;
     intf_sys_t *p_sys = p_this->p_sys;
 
@@ -325,17 +330,16 @@ static void Run( intf_thread_t *p_this )
     /* main loop */
     while( !p_this->b_die )
     {
-        /* verify if there is data to submit 
+        /* verify if there is data to submit
          * and if waiting interval is elapsed */
         if ( ( p_sys->p_first_queue->i_songs_nb > 0 ) &&
-            ( time( NULL ) >=
-            ( p_sys->time_last_interval + p_sys->i_interval )  ) )
+            ( time( NULL ) >= p_sys->time_next_exchange ) )
         {
             /* handshake if needed */
             if( p_sys->b_handshaked == VLC_FALSE )
             {
                 msg_Dbg( p_this, "Handshaking with last.fm ..." );
+
                 switch( Handshake( p_this ) )
                 {
                     case VLC_ENOMEM:
@@ -347,7 +351,7 @@ static void Run( intf_thread_t *p_this )
                         vlc_mutex_unlock ( &p_sys->lock );
                         intf_UserFatal( p_this, VLC_FALSE,
                             _("Last.fm username not set"),
-                            _("Please set an username or disable"
+                            _("Please set an username or disable "
                             "audioscrobbler plugin, and then restart VLC.\n"
                             "Visit https://www.last.fm/join/ to get an account")
                         );
@@ -368,11 +372,15 @@ static void Run( intf_thread_t *p_this )
                     default:
                         /* protocol error : we'll try later */
                         vlc_mutex_lock ( &p_sys->lock );
-                        p_sys->i_interval = DEFAULT_INTERVAL;
-                        time( &p_sys->time_last_interval );
+                        time( &p_sys->time_next_exchange );
+                        p_sys->time_next_exchange += DEFAULT_INTERVAL;
                         vlc_mutex_unlock ( &p_sys->lock );
                         break;
                 }
+                /* handshake is done or failed, lets start from
+                 * beginning to check it out and wait INTERVAL if needed
+                 */
+                continue;
             }
 
             msg_Dbg( p_this, "Going to submit some data..." );
@@ -399,6 +407,16 @@ static void Run( intf_thread_t *p_this )
             i_post_socket = net_ConnectTCP( p_this,
                 p_sys->psz_submit_host, p_sys->i_submit_port);
 
+            if ( i_post_socket == -1 )
+            {
+                /* If connection fails, we assume we must handshake again */
+                time( &p_sys->time_next_exchange );
+                p_sys->time_next_exchange += DEFAULT_INTERVAL;
+                p_sys->b_handshaked = VLC_FALSE;
+                vlc_mutex_unlock( &p_sys->lock );
+                continue;
+            }
+
             /* we transmit the data */
             i_net_ret = net_Printf(
                 VLC_OBJECT(p_this), i_post_socket, NULL,
@@ -410,8 +428,8 @@ static void Run( intf_thread_t *p_this )
             if ( i_net_ret == -1 )
             {
                 /* If connection fails, we assume we must handshake again */
-                p_sys->i_interval = DEFAULT_INTERVAL;
-                time( &p_sys->time_last_interval );
+                time( &p_sys->time_next_exchange );
+                p_sys->time_next_exchange += DEFAULT_INTERVAL;
                 p_sys->b_handshaked = VLC_FALSE;
                 vlc_mutex_unlock( &p_sys->lock );
                 continue;
@@ -434,16 +452,16 @@ static void Run( intf_thread_t *p_this )
             p_buffer_pos = strstr( ( char * ) p_buffer, "INTERVAL" );
             if ( p_buffer_pos )
             {
-                p_sys->i_interval = atoi( p_buffer_pos +
+                time( &p_sys->time_next_exchange );
+                p_sys->time_next_exchange += atoi( p_buffer_pos +
                                             strlen( "INTERVAL " ) );
-                time( &p_sys->time_last_interval );
             }
 
             p_buffer_pos = strstr( ( char * ) p_buffer, "FAILED" );
             if ( p_buffer_pos )
             {
                 /* woops, submission failed */
-                msg_Dbg( p_this, p_buffer_pos );
+                msg_Dbg( p_this, "%s", p_buffer_pos );
                 vlc_mutex_unlock ( &p_sys->lock );
                 continue;
             }
@@ -497,15 +515,15 @@ static void Run( intf_thread_t *p_this )
         if( p_sys->b_metadata_read == VLC_FALSE )
         {
             /* we read the metadata of the playing song */
-            /* TODO: remove when meta_engine works */
             time( &played_time );
             played_time -= p_sys->p_current_song->time_playing;
             played_time -= p_sys->time_total_pauses;
 
             vlc_mutex_unlock( &p_sys->lock );
 
-            /* TODO: remove when meta_engine works */
-            if( played_time > 10 )
+            if( played_time > 20 )
+            /* wait at least 20 secondes before reading the meta data
+             * since the songs must be at least 30s */
             {
                 if ( ReadMetaData( p_this ) == VLC_ENOMEM )
                 {
@@ -591,12 +609,14 @@ static int ItemChange( vlc_object_t *p_this, const char *psz_var,
     {
         PL_UNLOCK;
         pl_Release( p_playlist );
+
         vlc_mutex_lock( &p_sys->lock );
 
         p_sys->b_queued = VLC_TRUE;
         p_sys->b_metadata_read = VLC_TRUE;
 
         vlc_mutex_unlock( &p_sys->lock );
+
         return VLC_SUCCESS;
     }
 
@@ -624,8 +644,10 @@ static int ItemChange( vlc_object_t *p_this, const char *psz_var,
     p_sys->p_current_song->psz_i = encode_URI_component( psz_date );
     p_sys->p_current_song->time_playing = epoch;
 
-    p_sys->b_paused = ( p_input->b_dead || !input_GetItem(p_input)->psz_name )
+    char *psz_name = input_item_GetName( input_GetItem( p_input ) );
+    p_sys->b_paused = ( p_input->b_dead || !psz_name )
                       ? VLC_TRUE : VLC_FALSE;
+    free( psz_name );
 
     vlc_mutex_unlock( &p_sys->lock );
 
@@ -737,7 +759,7 @@ static int Handshake( intf_thread_t *p_this )
     stream_t            *p_stream;
     char                *psz_handshake_url      = NULL;
     uint8_t             *p_buffer               = NULL;
-    char                *p_buffer_pos           = NULL; 
+    char                *p_buffer_pos           = NULL;
     char                *psz_url_parser         = NULL;
     char                *psz_buffer_substring;
     int                 i_url_pos, i;
@@ -810,15 +832,16 @@ static int Handshake( intf_thread_t *p_this )
     p_buffer_pos = strstr( ( char* ) p_buffer, "INTERVAL" );
     if ( p_buffer_pos )
     {
-        p_sys->i_interval = atoi( p_buffer_pos + strlen( "INTERVAL " ) );
-        time( &p_sys->time_last_interval );
+        time( &p_sys->time_next_exchange );
+        p_sys->time_next_exchange +=
+                atoi( p_buffer_pos + strlen( "INTERVAL " ) );
     }
 
     p_buffer_pos = strstr( ( char* ) p_buffer, "FAILED" );
     if ( p_buffer_pos )
     {
         /* handshake request failed, sorry */
-        msg_Dbg( p_this, p_buffer_pos );
+        msg_Dbg( p_this, "%s", p_buffer_pos );
         PROTOCOL_ERROR
     }
 
@@ -837,7 +860,7 @@ static int Handshake( intf_thread_t *p_this )
     {
         /* protocol has been updated, time to update the code */
         msg_Dbg( p_intf, "Protocol updated : plugin may be outdated" );
-        msg_Dbg( p_intf, p_buffer_pos );
+        msg_Dbg( p_intf, "%s", p_buffer_pos );
     }
 
     else
@@ -967,10 +990,17 @@ void DeleteQueue( audioscrobbler_queue_t *p_queue )
 static int ReadMetaData( intf_thread_t *p_this )
 {
     playlist_t          *p_playlist;
-    input_thread_t      *p_input    = NULL;
+    input_thread_t      *p_input        = NULL;
     vlc_value_t         video_val;
 
-    intf_sys_t          *p_sys      = p_this->p_sys;
+    char                *psz_title      = NULL;
+    char                *psz_artist     = NULL;
+    char                *psz_album      = NULL;
+    char                *psz_trackid    = NULL;
+    int                 i_length        = -1;
+    vlc_bool_t          b_waiting;
+    intf_sys_t          *p_sys          = p_this->p_sys;
+    int                 i_status;
 
     p_playlist = pl_Yield( p_this );
     PL_LOCK;
@@ -989,7 +1019,7 @@ static int ReadMetaData( intf_thread_t *p_this )
 
     var_Change( p_input, "video-es", VLC_VAR_CHOICESCOUNT, &video_val, NULL );
     if( ( video_val.i_int > 0 ) || \
-        ( input_GetItem(p_input)->i_type == ITEM_TYPE_NET ) )
+        ( input_GetItem( p_input )->i_type == ITEM_TYPE_NET ) )
     {
         msg_Dbg( p_this, "Not an audio only local file -> no submission");
         vlc_object_release( p_input );
@@ -1002,25 +1032,6 @@ static int ReadMetaData( intf_thread_t *p_this )
         return VLC_SUCCESS;
     }
 
-    return ReadLocalMetaData( p_this, p_input );    
-}
-
-/*****************************************************************************
- * ReadLocalMetaData : Puts current song's meta data in p_sys->p_current_song
- *****************************************************************************/
-static int ReadLocalMetaData( intf_thread_t *p_this, input_thread_t  *p_input )
-{
-    char                *psz_title      = NULL;
-    char                *psz_artist     = NULL;
-    char                *psz_album      = NULL;
-    char                *psz_trackid    = NULL;
-    int                 i_length        = -1;
-    vlc_bool_t          b_waiting;
-    intf_sys_t          *p_sys          = p_this->p_sys;
-    int                 i_status;
-
-    i_status = input_GetItem(p_input)->p_meta->i_status;
-
     #define FREE_INPUT_AND_CHARS \
         vlc_object_release( p_input ); \
         free( psz_title ); \
@@ -1043,49 +1054,62 @@ static int ReadLocalMetaData( intf_thread_t *p_this, input_thread_t  *p_input )
             return VLC_SUCCESS; \
         }
 
+    char *psz_meta;
     #define ALLOC_ITEM_META( a, b ) \
-        if ( input_GetItem(p_input)->b ) \
+        psz_meta = input_item_Get##b( input_GetItem( p_input ) ); \
+        if( psz_meta ) \
         { \
-            a = encode_URI_component( \
-                input_GetItem(p_input)->b ); \
+            a = encode_URI_component( psz_meta ); \
             if( !a ) \
             { \
+                free( psz_meta ); \
                 FREE_INPUT_AND_CHARS \
                 return VLC_ENOMEM; \
             } \
+            free( psz_meta ); \
         }
 
+    i_status = input_GetItem(p_input)->p_meta->i_status;
+
     vlc_mutex_lock( &p_sys->lock );
     b_waiting = p_sys->b_waiting_meta;
     vlc_mutex_unlock( &p_sys->lock );
 
-    /* TODO : replace 1 with ( i_status & ITEM_PREPARSED )
-     * when meta_engine works */
-    if ( ( b_waiting == VLC_FALSE ) ? 1 : ( i_status & ITEM_META_FETCHED ) )
+    if( i_status & ( !b_waiting ? ITEM_PREPARSED : ITEM_META_FETCHED ) )
     {
-        ALLOC_ITEM_META( psz_artist, p_meta->psz_artist )
+        ALLOC_ITEM_META( psz_artist, Artist )
         else
         {
             msg_Dbg( p_this, "No artist.." );
             WAIT_METADATA_FETCHING( psz_artist )
         }
-
-        ALLOC_ITEM_META( psz_title, psz_name )
+        psz_meta = input_item_GetTitle( input_GetItem( p_input ) );
+        if( psz_meta )
+        {
+            psz_title = encode_URI_component( psz_meta );
+            if( !psz_title )
+            {
+                free( psz_meta );
+                FREE_INPUT_AND_CHARS
+                return VLC_ENOMEM;
+            }
+            free( psz_meta );
+        }
         else
         {
             msg_Dbg( p_this, "No track name.." );
             WAIT_METADATA_FETCHING( psz_title );
         }
 
-        ALLOC_ITEM_META( psz_album, p_meta->psz_album )
+        ALLOC_ITEM_META( psz_album, Album )
         else
             psz_album = calloc( 1, 1 );
 
-        ALLOC_ITEM_META( psz_trackid, p_meta->psz_trackid )
+        ALLOC_ITEM_META( psz_trackid, TrackID )
         else
             psz_trackid = calloc( 1, 1 );
 
-        i_length = input_GetItem(p_input)->i_duration / 1000000;
+        i_length = input_item_GetDuration( input_GetItem( p_input ) ) / 1000000;
 
         vlc_mutex_lock ( &p_sys->lock );
 
@@ -1100,11 +1124,9 @@ static int ReadLocalMetaData( intf_thread_t *p_this, input_thread_t  *p_input )
         vlc_mutex_unlock( &p_sys->lock );
 
         msg_Dbg( p_this, "Meta data registered, waiting to be queued" );
-
-        FREE_INPUT_AND_CHARS
     }
-    
-    vlc_object_release( p_input );
+    FREE_INPUT_AND_CHARS
     return VLC_SUCCESS;
 #undef FREE_INPUT_AND_CHARS
 #undef ALLOC_ITEM_META