# HG changeset patch # User Cristi Magherusan # Date 1183302704 -10800 # Node ID 0ae013f630fac59834d7993787f35b824c5649e3 # Parent 2cb9c6b5cf4d516ef442bf2f8e06c9e4db0a5db9 mowgli transition, and some fixes diff -r 2cb9c6b5cf4d -r 0ae013f630fa src/lastfm/lastfm.c --- a/src/lastfm/lastfm.c Sun Jul 01 07:01:48 2007 -0500 +++ b/src/lastfm/lastfm.c Sun Jul 01 18:11:44 2007 +0300 @@ -1,131 +1,200 @@ -/* Audacious - * Copyright (c) 2007 Cristi Magherusan - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. +/* Audacious lastfm transport plugin + * Copyright (c) 2007 Cristi Magherusan + * All rights reserved. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the author nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include - #include #include #include #include "lastfm.h" -#define DEBUG 0 +#define DEBUG 1 + +size_t lastfm_store_res(void *ptr, size_t size, size_t nmemb, void *udata) +{ + GString *data = (GString *) udata; + g_string_append_len(data, ptr, nmemb); + return size * nmemb; +} -LastFM *LastFMGlobalData; -/*this keeps the login data in a global place since - * we cannot login on every fopen call* if anyone - * has a better solution to this any hint is welcome */ - -static size_t lastfm_store_res(void *ptr, size_t size, size_t nmemb, void *udata) +gint lastfm_get_data_from_uri(gchar *url, GString * result) { - GString *data = (GString *) udata; - g_string_append_len(data, ptr, nmemb); - return size * nmemb; + CURL *curl = curl_easy_init(); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1); + curl_easy_setopt(curl, CURLOPT_USERAGENT, "mplayer"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, lastfm_store_res); + curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, LASTFM_CURL_TIMEOUT); + curl_easy_setopt(curl, CURLOPT_URL, url); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, result); + gint status = curl_easy_perform(curl); + curl_easy_cleanup(curl); + return status; } -gint get_data_from_url(gchar buf[4096], GString * res) +gchar* lastfm_get_login_uri() { - CURL *curl = curl_easy_init(); - curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1); - curl_easy_setopt(curl, CURLOPT_USERAGENT, "Audacious"); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, lastfm_store_res); - curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); - curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); - curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, LASTFM_CURL_TIMEOUT); - curl_easy_setopt(curl, CURLOPT_URL, buf); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, res); - gint status = curl_easy_perform(curl); - curl_easy_cleanup(curl); - return status; +#if DEBUG + g_print("Getting login data from config\n"); +#endif + + ConfigDb *cfgfile = NULL; + gchar *buf=NULL, + *username = NULL, + *password = NULL; + if ((cfgfile = bmp_cfg_db_open()) != NULL) + { + bmp_cfg_db_get_string(cfgfile, "audioscrobbler","username", + &username); + bmp_cfg_db_get_string(cfgfile, "audioscrobbler","password", + &password); + g_free(cfgfile); + } + if (username != NULL && password != NULL) + { +#if DEBUG + g_print("Creating the login URI\n"); +#endif + + buf=g_strdup_printf(LASTFM_HANDSHAKE_URL, username, password); + g_free(password); + g_free(username); +#if DEBUG + g_print("Succesfully created the login uri\n"); +#endif + return buf; + } + else { +#if DEBUG + g_print("Couldn't find the login data. Use the scrobbler plugin to set it up.\n"); +#endif + + return NULL; + } +} + +void lastfm_store(gchar *var_name,gchar* var){ +if (mowgli_global_storage_get(var_name)) + mowgli_global_storage_free(var_name); + + mowgli_global_storage_put(var_name,var); +#if DEBUG + g_print("Storing into '%s' the value '%s'\n",var_name,var); +#endif } -static gboolean lastfm_login(void) +int lastfm_login(void) { - /*gets the session ID in lastfm_session_id and returns the URL to be played - * read http://gabistapler.de/blog/index.php?/archives/268-Play-last.fm-streams-without-the-player.html for more info - */ - gint status, i; - gchar buf[4096], **split = NULL; - GString *res = g_string_new(NULL); - ConfigDb *cfgfile = NULL; - char *username = NULL, *password = NULL; - if ((cfgfile = bmp_cfg_db_open()) != NULL) - { - bmp_cfg_db_get_string(cfgfile, "audioscrobbler", "username", &username); - bmp_cfg_db_get_string(cfgfile, "audioscrobbler", "password", &password); - g_free(cfgfile); - } - if (username != NULL && password != NULL) - { - snprintf(buf, sizeof(buf), LASTFM_HANDSHAKE_URL, username, password); - g_free(password); - g_free(username); - } - else - return FALSE; + /*gets the session ID in the URL to be played and stores them using + * mowgli_global_storage + * read http://gabistapler.de/blog/index.php?/archives/268-Play-last.fm-streams-without-the-player.html for more info + */ + + gint status, i; + gchar *lastfm_session_id=NULL, + *lastfm_stream_uri=NULL, + *login_uri=NULL, + **split = NULL; + GString *res = g_string_new(NULL); +g_print("Logging in\n"); + login_uri=lastfm_get_login_uri(); + if(login_uri==NULL){ + g_free(login_uri); + return LASTFM_MISSING_LOGIN_DATA; + } + status = lastfm_get_data_from_uri(login_uri, res); +#if DEBUG + g_print("Opened login URI: '%s'\n", login_uri); + g_print("Got following data: '%s'\n", res->str); +#endif - status = get_data_from_url(buf, res); + if (status == CURLE_OK) + { + split = g_strsplit(res->str, "\n", 7); -#ifdef DEBUG - g_print("URL:%s\n", buf); - g_print("Downloaded data:%s\n", res->str); + for (i = 0; split && split[i]; i++) + { + if (g_str_has_prefix(split[i], "session=")) + { + lastfm_session_id = g_strndup(split[i] + 8, 32); +#if DEBUG + g_print("Got session ID:'%s'\n",lastfm_session_id); #endif - if (status == CURLE_OK) - { - split = g_strsplit(res->str, "\n", 7); + } + else if (g_str_has_prefix(split[i], "stream_url=")) + lastfm_stream_uri = g_strdup(split[i] + 11); + } + } + else + { + g_strfreev(split); + g_string_erase(res, 0, -1); + g_free(lastfm_session_id); + g_free(lastfm_stream_uri); + g_free(login_uri); + return LASTFM_LOGIN_ERROR; + } + lastfm_store("lastfm_session_id",lastfm_session_id); + lastfm_store("lastfm_stream_uri",lastfm_stream_uri); - for (i = 0; split && split[i]; i++) - { - if (g_str_has_prefix(split[i], "session=")) - LastFMGlobalData->lastfm_session_id = g_strndup(split[i] + 8, 32); - else if (g_str_has_prefix(split[i], "stream_url=")) - LastFMGlobalData->lastfm_mp3_stream_url = g_strdup(split[i] + 11); - } - } - else - return FALSE; - - g_strfreev(split); - g_string_erase(res, 0, -1); - - if (mowgli_global_storage_get("lastfm_session_id")) - mowgli_global_storage_free("lastfm_session_id"); - - mowgli_global_storage_put("lastfm_session_id", LastFMGlobalData->lastfm_session_id); - - return (gboolean) TRUE; +#if DEBUG + g_print("Login finished succesfully\n"); +#endif + g_strfreev(split); + g_string_erase(res, 0, -1); + g_free(login_uri); + return LASTFM_LOGIN_OK ; } -static gboolean lastfm_adjust(const gchar * url) +gint lastfm_adjust(const gchar * uri) { - int status, i; - gchar tmp[4096], **split = NULL; - gboolean ret = FALSE; - GString *res = g_string_new(NULL); + int status, i; + gchar tmp[4096], **split = NULL; + gboolean ret = FALSE; + GString *res = g_string_new(NULL); + gchar* session_id=mowgli_global_storage_get("lastfm_session_id"); + - if (LastFMGlobalData->lastfm_session_id == NULL) - return FALSE; - snprintf(tmp, sizeof(tmp), LASTFM_ADJUST_URL, LastFMGlobalData->lastfm_session_id, url); + if (!session_id) + return LASTFM_SESSION_MISSING; +#if DEBUG + g_print("Session ID: '%s'\n",session_id); +#endif - status = get_data_from_url(tmp, res); + snprintf(tmp, sizeof(tmp), LASTFM_ADJUST_URL, session_id, uri); -#ifdef DEBUG + status = lastfm_get_data_from_uri(tmp, res); + +#if DEBUG g_print("Adjust received data:%s\n", res->str); #endif if (status == CURLE_OK) @@ -135,54 +204,67 @@ for (i = 0; split && split[i]; i++) { if (g_str_has_prefix(split[i], "response=OK")) - ret = TRUE; + ret = LASTFM_ADJUST_OK; if (g_str_has_prefix(split[i], "stationname=")) { - LastFMGlobalData->lastfm_station_name = g_strdup(split[i] + 12); -#ifdef DEBUG - g_print("StationnName:%s\n", LastFMGlobalData->lastfm_station_name); + mowgli_global_storage_put("lastfm_station_name", g_strdup(split[i] + 12)); +#if DEBUG + g_print ("Setting station name: '%s'\n", + (gchar*)mowgli_global_storage_get("lastfm_station_name")); #endif } } g_strfreev(split); } g_string_erase(res, 0, -1); - + return ret; } +void parse( gchar **split , gchar* field, gchar* data){ -static void parse_metadata(LastFM * handle,GString * res) + +} + +void parse_metadata(LastFM * handle,GString * metadata) { - gchar **split = g_strsplit(res->str, "\n", 20); + gchar **split = g_strsplit(metadata->str, "\n", 20); int i; + handle->lastfm_duration=0; + for (i = 0; split && split[i]; i++) { if (g_str_has_prefix(split[i], "artist=")) { - if (handle->lastfm_artist) g_free(handle->lastfm_artist); + if (handle->lastfm_artist) + g_free(handle->lastfm_artist); + handle->lastfm_artist = g_strdup(split[i] + 7); -#ifdef DEBUG +#if DEBUG g_print("Artist: %s\n", handle->lastfm_artist); #endif } if (g_str_has_prefix(split[i], "track=")) { - if (handle->lastfm_title) g_free(handle->lastfm_title); + if (handle->lastfm_title) + g_free(handle->lastfm_title); + handle->lastfm_title = g_strdup(split[i] + 6); -#ifdef DEBUG +#if DEBUG g_print("Title: %s\n", handle->lastfm_title); #endif } if (g_str_has_prefix(split[i], "album=")) handle->lastfm_album = g_strdup(split[i] + 6); + if (g_str_has_prefix(split[i], "albumcover_medium=")) handle->lastfm_cover = g_strdup(split[i] + 18); + if (g_str_has_prefix(split[i], "trackduration=")) { handle->lastfm_duration = g_ascii_strtoull(g_strdup(split[i] + 14), NULL, 10); -#ifdef DEBUG +#if DEBUG g_print("Duration:%d\n", handle->lastfm_duration); #endif } @@ -192,7 +274,7 @@ if (g_str_has_prefix(split[i], "station=")) { handle->lastfm_station_name = g_strdup(split[i] + 8); -#ifdef DEBUG +#if DEBUG g_print("Station Name: %s\n", handle->lastfm_station_name); #endif } @@ -203,22 +285,31 @@ } -static gpointer lastfm_get_metadata(gpointer arg) -{ - int err=0,delay=-2; - - int sleep_duration,count=0; - gint status; - gchar tmp[4096]; +gpointer lastfm_get_metadata(gpointer arg) +{ + gint err=0, + delay=-2, + sleep_duration=1, + count=0, + status; + gchar uri[4096]; GString *res = g_string_new(NULL); gboolean track_end=FALSE; LastFM *handle = (LastFM *)arg; + handle->lastfm_session_id =g_strdup(mowgli_global_storage_get("lastfm_session_id")); +#if DEBUG + g_print("Session ID: %s\n", handle->lastfm_session_id); +#endif if (handle->lastfm_session_id == NULL) return NULL; - snprintf(tmp, sizeof(tmp), LASTFM_METADATA_URL, handle->lastfm_session_id); + snprintf(uri, sizeof(uri), LASTFM_METADATA_URL, handle->lastfm_session_id); +#if DEBUG + g_print("Download URI: %s\n", uri); +#endif - while ( (handle!= NULL) && (handle->metadata_thread == g_thread_self ()) && (err<5)) + + while ( (handle!= NULL) && (err<5)) //exit after 5 failed retries or after metadata_thread changes { count++; @@ -226,14 +317,12 @@ { handle->lastfm_duration = 0; handle->lastfm_progress = 0; - status = get_data_from_url(tmp, res); -#if 0 - g_print("Received metadata:%s\n", res->str); -#endif + status = lastfm_get_data_from_uri(uri, res); if (status == CURLE_OK) { -#ifdef DEBUG - g_print("Got Metadata\n"); +#if DEBUG + g_print("Successfully got Metadata\n"); + g_print("Received metadata:'%s'\nParsing...", res->str); #endif parse_metadata( handle,res); } @@ -263,14 +352,14 @@ //when calculating sleep_time } -#ifdef DEBUG +#if DEBUG g_print("Sleeping for %d seconds\n", sleep_duration); #endif } sleep(1); } -#ifdef DEBUG +#if DEBUG g_print("Exiting thread, ID = %p\n", (void *)g_thread_self()); #endif handle->metadata_thread = NULL; @@ -284,29 +373,32 @@ LastFM *handle; file = g_new0(VFSFile, 1); handle = g_new0(LastFM, 1); - while ((LastFMGlobalData->lastfm_mp3_stream_url == NULL) && (LastFMGlobalData->login_count <= 3)) + int login_count = 0; + while( ! mowgli_global_storage_get("lastfm_stream_uri")&&(login_count <= 3)) { - printf("Login try count: %d\n", LastFMGlobalData->login_count++); + printf("Login try count: %d\n", login_count++); lastfm_login(); - if (LastFMGlobalData->lastfm_mp3_stream_url == NULL) + if (!mowgli_global_storage_get("lastfm_stream_uri")) sleep(5); } - if (LastFMGlobalData->lastfm_mp3_stream_url == NULL) + if (!mowgli_global_storage_get("lastfm_stream_uri")) return NULL; - - if (LastFMGlobalData->lastfm_station_name==NULL) + handle->lastfm_session_id = g_strdup(mowgli_global_storage_get("lastfm_session_id")); + handle->lastfm_mp3_stream_url = g_strdup(mowgli_global_storage_get("lastfm_stream_uri")); + + if (!mowgli_global_storage_get("lastfm_station_name")) { - if(lastfm_adjust(path)) + if(lastfm_adjust(path)==LASTFM_ADJUST_OK) { -#ifdef DEBUG +#if DEBUG g_print("Tuning was successfully completed into the channel\n"); #endif } else { -#ifdef DEBUG +#if DEBUG g_print("Cannot tune to given channel\n"); #endif } @@ -314,21 +406,18 @@ if ((handle->metadata_thread = g_thread_create(lastfm_get_metadata, handle, FALSE, NULL)) == NULL) { -#ifdef DEBUG - g_print("Error creating metadata thread!!!\n"); +#if DEBUG + g_print("Error creating metadata thread!!!\n"); #endif return NULL; } else { -#ifdef DEBUG - g_print("A metadata thread has just been created, ID = %p \n", (void *)handle->metadata_thread); +#if DEBUG + g_print("A metadata thread has just been created, ID = %p \n", (void *)handle->metadata_thread); #endif } - handle->lastfm_mp3_stream_url = g_strdup(LastFMGlobalData->lastfm_mp3_stream_url); - handle->lastfm_session_id = g_strdup(LastFMGlobalData->lastfm_session_id); - handle->lastfm_station_name = g_strdup(LastFMGlobalData->lastfm_station_name); handle->proxy_fd = vfs_fopen(handle->lastfm_mp3_stream_url, mode); file->handle = handle; @@ -459,13 +548,17 @@ static void init(void) { - LastFMGlobalData = g_new0(LastFM, 1); vfs_register_transport(&lastfm_const); } static void cleanup(void) { - g_free(LastFMGlobalData); + +mowgli_global_storage_free("lastfm_session_id"); +mowgli_global_storage_free("lastfm_stream_uri"); +#if DEBUG +g_print ("Cleanup finished\n"); +#endif } DECLARE_PLUGIN(lastfm, init, cleanup, NULL, NULL, NULL, NULL, NULL) diff -r 2cb9c6b5cf4d -r 0ae013f630fa src/lastfm/lastfm.h --- a/src/lastfm/lastfm.h Sun Jul 01 07:01:48 2007 -0500 +++ b/src/lastfm/lastfm.h Sun Jul 01 18:11:44 2007 +0300 @@ -5,6 +5,13 @@ #define LASTFM_CURL_TIMEOUT 10 +#define LASTFM_LOGIN_OK 0 +#define LASTFM_LOGIN_ERROR 1 +#define LASTFM_MISSING_LOGIN_DATA 2 +#define LASTFM_SESSION_MISSING 4 +#define LASTFM_ADJUST_OK 0 + + typedef struct { VFSFile *proxy_fd;