/* * Initialization functions */ void xs_reinit(void) { XSDEBUG("xs_reinit() thread = %p\n", g_thread_self()); XS_MUTEX_LOCK(xs_status); XS_MUTEX_LOCK(xs_cfg); /* Initialize status and sanitize configuration */ memset(&xs_status, 0, sizeof(xs_status)); if (xs_cfg.audioFrequency < 8000) xs_cfg.audioFrequency = 8000; if (xs_cfg.oversampleFactor < XS_MIN_OVERSAMPLE) xs_cfg.oversampleFactor = XS_MIN_OVERSAMPLE; else if (xs_cfg.oversampleFactor > XS_MAX_OVERSAMPLE) xs_cfg.oversampleFactor = XS_MAX_OVERSAMPLE; if (xs_cfg.audioChannels != XS_CHN_MONO) xs_cfg.oversampleEnable = FALSE; xs_status.audioFrequency = xs_cfg.audioFrequency; xs_status.audioBitsPerSample = xs_cfg.audioBitsPerSample; xs_status.audioChannels = xs_cfg.audioChannels; xs_status.audioFormat = -1; xs_status.oversampleEnable = xs_cfg.oversampleEnable; xs_status.oversampleFactor = xs_cfg.oversampleFactor; /* Try to initialize emulator engine */ xs_init_emu_engine(&xs_cfg.playerEngine, &xs_status); /* Get settings back, in case the chosen emulator backend changed them */ xs_cfg.audioFrequency = xs_status.audioFrequency; xs_cfg.audioBitsPerSample = xs_status.audioBitsPerSample; xs_cfg.audioChannels = xs_status.audioChannels; xs_cfg.oversampleEnable = xs_status.oversampleEnable; XS_MUTEX_UNLOCK(xs_status); XS_MUTEX_UNLOCK(xs_cfg); /* Initialize song-length database */ xs_songlen_close(); if (xs_cfg.songlenDBEnable && (xs_songlen_init() != 0)) { xs_error("Error initializing song-length database!\n"); } /* Initialize STIL database */ xs_stil_close(); if (xs_cfg.stilDBEnable && (xs_stil_init() != 0)) { xs_error("Error initializing STIL database!\n"); } }
Tuple * xs_probe_for_tuple(const gchar *filename, xs_file_t *fd) { Tuple *tuple; xs_tuneinfo_t *info; gint tune = -1; if (xs_status.sidPlayer == NULL || filename == NULL) return NULL; XS_MUTEX_LOCK(xs_status); if (!xs_status.sidPlayer->plrProbe(fd)) { XS_MUTEX_UNLOCK(xs_status); return NULL; } XS_MUTEX_UNLOCK(xs_status); /* Get information from URL */ tuple = tuple_new_from_filename (filename); tune = tuple_get_int (tuple, FIELD_SUBSONG_NUM, NULL); /* Get tune information from emulation engine */ XS_MUTEX_LOCK(xs_status); info = xs_status.sidPlayer->plrGetSIDInfo (filename); XS_MUTEX_UNLOCK(xs_status); if (info == NULL) return tuple; xs_get_song_tuple_info(tuple, info, tune); if (xs_cfg.subAutoEnable && info->nsubTunes > 1 && ! tune) xs_fill_subtunes(tuple, info); xs_tuneinfo_free(info); return tuple; }
/* * 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 * also the function where you close the output-plugin, but since * XMMS-SID has special behaviour (audio opened/closed in the * playing thread), we don't do that here. * * Finally tune and other memory allocations are free'd. */ void xs_stop(InputPlayback *pb) { XSDEBUG("stop requested\n"); /* Lock xs_status and stop playing thread */ XS_MUTEX_LOCK(xs_status); if (! xs_status.stop_flag) { XSDEBUG("stopping...\n"); xs_status.stop_flag = TRUE; pb->output->abort_write (); } XS_MUTEX_UNLOCK (xs_status); XSDEBUG("ok\n"); }
/* Reset/initialize the configuration */ void xs_init_configuration(void) { /* Lock configuration mutex */ XSDEBUG("initializing configuration ...\n"); XS_MUTEX_LOCK(xs_cfg); memset(&xs_cfg, 0, sizeof(xs_cfg)); /* Initialize values with sensible defaults */ xs_cfg.audioBitsPerSample = XS_RES_16BIT; xs_cfg.audioChannels = XS_CHN_MONO; xs_cfg.audioFrequency = XS_AUDIO_FREQ; xs_cfg.mos8580 = FALSE; xs_cfg.forceModel = FALSE; /* Filter values */ xs_cfg.emulateFilters = TRUE; xs_cfg.sid1Filter.fs = XS_SIDPLAY1_FS; xs_cfg.sid1Filter.fm = XS_SIDPLAY1_FM; xs_cfg.sid1Filter.ft = XS_SIDPLAY1_FT; #ifdef HAVE_SIDPLAY2 xs_cfg.playerEngine = XS_ENG_SIDPLAY2; xs_cfg.memoryMode = XS_MPU_REAL; #else #ifdef HAVE_SIDPLAY1 xs_cfg.playerEngine = XS_ENG_SIDPLAY1; xs_cfg.memoryMode = XS_MPU_BANK_SWITCHING; #else #error This should not happen! No emulator engines configured in! #endif #endif xs_cfg.clockSpeed = XS_CLOCK_PAL; xs_cfg.forceSpeed = FALSE; xs_cfg.sid2OptLevel = 0; xs_cfg.sid2NFilterPresets = 0; #ifdef HAVE_RESID_BUILDER xs_cfg.sid2Builder = XS_BLD_RESID; #else #ifdef HAVE_HARDSID_BUILDER xs_cfg.sid2Builder = XS_BLD_HARDSID; #else #ifdef HAVE_SIDPLAY2 #error This should not happen! No supported SIDPlay2 builders configured in! #endif #endif #endif xs_cfg.oversampleEnable = FALSE; xs_cfg.oversampleFactor = XS_MIN_OVERSAMPLE; xs_cfg.playMaxTimeEnable = FALSE; xs_cfg.playMaxTimeUnknown = FALSE; xs_cfg.playMaxTime = 150; xs_cfg.playMinTimeEnable = FALSE; xs_cfg.playMinTime = 15; xs_cfg.songlenDBEnable = FALSE; xs_pstrcpy(&xs_cfg.songlenDBPath, "~/C64Music/DOCUMENTS/Songlengths.txt"); xs_cfg.stilDBEnable = FALSE; xs_pstrcpy(&xs_cfg.stilDBPath, "~/C64Music/DOCUMENTS/STIL.txt"); xs_pstrcpy(&xs_cfg.hvscPath, "~/C64Music"); #if defined(HAVE_SONG_POSITION) && !defined(AUDACIOUS_PLUGIN) xs_cfg.subsongControl = XS_SSC_PATCH; #else xs_cfg.subsongControl = XS_SSC_POPUP; #endif xs_cfg.detectMagic = FALSE; #ifndef HAVE_XMMSEXTRA xs_cfg.titleOverride = TRUE; #endif #ifdef AUDACIOUS_PLUGIN xs_pstrcpy(&xs_cfg.titleFormat, "${artist} - ${title} (${copyright}) <${subsong-id}/${subsong-num}> [${sid-model}/${sid-speed}]"); #else xs_pstrcpy(&xs_cfg.titleFormat, "%p - %t (%c) <%n/%N> [%m/%C]"); #endif xs_cfg.subAutoEnable = FALSE; xs_cfg.subAutoMinOnly = TRUE; xs_cfg.subAutoMinTime = 15; /* Unlock the configuration */ XS_MUTEX_UNLOCK(xs_cfg); }
/* * Pause/unpause the playing */ void xs_pause (InputPlayback * pb, gboolean pauseState) { XS_MUTEX_LOCK(xs_status); pb->output->pause(pauseState); XS_MUTEX_UNLOCK(xs_status); }
/* * Start playing the given file */ gboolean xs_play_file(InputPlayback *pb, const gchar *filename, VFSFile *file, gint start_time, gint stop_time, gboolean pause) { xs_tuneinfo_t *tmpTune; gint audioBufSize, bufRemaining, tmpLength, subTune = -1; gchar *audioBuffer = NULL, *oversampleBuffer = NULL; Tuple *tmpTuple; assert(pb); assert(xs_status.sidPlayer != NULL); uri_parse (filename, NULL, NULL, NULL, & subTune); /* Get tune information */ XS_MUTEX_LOCK(xs_status); if (! (xs_status.tuneInfo = xs_status.sidPlayer->plrGetSIDInfo (filename))) { XS_MUTEX_UNLOCK(xs_status); return FALSE; } /* Initialize the tune */ if (! xs_status.sidPlayer->plrLoadSID (& xs_status, filename)) { XS_MUTEX_UNLOCK(xs_status); xs_tuneinfo_free(xs_status.tuneInfo); xs_status.tuneInfo = NULL; return FALSE; } gboolean error = FALSE; /* Set general status information */ tmpTune = xs_status.tuneInfo; 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); gint channels = (xs_status.audioChannels == XS_CHN_AUTOPAN) ? 2 : xs_status.audioChannels; /* Allocate audio buffer */ audioBufSize = xs_status.audioFrequency * channels * xs_status.audioBitsPerSample / (8 * 4); if (audioBufSize < 512) audioBufSize = 512; audioBuffer = (gchar *) g_malloc(audioBufSize); if (audioBuffer == NULL) { xs_error("Couldn't allocate memory for audio data buffer!\n"); XS_MUTEX_UNLOCK(xs_status); goto xs_err_exit; } if (xs_status.oversampleEnable) { oversampleBuffer = (gchar *) g_malloc(audioBufSize * xs_status.oversampleFactor); if (oversampleBuffer == NULL) { xs_error("Couldn't allocate memory for audio oversampling buffer!\n"); XS_MUTEX_UNLOCK(xs_status); goto xs_err_exit; } } /* Check minimum playtime */ tmpLength = tmpTune->subTunes[xs_status.currSong - 1].tuneLength; if (xs_cfg.playMinTimeEnable && (tmpLength >= 0)) { if (tmpLength < xs_cfg.playMinTime) tmpLength = xs_cfg.playMinTime; } /* Initialize song */ if (!xs_status.sidPlayer->plrInitSong(&xs_status)) { xs_error("Couldn't initialize SID-tune '%s' (sub-tune #%i)!\n", tmpTune->sidFilename, xs_status.currSong); XS_MUTEX_UNLOCK(xs_status); goto xs_err_exit; } /* Open the audio output */ XSDEBUG("open audio output (%d, %d, %d)\n", xs_status.audioFormat, xs_status.audioFrequency, channels); if (!pb->output->open_audio(xs_status.audioFormat, xs_status.audioFrequency, channels)) { xs_error("Couldn't open audio output (fmt=%x, freq=%i, nchan=%i)!\n", xs_status.audioFormat, xs_status.audioFrequency, channels); XS_MUTEX_UNLOCK(xs_status); goto xs_err_exit; } /* Set song information for current subtune */ XSDEBUG("foobar #1\n"); xs_status.sidPlayer->plrUpdateSIDInfo(&xs_status); tmpTuple = tuple_new_from_filename(tmpTune->sidFilename); xs_get_song_tuple_info(tmpTuple, tmpTune, xs_status.currSong); xs_status.stop_flag = FALSE; XS_MUTEX_UNLOCK(xs_status); pb->set_tuple(pb, tmpTuple); pb->set_params (pb, -1, xs_status.audioFrequency, channels); pb->set_pb_ready(pb); XSDEBUG("playing\n"); while (1) { XS_MUTEX_LOCK (xs_status); if (xs_status.stop_flag) { XS_MUTEX_UNLOCK (xs_status); break; } XS_MUTEX_UNLOCK (xs_status); /* Render audio data */ if (xs_status.oversampleEnable) { /* Perform oversampled rendering */ bufRemaining = xs_status.sidPlayer->plrFillBuffer( &xs_status, oversampleBuffer, (audioBufSize * xs_status.oversampleFactor)); bufRemaining /= xs_status.oversampleFactor; /* Execute rate-conversion with filtering */ if (xs_filter_rateconv(audioBuffer, oversampleBuffer, xs_status.audioFormat, xs_status.oversampleFactor, bufRemaining) < 0) { xs_error("Oversampling rate-conversion pass failed.\n"); goto xs_err_exit; } } else { bufRemaining = xs_status.sidPlayer->plrFillBuffer( &xs_status, audioBuffer, audioBufSize); } pb->output->write_audio (audioBuffer, bufRemaining); /* Check if we have played enough */ if (xs_cfg.playMaxTimeEnable) { if (xs_cfg.playMaxTimeUnknown) { if (tmpLength < 0 && pb->output->written_time() >= xs_cfg.playMaxTime * 1000) break; } else { if (pb->output->written_time() >= xs_cfg.playMaxTime * 1000) break; } } if (tmpLength >= 0) { if (pb->output->written_time() >= tmpLength * 1000) break; } } DONE: XSDEBUG("out of playing loop\n"); g_free(audioBuffer); g_free(oversampleBuffer); /* Set playing status to false (stopped), thus when * XMMS next calls xs_get_time(), it can return appropriate * value "not playing" status and XMMS knows to move to * next entry in the playlist .. or whatever it wishes. */ XS_MUTEX_LOCK(xs_status); xs_status.stop_flag = TRUE; /* Free tune information */ xs_status.sidPlayer->plrDeleteSID(&xs_status); xs_tuneinfo_free(xs_status.tuneInfo); xs_status.tuneInfo = NULL; XS_MUTEX_UNLOCK(xs_status); /* Exit the playing thread */ XSDEBUG("exiting thread, bye.\n"); return ! error; xs_err_exit: error = TRUE; goto DONE; }