示例#1
0
/**
 * Import a "Comment frame" (ID3v2.4.0 section 4.10).  It
 * contains 4 fields:
 *
 * - encoding
 * - language
 * - string
 * - full string (we use this one)
 */
static void
tag_id3_import_comment(struct tag *dest, struct id3_tag *tag, const char *id,
		       enum tag_type type)
{
	struct id3_frame const *frame;
	id3_ucs4_t const *ucs4;
	id3_utf8_t *utf8;
	union id3_field const *field;

	frame = id3_tag_findframe(tag, id, 0);
	if (frame == NULL || frame->nfields != 4)
		return;

	/* for now I only read the 4th field, with the fullstring */
	field = id3_frame_field(frame, 3);
	if (field == NULL)
		return;

	ucs4 = id3_field_getfullstring(field);
	if (ucs4 == NULL)
		return;

	utf8 = import_id3_string(tag_is_id3v1(tag), ucs4);
	if (utf8 == NULL)
		return;

	tag_add_item(dest, type, (char *)utf8);
	g_free(utf8);
}
示例#2
0
/**
 * Import all known MusicBrainz tags from TXXX frames.
 */
static void
tag_id3_import_musicbrainz(struct tag *mpd_tag, struct id3_tag *id3_tag)
{
	for (unsigned i = 0;; ++i) {
		const struct id3_frame *frame;
		id3_utf8_t *name, *value;
		enum tag_type type;

		frame = id3_tag_findframe(id3_tag, "TXXX", i);
		if (frame == NULL)
			break;

		name = tag_id3_getstring(frame, 1);
		if (name == NULL)
			continue;

		type = tag_id3_parse_txxx_name((const char*)name);
		free(name);

		if (type == TAG_NUM_OF_ITEM_TYPES)
			continue;

		value = tag_id3_getstring(frame, 2);
		if (value == NULL)
			continue;

		tag_add_item(mpd_tag, type, (const char*)value);
		free(value);
	}
}
static struct tag *
modplug_stream_tag(struct input_stream *is)
{
	ModPlugFile *f;
	struct tag *ret = NULL;
	GByteArray *bdatas;
	char *title;

	bdatas = mod_loadfile(NULL, is);
	if (!bdatas)
		return NULL;

	f = ModPlug_Load(bdatas->data, bdatas->len);
	g_byte_array_free(bdatas, TRUE);
	if (f == NULL)
		return NULL;

	ret = tag_new();
	ret->time = ModPlug_GetLength(f) / 1000;

	title = g_strdup(ModPlug_GetName(f));
	if (title)
		tag_add_item(ret, TAG_TITLE, title);
	g_free(title);

	ModPlug_Unload(f);

	return ret;
}
示例#4
0
static int handle_end_map(void *ctx)
{
	struct parse_data *data = (struct parse_data *) ctx;

	if (data->got_url > 1) {
		data->got_url--;
		return 1;
	}

	if (data->got_url == 0)
		return 1;

	/* got_url == 1, track finished, make it into a song */
	data->got_url = 0;

	struct song *s;
	struct tag *t;
	char *u;

	u = g_strconcat(data->stream_url, "?client_id=", soundcloud_config.apikey, NULL);
	s = song_remote_new(u);
	g_free(u);
	t = tag_new();
	t->time = data->duration / 1000;
	if (data->title != NULL)
		tag_add_item(t, TAG_NAME, data->title);
	s->tag = t;

	data->songs = g_slist_prepend(data->songs, s);

	return 1;
}
static struct tag *
sndfile_tag_dup(const char *path_fs)
{
	SNDFILE *sf;
	SF_INFO info;
	struct tag *tag;
	const char *p;

	info.format = 0;

	sf = sf_open(path_fs, SFM_READ, &info);
	if (sf == NULL)
		return NULL;

	if (!audio_valid_sample_rate(info.samplerate)) {
		sf_close(sf);
		g_warning("Invalid sample rate in %s\n", path_fs);
		return NULL;
	}

	tag = tag_new();
	tag->time = info.frames / info.samplerate;

	p = sf_get_string(sf, SF_STR_TITLE);
	if (p != NULL)
		tag_add_item(tag, TAG_TITLE, p);

	p = sf_get_string(sf, SF_STR_ARTIST);
	if (p != NULL)
		tag_add_item(tag, TAG_ARTIST, p);

	p = sf_get_string(sf, SF_STR_DATE);
	if (p != NULL)
		tag_add_item(tag, TAG_DATE, p);

	sf_close(sf);

	return tag;
}
示例#6
0
/*
 * Reads metainfo from the specified file.
 */
static struct tag *
wavpack_tagdup(const char *fname)
{
	WavpackContext *wpc;
	struct tag *tag;
	char error[ERRORLEN];
	char *s;
	int size, allocated_size;

	wpc = WavpackOpenFileInput(fname, error, OPEN_TAGS, 0);
	if (wpc == NULL) {
		g_warning(
			"failed to open WavPack file \"%s\": %s\n",
			fname, error
		);
		return NULL;
	}

	tag = tag_new();
	tag->time = WavpackGetNumSamples(wpc);
	tag->time /= WavpackGetSampleRate(wpc);

	allocated_size = 0;
	s = NULL;

	for (unsigned i = 0; i < G_N_ELEMENTS(tagtypes); ++i) {
		size = WavpackGetTagItem(wpc, tagtypes[i].name, NULL, 0);
		if (size > 0) {
			++size; /* EOS */

			if (s == NULL) {
				s = g_malloc(size);
				allocated_size = size;
			} else if (size > allocated_size) {
				char *t = (char *)g_realloc(s, size);
				allocated_size = size;
				s = t;
			}

			WavpackGetTagItem(wpc, tagtypes[i].name, s, size);
			tag_add_item(tag, tagtypes[i].type, s);
		}
	}

	g_free(s);

	WavpackCloseFile(wpc);

	return tag;
}
示例#7
0
static void
copy_icy_tag(struct input_curl *c)
{
	struct tag *tag = icy_tag(&c->icy_metadata);

	if (tag == NULL)
		return;

	if (c->tag != NULL)
		tag_free(c->tag);

	if (c->meta_name != NULL && !tag_has_type(tag, TAG_NAME))
		tag_add_item(tag, TAG_NAME, c->meta_name);

	c->tag = tag;
}
示例#8
0
/**
 * Import a "Text information frame" (ID3v2.4.0 section 4.2).  It
 * contains 2 fields:
 *
 * - encoding
 * - string list
 */
static void
tag_id3_import_text(struct tag *dest, struct id3_tag *tag, const char *id,
		    enum tag_type type)
{
	struct id3_frame const *frame;
	id3_ucs4_t const *ucs4;
	id3_utf8_t *utf8;
	union id3_field const *field;
	unsigned int nstrings, i;

	frame = id3_tag_findframe(tag, id, 0);
	if (frame == NULL || frame->nfields != 2)
		return;

	/* check the encoding field */

	field = id3_frame_field(frame, 0);
	if (field == NULL || field->type != ID3_FIELD_TYPE_TEXTENCODING)
		return;

	/* process the value(s) */

	field = id3_frame_field(frame, 1);
	if (field == NULL || field->type != ID3_FIELD_TYPE_STRINGLIST)
		return;

	/* Get the number of strings available */
	nstrings = id3_field_getnstrings(field);
	for (i = 0; i < nstrings; i++) {
		ucs4 = id3_field_getstrings(field, i);
		if (ucs4 == NULL)
			continue;

		if (type == TAG_GENRE)
			ucs4 = id3_genre_name(ucs4);

		utf8 = import_id3_string(tag_is_id3v1(tag), ucs4);
		if (utf8 == NULL)
			continue;

		tag_add_item(dest, type, (char *)utf8);
		g_free(utf8);
	}
}
static struct tag *
cue_cue_tag_load(const char *file,	const unsigned int tnum)
{
    struct tag* tag = NULL;
    char* char_tnum = NULL;
    char* ptr = NULL;
    //	unsigned int sample_rate = 0;
#ifdef HAVE_CUE /* libcue */
    FILE* cs_file;
#endif /* libcue */

    ptr = g_strdup(file);
    remove_suffix(ptr,'/');

#ifdef HAVE_CUE /* libcue */

    cs_file = fopen(ptr, "rt");
    g_free(ptr);
    if (cs_file != NULL) {
        tag = cue_tag_file(cs_file, tnum);
        fclose(cs_file);
    }
#else
    g_free(ptr);
#endif /* libcue */

    if (tag == NULL)
        return NULL;

    char_tnum = g_strdup_printf("%u", tnum);

    if (char_tnum != NULL) {
        tag_add_item(tag, TAG_TRACK, char_tnum);
        g_free(char_tnum);
    }

    //	if (sample_rate != 0)
    //	{
    //		tag->time = (unsigned int)(track_time/sample_rate);
    //	}

    return tag;
}
示例#10
0
static void parse_exif_entry(ExifEntry * e, void *data) {
  MediaScanResult *r = (MediaScanResult *)data;
  const char *key;
  char val[1024];

  // Get orientation
  if (e->tag == 0x112) {
    ExifByteOrder o = exif_data_get_byte_order(e->parent->parent);
    r->image->orientation = exif_get_short(e->data, o);
    LOG_DEBUG("Exif orientation: %d\n", r->image->orientation);
  }

  // Get key and value
  key = exif_tag_get_name_in_ifd(e->tag, exif_entry_get_ifd(e));
  exif_entry_get_value(e, val, sizeof(val));

  LOG_DEBUG("Saving Exif entry: %s: %s\n", key, val);

  tag_add_item(r->_tag, key, (const char *)val);
}
示例#11
0
static void pls_parser(GKeyFile *keyfile, struct pls_playlist *playlist)
{
	gchar *key;
	gchar *value;
	int length;
	GError *error = NULL;
	int num_entries = g_key_file_get_integer(keyfile, "playlist",
						 "NumberOfEntries", &error);
	if (error) {
		g_debug("Invalid PLS file: '%s'", error->message);
		g_error_free(error);
		error = NULL;

		/* Hack to work around shoutcast failure to comform to spec */
		num_entries = g_key_file_get_integer(keyfile, "playlist",
						     "numberofentries", &error);
		if (error) {
			g_error_free(error);
			error = NULL;
		}
	}

	while (num_entries > 0) {
		struct song *song;
		key = g_strdup_printf("File%i", num_entries);
		value = g_key_file_get_string(keyfile, "playlist", key,
					      &error);
		if(error) {
			g_debug("Invalid PLS entry %s: '%s'",key, error->message);
			g_error_free(error);
			g_free(key);
			return;
		}
		g_free(key);

		song = song_remote_new(value);
		g_free(value);

		key = g_strdup_printf("Title%i", num_entries);
		value = g_key_file_get_string(keyfile, "playlist", key,
					      &error);
		g_free(key);
		if(error == NULL && value){
			if (song->tag == NULL)
				song->tag = tag_new();
			tag_add_item(song->tag,TAG_TITLE, value);
		}
		/* Ignore errors? Most likely value not present */
		if(error) g_error_free(error);
		error = NULL;
		g_free(value);

		key = g_strdup_printf("Length%i", num_entries);
		length = g_key_file_get_integer(keyfile, "playlist", key,
						&error);
		g_free(key);
		if(error == NULL && length > 0){
			if (song->tag == NULL)
				song->tag = tag_new();
			song->tag->time = length;
		}
		/* Ignore errors? Most likely value not present */
		if(error) g_error_free(error);
		error = NULL;

		playlist->songs = g_slist_prepend(playlist->songs, song);
		num_entries--;
	}

}
示例#12
0
/** called by curl when new data is available */
static size_t
input_curl_headerfunction(void *ptr, size_t size, size_t nmemb, void *stream)
{
	struct input_curl *c = (struct input_curl *)stream;
	const char *header = ptr, *end, *value;
	char name[64];

	size *= nmemb;
	end = header + size;

	value = memchr(header, ':', size);
	if (value == NULL || (size_t)(value - header) >= sizeof(name))
		return size;

	memcpy(name, header, value - header);
	name[value - header] = 0;

	/* skip the colon */

	++value;

	/* strip the value */

	while (value < end && g_ascii_isspace(*value))
		++value;

	while (end > value && g_ascii_isspace(end[-1]))
		--end;

	if (g_ascii_strcasecmp(name, "accept-ranges") == 0) {
		/* a stream with icy-metadata is not seekable */
		if (!icy_defined(&c->icy_metadata))
			c->base.seekable = true;
	} else if (g_ascii_strcasecmp(name, "content-length") == 0) {
		char buffer[64];

		if ((size_t)(end - header) >= sizeof(buffer))
			return size;

		memcpy(buffer, value, end - value);
		buffer[end - value] = 0;

		c->base.size = c->base.offset + g_ascii_strtoull(buffer, NULL, 10);
	} else if (g_ascii_strcasecmp(name, "content-type") == 0) {
		g_free(c->base.mime);
		c->base.mime = g_strndup(value, end - value);
	} else if (g_ascii_strcasecmp(name, "icy-name") == 0 ||
		   g_ascii_strcasecmp(name, "ice-name") == 0 ||
		   g_ascii_strcasecmp(name, "x-audiocast-name") == 0) {
		g_free(c->meta_name);
		c->meta_name = g_strndup(value, end - value);

		if (c->tag != NULL)
			tag_free(c->tag);

		c->tag = tag_new();
		tag_add_item(c->tag, TAG_NAME, c->meta_name);
	} else if (g_ascii_strcasecmp(name, "icy-metaint") == 0) {
		char buffer[64];
		size_t icy_metaint;

		if ((size_t)(end - header) >= sizeof(buffer) ||
		    icy_defined(&c->icy_metadata))
			return size;

		memcpy(buffer, value, end - value);
		buffer[end - value] = 0;

		icy_metaint = g_ascii_strtoull(buffer, NULL, 10);
		g_debug("icy-metaint=%zu", icy_metaint);

		if (icy_metaint > 0) {
			icy_start(&c->icy_metadata, icy_metaint);

			/* a stream with icy-metadata is not
			   seekable */
			c->base.seekable = false;
		}
	}

	return size;
}
示例#13
0
文件: song_save.c 项目: ion1/mpd
struct song *
song_load(FILE *fp, struct directory *parent, const char *uri,
	  GString *buffer, GError **error_r)
{
	struct song *song = parent != NULL
		? song_file_new(uri, parent)
		: song_remote_new(uri);
	char *line, *colon;
	enum tag_type type;
	const char *value;

	while ((line = read_text_line(fp, buffer)) != NULL &&
	       strcmp(line, SONG_END) != 0) {
		colon = strchr(line, ':');
		if (colon == NULL || colon == line) {
			if (song->tag != NULL)
				tag_end_add(song->tag);
			song_free(song);

			g_set_error(error_r, song_save_quark(), 0,
				    "unknown line in db: %s", line);
			return NULL;
		}

		*colon++ = 0;
		value = g_strchug(colon);

		if ((type = tag_name_parse(line)) != TAG_NUM_OF_ITEM_TYPES) {
			if (!song->tag) {
				song->tag = tag_new();
				tag_begin_add(song->tag);
			}

			tag_add_item(song->tag, type, value);
		} else if (strcmp(line, "Time") == 0) {
			if (!song->tag) {
				song->tag = tag_new();
				tag_begin_add(song->tag);
			}

			song->tag->time = atoi(value);
		} else if (strcmp(line, SONG_MTIME) == 0) {
			song->mtime = atoi(value);
		} else if (strcmp(line, "Range") == 0) {
			char *endptr;

			song->start_ms = strtoul(value, &endptr, 10);
			if (*endptr == '-')
				song->end_ms = strtoul(endptr + 1, NULL, 10);
		} else {
			if (song->tag != NULL)
				tag_end_add(song->tag);
			song_free(song);

			g_set_error(error_r, song_save_quark(), 0,
				    "unknown line in db: %s", line);
			return NULL;
		}
	}

	if (song->tag != NULL)
		tag_end_add(song->tag);

	return song;
}
示例#14
0
文件: tag_id3.c 项目: azuwis/mpd
static void
getID3Info(struct id3_tag *tag, const char *id, int type, struct tag *mpdTag)
{
	struct id3_frame const *frame;
	id3_ucs4_t const *ucs4;
	id3_utf8_t *utf8;
	union id3_field const *field;
	unsigned int nstrings, i;
	enum id3_field_textencoding id3_encoding = 0xff;

	frame = id3_tag_findframe(tag, id, 0);
	/* Check frame */
	if (!frame)
	{
		return;
	}
	/* Check fields in frame */
	if(frame->nfields == 0)
	{
		g_debug("Frame has no fields");
		return;
	}

	/* Starting with T is a stringlist */
	if (id[0] == 'T')
	{
		/* This one contains 2 fields:
		 * 1st: Text encoding
		 * 2: Stringlist
		 * Shamefully this isn't the RL case.
		 * But I am going to enforce it anyway. 
		 */
		if(frame->nfields != 2) 
		{
			g_debug("Invalid number '%i' of fields for TXX frame",
				frame->nfields);
			return;
		}
		field = &frame->fields[0];
		/**
		 * First field is encoding field.
		 * This is ignored by mpd.
		 */
		if(field->type != ID3_FIELD_TYPE_TEXTENCODING)
		{
			g_debug("Expected encoding, found: %i",
				field->type);
		} else
                        id3_encoding = field->number.value;
		/* Process remaining fields, should be only one */
		field = &frame->fields[1];
		/* Encoding field */
		if(field->type == ID3_FIELD_TYPE_STRINGLIST) {
			/* Get the number of strings available */
			nstrings = id3_field_getnstrings(field);
			for (i = 0; i < nstrings; i++) {
				ucs4 = id3_field_getstrings(field,i);
				if(!ucs4)
					continue;
				utf8 = processID3FieldString(isId3v1(tag),ucs4, type, id3_encoding);
				if(!utf8)
					continue;

				tag_add_item(mpdTag, type, (char *)utf8);
				g_free(utf8);
			}
		}
		else {
			g_warning("Field type not processed: %i",
				  (int)id3_field_gettextencoding(field));
		}
	}
	/* A comment frame */
	else if(!strcmp(ID3_FRAME_COMMENT, id))
	{
		/* A comment frame is different... */
	/* 1st: encoding
         * 2nd: Language
         * 3rd: String
         * 4th: FullString.
         * The 'value' we want is in the 4th field
         */
		if(frame->nfields == 4)
		{
			/* for now I only read the 4th field, with the fullstring */
			field = &frame->fields[3];
			if(field->type == ID3_FIELD_TYPE_STRINGFULL)
			{
				ucs4 = id3_field_getfullstring(field);
				if(ucs4)
				{
					utf8 = processID3FieldString(isId3v1(tag),ucs4, type, id3_encoding);
					if(utf8)
					{
						tag_add_item(mpdTag, type, (char *)utf8);
						g_free(utf8);
					}
				}
			}
			else
			{
				g_debug("4th field in comment frame differs from expected, got '%i': ignoring",
					field->type);
			}
		}
		else
		{
			g_debug("Invalid 'comments' tag, got '%i' fields instead of 4",
				frame->nfields);
		}
	}
	/* Unsupported */
	else
		g_debug("Unsupported tag type requrested");
}