Mercurial > audlegacy-plugins
changeset 1579:a5725f7f1a5e
Chainsaw, this is for you: Separate playlist entries added for sub-tunes;
Also cleaned up the playing function. Sub-tune controls are now gone.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Mon, 03 Sep 2007 09:04:49 +0300 |
parents | 6d90d40ca0c8 |
children | b83dfdc605d5 |
files | src/sid/xmms-sid.c |
diffstat | 1 files changed, 204 insertions(+), 217 deletions(-) [+] |
line wrap: on
line diff
--- a/src/sid/xmms-sid.c Mon Sep 03 08:45:34 2007 +0300 +++ b/src/sid/xmms-sid.c Mon Sep 03 09:04:49 2007 +0300 @@ -39,6 +39,7 @@ #include "xs_glade.h" #include "xs_player.h" #include "xs_slsup.h" +#include "audacious/playlist.h" /* @@ -256,59 +257,153 @@ */ gint xs_is_our_file(gchar *pcFilename) { + gint result = 0; t_xs_file *f; assert(xs_status.sidPlayer); /* Check the filename */ if (pcFilename == NULL) - return FALSE; + return 0; +// XS_MUTEX_LOCK(xs_status); if ((f = xs_fopen(pcFilename, "rb")) != NULL) { if (xs_status.sidPlayer->plrProbe(f)) - return TRUE; + result = 1; xs_fclose(f); } - return FALSE; +// XS_MUTEX_UNLOCK(xs_status); + return result; +} + +static gboolean xs_get_trackinfo(const gchar *pcFilename, gchar **pcResult, gint *pTrack) +{ + gchar *tmpSep; + + *pcResult = g_strdup(pcFilename); + tmpSep = xs_strrchr(*pcResult, '?'); + + if (tmpSep && g_ascii_isdigit(*(tmpSep + 1))) { + *tmpSep = '\0'; + *pTrack = atoi(tmpSep + 1); + return TRUE; + } else { + *pTrack = -1; + return FALSE; + } } gint xs_is_our_file_vfs(gchar *pcFilename, t_xs_file *f) { + gint tmpResult = 0; assert(xs_status.sidPlayer); /* Check the filename */ if (pcFilename == NULL) - return FALSE; + return 0; + + if (xs_status.sidPlayer->plrProbe(f)) { + gchar *tmpFilename = NULL; + gint tmpDummy = 0; - return xs_status.sidPlayer->plrProbe(f); + if (xs_get_trackinfo(pcFilename, &tmpFilename, &tmpDummy)) { + tmpResult = 1; + } else { + t_xs_tuneinfo *pInfo = xs_status.sidPlayer->plrGetSIDInfo(tmpFilename); + + if (pInfo->nsubTunes > 1) { + gint i; + + for (i = 1; i <= pInfo->nsubTunes; i++) { + gchar *tmpStr = g_strdup_printf("%s?%d", pcFilename, i); + gboolean doAdd = FALSE; + + if (xs_cfg.subAutoMinOnly) { + if (pInfo->subTunes[i - 1].tuneLength >= xs_cfg.subAutoMinTime) + doAdd = TRUE; + } else + doAdd = TRUE; + + if (doAdd) + playlist_add_url(playlist_get_active(), tmpStr); + + g_free(tmpStr); + } + + tmpResult = -1; + } else + tmpResult = 1; + + xs_tuneinfo_free(pInfo); + } + + g_free(tmpFilename); + } + + return tmpResult; } /* - * Main playing thread loop + * Start playing the given file */ -void *xs_playthread(void *argPointer) +void xs_play_file(InputPlayback *pb) { - InputPlayback *pb = argPointer; t_xs_status myStatus; t_xs_tuneinfo *myTune; gboolean audioOpen = FALSE, doPlay = FALSE, isFound = FALSE; - gint audioGot, songLength, i; - gchar *audioBuffer = NULL, *oversampleBuffer = NULL; + gint audioGot, songLength, i, subTune; + gchar *tmpFilename, *audioBuffer = NULL, *oversampleBuffer = NULL; Tuple *tmpTitle; - (void) argPointer; + assert(pb); + assert(xs_status.sidPlayer); + + XSDEBUG("play '%s'\n", pb->filename); - /* Initialize */ - XSDEBUG("entering player thread\n"); XS_MUTEX_LOCK(xs_status); - memcpy(&myStatus, &xs_status, sizeof(t_xs_status)); + + /* Get tune information */ + xs_get_trackinfo(pb->filename, &tmpFilename, &subTune); + + if ((xs_status.tuneInfo = xs_status.sidPlayer->plrGetSIDInfo(tmpFilename)) == NULL) { + g_free(tmpFilename); + return; + } + + /* Initialize the tune */ + if (!xs_status.sidPlayer->plrLoadSID(&xs_status, tmpFilename)) { + g_free(tmpFilename); + xs_tuneinfo_free(xs_status.tuneInfo); + xs_status.tuneInfo = NULL; + return; + } + + g_free(tmpFilename); + + XSDEBUG("load ok\n"); + + /* Set general status information */ + xs_status.isPlaying = TRUE; + xs_status.isError = FALSE; myTune = xs_status.tuneInfo; - for (i = 0; i <= myTune->nsubTunes; i++) - myTune->subTunes[i].tunePlayed = FALSE; + + if (subTune < 1 && subTune > xs_status.tuneInfo->nsubTunes) + xs_status.currSong = xs_status.tuneInfo->startTune; + else + xs_status.currSong = subTune; + + XSDEBUG("subtune #%i selected (#%d wanted), initializing...\n", xs_status.currSong, subTune); + memcpy(&myStatus, &xs_status, sizeof(t_xs_status)); XS_MUTEX_UNLOCK(xs_status); + + /* We are ready */ + xs_decode_thread = g_thread_self(); + pb->set_pb_ready(pb); + + /* Allocate audio buffer */ audioBuffer = (gchar *) g_malloc(XS_AUDIOBUF_SIZE); if (audioBuffer == NULL) { @@ -316,7 +411,7 @@ goto xs_err_exit; } - if (myStatus.oversampleEnable) { + if (xs_status.oversampleEnable) { oversampleBuffer = (gchar *) g_malloc(XS_AUDIOBUF_SIZE * myStatus.oversampleFactor); if (oversampleBuffer == NULL) { xs_error(_("Couldn't allocate memory for audio oversampling buffer!\n")); @@ -324,103 +419,44 @@ } } - /* - * Main player loop: while not stopped, loop here - play subtunes - */ - audioOpen = FALSE; - doPlay = TRUE; - while (xs_status.isPlaying && doPlay) { - /* Automatic sub-tune change logic */ - XS_MUTEX_LOCK(xs_cfg); - XS_MUTEX_LOCK(xs_status); - myStatus.isPlaying = TRUE; - - if (xs_status.currSong < 1 || myStatus.currSong < 1) { - XS_MUTEX_UNLOCK(xs_status); - XS_MUTEX_UNLOCK(xs_cfg); - goto xs_err_exit; - } - - if (xs_cfg.subAutoEnable && (myStatus.currSong == xs_status.currSong)) { - /* Check if currently selected sub-tune has been played already */ - if (myTune->subTunes[myStatus.currSong-1].tunePlayed) { - /* Find a tune that has not been played */ - XSDEBUG("tune #%i already played, finding next match ...\n", myStatus.currSong); - isFound = FALSE; - i = 0; - while (!isFound && (++i <= myTune->nsubTunes)) { - if (xs_cfg.subAutoMinOnly) { - /* A tune with minimum length must be found */ - if (!myTune->subTunes[i-1].tunePlayed && - myTune->subTunes[i-1].tuneLength >= xs_cfg.subAutoMinTime) - isFound = TRUE; - } else { - /* Any unplayed tune is okay */ - if (!myTune->subTunes[i-1].tunePlayed) - isFound = TRUE; - } - } - if (isFound) { - /* Set the new sub-tune */ - XSDEBUG("found #%i\n", i); - xs_status.currSong = i; - } else - /* This is the end */ - doPlay = FALSE; + /* Check minimum playtime */ + songLength = myTune->subTunes[myStatus.currSong - 1].tuneLength; + if (xs_cfg.playMinTimeEnable && (songLength >= 0)) { + if (songLength < xs_cfg.playMinTime) + songLength = xs_cfg.playMinTime; + } - XS_MUTEX_UNLOCK(xs_status); - XS_MUTEX_UNLOCK(xs_cfg); - continue; /* This is ugly, but ... */ - } - } - - /* Tell that we are initializing, update sub-tune controls */ - myStatus.currSong = xs_status.currSong; - myTune->subTunes[myStatus.currSong-1].tunePlayed = TRUE; - XS_MUTEX_UNLOCK(xs_status); - XS_MUTEX_UNLOCK(xs_cfg); - - XSDEBUG("subtune #%i selected, initializing...\n", myStatus.currSong); - - /* Check minimum playtime */ - songLength = myTune->subTunes[myStatus.currSong-1].tuneLength; - if (xs_cfg.playMinTimeEnable && (songLength >= 0)) { - if (songLength < xs_cfg.playMinTime) - songLength = xs_cfg.playMinTime; - } + /* Initialize song */ + if (!myStatus.sidPlayer->plrInitSong(&myStatus)) { + xs_error(_("Couldn't initialize SID-tune '%s' (sub-tune #%i)!\n"), + myTune->sidFilename, myStatus.currSong); + goto xs_err_exit; + } + + /* Open the audio output */ + XSDEBUG("open audio output (%d, %d, %d)\n", + myStatus.audioFormat, myStatus.audioFrequency, myStatus.audioChannels); + + if (!pb->output->open_audio(myStatus.audioFormat, myStatus.audioFrequency, myStatus.audioChannels)) { + xs_error(_("Couldn't open XMMS audio output (fmt=%x, freq=%i, nchan=%i)!\n"), + myStatus.audioFormat, + myStatus.audioFrequency, + myStatus.audioChannels); - /* Initialize song */ - if (!myStatus.sidPlayer->plrInitSong(&myStatus)) { - xs_error(_("Couldn't initialize SID-tune '%s' (sub-tune #%i)!\n"), - myTune->sidFilename, myStatus.currSong); - goto xs_err_exit; - } - - /* Open the audio output */ - XSDEBUG("open audio output (%d, %d, %d)\n", - myStatus.audioFormat, myStatus.audioFrequency, myStatus.audioChannels); - - if (!pb->output-> - open_audio(myStatus.audioFormat, myStatus.audioFrequency, myStatus.audioChannels)) { - xs_error(_("Couldn't open XMMS audio output (fmt=%x, freq=%i, nchan=%i)!\n"), - myStatus.audioFormat, - myStatus.audioFrequency, - myStatus.audioChannels); + XS_MUTEX_LOCK(xs_status); + xs_status.isError = TRUE; + XS_MUTEX_UNLOCK(xs_status); + goto xs_err_exit; + } - XS_MUTEX_LOCK(xs_status); - xs_status.isError = TRUE; - XS_MUTEX_UNLOCK(xs_status); - goto xs_err_exit; - } + audioOpen = TRUE; - audioOpen = TRUE; - - /* Set song information for current subtune */ - XSDEBUG("set tune info\n"); - myStatus.sidPlayer->plrUpdateSIDInfo(&myStatus); + /* Set song information for current subtune */ + XSDEBUG("foobar\n"); + myStatus.sidPlayer->plrUpdateSIDInfo(&myStatus); /* - tmpTitle = xs_make_titlestring(myTune, myStatus.currSong); + tmpTitle = xs_make_titlestring(myTune, subTune); xs_plugin_ip.set_info( tmpTitle, @@ -431,78 +467,58 @@ g_free(tmpTitle); */ - XSDEBUG("playing\n"); + + XSDEBUG("playing\n"); + while (xs_status.isPlaying && myStatus.isPlaying) { + /* Render audio data */ + if (myStatus.oversampleEnable) { + /* Perform oversampled rendering */ + audioGot = myStatus.sidPlayer->plrFillBuffer( + &myStatus, + oversampleBuffer, + (XS_AUDIOBUF_SIZE * myStatus.oversampleFactor)); + + audioGot /= myStatus.oversampleFactor; - /* - * Play the subtune - */ - while (xs_status.isPlaying && myStatus.isPlaying && (xs_status.currSong == myStatus.currSong)) { - /* Render audio data */ - if (myStatus.oversampleEnable) { - /* Perform oversampled rendering */ - audioGot = myStatus.sidPlayer->plrFillBuffer( - &myStatus, - oversampleBuffer, - (XS_AUDIOBUF_SIZE * myStatus.oversampleFactor)); + /* Execute rate-conversion with filtering */ + if (xs_filter_rateconv(audioBuffer, oversampleBuffer, + myStatus.audioFormat, myStatus.oversampleFactor, audioGot) < 0) { + xs_error(_("Oversampling rate-conversion pass failed.\n")); + XS_MUTEX_LOCK(xs_status); + xs_status.isError = TRUE; + XS_MUTEX_UNLOCK(xs_status); + goto xs_err_exit; + } + } else { + audioGot = myStatus.sidPlayer->plrFillBuffer( + &myStatus, audioBuffer, XS_AUDIOBUF_SIZE); + } - audioGot /= myStatus.oversampleFactor; + /* I <3 visualice/haujobb */ + produce_audio(pb->output->written_time(), + myStatus.audioFormat, myStatus.audioChannels, + audioGot, audioBuffer, NULL); - /* Execute rate-conversion with filtering */ - if (xs_filter_rateconv(audioBuffer, oversampleBuffer, - myStatus.audioFormat, myStatus.oversampleFactor, audioGot) < 0) { - xs_error(_("Oversampling rate-conversion pass failed.\n")); - XS_MUTEX_LOCK(xs_status); - xs_status.isError = TRUE; - XS_MUTEX_UNLOCK(xs_status); - goto xs_err_exit; - } + /* Wait a little */ + while (xs_status.isPlaying && (pb->output->buffer_free() < audioGot)) + xmms_usleep(500); + + /* Check if we have played enough */ + if (xs_cfg.playMaxTimeEnable) { + if (xs_cfg.playMaxTimeUnknown) { + if ((songLength < 0) && + (pb->output->output_time() >= (xs_cfg.playMaxTime * 1000))) + myStatus.isPlaying = FALSE; } else { - audioGot = myStatus.sidPlayer->plrFillBuffer( - &myStatus, audioBuffer, XS_AUDIOBUF_SIZE); - } - - /* I <3 visualice/haujobb */ - produce_audio(pb->output->written_time(), - myStatus.audioFormat, myStatus.audioChannels, - audioGot, audioBuffer, NULL); - - /* Wait a little */ - while (xs_status.isPlaying && - (xs_status.currSong == myStatus.currSong) && - (pb->output->buffer_free() < audioGot)) - xmms_usleep(500); - - /* Check if we have played enough */ - if (xs_cfg.playMaxTimeEnable) { - if (xs_cfg.playMaxTimeUnknown) { - if ((songLength < 0) && - (pb->output->output_time() >= (xs_cfg.playMaxTime * 1000))) - myStatus.isPlaying = FALSE; - } else { - if (pb->output->output_time() >= (xs_cfg.playMaxTime * 1000)) - myStatus.isPlaying = FALSE; - } - } - - if (songLength >= 0) { - if (pb->output->output_time() >= (songLength * 1000)) + if (pb->output->output_time() >= (xs_cfg.playMaxTime * 1000)) myStatus.isPlaying = FALSE; } } - XSDEBUG("subtune ended/stopped\n"); - - /* Close audio output plugin */ - if (audioOpen) { - XSDEBUG("close audio #1\n"); - pb->output->close_audio(); - audioOpen = FALSE; - XSDEBUG("closed\n"); + if (songLength >= 0) { + if (pb->output->output_time() >= (songLength * 1000)) + myStatus.isPlaying = FALSE; } - - /* Now determine if we continue by selecting other subtune or something */ - if (!myStatus.isPlaying && !xs_cfg.subAutoEnable) - doPlay = FALSE; } xs_err_exit: @@ -533,46 +549,6 @@ /* - * Start playing the given file - * Here we load the tune and initialize the playing thread. - * Usually you would also initialize the output-plugin, but - * this is XMMS-SID and we do it on the player thread instead. - */ -void xs_play_file(InputPlayback *pb) -{ - assert(pb); - assert(xs_status.sidPlayer); - - XSDEBUG("play '%s'\n", pb->filename); - - /* Get tune information */ - if ((xs_status.tuneInfo = xs_status.sidPlayer->plrGetSIDInfo(pb->filename)) == NULL) - return; - - /* Initialize the tune */ - if (!xs_status.sidPlayer->plrLoadSID(&xs_status, pb->filename)) { - xs_tuneinfo_free(xs_status.tuneInfo); - xs_status.tuneInfo = NULL; - return; - } - - XSDEBUG("load ok\n"); - - /* Set general status information */ - xs_status.isPlaying = TRUE; - xs_status.isError = FALSE; - xs_status.currSong = xs_status.tuneInfo->startTune; - - /* Start the playing thread! */ - xs_decode_thread = g_thread_self(); - pb->set_pb_ready(pb); - xs_playthread(pb); - - XSDEBUG("playback is done\n"); -} - - -/* * Stop playing * Here we set the playing status to stop and wait for playing * thread to shut down. In any "correctly" done plugin, this is @@ -669,22 +645,26 @@ { t_xs_tuneinfo *pInfo; Tuple *pResult; - gchar *tmpStr; + gchar *tmpStr, *tmpFilename; + gint subTune; XS_MUTEX_LOCK(xs_status); + xs_get_trackinfo(songFilename, &tmpFilename, &subTune); + pResult = tuple_new_from_filename(songFilename); /* Get tune information from emulation engine */ - pInfo = xs_status.sidPlayer->plrGetSIDInfo(songFilename); + pInfo = xs_status.sidPlayer->plrGetSIDInfo(tmpFilename); if (!pInfo) { XS_MUTEX_UNLOCK(xs_status); return pResult; } + + g_free(tmpFilename); tuple_associate_string(pResult, "title", pInfo->sidName); tuple_associate_string(pResult, "artist", pInfo->sidComposer); - tuple_associate_int(pResult, "track-number", pInfo->startTune); tuple_associate_string(pResult, "genre", "SID-tune"); tuple_associate_string(pResult, "copyright", pInfo->sidCopyright); tuple_associate_string(pResult, "format", pInfo->sidFormat); @@ -699,10 +679,17 @@ tuple_associate_string(pResult, "sid-model", tmpStr); /* Get sub-tune information, if available */ - if ((pInfo->startTune > 0) && (pInfo->startTune <= pInfo->nsubTunes)) { - gint tmpInt = pInfo->subTunes[pInfo->startTune-1].tuneLength; + if (subTune < 0 || pInfo->startTune > pInfo->nsubTunes) + subTune = pInfo->startTune; + + if ((subTune > 0) && (subTune <= pInfo->nsubTunes)) { + gint tmpInt = pInfo->subTunes[subTune - 1].tuneLength; tuple_associate_int(pResult, "length", (tmpInt < 0) ? -1 : tmpInt * 1000); - } + } else + subTune = 1; + + tuple_associate_int(pResult, "subtune", subTune); + tuple_associate_int(pResult, "track-number", subTune); /* Free tune information */ xs_tuneinfo_free(pInfo);