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();
+}
+
+