Mercurial > hg > xmms-sid
diff src/xmms-sid.c @ 71:2b32c75729ce
Started modularizing, separated sidplay1 things into a "wrapper" module.
Removed non-generic stuff from xmms-sid.cc, removed C++ references and
renamed to xmms-sid.c
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Wed, 10 Sep 2003 06:21:04 +0000 |
parents | |
children | e3b205a6bc7e |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xmms-sid.c Wed Sep 10 06:21:04 2003 +0000 @@ -0,0 +1,405 @@ +/* + XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS) + + Main source file + + Written by Matti "ccr" Hamalainen <ccr@tnsp.org> + + 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. + + 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#include <pthread.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <errno.h> + +#include <xmms/plugin.h> + +#include "xmms-sid.h" +#include "xs_support.h" +#include "xs_config.h" +#include "xs_length.h" +#include "xs_interface.h" +#include "xs_glade.h" + +/* + * Include player engines + */ +#include "xs_sidplay1.h" +#include "xs_sidplay2.h" + + +/* + * Global variables + */ +static GtkWidget *xs_ctrlwin = NULL; +static pthread_t xs_decode_thread; +static pthread_mutex_t xs_mutex = PTHREAD_MUTEX_INITIALIZER; +struct t_xs_cfg xs_cfg; + + +/* + * Create sub-song control window + */ +void xs_ctrlwin_open(void) +{ + /* Create sub-song control window */ + if (xs_ctrlwin != NULL) + { + if (xs_cfg.alwaysRaise) + gdk_window_raise(xs_ctrlwin->window); + return; + } + + xs_ctrlwin = create_xs_ctrlwin(); + gtk_widget_show(xs_ctrlwin); +} + + +/* + * Initialize XMMS-SID + */ +void xs_init(void) +{ + XSDEBUG("xs_init()\n"); + + /* Initialize and get configuration */ + memset(&xs_cfg, 0, sizeof(xs_cfg)); + + xs_read_configuration(); + + /* Initialize status */ + memset(&xs_status, 0, sizeof(xs_status)); + xs_status.allowNext = TRUE; // Initialize to TRUE to allow first song + + /* Try to initialize emulator engine(s) */ + XSDEBUG("initializing emulator engine(s)...\n"); + + + + + /* Read song-length database */ + if (xs_cfg.songlenDBEnable && (xs_songlen_init() < 0)) + { + XSERR("Error initializing song-length database!\n"); + } + + /* Initialize STIL structures */ + +// xs_ctrlwin_open(); + +// FIXME FIXME FIx ME + + XSDEBUG("OK\n"); +} + + +/* + * Shut down XMMS-SID + */ +void xs_close(void) +{ + XSDEBUG("xs_close(): shutting down...\n"); + + /* Stop playing */ + xs_stop(); + + /* Shutdown libSIDPlay(s) */ + + + + + + + /* Close sub-song control window */ + + /* Free allocated memory */ + xs_songlen_close(); + +// FIXME FIXME: STIL-entries + XSDEBUG("shutdown finished.\n"); +} + + +/* + * Main playing thread loop + */ +void *xs_play_loop(void *argPointer) +{ + t_xs_status myStatus; + t_xs_tuneinfo tuneInfo; + gboolean audioOpen; + gint audioFreq, audioChannels, songLength; + enum AFormat audioFmt; + gchar audioBuffer[XS_BUFSIZE]; + gchar *tmpStr; + + + pthread_mutex_lock(&xs_mutex); + XSDEBUG("entering play thread\n"); + + /* No idea, if this is really required here, but better be + * careful since we're dealing with EVIL threads ... + */ + if (!xs_status.allowNext) + { + pthread_mutex_unlock(&xs_mutex); + pthread_exit(NULL); + } + + /* Don't allow next song to be set yet */ + xs_status.allowNext = FALSE; + xs_status.isPlaying = TRUE; + memcpy(&myStatus, &xs_status, sizeof(t_xs_status)); + pthread_mutex_unlock(&xs_mutex); + + + /* Copy and check audio options here (they might change in config while running) */ +#ifdef HAVE_UNSIGNEDPCM + audioFmt = (xs_cfg.fmtBitsPerSample == XS_RES_16BIT) ? FMT_U16_NE : FMT_U8; +#else + audioFmt = (xs_cfg.fmtBitsPerSample == XS_RES_16BIT) ? FMT_S16_NE : FMT_S8; +#endif + audioFreq = xs_cfg.fmtFrequency; + audioChannels = (xs_cfg.fmtChannels == XS_CHN_MONO) ? 1 : 2; + audioOpen = FALSE; + + /* + * Main player loop: while not stopped, loop here - play subtunes + */ + while (xs_status.isPlaying) + { + pthread_mutex_lock(&xs_mutex); + myStatus.currSong = xs_status.currSong; + myStatus.isPlaying = TRUE; + pthread_mutex_unlock(&xs_mutex); + + XSDEBUG("subtune #%i selected, initializing...\n", myStatus.currSong); + + + /* Get song length for current subtune */ + songLength = xs_songlen_get(myStatus.currFileName, myStatus.currSong); + + /* Initialize song */ +#ifdef HAVE_SIDPLAY1 + if ((myStatus.currTune == NULL) || !myStatus.currTune->getStatus() || + !sidEmuInitializeSong(xs_emuEngine, *myStatus.currTune, myStatus.currSong)) +#endif +#ifdef HAVE_SIDPLAY2 + if () +#endif + { + XSERR("Couldn't initialize SID-tune '%s' (sub-tune #%i)!\n", + myStatus.currFileName, myStatus.currSong); + goto err_exit; + } + + myStatus.currTune->getInfo(tuneInfo); + + + /* Set information for current sub-tune */ + tmpStr = xs_filetitle_get(myStatus.currFileName, &tuneInfo, myStatus.currSong); + + xs_plugin_ip.set_info(tmpStr, (songLength > 0) ? songLength * 1000 : -1, + 1000 * (tuneInfo.songSpeed ? tuneInfo.songSpeed : (tuneInfo.clockSpeed == SIDTUNE_CLOCK_NTSC) ? 60 : 50), + audioFreq, audioChannels); + g_free(tmpStr); + + /* Open the audio output */ + if (!xs_plugin_ip.output->open_audio(audioFmt, audioFreq, audioChannels)) + { + XSERR("Couldn't open XMMS audio output!\n"); + pthread_mutex_lock(&xs_mutex); + xs_status.isError = TRUE; + pthread_mutex_unlock(&xs_mutex); + goto err_exit; + } + + audioOpen = TRUE; + + /* + * Play the subtune + */ + while (xs_status.isPlaying && myStatus.isPlaying && (xs_status.currSong == myStatus.currSong)) + { + /* Render audio data */ +#ifdef HAVE_SIDPLAY1 + sidEmuFillBuffer(xs_emuEngine, *myStatus.currTune, audioBuffer, XS_BUFSIZE); +#endif +#ifdef HAVE_SIDPLAY2 +#endif + + /* I <3 visualice/haujobb */ + xs_plugin_ip.add_vis_pcm( + xs_plugin_ip.output->written_time(), + audioFmt, audioChannels, XS_BUFSIZE, audioBuffer); + + /* Wait a little */ + while (xs_status.isPlaying && + (xs_status.currSong == myStatus.currSong) && + (xs_plugin_ip.output->buffer_free() < XS_BUFSIZE)) + xmms_usleep(10000); + + /* Output audio */ + if (xs_status.isPlaying && (xs_status.currSong == myStatus.currSong)) + xs_plugin_ip.output->write_audio(audioBuffer, XS_BUFSIZE); + + /* Check if we have played enough */ + if (xs_cfg.playMaxTimeEnable) + { + if (xs_cfg.playMaxTimeUnknown) + { + if ((songLength == -1) && + (xs_plugin_ip.output->output_time() >= (xs_cfg.playMaxTime * 1000))) + myStatus.isPlaying = FALSE; + } else { + if (xs_plugin_ip.output->output_time() >= (xs_cfg.playMaxTime * 1000)) + myStatus.isPlaying = FALSE; + } + } + + if (songLength > 0) + { + if (xs_plugin_ip.output->output_time() >= (songLength * 1000)) + myStatus.isPlaying = FALSE; + } + } + + XSDEBUG("subtune ended/stopped\n"); + + /* Close audio */ + if (audioOpen) + { + XSDEBUG("close audio #1\n"); + xs_plugin_ip.output->close_audio(); + audioOpen = FALSE; + } + + /* Now determine if we continue by selecting other subtune or something */ + if (!myStatus.isPlaying) xs_status.isPlaying = FALSE; + } + + /* When exiting, delete data */ +err_exit: + pthread_mutex_lock(&xs_mutex); + xs_status.isPlaying = FALSE; + pthread_mutex_unlock(&xs_mutex); + + if (audioOpen) + { + XSDEBUG("close audio #2\n"); + xs_plugin_ip.output->close_audio(); + } + + if (myStatus.currTune != NULL) + { + delete myStatus.currTune; + myStatus.currTune = NULL; + } + + g_free(myStatus.currFileName); + + /* Exit the playing thread */ + XSDEBUG("exiting thread, bye.\n"); + + /* Last thing we do is set allowNext to TRUE to flag + * that we have ended all action in the thread + */ + pthread_mutex_lock(&xs_mutex); + xs_status.allowNext = TRUE; + pthread_mutex_unlock(&xs_mutex); + + pthread_exit(NULL); +} + + +/* + * Start playing the given file + */ +void xs_play_file(char *pcFileName) +{ +} + + +/* + * Stop playing + */ +void xs_stop(void) +{ + /* If playing, stop. */ + XSDEBUG("STOP_REQ\n"); + if (xs_status.isPlaying || !xs_status.allowNext) + { + XSDEBUG("stopping...\n"); + pthread_mutex_lock(&xs_mutex); + xs_status.isPlaying = FALSE; + pthread_mutex_unlock(&xs_mutex); + pthread_join(xs_decode_thread, NULL); + } +} + + +/* + * Pause the playing + */ +void xs_pause(short pauseState) +{ + xs_plugin_ip.output->pause(pauseState); +} + + +/* + * Set the time-seek position + * (the playing thread will do the "seeking" aka song-change) + */ +void xs_seek(gint iTime) +{ + /* If we have song-position patch, check settings */ +#ifdef HAVE_SONG_POSITION + pthread_mutex_lock(&xs_mutex); + + if ((iTime > 0) && (iTime <= xs_status.nSongs) && xs_status.isPlaying) + xs_status.currSong = iTime; + + pthread_mutex_unlock(&xs_mutex); +#endif +} + + +/* + * Return the playing "position/time" + */ +gint xs_get_time(void) +{ + /* If errorflag is set, return -2 to signal it to XMMS's idle callback */ + if (xs_status.isError) + return -2; + + /* If tune has ended, return -1 */ + if (xs_status.allowNext && !xs_status.isPlaying) + return -1; + + /* Obsolete? */ +#ifdef HAVE_SONG_POSITION + pthread_mutex_lock(&xs_mutex); + set_song_position(xs_status.currSong, 1, xs_status.nSongs); + pthread_mutex_unlock(&xs_mutex); +#endif + + /* Else, return output time reported by audio output plugin */ + return xs_plugin_ip.output->output_time(); +} + +