X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fmisc%2Faudioscrobbler.c;h=15213061c9cc7959f523c30109de844712c3ee55;hb=6ee1e193fd896ab9a4729fde14f009d9ce629815;hp=cdccc20b891a552c35018477bd6a736e12e89184;hpb=d3fe7f28797d4dba65ffcdd60bf932e758a48a9e;p=vlc diff --git a/modules/misc/audioscrobbler.c b/modules/misc/audioscrobbler.c index cdccc20b89..15213061c9 100644 --- a/modules/misc/audioscrobbler.c +++ b/modules/misc/audioscrobbler.c @@ -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 * */ @@ -30,16 +30,11 @@ * Preamble *****************************************************************************/ -#define _GNU_SOURCE -#include #if defined( WIN32 ) #include #endif -/* - * TODO : - * check meta_engine's state, and remove delaying of metadata reading - */ + #include #include #include @@ -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