~ubuntu-branches/ubuntu/raring/flac/raring

« back to all changes in this revision

Viewing changes to src/libFLAC/metadata_object.c

  • Committer: Bazaar Package Importer
  • Author(s): Joshua Kwan
  • Date: 2007-05-29 22:56:36 UTC
  • mto: (8.1.1 lenny)
  • mto: This revision was merged to the branch mainline in revision 9.
  • Revision ID: james.westby@ubuntu.com-20070529225636-p8lkii0r0kp50pns
Tags: upstream-1.1.4
ImportĀ upstreamĀ versionĀ 1.1.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* libFLAC - Free Lossless Audio Codec library
2
 
 * Copyright (C) 2001,2002,2003,2004,2005  Josh Coalson
 
2
 * Copyright (C) 2001,2002,2003,2004,2005,2006,2007  Josh Coalson
3
3
 *
4
4
 * Redistribution and use in source and binary forms, with or without
5
5
 * modification, are permitted provided that the following conditions
29
29
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
30
 */
31
31
 
 
32
#if HAVE_CONFIG_H
 
33
#  include <config.h>
 
34
#endif
 
35
 
32
36
#include <stdlib.h>
33
37
#include <string.h>
34
38
 
43
47
 *
44
48
 ***************************************************************************/
45
49
 
 
50
/* copy bytes:
 
51
 *  from = NULL  && bytes = 0
 
52
 *       to <- NULL
 
53
 *  from != NULL && bytes > 0
 
54
 *       to <- copy of from
 
55
 *  else ASSERT
 
56
 * malloc error leaved 'to' unchanged
 
57
 */
46
58
static FLAC__bool copy_bytes_(FLAC__byte **to, const FLAC__byte *from, unsigned bytes)
47
59
{
 
60
        FLAC__ASSERT(0 != to);
48
61
        if(bytes > 0 && 0 != from) {
49
62
                FLAC__byte *x;
50
63
                if(0 == (x = (FLAC__byte*)malloc(bytes)))
60
73
        return true;
61
74
}
62
75
 
 
76
#if 0 /* UNUSED */
 
77
/* like copy_bytes_(), but free()s the original '*to' if the copy succeeds and the original '*to' is non-NULL */
 
78
static FLAC__bool free_copy_bytes_(FLAC__byte **to, const FLAC__byte *from, unsigned bytes)
 
79
{
 
80
        FLAC__byte *copy;
 
81
        FLAC__ASSERT(0 != to);
 
82
        if(copy_bytes_(&copy, from, bytes)) {
 
83
                if(*to)
 
84
                        free(*to);
 
85
                *to = copy;
 
86
                return true;
 
87
        }
 
88
        else
 
89
                return false;
 
90
}
 
91
#endif
 
92
 
 
93
/* reallocate entry to 1 byte larger and add a terminating NUL */
 
94
/* realloc() failure leaves entry unchanged */
63
95
static FLAC__bool ensure_null_terminated_(FLAC__byte **entry, unsigned length)
64
96
{
65
97
        FLAC__byte *x = (FLAC__byte*)realloc(*entry, length+1);
72
104
                return false;
73
105
}
74
106
 
 
107
/* copies the NUL-terminated C-string 'from' to '*to', leaving '*to'
 
108
 * unchanged if malloc fails, free()ing the original '*to' if it
 
109
 * succeeds and the original '*to' was not NULL
 
110
 */
 
111
static FLAC__bool copy_cstring_(char **to, const char *from)
 
112
{
 
113
        char *copy = strdup(from);
 
114
        FLAC__ASSERT(to);
 
115
        if(copy) {
 
116
                if(*to)
 
117
                        free(*to);
 
118
                *to = copy;
 
119
                return true;
 
120
        }
 
121
        else
 
122
                return false;
 
123
}
 
124
 
75
125
static FLAC__bool copy_vcentry_(FLAC__StreamMetadata_VorbisComment_Entry *to, const FLAC__StreamMetadata_VorbisComment_Entry *from)
76
126
{
77
127
        to->length = from->length;
413
463
                                */
414
464
                                break;
415
465
                        case FLAC__METADATA_TYPE_VORBIS_COMMENT:
416
 
                                {
417
 
                                        object->data.vorbis_comment.vendor_string.length = (unsigned)strlen(FLAC__VENDOR_STRING);
418
 
                                        if(!copy_bytes_(&object->data.vorbis_comment.vendor_string.entry, (const FLAC__byte*)FLAC__VENDOR_STRING, object->data.vorbis_comment.vendor_string.length+1)) {
419
 
                                                free(object);
420
 
                                                return 0;
421
 
                                        }
422
 
                                        vorbiscomment_calculate_length_(object);
 
466
                                object->data.vorbis_comment.vendor_string.length = (unsigned)strlen(FLAC__VENDOR_STRING);
 
467
                                if(!copy_bytes_(&object->data.vorbis_comment.vendor_string.entry, (const FLAC__byte*)FLAC__VENDOR_STRING, object->data.vorbis_comment.vendor_string.length+1)) {
 
468
                                        free(object);
 
469
                                        return 0;
423
470
                                }
 
471
                                vorbiscomment_calculate_length_(object);
424
472
                                break;
425
473
                        case FLAC__METADATA_TYPE_CUESHEET:
426
474
                                cuesheet_calculate_length_(object);
427
475
                                break;
 
476
                        case FLAC__METADATA_TYPE_PICTURE:
 
477
                                object->length = (
 
478
                                        FLAC__STREAM_METADATA_PICTURE_TYPE_LEN +
 
479
                                        FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN + /* empty mime_type string */
 
480
                                        FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN + /* empty description string */
 
481
                                        FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN +
 
482
                                        FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN +
 
483
                                        FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN +
 
484
                                        FLAC__STREAM_METADATA_PICTURE_COLORS_LEN +
 
485
                                        FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN +
 
486
                                        0 /* no data */
 
487
                                ) / 8;
 
488
                                object->data.picture.type = FLAC__STREAM_METADATA_PICTURE_TYPE_OTHER;
 
489
                                object->data.picture.mime_type = 0;
 
490
                                object->data.picture.description = 0;
 
491
                                /* calloc() took care of this for us:
 
492
                                object->data.picture.width = 0;
 
493
                                object->data.picture.height = 0;
 
494
                                object->data.picture.depth = 0;
 
495
                                object->data.picture.colors = 0;
 
496
                                object->data.picture.data_length = 0;
 
497
                                object->data.picture.data = 0;
 
498
                                */
 
499
                                /* now initialize mime_type and description with empty strings to make things easier on the client */
 
500
                                if(!copy_cstring_(&object->data.picture.mime_type, "")) {
 
501
                                        free(object);
 
502
                                        return 0;
 
503
                                }
 
504
                                if(!copy_cstring_((char**)(&object->data.picture.description), "")) {
 
505
                                        if(object->data.picture.mime_type)
 
506
                                                free(object->data.picture.mime_type);
 
507
                                        free(object);
 
508
                                        return 0;
 
509
                                }
 
510
                                break;
428
511
                        default:
429
512
                                /* calloc() took care of this for us:
430
513
                                object->length = 0;
504
587
                                        }
505
588
                                }
506
589
                                break;
 
590
                        case FLAC__METADATA_TYPE_PICTURE:
 
591
                                to->data.picture.type = object->data.picture.type;
 
592
                                if(!copy_cstring_(&to->data.picture.mime_type, object->data.picture.mime_type)) {
 
593
                                        FLAC__metadata_object_delete(to);
 
594
                                        return 0;
 
595
                                }
 
596
                                if(!copy_cstring_((char**)(&to->data.picture.description), (const char*)object->data.picture.description)) {
 
597
                                        FLAC__metadata_object_delete(to);
 
598
                                        return 0;
 
599
                                }
 
600
                                to->data.picture.width = object->data.picture.width;
 
601
                                to->data.picture.height = object->data.picture.height;
 
602
                                to->data.picture.depth = object->data.picture.depth;
 
603
                                to->data.picture.colors = object->data.picture.colors;
 
604
                                to->data.picture.data_length = object->data.picture.data_length;
 
605
                                if(!copy_bytes_((&to->data.picture.data), object->data.picture.data, object->data.picture.data_length)) {
 
606
                                        FLAC__metadata_object_delete(to);
 
607
                                        return 0;
 
608
                                }
 
609
                                break;
507
610
                        default:
508
611
                                if(!copy_bytes_(&to->data.unknown.data, object->data.unknown.data, object->length)) {
509
612
                                        FLAC__metadata_object_delete(to);
552
655
                                cuesheet_track_array_delete_(object->data.cue_sheet.tracks, object->data.cue_sheet.num_tracks);
553
656
                        }
554
657
                        break;
 
658
                case FLAC__METADATA_TYPE_PICTURE:
 
659
                        if(0 != object->data.picture.mime_type) {
 
660
                                free(object->data.picture.mime_type);
 
661
                                object->data.picture.mime_type = 0;
 
662
                        }
 
663
                        if(0 != object->data.picture.description) {
 
664
                                free(object->data.picture.description);
 
665
                                object->data.picture.description = 0;
 
666
                        }
 
667
                        if(0 != object->data.picture.data) {
 
668
                                free(object->data.picture.data);
 
669
                                object->data.picture.data = 0;
 
670
                        }
 
671
                        break;
555
672
                default:
556
673
                        if(0 != object->data.unknown.data) {
557
674
                                free(object->data.unknown.data);
706
823
        return true;
707
824
}
708
825
 
 
826
static FLAC__bool compare_block_data_picture_(const FLAC__StreamMetadata_Picture *block1, const FLAC__StreamMetadata_Picture *block2)
 
827
{
 
828
        if(block1->type != block2->type)
 
829
                return false;
 
830
        if(block1->mime_type != block2->mime_type && (0 == block1->mime_type || 0 == block2->mime_type || strcmp(block1->mime_type, block2->mime_type)))
 
831
                return false;
 
832
        if(block1->description != block2->description && (0 == block1->description || 0 == block2->description || strcmp((const char *)block1->description, (const char *)block2->description)))
 
833
                return false;
 
834
        if(block1->width != block2->width)
 
835
                return false;
 
836
        if(block1->height != block2->height)
 
837
                return false;
 
838
        if(block1->depth != block2->depth)
 
839
                return false;
 
840
        if(block1->colors != block2->colors)
 
841
                return false;
 
842
        if(block1->data_length != block2->data_length)
 
843
                return false;
 
844
        if(block1->data != block2->data && (0 == block1->data || 0 == block2->data || memcmp(block1->data, block2->data, block1->data_length)))
 
845
                return false;
 
846
        return true;
 
847
}
 
848
 
709
849
static FLAC__bool compare_block_data_unknown_(const FLAC__StreamMetadata_Unknown *block1, const FLAC__StreamMetadata_Unknown *block2, unsigned block_length)
710
850
{
711
851
        FLAC__ASSERT(0 != block1);
744
884
                        return compare_block_data_vorbiscomment_(&block1->data.vorbis_comment, &block2->data.vorbis_comment);
745
885
                case FLAC__METADATA_TYPE_CUESHEET:
746
886
                        return compare_block_data_cuesheet_(&block1->data.cue_sheet, &block2->data.cue_sheet);
 
887
                case FLAC__METADATA_TYPE_PICTURE:
 
888
                        return compare_block_data_picture_(&block1->data.picture, &block2->data.picture);
747
889
                default:
748
890
                        return compare_block_data_unknown_(&block1->data.unknown, &block2->data.unknown, block1->length);
749
891
        }
931
1073
        FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE);
932
1074
        FLAC__ASSERT(total_samples > 0);
933
1075
 
934
 
        if(num > 0) {
 
1076
        if(num > 0 && total_samples > 0) {
935
1077
                FLAC__StreamMetadata_SeekTable *seek_table = &object->data.seek_table;
936
1078
                unsigned i, j;
937
1079
 
950
1092
        return true;
951
1093
}
952
1094
 
 
1095
FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(FLAC__StreamMetadata *object, unsigned samples, FLAC__uint64 total_samples)
 
1096
{
 
1097
        FLAC__ASSERT(0 != object);
 
1098
        FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE);
 
1099
        FLAC__ASSERT(samples > 0);
 
1100
        FLAC__ASSERT(total_samples > 0);
 
1101
 
 
1102
        if(samples > 0 && total_samples > 0) {
 
1103
                FLAC__StreamMetadata_SeekTable *seek_table = &object->data.seek_table;
 
1104
                unsigned i, j;
 
1105
                FLAC__uint64 num, sample;
 
1106
 
 
1107
                num = 1 + total_samples / samples; /* 1+ for the first sample at 0 */
 
1108
                /* now account for the fact that we don't place a seekpoint at "total_samples" since samples are number from 0: */
 
1109
                if(total_samples % samples == 0)
 
1110
                        num--;
 
1111
 
 
1112
                i = seek_table->num_points;
 
1113
 
 
1114
                if(!FLAC__metadata_object_seektable_resize_points(object, seek_table->num_points + (unsigned)num))
 
1115
                        return false;
 
1116
 
 
1117
                sample = 0;
 
1118
                for(j = 0; j < num; i++, j++, sample += samples) {
 
1119
                        seek_table->points[i].sample_number = sample;
 
1120
                        seek_table->points[i].stream_offset = 0;
 
1121
                        seek_table->points[i].frame_samples = 0;
 
1122
                }
 
1123
        }
 
1124
 
 
1125
        return true;
 
1126
}
 
1127
 
953
1128
FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_sort(FLAC__StreamMetadata *object, FLAC__bool compact)
954
1129
{
955
1130
        unsigned unique;
1073
1248
 
1074
1249
                field_name_length = eq-entry.entry;
1075
1250
 
1076
 
                if((i = vorbiscomment_find_entry_from_(object, 0, entry.entry, field_name_length)) >= 0) {
 
1251
                if((i = vorbiscomment_find_entry_from_(object, 0, (const char *)entry.entry, field_name_length)) >= 0) {
1077
1252
                        unsigned index = (unsigned)i;
1078
1253
                        if(!FLAC__metadata_object_vorbiscomment_set_comment(object, index, entry, copy))
1079
1254
                                return false;
1080
1255
                        if(all && (index+1 < object->data.vorbis_comment.num_comments)) {
1081
 
                                for(i = vorbiscomment_find_entry_from_(object, index+1, entry.entry, field_name_length); i >= 0; ) {
 
1256
                                for(i = vorbiscomment_find_entry_from_(object, index+1, (const char *)entry.entry, field_name_length); i >= 0; ) {
1082
1257
                                        if(!FLAC__metadata_object_vorbiscomment_delete_comment(object, (unsigned)i))
1083
1258
                                                return false;
1084
1259
                                        if((unsigned)i < object->data.vorbis_comment.num_comments)
1085
 
                                                i = vorbiscomment_find_entry_from_(object, (unsigned)i, entry.entry, field_name_length);
 
1260
                                                i = vorbiscomment_find_entry_from_(object, (unsigned)i, (const char *)entry.entry, field_name_length);
1086
1261
                                        else
1087
1262
                                                i = -1;
1088
1263
                                }
1124
1299
 
1125
1300
        if(!FLAC__format_vorbiscomment_entry_name_is_legal(field_name))
1126
1301
                return false;
1127
 
        if(!FLAC__format_vorbiscomment_entry_value_is_legal(field_value, (unsigned)(-1)))
 
1302
        if(!FLAC__format_vorbiscomment_entry_value_is_legal((const FLAC__byte *)field_value, (unsigned)(-1)))
1128
1303
                return false;
1129
1304
 
1130
1305
        {
1178
1353
        FLAC__ASSERT(0 != entry.entry && entry.length > 0);
1179
1354
        {
1180
1355
                const FLAC__byte *eq = (FLAC__byte*)memchr(entry.entry, '=', entry.length);
1181
 
#if defined _MSC_VER || defined __MINGW32__
 
1356
#if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__ || defined __EMX__
1182
1357
#define FLAC__STRNCASECMP strnicmp
1183
1358
#else
1184
1359
#define FLAC__STRNCASECMP strncasecmp
1236
1411
        return ok? (int)matching : -1;
1237
1412
}
1238
1413
 
1239
 
FLAC_API FLAC__StreamMetadata_CueSheet_Track *FLAC__metadata_object_cuesheet_track_new()
 
1414
FLAC_API FLAC__StreamMetadata_CueSheet_Track *FLAC__metadata_object_cuesheet_track_new(void)
1240
1415
{
1241
1416
        return (FLAC__StreamMetadata_CueSheet_Track*)calloc(1, sizeof(FLAC__StreamMetadata_CueSheet_Track));
1242
1417
}
1470
1645
 
1471
1646
        return FLAC__format_cuesheet_is_legal(&object->data.cue_sheet, check_cd_da_subset, violation);
1472
1647
}
 
1648
 
 
1649
static FLAC__uint64 get_index_01_offset_(const FLAC__StreamMetadata_CueSheet *cs, unsigned track)
 
1650
{
 
1651
        if (track >= (cs->num_tracks-1) || cs->tracks[track].num_indices < 1)
 
1652
                return 0;
 
1653
        else if (cs->tracks[track].indices[0].number == 1)
 
1654
                return cs->tracks[track].indices[0].offset + cs->tracks[track].offset + cs->lead_in;
 
1655
        else if (cs->tracks[track].num_indices < 2)
 
1656
                return 0;
 
1657
        else if (cs->tracks[track].indices[1].number == 1)
 
1658
                return cs->tracks[track].indices[1].offset + cs->tracks[track].offset + cs->lead_in;
 
1659
        else
 
1660
                return 0;
 
1661
}
 
1662
 
 
1663
static FLAC__uint32 cddb_add_digits_(FLAC__uint32 x)
 
1664
{
 
1665
        FLAC__uint32 n = 0;
 
1666
        while (x) {
 
1667
                n += (x%10);
 
1668
                x /= 10;
 
1669
        }
 
1670
        return n;
 
1671
}
 
1672
 
 
1673
FLAC_API FLAC__uint32 FLAC__metadata_object_cuesheet_calculate_cddb_id(const FLAC__StreamMetadata *object)
 
1674
{
 
1675
        const FLAC__StreamMetadata_CueSheet *cs;
 
1676
 
 
1677
        FLAC__ASSERT(0 != object);
 
1678
        FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET);
 
1679
 
 
1680
        cs = &object->data.cue_sheet;
 
1681
 
 
1682
        if (cs->num_tracks < 2) /* need at least one real track and the lead-out track */
 
1683
                return 0;
 
1684
 
 
1685
        {
 
1686
                FLAC__uint32 i, length, sum = 0;
 
1687
                for (i = 0; i < (cs->num_tracks-1); i++) /* -1 to avoid counting the lead-out */
 
1688
                        sum += cddb_add_digits_((FLAC__uint32)(get_index_01_offset_(cs, i) / 44100));
 
1689
                length = (FLAC__uint32)((cs->tracks[cs->num_tracks-1].offset+cs->lead_in) / 44100) - (FLAC__uint32)(get_index_01_offset_(cs, 0) / 44100);
 
1690
 
 
1691
                return (sum % 0xFF) << 24 | length << 8 | (FLAC__uint32)(cs->num_tracks-1);
 
1692
        }
 
1693
}
 
1694
 
 
1695
FLAC_API FLAC__bool FLAC__metadata_object_picture_set_mime_type(FLAC__StreamMetadata *object, char *mime_type, FLAC__bool copy)
 
1696
{
 
1697
        char *old;
 
1698
        size_t old_length, new_length;
 
1699
 
 
1700
        FLAC__ASSERT(0 != object);
 
1701
        FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_PICTURE);
 
1702
        FLAC__ASSERT(0 != mime_type);
 
1703
 
 
1704
        old = object->data.picture.mime_type;
 
1705
        old_length = old? strlen(old) : 0;
 
1706
        new_length = strlen(mime_type);
 
1707
 
 
1708
        /* do the copy first so that if we fail we leave the object untouched */
 
1709
        if(copy) {
 
1710
                if(!copy_bytes_((FLAC__byte**)(&object->data.picture.mime_type), (FLAC__byte*)mime_type, new_length+1))
 
1711
                        return false;
 
1712
        }
 
1713
        else {
 
1714
                object->data.picture.mime_type = mime_type;
 
1715
        }
 
1716
 
 
1717
        if(0 != old)
 
1718
                free(old);
 
1719
 
 
1720
        object->length -= old_length;
 
1721
        object->length += new_length;
 
1722
        return true;
 
1723
}
 
1724
 
 
1725
FLAC_API FLAC__bool FLAC__metadata_object_picture_set_description(FLAC__StreamMetadata *object, FLAC__byte *description, FLAC__bool copy)
 
1726
{
 
1727
        FLAC__byte *old;
 
1728
        size_t old_length, new_length;
 
1729
 
 
1730
        FLAC__ASSERT(0 != object);
 
1731
        FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_PICTURE);
 
1732
        FLAC__ASSERT(0 != description);
 
1733
 
 
1734
        old = object->data.picture.description;
 
1735
        old_length = old? strlen((const char *)old) : 0;
 
1736
        new_length = strlen((const char *)description);
 
1737
 
 
1738
        /* do the copy first so that if we fail we leave the object untouched */
 
1739
        if(copy) {
 
1740
                if(!copy_bytes_(&object->data.picture.description, description, new_length+1))
 
1741
                        return false;
 
1742
        }
 
1743
        else {
 
1744
                object->data.picture.description = description;
 
1745
        }
 
1746
 
 
1747
        if(0 != old)
 
1748
                free(old);
 
1749
 
 
1750
        object->length -= old_length;
 
1751
        object->length += new_length;
 
1752
        return true;
 
1753
}
 
1754
 
 
1755
FLAC_API FLAC__bool FLAC__metadata_object_picture_set_data(FLAC__StreamMetadata *object, FLAC__byte *data, FLAC__uint32 length, FLAC__bool copy)
 
1756
{
 
1757
        FLAC__byte *old;
 
1758
 
 
1759
        FLAC__ASSERT(0 != object);
 
1760
        FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_PICTURE);
 
1761
        FLAC__ASSERT((0 != data && length > 0) || (0 == data && length == 0 && copy == false));
 
1762
 
 
1763
        old = object->data.picture.data;
 
1764
 
 
1765
        /* do the copy first so that if we fail we leave the object untouched */
 
1766
        if(copy) {
 
1767
                if(!copy_bytes_(&object->data.picture.data, data, length))
 
1768
                        return false;
 
1769
        }
 
1770
        else {
 
1771
                object->data.picture.data = data;
 
1772
        }
 
1773
 
 
1774
        if(0 != old)
 
1775
                free(old);
 
1776
 
 
1777
        object->length -= object->data.picture.data_length;
 
1778
        object->data.picture.data_length = length;
 
1779
        object->length += length;
 
1780
        return true;
 
1781
}
 
1782
 
 
1783
FLAC_API FLAC__bool FLAC__metadata_object_picture_is_legal(const FLAC__StreamMetadata *object, const char **violation)
 
1784
{
 
1785
        FLAC__ASSERT(0 != object);
 
1786
        FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_PICTURE);
 
1787
 
 
1788
        return FLAC__format_picture_is_legal(&object->data.picture, violation);
 
1789
}