From: Rafaël Carré Date: Mon, 8 Oct 2007 00:36:36 +0000 (+0000) Subject: audioscrobbler: use condition variables to be signaled when there are songs to be... X-Git-Tag: 0.9.0-test0~5171 X-Git-Url: http://git.videolan.org/gitweb.cgi/vlc.git/?p=vlc.git;p=vlc.git;a=commitdiff_plain;h=7de663b7317b3514f4a6c26c7685da9403da7c02;ds=sidebyside audioscrobbler: use condition variables to be signaled when there are songs to be submitted. checks if playlist has been stopped in the input "state" callback holds the p_sys mutex only when writing/reading audioscrobbler_song_t data --- diff --git a/modules/misc/audioscrobbler.c b/modules/misc/audioscrobbler.c index 980f2684a4..23142bf6dd 100644 --- a/modules/misc/audioscrobbler.c +++ b/modules/misc/audioscrobbler.c @@ -93,7 +93,6 @@ struct intf_sys_t time_t time_total_pauses; /**< total time in pause */ vlc_bool_t b_submit; /**< do we have to submit ? */ - vlc_bool_t b_paused; /**< is vlc paused ? */ vlc_bool_t b_state_cb; /**< if we registered the * "state" callback */ @@ -270,211 +269,191 @@ static void Main( intf_thread_t *p_intf ) char *psz_submit, *psz_submit_song, *psz_submit_tmp; int i_net_ret; int i_song; - playlist_t *p_playlist; uint8_t p_buffer[1024]; char *p_buffer_pos; int i_post_socket; + vlc_bool_t b_die; intf_sys_t *p_sys = p_intf->p_sys; /* main loop */ while( !p_intf->b_die && !p_intf->p_libvlc->b_die ) { - /* verify if there is data to submit - * and if waiting interval is elapsed */ - if ( ( p_sys->i_songs > 0 ) && - ( time( NULL ) >= p_sys->next_exchange ) ) + /* waiting for data to submit, if waiting interval is elapsed */ + vlc_object_lock( p_intf ); + if( time( NULL ) < p_sys->next_exchange ) + b_die = vlc_object_timedwait( p_intf, p_sys->next_exchange ); + else + b_die = vlc_object_wait( p_intf ); + vlc_object_unlock( p_intf ); + + if( b_die ) + return; + + /* handshake if needed */ + if( p_sys->b_handshaked == VLC_FALSE ) { - /* handshake if needed */ - if( p_sys->b_handshaked == VLC_FALSE ) + msg_Dbg( p_intf, "Handshaking with last.fm ..." ); + + switch( Handshake( p_intf ) ) { - msg_Dbg( p_intf, "Handshaking with last.fm ..." ); - - switch( Handshake( p_intf ) ) - { - case VLC_ENOMEM: - Unload( p_intf ); - return; - - case VLC_ENOVAR: - /* username not set */ - intf_UserFatal( p_intf, VLC_FALSE, - _("Last.fm username not set"), - _("Please set an username or disable " - "audioscrobbler plugin, and then restart VLC.\n" - "Visit https://www.last.fm/join/ to get an account") - ); - Unload( p_intf ); - return; - - case VLC_SUCCESS: - msg_Dbg( p_intf, "Handshake successfull :)" ); - vlc_mutex_lock ( &p_sys->lock ); - p_sys->b_handshaked = VLC_TRUE; - p_sys->i_interval = 0; - time( &p_sys->next_exchange ); - vlc_mutex_unlock ( &p_sys->lock ); - break; - - case VLC_AUDIOSCROBBLER_EFATAL: - msg_Warn( p_intf, "Unloading..." ); - Unload( p_intf ); - return; - - case VLC_EGENERIC: - default: - /* protocol error : we'll try later */ - vlc_mutex_lock ( &p_sys->lock ); - HandleInterval( &p_sys->next_exchange, - &p_sys->i_interval ); - vlc_mutex_unlock ( &p_sys->lock ); - break; - } - /* handshake is finished, let's restart the loop */ - continue; + case VLC_ENOMEM: + Unload( p_intf ); + return; + + case VLC_ENOVAR: + /* username not set */ + intf_UserFatal( p_intf, VLC_FALSE, + _("Last.fm username not set"), + _("Please set an username or disable " + "audioscrobbler plugin, and then restart VLC.\n" + "Visit https://www.last.fm/join/ to get an account") + ); + Unload( p_intf ); + return; + + case VLC_SUCCESS: + msg_Dbg( p_intf, "Handshake successfull :)" ); + p_sys->b_handshaked = VLC_TRUE; + p_sys->i_interval = 0; + time( &p_sys->next_exchange ); + break; + + case VLC_AUDIOSCROBBLER_EFATAL: + msg_Warn( p_intf, "Unloading..." ); + Unload( p_intf ); + return; + + case VLC_EGENERIC: + default: + /* protocol error : we'll try later */ + HandleInterval( &p_sys->next_exchange, &p_sys->i_interval ); + break; } + /* if handshake failed let's restart the loop */ + if( p_sys->b_handshaked == VLC_FALSE ) + continue; + } + + msg_Dbg( p_intf, "Going to submit some data..." ); - msg_Dbg( p_intf, "Going to submit some data..." ); - vlc_mutex_lock ( &p_sys->lock ); + if( !asprintf( &psz_submit, "s=%s", p_sys->psz_auth_token ) ) + { /* Out of memory */ + Unload( p_intf ); + return; + } - if( !asprintf( &psz_submit, "s=%s", p_sys->psz_auth_token ) ) + /* forge the HTTP POST request */ + vlc_mutex_lock( &p_sys->lock ); + audioscrobbler_song_t *p_song; + for( i_song = 0 ; i_song < p_sys->i_songs ; i_song++ ) + { + p_song = &p_sys->p_queue[i_song]; + if( !asprintf( &psz_submit_song, + "&a%%5B%d%%5D=%s&t%%5B%d%%5D=%s" + "&i%%5B%d%%5D=%llu&o%%5B%d%%5D=P&r%%5B%d%%5D=" + "&l%%5B%d%%5D=%d&b%%5B%d%%5D=%s" + "&n%%5B%d%%5D=%s&m%%5B%d%%5D=%s", + i_song, p_song->psz_a, i_song, p_song->psz_t, + i_song, (uintmax_t)p_song->date, i_song, i_song, + i_song, p_song->i_l, i_song, p_song->psz_b, + i_song, p_song->psz_n, i_song, p_song->psz_m + ) ) { /* Out of memory */ vlc_mutex_unlock( &p_sys->lock ); Unload( p_intf ); return; } - - /* forge the HTTP POST request */ - audioscrobbler_song_t *p_song; - for( i_song = 0 ; i_song < p_sys->i_songs ; i_song++ ) - { - p_song = &p_sys->p_queue[i_song]; - if( !asprintf( &psz_submit_song, - "&a%%5B%d%%5D=%s&t%%5B%d%%5D=%s" - "&i%%5B%d%%5D=%llu&o%%5B%d%%5D=P&r%%5B%d%%5D=" - "&l%%5B%d%%5D=%d&b%%5B%d%%5D=%s" - "&n%%5B%d%%5D=%s&m%%5B%d%%5D=%s", - i_song, p_song->psz_a, i_song, p_song->psz_t, - i_song, (uintmax_t)p_song->date, i_song, i_song, - i_song, p_song->i_l, i_song, p_song->psz_b, - i_song, p_song->psz_n, i_song, p_song->psz_m - ) ) - { /* Out of memory */ - vlc_mutex_unlock( &p_sys->lock ); - Unload( p_intf ); - return; - } - psz_submit_tmp = psz_submit; - if( !asprintf( &psz_submit, "%s%s", - psz_submit_tmp, psz_submit_song ) ) - { /* Out of memory */ - free( psz_submit_tmp ); - free( psz_submit_song ); - vlc_mutex_unlock( &p_sys->lock ); - Unload( p_intf ); - return; - } - free( psz_submit_song ); + psz_submit_tmp = psz_submit; + if( !asprintf( &psz_submit, "%s%s", + psz_submit_tmp, psz_submit_song ) ) + { /* Out of memory */ free( psz_submit_tmp ); - } - - i_post_socket = net_ConnectTCP( p_intf, - p_sys->psz_submit_host, p_sys->i_submit_port ); - - if ( i_post_socket == -1 ) - { - /* If connection fails, we assume we must handshake again */ - HandleInterval( &p_sys->next_exchange, &p_sys->i_interval ); - p_sys->b_handshaked = VLC_FALSE; + free( psz_submit_song ); vlc_mutex_unlock( &p_sys->lock ); - free( psz_submit ); - continue; + Unload( p_intf ); + return; } + free( psz_submit_song ); + free( psz_submit_tmp ); + } + vlc_mutex_unlock( &p_sys->lock ); - /* we transmit the data */ - i_net_ret = net_Printf( - VLC_OBJECT( p_intf ), i_post_socket, NULL, - POST_REQUEST, p_sys->psz_submit_file, - (unsigned)strlen( psz_submit ), p_sys->psz_submit_file, - VERSION, psz_submit - ); + i_post_socket = net_ConnectTCP( p_intf, + p_sys->psz_submit_host, p_sys->i_submit_port ); + if ( i_post_socket == -1 ) + { + /* If connection fails, we assume we must handshake again */ + HandleInterval( &p_sys->next_exchange, &p_sys->i_interval ); + p_sys->b_handshaked = VLC_FALSE; free( psz_submit ); - if ( i_net_ret == -1 ) - { - /* If connection fails, we assume we must handshake again */ - HandleInterval( &p_sys->next_exchange, &p_sys->i_interval ); - p_sys->b_handshaked = VLC_FALSE; - vlc_mutex_unlock( &p_sys->lock ); - continue; - } + continue; + } - i_net_ret = net_Read( p_intf, i_post_socket, NULL, - p_buffer, 1023, VLC_FALSE ); - if ( i_net_ret <= 0 ) - { - /* if we get no answer, something went wrong : try again */ - vlc_mutex_unlock( &p_sys->lock ); - continue; - } + /* we transmit the data */ + i_net_ret = net_Printf( + VLC_OBJECT( p_intf ), i_post_socket, NULL, + POST_REQUEST, p_sys->psz_submit_file, + (unsigned)strlen( psz_submit ), p_sys->psz_submit_file, + VERSION, psz_submit + ); - net_Close( i_post_socket ); - p_buffer[i_net_ret] = '\0'; + free( psz_submit ); + if ( i_net_ret == -1 ) + { + /* If connection fails, we assume we must handshake again */ + HandleInterval( &p_sys->next_exchange, &p_sys->i_interval ); + p_sys->b_handshaked = VLC_FALSE; + continue; + } - p_buffer_pos = strstr( ( char * ) p_buffer, "FAILED" ); - if ( p_buffer_pos ) - { - msg_Warn( p_intf, "%s", p_buffer_pos ); - HandleInterval( &p_sys->next_exchange, &p_sys->i_interval ); - vlc_mutex_unlock ( &p_sys->lock ); - continue; - } + i_net_ret = net_Read( p_intf, i_post_socket, NULL, + p_buffer, 1023, VLC_FALSE ); + if ( i_net_ret <= 0 ) + { + /* if we get no answer, something went wrong : try again */ + continue; + } - p_buffer_pos = strstr( ( char * ) p_buffer, "BADSESSION" ); - if ( p_buffer_pos ) - { - msg_Dbg( p_intf, "Authentification failed, handshaking again" ); - p_sys->b_handshaked = VLC_FALSE; - HandleInterval( &p_sys->next_exchange, &p_sys->i_interval ); - vlc_mutex_unlock ( &p_sys->lock ); - continue; - } + net_Close( i_post_socket ); + p_buffer[i_net_ret] = '\0'; - p_buffer_pos = strstr( ( char * ) p_buffer, "OK" ); - if ( p_buffer_pos ) - { - int i; - for( i = 0; i < p_sys->i_songs; i++ ) - DeleteSong( &p_sys->p_queue[i] ); - p_sys->i_songs = 0; - p_sys->i_interval = 0; - time( &p_sys->next_exchange ); - msg_Dbg( p_intf, "Submission successfull!" ); - } - else - { - msg_Dbg( p_intf, "Authentification failed, handshaking again" ); - p_sys->b_handshaked = VLC_FALSE; - HandleInterval( &p_sys->next_exchange, &p_sys->i_interval ); - vlc_mutex_unlock ( &p_sys->lock ); - continue; - } - vlc_mutex_unlock ( &p_sys->lock ); - } /* data transmission finished or skipped */ + p_buffer_pos = strstr( ( char * ) p_buffer, "FAILED" ); + if ( p_buffer_pos ) + { + msg_Warn( p_intf, "%s", p_buffer_pos ); + HandleInterval( &p_sys->next_exchange, &p_sys->i_interval ); + continue; + } - msleep( INTF_IDLE_SLEEP ); + p_buffer_pos = strstr( ( char * ) p_buffer, "BADSESSION" ); + if ( p_buffer_pos ) + { + msg_Dbg( p_intf, "Authentification failed, handshaking again" ); + p_sys->b_handshaked = VLC_FALSE; + HandleInterval( &p_sys->next_exchange, &p_sys->i_interval ); + continue; + } - p_playlist = pl_Yield( p_intf ); - PL_LOCK; - if( p_playlist->request.i_status == PLAYLIST_STOPPED ) + p_buffer_pos = strstr( ( char * ) p_buffer, "OK" ); + if ( p_buffer_pos ) { - /* if we stopped, we won't submit playing song */ - vlc_mutex_lock( &p_sys->lock ); - p_sys->b_submit = VLC_FALSE; - vlc_mutex_unlock( &p_sys->lock ); + int i; + for( i = 0; i < p_sys->i_songs; i++ ) + DeleteSong( &p_sys->p_queue[i] ); + p_sys->i_songs = 0; + p_sys->i_interval = 0; + time( &p_sys->next_exchange ); + msg_Dbg( p_intf, "Submission successfull!" ); + } + else + { + msg_Dbg( p_intf, "Authentification failed, handshaking again" ); + p_sys->b_handshaked = VLC_FALSE; + HandleInterval( &p_sys->next_exchange, &p_sys->i_interval ); + continue; } - PL_UNLOCK; - pl_Release( p_playlist ); } } @@ -492,21 +471,22 @@ static int PlayingChange( vlc_object_t *p_this, const char *psz_var, if( p_intf->b_dead ) return VLC_SUCCESS; - vlc_mutex_lock( &p_sys->lock ); - - if( oldval.i_int == PLAYING_S && newval.i_int == PAUSE_S ) + if( newval.i_int == END_S || newval.i_int == ERROR_S ) { - time( &p_sys->time_pause ); - p_sys->b_paused = VLC_TRUE; + playlist_t *p_playlist = pl_Yield( p_intf ); + PL_LOCK; + if( p_playlist->request.i_status == PLAYLIST_STOPPED ) + { + /* if we stopped, we won't submit playing song */ + p_sys->b_submit = VLC_FALSE; + } + PL_UNLOCK; + pl_Release( p_playlist ); } - + else if( oldval.i_int == PLAYING_S && newval.i_int == PAUSE_S ) + time( &p_sys->time_pause ); else if( oldval.i_int == PAUSE_S && newval.i_int == PLAYING_S ) - { p_sys->time_total_pauses += time( NULL ) - p_sys->time_pause; - p_sys->b_paused = VLC_FALSE; - } - - vlc_mutex_unlock( &p_sys->lock ); return VLC_SUCCESS; } @@ -522,9 +502,7 @@ static int MetaPreparsed( vlc_object_t *p_this, const char *psz_var, if( p_intf->b_dead ) return VLC_SUCCESS; - vlc_mutex_lock( &p_intf->p_sys->lock ); ReadMetaData( p_intf ); - vlc_mutex_unlock( &p_intf->p_sys->lock ); return VLC_SUCCESS; } @@ -547,17 +525,12 @@ static int ItemChange( vlc_object_t *p_this, const char *psz_var, if( p_intf->b_dead ) return VLC_SUCCESS; - vlc_mutex_lock( &p_sys->lock ); - p_sys->b_preparsed_cb = VLC_FALSE; p_sys->b_state_cb = VLC_FALSE; /* We'll try to add the previously playing song in the queue */ if( AddToQueue( p_intf ) == VLC_ENOMEM ) - { - vlc_mutex_unlock( &p_sys->lock ); return VLC_ENOMEM; - } p_playlist = pl_Yield( p_intf ); PL_LOCK; @@ -567,9 +540,7 @@ static int ItemChange( vlc_object_t *p_this, const char *psz_var, { PL_UNLOCK; pl_Release( p_playlist ); - p_sys->b_submit = VLC_FALSE; - vlc_mutex_unlock( &p_sys->lock ); return VLC_SUCCESS; } @@ -582,7 +553,6 @@ static int ItemChange( vlc_object_t *p_this, const char *psz_var, { vlc_object_release( p_input ); p_sys->b_submit = VLC_FALSE; - vlc_mutex_unlock( &p_sys->lock ); return VLC_SUCCESS; } @@ -592,21 +562,19 @@ static int ItemChange( vlc_object_t *p_this, const char *psz_var, msg_Dbg( p_this, "Not an audio local file, not submitting"); vlc_object_release( p_input ); p_sys->b_submit = VLC_FALSE; - vlc_mutex_unlock( &p_sys->lock ); return VLC_SUCCESS; } - var_AddCallback( p_input, "state", PlayingChange, p_intf ); - p_sys->b_state_cb = VLC_TRUE; - p_sys->b_submit = VLC_TRUE; p_sys->time_total_pauses = 0; time( &p_sys->p_current_song.date ); + var_AddCallback( p_input, "state", PlayingChange, p_intf ); + p_sys->b_state_cb = VLC_TRUE; + if( input_item_IsPreparsed( p_item ) ) { ReadMetaData( p_intf ); - vlc_mutex_unlock( &p_sys->lock ); vlc_object_release( p_input ); return VLC_SUCCESS; } @@ -615,7 +583,6 @@ static int ItemChange( vlc_object_t *p_this, const char *psz_var, /* We'll read the meta data when it will be preparsed */ var_AddCallback( p_input, "meta-preparsed", MetaPreparsed, p_intf ); p_sys->b_preparsed_cb = VLC_TRUE; - vlc_mutex_unlock( &p_sys->lock ); vlc_object_release( p_input ); return VLC_SUCCESS; } @@ -629,9 +596,11 @@ static int AddToQueue ( intf_thread_t *p_this ) time_t played_time; intf_sys_t *p_sys = p_this->p_sys; + vlc_mutex_lock( &p_sys->lock ); if( !p_sys->b_submit ) { DeleteSong( &p_sys->p_current_song ); + vlc_mutex_unlock( &p_sys->lock ); return VLC_SUCCESS; } @@ -644,6 +613,7 @@ static int AddToQueue ( intf_thread_t *p_this ) { msg_Dbg( p_this, "Song not listened long enough, not submitting" ); DeleteSong( &p_sys->p_current_song ); + vlc_mutex_unlock( &p_sys->lock ); return VLC_SUCCESS; } @@ -651,6 +621,7 @@ static int AddToQueue ( intf_thread_t *p_this ) { msg_Dbg( p_this, "Song too short (< 30s), not submitting" ); DeleteSong( &p_sys->p_current_song ); + vlc_mutex_unlock( &p_sys->lock ); return VLC_SUCCESS; } @@ -659,6 +630,7 @@ static int AddToQueue ( intf_thread_t *p_this ) { msg_Dbg( p_this, "Missing artist or title, not submitting" ); DeleteSong( &p_sys->p_current_song ); + vlc_mutex_unlock( &p_sys->lock ); return VLC_SUCCESS; } @@ -666,6 +638,7 @@ static int AddToQueue ( intf_thread_t *p_this ) { msg_Warn( p_this, "Submission queue is full, not submitting" ); DeleteSong( &p_sys->p_current_song ); + vlc_mutex_unlock( &p_sys->lock ); return VLC_SUCCESS; } @@ -689,6 +662,13 @@ static int AddToQueue ( intf_thread_t *p_this ) #undef QUEUE_COPY p_sys->i_songs++; + + /* signal the main loop we have something to submit */ + vlc_object_lock( p_this ); + vlc_cond_signal( &p_this->object_wait ); + vlc_object_unlock( p_this ); + + vlc_mutex_unlock( &p_sys->lock ); return VLC_SUCCESS; } @@ -820,8 +800,6 @@ static int Handshake( intf_thread_t *p_this ) AddMD5( &p_struct_md5, ( uint8_t* ) psz_timestamp, strlen( psz_timestamp )); EndMD5( &p_struct_md5 ); - vlc_mutex_lock ( &p_sys->lock ); - for ( i = 0; i < 4; i++ ) { sprintf( &p_sys->psz_auth_token[8*i], "%02x%02x%02x%02x", @@ -840,7 +818,6 @@ static int Handshake( intf_thread_t *p_this ) p_sys->psz_auth_token ) ) { free( psz_username ); - vlc_mutex_unlock( &p_sys->lock ); return VLC_ENOMEM; } free( psz_username ); @@ -850,17 +827,13 @@ static int Handshake( intf_thread_t *p_this ) free( psz_handshake_url ); if( !p_stream ) - { - vlc_mutex_unlock ( &p_sys->lock ); return VLC_EGENERIC; - } /* read answer */ i_ret = stream_Read( p_stream, p_buffer, 1023 ); if( i_ret == 0 ) { stream_Delete( p_stream ); - vlc_mutex_unlock( &p_sys->lock ); return VLC_EGENERIC; } p_buffer[i_ret] = '\0'; @@ -871,7 +844,6 @@ static int Handshake( intf_thread_t *p_this ) { /* handshake request failed, sorry */ msg_Warn( p_this, "last.fm handshake failed: %s", p_buffer_pos + 7 ); - vlc_mutex_unlock( &p_sys->lock ); return VLC_EGENERIC; } @@ -883,7 +855,6 @@ static int Handshake( intf_thread_t *p_this ) _("last.fm: Authentication failed"), _("last.fm Username or Password is incorrect," " please verify your settings and relaunch VLC." ) ); - vlc_mutex_unlock( &p_sys->lock ); return VLC_AUDIOSCROBBLER_EFATAL; } @@ -962,16 +933,13 @@ static int Handshake( intf_thread_t *p_this ) break; } - vlc_mutex_unlock ( &p_sys->lock ); return VLC_SUCCESS; oom: - vlc_mutex_unlock( &p_sys->lock ); return VLC_ENOMEM; proto: msg_Warn( p_intf, "Handshake: can't recognize server protocol" ); - vlc_mutex_unlock( &p_sys->lock ); return VLC_EGENERIC; } @@ -1030,9 +998,12 @@ static int ReadMetaData( intf_thread_t *p_this ) free( psz_meta ); \ } + vlc_mutex_lock( &p_sys->lock ); + ALLOC_ITEM_META( p_sys->p_current_song.psz_a, Artist ) else { + vlc_mutex_unlock( &p_sys->lock ); msg_Dbg( p_this, "No artist.." ); vlc_object_release( p_input ); free( psz_meta ); @@ -1042,6 +1013,7 @@ static int ReadMetaData( intf_thread_t *p_this ) ALLOC_ITEM_META( p_sys->p_current_song.psz_t, Title ) else { + vlc_mutex_unlock( &p_sys->lock ); msg_Dbg( p_this, "No track name.." ); vlc_object_release( p_input ); free( p_sys->p_current_song.psz_a ); @@ -1066,6 +1038,7 @@ static int ReadMetaData( intf_thread_t *p_this ) msg_Dbg( p_this, "Meta data registered" ); + vlc_mutex_unlock( &p_sys->lock ); vlc_object_release( p_input ); return VLC_SUCCESS;