# HG changeset patch # User Cristi Magherusan # Date 1184195083 -10800 # Node ID 8af27e02e7b77221523874c7774a64ea28b8fe75 # Parent 574d0cc96a394597a17458c69077044030ae4316 fixed crashes when opening multiple tracks, optimized metadata thread diff -r 574d0cc96a39 -r 8af27e02e7b7 src/lastfm/lastfm.c --- a/src/lastfm/lastfm.c Wed Jul 11 04:35:57 2007 +0300 +++ b/src/lastfm/lastfm.c Thu Jul 12 02:04:43 2007 +0300 @@ -30,7 +30,7 @@ /* * Current status and known issues: - * - Works fine ant is relatively stable unless DEBUG is enabled (read below) + * - Works fine ant is relatively stable * - The adjust fails when having 2 or more opened streams at the same time. * * It will randomly adjust to any one of them, because the playlist keeps * pulling metadata @@ -49,9 +49,6 @@ #include "lastfm.h" #define DEBUG 1 -/*Caution!!! setting DEBUG to 1 is very likely to crash the player because the g_print-ed values - aren't checked of being !=NULL - */ size_t lastfm_store_res(void *ptr, size_t size, size_t nmemb, void *udata) { @@ -106,14 +103,16 @@ } } - void lastfm_store(gchar *var_name,gchar* var){ /*mowgli storage wrapper*/ - if (mowgli_global_storage_get(var_name)) - mowgli_global_storage_free(var_name); +void lastfm_store(gchar *var_name,gchar* var) /*mowgli storage wrapper, for storing global data*/ +{ + if (mowgli_global_storage_get(var_name)) + mowgli_global_storage_free(var_name); - mowgli_global_storage_put(var_name,var); - } + mowgli_global_storage_put(var_name,var); +} int lastfm_login(void) /*gets the session ID and the mp3 stream URL and stores them*/ + //it is called just on the first fopen, since it doesnt change (hopefully!!!) { gint status, i, ret=LASTFM_LOGIN_OK; /*suppose everything goes fine*/ @@ -157,7 +156,7 @@ return g_strdup(strchr(input_string, '=') + 1); } -gint lastfm_adjust(const gchar * uri) /*tunes into a channel*/ +gint lastfm_adjust(LastFM * handle,const gchar * uri) /*tunes into a channel*/ { gint status, i,ret = LASTFM_ADJUST_FAILED; gchar *fetch_url=NULL, @@ -175,20 +174,14 @@ fetch_url=g_strdup_printf(LASTFM_ADJUST_URL, session_id, uri); res= g_string_new(NULL); status = lastfm_get_data_from_uri(fetch_url, res); -#if 0 - g_print("\nAdjusting: \nSession ID:%s\n",session_id); - g_print("Fetch URL:%s\n",fetch_url); - g_print("Adjust OK, \nReceived data:\n%s\n", res->str); -#endif + if (status == CURLE_OK) { - split = g_strsplit(res->str, "\n", 20); + split = g_strsplit(res->str, "\n", 2); for (i = 0; split && split[i]; i++) { if (g_str_has_prefix(split[i], "response=OK")) ret = LASTFM_ADJUST_OK; - if (g_str_has_prefix(split[i], "url=")) - lastfm_store("lastfm_tuned_to_url", parse(split[i], "url=")); } } g_string_erase(res, 0, -1); @@ -303,11 +296,12 @@ t0=g_new0(GTimeVal,1); t1=g_new0(GTimeVal,1); gboolean track_end_expected=FALSE,track_beginning=TRUE; - gchar* previous_track_title=NULL; + // gchar* previous_track_title=NULL; LastFM *handle = (LastFM *)arg; - // metadata is fetched 1 second after the stream is opened. + // metadata is fetched 1 second after the stream is opened, + // and again after 2 seconds. // if metadata was fetched ok i'm waiting for - // track_length - fetch_duration - 5 seconds + // track_length - fetch_duration - 10 seconds // then start polling for new metadata each 2 seconds, until // the track gets changed from the previous iteration do @@ -315,45 +309,60 @@ if(count%sleep_duration==0) { g_get_current_time (t0); - g_mutex_lock(mutex); + g_mutex_lock(metadata_mutex); status=fetch_metadata(handle); - g_mutex_unlock(mutex); + g_mutex_unlock(metadata_mutex); g_get_current_time (t1); if(status==METADATA_FETCH_SUCCEEDED) { if(!track_end_expected) { - if(track_beginning||(previous_track_duration==-1)) //fetch again 2 sec after track start + if(track_beginning) + { //first try after track has changed +#if DEBUG + g_print("retrying in 2 seconds\n"); +#endif + track_beginning=FALSE; + sleep_duration=2; + } + else { + sleep_duration=handle->lastfm_duration-(t1->tv_sec - t0->tv_sec)-10; + previous_track_duration=handle->lastfm_duration; + count=err=0; + track_end_expected=TRUE; /*then the track_end will follow*/ + track_beginning=TRUE; +#if DEBUG + g_print("second fetch after new track started, the next will follow in %d sec\n",sleep_duration); +#endif + } + + } + else + { + //if the track hasnt yet changed (two tracks are considered identical if they + //have the same length or the same title) + if(handle->lastfm_duration == previous_track_duration) + { +#if DEBUG + g_print("it is the same track as before, waiting for new track to start\n"); +#endif sleep_duration=2; - track_beginning=FALSE; } else { - sleep_duration=handle->lastfm_duration-(t1->tv_sec - t0->tv_sec)-5; - previous_track_duration=handle->lastfm_duration; - previous_track_title=g_strdup(handle->lastfm_title); - track_end_expected=TRUE; /*then the track_end will follow*/ - count=err=0; - track_beginning=TRUE; +#if DEBUG + g_print("the track has changed\n"); +#endif + track_end_expected=FALSE; + sleep_duration=2; + /*if(previous_track_title) + { + g_free(previous_track_title); + previous_track_title=NULL; + }*/ } } - else - { - //if the track has changed (two tracks are considered identical if they - //have the same length and the same title) - if((handle->lastfm_duration != previous_track_duration)|| - !g_str_has_prefix(handle->lastfm_title, previous_track_title)) - { - track_end_expected=FALSE; - if(previous_track_title) - { - g_free(previous_track_title); - previous_track_title=NULL; - } - } - sleep_duration=2; - } #if DEBUG g_print("Current thread, ID = %p\n", (void *)g_thread_self()); #endif @@ -365,7 +374,7 @@ } #if DEBUG g_print("Thread_count: %d\n",thread_count); - g_print("Sleeping for %d seconds\n",sleep_duration); + g_print("Sleeping for %d seconds, track length = %d sec\n",sleep_duration, handle->lastfm_duration); #endif } @@ -386,26 +395,35 @@ { VFSFile *file = g_new0(VFSFile, 1); LastFM *handle = g_new0(LastFM, 1); - gchar* lastfm_uri=NULL; + handle->lastfm_artist=NULL; + handle->lastfm_title=NULL; + handle->lastfm_album=NULL; + handle->lastfm_cover=NULL; + handle->lastfm_session_id=NULL; + handle->lastfm_mp3_stream_url=NULL; + handle->lastfm_station_name=NULL; int login_count = 0; - while((login_count++ <= 3)&&(lastfm_login()!= LASTFM_LOGIN_OK)) - sleep(5); + + if(!mowgli_global_storage_get("lastfm_session_id")) //login only if really needed + { + while((login_count++ <= 3)&&(lastfm_login()!= LASTFM_LOGIN_OK)) + sleep(5); + if(login_count>3) + return NULL; + } + //the following data is completed during login, which happens just once + //maybe making it happen on each time vfs_fopen would make it eliminate the issue + //that occurs when having more opened tracks (random play of anyone of them) handle->lastfm_session_id = mowgli_global_storage_get("lastfm_session_id"); handle->lastfm_mp3_stream_url = mowgli_global_storage_get("lastfm_stream_uri"); - lastfm_uri=mowgli_global_storage_get("lastfm_tuned_to_url"); - //only tune in if the existing uri is NULL or != our new one(from path) - //adjust doesnt work as it should when having more than one lastfm stream opened at a time - if (!lastfm_uri || (!g_str_has_prefix(path,lastfm_uri)) ) - if(!lastfm_adjust(path)==LASTFM_ADJUST_OK) - return NULL; - + if(!lastfm_adjust(handle,path)==LASTFM_ADJUST_OK) + return NULL; metadata_thread = g_thread_create(lastfm_metadata_thread_func, handle, FALSE, NULL); thread_count++; #if DEBUG g_print("Thread_count: %d\n",thread_count); #endif handle->proxy_fd = vfs_fopen(handle->lastfm_mp3_stream_url, mode); - file->handle = handle; return file; } @@ -520,13 +538,14 @@ static void init(void) { vfs_register_transport(&lastfm_const); - if (!mutex) - mutex = g_mutex_new (); + if (!metadata_mutex) + metadata_mutex = g_mutex_new (); + } static void cleanup(void) { - g_mutex_free(mutex); + g_mutex_free(metadata_mutex); mowgli_global_storage_free("lastfm_session_id"); mowgli_global_storage_free("lastfm_stream_uri"); #if DEBUG diff -r 574d0cc96a39 -r 8af27e02e7b7 src/lastfm/lastfm.h --- a/src/lastfm/lastfm.h Wed Jul 11 04:35:57 2007 +0300 +++ b/src/lastfm/lastfm.h Thu Jul 12 02:04:43 2007 +0300 @@ -29,7 +29,7 @@ GThread* metadata_thread=NULL; gint thread_count=0; -static GMutex * mutex = NULL; +static GMutex * metadata_mutex = NULL; VFSFile *lastfm_vfs_fopen_impl(const gchar * path, const gchar * mode);