Esempio n. 1
0
/*
 * 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)
{
  struct id3_frame *frame;
  unsigned int number, i;

  if (buffer == 0)
    return 128;

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

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

  frame = id3_tag_findframe(tag, ID3_FRAME_TRACK, 0);
  if (frame) {
    number = id3_ucs4_getnumber(id3_field_getstrings(&frame->fields[1], 0));
    if (number & 0xff) {
      buffer[-2] = 0;
      buffer[-1] = number;
    }
  }

  frame = id3_tag_findframe(tag, ID3_FRAME_GENRE, 0);
  number = frame ?
    id3_ucs4_getnumber(id3_field_getstrings(&frame->fields[1], 0)) : 0xff;
  id3_render_int(&buffer, number, 1);

  /* make sure the tag is not empty */

  buffer -= 128;
  for (i = 3; i < 127; ++i) {
    if (buffer[i] != ' ')
      break;
  }

  return (i == 127 && buffer[127] == 0xff) ? 0 : 128;
}
Esempio n. 2
0
/*
 * 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;
}
Esempio n. 3
0
/*
 * 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;
}
Esempio n. 4
0
/*
 * NAME:	field->render()
 * DESCRIPTION:	render a field value
 */
id3_length_t id3_field_render(union id3_field const *field, id3_byte_t **ptr,
			      enum id3_field_textencoding *encoding,
			      int terminate)
{
  id3_length_t size;
  unsigned int i;

  assert(field && encoding);

  switch (field->type) {
  case ID3_FIELD_TYPE_INT32:
    return id3_render_int(ptr, field->number.value, 4);

  case ID3_FIELD_TYPE_INT24:
    return id3_render_int(ptr, field->number.value, 3);

  case ID3_FIELD_TYPE_INT16:
    return id3_render_int(ptr, field->number.value, 2);

  case ID3_FIELD_TYPE_TEXTENCODING:
    *encoding = field->number.value;
  case ID3_FIELD_TYPE_INT8:
    return id3_render_int(ptr, field->number.value, 1);

  case ID3_FIELD_TYPE_LATIN1:
  case ID3_FIELD_TYPE_LATIN1FULL:
    return id3_render_latin1(ptr, field->latin1.ptr, terminate);

  case ID3_FIELD_TYPE_LATIN1LIST:
    size = 0;
    for (i = 0; i < field->latin1list.nstrings; ++i) {
      size += id3_render_latin1(ptr, field->latin1list.strings[i],
				(i < field->latin1list.nstrings - 1) ||
				terminate);
    }
    return size;

  case ID3_FIELD_TYPE_STRING:
  case ID3_FIELD_TYPE_STRINGFULL:
    return id3_render_string(ptr, field->string.ptr, *encoding, terminate);

  case ID3_FIELD_TYPE_STRINGLIST:
    size = 0;
    for (i = 0; i < field->stringlist.nstrings; ++i) {
      size += id3_render_string(ptr, field->stringlist.strings[i], *encoding,
				(i < field->stringlist.nstrings - 1) ||
				terminate);
    }
    return size;

  case ID3_FIELD_TYPE_LANGUAGE:
    return id3_render_immediate(ptr, field->immediate.value, 3);

  case ID3_FIELD_TYPE_FRAMEID:
    return id3_render_immediate(ptr, field->immediate.value, 4);

  case ID3_FIELD_TYPE_DATE:
    return id3_render_immediate(ptr, field->immediate.value, 8);

  case ID3_FIELD_TYPE_INT32PLUS:
  case ID3_FIELD_TYPE_BINARYDATA:
    return id3_render_binary(ptr, field->binary.data, field->binary.length);
  }

  return 0;
}