00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #ifdef HAVE_CONFIG_H
00034 # include "config.h"
00035 #endif
00036
00037 #if STDC_HEADERS
00038 # include <stdlib.h>
00039 # include <string.h>
00040 #elif HAVE_STRINGS_H
00041 # include <strings.h>
00042 #endif
00043
00044 #if HAVE_UNISTD_H
00045 # include <unistd.h>
00046 # include <sys/types.h>
00047 #endif
00048
00049 #include <errno.h>
00050 #include <stdio.h>
00051 #include <fcntl.h>
00052
00053 #include "xmalloc.h"
00054 #include "mplib.h"
00055 #include "mplib_s.h"
00056 #include "mplib_s.c"
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 mpeg_header*
00071 mp_get_mpeg_header_from_file(const char* filename)
00072 {
00073 mpeg_header *ret;
00074 int fd;
00075
00076 if(!filename) return NULL;
00077
00078 fd = open(filename, O_RDONLY);
00079 if(fd == -1) return NULL;
00080
00081 ret = mp_get_mpeg_header_from_fd(fd);
00082 close(fd);
00083 return ret;
00084 }
00085
00086
00087 mpeg_header*
00088 mp_get_mpeg_header_from_fd(int fd)
00089 {
00090 mpeg_header *h;
00091 unsigned char c[5];
00092
00093 h = XMALLOCD(mpeg_header, "mp_get_mpeg_header_from_fd:h");
00094
00095 if(id3_lseek_syncword(fd)) goto exit_on_error;
00096
00097 if(read(fd, c, 4) < 4) goto exit_on_error;
00098
00099 memset(h, 0, sizeof(h));
00100 h->syncword = (c[1] & 240);
00101 h->syncword <<= 8;
00102 h->syncword |= c[0];
00103 h->version = (c[1] & 8) >> 3;
00104 h->layer = (c[1] & 6) >> 1;
00105 h->protbit = (c[1] & 1);
00106 h->bitrate = (c[2] & 240) >> 4;
00107 h->samplingfreq = (c[2] & 12) >> 2;
00108 h->padbit = (c[2] & 2) >> 1;
00109 h->privbit = (c[2] & 1);
00110 h->mode = (c[3] & 192) >> 6;
00111 h->mode_ext = (c[3] & 48) >> 4;
00112 h->copyright = (c[3] & 8) >> 3;
00113 h->originalhome = (c[3] & 4) >> 2;
00114 h->emphasis = (c[3] & 3);
00115
00116 return h;
00117
00118 exit_on_error:
00119 xfree(h);
00120 return NULL;
00121 }
00122
00123 char*
00124 mp_get_str_version(const mpeg_header *h)
00125 {
00126 return h->version == 0 ? "MPEG 2" : "MPEG 1";
00127 }
00128
00129 char*
00130 mp_get_str_layer(const mpeg_header *h)
00131 {
00132 switch(h->layer)
00133 {
00134 case 1: return "Layer III";
00135 case 2: return "Layer II";
00136 case 3: return "Layer I";
00137 default: return "undefined";
00138 }
00139 }
00140
00141 char*
00142 mp_get_str_bitrate(const mpeg_header *h)
00143 {
00144 char *buf = (char *)xmallocd0(11, "mp_get_str_bitrate:buf");
00145
00146 if(h->version == 1)
00147 {
00148 switch(h->layer)
00149 {
00150 case 1:
00151 snprintf(buf, sizeof buf, "%d kBit/s", br_1_3[h->bitrate]);
00152 return buf;
00153 case 2:
00154 snprintf(buf, sizeof buf, "%d kBit/s", br_1_2[h->bitrate]);
00155 return buf;
00156 case 3:
00157 snprintf(buf, sizeof buf, "%d kBit/s", br_1_1[h->bitrate]);
00158 return buf;
00159 default:
00160 return "undefined";
00161 }
00162 }
00163 else
00164 {
00165 switch(h->layer)
00166 {
00167 case 1:
00168 snprintf(buf, sizeof buf, "%d kBit/s", br_2_3[h->bitrate]);
00169 return buf;
00170 case 2:
00171 snprintf(buf, sizeof buf, "%d kBit/s", br_2_2[h->bitrate]);
00172 return buf;
00173 case 3:
00174 snprintf(buf, sizeof buf, "%d kBit/s", br_2_1[h->bitrate]);
00175 return buf;
00176 default:
00177 return "undefined";
00178 }
00179 }
00180 }
00181
00182 char*
00183 mp_get_str_samplingfreq(const mpeg_header *h)
00184 {
00185 if(h->version == 1)
00186 {
00187 switch(h->samplingfreq)
00188 {
00189 case 0: return "44100 Hz";
00190 case 1: return "48000 Hz";
00191 case 2: return "32000 Hz";
00192 default: return "undefined";
00193 }
00194 }
00195 else
00196 {
00197 switch(h->samplingfreq)
00198 {
00199 case 0: return "22050 Hz";
00200 case 1: return "24000 Hz";
00201 case 2: return "16000 Hz";
00202 default: return "undefined";
00203 }
00204 }
00205 }
00206
00207 char*
00208 mp_get_str_mode(const mpeg_header *h)
00209 {
00210 switch(h->mode)
00211 {
00212 case 0: return "Stereo";
00213 case 1: return "Joint-Stereo";
00214 case 2: return "Dual-Channel";
00215 case 3: return "Mono";
00216 default: return "undefined";
00217 }
00218 }
00219
00220 id3_tag_list*
00221 mp_get_tag_list_from_mem(void *buf, size_t size)
00222 {
00223 mem_arg arg;
00224
00225 arg.buf = buf;
00226 arg.size = size;
00227 arg.act = buf;
00228
00229 return mp_get_tag_list(read_mem, lseek_mem, &arg);
00230 }
00231
00232 id3_tag_list*
00233 mp_get_tag_list_from_file(const char* filename)
00234 {
00235 id3_tag_list *ret;
00236 int fd;
00237
00238 if(!filename) return NULL;
00239
00240 fd = open(filename, O_RDONLY);
00241 if(fd == -1) return NULL;
00242
00243 ret = mp_get_tag_list_from_fd(fd);
00244
00245 close(fd);
00246 return ret;
00247 }
00248
00249 id3_tag_list*
00250 mp_get_tag_list_from_fd(int fd)
00251 {
00252 file_arg arg;
00253
00254 arg.fd = fd;
00255 return mp_get_tag_list(read_file, lseek_file, &arg);
00256 }
00257
00258 id3_tag_list*
00259 mp_get_tag_list(size_t (*read_func)(void *, size_t, void *),
00260 off_t (*lseek_func)(off_t, int, void *),
00261 void *arg)
00262 {
00263 id3_tag_list *tag_list = NULL;
00264 id3_tag_list *tag_list2 = NULL;
00265 id3v2_tag *v2tag = NULL;
00266 id3v1_tag *v1tag = NULL;
00267 id3_tag *tag = NULL;
00268
00269 v2tag = id3v2_get_tag(read_func, lseek_func, arg);
00270 if(v2tag)
00271 {
00272 tag = XMALLOCD0(id3_tag, "mp_get_tag_list:tag");
00273 if(v2tag->header->version_minor == 3 || v2tag->header->version_minor == 4)
00274 tag->version = 2;
00275 else
00276 tag->version = -1;
00277 tag->tag = v2tag;
00278
00279 tag_list = XMALLOCD(id3_tag_list, "mp_get_tag_list:tag_list");
00280 tag_list->tag = tag;
00281 tag_list->next = NULL;
00282 tag_list->first = tag_list;
00283 }
00284
00285 v1tag = id3v1_get_tag(read_func, lseek_func, arg);
00286 if(v1tag)
00287 {
00288 tag = XMALLOCD(id3_tag, "mp_get_tag_list:tag");
00289 tag->version = 1;
00290 tag->tag = v1tag;
00291
00292 if(tag_list)
00293 {
00294 tag_list2 = XMALLOCD(id3_tag_list, "mp_get_tag_list:tag_list2");
00295 tag_list2->tag = tag;
00296 tag_list2->next = NULL;
00297 tag_list2->first = tag_list;
00298 tag_list->next = tag_list2;
00299 }
00300 else
00301 {
00302 tag_list = XMALLOCD(id3_tag_list, "mp_get_tag_list:tag_list");
00303 tag_list->tag = tag;
00304 tag_list->next = NULL;
00305 tag_list->first = tag_list;
00306 }
00307 }
00308
00309 return tag_list;
00310
00311 }
00312
00313 id3_content*
00314 mp_get_content(const id3_tag *tag, int field)
00315 {
00316 return mp_get_content_at_pos(tag, field, 0);
00317 }
00318
00319 id3_content*
00320 mp_get_content_at_pos(const id3_tag *tag, int field, int pos)
00321 {
00322 int i;
00323 char *c;
00324 id3_content *ret;
00325
00326 if(!tag || !tag->tag)
00327 {
00328 errno = MP_EERROR;
00329 return NULL;
00330 }
00331
00332 if(tag->version == 1)
00333 {
00334 if(pos != 0)
00335 {
00336 errno = MP_EERROR;
00337 return NULL;
00338 }
00339 else return id3v1_get_content(tag->tag, field);
00340 }
00341 else if(tag->version == 2)
00342 {
00343 id3v2_tag *v2 = tag->tag;
00344 char *val;
00345
00346 switch(field)
00347 {
00348 case MP_ARTIST:
00349 return mp_get_content_custom_at_pos(tag, "TPE1", pos);
00350 case MP_TITLE:
00351 return mp_get_content_custom_at_pos(tag, "TIT2", pos);
00352 case MP_ALBUM:
00353 return mp_get_content_custom_at_pos(tag, "TALB", pos);
00354 case MP_GENRE:
00355 return mp_get_content_custom_at_pos(tag, "TCON", pos);
00356 case MP_COMMENT:
00357 return mp_get_content_custom_at_pos(tag, "COMM", pos);
00358 case MP_YEAR:
00359 return mp_get_content_custom_at_pos(tag, "TYER", pos);
00360 case MP_TRACK:
00361 return mp_get_content_custom_at_pos(tag, "TRCK", pos);
00362 }
00363 errno = MP_EFNF;
00364 return NULL;
00365 }
00366 else
00367 {
00368 errno = MP_EVERSION;
00369 return NULL;
00370 }
00371 }
00372
00373 id3_content*
00374 mp_get_content_custom(const id3_tag* tag, const char*field)
00375 {
00376 if(!tag)
00377 {
00378 errno = MP_EERROR;
00379 return NULL;
00380 }
00381 else if(tag->version != 2)
00382 {
00383 errno = MP_EVERSION;
00384 return NULL;
00385 }
00386
00387 return id3v2_get_content_at_pos(tag->tag, field, 0);
00388
00389 }
00390
00391 id3_content*
00392 mp_get_content_custom_at_pos(const id3_tag* tag, const char*field, int pos)
00393 {
00394 if(!tag)
00395 {
00396 errno = MP_EERROR;
00397 return NULL;
00398 }
00399 else if(tag->version != 2)
00400 {
00401 errno = MP_EVERSION;
00402 return NULL;
00403 }
00404
00405
00406 return id3v2_get_content_at_pos(tag->tag, field, pos);
00407 }
00408
00409
00410
00411
00412
00413
00414 int
00415 mp_set_content(id3_tag* tag, const int field, id3_content* new_content)
00416 {
00417 id3v1_tag *v1;
00418 id3v2_tag *v2;
00419
00420
00421 if(!tag) return MP_EERROR;
00422
00423 if(tag->version == 2)
00424 {
00425 return mp_set_content_at_pos(tag, field, new_content, 0);
00426 }
00427 else if(tag->version == 1)
00428 {
00429 unsigned char c;
00430 char *my_val;
00431 int len, j;
00432
00433 v1 = tag->tag;
00434
00435 switch(field)
00436 {
00437
00438 #define FLD(str1, str2, str3, str4) \
00439 case str1:\
00440 if(!new_content) v1->str2 = NULL;\
00441 else\
00442 {\
00443 id3_text_content *tc = str4(new_content);\
00444 if(strlen(tc->text) > str3 || tc->encoding != ISO_8859_1)\
00445 {\
00446 mp_convert_to_v2(tag);\
00447 mp_free_text_content(tc);\
00448 return mp_set_content(tag, field, new_content);\
00449 }\
00450 \
00451 v1->str2 = tc->text;\
00452 xfree(tc);\
00453 }\
00454 break;
00455
00456 FLD(MP_ARTIST, artist, 30, mp_parse_artist);
00457 FLD(MP_TITLE, title, 30, mp_parse_title);
00458 FLD(MP_ALBUM, album, 30, mp_parse_album);
00459 FLD(MP_YEAR, year, 4, mp_parse_year);
00460
00461 case MP_COMMENT:
00462 if(!new_content) v1->comment = NULL;
00463 else
00464 {
00465 id3_comment_content *tc = mp_parse_comment(new_content);
00466 if(strlen(tc->text) > 30 || tc->short_descr || tc->encoding != ISO_8859_1)
00467 {
00468 mp_convert_to_v2(tag);
00469 mp_free_comment_content(tc);
00470 return mp_set_content(tag, field, new_content);
00471 }
00472 v1->comment = xmallocd0(strlen(tc->text)+1,
00473 "mp_set_content:v1->comment");
00474 memcpy(v1->comment, tc->text, strlen(tc->text));
00475 mp_free_comment_content(tc);
00476 }
00477 break;
00478
00479 case MP_TRACK:
00480 if(!new_content) v1->track = 0;
00481 else
00482 {
00483 id3_text_content *tc = mp_parse_track(new_content);
00484 #ifdef HAVE_STRTOL
00485 errno = 0;
00486 j = strtol(tc->text, (char **)NULL, 10);
00487 if(errno != ERANGE) v1->track = j;
00488 else return MP_EERROR;
00489 #else
00490 v1->track = atoi(tc->text);
00491 #endif
00492 mp_free_text_content(tc);
00493 }
00494 break;
00495
00496 case MP_GENRE:
00497 if(!new_content) v1->genre = 0xFF;
00498 else
00499 {
00500 int b = 0, i;
00501 id3_text_content *tc = mp_parse_genre(new_content);
00502
00503 for(c = 0; c < GLL; c++) {
00504 if(!strcmp(genre_list[c], tc->text))
00505 {
00506 v1->genre = c;
00507 b = 1;
00508 }
00509 }
00510 mp_free_text_content(tc);
00511 if(!b)
00512 {
00513 mp_convert_to_v2(tag);
00514 return mp_set_content(tag, field, new_content);
00515 }
00516 break;
00517 }
00518 }
00519 }
00520 else if(tag->version == -1) return MP_EVERSION;
00521 else return MP_EFNF;
00522
00523 return 0;
00524 }
00525
00526 int
00527 mp_set_content_at_pos(id3_tag* tag, const int field, id3_content* new_content, int pos)
00528 {
00529 char* c;
00530
00531 if(!tag) return MP_EERROR;
00532 if(field < MP_ARTIST || field > MP_TRACK) return MP_EFNF;
00533
00534 if(tag->version == 1 && pos == 0) return mp_set_content(tag, field, new_content);
00535
00536 switch(field)
00537 {
00538 case MP_ARTIST: c = "TPE1"; break;
00539 case MP_TITLE: c = "TIT2"; break;
00540 case MP_ALBUM: c = "TALB"; break;
00541 case MP_TRACK: c = "TRCK"; break;
00542 case MP_YEAR: c = "TYER"; break;
00543 case MP_COMMENT: c = "COMM"; break;
00544 case MP_GENRE: c = "TCON"; break;
00545 }
00546 return mp_set_custom_content_at_pos(tag, c, new_content, pos);
00547 }
00548
00549 int
00550 mp_set_custom_content(id3_tag* tag, char* field, id3_content* new_content)
00551 {
00552 return mp_set_custom_content_at_pos(tag, field, new_content, 0);
00553 }
00554
00555 int
00556 mp_set_custom_content_at_pos(id3_tag* tag, char* field, id3_content* new_content, int pos)
00557 {
00558 id3v2_tag *v2;
00559
00560 if(!tag || !field || strlen(field) != 4) return MP_EERROR;
00561
00562 if(tag->version == 1)
00563 {
00564 if(mp_convert_to_v2(tag))
00565 return MP_EERROR;
00566 }
00567 else if(tag->version == -1) return MP_EVERSION;
00568
00569 v2 = (id3v2_tag*)tag->tag;
00570 if(!v2->frame_list)
00571 {
00572 v2->frame_list = XMALLOCD0(id3v2_frame_list,
00573 "mp_set_custom_content_at_pos:v2->frame_list");
00574 id3_add_frame(v2->frame_list, field, new_content->data, new_content->length);
00575 }
00576 else
00577 {
00578 id3v2_frame *frame;
00579
00580 if((frame = id3_lookup_frame(v2->frame_list, field, pos)))
00581 {
00582 if(new_content)
00583 {
00584 long len, len_sync;
00585
00586 len = new_content->length;
00587 len_sync = id3_sync(new_content->data, len);
00588
00589 xfree(frame->data);
00590 frame->data = xmallocd(new_content->length,
00591 "mp_set_custom_content_at_pos:frame->data");
00592 memcpy(frame->data, new_content->data, new_content->length);
00593 frame->status_flag = 0;
00594 if(len != len_sync) frame->format_flag = 64;
00595 else frame->format_flag = 0;
00596 frame->data_size = len_sync;
00597 }
00598 else id3_remove_frame(v2->frame_list, frame);
00599 }
00600 else if(pos == 0) id3_add_frame(v2->frame_list, field, new_content->data, new_content->length);
00601 else return MP_EFNF;
00602 }
00603
00604 return 0;
00605 }
00606
00607
00608
00609
00610 int
00611 mp_write_to_file(const id3_tag_list* tag_list, const char *filename)
00612 {
00613 int ret;
00614 int fd;
00615
00616 if(!filename) return MP_EERROR;
00617
00618 fd = open(filename, O_RDWR);
00619 if(fd == -1) return MP_EERROR;
00620
00621 ret = mp_write_to_fd(tag_list, fd);
00622 close(fd);
00623 return ret;
00624 }
00625
00626
00627 int
00628 mp_write_to_fd(const id3_tag_list* tag_list, const int fd)
00629 {
00630 id3_tag *tag;
00631 id3v1_tag *v1;
00632 id3v2_tag *v2;
00633 id3_tag_list *mylist;
00634 int ret = 0;
00635 file_arg arg;
00636
00637 if(!tag_list) {
00638 ret |= id3v1_del_tag(fd);
00639 ret |= id3v2_del_tag(fd, NULL);
00640 return ret;
00641 }
00642
00643 while(tag_list)
00644 {
00645 tag = tag_list->tag;
00646 if(!tag)
00647 {
00648 tag_list = tag_list->next;
00649 continue;
00650 }
00651
00652 if(tag->version == 1)
00653 {
00654 id3v1_del_tag(fd);
00655 ret |= id3v1_add_tag(fd, tag->tag);
00656 }
00657 else if(tag->version == 2)
00658 {
00659 int pad = 0;
00660 id3v2_frame_list *frame_list;
00661 id3v2_tag *old_v2;
00662 id3v2_tag *v2 = tag->tag;
00663
00664
00665 v2->header->total_tag_size = 10;
00666 if(v2->header->has_footer) v2->header->total_tag_size += 10;
00667 if(v2->header->has_extended_header) v2->header->total_tag_size += v2->header->extended_header->size;
00668 frame_list = v2->frame_list;
00669 while(frame_list)
00670 {
00671 v2->header->total_tag_size += frame_list->data->data_size + 10;
00672 frame_list = frame_list->next;
00673 }
00674
00675
00676
00677 arg.fd = fd;
00678 old_v2 = id3v2_get_tag(read_file, lseek_file, &arg);
00679 if(old_v2) {
00680 if(v2->header->total_tag_size > old_v2->header->total_tag_size)
00681 {
00682
00683 ret |= id3v2_del_tag(fd, old_v2);
00684 ret |= id3v2_add_tag(fd, v2, NULL);
00685 }
00686 else
00687 {
00688 ret |= id3v2_add_tag(fd, v2, old_v2);
00689 }
00690 id3v2_free_tag(old_v2);
00691 } else {
00692 ret |= id3v2_add_tag(fd, v2, NULL);
00693 }
00694
00695 }
00696 else
00697 {
00698 ret |= MP_EVERSION;
00699 }
00700
00701 tag_list = tag_list->next;
00702 }
00703
00704 return ret;
00705 }
00706
00707 int
00708 mp_del_tags_from_file(const char* filename)
00709 {
00710 int ret, fd;
00711
00712 if(!filename) return 1;
00713
00714 fd = open(filename, O_RDWR);
00715 if(fd == -1) return 1;
00716
00717 ret = mp_del_tags_from_fd(fd);
00718 close(fd);
00719 return ret;
00720 }
00721
00722 int
00723 mp_del_tags_from_fd(const int fd)
00724 {
00725 int ret = 0;
00726
00727 ret |= id3v1_del_tag(fd);
00728 ret |= id3v2_del_tag(fd, NULL);
00729
00730 return ret;
00731 }
00732
00733 int
00734 mp_del_tags_by_ver_from_file(const char* filename, const int version)
00735 {
00736 int fd, ret;
00737
00738 if(!filename) return 1;
00739
00740 fd = open(filename, O_RDWR);
00741 if(fd == -1) return 1;
00742
00743 ret = mp_del_tags_by_ver_from_fd(fd, version);
00744 close(fd);
00745 return ret;
00746 }
00747
00748 int
00749 mp_del_tags_by_ver_from_fd(const int fd, const int version)
00750 {
00751 if(version == 1) return id3v1_del_tag(fd);
00752 else if(version == 2) return id3v2_del_tag(fd, NULL);
00753 else return MP_EVERSION;
00754 }
00755
00756
00757
00758
00759
00760
00761
00762
00763 int
00764 mp_convert_to_v2(id3_tag *tag)
00765 {
00766 id3v1_tag *v1;
00767 id3_tag *tmp;
00768 id3_content* content;
00769
00770 if(tag->version == 2) return 0;
00771 else if(tag->version == -1) return MP_EVERSION;
00772
00773 tmp = mp_alloc_tag_with_version(2);
00774
00775 v1 = (id3v1_tag*)tag->tag;
00776
00777 content = mp_assemble_text_content(v1->artist, ISO_8859_1);
00778 if(v1->artist) mp_set_content(tmp, MP_ARTIST, content);
00779
00780 content = mp_assemble_text_content(v1->title, ISO_8859_1);
00781 if(v1->title) mp_set_content(tmp, MP_TITLE, content);
00782
00783 content = mp_assemble_text_content(v1->album, ISO_8859_1);
00784 if(v1->album) mp_set_content(tmp, MP_ALBUM, content);
00785
00786 content = mp_assemble_text_content(v1->year, ISO_8859_1);
00787 if(v1->year) mp_set_content(tmp, MP_YEAR, content);
00788
00789 content = mp_assemble_comment_content(v1->comment, NULL, ISO_8859_1, NULL);
00790 if(v1->comment) mp_set_content(tmp, MP_COMMENT, content);
00791
00792 if(v1->genre != 0xFF)
00793 {
00794 char *c = xmallocd(strlen(genre_list[v1->genre]) + 1,
00795 "mp_convert_to_v2:c");
00796 strcpy(c, genre_list[v1->genre]);
00797 content = mp_assemble_text_content(c, ISO_8859_1);
00798 mp_set_content(tmp, MP_GENRE, content);
00799 }
00800 if(v1->track > 0)
00801 {
00802 char *trk = (char *)xmallocd(4, "mp_convert_to_v2:trk");
00803 snprintf(trk, 3, "%d", v1->track);
00804 trk[3] = 0;
00805 content = mp_assemble_text_content(trk, ISO_8859_1);
00806 mp_set_content(tmp, MP_TRACK, content);
00807 }
00808
00809 tag->version = 2;
00810 tag->tag = tmp->tag;
00811
00812 id3v1_free_tag(v1);
00813 xfree(tmp);
00814
00815 return 0;
00816 }
00817
00818 int
00819 mp_convert_to_v1(id3_tag *tag)
00820 {
00821 id3v1_tag *v1;
00822 id3_tag* tmp;
00823 id3_content* content;
00824 id3_text_content* tc;
00825 id3_comment_content* cc;
00826 char* c;
00827 int j, k = 0;
00828
00829 if(tag->version == 1) return 0;
00830 else if(tag->version == -1) return MP_EVERSION;
00831
00832 v1 = XMALLOCD0(id3v1_tag, "mp_convert_to_v1:v1");
00833
00834 content = mp_get_content(tag, MP_ARTIST);
00835 tc = mp_parse_artist(content);
00836 v1->artist = tc->text;
00837 xfree(tc);
00838 mp_free_content(content);
00839
00840 content = mp_get_content(tag, MP_TITLE);
00841 tc = mp_parse_title(content);
00842 v1->title = tc->text;
00843 xfree(tc);
00844 mp_free_content(content);
00845
00846 content = mp_get_content(tag, MP_ALBUM);
00847 tc = mp_parse_album(content);
00848 v1->album = tc->text;
00849 xfree(tc);
00850 mp_free_content(content);
00851
00852 content = mp_get_content(tag, MP_YEAR);
00853 tc = mp_parse_year(content);
00854 v1->year = tc->text;
00855 xfree(tc);
00856 mp_free_content(content);
00857
00858 content = mp_get_content(tag, MP_COMMENT);
00859 cc = mp_parse_comment(content);
00860 v1->comment = cc->text;
00861 xfree(cc->language);
00862 xfree(cc->short_descr);
00863 xfree(cc);
00864 mp_free_content(content);
00865
00866 content = mp_get_content(tag, MP_TRACK);
00867 tc = mp_parse_track(content);
00868 c = tc->text;
00869 if(c)
00870 {
00871 #ifdef HAVE_STRTOL
00872 errno = 0;
00873 j = strtol(c, (char **)NULL, 10);
00874 if(errno != ERANGE) v1->track = j;
00875 else v1->track = 0;
00876 #else
00877 v1->track = atoi(c);
00878 #endif
00879 }
00880 else v1->track = 0;
00881 mp_free_text_content(tc);
00882 mp_free_content(content);
00883
00884 content = mp_get_content(tag, MP_GENRE);
00885 tc = mp_parse_genre(content);
00886 c = tc->text;
00887 for(j = 0; c, j < GLL; j++) {
00888 if(!strcmp(genre_list[j], c))
00889 {
00890 v1->genre = j;
00891 k = 1;
00892 }
00893 }
00894 if(!c) v1->genre = 0xFF;
00895 mp_free_text_content(tc);
00896 mp_free_content(content);
00897
00898 id3v1_truncate_tag(v1);
00899
00900 id3v2_free_tag(tag->tag);
00901
00902 tag->version = 1;
00903 tag->tag = v1;
00904
00905 return 0;
00906 }
00907
00908 int
00909 mp_is_valid_v1_value(int field, char *value)
00910 {
00911 int len = 30;
00912 int j;
00913
00914 switch(field) {
00915 case MP_YEAR:
00916 len = 4;
00917 break;
00918
00919 case MP_TRACK:
00920 #ifdef HAVE_STRTOL
00921 errno = 0;
00922 j = strtol(value, (char **)NULL, 10);
00923 if(errno != ERANGE) return 1;
00924 else return 0;
00925 #else
00926 return 1;
00927 #endif
00928
00929 case MP_GENRE:
00930 for(j = 0; j < GLL; j++) {
00931 if(!strcmp(genre_list[j], value))
00932 {
00933 return 1;
00934 }
00935 return 0;
00936 }
00937 }
00938
00939
00940 if(strlen(value) > len) return 0;
00941 else return 1;
00942 }
00943
00944
00945 void
00946 mp_free_list(id3_tag_list *list)
00947 {
00948 if(!list) return;
00949
00950
00951 if(list->tag) mp_free_tag(list->tag);
00952
00953
00954 if(list->next) mp_free_list(list->next);
00955
00956
00957 xfree(list);
00958 }
00959
00960 id3_tag*
00961 mp_alloc_tag(void)
00962 {
00963
00964
00965
00966 return mp_alloc_tag_with_version(1);
00967 }
00968
00969 id3_tag*
00970 mp_alloc_tag_with_version(int v)
00971 {
00972 id3_tag* ret;
00973
00974 if(v != 1 && v != 2) return NULL;
00975
00976 ret = XMALLOCD(id3_tag, "mp_alloc_tag_with_version:ret");
00977 ret->version = v;
00978 if(v == 1)
00979 {
00980 ret->tag = XMALLOCD0(id3v1_tag, "mp_alloc_tag_with_version:ret->tag");
00981 ((id3v1_tag*)ret->tag)->genre = 0xFF;
00982 }
00983 else
00984 {
00985 id3v2_tag *v2;
00986
00987 ret->tag = XMALLOCD0(id3v2_tag, "mp_alloc_tag_with_version:ret->tag");
00988 v2 = (id3v2_tag*)ret->tag;
00989 v2->header = XMALLOCD0(id3v2_header, "mp_alloc_tag_with_version:v2->header");
00990
00991 v2->header->version_minor = 4;
00992
00993 v2->header->version_minor = 3;
00994
00995 v2->header->version_revision = 0;
00996 v2->header->unsyncronization = 1;
00997 v2->header->has_extended_header = 0;
00998 v2->header->is_experimental = 1;
00999 v2->header->has_footer = 0;
01000 v2->header->flags = 0;
01001 v2->header->total_tag_size = 0;
01002 v2->header->extended_header = NULL;
01003 v2->frame_list = NULL;
01004 }
01005 return ret;
01006 }
01007
01008 void
01009 mp_free_tag(id3_tag *tag)
01010 {
01011 if(!tag) return;
01012
01013 if(tag->version == 1)
01014 {
01015 id3v1_free_tag(tag->tag);
01016 }
01017 else if(tag->version == 2)
01018 {
01019 id3v2_free_tag(tag->tag);
01020 }
01021 xfree(tag);
01022 }
01023
01024 void
01025 mp_free_content(id3_content *content)
01026 {
01027 if(!content) return;
01028 xfree(content->data);
01029 xfree(content);
01030 }
01031
01032 void
01033 mp_free_text_content(id3_text_content *content)
01034 {
01035 if(!content) return;
01036 xfree(content->text);
01037 xfree(content);
01038 }
01039
01040 void
01041 mp_free_comment_content(id3_comment_content *content)
01042 {
01043 if(!content) return;
01044 xfree(content->language);
01045 xfree(content->short_descr);
01046 xfree(content->text);
01047 xfree(content);
01048 }
01049
01050