diff --git a/src/scrobbler/plugin.c b/src/scrobbler/plugin.c index 5924b56..6b82b64 100644 --- a/src/scrobbler/plugin.c +++ b/src/scrobbler/plugin.c @@ -40,8 +40,6 @@ static GMutex *m_scrobbler; guint track_timeout = 0; -Tuple *submit_tuple = NULL; - static gboolean ishttp(const char *a) { g_return_val_if_fail(a != NULL, FALSE); @@ -53,30 +51,32 @@ static void aud_hook_playback_begin(gpointer hook_data, gpointer user_data) gint playlist = aud_playlist_get_playing(); gint pos = aud_playlist_get_position(playlist); - if (aud_playlist_entry_get_length (playlist, pos, FALSE) < 30) - { - AUDDBG(" *** not submitting due to entry->length < 30"); + char *filename = aud_playlist_entry_get_filename(playlist, pos); + bool_t is_http_source = ishttp(filename); + str_unref(filename); + + Tuple *tuple = aud_playlist_entry_get_tuple(playlist, pos, FALSE); + if (!tuple) return; - } - gchar * filename = aud_playlist_entry_get_filename (playlist, pos); - if (ishttp (filename)) + int len = tuple_get_int(tuple, FIELD_LENGTH, NULL) / 1000; + + /* Make up a length when we submit streaming to now playing. + * We will change it before we actually scrobble the track. */ + if (len < 1 && is_http_source) + len = 240; + + if (len < 30) { - AUDDBG(" *** not submitting due to HTTP source"); - str_unref (filename); + AUDDBG("Length less than 30 seconds; not submitting\n"); + tuple_unref(tuple); return; } - str_unref (filename); sc_idle(m_scrobbler); - if (submit_tuple) - tuple_unref (submit_tuple); - submit_tuple = aud_playlist_entry_get_tuple (playlist, pos, FALSE); - if (! submit_tuple) - return; - - sc_addentry(m_scrobbler, submit_tuple, tuple_get_int(submit_tuple, FIELD_LENGTH, NULL) / 1000); + sc_addentry(m_scrobbler, tuple, len, is_http_source); + tuple_unref(tuple); if (!track_timeout) track_timeout = g_timeout_add_seconds(1, sc_timeout, NULL); @@ -84,6 +84,7 @@ static void aud_hook_playback_begin(gpointer hook_data, gpointer user_data) static void aud_hook_playback_end(gpointer aud_hook_data, gpointer user_data) { + sc_playback_end(); sc_idle(m_scrobbler); if (track_timeout) @@ -91,12 +92,6 @@ static void aud_hook_playback_end(gpointer aud_hook_data, gpointer user_data) g_source_remove(track_timeout); track_timeout = 0; } - - if (submit_tuple != NULL) - { - tuple_unref (submit_tuple); - submit_tuple = NULL; - } } void start(void) { diff --git a/src/scrobbler/scrobbler.c b/src/scrobbler/scrobbler.c index 1ac17ee..16c8d65 100644 --- a/src/scrobbler/scrobbler.c +++ b/src/scrobbler/scrobbler.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #define SCROBBLER_CLI_ID "aud" @@ -48,6 +49,7 @@ static char *sc_submit_url, /* queue */ sc_curl_errbuf[CURL_ERROR_SIZE], *sc_major_error; +static int sc_submit_np(Tuple *tuple, int len); static void dump_queue(); /**** Queue stuff ****/ @@ -63,6 +65,7 @@ typedef struct { int utctime, track, len; int timeplayed; int numtries; + bool_t is_http_source; void *next; } item_t; @@ -137,7 +140,7 @@ static item_t *q_additem(item_t *newitem) return newitem; } -static item_t *create_item(Tuple *tuple, int len) +static item_t *create_item(Tuple *tuple, int len, bool_t is_http_source) { item_t *item; gchar *album, *artist, *title; @@ -172,6 +175,8 @@ static item_t *create_item(Tuple *tuple, int len) else item->album = fmt_escape(""); + item->is_http_source = is_http_source; + item->next = NULL; return item; @@ -181,7 +186,7 @@ static item_t *q_put(Tuple *tuple, int t, int len) { item_t *item; - if ((item = create_item (tuple, len)) == NULL) + if (!(item = create_item(tuple, len, FALSE))) return NULL; item->timeplayed = len; @@ -190,12 +195,12 @@ static item_t *q_put(Tuple *tuple, int t, int len) return q_additem(item); } -static item_t *set_np(Tuple *tuple, int len) +static item_t *set_np(Tuple *tuple, int len, bool_t is_http_source) { if (np_item != NULL) q_item_free (np_item); - if ((np_item = create_item (tuple, len)) != NULL) + if ((np_item = create_item(tuple, len, is_http_source))) AUDDBG ("Tracking now-playing track: %s - %s\n", np_item->artist, np_item->title); @@ -266,11 +271,70 @@ static void q_free(void) /* isn't there better way for that? --desowin */ gboolean sc_timeout(gpointer data) { - if (np_item) + if (!np_item) + return TRUE; + + if (aud_drct_get_playing() && !aud_drct_get_paused()) + np_item->timeplayed++; + + if (np_item->is_http_source) { - if (aud_drct_get_playing() && !aud_drct_get_paused()) - np_item->timeplayed+=1; + /* This might be a stream, so check if the track info has changed. */ + int playlist = aud_playlist_get_playing(); + int pos = aud_playlist_get_position(playlist); + Tuple *tuple = aud_playlist_entry_get_tuple(playlist, pos, FALSE); + + if (!tuple) + return TRUE; + + int len = tuple_get_int(tuple, FIELD_LENGTH, NULL) / 1000; + + /* Make up a length when we submit streaming to now playing. + * We will change it before we actually scrobble the track. */ + if (len < 1) + len = 240; + + item_t *current_item = create_item(tuple, len, TRUE); + + if (!current_item) + { + tuple_unref(tuple); + return TRUE; + } + + if (strcmp(np_item->artist, current_item->artist) + || strcmp(np_item->title, current_item->title) + || strcmp (np_item->album, current_item->album) + || np_item->track != current_item->track) + { + /* Now set the real length of the track. */ + np_item->len = np_item->timeplayed; + + AUDDBG ("Submitting\n"); + + q_additem(np_item); + np_item = current_item; + dump_queue(); + + sc_submit_np(tuple, len); + } + else + { + q_item_free(current_item); + if (np_item->timeplayed > np_item->len) + { + /* Submit the track again to make sure it stays on now playing. + * This doubles the total length we have submitted. */ + sc_submit_np(tuple, np_item->len); + np_item->len *= 2; + } + } + + tuple_unref(tuple); + } + else + { /* * Check our now-playing track to see if it should go into the queue */ @@ -288,6 +352,21 @@ gboolean sc_timeout(gpointer data) return TRUE; } +void sc_playback_end(void) +{ + if (np_item && np_item->is_http_source) + { + /* Now set the real length of the track. */ + np_item->len = np_item->timeplayed; + + AUDDBG ("Submitting\n"); + + q_additem(np_item); + np_item = NULL; + dump_queue(); + } +} + /* Error functions */ static void sc_throw_error(char *errortxt) @@ -778,7 +857,7 @@ static int sc_generateentry(GString *submission) return i; } -static int sc_submit_np(Tuple *tuple) +static int sc_submit_np(Tuple *tuple, int len) { CURL *curl; /* struct HttpPost *post = NULL , *last = NULL; */ @@ -810,7 +889,7 @@ static int sc_submit_np(Tuple *tuple) field_artist, field_title, field_album, - tuple_get_int(tuple, FIELD_LENGTH, NULL) / 1000, + len, tuple_get_int(tuple, FIELD_TRACK_NUMBER, NULL)); curl_free(field_artist); curl_free(field_title); @@ -1126,12 +1205,12 @@ void sc_init(char *uname, char *pwd, char *url) AUDDBG("scrobbler starting up\n"); } -void sc_addentry(GMutex *mutex, Tuple *tuple, int len) +void sc_addentry(GMutex *mutex, Tuple *tuple, int len, bool_t is_http_source) { g_mutex_lock(mutex); - sc_submit_np(tuple); - set_np(tuple, len); + sc_submit_np(tuple, len); + set_np(tuple, len, is_http_source); /* * This will help make sure the queue will be saved on a nasty diff --git a/src/scrobbler/scrobbler.h b/src/scrobbler/scrobbler.h index 2203696..038c1f3 100644 --- a/src/scrobbler/scrobbler.h +++ b/src/scrobbler/scrobbler.h @@ -14,9 +14,11 @@ gboolean sc_timeout(gpointer data); int sc_idle(GMutex *); void sc_init(char *, char *, char *); -void sc_addentry(GMutex *, Tuple *, int); +void sc_addentry(GMutex *mutex, Tuple *tuple, int len, bool_t is_http_source); void sc_cleaner(void); int sc_catch_error(void); char *sc_fetch_error(void); void sc_clear_error(void); +void sc_playback_end(void); + #endif