Mercurial > hg > xmms-sid
view 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 source
/* 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(); }