char* mp_get_str_bitrate(const mpeg_header *h) { char *buf = (char *)xmallocd0(11, "mp_get_str_bitrate:buf"); if(h->version == 1) /* MPEG 1 */ { switch(h->layer) { case 1: snprintf(buf, sizeof buf, "%d kBit/s", br_1_3[h->bitrate]); return buf; case 2: snprintf(buf, sizeof buf, "%d kBit/s", br_1_2[h->bitrate]); return buf; case 3: snprintf(buf, sizeof buf, "%d kBit/s", br_1_1[h->bitrate]); return buf; default: return "undefined"; } } else /* MPEG 2 */ { switch(h->layer) { case 1: snprintf(buf, sizeof buf, "%d kBit/s", br_2_3[h->bitrate]); return buf; case 2: snprintf(buf, sizeof buf, "%d kBit/s", br_2_2[h->bitrate]); return buf; case 3: snprintf(buf, sizeof buf, "%d kBit/s", br_2_1[h->bitrate]); return buf; default: return "undefined"; } } }
static id3v2_tag* id3v2_get_tag(int fd,int *cancle) { if(1<=*cancle) return NULL; unsigned char *c; id3v2_header *header; id3v2_frame_list *frame_list; id3v2_frame *frame; id3v2_tag *tag = NULL; int i; if(lseek(fd, 0L, SEEK_SET) == -1) return NULL; c = (unsigned char*)xmallocd0(1024, "id3v2_get_tag:c"); if(read(fd, c, 10) < 10) goto exit_on_error; c[10] = 0; if(strncmp(c, "ID3", 3)) goto exit_on_error; header = XMALLOCD0(id3v2_header, "id3v2_get_tag:header"); header->version_minor = c[3]; header->version_revision = c[4]; header->flags = c[5]; header->unsyncronization = (c[5] & 128) >> 7; //[email protected] if( 2!=header->version_minor ) { header->has_extended_header = (c[5] & 64) >> 6; header->is_experimental = (c[5] & 32) >> 5; header->has_footer = (c[5] & 16) >> 4; }
static id3v2_tag* id3v2_get_tag(int fd) { unsigned char *c; id3v2_header *header; id3v2_frame_list *frame_list; id3v2_frame *frame; id3v2_tag *tag = NULL; int i; if(lseek(fd, 0L, SEEK_SET) == -1) return NULL; c = (unsigned char*)xmallocd0(1024, "id3v2_get_tag:c"); if(read(fd, c, 10) < 10) goto exit_on_error; c[10] = 0; if(strncmp(c, "ID3", 3)) goto exit_on_error; header = XMALLOCD0(id3v2_header, "id3v2_get_tag:header"); header->version_minor = c[3]; header->version_revision = c[4]; header->flags = c[5]; header->unsyncronization = (c[5] & 128) >> 7; header->has_extended_header = (c[5] & 64) >> 6; header->is_experimental = (c[5] & 32) >> 5; header->has_footer = (c[5] & 16) >> 4; header->total_tag_size = id3_unsync32(c, 6) + 10; if(header->has_footer) header->total_tag_size += 10; tag = XMALLOCD0(id3v2_tag, "id3v2_get_tag:tag"); /* check if version is supported */ if(c[3] != 3 && c[3] != 4) { xfree(c); tag->header = header; tag->frame_list = NULL; return tag; } frame_list = XMALLOCD0(id3v2_frame_list, "id3v2_get_tag:frame_list"); frame_list->start = frame_list; /* assigning header and frame list to tag */ tag->header = header; tag->frame_list = frame_list; if(header->has_extended_header) { id3v2_extended_header *xt_header = XMALLOCD0(id3v2_extended_header, "id3v2_get_tag:id3v2_extended_header"); header->extended_header = xt_header; read(fd, c, 4); /* get length of extended header */ xt_header->size = id3_unsync32(c, 0); read(fd, c, 1); /* get number of flags */ xt_header->no_flag_bytes = (c[0] > 0) ? c[0] : 1; read(fd, c, xt_header->no_flag_bytes); /* get flag bytes */ xt_header->is_update = (c[0] & 64) >> 6; xt_header->crc_data_present = (c[0] & 32) >> 5; xt_header->restrictions = (c[0] & 16) >> 4; /* Flag data */ if(xt_header->is_update) read(fd, c, 1); /* Data length ind. is 0 -skip */ if(xt_header->crc_data_present) { read(fd, c, 1); /* data length - shoud be 5 */ if(*c != 5) goto exit_on_error; /* else things might break badly */ xt_header->crc_data_length = *c; xt_header->crc_data = xmallocd0(*c, "id3v2_get_tag:xt_header->crc_data"); read(fd, xt_header->crc_data, *c); } if(xt_header->restrictions) { read(fd, c, 1); /* data length - shoud be 1 */ if(*c != 1) goto exit_on_error; xt_header->restrictions_data_length = *c; xt_header->restrictions_data = xmallocd0(*c, "id3v2_get_tag:xt_header->restrictions_data"); read(fd, xt_header->restrictions_data, *c); } }
static int id3v2_add_tag(int fd, id3v2_tag *tag, id3v2_tag *old) { unsigned char *btag, *btag_start; unsigned char flag = 0; int i, j; char *b_tag, *b_tag_start, *d; id3v2_frame_list *frame_list; id3v2_frame *frame; /* at first we are going to write the tags raw data into the btag byte array */ btag = btag_start = xmallocd0(tag->header->total_tag_size, "id3v2_add_tag:btag"); strncpy(btag, "ID3", 3); btag += 3; *btag = (char)tag->header->version_minor; btag += 1; *btag = (char)tag->header->version_revision; btag += 1; flag |= ((tag->header->unsyncronization & 1) << 7); flag |= ((tag->header->has_extended_header & 1) << 6); flag |= ((tag->header->is_experimental & 1) << 5); flag |= ((tag->header->has_footer & 1) << 4); memcpy(btag, &flag, 1); btag += 1; if(old) { i = old->header->total_tag_size - 10; if(old->header->has_footer) i -= 10; } else { i = tag->header->total_tag_size - 10; if(tag->header->has_footer) i -= 10; /* add padding to total size we mean to store on disk */ /* mplib does not use any kind of padding internaly */ i += 1024; } d = id3_sync32(i); btag[0] = d[0]; btag[1] = d[1]; btag[2] = d[2]; btag[3] = d[3]; xfree(d); btag += 4; if(tag->header->has_extended_header) { d = id3_sync32(tag->header->extended_header->size); btag[0] = d[0]; btag[1] = d[1]; btag[2] = d[2]; btag[3] = d[3]; xfree(d); btag += 4; *btag = (char)tag->header->extended_header->no_flag_bytes; btag += 1; flag = ((tag->header->extended_header->is_update & 1) << 6); flag |= ((tag->header->extended_header->crc_data_present & 1) << 5); flag |= ((tag->header->extended_header->restrictions & 1) << 4); memcpy(btag, &flag, 1); btag += 1; if(tag->header->extended_header->is_update) { btag[0] = 0; btag += 1; } if(tag->header->extended_header->crc_data_present) { int length = tag->header->extended_header->crc_data_length ? tag->header->extended_header->crc_data_length : 5; *btag = (char)length; btag += 1; memcpy(btag, tag->header->extended_header->crc_data, length); btag += 1; } if(tag->header->extended_header->restrictions) { int length = tag->header->extended_header->restrictions_data_length ? tag->header->extended_header->restrictions_data_length : 5; *btag = (char)length; btag += 1; memcpy(btag, tag->header->extended_header->restrictions_data, length); btag += 1; } } frame_list = tag->frame_list; while(frame_list) { int j; frame = frame_list->data; strncpy(btag, frame->frame_id, 4); btag += 4; d = id3_sync32(frame->data_size); btag[0] = d[0]; btag[1] = d[1]; btag[2] = d[2]; btag[3] = d[3]; xfree(d); btag += 4; memcpy(btag, &frame->status_flag, 1); btag += 1; memcpy(btag, &frame->format_flag, 1); btag += 1; memcpy(btag, frame->data, frame->data_size); btag += frame->data_size; frame_list = frame_list->next; } /* XXX footer not supported yet */ /* if an old tag was provided it is desired to overwrite it */ /* else this is a brand new tag */ if(old) { FILE *file; void *ptr = xmallocd0(old->header->total_tag_size - tag->header->total_tag_size, "id3v2_add_tag:ptr"); if(!(file = fdopen(fd, "r+b"))) { xfree(ptr); goto exit_on_error; } fseek(file, 0, SEEK_SET); if(fwrite(btag_start, tag->header->total_tag_size, 1, file) < 1) { xfree(ptr); goto exit_on_error; } /* write padding till end of old tag */ if(fwrite(ptr, old->header->total_tag_size - tag->header->total_tag_size, 1, file) < 1) { xfree(ptr); goto exit_on_error; } fflush(file); xfree(ptr); } else { FILE *file, *tmp; int read; void *ptr, *blank; unsigned char *c; ptr = xmallocd(4096, "id3v2_add_tag:ptr"); blank = xmallocd0(1024, "id3v2_add_tag:blank"); file = fdopen(fd, "r+b"); tmp = tmpfile(); if(!(file && tmp)) { fflush(file); fclose(tmp); xfree(ptr); xfree(blank); goto exit_on_error; } fseek(file, 0, SEEK_SET); fseek(tmp, 0, SEEK_SET); /* write tag in tmp file */ fwrite(btag_start, tag->header->total_tag_size, 1, tmp); /* Write 1024b padding */ fwrite(blank, 1024, 1, tmp); /* write rest of file */ while(!feof(file)) { read = fread(ptr, 1, 4096, file); if(fwrite(ptr, 1, read, tmp) != read && !feof(file)) { fflush(file); fclose(tmp); xfree(ptr); xfree(blank); goto exit_on_error; } } fflush(tmp); fseek(file, 0, SEEK_SET); fseek(tmp, 0, SEEK_SET); while(!feof(tmp)) { read = fread(ptr, 1, 4096, tmp); if(fwrite(ptr, 1, read, file) != read && !feof(tmp)) { fflush(file); fclose(tmp); xfree(ptr); xfree(blank); goto exit_on_error; } } fflush(file); fclose(tmp); xfree(ptr); xfree(blank); } xfree(btag_start); return 0; exit_on_error: xfree(btag_start); return MP_EERROR; }
static int id3v1_add_tag(int fd, id3v1_tag *tag) { int i, j; void *blank, *set; char *b_tag, *b_tag_start; blank = xmallocd0(30, "id3v1_add_tag:blank"); set = xmallocd(30, "id3v1_add_tag:set"); memset(set, 0xFF, 30); b_tag = b_tag_start = (char *)xmallocd0(128, "id3v1_add_tag:b_tag"); strncpy(b_tag, "TAG", 3); b_tag += 3; if(tag->title) { j = strlen(tag->title); strncpy(b_tag, tag->title, j); b_tag += j; i = 30 - j; if(i > 0) { strncpy(b_tag, blank, i); b_tag += i; } } else { strncpy(b_tag, blank, 30); b_tag += 30; } if(tag->artist) { j = strlen(tag->artist); strncpy(b_tag, tag->artist, j); b_tag += j; i = 30 - j; if(i > 0) { strncpy(b_tag, blank, i); b_tag += i; } } else { strncpy(b_tag, blank, 30); b_tag += 30; } if(tag->album) { j = strlen(tag->album); strncpy(b_tag, tag->album, j); b_tag += j; i = 30 - j; if(i > 0) { strncpy(b_tag, blank, i); b_tag += i; } } else { strncpy(b_tag, blank, 30); b_tag += 30; } if(tag->year) { j = strlen(tag->year); strncpy(b_tag, tag->year, j); b_tag += j; i = 4 - j; if(i > 0) { strncpy(b_tag, blank, i); b_tag += i; } } else { strncpy(b_tag, blank, 4); b_tag += 4; } if(tag->comment) { int hastrack = 0; j = strlen(tag->comment); if(tag->track > 0) hastrack = 1; if(hastrack && j > 28) { strncpy(b_tag, tag->comment, 28); b_tag += 28; } else { strncpy(b_tag, tag->comment, j); b_tag += j; i = ((tag->track > 0) ? 28 : 30) - j; } if(i > 0) { strncpy(b_tag, blank, i); b_tag += i; } } else { strncpy(b_tag, blank, (tag->track > 0) ? 28 : 30); b_tag += (tag->track > 0) ? 28 : 30; } if(tag->track > 0) { strncpy(b_tag, blank, 1); b_tag += 1; strncpy(b_tag, &(tag->track), 1); b_tag += 1; } if(tag->genre != 0xFF) { strncpy(b_tag, &(tag->genre), 1); b_tag += 1; } else { strncpy(b_tag, set, 1); b_tag += 1; } j = 0; if(lseek(fd, 0L, SEEK_END) != -1) { if(write(fd, b_tag - 128, 128) < 128) j = 1; } else j = 1; xfree(b_tag_start); xfree(blank); xfree(set); return j; }
int mp_set_content(id3_tag* tag, const int field, id3_content* new_content) { id3v1_tag *v1; id3v2_tag *v2; if(!tag) return MP_EERROR; if(tag->version == 2) { return mp_set_content_at_pos(tag, field, new_content, 0); } else if(tag->version == 1) { unsigned char c; char *my_val; int len, j; v1 = tag->tag; switch(field) { #define FLD(str1, str2, str3, str4) \ case str1:\ if(!new_content) v1->str2 = NULL;\ else\ {\ id3_text_content *tc = str4(new_content);\ if(strlen(tc->text) > str3 || tc->encoding != ISO_8859_1)\ {\ mp_convert_to_v2(tag);\ mp_free_text_content(tc);\ return mp_set_content(tag, field, new_content);\ }\ \ v1->str2 = tc->text;\ xfree(tc);\ }\ break; FLD(MP_ARTIST, artist, 30, mp_parse_artist); FLD(MP_TITLE, title, 30, mp_parse_title); FLD(MP_ALBUM, album, 30, mp_parse_album); FLD(MP_YEAR, year, 4, mp_parse_year); case MP_COMMENT: if(!new_content) v1->comment = NULL; else { id3_comment_content *tc = mp_parse_comment(new_content); if(strlen(tc->text) > 30 || tc->short_descr || tc->encoding != ISO_8859_1) { mp_convert_to_v2(tag); mp_free_comment_content(tc); return mp_set_content(tag, field, new_content); } v1->comment = xmallocd0(strlen(tc->text)+1, "mp_set_content:v1->comment"); memcpy(v1->comment, tc->text, strlen(tc->text)); mp_free_comment_content(tc); } break; case MP_TRACK: if(!new_content) v1->track = 0; else { id3_text_content *tc = mp_parse_track(new_content); #ifdef HAVE_STRTOL errno = 0; j = strtol(tc->text, (char **)NULL, 10); if(errno != ERANGE) v1->track = j; else return MP_EERROR; #else v1->track = atoi(tc->text); #endif mp_free_text_content(tc); } break; case MP_GENRE: if(!new_content) v1->genre = 0xFF; else { int b = 0, i; id3_text_content *tc = mp_parse_genre(new_content); /* i = strlen(tc->text); */ for(c = 0; c < GLL; c++) { if(!strcmp(genre_list[c], tc->text)) { v1->genre = c; b = 1; } } mp_free_text_content(tc); if(!b) { mp_convert_to_v2(tag); return mp_set_content(tag, field, new_content); } break; } } } else if(tag->version == -1) return MP_EVERSION; else return MP_EFNF; return 0; }