Tuple * xs_probe_for_tuple(const char *filename, VFSFile *fd) { Tuple *tuple; xs_tuneinfo_t *info; int tune = -1; pthread_mutex_lock(&xs_status_mutex); if (!xs_sidplayfp_probe(fd)) { pthread_mutex_unlock(&xs_status_mutex); return NULL; } pthread_mutex_unlock(&xs_status_mutex); /* Get information from URL */ tuple = tuple_new_from_filename (filename); tune = tuple_get_int (tuple, FIELD_SUBSONG_NUM); /* Get tune information from emulation engine */ pthread_mutex_lock(&xs_status_mutex); info = xs_sidplayfp_getinfo (filename); pthread_mutex_unlock(&xs_status_mutex); 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; }
/* * Shut down XMMS-SID */ void xs_close(void) { xs_tuneinfo_free(xs_status.tuneInfo); xs_status.tuneInfo = NULL; xs_sidplayfp_delete (& xs_status); xs_sidplayfp_close (& xs_status); xs_songlen_close(); xs_stil_close(); }
/* * Shut down XMMS-SID */ void xs_close(void) { XSDEBUG("xs_close(): shutting down...\n"); xs_tuneinfo_free(xs_status.tuneInfo); xs_status.tuneInfo = NULL; if (xs_status.sidPlayer) { xs_status.sidPlayer->plrDeleteSID (& xs_status); xs_status.sidPlayer->plrClose (& xs_status); } xs_songlen_close(); xs_stil_close(); XSDEBUG("shutdown finished.\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; }
/* * Start playing the given file */ bool_t xs_play_file(const char *filename, VFSFile *file) { xs_tuneinfo_t *tmpTune; int audioBufSize, bufRemaining, tmpLength, subTune = -1; char *audioBuffer = NULL, *oversampleBuffer = NULL; Tuple *tmpTuple; uri_parse (filename, NULL, NULL, NULL, & subTune); /* Get tune information */ pthread_mutex_lock(&xs_status_mutex); if (! (xs_status.tuneInfo = xs_sidplayfp_getinfo (filename))) { pthread_mutex_unlock(&xs_status_mutex); return FALSE; } /* Initialize the tune */ if (! xs_sidplayfp_load (& xs_status, filename)) { pthread_mutex_unlock(&xs_status_mutex); xs_tuneinfo_free(xs_status.tuneInfo); xs_status.tuneInfo = NULL; return FALSE; } bool_t 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; int channels = xs_status.audioChannels; /* Allocate audio buffer */ audioBufSize = xs_status.audioFrequency * channels * FMT_SIZEOF (FMT_S16_NE); if (audioBufSize < 512) audioBufSize = 512; audioBuffer = (char *) malloc(audioBufSize); if (audioBuffer == NULL) { xs_error("Couldn't allocate memory for audio data buffer!\n"); pthread_mutex_unlock(&xs_status_mutex); 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_sidplayfp_initsong(&xs_status)) { xs_error("Couldn't initialize SID-tune '%s' (sub-tune #%i)!\n", tmpTune->sidFilename, xs_status.currSong); pthread_mutex_unlock(&xs_status_mutex); goto xs_err_exit; } /* Open the audio output */ if (!aud_input_open_audio(FMT_S16_NE, xs_status.audioFrequency, channels)) { xs_error("Couldn't open audio output (fmt=%x, freq=%i, nchan=%i)!\n", FMT_S16_NE, xs_status.audioFrequency, channels); pthread_mutex_unlock(&xs_status_mutex); goto xs_err_exit; } /* Set song information for current subtune */ xs_sidplayfp_updateinfo(&xs_status); tmpTuple = tuple_new_from_filename(tmpTune->sidFilename); xs_get_song_tuple_info(tmpTuple, tmpTune, xs_status.currSong); pthread_mutex_unlock(&xs_status_mutex); aud_input_set_tuple(tmpTuple); while (! aud_input_check_stop ()) { bufRemaining = xs_sidplayfp_fillbuffer(&xs_status, audioBuffer, audioBufSize); aud_input_write_audio (audioBuffer, bufRemaining); /* Check if we have played enough */ if (xs_cfg.playMaxTimeEnable) { if (xs_cfg.playMaxTimeUnknown) { if (tmpLength < 0 && aud_input_written_time() >= xs_cfg.playMaxTime * 1000) break; } else { if (aud_input_written_time() >= xs_cfg.playMaxTime * 1000) break; } } if (tmpLength >= 0) { if (aud_input_written_time() >= tmpLength * 1000) break; } } DONE: free(audioBuffer); 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. */ pthread_mutex_lock(&xs_status_mutex); /* Free tune information */ xs_sidplayfp_delete(&xs_status); xs_tuneinfo_free(xs_status.tuneInfo); xs_status.tuneInfo = NULL; pthread_mutex_unlock(&xs_status_mutex); /* Exit the playing thread */ return ! error; xs_err_exit: error = TRUE; goto DONE; }
/* * 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; }