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;
}
Beispiel #2
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;
}
Beispiel #3
0
/*
 * Return song information Tuple
 */
static void xs_get_song_tuple_info(Tuple *tuple, xs_tuneinfo_t *info, gint subTune)
{
    gchar *tmpStr;

    tmpStr = str_to_utf8(info->sidName);
    tuple_set_str(tuple, FIELD_TITLE, NULL, tmpStr);
    g_free(tmpStr);
    tmpStr = str_to_utf8(info->sidComposer);
    tuple_set_str(tuple, FIELD_ARTIST, NULL, tmpStr);
    g_free(tmpStr);
    tmpStr = str_to_utf8(info->sidCopyright);
    tuple_set_str(tuple, FIELD_COPYRIGHT, NULL, tmpStr);
    g_free(tmpStr);
    tuple_set_str(tuple, FIELD_CODEC, NULL, info->sidFormat);

#if 0
    switch (info->sidModel) {
        case XS_SIDMODEL_6581: tmpStr = "6581"; break;
        case XS_SIDMODEL_8580: tmpStr = "8580"; break;
        case XS_SIDMODEL_ANY: tmpStr = "ANY"; break;
        default: tmpStr = "?"; break;
    }
    tuple_set_str(tuple, -1, "sid-model", tmpStr);
#endif

    /* Get sub-tune information, if available */
    if (subTune < 0 || info->startTune > info->nsubTunes)
        subTune = info->startTune;

    if (subTune > 0 && subTune <= info->nsubTunes) {
        gint tmpInt = info->subTunes[subTune - 1].tuneLength;
        tuple_set_int(tuple, FIELD_LENGTH, NULL, (tmpInt < 0) ? -1 : tmpInt * 1000);

#if 0
        tmpInt = info->subTunes[subTune - 1].tuneSpeed;
        if (tmpInt > 0) {
            switch (tmpInt) {
            case XS_CLOCK_PAL: tmpStr = "PAL"; break;
            case XS_CLOCK_NTSC: tmpStr = "NTSC"; break;
            case XS_CLOCK_ANY: tmpStr = "ANY"; break;
            case XS_CLOCK_VBI: tmpStr = "VBI"; break;
            case XS_CLOCK_CIA: tmpStr = "CIA"; break;
            default:
                g_snprintf(tmpStr2, sizeof(tmpStr2), "%dHz", tmpInt);
                tmpStr = tmpStr2;
                break;
            }
        } else
            tmpStr = "?";

        tuple_set_str(tuple, -1, "sid-speed", tmpStr);
#endif
    } else
        subTune = 1;

    tuple_set_int(tuple, FIELD_SUBSONG_NUM, NULL, info->nsubTunes);
    tuple_set_int(tuple, FIELD_SUBSONG_ID, NULL, subTune);
    tuple_set_int(tuple, FIELD_TRACK_NUMBER, NULL, subTune);
}
Beispiel #4
0
static void set_gain_info(Tuple *tuple, int field, int unit_field, const char *text)
{
    int value, unit;

    parse_gain_text(text, &value, &unit);

    if (tuple_get_value_type(tuple, unit_field, NULL) == TUPLE_INT)
        value = value * (int64_t) tuple_get_int(tuple, unit_field, NULL) / unit;
    else
        tuple_set_int(tuple, unit_field, NULL, unit);

    tuple_set_int(tuple, field, NULL, value);
}
Beispiel #5
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;
}
Beispiel #6
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;
}
Beispiel #7
0
static void set_field_int_from_entry (Tuple * tuple, int fieldn, GtkWidget *
 widget)
{
    const char * text = gtk_entry_get_text ((GtkEntry *) widget);

    if (text[0])
        tuple_set_int (tuple, fieldn, NULL, atoi (text));
    else
        tuple_unset (tuple, fieldn, NULL);
}
Beispiel #8
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;
}
Beispiel #9
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;
}
Beispiel #10
0
static void decode_rva2 (Tuple * tuple, const unsigned char * data, int size)
{
    const char * domain;
    int channel, adjustment, adjustment_unit, peak, peak_unit;

    if (memchr (data, 0, size) == NULL)
        return;

    domain = (const char *) data;

    TAGDBG ("RVA2 domain: %s\n", domain);

    size -= strlen (domain) + 1;
    data += strlen (domain) + 1;

    while (size > 0)
    {
        if (! decode_rva2_block (& data, & size, & channel, & adjustment,
         & adjustment_unit, & peak, & peak_unit))
            break;

        if (channel != 1) /* specific channel? */
            continue;

        if (tuple_get_value_type (tuple, FIELD_GAIN_GAIN_UNIT, NULL) ==
         TUPLE_INT)
            adjustment = adjustment * (int64_t) tuple_get_int (tuple,
             FIELD_GAIN_GAIN_UNIT, NULL) / adjustment_unit;
        else
            tuple_set_int (tuple, FIELD_GAIN_GAIN_UNIT, NULL,
             adjustment_unit);

        if (peak_unit)
        {
            if (tuple_get_value_type (tuple, FIELD_GAIN_PEAK_UNIT, NULL) ==
             TUPLE_INT)
                peak = peak * (int64_t) tuple_get_int (tuple,
                 FIELD_GAIN_PEAK_UNIT, NULL) / peak_unit;
            else
                tuple_set_int (tuple, FIELD_GAIN_PEAK_UNIT, NULL,
                 peak_unit);
        }

        if (! g_ascii_strcasecmp (domain, "album"))
        {
            tuple_set_int (tuple, FIELD_GAIN_ALBUM_GAIN, NULL, adjustment);

            if (peak_unit)
                tuple_set_int (tuple, FIELD_GAIN_ALBUM_PEAK, NULL, peak);
        }
        else if (! g_ascii_strcasecmp (domain, "track"))
        {
            tuple_set_int (tuple, FIELD_GAIN_TRACK_GAIN, NULL, adjustment);

            if (peak_unit)
                tuple_set_int (tuple, FIELD_GAIN_TRACK_PEAK, NULL, peak);
        }
    }
}
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;
}
Beispiel #12
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;
}
Beispiel #13
0
static void parse_comment (Tuple * tuple, const char * key, const char * value)
{
    AUDDBG ("Found key %s <%s>\n", key, value);

    const struct {
        const char * key;
        int field;
    } tfields[] = {
     {"ARTIST", FIELD_ARTIST},
     {"ALBUM", FIELD_ALBUM},
     {"TITLE", FIELD_TITLE},
     {"COMMENT", FIELD_COMMENT},
     {"GENRE", FIELD_GENRE},
     {"musicbrainz_trackid", FIELD_MBID}};

    for (int i = 0; i < ARRAY_LEN (tfields); i ++)
    {
        if (! g_ascii_strcasecmp (key, tfields[i].key))
        {
            add_text (tuple, tfields[i].field, value);
            return;
        }
    }

    if (! g_ascii_strcasecmp (key, "TRACKNUMBER"))
        tuple_set_int(tuple, FIELD_TRACK_NUMBER, atoi(value));
    else if (! g_ascii_strcasecmp (key, "DATE"))
        tuple_set_int(tuple, FIELD_YEAR, atoi(value));
    else if (! g_ascii_strcasecmp (key, "REPLAYGAIN_TRACK_GAIN"))
        set_gain_info(tuple, FIELD_GAIN_TRACK_GAIN, FIELD_GAIN_GAIN_UNIT, value);
    else if (! g_ascii_strcasecmp (key, "REPLAYGAIN_TRACK_PEAK"))
        set_gain_info(tuple, FIELD_GAIN_TRACK_PEAK, FIELD_GAIN_PEAK_UNIT, value);
    else if (! g_ascii_strcasecmp (key, "REPLAYGAIN_ALBUM_GAIN"))
        set_gain_info(tuple, FIELD_GAIN_ALBUM_GAIN, FIELD_GAIN_GAIN_UNIT, value);
    else if (! g_ascii_strcasecmp (key, "REPLAYGAIN_ALBUM_PEAK"))
        set_gain_info(tuple, FIELD_GAIN_ALBUM_PEAK, FIELD_GAIN_PEAK_UNIT, value);
}
Beispiel #14
0
static void associate_int (Tuple * tuple, int field, const char *
 customfield, const unsigned char * data, int size)
{
    char * text = decode_text_frame (data, size);

    if (text == NULL || atoi (text) < 1)
    {
        g_free (text);
        return;
    }

    if (customfield != NULL)
        TAGDBG ("Custom field %s = %s.\n", customfield, text);
    else
        TAGDBG ("Field %i = %s.\n", field, text);

    tuple_set_int (tuple, field, customfield, atoi (text));
    g_free (text);
}
static void read_metadata_dict (Tuple * tuple, AVDictionary * dict)
{
    for (int i = 0; i < ARRAY_LEN (metaentries); i ++)
    {
        const ffaudio_meta_t * m = & metaentries[i];
        AVDictionaryEntry * entry = NULL;

        for (int j = 0; ! entry && m->keys[j]; j ++)
            entry = av_dict_get (dict, m->keys[j], NULL, 0);

        if (entry && entry->value)
        {
            if (m->ttype == TUPLE_STRING)
                tuple_set_str (tuple, m->field, entry->value);
            else if (m->ttype == TUPLE_INT)
                tuple_set_int (tuple, m->field, atoi (entry->value));
        }
    }
}
Beispiel #16
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;
}
Beispiel #17
0
static void xspf_add_file (xmlNode * track, const gchar * filename, const gchar
 * base, Index * filenames, Index * tuples)
{
    xmlNode *nptr;
    gchar *location = NULL;
    Tuple * tuple = NULL;

    for (nptr = track->children; nptr != NULL; nptr = nptr->next) {
        if (nptr->type == XML_ELEMENT_NODE) {
            if (!xmlStrcmp(nptr->name, (xmlChar *)"location")) {
                /* Location is a special case */
                gchar *str = (gchar *)xmlNodeGetContent(nptr);

                if (strstr (str, "://") != NULL)
                    location = str_get (str);
                else if (str[0] == '/' && base != NULL)
                {
                    const gchar * colon = strstr (base, "://");

                    if (colon != NULL)
                        location = str_printf ("%.*s%s", (gint) (colon + 3 -
                         base), base, str);
                }
                else if (base != NULL)
                {
                    const gchar * slash = strrchr (base, '/');

                    if (slash != NULL)
                        location = str_printf ("%.*s%s", (gint) (slash + 1 -
                         base), base, str);
                }

                xmlFree(str);
            } else {
                /* Rest of the nodes are handled here */
                gint i;
                gboolean isMeta;
                xmlChar *findName;

                if (!xmlStrcmp(nptr->name, (xmlChar *)"meta")) {
                    isMeta = TRUE;
                    findName = xmlGetProp(nptr, (xmlChar *)"rel");
                } else {
                    isMeta = FALSE;
                    findName = xmlStrdup(nptr->name);
                }

                for (i = 0; i < xspf_nentries; i++)
                if ((xspf_entries[i].isMeta == isMeta) &&
                    !xmlStrcmp(findName, (xmlChar *)xspf_entries[i].xspfName)) {
                    xmlChar *str = xmlNodeGetContent(nptr);
                    switch (xspf_entries[i].type) {
                        case TUPLE_STRING:
                            if (! tuple)
                                tuple = tuple_new ();
                            tuple_set_str(tuple, xspf_entries[i].tupleField, NULL, (gchar *)str);
                            break;

                        case TUPLE_INT:
                            if (! tuple)
                                tuple = tuple_new ();
                            tuple_set_int(tuple, xspf_entries[i].tupleField, NULL, atol((char *)str));
                            break;

                        default:
                            break;
                    }
                    xmlFree(str);
                    break;
                }

                xmlFree(findName);
            }
        }
    }

    if (location != NULL)
    {
        if (tuple)
            tuple_set_filename (tuple, location);

        index_append(filenames, location);
        index_append(tuples, tuple);
    }
    else if (tuple)
        tuple_unref (tuple);
}
Beispiel #18
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;
}
Beispiel #19
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;
}