Exemple #1
0
const id3_ucs4_t* metadata_getstring(const struct id3_tag* tag, const char* id, enum id3_field_textencoding* encoding)
{
  int nstrings, j;
  char const *name;
  id3_ucs4_t const *ucs4;
  union id3_field const *field;
  struct id3_frame const *frame;

  frame = id3_tag_findframe(tag, id, 0);
  if (frame == 0)
	  return id3_ucs4_empty;

  *encoding = id3_field_gettextencoding(id3_frame_field(frame, 0));

  field = id3_frame_field(frame, 1);
  if (field == 0)
    return id3_ucs4_empty;

  nstrings = id3_field_getnstrings(field);

  ucs4 = id3_ucs4_empty;

  for (j = 0; j < nstrings; ++j)
  {
    ucs4 = id3_field_getstrings(field, j);
    if (ucs4 && *ucs4)
      break;
  }

  return ucs4;
}
Exemple #2
0
const id3_ucs4_t* id3_metadata_getcomment(const struct id3_tag* tag, enum id3_field_textencoding* encoding)
{
  union id3_field const *field;
  struct id3_frame const *frame;
  const id3_ucs4_t* ucs4 = 0;
  int commentNumber = 0;

  // return the first non-empty comment
  do
  {
    frame = id3_tag_findframe(tag, ID3_FRAME_COMMENT, commentNumber++);
    if (frame == 0)
	    return id3_ucs4_empty;

    *encoding = id3_field_gettextencoding(id3_frame_field(frame, 0));

    field = id3_frame_field(frame, 3);
    if (field == 0)
      return id3_ucs4_empty;
    
    ucs4 = id3_field_getfullstring(field);
    if (!ucs4)
      return id3_ucs4_empty;
  }
  while (*ucs4 == 0);
  return ucs4;
}
Exemple #3
0
id3_ucs4_list_t *metadata_getstrings(const struct id3_tag* tag, const char* id, enum id3_field_textencoding* encoding)
{
  int nstrings, j;
  union id3_field const *field;
  struct id3_frame const *frame;
  id3_ucs4_list_t *list;

  frame = id3_tag_findframe(tag, id, 0);
  if (frame == 0)
	  return 0;

  *encoding = id3_field_gettextencoding(id3_frame_field(frame, 0));

  field = id3_frame_field(frame, 1);
  if (field == 0)
    return 0;

  nstrings = id3_field_getnstrings(field);

  list = 0;
  if (nstrings)
  {
    list = (id3_ucs4_list_t*)malloc(sizeof(*list));
    if (list)
      list->strings = (const id3_ucs4_t**)malloc(nstrings * sizeof(*list->strings));
  }
  if (list && list->strings)
  {
    list->nstrings = nstrings;
    for (j = 0; j < list->nstrings; ++j)
      list->strings[j] = id3_field_getstrings(field, j);
  }
  return list;
}
Exemple #4
0
static void
write_tags(ImlibImage * im, lopt * opt)
{
   struct id3_frame   *frame = id3_tag_get_frame(opt->ctx->tag, opt->index - 1);
   union id3_field    *field;
   int                 num_data;
   char               *data;

   if ((field = id3_frame_field(frame, 1)) &&
       (data = (char *)id3_field_getlatin1(field)))
      __imlib_AttachTag(im, "mime-type", 0, strdup(data), destructor_data);
   if ((field = id3_frame_field(frame, 3)) &&
       (data = (char *)id3_field_getstring(field)))
     {
        size_t              length;
        char               *dup;
        id3_ucs4_t         *ptr = (id3_ucs4_t *) data;

        while (*ptr)
           ptr++;
        length = (ptr - (id3_ucs4_t *) data + 1) * sizeof(id3_ucs4_t);
        dup = (char *)malloc(length);
        memcpy(dup, data, length);
        __imlib_AttachTag(im, "id3-description", 0, dup, destructor_data);
     }
   if (field = id3_frame_field(frame, 0))
      __imlib_AttachTag(im, "id3-description-text-encoding",
                        (num_data = (int)id3_field_gettextencoding(field)),
                        num_data < NUM_OF_ID3_TEXT_ENCODINGS ?
                        id3_text_encodings[num_data] : NULL, NULL);
   if (field = id3_frame_field(frame, 2))
      __imlib_AttachTag(im, "id3-picture-type",
                        (num_data = id3_field_getint(field)),
                        num_data < NUM_OF_ID3_PIC_TYPES ?
                        id3_pic_types[num_data] : NULL, NULL);
   __imlib_AttachTag(im, "count", id3_tag_get_numframes(opt->ctx->tag),
                     NULL, NULL);
   if (opt->cache_level)
     {
        context_addref(opt->ctx);
        __imlib_AttachTag(im, "context", opt->ctx->id,
                          opt->ctx, destructor_context);
     }
   __imlib_AttachTag(im, "index", opt->index, NULL, NULL);
   if (opt->traverse)
     {
        char               *buf = NULL;

        if ((opt->index + opt->traverse)
            <= id3_tag_get_numframes(opt->ctx->tag)
            && (opt->index + opt->traverse) > 0)
          {
             buf = (char *)malloc((strlen(im->real_file) + 50) * sizeof(char));
             sprintf(buf, "%s:index=%d,traverse=%d", im->real_file,
                     opt->index + opt->traverse, opt->traverse);
          }
        __imlib_AttachTag(im, "next", 0, buf, destructor_data);
     }
}
Exemple #5
0
const id3_ucs4_t* id3_metadata_getcomment(const struct id3_tag* tag, enum id3_field_textencoding* encoding)
{
  union id3_field const *field;
  struct id3_frame const *frame;
  int commentNumber = 0;
  const id3_ucs4_t* ucs4 = 0;

  // return the first non-empty comment
  do
  {
    frame = id3_tag_findframe(tag, ID3_FRAME_COMMENT, commentNumber++);

    if (frame && frame->nfields == 4)
    {
      //get short description
      field = id3_frame_field(frame, 2);
      if (field == 0)
        continue;
      
      ucs4 = id3_field_getstring(field);

      // Multiple values are allowed per comment field, but storing different comment
      // frames requires a different description for each frame. The first COMM frame
      // encountered without a description will be used as the comment field.
      // Source http://puddletag.sourceforge.net/source/id3.html
      if (ucs4 && *ucs4 == 0)//if short description on this frame is empty - consider this the wanted comment frame
      {
        //fetch encoding of the frame
        field = id3_frame_field(frame, 0);
        
        if(field == 0)
          continue;
          
        *encoding = id3_field_gettextencoding(field);

        //finally fetch the comment
        field = id3_frame_field(frame, 3);
        if (field == 0)
          continue;
    
        return id3_field_getfullstring(field);
      }
    }
  }
  while (frame);
  return ucs4;
}
Exemple #6
0
static char *get_tag (struct id3_tag *tag, const char *what)
{
	struct id3_frame *frame;
	union id3_field *field;
	const id3_ucs4_t *ucs4;
	char *comm = NULL;

	frame = id3_tag_findframe (tag, what, 0);
	if (frame && (field = &frame->fields[1])) {
		ucs4 = id3_field_getstrings (field, 0);
		if (ucs4) {
			/* Workaround for ID3 tags v1/v1.1 where the encoding
			 * is latin1. */
            union id3_field *encoding_field = &frame->fields[0];
			if ((id3_tag_options(tag, 0, 0) & ID3_TAG_OPTION_ID3V1) 
                    || ((options_get_int ("EnforceTagsEncoding") && 
                            (id3_field_gettextencoding((encoding_field)) 
                             == ID3_FIELD_TEXTENCODING_ISO_8859_1))))
            {
				char *t;

				comm = (char *)id3_ucs4_latin1duplicate (ucs4);

#ifdef HAVE_RCC
				if (options_get_int("UseRCC"))
					comm = do_rcc (comm);
				else {
#endif /* HAVE_RCC */
					t = comm;
					comm = id3v1_fix (comm);
					free (t);
#ifdef HAVE_RCC
				}
#endif /* HAVE_RCC */
			}
			else
				comm = (char *)id3_ucs4_utf8duplicate (ucs4);
		}
	}

	return comm;
}
Exemple #7
0
wchar_t* GetMP3Tag(const id3_tag* tag, const char* name)
{
	wchar_t* content = NULL;
	id3_frame* frame = id3_tag_findframe(tag, name, 0);
	if (frame != NULL)
	{
		id3_field* field = id3_frame_field(frame, 0);
		id3_field_textencoding encoding = id3_field_gettextencoding(field);
		field = id3_frame_field(frame, 1);

		switch (id3_field_type(field))
		{
		case ID3_FIELD_TYPE_STRING:
			content = GetMP3Text(encoding, field, id3_field_getstring(field));
			break;

		case ID3_FIELD_TYPE_STRINGFULL:						
			content = GetMP3Text(encoding, field, id3_field_getfullstring(field));
			break;

		case ID3_FIELD_TYPE_STRINGLIST:
			{				
				DWORD dataLength = 0, bufferLength = 0;
				unsigned int n = id3_field_getnstrings(field);
				for (unsigned int i = 0; i < n; i++)
				{
					wchar_t* p = GetMP3Text(encoding, field, id3_field_getstrings(field, i));
					if (p == NULL)
						continue;

					AppendBuffer((char**)&content, dataLength, bufferLength, (const char*)p, wcslen(p) * 2 + 1);
					SAFE_DELETE_ARRAY(p);
				}
			}
			break;
		}
	}

	return content;
}
int scan_mp3_get_mp3tags(char *file, MP3FILE *pmp3) {
    struct id3_file *pid3file;
    struct id3_tag *pid3tag;
    struct id3_frame *pid3frame;
    int err;
    int index;
    int used;
    char *utf8_text;
    int genre=WINAMP_GENRE_UNKNOWN;
    int have_utf8;
    int have_text;
    id3_ucs4_t const *native_text;
    char *tmp;
    int got_numeric_genre;
    int rating;
    char *conversion_codepage;

    pid3file=id3_file_open(file,ID3_FILE_MODE_READONLY);
    if(!pid3file) {
        DPRINTF(E_WARN,L_SCAN,"Cannot open %s\n",file);
        return FALSE;
    }

    pid3tag=id3_file_tag(pid3file);

    if(!pid3tag) {
        err=errno;
        id3_file_close(pid3file);
        errno=err;
        DPRINTF(E_WARN,L_SCAN,"Cannot get ID3 tag for %s\n",file);
        return FALSE;
    }

    DPRINTF(E_SPAM,L_SCAN,"Starting mp3 tag scan\n");

    conversion_codepage = conf_alloc_string("scanning","mp3_tag_codepage",
                                            "ISO-8859-1");

    index=0;
    while((pid3frame=id3_tag_findframe(pid3tag,"",index))) {
        used=0;
        utf8_text=NULL;
        native_text=NULL;
        have_utf8=0;
        have_text=0;

        DPRINTF(E_SPAM,L_SCAN,"Found tag %s\n",pid3frame->id);

        if(!strcmp(pid3frame->id,"YTCP")) { /* for id3v2.2 */
            pmp3->compilation = 1;
            DPRINTF(E_DBG,L_SCAN,"Compilation: %d\n", pmp3->compilation);
        }

        if(((pid3frame->id[0] == 'T')||(strcmp(pid3frame->id,"COMM")==0)) &&
           (id3_field_getnstrings(&pid3frame->fields[1])))
            have_text=1;

        if(have_text) {
            native_text=id3_field_getstrings(&pid3frame->fields[1],0);

            if(native_text) {
                have_utf8=1;


                utf8_text = (char*)id3_ucs4_utf8duplicate(native_text);
                if(utf8_text)
                    mem_register(utf8_text,0);

                if(id3_field_gettextencoding(&pid3frame->fields[1]) ==
                   ID3_FIELD_TEXTENCODING_ISO_8859_1) {
#ifdef HAVE_ICONV
                    /* this is kinda cheesy, but ucs4* == char* for 8859-1 */
                    free(utf8_text);
                    utf8_text =
                        (char*)util_xtoutf8_alloc((unsigned char*)native_text,
                                                  strlen((char*)native_text),
                                                  conversion_codepage);
#endif
                }



                if(!strcmp(pid3frame->id,"TIT2")) { /* Title */
                    used=1;
                    pmp3->title = utf8_text;
                    DPRINTF(E_DBG,L_SCAN," Title: %s\n",utf8_text);
                } else if(!strcmp(pid3frame->id,"TPE1")) {
                    used=1;
                    pmp3->artist = utf8_text;
                    DPRINTF(E_DBG,L_SCAN," Artist: %s\n",utf8_text);
                } else if(!strcmp(pid3frame->id,"TALB")) {
                    used=1;
                    pmp3->album = utf8_text;
                    DPRINTF(E_DBG,L_SCAN," Album: %s\n",utf8_text);
                } else if(!strcmp(pid3frame->id,"TCOM")) {
                    used=1;
                    pmp3->composer = utf8_text;
                    DPRINTF(E_DBG,L_SCAN," Composer: %s\n",utf8_text);
                } else if(!strcmp(pid3frame->id,"TIT1")) {
                    used=1;
                    pmp3->grouping = utf8_text;
                    DPRINTF(E_DBG,L_SCAN," Grouping: %s\n",utf8_text);
                } else if(!strcmp(pid3frame->id,"TPE2")) {
                    used=1;
                    pmp3->orchestra = utf8_text;
                    DPRINTF(E_DBG,L_SCAN," Orchestra: %s\n",utf8_text);
                } else if(!strcmp(pid3frame->id,"TPE3")) {
                    used=1;
                    pmp3->conductor = utf8_text;
                    DPRINTF(E_DBG,L_SCAN," Conductor: %s\n",utf8_text);
                } else if(!strcmp(pid3frame->id,"TCON")) {
                    used=1;
                    pmp3->genre = utf8_text;
                    got_numeric_genre=0;
                    DPRINTF(E_DBG,L_SCAN," Genre: %s\n",utf8_text);
                    if(pmp3->genre) {
                        if(!strlen(pmp3->genre)) {
                            genre=WINAMP_GENRE_UNKNOWN;
                            got_numeric_genre=1;
                        } else if (scan_mp3_is_numeric(pmp3->genre)) {
                            genre=atoi(pmp3->genre);
                            got_numeric_genre=1;
                        } else if ((pmp3->genre[0] == '(') && (isdigit(pmp3->genre[1]))) {
                            genre=atoi((char*)&pmp3->genre[1]);
                            got_numeric_genre=1;
                        }

                        if(got_numeric_genre) {
                            if((genre < 0) || (genre > WINAMP_GENRE_UNKNOWN))
                                genre=WINAMP_GENRE_UNKNOWN;
                            free(pmp3->genre);
                            pmp3->genre=strdup(scan_winamp_genre[genre]);
                        }
                    }
                } else if(!strcmp(pid3frame->id,"COMM")) {
                    used=1;
                    pmp3->comment = utf8_text;
                    DPRINTF(E_DBG,L_SCAN," Comment: %s\n",pmp3->comment);
                } else if(!strcmp(pid3frame->id,"TPOS")) {
                    tmp=utf8_text;
                    strsep(&tmp,"/");
                    if(tmp) {
                        pmp3->total_discs=atoi(tmp);
                    }
                    pmp3->disc=atoi(utf8_text);
                    DPRINTF(E_DBG,L_SCAN," Disc %d of %d\n",pmp3->disc,pmp3->total_discs);
                } else if(!strcmp(pid3frame->id,"TRCK")) {
                    tmp=utf8_text;
                    strsep(&tmp,"/");
                    if(tmp) {
                        pmp3->total_tracks=atoi(tmp);
                    }
                    pmp3->track=atoi(utf8_text);
                    DPRINTF(E_DBG,L_SCAN," Track %d of %d\n",pmp3->track,pmp3->total_tracks);
                } else if(!strcmp(pid3frame->id,"TDRC")) {
                    pmp3->year = atoi(utf8_text);
                    DPRINTF(E_DBG,L_SCAN," Year: %d\n",pmp3->year);
                } else if(!strcmp(pid3frame->id,"TLEN")) {
                    pmp3->song_length = atoi(utf8_text); /* now in ms */
                    DPRINTF(E_DBG,L_SCAN," Length: %d\n", pmp3->song_length);
                } else if(!strcmp(pid3frame->id,"TBPM")) {
                    pmp3->bpm = atoi(utf8_text);
                    DPRINTF(E_DBG,L_SCAN,"BPM: %d\n", pmp3->bpm);
                } else if(!strcmp(pid3frame->id,"TCMP")) { /* for id3v2.3 */
                    pmp3->compilation = (char)atoi(utf8_text);
                    DPRINTF(E_DBG,L_SCAN,"Compilation: %d\n", pmp3->compilation);
                }
            }
        }

        /* can check for non-text tags here */
        if((!used) && (have_utf8) && (utf8_text))
            free(utf8_text);

        if((!strcmp(pid3frame->id,"POPM")) && (pid3frame->nfields == 3)) {
            rating = id3_field_getint(&pid3frame->fields[1]);
            if(rating >= 0x01)
                pmp3->rating = 20;
            if(rating >= 0x40)
                pmp3->rating = 40;
            if(rating >= 0x80)
                pmp3->rating = 60;
            if(rating >= 0xC4)
                pmp3->rating = 80;
            if(rating >= 0xFF)
                pmp3->rating = 100;
        }


        /* v2 COMM tags are a bit different than v1 */
        if((!strcmp(pid3frame->id,"COMM")) && (pid3frame->nfields == 4)) {
            /* Make sure it isn't a application-specific comment...
             * This currently includes the following:
             *
             * iTunes_CDDB_IDs
             * iTunNORM
             *
             * If other apps stuff crap into comment fields, then we'll ignore them
             * here.
             */
            native_text=id3_field_getstring(&pid3frame->fields[2]);
            if(native_text) {
                utf8_text=(char*)id3_ucs4_utf8duplicate(native_text);
                if(utf8_text)
                    mem_register(utf8_text,0);

                if((utf8_text) && (strncasecmp(utf8_text,"iTun",4) != 0)) {
                    /* it's a real comment */
                    if(utf8_text)
                        free(utf8_text);

                    native_text=id3_field_getfullstring(&pid3frame->fields[3]);
                    if(native_text) {
                        if(pmp3->comment)
                            free(pmp3->comment);
                        utf8_text=(char*)id3_ucs4_utf8duplicate(native_text);
                        if(utf8_text) {
                            mem_register(utf8_text,0);
                            pmp3->comment=utf8_text;
                        }
                    }
                } else {
                    if(utf8_text)
                        free(utf8_text);
                }
            }
        }

        index++;
    }

    free(conversion_codepage);
    id3_file_close(pid3file);
    DPRINTF(E_DBG,L_SCAN,"Got id3 tag successfully\n");
    return TRUE;
}
Exemple #9
0
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");
}