~ubuntu-branches/ubuntu/utopic/libjaudiotagger-java/utopic-proposed

« back to all changes in this revision

Viewing changes to src/org/jaudiotagger/tag/mp4/Mp4Tag.java

  • Committer: Bazaar Package Importer
  • Author(s): Damien Raude-Morvan
  • Date: 2011-04-28 23:52:43 UTC
  • mfrom: (3.1.4 sid)
  • Revision ID: james.westby@ubuntu.com-20110428235243-pzalvw6lncis3ukf
Tags: 2.0.3-1
* d/control: Drop Depends on default-jre per Debian Java Policy as its
  a library package.
* d/watch: Fix to directly monitor SVN tags.
* Switch to 3.0 (quilt) format.
* Bump Standards-Version to 3.9.2 (no changes needed).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Entagged Audio Tag library
3
 
 * Copyright (c) 2003-2005 Raphael Slinckx <raphael@slinckx.net>
4
 
 * 
5
 
 * This library is free software; you can redistribute it and/or
6
 
 * modify it under the terms of the GNU Lesser General Public
7
 
 * License as published by the Free Software Foundation; either
8
 
 * version 2.1 of the License, or (at your option) any later version.
9
 
 *  
10
 
 * This library is distributed in the hope that it will be useful,
11
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 
 * Lesser General Public License for more details.
14
 
 * 
15
 
 * You should have received a copy of the GNU Lesser General Public
16
 
 * License along with this library; if not, write to the Free Software
17
 
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 
 */
19
 
package org.jaudiotagger.tag.mp4;
20
 
 
21
 
import org.jaudiotagger.audio.generic.AbstractTag;
22
 
import org.jaudiotagger.audio.mp4.atom.Mp4BoxHeader;
23
 
import org.jaudiotagger.logging.ErrorMessage;
24
 
import org.jaudiotagger.tag.*;
25
 
import org.jaudiotagger.tag.datatype.Artwork;
26
 
import static org.jaudiotagger.tag.mp4.Mp4FieldKey.*;
27
 
import org.jaudiotagger.tag.mp4.field.*;
28
 
 
29
 
import java.util.ArrayList;
30
 
import java.util.EnumMap;
31
 
import java.util.List;
32
 
 
33
 
/**
34
 
 * A Logical representation of Mp4Tag, i.e the meta information stored in an Mp4 file underneath the
35
 
 * moov.udt.meta.ilst atom.
36
 
 */
37
 
public class Mp4Tag extends AbstractTag
38
 
{
39
 
 
40
 
    private static final EnumMap<FieldKey, Mp4FieldKey> tagFieldToMp4Field = new EnumMap<FieldKey, Mp4FieldKey>(FieldKey.class);
41
 
 
42
 
    //Mapping from generic key to mp4 key
43
 
    static
44
 
    {
45
 
        tagFieldToMp4Field.put(FieldKey.ARTIST, Mp4FieldKey.ARTIST);
46
 
        tagFieldToMp4Field.put(FieldKey.ALBUM, Mp4FieldKey.ALBUM);
47
 
        tagFieldToMp4Field.put(FieldKey.TITLE, Mp4FieldKey.TITLE);
48
 
        tagFieldToMp4Field.put(FieldKey.TRACK, Mp4FieldKey.TRACK);
49
 
        tagFieldToMp4Field.put(FieldKey.YEAR, Mp4FieldKey.DAY);
50
 
        tagFieldToMp4Field.put(FieldKey.GENRE, Mp4FieldKey.GENRE);
51
 
        tagFieldToMp4Field.put(FieldKey.COMMENT, Mp4FieldKey.COMMENT);
52
 
        tagFieldToMp4Field.put(FieldKey.ALBUM_ARTIST, Mp4FieldKey.ALBUM_ARTIST);
53
 
        tagFieldToMp4Field.put(FieldKey.COMPOSER, Mp4FieldKey.COMPOSER);
54
 
        tagFieldToMp4Field.put(FieldKey.GROUPING, Mp4FieldKey.GROUPING);
55
 
        tagFieldToMp4Field.put(FieldKey.DISC_NO, Mp4FieldKey.DISCNUMBER);
56
 
        tagFieldToMp4Field.put(FieldKey.BPM, Mp4FieldKey.BPM);
57
 
        tagFieldToMp4Field.put(FieldKey.ENCODER, Mp4FieldKey.ENCODER);
58
 
        tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_ARTISTID, Mp4FieldKey.MUSICBRAINZ_ARTISTID);
59
 
        tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_RELEASEID, Mp4FieldKey.MUSICBRAINZ_ALBUMID);
60
 
        tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_RELEASEARTISTID, Mp4FieldKey.MUSICBRAINZ_ALBUMARTISTID);
61
 
        tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_TRACK_ID, Mp4FieldKey.MUSICBRAINZ_TRACKID);
62
 
        tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_DISC_ID, Mp4FieldKey.MUSICBRAINZ_DISCID);
63
 
        tagFieldToMp4Field.put(FieldKey.MUSICIP_ID, Mp4FieldKey.MUSICIP_PUID);
64
 
        tagFieldToMp4Field.put(FieldKey.AMAZON_ID, Mp4FieldKey.ASIN);
65
 
        tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_RELEASE_STATUS, Mp4FieldKey.MUSICBRAINZ_ALBUM_STATUS);
66
 
        tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_RELEASE_TYPE, Mp4FieldKey.MUSICBRAINZ_ALBUM_TYPE);
67
 
        tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_RELEASE_COUNTRY, Mp4FieldKey.RELEASECOUNTRY);
68
 
        tagFieldToMp4Field.put(FieldKey.LYRICS, Mp4FieldKey.LYRICS);
69
 
        tagFieldToMp4Field.put(FieldKey.IS_COMPILATION, Mp4FieldKey.COMPILATION);
70
 
        tagFieldToMp4Field.put(FieldKey.ARTIST_SORT, Mp4FieldKey.ARTIST_SORT);
71
 
        tagFieldToMp4Field.put(FieldKey.ALBUM_ARTIST_SORT, Mp4FieldKey.ALBUM_ARTIST_SORT);
72
 
        tagFieldToMp4Field.put(FieldKey.ALBUM_SORT, Mp4FieldKey.ALBUM_SORT);
73
 
        tagFieldToMp4Field.put(FieldKey.TITLE_SORT, Mp4FieldKey.TITLE_SORT);
74
 
        tagFieldToMp4Field.put(FieldKey.COMPOSER_SORT, Mp4FieldKey.COMPOSER_SORT);
75
 
        tagFieldToMp4Field.put(FieldKey.COVER_ART, Mp4FieldKey.ARTWORK);
76
 
        tagFieldToMp4Field.put(FieldKey.ISRC, Mp4FieldKey.ISRC);
77
 
        tagFieldToMp4Field.put(FieldKey.CATALOG_NO, Mp4FieldKey.CATALOGNO);
78
 
        tagFieldToMp4Field.put(FieldKey.BARCODE, Mp4FieldKey.BARCODE);
79
 
        tagFieldToMp4Field.put(FieldKey.RECORD_LABEL, Mp4FieldKey.LABEL);
80
 
        tagFieldToMp4Field.put(FieldKey.LYRICIST, Mp4FieldKey.LYRICIST);
81
 
        tagFieldToMp4Field.put(FieldKey.CONDUCTOR, Mp4FieldKey.CONDUCTOR);
82
 
        tagFieldToMp4Field.put(FieldKey.REMIXER, Mp4FieldKey.REMIXER);
83
 
        tagFieldToMp4Field.put(FieldKey.MOOD, Mp4FieldKey.MOOD);
84
 
        tagFieldToMp4Field.put(FieldKey.MEDIA, Mp4FieldKey.MEDIA);
85
 
        tagFieldToMp4Field.put(FieldKey.URL_OFFICIAL_RELEASE_SITE, Mp4FieldKey.URL_OFFICIAL_RELEASE_SITE);
86
 
        tagFieldToMp4Field.put(FieldKey.URL_DISCOGS_RELEASE_SITE, Mp4FieldKey.URL_DISCOGS_RELEASE_SITE);
87
 
        tagFieldToMp4Field.put(FieldKey.URL_WIKIPEDIA_RELEASE_SITE, Mp4FieldKey.URL_WIKIPEDIA_RELEASE_SITE);
88
 
        tagFieldToMp4Field.put(FieldKey.URL_OFFICIAL_ARTIST_SITE, Mp4FieldKey.URL_OFFICIAL_ARTIST_SITE);
89
 
        tagFieldToMp4Field.put(FieldKey.URL_DISCOGS_ARTIST_SITE, Mp4FieldKey.URL_DISCOGS_ARTIST_SITE);
90
 
        tagFieldToMp4Field.put(FieldKey.URL_WIKIPEDIA_ARTIST_SITE, Mp4FieldKey.URL_WIKIPEDIA_ARTIST_SITE);
91
 
        tagFieldToMp4Field.put(FieldKey.LANGUAGE, Mp4FieldKey.LANGUAGE);
92
 
        tagFieldToMp4Field.put(FieldKey.KEY, Mp4FieldKey.KEY);
93
 
        tagFieldToMp4Field.put(FieldKey.URL_LYRICS_SITE, Mp4FieldKey.URL_LYRICS_SITE);
94
 
        tagFieldToMp4Field.put(FieldKey.TRACK_TOTAL, Mp4FieldKey.TRACK);
95
 
        tagFieldToMp4Field.put(FieldKey.DISC_TOTAL, Mp4FieldKey.DISCNUMBER);
96
 
    }
97
 
 
98
 
    /**
99
 
     * Create genre field
100
 
     * <p/>
101
 
     * <p>If the content can be parsed to one of the known values use the genre field otherwise
102
 
     * use the custom field.
103
 
     *
104
 
     * @param content
105
 
     * @return
106
 
     */
107
 
    @SuppressWarnings({"JavaDoc"})
108
 
    private TagField createGenreField(String content)
109
 
    {
110
 
        if (content == null)
111
 
        {
112
 
            throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg());
113
 
        }
114
 
        if (Mp4GenreField.isValidGenre(content))
115
 
        {
116
 
            return new Mp4GenreField(content);
117
 
        }
118
 
        else
119
 
        {
120
 
            return new Mp4TagTextField(GENRE_CUSTOM.getFieldName(), content);
121
 
        }
122
 
    }
123
 
 
124
 
    protected boolean isAllowedEncoding(String enc)
125
 
    {
126
 
        return enc.equals(Mp4BoxHeader.CHARSET_UTF_8);
127
 
    }
128
 
 
129
 
    public String toString()
130
 
    {
131
 
        return "Mpeg4 " + super.toString();
132
 
    }
133
 
 
134
 
 
135
 
    /**
136
 
     * Maps the generic key to the mp4 key and return the list of values for this field
137
 
     *
138
 
     * @param genericKey
139
 
     */
140
 
    @SuppressWarnings({"JavaDoc"})
141
 
    @Override
142
 
    public List<TagField> getFields(FieldKey genericKey) throws KeyNotFoundException
143
 
    {
144
 
        if (genericKey == null)
145
 
        {
146
 
            throw new KeyNotFoundException();
147
 
        }
148
 
        return super.get(tagFieldToMp4Field.get(genericKey).getFieldName());
149
 
    }
150
 
 
151
 
 
152
 
    /**
153
 
     * Retrieve the  values that exists for this mp4keyId (this is the internalid actually used)
154
 
     * <p/>
155
 
     *
156
 
     * @param mp4FieldKey
157
 
     * @throws org.jaudiotagger.tag.KeyNotFoundException
158
 
     * @return
159
 
     */
160
 
    public List<TagField> get(Mp4FieldKey mp4FieldKey) throws KeyNotFoundException
161
 
    {
162
 
        if (mp4FieldKey == null)
163
 
        {
164
 
            throw new KeyNotFoundException();
165
 
        }
166
 
        return super.get(mp4FieldKey.getFieldName());
167
 
    }
168
 
 
169
 
    /**
170
 
     * Retrieve the first value that exists for this generic key
171
 
     *
172
 
     * @param genericKey
173
 
     * @return
174
 
     */
175
 
    public String getFirst(FieldKey genericKey) throws KeyNotFoundException
176
 
    {
177
 
        if (genericKey == null)
178
 
        {
179
 
            throw new KeyNotFoundException();
180
 
        }
181
 
 
182
 
        if(genericKey== FieldKey.GENRE)
183
 
        {
184
 
            List<TagField> genres = get(GENRE.getFieldName());
185
 
            if (genres.size() == 0)
186
 
            {
187
 
                genres = get(GENRE_CUSTOM.getFieldName());
188
 
            }
189
 
            if(genres.size()>0)
190
 
            {
191
 
                return ((TagTextField)genres.get(0)).getContent();
192
 
            }
193
 
            else
194
 
            {
195
 
                return "";
196
 
            }
197
 
 
198
 
        }
199
 
        else if(genericKey== FieldKey.TRACK)
200
 
        {
201
 
            List<TagField> list = get(tagFieldToMp4Field.get(genericKey));
202
 
            if(list.size()>0)
203
 
            {
204
 
                Mp4TrackField trackField = (Mp4TrackField)list.get(0);
205
 
                if(trackField.getTrackNo()>0)
206
 
                {
207
 
                    return String.valueOf(trackField.getTrackNo());
208
 
                }
209
 
            }
210
 
        }
211
 
        else if(genericKey== FieldKey.TRACK_TOTAL)
212
 
        {
213
 
            List<TagField> list = get(tagFieldToMp4Field.get(genericKey));
214
 
            if(list.size()>0)
215
 
            {
216
 
                Mp4TrackField trackField = (Mp4TrackField)list.get(0);
217
 
                if(trackField.getTrackTotal()>0)
218
 
                {
219
 
                    return String.valueOf(trackField.getTrackTotal());
220
 
                }
221
 
            }
222
 
        }
223
 
        else if(genericKey== FieldKey.DISC_NO)
224
 
        {
225
 
            List<TagField> list = get(tagFieldToMp4Field.get(genericKey));
226
 
            if(list.size()>0)
227
 
            {
228
 
                Mp4DiscNoField discField = (Mp4DiscNoField)list.get(0);
229
 
                if(discField.getDiscNo()>0)
230
 
                {
231
 
                     return String.valueOf(discField.getDiscNo());
232
 
                }
233
 
 
234
 
            }
235
 
        }
236
 
        else if(genericKey== FieldKey.DISC_TOTAL)
237
 
        {
238
 
            List<TagField> list = get(tagFieldToMp4Field.get(genericKey));
239
 
            if(list.size()>0)
240
 
            {
241
 
                Mp4DiscNoField discField = (Mp4DiscNoField)list.get(0);
242
 
                if(discField.getDiscTotal()>0)
243
 
                {
244
 
                     return String.valueOf(discField.getDiscTotal());
245
 
                }
246
 
            }
247
 
        }
248
 
        else
249
 
        {
250
 
            return super.getFirst(tagFieldToMp4Field.get(genericKey).getFieldName());
251
 
        }
252
 
        return "";
253
 
    }
254
 
 
255
 
    /**
256
 
     * Retrieve the first value that exists for this mp4key
257
 
     *
258
 
     * @param mp4Key
259
 
     * @return
260
 
     * @throws org.jaudiotagger.tag.KeyNotFoundException
261
 
     */
262
 
    public String getFirst(Mp4FieldKey mp4Key) throws KeyNotFoundException
263
 
    {
264
 
        if (mp4Key == null)
265
 
        {
266
 
            throw new KeyNotFoundException();
267
 
        }
268
 
        return super.getFirst(mp4Key.getFieldName());
269
 
    }
270
 
 
271
 
    public Mp4TagField getFirstField(FieldKey genericKey) throws KeyNotFoundException
272
 
    {
273
 
        if (genericKey == null)
274
 
        {
275
 
            throw new KeyNotFoundException();
276
 
        }
277
 
        return (Mp4TagField)super.getFirstField(tagFieldToMp4Field.get(genericKey).getFieldName());
278
 
    }
279
 
 
280
 
    public Mp4TagField getFirstField(Mp4FieldKey mp4Key) throws KeyNotFoundException
281
 
    {
282
 
        if (mp4Key == null)
283
 
        {
284
 
            throw new KeyNotFoundException();
285
 
        }
286
 
        return (Mp4TagField) super.getFirstField(mp4Key.getFieldName());
287
 
    }
288
 
 
289
 
    /**
290
 
     * Delete fields with this generic key
291
 
     *
292
 
     * @param genericKey
293
 
     */
294
 
    public void deleteField(FieldKey genericKey) throws KeyNotFoundException
295
 
    {
296
 
        if (genericKey == null)
297
 
        {
298
 
            throw new KeyNotFoundException();
299
 
        }
300
 
        super.deleteField(tagFieldToMp4Field.get(genericKey).getFieldName());
301
 
    }
302
 
 
303
 
    /**
304
 
     * Delete fields with this mp4key
305
 
     *
306
 
     * @param mp4Key
307
 
     * @throws org.jaudiotagger.tag.KeyNotFoundException
308
 
     */
309
 
    public void deleteTagField(Mp4FieldKey mp4Key) throws KeyNotFoundException
310
 
    {
311
 
        if (mp4Key == null)
312
 
        {
313
 
            throw new KeyNotFoundException();
314
 
        }
315
 
        super.deleteField(mp4Key.getFieldName());
316
 
    }
317
 
 
318
 
    /**
319
 
     * Create discno field
320
 
     *
321
 
     * @param content can be any of the following
322
 
     *                1
323
 
     *                1/10
324
 
     * @return
325
 
     * @throws org.jaudiotagger.tag.FieldDataInvalidException
326
 
     */
327
 
    public TagField createDiscNoField(String content) throws FieldDataInvalidException
328
 
    {
329
 
        return new Mp4DiscNoField(content);
330
 
    }
331
 
 
332
 
    /**
333
 
     * Create artwork field
334
 
     *
335
 
     * @param data raw image data
336
 
     * @return
337
 
     * @throws org.jaudiotagger.tag.FieldDataInvalidException
338
 
     */
339
 
    public TagField createArtworkField(byte[] data)
340
 
    {
341
 
        return new Mp4TagCoverField(data);
342
 
    }
343
 
 
344
 
     /**
345
 
     * Create artwork field
346
 
     *    
347
 
     * @return
348
 
     */
349
 
    public TagField createField(Artwork artwork) throws FieldDataInvalidException
350
 
    {
351
 
        return new Mp4TagCoverField(artwork.getBinaryData());
352
 
    }
353
 
 
354
 
    /**
355
 
     * Create Tag Field using generic key
356
 
     * <p/>
357
 
     * This should use the correct subclass for the key
358
 
     *
359
 
     * @param genericKey
360
 
     * @param value
361
 
     * @return
362
 
     * @throws KeyNotFoundException
363
 
     * @throws FieldDataInvalidException
364
 
     */
365
 
    @Override
366
 
    public TagField createField(FieldKey genericKey, String value) throws KeyNotFoundException, FieldDataInvalidException
367
 
    {
368
 
        if (value == null)
369
 
        {
370
 
            throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg());
371
 
        }
372
 
        if (genericKey == null)
373
 
        {
374
 
            throw new KeyNotFoundException();
375
 
        }
376
 
 
377
 
        if(genericKey== FieldKey.TRACK)
378
 
        {
379
 
            return new Mp4TrackField(Integer.parseInt(value));
380
 
        }
381
 
        else if(genericKey== FieldKey.TRACK_TOTAL)
382
 
        {
383
 
            return new Mp4TrackField(0,Integer.parseInt(value));
384
 
        }
385
 
        else if(genericKey== FieldKey.DISC_NO)
386
 
        {
387
 
            return new Mp4DiscNoField(Integer.parseInt(value));
388
 
        }
389
 
        else if(genericKey== FieldKey.DISC_TOTAL)
390
 
        {
391
 
            return new Mp4DiscNoField(0,Integer.parseInt(value));
392
 
        }
393
 
        else
394
 
        {
395
 
            return createTagField(tagFieldToMp4Field.get(genericKey), value);
396
 
        }
397
 
    }
398
 
 
399
 
    /**
400
 
     * Set field, special handling for track and disc because they hold two fields
401
 
     * 
402
 
     * @param field
403
 
     */
404
 
    @Override
405
 
    public void setField(TagField field)
406
 
    {
407
 
        if (field == null)
408
 
        {
409
 
            return;
410
 
        }
411
 
 
412
 
        if(field.getId().equals(TRACK.getFieldName()))
413
 
        {
414
 
            List<TagField> list = fields.get(field.getId());
415
 
            if(list==null||list.size()==0)
416
 
            {
417
 
                 super.setField(field);
418
 
            }
419
 
            else
420
 
            {
421
 
                Mp4TrackField existingTrackField = (Mp4TrackField)list.get(0);
422
 
                Mp4TrackField newTrackField      = (Mp4TrackField)field;
423
 
                Short trackNo    = existingTrackField.getTrackNo();
424
 
                Short trackTotal = existingTrackField.getTrackTotal();
425
 
                if(newTrackField.getTrackNo()>0 )
426
 
                {
427
 
                    trackNo = newTrackField.getTrackNo();
428
 
                }
429
 
                if(newTrackField.getTrackTotal()>0 )
430
 
                {
431
 
                    trackTotal = newTrackField.getTrackTotal();
432
 
                }
433
 
 
434
 
                Mp4TrackField mergedTrackField = new Mp4TrackField(trackNo,trackTotal);
435
 
                super.setField(mergedTrackField);
436
 
            }
437
 
        }
438
 
        else if(field.getId().equals(DISCNUMBER.getFieldName()))
439
 
        {
440
 
            List<TagField> list = fields.get(field.getId());
441
 
            if(list==null||list.size()==0)
442
 
            {
443
 
                 super.setField(field);
444
 
            }
445
 
            else
446
 
            {
447
 
                Mp4DiscNoField existingDiscNoField = (Mp4DiscNoField)list.get(0);
448
 
                Mp4DiscNoField newDiscNoField      = (Mp4DiscNoField)field;
449
 
                Short discNo    = existingDiscNoField.getDiscNo();
450
 
                Short discTotal = existingDiscNoField.getDiscTotal();
451
 
                if(newDiscNoField.getDiscNo()>0 )
452
 
                {
453
 
                    discNo = newDiscNoField.getDiscNo();
454
 
                }
455
 
                if(newDiscNoField.getDiscTotal()>0 )
456
 
                {
457
 
                    discTotal = newDiscNoField.getDiscTotal();
458
 
                }
459
 
 
460
 
                Mp4DiscNoField mergedDiscNoField = new Mp4DiscNoField(discNo,discTotal);
461
 
                super.setField(mergedDiscNoField);
462
 
            }
463
 
        }
464
 
        else
465
 
        {
466
 
            super.setField(field);
467
 
        }
468
 
    }
469
 
 
470
 
    /**
471
 
     * Create Tag Field using mp4 key
472
 
     * <p/>
473
 
     * Uses the correct subclass for the key
474
 
     *
475
 
     * @param mp4FieldKey
476
 
     * @param value
477
 
     * @return
478
 
     * @throws KeyNotFoundException
479
 
     * @throws FieldDataInvalidException
480
 
     */
481
 
    public TagField createTagField(Mp4FieldKey mp4FieldKey, String value) throws KeyNotFoundException, FieldDataInvalidException
482
 
    {
483
 
        if (value == null)
484
 
        {
485
 
            throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg());
486
 
        }
487
 
        if (mp4FieldKey == null)
488
 
        {
489
 
            throw new KeyNotFoundException();
490
 
        }
491
 
        switch (mp4FieldKey)
492
 
        {
493
 
            //This is boolean stored as 1, but calling program might setField as 'true' so we handle this
494
 
            //case internally
495
 
            case COMPILATION:
496
 
                if(value.equals("true"))
497
 
                {
498
 
                    value= Mp4TagByteField.TRUE_VALUE;
499
 
                }
500
 
                return new Mp4TagByteField(mp4FieldKey, value, mp4FieldKey.getFieldLength());
501
 
 
502
 
            case RATING:
503
 
            case BPM:
504
 
            case CONTENT_TYPE:
505
 
            case TV_SEASON:
506
 
            case TV_EPISODE:
507
 
            case TOOL:
508
 
                return new Mp4TagByteField(mp4FieldKey, value, mp4FieldKey.getFieldLength());
509
 
 
510
 
            case GENRE:
511
 
                return createGenreField(value);
512
 
 
513
 
            case PODCAST_URL:
514
 
            case EPISODE_GLOBAL_ID:
515
 
                return new Mp4TagTextNumberField(mp4FieldKey.getFieldName(), value);
516
 
 
517
 
            case DISCNUMBER:
518
 
                return new Mp4DiscNoField(value);
519
 
 
520
 
            case TRACK:
521
 
                return new Mp4TrackField(value);
522
 
 
523
 
            case MUSICBRAINZ_TRACKID:
524
 
            case MUSICBRAINZ_ARTISTID:
525
 
            case MUSICBRAINZ_ALBUMID:
526
 
            case MUSICBRAINZ_ALBUMARTISTID:
527
 
            case MUSICBRAINZ_DISCID:
528
 
            case MUSICIP_PUID:
529
 
            case ASIN:
530
 
            case MUSICBRAINZ_ALBUM_STATUS:
531
 
            case MUSICBRAINZ_ALBUM_TYPE:
532
 
            case RELEASECOUNTRY:
533
 
            case PART_OF_GAPLESS_ALBUM:
534
 
            case ITUNES_SMPB:
535
 
            case ITUNES_NORM:
536
 
            case CDDB_1:
537
 
            case CDDB_TRACKNUMBER:
538
 
            case CDDB_IDS:
539
 
            case LYRICIST:
540
 
            case CONDUCTOR:
541
 
            case REMIXER:
542
 
            case ENGINEER:
543
 
            case PRODUCER:
544
 
            case DJMIXER:
545
 
            case MIXER:
546
 
            case MOOD:
547
 
            case ISRC:
548
 
            case MEDIA:
549
 
            case LABEL:
550
 
            case CATALOGNO:
551
 
            case BARCODE:
552
 
            case URL_OFFICIAL_RELEASE_SITE:
553
 
            case URL_DISCOGS_RELEASE_SITE:
554
 
            case URL_WIKIPEDIA_RELEASE_SITE:
555
 
            case URL_OFFICIAL_ARTIST_SITE:
556
 
            case URL_DISCOGS_ARTIST_SITE:
557
 
            case URL_WIKIPEDIA_ARTIST_SITE:
558
 
            case LANGUAGE:
559
 
            case KEY: 
560
 
            case URL_LYRICS_SITE:
561
 
                return new Mp4TagReverseDnsField(mp4FieldKey, value);
562
 
 
563
 
            case ARTWORK:
564
 
                throw new UnsupportedOperationException(ErrorMessage.ARTWORK_CANNOT_BE_CREATED_WITH_THIS_METHOD.getMsg());
565
 
                 
566
 
            default:
567
 
                return new Mp4TagTextField(mp4FieldKey.getFieldName(), value);
568
 
        }
569
 
    }
570
 
 
571
 
    public List<Artwork> getArtworkList()
572
 
    {
573
 
        List<TagField> coverartList = get(Mp4FieldKey.ARTWORK);
574
 
        List<Artwork> artworkList = new ArrayList<Artwork>(coverartList.size());
575
 
 
576
 
        for(TagField next:coverartList)
577
 
        {
578
 
            Mp4TagCoverField mp4CoverArt = (Mp4TagCoverField)next;
579
 
            Artwork artwork = new Artwork();
580
 
            artwork.setBinaryData(mp4CoverArt.getData());
581
 
            artwork.setMimeType(Mp4TagCoverField.getMimeTypeForImageType(mp4CoverArt.getFieldType()));
582
 
            artworkList.add(artwork);
583
 
        }
584
 
        return artworkList;
585
 
    }
586
 
 
587
 
}
 
1
/*
 
2
 * Entagged Audio Tag library
 
3
 * Copyright (c) 2003-2005 Raphael Slinckx <raphael@slinckx.net>
 
4
 * 
 
5
 * This library is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU Lesser General Public
 
7
 * License as published by the Free Software Foundation; either
 
8
 * version 2.1 of the License, or (at your option) any later version.
 
9
 *  
 
10
 * This library is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
 * Lesser General Public License for more details.
 
14
 * 
 
15
 * You should have received a copy of the GNU Lesser General Public
 
16
 * License along with this library; if not, write to the Free Software
 
17
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
18
 */
 
19
package org.jaudiotagger.tag.mp4;
 
20
 
 
21
import org.jaudiotagger.audio.generic.AbstractTag;
 
22
import org.jaudiotagger.audio.mp4.atom.Mp4BoxHeader;
 
23
import org.jaudiotagger.logging.ErrorMessage;
 
24
import org.jaudiotagger.tag.*;
 
25
import org.jaudiotagger.tag.datatype.Artwork;
 
26
import static org.jaudiotagger.tag.mp4.Mp4FieldKey.*;
 
27
import org.jaudiotagger.tag.mp4.field.*;
 
28
import org.jaudiotagger.tag.vorbiscomment.VorbisCommentFieldKey;
 
29
 
 
30
import java.util.ArrayList;
 
31
import java.util.EnumMap;
 
32
import java.util.List;
 
33
 
 
34
/**
 
35
 * A Logical representation of Mp4Tag, i.e the meta information stored in an Mp4 file underneath the
 
36
 * moov.udt.meta.ilst atom.
 
37
 */
 
38
public class Mp4Tag extends AbstractTag
 
39
{
 
40
 
 
41
    private static final EnumMap<FieldKey, Mp4FieldKey> tagFieldToMp4Field = new EnumMap<FieldKey, Mp4FieldKey>(FieldKey.class);
 
42
 
 
43
    //Mapping from generic key to mp4 key
 
44
    static
 
45
    {
 
46
        tagFieldToMp4Field.put(FieldKey.ALBUM, Mp4FieldKey.ALBUM);
 
47
        tagFieldToMp4Field.put(FieldKey.ALBUM_ARTIST, Mp4FieldKey.ALBUM_ARTIST);
 
48
        tagFieldToMp4Field.put(FieldKey.ALBUM_ARTIST_SORT, Mp4FieldKey.ALBUM_ARTIST_SORT);
 
49
        tagFieldToMp4Field.put(FieldKey.ALBUM_SORT, Mp4FieldKey.ALBUM_SORT);
 
50
        tagFieldToMp4Field.put(FieldKey.AMAZON_ID, Mp4FieldKey.ASIN);
 
51
        tagFieldToMp4Field.put(FieldKey.ARTIST, Mp4FieldKey.ARTIST);
 
52
        tagFieldToMp4Field.put(FieldKey.ARTIST_SORT, Mp4FieldKey.ARTIST_SORT);
 
53
        tagFieldToMp4Field.put(FieldKey.BARCODE, Mp4FieldKey.BARCODE);
 
54
        tagFieldToMp4Field.put(FieldKey.BPM, Mp4FieldKey.BPM);
 
55
        tagFieldToMp4Field.put(FieldKey.CATALOG_NO, Mp4FieldKey.CATALOGNO);
 
56
        tagFieldToMp4Field.put(FieldKey.COMMENT, Mp4FieldKey.COMMENT);
 
57
        tagFieldToMp4Field.put(FieldKey.COMPOSER, Mp4FieldKey.COMPOSER);
 
58
        tagFieldToMp4Field.put(FieldKey.COMPOSER_SORT, Mp4FieldKey.COMPOSER_SORT);
 
59
        tagFieldToMp4Field.put(FieldKey.CONDUCTOR, Mp4FieldKey.CONDUCTOR);
 
60
        tagFieldToMp4Field.put(FieldKey.COVER_ART, Mp4FieldKey.ARTWORK);
 
61
        tagFieldToMp4Field.put(FieldKey.CUSTOM1, Mp4FieldKey.MM_CUSTOM_1);
 
62
        tagFieldToMp4Field.put(FieldKey.CUSTOM2, Mp4FieldKey.MM_CUSTOM_2);
 
63
        tagFieldToMp4Field.put(FieldKey.CUSTOM3, Mp4FieldKey.MM_CUSTOM_3);
 
64
        tagFieldToMp4Field.put(FieldKey.CUSTOM4, Mp4FieldKey.MM_CUSTOM_4);
 
65
        tagFieldToMp4Field.put(FieldKey.CUSTOM5, Mp4FieldKey.MM_CUSTOM_5);
 
66
        tagFieldToMp4Field.put(FieldKey.DISC_NO, Mp4FieldKey.DISCNUMBER);
 
67
        tagFieldToMp4Field.put(FieldKey.DISC_TOTAL, Mp4FieldKey.DISCNUMBER);
 
68
        tagFieldToMp4Field.put(FieldKey.ENCODER, Mp4FieldKey.ENCODER);
 
69
        tagFieldToMp4Field.put(FieldKey.FBPM, Mp4FieldKey.FBPM);
 
70
        tagFieldToMp4Field.put(FieldKey.GENRE, Mp4FieldKey.GENRE);
 
71
        tagFieldToMp4Field.put(FieldKey.GROUPING, Mp4FieldKey.GROUPING);
 
72
        tagFieldToMp4Field.put(FieldKey.ISRC, Mp4FieldKey.ISRC);
 
73
        tagFieldToMp4Field.put(FieldKey.IS_COMPILATION, Mp4FieldKey.COMPILATION);
 
74
        tagFieldToMp4Field.put(FieldKey.KEY, Mp4FieldKey.KEY);
 
75
        tagFieldToMp4Field.put(FieldKey.LANGUAGE, Mp4FieldKey.LANGUAGE);
 
76
        tagFieldToMp4Field.put(FieldKey.LYRICIST, Mp4FieldKey.LYRICIST);
 
77
        tagFieldToMp4Field.put(FieldKey.LYRICS, Mp4FieldKey.LYRICS);
 
78
        tagFieldToMp4Field.put(FieldKey.MEDIA, Mp4FieldKey.MEDIA);
 
79
        tagFieldToMp4Field.put(FieldKey.MOOD, Mp4FieldKey.MOOD);
 
80
        tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_ARTISTID, Mp4FieldKey.MUSICBRAINZ_ARTISTID);
 
81
        tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_DISC_ID, Mp4FieldKey.MUSICBRAINZ_DISCID);
 
82
        tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_RELEASEARTISTID, Mp4FieldKey.MUSICBRAINZ_ALBUMARTISTID);
 
83
        tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_RELEASEID, Mp4FieldKey.MUSICBRAINZ_ALBUMID);
 
84
        tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_RELEASE_COUNTRY, Mp4FieldKey.RELEASECOUNTRY);
 
85
        tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_RELEASE_GROUP_ID, Mp4FieldKey.MUSICBRAINZ_RELEASE_GROUPID);
 
86
        tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_RELEASE_STATUS, Mp4FieldKey.MUSICBRAINZ_ALBUM_STATUS);
 
87
        tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_RELEASE_TYPE, Mp4FieldKey.MUSICBRAINZ_ALBUM_TYPE);
 
88
        tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_TRACK_ID, Mp4FieldKey.MUSICBRAINZ_TRACKID);
 
89
        tagFieldToMp4Field.put(FieldKey.MUSICBRAINZ_WORK_ID, Mp4FieldKey.MUSICBRAINZ_WORKID);
 
90
        tagFieldToMp4Field.put(FieldKey.MUSICIP_ID, Mp4FieldKey.MUSICIP_PUID);
 
91
        tagFieldToMp4Field.put(FieldKey.OCCASION, Mp4FieldKey.OCCASION);
 
92
        tagFieldToMp4Field.put(FieldKey.ORIGINAL_ALBUM, Mp4FieldKey.MM_ORIGINAL_ALBUM_TITLE);
 
93
        tagFieldToMp4Field.put(FieldKey.ORIGINAL_ARTIST, Mp4FieldKey.MM_ORIGINAL_ARTIST);
 
94
        tagFieldToMp4Field.put(FieldKey.ORIGINAL_LYRICIST, Mp4FieldKey.MM_ORIGINAL_LYRICIST);
 
95
        tagFieldToMp4Field.put(FieldKey.ORIGINAL_YEAR, Mp4FieldKey.MM_ORIGINAL_YEAR);
 
96
        tagFieldToMp4Field.put(FieldKey.QUALITY, Mp4FieldKey.QUALITY);
 
97
        tagFieldToMp4Field.put(FieldKey.RATING, Mp4FieldKey.SCORE);
 
98
        tagFieldToMp4Field.put(FieldKey.RECORD_LABEL, Mp4FieldKey.LABEL);
 
99
        tagFieldToMp4Field.put(FieldKey.REMIXER, Mp4FieldKey.REMIXER);
 
100
        tagFieldToMp4Field.put(FieldKey.SCRIPT, Mp4FieldKey.SCRIPT);
 
101
        tagFieldToMp4Field.put(FieldKey.TAGS, Mp4FieldKey.TAGS);
 
102
        tagFieldToMp4Field.put(FieldKey.TEMPO, Mp4FieldKey.TEMPO);
 
103
        tagFieldToMp4Field.put(FieldKey.TITLE, Mp4FieldKey.TITLE);
 
104
        tagFieldToMp4Field.put(FieldKey.TITLE_SORT, Mp4FieldKey.TITLE_SORT);
 
105
        tagFieldToMp4Field.put(FieldKey.TRACK, Mp4FieldKey.TRACK);
 
106
        tagFieldToMp4Field.put(FieldKey.TRACK_TOTAL, Mp4FieldKey.TRACK);
 
107
        tagFieldToMp4Field.put(FieldKey.URL_DISCOGS_ARTIST_SITE, Mp4FieldKey.URL_DISCOGS_ARTIST_SITE);
 
108
        tagFieldToMp4Field.put(FieldKey.URL_DISCOGS_RELEASE_SITE, Mp4FieldKey.URL_DISCOGS_RELEASE_SITE);
 
109
        tagFieldToMp4Field.put(FieldKey.URL_LYRICS_SITE, Mp4FieldKey.URL_LYRICS_SITE);
 
110
        tagFieldToMp4Field.put(FieldKey.URL_OFFICIAL_ARTIST_SITE, Mp4FieldKey.URL_OFFICIAL_ARTIST_SITE);
 
111
        tagFieldToMp4Field.put(FieldKey.URL_OFFICIAL_RELEASE_SITE, Mp4FieldKey.URL_OFFICIAL_RELEASE_SITE);
 
112
        tagFieldToMp4Field.put(FieldKey.URL_WIKIPEDIA_ARTIST_SITE, Mp4FieldKey.URL_WIKIPEDIA_ARTIST_SITE);
 
113
        tagFieldToMp4Field.put(FieldKey.URL_WIKIPEDIA_RELEASE_SITE, Mp4FieldKey.URL_WIKIPEDIA_RELEASE_SITE);
 
114
        tagFieldToMp4Field.put(FieldKey.YEAR, Mp4FieldKey.DAY);
 
115
        tagFieldToMp4Field.put(FieldKey.ENGINEER, Mp4FieldKey.ENGINEER);
 
116
        tagFieldToMp4Field.put(FieldKey.PRODUCER, Mp4FieldKey.PRODUCER);
 
117
        tagFieldToMp4Field.put(FieldKey.DJMIXER, Mp4FieldKey.DJMIXER);
 
118
        tagFieldToMp4Field.put(FieldKey.MIXER, Mp4FieldKey.MIXER);
 
119
        tagFieldToMp4Field.put(FieldKey.ARRANGER, Mp4FieldKey.ARRANGER);
 
120
    }
 
121
 
 
122
    /**
 
123
     * Create genre field
 
124
     * <p/>
 
125
     * <p>If the content can be parsed to one of the known values use the genre field otherwise
 
126
     * use the custom field.
 
127
     *
 
128
     * @param content
 
129
     * @return
 
130
     */
 
131
    @SuppressWarnings({"JavaDoc"})
 
132
    private TagField createGenreField(String content)
 
133
    {
 
134
        if (content == null)
 
135
        {
 
136
            throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg());
 
137
        }
 
138
        if (Mp4GenreField.isValidGenre(content))
 
139
        {
 
140
            return new Mp4GenreField(content);
 
141
        }
 
142
        else
 
143
        {
 
144
            return new Mp4TagTextField(GENRE_CUSTOM.getFieldName(), content);
 
145
        }
 
146
    }
 
147
 
 
148
    protected boolean isAllowedEncoding(String enc)
 
149
    {
 
150
        return enc.equals(Mp4BoxHeader.CHARSET_UTF_8);
 
151
    }
 
152
 
 
153
    public String toString()
 
154
    {
 
155
        return "Mpeg4 " + super.toString();
 
156
    }
 
157
 
 
158
 
 
159
    /**
 
160
     * Maps the generic key to the mp4 key and return the list of values for this field
 
161
     *
 
162
     * @param genericKey
 
163
     */
 
164
    @SuppressWarnings({"JavaDoc"})
 
165
    @Override
 
166
    public List<TagField> getFields(FieldKey genericKey) throws KeyNotFoundException
 
167
    {
 
168
        if (genericKey == null)
 
169
        {
 
170
            throw new KeyNotFoundException();
 
171
        }
 
172
        return super.getFields(tagFieldToMp4Field.get(genericKey).getFieldName());
 
173
    }
 
174
 
 
175
 
 
176
    /**
 
177
     * Retrieve the  values that exists for this mp4keyId (this is the internalid actually used)
 
178
     * <p/>
 
179
     *
 
180
     * @param mp4FieldKey
 
181
     * @throws org.jaudiotagger.tag.KeyNotFoundException
 
182
     * @return
 
183
     */
 
184
    public List<TagField> get(Mp4FieldKey mp4FieldKey) throws KeyNotFoundException
 
185
    {
 
186
        if (mp4FieldKey == null)
 
187
        {
 
188
            throw new KeyNotFoundException();
 
189
        }
 
190
        return super.getFields(mp4FieldKey.getFieldName());
 
191
    }
 
192
 
 
193
    /**
 
194
     * Retrieve the indexed value that exists for this generic key
 
195
     *
 
196
     * @param genericKey
 
197
     * @return
 
198
     */
 
199
    public String getValue(FieldKey genericKey, int index) throws KeyNotFoundException
 
200
    {
 
201
        if (genericKey == null)
 
202
        {
 
203
            throw new KeyNotFoundException();
 
204
        }
 
205
 
 
206
        if(genericKey== FieldKey.GENRE)
 
207
        {
 
208
            List<TagField> genres = getFields(GENRE.getFieldName());
 
209
            if (genres.size() == 0)
 
210
            {
 
211
                genres = getFields(GENRE_CUSTOM.getFieldName());
 
212
            }
 
213
            if(genres.size()>index)
 
214
            {
 
215
                return ((TagTextField)genres.get(index)).getContent();
 
216
            }
 
217
            else
 
218
            {
 
219
                return "";
 
220
            }
 
221
 
 
222
        }
 
223
        else if(genericKey== FieldKey.TRACK)
 
224
        {
 
225
            List<TagField> list = get(tagFieldToMp4Field.get(genericKey));
 
226
            if(list.size()>index)
 
227
            {
 
228
                Mp4TrackField trackField = (Mp4TrackField)list.get(index);
 
229
                if(trackField.getTrackNo()>0)
 
230
                {
 
231
                    return String.valueOf(trackField.getTrackNo());
 
232
                }
 
233
            }
 
234
        }
 
235
        else if(genericKey== FieldKey.TRACK_TOTAL)
 
236
        {
 
237
            List<TagField> list = get(tagFieldToMp4Field.get(genericKey));
 
238
            if(list.size()>index)
 
239
            {
 
240
                Mp4TrackField trackField = (Mp4TrackField)list.get(index);
 
241
                if(trackField.getTrackTotal()>0)
 
242
                {
 
243
                    return String.valueOf(trackField.getTrackTotal());
 
244
                }
 
245
            }
 
246
        }
 
247
        else if(genericKey== FieldKey.DISC_NO)
 
248
        {
 
249
            List<TagField> list = get(tagFieldToMp4Field.get(genericKey));
 
250
            if(list.size()>index)
 
251
            {
 
252
                Mp4DiscNoField discField = (Mp4DiscNoField)list.get(index);
 
253
                if(discField.getDiscNo()>0)
 
254
                {
 
255
                     return String.valueOf(discField.getDiscNo());
 
256
                }
 
257
 
 
258
            }
 
259
        }
 
260
        else if(genericKey== FieldKey.DISC_TOTAL)
 
261
        {
 
262
            List<TagField> list = get(tagFieldToMp4Field.get(genericKey));
 
263
            if(list.size()>index)
 
264
            {
 
265
                Mp4DiscNoField discField = (Mp4DiscNoField)list.get(index);
 
266
                if(discField.getDiscTotal()>0)
 
267
                {
 
268
                     return String.valueOf(discField.getDiscTotal());
 
269
                }
 
270
            }
 
271
        }
 
272
        else
 
273
        {
 
274
            return super.getItem(tagFieldToMp4Field.get(genericKey).getFieldName(), index);
 
275
        }
 
276
        return "";
 
277
    }
 
278
 
 
279
  /**
 
280
     * Retrieve the first value that exists for this mp4key
 
281
     *
 
282
     * @param mp4Key
 
283
     * @return
 
284
     * @throws org.jaudiotagger.tag.KeyNotFoundException
 
285
     */
 
286
    public String getFirst(Mp4FieldKey mp4Key) throws KeyNotFoundException
 
287
    {
 
288
        if (mp4Key == null)
 
289
        {
 
290
            throw new KeyNotFoundException();
 
291
        }
 
292
        return super.getFirst(mp4Key.getFieldName());
 
293
    }
 
294
 
 
295
    public Mp4TagField getFirstField(FieldKey genericKey) throws KeyNotFoundException
 
296
    {
 
297
        if (genericKey == null)
 
298
        {
 
299
            throw new KeyNotFoundException();
 
300
        }
 
301
        return (Mp4TagField)super.getFirstField(tagFieldToMp4Field.get(genericKey).getFieldName());
 
302
    }
 
303
 
 
304
    public Mp4TagField getFirstField(Mp4FieldKey mp4Key) throws KeyNotFoundException
 
305
    {
 
306
        if (mp4Key == null)
 
307
        {
 
308
            throw new KeyNotFoundException();
 
309
        }
 
310
        return (Mp4TagField) super.getFirstField(mp4Key.getFieldName());
 
311
    }
 
312
 
 
313
    /**
 
314
     * Delete fields with this generic key
 
315
     *
 
316
     * @param genericKey
 
317
     */
 
318
    public void deleteField(FieldKey genericKey) throws KeyNotFoundException
 
319
    {
 
320
        if (genericKey == null)
 
321
        {
 
322
            throw new KeyNotFoundException();
 
323
        }
 
324
        super.deleteField(tagFieldToMp4Field.get(genericKey).getFieldName());
 
325
    }
 
326
 
 
327
    /**
 
328
     * Delete fields with this mp4key
 
329
     *
 
330
     * @param mp4Key
 
331
     * @throws org.jaudiotagger.tag.KeyNotFoundException
 
332
     */
 
333
    public void deleteField(Mp4FieldKey mp4Key) throws KeyNotFoundException
 
334
    {
 
335
        if (mp4Key == null)
 
336
        {
 
337
            throw new KeyNotFoundException();
 
338
        }
 
339
        super.deleteField(mp4Key.getFieldName());
 
340
    }
 
341
 
 
342
    /**
 
343
     * Create artwork field
 
344
     *
 
345
     * @param data raw image data
 
346
     * @return
 
347
     * @throws org.jaudiotagger.tag.FieldDataInvalidException
 
348
     */
 
349
    public TagField createArtworkField(byte[] data)
 
350
    {
 
351
        return new Mp4TagCoverField(data);
 
352
    }
 
353
 
 
354
     /**
 
355
     * Create artwork field
 
356
     *    
 
357
     * @return
 
358
     */
 
359
    public TagField createField(Artwork artwork) throws FieldDataInvalidException
 
360
    {
 
361
        return new Mp4TagCoverField(artwork.getBinaryData());
 
362
    }
 
363
 
 
364
    /**
 
365
     * Create Tag Field using generic key
 
366
     * <p/>
 
367
     * This should use the correct subclass for the key
 
368
     *
 
369
     * @param genericKey
 
370
     * @param value
 
371
     * @return
 
372
     * @throws KeyNotFoundException
 
373
     * @throws FieldDataInvalidException
 
374
     */
 
375
    @Override
 
376
    public TagField createField(FieldKey genericKey, String value) throws KeyNotFoundException, FieldDataInvalidException
 
377
    {
 
378
        if (value == null)
 
379
        {
 
380
            throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg());
 
381
        }
 
382
        if (genericKey == null)
 
383
        {
 
384
            throw new KeyNotFoundException();
 
385
        }
 
386
 
 
387
        //Special handling for these number fields
 
388
        if(
 
389
                (genericKey== FieldKey.TRACK)||
 
390
                (genericKey== FieldKey.TRACK_TOTAL)||
 
391
                (genericKey== FieldKey.DISC_NO)||
 
392
                (genericKey== FieldKey.DISC_TOTAL)
 
393
            )
 
394
        {
 
395
            try
 
396
            {
 
397
                int number = Integer.parseInt(value);
 
398
                if(genericKey== FieldKey.TRACK)
 
399
                {
 
400
                    return new Mp4TrackField(number);
 
401
                }
 
402
                else if(genericKey== FieldKey.TRACK_TOTAL)
 
403
                {
 
404
                    return new Mp4TrackField(0,number);
 
405
                }
 
406
                else if(genericKey== FieldKey.DISC_NO)
 
407
                {
 
408
                    return new Mp4DiscNoField(number);
 
409
                }
 
410
                else if(genericKey== FieldKey.DISC_TOTAL)
 
411
                {
 
412
                    return new Mp4DiscNoField(0,number);
 
413
                }
 
414
            }
 
415
            catch(NumberFormatException nfe)
 
416
            {
 
417
                //If not number we want to convert to an expected exception (which is not a RuntimeException)
 
418
                //so can be handled properly by calling program
 
419
                throw new FieldDataInvalidException("Value "+value + " is not a number as required",nfe);
 
420
            }
 
421
        }
 
422
 
 
423
        //Default for all other fields
 
424
        return createField(tagFieldToMp4Field.get(genericKey), value);
 
425
 
 
426
    }
 
427
 
 
428
    /**
 
429
     * Set field, special handling for track and disc because they hold two fields
 
430
     * 
 
431
     * @param field
 
432
     */
 
433
    @Override
 
434
    public void setField(TagField field)
 
435
    {
 
436
        if (field == null)
 
437
        {
 
438
            return;
 
439
        }
 
440
 
 
441
        if(field.getId().equals(TRACK.getFieldName()))
 
442
        {
 
443
            List<TagField> list = fields.get(field.getId());
 
444
            if(list==null||list.size()==0)
 
445
            {
 
446
                 super.setField(field);
 
447
            }
 
448
            else
 
449
            {
 
450
                Mp4TrackField existingTrackField = (Mp4TrackField)list.get(0);
 
451
                Mp4TrackField newTrackField      = (Mp4TrackField)field;
 
452
                Short trackNo    = existingTrackField.getTrackNo();
 
453
                Short trackTotal = existingTrackField.getTrackTotal();
 
454
                if(newTrackField.getTrackNo()>0 )
 
455
                {
 
456
                    trackNo = newTrackField.getTrackNo();
 
457
                }
 
458
                if(newTrackField.getTrackTotal()>0 )
 
459
                {
 
460
                    trackTotal = newTrackField.getTrackTotal();
 
461
                }
 
462
 
 
463
                Mp4TrackField mergedTrackField = new Mp4TrackField(trackNo,trackTotal);
 
464
                super.setField(mergedTrackField);
 
465
            }
 
466
        }
 
467
        else if(field.getId().equals(DISCNUMBER.getFieldName()))
 
468
        {
 
469
            List<TagField> list = fields.get(field.getId());
 
470
            if(list==null||list.size()==0)
 
471
            {
 
472
                 super.setField(field);
 
473
            }
 
474
            else
 
475
            {
 
476
                Mp4DiscNoField existingDiscNoField = (Mp4DiscNoField)list.get(0);
 
477
                Mp4DiscNoField newDiscNoField      = (Mp4DiscNoField)field;
 
478
                Short discNo    = existingDiscNoField.getDiscNo();
 
479
                Short discTotal = existingDiscNoField.getDiscTotal();
 
480
                if(newDiscNoField.getDiscNo()>0 )
 
481
                {
 
482
                    discNo = newDiscNoField.getDiscNo();
 
483
                }
 
484
                if(newDiscNoField.getDiscTotal()>0 )
 
485
                {
 
486
                    discTotal = newDiscNoField.getDiscTotal();
 
487
                }
 
488
 
 
489
                Mp4DiscNoField mergedDiscNoField = new Mp4DiscNoField(discNo,discTotal);
 
490
                super.setField(mergedDiscNoField);
 
491
            }
 
492
        }
 
493
        else
 
494
        {
 
495
            super.setField(field);
 
496
        }
 
497
    }
 
498
 
 
499
    /**
 
500
     * Create Tag Field using mp4 key
 
501
     * <p/>
 
502
     * Uses the correct subclass for the key
 
503
     *
 
504
     * @param mp4FieldKey
 
505
     * @param value
 
506
     * @return
 
507
     * @throws KeyNotFoundException
 
508
     * @throws FieldDataInvalidException
 
509
     */
 
510
    public TagField createField(Mp4FieldKey mp4FieldKey, String value) throws KeyNotFoundException, FieldDataInvalidException
 
511
    {
 
512
        if (value == null)
 
513
        {
 
514
            throw new IllegalArgumentException(ErrorMessage.GENERAL_INVALID_NULL_ARGUMENT.getMsg());
 
515
        }
 
516
        if (mp4FieldKey == null)
 
517
        {
 
518
            throw new KeyNotFoundException();
 
519
        }
 
520
 
 
521
        //This is boolean stored as 1, but calling program might setField as 'true' so we handle this
 
522
        //case internally
 
523
        if(mp4FieldKey==Mp4FieldKey.COMPILATION)
 
524
        {
 
525
            if(value.equals("true"))
 
526
            {
 
527
                value= Mp4TagByteField.TRUE_VALUE;
 
528
            }
 
529
            return new Mp4TagByteField(mp4FieldKey, value, mp4FieldKey.getFieldLength());
 
530
        }
 
531
        else if(mp4FieldKey==Mp4FieldKey.GENRE)
 
532
        {
 
533
            return createGenreField(value);
 
534
        }
 
535
        else if(mp4FieldKey.getSubClassFieldType()==Mp4TagFieldSubType.DISC_NO)
 
536
        {
 
537
            return new Mp4DiscNoField(value);
 
538
        }
 
539
        else if(mp4FieldKey.getSubClassFieldType()==Mp4TagFieldSubType.TRACK_NO)
 
540
        {
 
541
            return new Mp4TrackField(value);
 
542
        }
 
543
        else if(mp4FieldKey.getSubClassFieldType()==Mp4TagFieldSubType.BYTE)
 
544
        {
 
545
            return new Mp4TagByteField(mp4FieldKey, value, mp4FieldKey.getFieldLength());
 
546
        }
 
547
        else if(mp4FieldKey.getSubClassFieldType()==Mp4TagFieldSubType.NUMBER)
 
548
        {
 
549
            return new Mp4TagTextNumberField(mp4FieldKey.getFieldName(), value);
 
550
        }
 
551
        else if(mp4FieldKey.getSubClassFieldType()==Mp4TagFieldSubType.REVERSE_DNS)
 
552
        {
 
553
            return new Mp4TagReverseDnsField(mp4FieldKey, value);
 
554
        }
 
555
        else if(mp4FieldKey.getSubClassFieldType()==Mp4TagFieldSubType.ARTWORK)
 
556
        {
 
557
            throw new UnsupportedOperationException(ErrorMessage.ARTWORK_CANNOT_BE_CREATED_WITH_THIS_METHOD.getMsg());
 
558
        }
 
559
        else if(mp4FieldKey.getSubClassFieldType()==Mp4TagFieldSubType.TEXT)
 
560
        {
 
561
            return new Mp4TagTextField(mp4FieldKey.getFieldName(), value);
 
562
        }
 
563
        else if(mp4FieldKey.getSubClassFieldType()==Mp4TagFieldSubType.UNKNOWN)
 
564
        {
 
565
            throw new UnsupportedOperationException(ErrorMessage.DO_NOT_KNOW_HOW_TO_CREATE_THIS_ATOM_TYPE.getMsg(mp4FieldKey.getFieldName()));
 
566
        }
 
567
        else
 
568
        {
 
569
            throw new UnsupportedOperationException(ErrorMessage.DO_NOT_KNOW_HOW_TO_CREATE_THIS_ATOM_TYPE.getMsg(mp4FieldKey.getFieldName()));
 
570
        }
 
571
    }
 
572
 
 
573
    public List<Artwork> getArtworkList()
 
574
    {
 
575
        List<TagField> coverartList = get(Mp4FieldKey.ARTWORK);
 
576
        List<Artwork> artworkList = new ArrayList<Artwork>(coverartList.size());
 
577
 
 
578
        for(TagField next:coverartList)
 
579
        {
 
580
            Mp4TagCoverField mp4CoverArt = (Mp4TagCoverField)next;
 
581
            Artwork artwork = new Artwork();
 
582
            artwork.setBinaryData(mp4CoverArt.getData());
 
583
            artwork.setMimeType(Mp4TagCoverField.getMimeTypeForImageType(mp4CoverArt.getFieldType()));
 
584
            artworkList.add(artwork);
 
585
        }
 
586
        return artworkList;
 
587
    }
 
588
 
 
589
}