Пример #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;
}
Пример #2
0
static Tuple *
wv_probe_for_tuple(const char * filename, VFSFile * fd)
{
    WavpackContext *ctx;
    Tuple *tu;
    char error[1024];

    ctx = WavpackOpenFileInputEx(&wv_readers, fd, NULL, error, OPEN_TAGS, 0);

    if (ctx == NULL)
        return NULL;

    AUDDBG("starting probe of %p\n", (void *) fd);

    vfs_rewind(fd);
    tu = tuple_new_from_filename(filename);

    vfs_rewind(fd);
    tag_tuple_read(tu, fd);

    tuple_set_int(tu, FIELD_LENGTH, NULL,
        ((uint64_t) WavpackGetNumSamples(ctx) * 1000) / (uint64_t) WavpackGetSampleRate(ctx));
    tuple_set_str(tu, FIELD_CODEC, NULL, "WavPack");

    char * quality = wv_get_quality (ctx);
    tuple_set_str (tu, FIELD_QUALITY, NULL, quality);
    str_unref (quality);

    WavpackCloseFile(ctx);

    AUDDBG("returning tuple %p for file %p\n", (void *) tu, (void *) fd);
    return tu;
}
Пример #3
0
static Tuple * read_tuple (const gchar * filename, VFSFile * file)
{
    Tuple * tuple = NULL;
    AVFormatContext * ic = open_input_file (filename, file);

    if (ic)
    {
        CodecInfo cinfo;

        if (find_codec (ic, & cinfo))
        {
            tuple = tuple_new_from_filename (filename);

            tuple_set_int (tuple, FIELD_LENGTH, ic->duration / 1000);
            tuple_set_int (tuple, FIELD_BITRATE, ic->bit_rate / 1000);

            if (cinfo.codec->long_name)
                tuple_set_str (tuple, FIELD_CODEC, cinfo.codec->long_name);

            if (ic->metadata)
                read_metadata_dict (tuple, ic->metadata);
            if (cinfo.stream->metadata)
                read_metadata_dict (tuple, cinfo.stream->metadata);
        }

        close_input_file (ic);
    }

    return tuple;
}
Пример #4
0
Tuple *psf2_tuple(const char *filename, VFSFile *file)
{
	Tuple *t;
	corlett_t *c;
	void *buf;
	int64_t sz;

	vfs_file_get_contents (filename, & buf, & sz);

	if (!buf)
		return NULL;

	if (corlett_decode(buf, sz, NULL, NULL, &c) != AO_SUCCESS)
		return NULL;

	t = tuple_new_from_filename(filename);

	tuple_set_int(t, FIELD_LENGTH, NULL, c->inf_length ? psfTimeToMS(c->inf_length) + psfTimeToMS(c->inf_fade) : -1);
	tuple_set_str(t, FIELD_ARTIST, NULL, c->inf_artist);
	tuple_set_str(t, FIELD_ALBUM, NULL, c->inf_game);
	tuple_set_str(t, -1, "game", c->inf_game);
	tuple_set_str(t, FIELD_TITLE, NULL, c->inf_title);
	tuple_set_str(t, FIELD_COPYRIGHT, NULL, c->inf_copy);
	tuple_set_str(t, FIELD_QUALITY, NULL, _("sequenced"));
	tuple_set_str(t, FIELD_CODEC, NULL, "PlayStation 1/2 Audio");
	tuple_set_str(t, -1, "console", "PlayStation 1/2");

	free(c);
	free(buf);

	return t;
}
Пример #5
0
static Tuple *probe_for_tuple(const char *filename, VFSFile *file)
{
	int song = -1;
	unsigned char module[ASAPInfo_MAX_MODULE_LENGTH];
	int module_len;
	ASAPInfo *info = NULL;
	Tuple *tuple = NULL;
	int songs;
	int duration;
	int year;

#if _AUD_PLUGIN_VERSION >= 10
	char *real_filename = filename_split_subtune(filename, &song);
	if (real_filename != NULL)
		filename = real_filename;
#endif
	module_len = load_module(filename, file, module);
	if (module_len > 0) {
		info = ASAPInfo_New();
		if (info != NULL && ASAPInfo_Load(info, filename, module, module_len))
			tuple = tuple_new_from_filename(filename);
	}
#if _AUD_PLUGIN_VERSION >= 10
	g_free(real_filename);
#endif
	if (tuple == NULL) {
		ASAPInfo_Delete(info);
		return NULL;
	}

	tuple_set_nonblank(tuple, FIELD_ARTIST, ASAPInfo_GetAuthor(info));
	tuple_set_nonblank(tuple, FIELD_TITLE, ASAPInfo_GetTitleOrFilename(info));
	tuple_set_nonblank(tuple, FIELD_DATE, ASAPInfo_GetDate(info));
	tuple_set_str(tuple, FIELD_CODEC, NULL, "ASAP");
	songs = ASAPInfo_GetSongs(info);
	if (song > 0) {
		tuple_set_int(tuple, FIELD_SUBSONG_ID, NULL, song);
		tuple_set_int(tuple, FIELD_SUBSONG_NUM, NULL, songs);
		song--;
	}
	else {
		if (songs > 1) {
#if _AUD_PLUGIN_VERSION >= 37
			tuple_set_subtunes(tuple, songs, NULL);
#else
			tuple->nsubtunes = songs;
#endif
		}
		song = ASAPInfo_GetDefaultSong(info);
	}
	duration = ASAPInfo_GetDuration(info, song);
	if (duration > 0)
		tuple_set_int(tuple, FIELD_LENGTH, NULL, duration);
	year = ASAPInfo_GetYear(info);
	if (year > 0)
		tuple_set_int(tuple, FIELD_YEAR, NULL, year);
	ASAPInfo_Delete(info);
	return tuple;
}
Пример #6
0
static bool_t audpl_load (const char * path, VFSFile * file, char * * title,
 Index * filenames, Index * tuples)
{
    ReadState * state = malloc (sizeof (ReadState));
    state->file = file;
    state->cur = state->buf;
    state->len = 0;

    char * key, * val;

    if (! read_key (state, & key, & val) || strcmp (key, "title"))
    {
        free (state);
        return FALSE;
    }

    * title = str_get (val);

    bool_t readed = read_key (state, & key, & val);

    while (readed && ! strcmp (key, "uri"))
    {
        char * uri = str_get (val);
        Tuple * tuple = NULL;

        while ((readed = read_key (state, & key, & val)) && strcmp (key, "uri"))
        {
            if (! tuple)
                tuple = tuple_new_from_filename (uri);

            if (! strcmp (key, "empty"))
                continue;

            int field = tuple_field_by_name (key);
            TupleValueType type = tuple_field_get_type (field);

            if (field < 0)
                break;

            if (type == TUPLE_STRING)
                tuple_set_str (tuple, field, NULL, val);
            else if (type == TUPLE_INT)
                tuple_set_int (tuple, field, NULL, atoi (val));
        }

        index_append (filenames, uri);
        index_append (tuples, tuple);
    }

    free (state);
    return TRUE;
}
Пример #7
0
static Tuple *metronom_probe_for_tuple(const char * filename, VFSFile *fd)
{
    Tuple *tuple = tuple_new_from_filename(filename);
    metronom_t metronom;
    char *tmp = NULL;

    if (metronom_get_cp(filename, &metronom, &tmp))
        tuple_set_str(tuple, FIELD_TITLE, tmp);

    str_unref(tmp);

    return tuple;
}
Tuple *gsf_get_song_tuple(const gchar *filename, VFSFile *file)
{
  char tag[50001];
  char tmp_str[256];
  const gchar *fn;

  Tuple *ti;

  fn = g_filename_from_uri(filename, NULL, NULL);

  ti = tuple_new_from_filename(fn);

  psftag_readfromfile((void*)tag, fn);

  if (!psftag_getvar(tag, "title", tmp_str, sizeof(tmp_str)-1)) {
      tuple_set_str(ti, FIELD_TITLE, NULL, tmp_str);
  }

  if (!psftag_getvar(tag, "artist", tmp_str, sizeof(tmp_str)-1)) {
      tuple_set_str(ti, FIELD_ARTIST, NULL, tmp_str);
  }

  if (!psftag_getvar(tag, "game", tmp_str, sizeof(tmp_str)-1)) {
      tuple_set_str(ti, FIELD_ALBUM, NULL, tmp_str);
  }

  if (!psftag_getvar(tag, "year", tmp_str, sizeof(tmp_str)-1)) {
      tuple_set_str(ti, FIELD_DATE, NULL, tmp_str);
  }

  if (!psftag_getvar(tag, "copyright", tmp_str, sizeof(tmp_str)-1)) {
      tuple_set_str(ti, FIELD_COPYRIGHT, NULL, tmp_str);
  }

  if (!psftag_getvar(tag, "tagger", tmp_str, sizeof(tmp_str)-1)) {
      tuple_set_str(ti, -1, "tagger", tmp_str);
  }

  if (!psftag_raw_getvar(tag, "length", tmp_str, sizeof(tmp_str)-1)) {
      tuple_set_int(ti, FIELD_LENGTH, NULL, LengthFromString(tmp_str) + FadeLength);
  }

  if (!psftag_getvar(tag, "comment", tmp_str, sizeof(tmp_str)-1)) {
      tuple_set_str(ti, FIELD_COMMENT, NULL, tmp_str);
  }

  tuple_set_str(ti, FIELD_CODEC, NULL, "GameBoy Advanced Audio (GSF)");
  tuple_set_str(ti, FIELD_QUALITY, NULL, "sequenced");

  return ti;
}
Пример #9
0
static Tuple *tone_probe_for_tuple(const gchar *filename, VFSFile *fd)
{
    Tuple *tuple = tuple_new_from_filename(filename);
    gchar *tmp;

    if (tuple == NULL)
        return NULL;

    if ((tmp = tone_title(filename)) != NULL)
    {
        tuple_set_str(tuple, FIELD_TITLE, NULL, tmp);
        g_free(tmp);
    }

    return tuple;
}
Пример #10
0
Tuple *vtx_get_song_tuple_from_vtx(const gchar * filename, ayemu_vtx_t * in)
{
    Tuple *out = tuple_new_from_filename(filename);

    tuple_set_str(out, FIELD_ARTIST, in->hdr.author);
    tuple_set_str(out, FIELD_TITLE, in->hdr.title);

    tuple_set_int(out, FIELD_LENGTH, in->hdr.regdata_size / 14 * 1000 / 50);

    tuple_set_str(out, FIELD_GENRE, (in->hdr.chiptype == AYEMU_AY) ? "AY chiptunes" : "YM chiptunes");
    tuple_set_str(out, FIELD_ALBUM, in->hdr.from);

    tuple_set_str(out, FIELD_QUALITY, _("sequenced"));
    tuple_set_str(out, FIELD_CODEC, in->hdr.tracker);

    tuple_set_int(out, FIELD_YEAR, in->hdr.year);

    return out;
}
Пример #11
0
static Tuple *
get_tuple_for_vorbisfile(OggVorbis_File * vorbisfile, const gchar *filename)
{
    Tuple *tuple;
    gint length;
    vorbis_comment *comment = NULL;

    tuple = tuple_new_from_filename(filename);

    length = vfs_is_streaming (vorbisfile->datasource) ? -1 : ov_time_total
     (vorbisfile, -1) * 1000;

    /* associate with tuple */
    tuple_set_int(tuple, FIELD_LENGTH, length);

    if ((comment = ov_comment(vorbisfile, -1)) != NULL) {
        gchar *tmps;
        set_tuple_str(tuple, FIELD_TITLE, comment, "title");
        set_tuple_str(tuple, FIELD_ARTIST, comment, "artist");
        set_tuple_str(tuple, FIELD_ALBUM, comment, "album");
        set_tuple_str(tuple, FIELD_GENRE, comment, "genre");
        set_tuple_str(tuple, FIELD_COMMENT, comment, "comment");

        if ((tmps = vorbis_comment_query(comment, "tracknumber", 0)) != NULL)
            tuple_set_int(tuple, FIELD_TRACK_NUMBER, atoi(tmps));

        if ((tmps = vorbis_comment_query (comment, "date", 0)) != NULL)
            tuple_set_int (tuple, FIELD_YEAR, atoi (tmps));
    }

    vorbis_info * info = ov_info (vorbisfile, -1);
    tuple_set_format (tuple, "Ogg Vorbis", info->channels, info->rate,
     info->bitrate_nominal / 1000);

    tuple_set_str(tuple, FIELD_MIMETYPE, "application/ogg");

    return tuple;
}
Пример #12
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;
}
Пример #13
0
static void infowin_update_tuple (void * unused)
{
    Tuple * tuple = tuple_new_from_filename (current_file);

    set_field_str_from_entry (tuple, FIELD_TITLE, entry_title);
    set_field_str_from_entry (tuple, FIELD_ARTIST, entry_artist);
    set_field_str_from_entry (tuple, FIELD_ALBUM, entry_album);
    set_field_str_from_entry (tuple, FIELD_COMMENT, entry_comment);
    set_field_str_from_entry (tuple, FIELD_GENRE, gtk_bin_get_child ((GtkBin *)
     entry_genre));
    set_field_int_from_entry (tuple, FIELD_YEAR, entry_year);
    set_field_int_from_entry (tuple, FIELD_TRACK_NUMBER, entry_track);

    if (aud_file_write_tuple (current_file, current_decoder, tuple))
    {
        ministatus_display_message (_("Metadata updated successfully"));
        something_changed = FALSE;
        gtk_widget_set_sensitive (btn_apply, FALSE);
    }
    else
        ministatus_display_message (_("Metadata updating failed"));

    tuple_unref (tuple);
}
Пример #14
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;
}
Пример #15
0
Tuple *flac_probe_for_tuple(const char *filename, VFSFile *fd)
{
    AUDDBG("Probe for tuple.\n");

    Tuple *tuple = NULL;
    FLAC__Metadata_Iterator *iter;
    FLAC__Metadata_Chain *chain;
    FLAC__StreamMetadata *metadata = NULL;
    FLAC__Metadata_ChainStatus status;
    FLAC__StreamMetadata_VorbisComment_Entry *entry;
    char *key;
    char *value;

    tuple = tuple_new_from_filename(filename);

    tuple_set_str(tuple, FIELD_CODEC, NULL, "Free Lossless Audio Codec (FLAC)");
    tuple_set_str(tuple, FIELD_QUALITY, NULL, _("lossless"));

    chain = FLAC__metadata_chain_new();

    if (!FLAC__metadata_chain_read_with_callbacks(chain, fd, io_callbacks))
        goto ERR;

    iter = FLAC__metadata_iterator_new();

    FLAC__metadata_iterator_init(iter, chain);

    do
    {
        switch (FLAC__metadata_iterator_get_block_type(iter))
        {
            case FLAC__METADATA_TYPE_VORBIS_COMMENT:

                if (FLAC__metadata_iterator_get_block_type(iter) == FLAC__METADATA_TYPE_VORBIS_COMMENT)
                {
                    metadata = FLAC__metadata_iterator_get_block(iter);

                    AUDDBG("Vorbis comment contains %d fields\n", metadata->data.vorbis_comment.num_comments);
                    AUDDBG("Vendor string: %s\n", metadata->data.vorbis_comment.vendor_string.entry);

                    entry = metadata->data.vorbis_comment.comments;

                    for (int i = 0; i < metadata->data.vorbis_comment.num_comments; i++, entry++)
                    {
                        if (FLAC__metadata_object_vorbiscomment_entry_to_name_value_pair(*entry, &key, &value) == false)
                            AUDDBG("Could not parse comment\n");
                        else
                        {
                            parse_comment(tuple, key, value);
                            free(key);
                            free(value);
                        }
                    }
                }
                break;

            case FLAC__METADATA_TYPE_STREAMINFO:
                metadata = FLAC__metadata_iterator_get_block(iter);

                /* Calculate the stream length (milliseconds) */
                if (metadata->data.stream_info.sample_rate == 0)
                {
                    FLACNG_ERROR("Invalid sample rate for stream!\n");
                    tuple_set_int(tuple, FIELD_LENGTH, NULL, -1);
                }
                else
                {
                    tuple_set_int(tuple, FIELD_LENGTH, NULL,
                        (metadata->data.stream_info.total_samples / metadata->data.stream_info.sample_rate) * 1000);
                    AUDDBG("Stream length: %d seconds\n", tuple_get_int(tuple, FIELD_LENGTH, NULL));
                }

                int64_t size = vfs_fsize(fd);

                if (size == -1 || metadata->data.stream_info.total_samples == 0)
                    tuple_set_int(tuple, FIELD_BITRATE, NULL, 0);
                else
                {
                    int bitrate = 8 * size *
                        (int64_t) metadata->data.stream_info.sample_rate / metadata->data.stream_info.total_samples;

                    tuple_set_int(tuple, FIELD_BITRATE, NULL, (bitrate + 500) / 1000);
                }
                break;

            default:
                ;
        }
    } while (FLAC__metadata_iterator_next(iter));

    FLAC__metadata_iterator_delete(iter);
    FLAC__metadata_chain_delete(chain);

    return tuple;

ERR:
    status = FLAC__metadata_chain_status(chain);
    FLAC__metadata_chain_delete(chain);

    FLACNG_ERROR("An error occured: %s\n", FLAC__Metadata_ChainStatusString[status]);
    return tuple;
}
Пример #16
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;
}
Пример #17
0
static bool_t playlist_load_cue (const char * cue_filename, VFSFile * file,
 char * * title, Index * filenames, Index * tuples)
{
    void * buffer = NULL;
    vfs_file_read_all (file, & buffer, NULL);
    if (! buffer)
        return FALSE;

    * title = NULL;

    Cd * cd = cue_parse_string (buffer);
    g_free (buffer);
    if (cd == NULL)
        return FALSE;

    int tracks = cd_get_ntrack (cd);
    if (tracks == 0)
        return FALSE;

    Track * current = cd_get_track (cd, 1);
    if (current == NULL)
        return FALSE;

    char * track_filename = track_get_filename (current);
    if (track_filename == NULL)
        return FALSE;

    char * filename = uri_construct (track_filename, cue_filename);

    Tuple * base_tuple = NULL;
    bool_t base_tuple_scanned = FALSE;

    for (int track = 1; track <= tracks; track ++)
    {
        if (current == NULL || filename == NULL)
            return FALSE;

        if (base_tuple == NULL && ! base_tuple_scanned)
        {
            base_tuple_scanned = TRUE;
            PluginHandle * decoder = aud_file_find_decoder (filename, FALSE);
            if (decoder != NULL)
                base_tuple = aud_file_read_tuple (filename, decoder);
        }

        Track * next = (track + 1 <= tracks) ? cd_get_track (cd, track + 1) : NULL;
        char * next_filename = (next != NULL) ? uri_construct
         (track_get_filename (next), cue_filename) : NULL;
        bool_t last_track = (next_filename == NULL || strcmp (next_filename, filename));

        Tuple * tuple = (base_tuple != NULL) ? tuple_copy (base_tuple) :
         tuple_new_from_filename (filename);
        tuple_set_int (tuple, FIELD_TRACK_NUMBER, track);

        int begin = (int64_t) track_get_start (current) * 1000 / 75;
        tuple_set_int (tuple, FIELD_SEGMENT_START, begin);

        if (last_track)
        {
            if (base_tuple != NULL && tuple_get_value_type (base_tuple,
             FIELD_LENGTH) == TUPLE_INT)
                tuple_set_int (tuple, FIELD_LENGTH, tuple_get_int
                 (base_tuple, FIELD_LENGTH) - begin);
        }
        else
        {
            int length = (int64_t) track_get_length (current) * 1000 / 75;
            tuple_set_int (tuple, FIELD_LENGTH, length);
            tuple_set_int (tuple, FIELD_SEGMENT_END, begin + length);
        }

        for (int i = 0; i < ARRAY_LEN (pti_map); i ++)
            tuple_attach_cdtext (tuple, current, pti_map[i].tuple_type, pti_map[i].pti);

        index_insert (filenames, -1, str_get (filename));
        index_insert (tuples, -1, tuple);

        current = next;
        str_unref (filename);
        filename = next_filename;

        if (last_track && base_tuple != NULL)
        {
            tuple_unref (base_tuple);
            base_tuple = NULL;
            base_tuple_scanned = FALSE;
        }
    }

    return TRUE;
}
Пример #18
0
/* thread safe */
static Tuple * make_tuple (const gchar * filename, VFSFile * file)
{
    Tuple *tuple = NULL;
    gint trackno;

    g_mutex_lock (mutex);

    if (trackinfo == NULL)
        refresh_trackinfo (TRUE);
    if (trackinfo == NULL)
        goto DONE;

    if (!strcmp (filename, "cdda://"))
    {
        tuple = tuple_new_from_filename (filename);

        gint subtunes[n_audio_tracks];
        gint i = 0;

        /* only add the audio tracks to the playlist */
        for (trackno = firsttrackno; trackno <= lasttrackno; trackno++)
            if (cdda_track_audiop (pcdrom_drive, trackno))
                subtunes[i ++] = trackno;

        tuple_set_subtunes (tuple, n_audio_tracks, subtunes);

        goto DONE;
    }

    trackno = find_trackno_from_filename (filename);

    if (trackno < firsttrackno || trackno > lasttrackno)
    {
        warn ("Track %d not found.\n", trackno);
        goto DONE;
    }

    if (!cdda_track_audiop (pcdrom_drive, trackno))
    {
        warn ("Track %d is a data track.\n", trackno);
        goto DONE;
    }

    tuple = tuple_new_from_filename (filename);
    tuple_set_format (tuple, _("Audio CD"), 2, 44100, 1411);

    if (strlen (trackinfo[trackno].performer))
    {
        tuple_set_str (tuple, FIELD_ARTIST, NULL,
                                    trackinfo[trackno].performer);
    }
    if (strlen (trackinfo[0].name))
    {
        tuple_set_str (tuple, FIELD_ALBUM, NULL,
                                    trackinfo[0].name);
    }
    if (strlen (trackinfo[trackno].name))
    {
        tuple_set_str (tuple, FIELD_TITLE, NULL,
                                    trackinfo[trackno].name);
    }

    tuple_set_int (tuple, FIELD_TRACK_NUMBER, NULL, trackno);

    tuple_set_int (tuple, FIELD_LENGTH, NULL,
                             calculate_track_length (trackinfo[trackno].
                                                     startlsn,
                                                     trackinfo[trackno].
                                                     endlsn));

    if (strlen (trackinfo[trackno].genre))
    {
        tuple_set_str (tuple, FIELD_GENRE, NULL,
                                    trackinfo[trackno].genre);
    }

  DONE:
    g_mutex_unlock (mutex);
    return tuple;
}