# HG changeset patch # User William Pitcock # Date 1183609647 18000 # Node ID c1dcc9d38f98b16985eb082d354c223d2321b5ea # Parent 3094d9c8a935ecb6a3d0bce4d3e4dcb6c9a4f804# Parent c39a61e6a276eb84f1329b6e940c70d824e3901e Automated merge with ssh://hg.atheme.org//hg/audacious-plugins diff -r 3094d9c8a935 -r c1dcc9d38f98 AUTHORS --- a/AUTHORS Wed Jul 04 23:25:02 2007 -0500 +++ b/AUTHORS Wed Jul 04 23:27:27 2007 -0500 @@ -4,6 +4,7 @@ -------------------------------------------- George Averill +Michael Färber <0102@gmx.at> Giacomo Lozito William Pitcock Derek Pomery @@ -24,7 +25,7 @@ Greek - Kouzinopoulos Haris Stavros Giannouris Stathis Kamperis -Italian - Diego Petteno +Italian - Diego Petteno Japanese - Dai - @@ -91,7 +92,7 @@ Japanese - Takeshi Aihana Korean - DongCheon Park Lithuanian - Rimas Kudelis -Macedonian - Arangel Angov +Macedonian - Arangel Angov Polish - Jacek Wolszczak Romanian - Liviu Danicel Russian - Pavlo Bohmat diff -r 3094d9c8a935 -r c1dcc9d38f98 src/lastfm/lastfm.c --- a/src/lastfm/lastfm.c Wed Jul 04 23:25:02 2007 -0500 +++ b/src/lastfm/lastfm.c Wed Jul 04 23:27:27 2007 -0500 @@ -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 3094d9c8a935 -r c1dcc9d38f98 src/lastfm/lastfm.h --- a/src/lastfm/lastfm.h Wed Jul 04 23:25:02 2007 -0500 +++ b/src/lastfm/lastfm.h Wed Jul 04 23:27:27 2007 -0500 @@ -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; diff -r 3094d9c8a935 -r c1dcc9d38f98 src/sexypsf/Makefile --- a/src/sexypsf/Makefile Wed Jul 04 23:25:02 2007 -0500 +++ b/src/sexypsf/Makefile Wed Jul 04 23:27:27 2007 -0500 @@ -18,7 +18,7 @@ PsxInterpreter.c \ PsxHLE.c \ spu/spu.c \ - xmms.c + plugin.c LIBADD = -lz diff -r 3094d9c8a935 -r c1dcc9d38f98 src/sexypsf/plugin.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sexypsf/plugin.c Wed Jul 04 23:27:27 2007 -0500 @@ -0,0 +1,292 @@ +/* sexyPSF - PSF1 player + * Copyright (C) 2002-2004 xodnizel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "audacious/output.h" +#include "audacious/plugin.h" +#include "audacious/titlestring.h" +#include "audacious/util.h" +#include "audacious/vfs.h" +#include +#include +#include +#include +#include "driver.h" + +static volatile int seek = 0; +static volatile gboolean playing = FALSE; +static volatile gboolean paused = FALSE; +static volatile gboolean stop = FALSE; +static volatile gboolean nextsong = FALSE; + +extern InputPlugin sexypsf_ip; +static gboolean audio_error = FALSE; + +static PSFINFO *PSFInfo = NULL; +static gchar *fnsave = NULL; +static GThread *dethread = NULL; +static InputPlayback *playback = NULL; + +static gchar *get_title_psf(gchar *fn); + +static int is_our_fd(gchar *filename, VFSFile *file) { + gchar magic[4]; + vfs_fread(magic, 1, 4, file); + + // only allow PSF1 for now + if (!memcmp(magic, "PSF\x01", 4)) + return 1; + return 0; +} + + +void sexypsf_update(unsigned char *buffer, long count) +{ + const int mask = ~((((16 / 8) * 2)) - 1); + + while (count > 0) + { + int t = playback->output->buffer_free() & mask; + if (t > count) + produce_audio(playback->output->written_time(), + FMT_S16_NE, 2, count, buffer, NULL); + else + { + if (t) + produce_audio(playback->output->written_time(), + FMT_S16_NE, 2, t, buffer, NULL); + g_usleep((count-t)*1000*5/441/2); + } + count -= t; + buffer += t; + } + if (seek) + { + if(sexypsf_seek(seek)) + { + playback->output->flush(seek); + seek = 0; + } + else // negative time - must make a C time machine + { + sexypsf_stop(); + return; + } + } + if (stop) + sexypsf_stop(); +} + +static gpointer sexypsf_playloop(gpointer arg) +{ + while (TRUE) + { + sexypsf_execute(); + + /* we have reached the end of the song or a command was issued */ + + playback->output->buffer_free(); + playback->output->buffer_free(); + + if (stop) + break; + + if (seek) + { + playback->output->flush(seek); + if(!(PSFInfo = sexypsf_load(fnsave))) + break; + sexypsf_seek(seek); + seek = 0; + continue; + } + + // timeout at the end of a file + sleep(4); + break; + } + + playback->output->close_audio(); + if (!(stop)) nextsong = TRUE; + g_thread_exit(NULL); + return NULL; +} + +static void sexypsf_xmms_play(InputPlayback *data) +{ + if (playing) + return; + + playback = data; + nextsong = FALSE; + paused = FALSE; + + if (!playback->output->open_audio(FMT_S16_NE, 44100, 2)) + { + audio_error = TRUE; + return; + } + + fnsave = malloc(strlen(data->filename)+1); + strcpy(fnsave, data->filename); + if(!(PSFInfo=sexypsf_load(data->filename))) + { + playback->output->close_audio(); + nextsong = 1; + } + else + { + stop = seek = 0; + + gchar *name = get_title_psf(data->filename); + sexypsf_ip.set_info(name, PSFInfo->length, 44100*2*2*8, 44100, 2); + g_free(name); + + playing = 1; + dethread = g_thread_create((GThreadFunc)sexypsf_playloop, + NULL, TRUE, NULL); + } +} + +static void sexypsf_xmms_stop(InputPlayback * playback) +{ + if (!playing) return; + + if (paused) + playback->output->pause(0); + paused = FALSE; + + stop = TRUE; + g_thread_join(dethread); + playing = FALSE; + + if (fnsave) + { + free(fnsave); + fnsave = NULL; + } + sexypsf_freepsfinfo(PSFInfo); + PSFInfo = NULL; +} + +static void sexypsf_xmms_pause(InputPlayback *playback, short p) +{ + if (!playing) return; + playback->output->pause(p); + paused = p; +} + +static void sexypsf_xmms_seek(InputPlayback * data, int time) +{ + if (!playing) return; + seek = time * 1000; +} + +static int sexypsf_xmms_gettime(InputPlayback *playback) +{ + if (audio_error) + return -2; + if (nextsong) + return -1; + if (!playing) + return 0; + + return playback->output->output_time(); +} + +static void sexypsf_xmms_getsonginfo(char *fn, char **title, int *length) +{ + PSFINFO *tmp; + + if((tmp = sexypsf_getpsfinfo(fn))) { + *length = tmp->length; + *title = get_title_psf(fn); + sexypsf_freepsfinfo(tmp); + } +} + +static TitleInput *get_tuple_psf(gchar *fn) { + TitleInput *tuple = NULL; + PSFINFO *tmp = sexypsf_getpsfinfo(fn); + + if (tmp->length) { + tuple = bmp_title_input_new(); + tuple->length = tmp->length; + tuple->performer = g_strdup(tmp->artist); + tuple->album_name = g_strdup(tmp->game); + tuple->track_name = g_strdup(tmp->title); + tuple->file_name = g_path_get_basename(fn); + tuple->file_path = g_path_get_dirname(fn); + sexypsf_freepsfinfo(tmp); + } + + return tuple; +} + +static gchar *get_title_psf(gchar *fn) { + gchar *title = NULL; + TitleInput *tinput = get_tuple_psf(fn); + + if (tinput != NULL) { + title = xmms_get_titlestring(xmms_get_gentitle_format(), + tinput); + bmp_title_input_free(tinput); + } + else + title = g_path_get_basename(fn); + + return title; +} + +gchar *sexypsf_fmts[] = { "psf", "minipsf", NULL }; + +InputPlugin sexypsf_ip = +{ + NULL, + NULL, + "PSF Audio Plugin", + NULL, + NULL, + NULL, + NULL, + NULL, + sexypsf_xmms_play, + sexypsf_xmms_stop, + sexypsf_xmms_pause, + sexypsf_xmms_seek, + NULL, + sexypsf_xmms_gettime, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + sexypsf_xmms_getsonginfo, + NULL, + NULL, + get_tuple_psf, + NULL, + NULL, + is_our_fd, + sexypsf_fmts, +}; + +InputPlugin *sexypsf_iplist[] = { &sexypsf_ip, NULL }; + +DECLARE_PLUGIN(sexypsf, NULL, NULL, sexypsf_iplist, NULL, NULL, NULL, NULL); diff -r 3094d9c8a935 -r c1dcc9d38f98 src/sexypsf/xmms.c --- a/src/sexypsf/xmms.c Wed Jul 04 23:25:02 2007 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,291 +0,0 @@ -/* sexyPSF - PSF1 player - * Copyright (C) 2002-2004 xodnizel - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include "audacious/output.h" -#include "audacious/plugin.h" -#include "audacious/titlestring.h" -#include "audacious/util.h" -#include "audacious/vfs.h" -#include -#include -#include -#include -#include "driver.h" - -#define CMD_SEEK 0x80000000 -#define CMD_STOP 0x40000000 - -#define uint32 u32 -#define int16 short - -static volatile uint32 command; -static volatile int playing=0; -static volatile int nextsong=0; - -extern InputPlugin sexypsf_ip; -static char *fnsave=NULL; - -static gchar *get_title_psf(gchar *fn); -static int paused; -static GThread *dethread; -static PSFINFO *PSFInfo=NULL; - -static int is_our_fd(gchar *filename, VFSFile *file) { - gchar magic[4], *tmps; - // Filter out psflib [we use them, but we can't play them] - static const gchar *teststr = "psflib"; - if (strlen(teststr) < strlen(filename)) { - tmps = filename + strlen(filename); - tmps -= strlen(teststr); - if (!strcasecmp(tmps, teststr)) - return 0; - } - vfs_fread(magic,1,4,file); - //Only allow PSF1 for now. - if (!memcmp(magic,"PSF\x01",4)) - return 1; - return 0; -} - -static void SI(gchar *filename) -{ - gchar *name = get_title_psf(filename); - sexypsf_ip.set_info(name,PSFInfo->length,44100*2*2*8,44100,2); - g_free(name); -} - -static InputPlayback *playback; - -void sexypsf_update(unsigned char *Buffer, long count) -{ - int mask = ~((((16 / 8) * 2)) - 1); - - while(count>0) - { - int t=playback->output->buffer_free() & mask; - if(t>count) - produce_audio(playback->output->written_time(), FMT_S16_NE, 2, count, Buffer, NULL); - else - { - if(t) - produce_audio(playback->output->written_time(), FMT_S16_NE, 2, t, Buffer, NULL); - g_usleep((count-t)*1000*5/441/2); - } - count-=t; - Buffer+=t; - } - if(command&CMD_SEEK) - { - int t=(command&~(CMD_SEEK|CMD_STOP))*1000; - - if(sexypsf_seek(t)) - playback->output->flush(t); - else // Negative time! Must make a C time machine. - { - sexypsf_stop(); - return; - } - command&=~CMD_SEEK; - } - if(command&CMD_STOP) - sexypsf_stop(); -} - -static void *sexypsf_playloop(void *arg) -{ -dofunky: - - sexypsf_execute(); - - /* We have reached the end of the song. Now what... */ - playback->output->buffer_free(); - playback->output->buffer_free(); - - while(!(command&CMD_STOP)) - { - if(command&CMD_SEEK) - { - int t=(command&~(CMD_SEEK|CMD_STOP))*1000; - playback->output->flush(t); - if(!(PSFInfo=sexypsf_load(fnsave))) - break; - sexypsf_seek(t); - command&=~CMD_SEEK; - goto dofunky; - } - if(!playback->output->buffer_playing()) break; - usleep(2000); - } - playback->output->close_audio(); - if(!(command&CMD_STOP)) nextsong=1; - g_thread_exit(NULL); - return(NULL); -} - -static void sexypsf_xmms_play(InputPlayback *data) -{ - char *fn = data->filename; - if(playing) - return; - playback = data; - nextsong=0; - paused = 0; - if(!playback->output->open_audio(FMT_S16_NE, 44100, 2)) - { - puts("Error opening audio."); - return; - } - fnsave=malloc(strlen(fn)+1); - strcpy(fnsave,fn); - if(!(PSFInfo=sexypsf_load(fn))) - { - playback->output->close_audio(); - nextsong=1; - } - else - { - command=0; - SI(fn); - playing=1; - dethread = g_thread_create((GThreadFunc)sexypsf_playloop,NULL,TRUE,NULL); - } -} - -static void sexypsf_xmms_stop(InputPlayback * playback) -{ - if(!playing) return; - - if(paused) - playback->output->pause(0); - paused = 0; - - command=CMD_STOP; - g_thread_join(dethread); - playing = 0; - - if(fnsave) - { - free(fnsave); - fnsave=NULL; - } - sexypsf_freepsfinfo(PSFInfo); - PSFInfo=NULL; -} - -static void sexypsf_xmms_pause(InputPlayback * playback, short p) -{ - if(!playing) return; - playback->output->pause(p); - paused = p; -} - -static void sexypsf_xmms_seek(InputPlayback * data, int time) -{ - if(!playing) return; - command=CMD_SEEK|time; -} - -static int sexypsf_xmms_gettime(InputPlayback *playback) -{ - if(nextsong) - return(-1); - if(!playing) return(0); - return playback->output->output_time(); -} - -static void sexypsf_xmms_getsonginfo(char *fn, char **title, int *length) -{ - PSFINFO *tmp; - - if((tmp=sexypsf_getpsfinfo(fn))) { - *length = tmp->length; - *title = get_title_psf(fn); - sexypsf_freepsfinfo(tmp); - } -} - -static TitleInput *get_tuple_psf(gchar *fn) { - TitleInput *tuple = NULL; - PSFINFO *tmp = sexypsf_getpsfinfo(fn); - - if (tmp->length) { - tuple = bmp_title_input_new(); - tuple->length = tmp->length; - tuple->performer = g_strdup(tmp->artist); - tuple->album_name = g_strdup(tmp->game); - tuple->track_name = g_strdup(tmp->title); - tuple->file_name = g_path_get_basename(fn); - tuple->file_path = g_path_get_dirname(fn); - } - - return tuple; -} - -static gchar *get_title_psf(gchar *fn) { - gchar *title; - TitleInput *tinput = get_tuple_psf(fn); - - if (tinput != NULL) { - title = xmms_get_titlestring(xmms_get_gentitle_format(), - tinput); - bmp_title_input_free(tinput); - } - else - title = g_path_get_basename(fn); - - return title; -} - -gchar *sexypsf_fmts[] = { "psf", "minipsf", NULL }; - -InputPlugin sexypsf_ip = -{ - NULL, - NULL, - "PSF Audio Plugin", - NULL, - NULL, - NULL, - NULL, - NULL, - sexypsf_xmms_play, - sexypsf_xmms_stop, - sexypsf_xmms_pause, - sexypsf_xmms_seek, - NULL, - sexypsf_xmms_gettime, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - sexypsf_xmms_getsonginfo, - NULL, - NULL, - get_tuple_psf, - NULL, - NULL, - is_our_fd, - sexypsf_fmts, -}; - -InputPlugin *sexypsf_iplist[] = { &sexypsf_ip, NULL }; - -DECLARE_PLUGIN(sexypsf, NULL, NULL, sexypsf_iplist, NULL, NULL, NULL, NULL);