Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
/*
 * 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;
}
Exemplo n.º 4
0
/*
 * 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;
}