⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tag.c

📁 OggPlay for Symbian 是symbian上的一个媒体播放程序的源码。它支持ogg,wav等等多媒体格式。
💻 C
📖 第 1 页 / 共 2 页
字号:
      size = id3_util_deunsynchronise(mem, size);
      ptr  = mem;
    }

    end = ptr + size;

    if (tag->flags & ID3_TAG_FLAG_EXTENDEDHEADER) {
      switch (ID3_TAG_VERSION_MAJOR(tag->version)) {
      case 2:
	goto fail;

      case 3:
	{
	  id3_byte_t const *ehptr, *ehend;
	  id3_length_t ehsize;

	  enum {
	    EH_FLAG_CRC = 0x8000  /* CRC data present */
	  };

	  if (end - ptr < 4)
	    goto fail;

	  ehsize = id3_parse_uint(&ptr, 4);

	  if (ehsize > end - ptr)
	    goto fail;

	  ehptr = ptr;
	  ehend = ptr + ehsize;

	  ptr = ehend;

	  if (ehend - ehptr >= 6) {
	    int ehflags;
	    id3_length_t padsize;

	    ehflags = id3_parse_uint(&ehptr, 2);
	    padsize = id3_parse_uint(&ehptr, 4);

	    if (padsize > end - ptr)
	      goto fail;

	    end -= padsize;

	    if (ehflags & EH_FLAG_CRC) {
	      unsigned long crc;

	      if (ehend - ehptr < 4)
		goto fail;

	      crc = id3_parse_uint(&ehptr, 4);

	      if (crc != id3_crc_compute(ptr, end - ptr))
		goto fail;

	      tag->extendedflags |= ID3_TAG_EXTENDEDFLAG_CRCDATAPRESENT;
	    }
	  }
	}
	break;

      case 4:
	{
	  id3_byte_t const *ehptr, *ehend;
	  id3_length_t ehsize;
	  unsigned int bytes;

	  if (end - ptr < 4)
	    goto fail;

	  ehptr  = ptr;
	  ehsize = id3_parse_syncsafe(&ptr, 4);

	  if (ehsize < 6 || ehsize > end - ehptr)
	    goto fail;

	  ehend = ehptr + ehsize;

	  bytes = id3_parse_uint(&ptr, 1);

	  if (bytes < 1 || bytes > ehend - ptr)
	    goto fail;

	  ehptr = ptr + bytes;

	  /* verify extended header size */
	  {
	    id3_byte_t const *flagsptr = ptr, *dataptr = ehptr;
	    unsigned int datalen;
	    int ehflags;

	    while (bytes--) {
	      for (ehflags = id3_parse_uint(&flagsptr, 1); ehflags;
		   ehflags = (ehflags << 1) & 0xff) {
		if (ehflags & 0x80) {
		  if (dataptr == ehend)
		    goto fail;
		  datalen = id3_parse_uint(&dataptr, 1);
		  if (datalen > 0x7f || datalen > ehend - dataptr)
		    goto fail;
		  dataptr += datalen;
		}
	      }
	    }
	  }

	  tag->extendedflags = id3_parse_uint(&ptr, 1);

	  ptr = ehend;

	  if (tag->extendedflags & ID3_TAG_EXTENDEDFLAG_TAGISANUPDATE) {
	    bytes  = id3_parse_uint(&ehptr, 1);
	    ehptr += bytes;
	  }

	  if (tag->extendedflags & ID3_TAG_EXTENDEDFLAG_CRCDATAPRESENT) {
	    unsigned long crc;

	    bytes = id3_parse_uint(&ehptr, 1);
	    if (bytes < 5)
	      goto fail;

	    crc = id3_parse_syncsafe(&ehptr, 5);
	    ehptr += bytes - 5;

	    if (crc != id3_crc_compute(ptr, end - ptr))
	      goto fail;
	  }

	  if (tag->extendedflags & ID3_TAG_EXTENDEDFLAG_TAGRESTRICTIONS) {
	    bytes = id3_parse_uint(&ehptr, 1);
	    if (bytes < 1)
	      goto fail;

	    tag->restrictions = id3_parse_uint(&ehptr, 1);
	    ehptr += bytes - 1;
	  }
	}
	break;
      }
    }

    /* frames */

    while (ptr < end) {
      struct id3_frame *frame;

      if (*ptr == 0)
	break;  /* padding */

      frame = id3_frame_parse(&ptr, end - ptr, tag->version);
      if (frame == 0 || id3_tag_attachframe(tag, frame) == -1)
	goto fail;
    }

    if (ID3_TAG_VERSION_MAJOR(tag->version) < 4 &&
	id3_compat_fixup(tag) == -1)
      goto fail;
  }

  if (0) {
  fail:
    id3_tag_delete(tag);
    tag = 0;
  }

  if (mem)
    free(mem);

  return tag;
}

/*
 * NAME:	tag->parse()
 * DESCRIPTION:	parse a complete ID3 tag
 */
struct id3_tag *id3_tag_parse(id3_byte_t const *data, id3_length_t length)
{
  id3_byte_t const *ptr;
  unsigned int version;
  int flags;
  id3_length_t size;

  assert(data);

  switch (tagtype(data, length)) {
  case TAGTYPE_ID3V1:
    return (length < 128) ? 0 : v1_parse(data);

  case TAGTYPE_ID3V2:
    break;

  case TAGTYPE_ID3V2_FOOTER:
  case TAGTYPE_NONE:
    return 0;
  }

  /* ID3v2.x */

  ptr = data;
  parse_header(&ptr, &version, &flags, &size);

  switch (ID3_TAG_VERSION_MAJOR(version)) {
  case 4:
    if (flags & ID3_TAG_FLAG_FOOTERPRESENT)
      size += 10;
  case 2:
  case 3:
    return (length < 10 + size) ? 0 : v2_parse(data);
  }

  return 0;
}

static
void v1_renderstr(struct id3_tag const *tag, char const *frameid,
		  id3_byte_t **buffer, id3_length_t length)
{
  struct id3_frame *frame;
  id3_ucs4_t const *string;

  frame = id3_tag_findframe(tag, frameid, 0);
  if (frame == 0)
    string = id3_ucs4_empty;
  else {
    if (strcmp(frameid, ID3_FRAME_COMMENT) == 0)
      string = id3_field_getfullstring(&frame->fields[3]);
    else
      string = id3_field_getstrings(&frame->fields[1], 0);
  }

  id3_render_paddedstring(buffer, string, length);
}

/*
 * NAME:	v1->render()
 * DESCRIPTION:	render an ID3v1 (or ID3v1.1) tag
 */
static
id3_length_t v1_render(struct id3_tag const *tag, id3_byte_t *buffer)
{
  id3_byte_t data[128], *ptr;
  struct id3_frame *frame;
  unsigned int i;
  int genre = -1;

  ptr = data;

  id3_render_immediate(&ptr, "TAG", 3);

  v1_renderstr(tag, ID3_FRAME_TITLE,   &ptr, 30);
  v1_renderstr(tag, ID3_FRAME_ARTIST,  &ptr, 30);
  v1_renderstr(tag, ID3_FRAME_ALBUM,   &ptr, 30);
  v1_renderstr(tag, ID3_FRAME_YEAR,    &ptr,  4);
  v1_renderstr(tag, ID3_FRAME_COMMENT, &ptr, 30);

  /* ID3v1.1 track number */

  frame = id3_tag_findframe(tag, ID3_FRAME_TRACK, 0);
  if (frame) {
    unsigned int track;

    track = id3_ucs4_getnumber(id3_field_getstrings(&frame->fields[1], 0));
    if (track > 0 && track <= 0xff) {
      ptr[-2] = 0;
      ptr[-1] = track;
    }
  }

  /* ID3v1 genre number */

  frame = id3_tag_findframe(tag, ID3_FRAME_GENRE, 0);
  if (frame) {
    unsigned int nstrings;

    nstrings = id3_field_getnstrings(&frame->fields[1]);

    for (i = 0; i < nstrings; ++i) {
      genre = id3_genre_number(id3_field_getstrings(&frame->fields[1], i));
      if (genre != -1)
	break;
    }

    if (i == nstrings && nstrings > 0)
      genre = ID3_GENRE_OTHER;
  }

  id3_render_int(&ptr, genre, 1);

  /* make sure the tag is not empty */

  if (genre == -1) {
    for (i = 3; i < 127; ++i) {
      if (data[i] != ' ')
	break;
    }

    if (i == 127)
      return 0;
  }

  if (buffer)
    memcpy(buffer, data, 128);

  return 128;
}

/*
 * NAME:	tag->render()
 * DESCRIPTION:	render a complete ID3 tag
 */
id3_length_t id3_tag_render(struct id3_tag const *tag, id3_byte_t *buffer)
{
  id3_length_t size = 0;
  id3_byte_t **ptr,
    *header_ptr = 0, *tagsize_ptr = 0, *crc_ptr = 0, *frames_ptr = 0;
  int flags, extendedflags;
  unsigned int i;

  assert(tag);

  if (tag->options & ID3_TAG_OPTION_ID3V1)
    return v1_render(tag, buffer);

  /* a tag must contain at least one (renderable) frame */

  for (i = 0; i < tag->nframes; ++i) {
    if (id3_frame_render(tag->frames[i], 0, 0) > 0)
      break;
  }

  if (i == tag->nframes)
    return 0;

  ptr = buffer ? &buffer : 0;

  /* get flags */

  flags         = tag->flags         & ID3_TAG_FLAG_KNOWNFLAGS;
  extendedflags = tag->extendedflags & ID3_TAG_EXTENDEDFLAG_KNOWNFLAGS;

  extendedflags &= ~ID3_TAG_EXTENDEDFLAG_CRCDATAPRESENT;
  if (tag->options & ID3_TAG_OPTION_CRC)
    extendedflags |= ID3_TAG_EXTENDEDFLAG_CRCDATAPRESENT;

  extendedflags &= ~ID3_TAG_EXTENDEDFLAG_TAGRESTRICTIONS;
  if (tag->restrictions)
    extendedflags |= ID3_TAG_EXTENDEDFLAG_TAGRESTRICTIONS;

  flags &= ~ID3_TAG_FLAG_UNSYNCHRONISATION;
  if (tag->options & ID3_TAG_OPTION_UNSYNCHRONISATION)
    flags |= ID3_TAG_FLAG_UNSYNCHRONISATION;

  flags &= ~ID3_TAG_FLAG_EXTENDEDHEADER;
  if (extendedflags)
    flags |= ID3_TAG_FLAG_EXTENDEDHEADER;

  flags &= ~ID3_TAG_FLAG_FOOTERPRESENT;
  if (tag->options & ID3_TAG_OPTION_APPENDEDTAG)
    flags |= ID3_TAG_FLAG_FOOTERPRESENT;

  /* header */

  if (ptr)
    header_ptr = *ptr;

  size += id3_render_immediate(ptr, "ID3", 3);
  size += id3_render_int(ptr, ID3_TAG_VERSION, 2);
  size += id3_render_int(ptr, flags, 1);

  if (ptr)
    tagsize_ptr = *ptr;

  size += id3_render_syncsafe(ptr, 0, 4);

  /* extended header */

  if (flags & ID3_TAG_FLAG_EXTENDEDHEADER) {
    id3_length_t ehsize = 0;
    id3_byte_t *ehsize_ptr = 0;

    if (ptr)
      ehsize_ptr = *ptr;

    ehsize += id3_render_syncsafe(ptr, 0, 4);
    ehsize += id3_render_int(ptr, 1, 1);
    ehsize += id3_render_int(ptr, extendedflags, 1);

    if (extendedflags & ID3_TAG_EXTENDEDFLAG_TAGISANUPDATE)
      ehsize += id3_render_int(ptr, 0, 1);

    if (extendedflags & ID3_TAG_EXTENDEDFLAG_CRCDATAPRESENT) {
      ehsize += id3_render_int(ptr, 5, 1);

      if (ptr)
	crc_ptr = *ptr;

      ehsize += id3_render_syncsafe(ptr, 0, 5);
    }

    if (extendedflags & ID3_TAG_EXTENDEDFLAG_TAGRESTRICTIONS) {
      ehsize += id3_render_int(ptr, 1, 1);
      ehsize += id3_render_int(ptr, tag->restrictions, 1);
    }

    if (ehsize_ptr)
      id3_render_syncsafe(&ehsize_ptr, ehsize, 4);

    size += ehsize;
  }

  /* frames */

  if (ptr)
    frames_ptr = *ptr;

  for (i = 0; i < tag->nframes; ++i)
    size += id3_frame_render(tag->frames[i], ptr, tag->options);

  /* padding */

  if (!(flags & ID3_TAG_FLAG_FOOTERPRESENT)) {
    if (size < tag->paddedsize)
      size += id3_render_padding(ptr, 0, tag->paddedsize - size);
    else if (tag->options & ID3_TAG_OPTION_UNSYNCHRONISATION) {
      if (ptr == 0)
	size += 1;
      else {
	if ((*ptr)[-1] == 0xff)
	  size += id3_render_padding(ptr, 0, 1);
      }
    }
  }

  /* patch tag size and CRC */

  if (tagsize_ptr)
    id3_render_syncsafe(&tagsize_ptr, size - 10, 4);

  if (crc_ptr) {
    id3_render_syncsafe(&crc_ptr,
			id3_crc_compute(frames_ptr, *ptr - frames_ptr), 5);
  }

  /* footer */

  if (flags & ID3_TAG_FLAG_FOOTERPRESENT) {
    size += id3_render_immediate(ptr, "3DI", 3);
    size += id3_render_binary(ptr, header_ptr + 3, 7);
  }

  return size;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -