~ubuntu-branches/ubuntu/gutsy/kid3/gutsy

« back to all changes in this revision

Viewing changes to kid3/mp3file.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Mercatante
  • Date: 2007-07-01 00:31:03 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20070701003103-2qownnv49a7jdqm3
Tags: 0.9-0ubuntu1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
#include "standardtags.h"
29
29
#include "mp3framelist.h"
30
30
#include "genres.h"
 
31
#include "dirinfo.h"
31
32
#include <sys/stat.h>
32
33
#ifdef WIN32
33
34
#include <sys/utime.h>
49
50
/**
50
51
 * Constructor.
51
52
 *
52
 
 * @param dn directory name
 
53
 * @param di directory information
53
54
 * @param fn filename
54
55
 */
55
 
 
56
 
Mp3File::Mp3File(const QString& dn, const QString& fn) :
57
 
        TaggedFile(dn, fn)
 
56
Mp3File::Mp3File(const DirInfo* di, const QString& fn) :
 
57
        TaggedFile(di, fn), m_tagV1(0), m_tagV2(0)
58
58
{
59
 
        tagV1 = 0;
60
 
        tagV2 = 0;
61
59
}
62
60
 
63
61
/**
64
62
 * Destructor.
65
63
 */
66
 
 
67
 
Mp3File::~Mp3File(void)
 
64
Mp3File::~Mp3File()
68
65
{
69
 
        if (tagV1) {
70
 
                delete tagV1;
 
66
        if (m_tagV1) {
 
67
                delete m_tagV1;
71
68
        }
72
 
        if (tagV2) {
73
 
                delete tagV2;
 
69
        if (m_tagV2) {
 
70
                delete m_tagV2;
74
71
        }
75
72
}
76
73
 
77
74
/**
78
75
 * Read tags from file.
79
76
 *
80
 
 * @param force TRUE to force reading even if tags were already read.
 
77
 * @param force true to force reading even if tags were already read.
81
78
 */
82
 
 
83
79
void Mp3File::readTags(bool force)
84
80
{
85
 
        Q3CString fn = QFile::encodeName(dirname + QDir::separator() + filename);
 
81
        Q3CString fn = QFile::encodeName(getDirInfo()->getDirname() + QDir::separator() + currentFilename());
86
82
 
87
 
        if (force && tagV1) {
88
 
                tagV1->Clear();
89
 
                tagV1->Link(fn, ID3TT_ID3V1);
90
 
                changedV1 = FALSE;
 
83
        if (force && m_tagV1) {
 
84
                m_tagV1->Clear();
 
85
                m_tagV1->Link(fn, ID3TT_ID3V1);
 
86
                markTag1Changed(false);
91
87
        }
92
 
        if (!tagV1) {
93
 
                tagV1 = new ID3_Tag;
94
 
                if (tagV1) {
95
 
                        tagV1->Link(fn, ID3TT_ID3V1);
96
 
                        changedV1 = FALSE;
 
88
        if (!m_tagV1) {
 
89
                m_tagV1 = new ID3_Tag;
 
90
                if (m_tagV1) {
 
91
                        m_tagV1->Link(fn, ID3TT_ID3V1);
 
92
                        markTag1Changed(false);
97
93
                }
98
94
        }
99
95
 
100
 
        if (force && tagV2) {
101
 
                tagV2->Clear();
102
 
                tagV2->Link(fn, ID3TT_ID3V2);
103
 
                changedV2 = FALSE;
 
96
        if (force && m_tagV2) {
 
97
                m_tagV2->Clear();
 
98
                m_tagV2->Link(fn, ID3TT_ID3V2);
 
99
                markTag2Changed(false);
104
100
        }
105
 
        if (!tagV2) {
106
 
                tagV2 = new ID3_Tag;
107
 
                if (tagV2) {
108
 
                        tagV2->Link(fn, ID3TT_ID3V2);
109
 
                        changedV2 = FALSE;
 
101
        if (!m_tagV2) {
 
102
                m_tagV2 = new ID3_Tag;
 
103
                if (m_tagV2) {
 
104
                        m_tagV2->Link(fn, ID3TT_ID3V2);
 
105
                        markTag2Changed(false);
110
106
                }
111
107
        }
112
108
 
113
109
        if (force) {
114
 
                new_filename = filename;
 
110
                setFilename(currentFilename());
115
111
        }
116
112
}
117
113
 
118
114
/**
119
115
 * Write tags to file and rename it if necessary.
120
116
 *
121
 
 * @param force   TRUE to force writing even if file was not changed.
122
 
 * @param renamed will be set to TRUE if the file was renamed,
 
117
 * @param force   true to force writing even if file was not changed.
 
118
 * @param renamed will be set to true if the file was renamed,
123
119
 *                i.e. the file name is no longer valid, else *renamed
124
120
 *                is left unchanged
125
121
 * @param preserve true to preserve file time stamps
126
122
 *
127
 
 * @return TRUE if ok, FALSE if the file could not be written or renamed.
 
123
 * @return true if ok, false if the file could not be written or renamed.
128
124
 */
129
 
 
130
 
bool Mp3File::writeTags(bool force, bool *renamed, bool preserve)
 
125
bool Mp3File::writeTags(bool force, bool* renamed, bool preserve)
131
126
{
132
 
        QString fnStr(dirname + QDir::separator() + filename);
 
127
        QString fnStr(getDirInfo()->getDirname() + QDir::separator() + currentFilename());
133
128
        if (isChanged() && !QFileInfo(fnStr).isWritable()) {
134
 
                return FALSE;
 
129
                return false;
135
130
        }
136
131
 
137
132
        // store time stamp if it has to be preserved
151
146
        // There seems to be a bug in id3lib: The V1 genre is not
152
147
        // removed. So we check here and strip the whole header
153
148
        // if there are no frames.
154
 
        if (tagV1 && (force || changedV1) && (tagV1->NumFrames() == 0)) {
155
 
                tagV1->Strip(ID3TT_ID3V1);
156
 
                changedV1 = FALSE;
 
149
        if (m_tagV1 && (force || isTag1Changed()) && (m_tagV1->NumFrames() == 0)) {
 
150
                m_tagV1->Strip(ID3TT_ID3V1);
 
151
                markTag1Changed(false);
157
152
        }
158
153
        // Even after removing all frames, HasV2Tag() still returns true,
159
154
        // so we strip the whole header.
160
 
        if (tagV2 && (force || changedV2) && (tagV2->NumFrames() == 0)) {
161
 
                tagV2->Strip(ID3TT_ID3V2);
162
 
                changedV2 = FALSE;
 
155
        if (m_tagV2 && (force || isTag2Changed()) && (m_tagV2->NumFrames() == 0)) {
 
156
                m_tagV2->Strip(ID3TT_ID3V2);
 
157
                markTag2Changed(false);
163
158
        }
164
159
        // There seems to be a bug in id3lib: If I update an ID3v1 and then
165
160
        // strip the ID3v2 the ID3v1 is removed too and vice versa, so I
166
161
        // first make any stripping and then the updating.
167
 
        if (tagV1 && (force || changedV1) && (tagV1->NumFrames() > 0)) {
168
 
                tagV1->Update(ID3TT_ID3V1);
169
 
                changedV1 = FALSE;
 
162
        if (m_tagV1 && (force || isTag1Changed()) && (m_tagV1->NumFrames() > 0)) {
 
163
                m_tagV1->Update(ID3TT_ID3V1);
 
164
                markTag1Changed(false);
170
165
        }
171
 
        if (tagV2 && (force || changedV2) && (tagV2->NumFrames() > 0)) {
172
 
                tagV2->Update(ID3TT_ID3V2);
173
 
                changedV2 = FALSE;
 
166
        if (m_tagV2 && (force || isTag2Changed()) && (m_tagV2->NumFrames() > 0)) {
 
167
                m_tagV2->Update(ID3TT_ID3V2);
 
168
                markTag2Changed(false);
174
169
        }
175
170
 
176
171
        // restore time stamp
178
173
                ::utime(fn, &times);
179
174
        }
180
175
 
181
 
        if (new_filename != filename) {
182
 
                if (!renameFile(filename, new_filename)) {
183
 
                        return FALSE;
 
176
        if (getFilename() != currentFilename()) {
 
177
                if (!renameFile(currentFilename(), getFilename())) {
 
178
                        return false;
184
179
                }
185
 
                *renamed = TRUE;
 
180
                updateCurrentFilename();
 
181
                // link tags to new file name
 
182
                readTags(true);
 
183
                *renamed = true;
186
184
        }
187
 
        return TRUE;
 
185
        return true;
188
186
}
189
187
 
190
188
/**
192
190
 *
193
191
 * @param flt filter specifying which fields to remove
194
192
 */
195
 
 
196
193
void Mp3File::removeTagsV1(const StandardTagsFilter& flt)
197
194
{
198
 
        if (tagV1) {
 
195
        if (m_tagV1) {
199
196
                if (flt.areAllTrue()) {
200
 
                        ID3_Tag::Iterator* iter = tagV1->CreateIterator();
 
197
                        ID3_Tag::Iterator* iter = m_tagV1->CreateIterator();
201
198
                        ID3_Frame* frame;
202
199
                        while ((frame = iter->GetNext()) != NULL) {
203
 
                                tagV1->RemoveFrame(frame);
 
200
                                m_tagV1->RemoveFrame(frame);
204
201
                        }
205
202
#ifdef WIN32
206
203
                        /* allocated in Windows DLL => must be freed in the same DLL */
208
205
#else
209
206
                        delete iter;
210
207
#endif
211
 
                        changedV1 = TRUE;
 
208
                        markTag1Changed();
 
209
                        clearTrunctionFlags();
212
210
                } else {
213
211
                        removeStandardTagsV1(flt);
214
212
                }
220
218
 *
221
219
 * @param flt filter specifying which fields to remove
222
220
 */
223
 
 
224
221
void Mp3File::removeTagsV2(const StandardTagsFilter& flt)
225
222
{
226
 
        if (tagV2) {
 
223
        if (m_tagV2) {
227
224
                if (flt.areAllTrue()) {
228
 
                        ID3_Tag::Iterator* iter = tagV2->CreateIterator();
 
225
                        ID3_Tag::Iterator* iter = m_tagV2->CreateIterator();
229
226
                        ID3_Frame* frame;
230
227
                        while ((frame = iter->GetNext()) != NULL) {
231
 
                                tagV2->RemoveFrame(frame);
 
228
                                m_tagV2->RemoveFrame(frame);
232
229
                        }
233
230
#ifdef WIN32
234
231
                        /* allocated in Windows DLL => must be freed in the same DLL */
236
233
#else
237
234
                        delete iter;
238
235
#endif
239
 
                        changedV2 = TRUE;
 
236
                        markTag2Changed();
240
237
                } else {
241
238
                        removeStandardTagsV2(flt);
242
239
                }
251
248
 * @return string,
252
249
 *         "" if the field does not exist.
253
250
 */
254
 
 
255
251
QString Mp3File::getString(ID3_Field* field)
256
252
{
257
253
        QString text("");
258
254
        if (field != NULL) {
259
255
                ID3_TextEnc enc = field->GetEncoding();
260
256
                if (enc == ID3TE_UTF16 || enc == ID3TE_UTF16BE) {
261
 
                        const unicode_t *txt = field->GetRawUnicodeText();
 
257
                        const unicode_t* txt = field->GetRawUnicodeText();
262
258
                        uint unicode_size = field->Size() / sizeof(unicode_t);
263
259
                        if (unicode_size && txt) {
264
 
                                QChar *qcarray = new QChar[unicode_size];
 
260
                                QChar* qcarray = new QChar[unicode_size];
265
261
                                if (qcarray) {
266
262
                                        // Unfortunately, Unicode support in id3lib is rather buggy
267
263
                                        // in the current version: The codes are mirrored.
303
299
 *         "" if the field does not exist,
304
300
 *         QString::null if the tags do not exist.
305
301
 */
306
 
 
307
 
QString Mp3File::getTextField(const ID3_Tag *tag, ID3_FrameID id)
 
302
QString Mp3File::getTextField(const ID3_Tag* tag, ID3_FrameID id)
308
303
{
309
304
        if (!tag) {
310
305
                return QString::null;
311
306
        }
312
307
        QString str("");
313
308
        ID3_Field* fld;
314
 
        ID3_Frame *frame = tag->Find(id);
 
309
        ID3_Frame* frame = tag->Find(id);
315
310
        if (frame && ((fld = frame->GetField(ID3FN_TEXT)) != NULL)) {
316
311
                str = getString(fld);
317
312
        }
326
321
 *         0 if the field does not exist,
327
322
 *         -1 if the tags do not exist.
328
323
 */
329
 
 
330
 
int Mp3File::getYear(const ID3_Tag *tag)
 
324
int Mp3File::getYear(const ID3_Tag* tag)
331
325
{
332
326
        QString str = getTextField(tag, ID3FID_YEAR);
333
327
        if (str.isNull()) return -1;
343
337
 *         0 if the field does not exist,
344
338
 *         -1 if the tags do not exist.
345
339
 */
346
 
 
347
 
int Mp3File::getTrackNum(const ID3_Tag *tag)
 
340
int Mp3File::getTrackNum(const ID3_Tag* tag)
348
341
{
349
342
        QString str = getTextField(tag, ID3FID_TRACKNUM);
350
343
        if (str.isNull()) return -1;
365
358
 *         0xff if the field does not exist,
366
359
 *         -1 if the tags do not exist.
367
360
 */
368
 
 
369
 
int Mp3File::getGenreNum(const ID3_Tag *tag)
 
361
int Mp3File::getGenreNum(const ID3_Tag* tag)
370
362
{
371
363
        QString str = getTextField(tag, ID3FID_CONTENTTYPE);
372
364
        if (str.isNull()) return -1;
393
385
 * @param field        field
394
386
 * @param text         text to set
395
387
 */
396
 
 
397
 
void Mp3File::setString(ID3_Field* field, const QString &text)
 
388
void Mp3File::setString(ID3_Field* field, const QString& text)
398
389
{
399
390
        ID3_TextEnc enc = field->GetEncoding();
400
391
        // (ID3TE_IS_DOUBLE_BYTE_ENC(enc))
408
399
                // In the hope that my patches will be included, I try here to
409
400
                // work around these bugs, but there is no solution for the
410
401
                // LSB >= 0x80 bug.
411
 
                const QChar *qcarray = text.unicode();
 
402
                const QChar* qcarray = text.unicode();
412
403
                uint unicode_size = text.length();
413
 
                unicode_t *unicode = new unicode_t[unicode_size + 1];
 
404
                unicode_t* unicode = new unicode_t[unicode_size + 1];
414
405
                if (unicode) {
415
406
                        uint i;
416
407
                        for (i = 0; i < unicode_size; i++) {
444
435
 *
445
436
 * @return true if the field was changed.
446
437
 */
447
 
 
448
 
bool Mp3File::setTextField(ID3_Tag *tag, ID3_FrameID id, const QString &text,
 
438
bool Mp3File::setTextField(ID3_Tag* tag, ID3_FrameID id, const QString& text,
449
439
                                                   bool allowUnicode, bool replace, bool removeEmpty)
450
440
{
451
441
        bool changed = false;
466
456
                                        if (allowUnicode && fld->GetEncoding() == ID3TE_ISO8859_1) {
467
457
                                                // check if information is lost if the string is not unicode
468
458
                                                uint i, unicode_size = text.length();
469
 
                                                const QChar *qcarray = text.unicode();
 
459
                                                const QChar* qcarray = text.unicode();
470
460
                                                for (i = 0; i < unicode_size; i++) {
471
461
                                                        if (qcarray[i].latin1() == 0) {
472
 
                                                                ID3_Field *encfld = frame->GetField(ID3FN_TEXTENC);
 
462
                                                                ID3_Field* encfld = frame->GetField(ID3FN_TEXTENC);
473
463
                                                                if (encfld) {
474
464
                                                                        encfld->Set(ID3TE_UTF16);
475
465
                                                                }
496
486
 *
497
487
 * @return true if the field was changed.
498
488
 */
499
 
 
500
 
bool Mp3File::setYear(ID3_Tag *tag, int num)
 
489
bool Mp3File::setYear(ID3_Tag* tag, int num)
501
490
{
502
491
        bool changed = false;
503
492
        if (num >= 0) {
521
510
 *
522
511
 * @return true if the field was changed.
523
512
 */
524
 
 
525
 
bool Mp3File::setTrackNum(ID3_Tag *tag, int num, int numTracks)
 
513
bool Mp3File::setTrackNum(ID3_Tag* tag, int num, int numTracks)
526
514
{
527
515
        bool changed = false;
528
516
        if (num >= 0) {
549
537
 *
550
538
 * @return true if the field was changed.
551
539
 */
552
 
 
553
 
bool Mp3File::setGenreNum(ID3_Tag *tag, int num)
 
540
bool Mp3File::setGenreNum(ID3_Tag* tag, int num)
554
541
{
555
542
        bool changed = false;
556
543
        if (num >= 0) {
572
559
 *         "" if the field does not exist,
573
560
 *         QString::null if the tags do not exist.
574
561
 */
575
 
 
576
 
QString Mp3File::getTitleV1(void)
 
562
QString Mp3File::getTitleV1()
577
563
{
578
 
        return getTextField(tagV1, ID3FID_TITLE);
 
564
        return getTextField(m_tagV1, ID3FID_TITLE);
579
565
}
580
566
 
581
567
/**
585
571
 *         "" if the field does not exist,
586
572
 *         QString::null if the tags do not exist.
587
573
 */
588
 
 
589
 
QString Mp3File::getArtistV1(void)
 
574
QString Mp3File::getArtistV1()
590
575
{
591
 
        return getTextField(tagV1, ID3FID_LEADARTIST);
 
576
        return getTextField(m_tagV1, ID3FID_LEADARTIST);
592
577
}
593
578
 
594
579
/**
598
583
 *         "" if the field does not exist,
599
584
 *         QString::null if the tags do not exist.
600
585
 */
601
 
 
602
 
QString Mp3File::getAlbumV1(void)
 
586
QString Mp3File::getAlbumV1()
603
587
{
604
 
        return getTextField(tagV1, ID3FID_ALBUM);
 
588
        return getTextField(m_tagV1, ID3FID_ALBUM);
605
589
}
606
590
 
607
591
/**
611
595
 *         "" if the field does not exist,
612
596
 *         QString::null if the tags do not exist.
613
597
 */
614
 
 
615
 
QString Mp3File::getCommentV1(void)
 
598
QString Mp3File::getCommentV1()
616
599
{
617
 
        return getTextField(tagV1, ID3FID_COMMENT);
 
600
        return getTextField(m_tagV1, ID3FID_COMMENT);
618
601
}
619
602
 
620
603
/**
624
607
 *         0 if the field does not exist,
625
608
 *         -1 if the tags do not exist.
626
609
 */
627
 
 
628
 
int Mp3File::getYearV1(void)
 
610
int Mp3File::getYearV1()
629
611
{
630
 
        return getYear(tagV1);
 
612
        return getYear(m_tagV1);
631
613
}
632
614
 
633
615
/**
637
619
 *         0 if the field does not exist,
638
620
 *         -1 if the tags do not exist.
639
621
 */
640
 
 
641
 
int Mp3File::getTrackNumV1(void)
 
622
int Mp3File::getTrackNumV1()
642
623
{
643
 
        return getTrackNum(tagV1);
 
624
        return getTrackNum(m_tagV1);
644
625
}
645
626
 
646
627
/**
647
628
 * Get ID3v1 genre.
648
629
 *
649
 
 * @return number,
650
 
 *         0xff if the field does not exist,
651
 
 *         -1 if the tags do not exist.
 
630
 * @return string,
 
631
 *         "" if the field does not exist,
 
632
 *         QString::null if the tags do not exist.
652
633
 */
653
 
 
654
 
int Mp3File::getGenreNumV1(void)
 
634
QString Mp3File::getGenreV1()
655
635
{
656
 
        return getGenreNum(tagV1);
 
636
        int num = getGenreNum(m_tagV1);
 
637
        if (num == -1) {
 
638
                return QString::null;
 
639
        } else if (num == 0xff) {
 
640
                return "";
 
641
        } else {
 
642
                return Genres::getName(num);
 
643
        }
657
644
}
658
645
 
659
646
/**
663
650
 *         "" if the field does not exist,
664
651
 *         QString::null if the tags do not exist.
665
652
 */
666
 
 
667
 
QString Mp3File::getTitleV2(void)
 
653
QString Mp3File::getTitleV2()
668
654
{
669
 
        return getTextField(tagV2, ID3FID_TITLE);
 
655
        return getTextField(m_tagV2, ID3FID_TITLE);
670
656
}
671
657
 
672
658
/**
676
662
 *         "" if the field does not exist,
677
663
 *         QString::null if the tags do not exist.
678
664
 */
679
 
 
680
 
QString Mp3File::getArtistV2(void)
 
665
QString Mp3File::getArtistV2()
681
666
{
682
 
        return getTextField(tagV2, ID3FID_LEADARTIST);
 
667
        return getTextField(m_tagV2, ID3FID_LEADARTIST);
683
668
}
684
669
 
685
670
/**
689
674
 *         "" if the field does not exist,
690
675
 *         QString::null if the tags do not exist.
691
676
 */
692
 
 
693
 
QString Mp3File::getAlbumV2(void)
 
677
QString Mp3File::getAlbumV2()
694
678
{
695
 
        return getTextField(tagV2, ID3FID_ALBUM);
 
679
        return getTextField(m_tagV2, ID3FID_ALBUM);
696
680
}
697
681
 
698
682
/**
702
686
 *         "" if the field does not exist,
703
687
 *         QString::null if the tags do not exist.
704
688
 */
705
 
 
706
 
QString Mp3File::getCommentV2(void)
 
689
QString Mp3File::getCommentV2()
707
690
{
708
 
        return getTextField(tagV2, ID3FID_COMMENT);
 
691
        return getTextField(m_tagV2, ID3FID_COMMENT);
709
692
}
710
693
 
711
694
/**
715
698
 *         0 if the field does not exist,
716
699
 *         -1 if the tags do not exist.
717
700
 */
718
 
 
719
 
int Mp3File::getYearV2(void)
 
701
int Mp3File::getYearV2()
720
702
{
721
 
        return getYear(tagV2);
 
703
        return getYear(m_tagV2);
722
704
}
723
705
 
724
706
/**
728
710
 *         0 if the field does not exist,
729
711
 *         -1 if the tags do not exist.
730
712
 */
731
 
 
732
 
int Mp3File::getTrackNumV2(void)
733
 
{
734
 
        return getTrackNum(tagV2);
735
 
}
736
 
 
737
 
/**
738
 
 * Get ID3v2 genre.
739
 
 *
740
 
 * @return number,
741
 
 *         0xff if the field does not exist,
742
 
 *         -1 if the tags do not exist.
743
 
 */
744
 
 
745
 
int Mp3File::getGenreNumV2(void)
746
 
{
747
 
        return getGenreNum(tagV2);
 
713
int Mp3File::getTrackNumV2()
 
714
{
 
715
        return getTrackNum(m_tagV2);
748
716
}
749
717
 
750
718
/**
756
724
 */
757
725
QString Mp3File::getGenreV2()
758
726
{
759
 
        int num = getGenreNumV2();
 
727
        int num = getGenreNum(m_tagV2);
760
728
        if (num != 0xff && num != -1) {
761
729
                return Genres::getName(num);
762
730
        } else {
763
 
                return getTextField(tagV2, ID3FID_CONTENTTYPE);
 
731
                return getTextField(m_tagV2, ID3FID_CONTENTTYPE);
764
732
        }
765
733
}
766
734
 
769
737
 *
770
738
 * @param str string to set, "" to remove field.
771
739
 */
772
 
 
773
740
void Mp3File::setTitleV1(const QString& str)
774
741
{
775
 
        if (setTextField(tagV1, ID3FID_TITLE, str)) {
776
 
                changedV1 = true;
 
742
        if (setTextField(m_tagV1, ID3FID_TITLE, str)) {
 
743
                markTag1Changed();
 
744
                QString s = checkTruncation(str, StandardTags::TF_Title);
 
745
                if (!s.isNull()) setTextField(m_tagV1, ID3FID_TITLE, s);
777
746
        }
778
747
}
779
748
 
782
751
 *
783
752
 * @param str string to set, "" to remove field.
784
753
 */
785
 
 
786
754
void Mp3File::setArtistV1(const QString& str)
787
755
{
788
 
        if (setTextField(tagV1, ID3FID_LEADARTIST, str)) {
789
 
                changedV1 = true;
 
756
        if (setTextField(m_tagV1, ID3FID_LEADARTIST, str)) {
 
757
                markTag1Changed();
 
758
                QString s = checkTruncation(str, StandardTags::TF_Artist);
 
759
                if (!s.isNull()) setTextField(m_tagV1, ID3FID_LEADARTIST, s);
790
760
        }
791
761
}
792
762
 
795
765
 *
796
766
 * @param str string to set, "" to remove field.
797
767
 */
798
 
 
799
768
void Mp3File::setAlbumV1(const QString& str)
800
769
{
801
 
        if (setTextField(tagV1, ID3FID_ALBUM, str)) {
802
 
                changedV1 = true;
 
770
        if (setTextField(m_tagV1, ID3FID_ALBUM, str)) {
 
771
                markTag1Changed();
 
772
                QString s = checkTruncation(str, StandardTags::TF_Album);
 
773
                if (!s.isNull()) setTextField(m_tagV1, ID3FID_ALBUM, s);
803
774
        }
804
775
}
805
776
 
808
779
 *
809
780
 * @param str string to set, "" to remove field.
810
781
 */
811
 
 
812
782
void Mp3File::setCommentV1(const QString& str)
813
783
{
814
 
        if (setTextField(tagV1, ID3FID_COMMENT, str)) {
815
 
                changedV1 = true;
 
784
        if (setTextField(m_tagV1, ID3FID_COMMENT, str)) {
 
785
                markTag1Changed();
 
786
                QString s = checkTruncation(str, StandardTags::TF_Comment, 28);
 
787
                if (!s.isNull()) setTextField(m_tagV1, ID3FID_COMMENT, s);
816
788
        }
817
789
}
818
790
 
821
793
 *
822
794
 * @param num number to set, 0 to remove field.
823
795
 */
824
 
 
825
796
void Mp3File::setYearV1(int num)
826
797
{
827
 
        if (setYear(tagV1, num)) {
828
 
                changedV1 = true;
 
798
        if (setYear(m_tagV1, num)) {
 
799
                markTag1Changed();
829
800
        }
830
801
}
831
802
 
834
805
 *
835
806
 * @param num number to set, 0 to remove field.
836
807
 */
837
 
 
838
808
void Mp3File::setTrackNumV1(int num)
839
809
{
840
 
        if (setTrackNum(tagV1, num)) {
841
 
                changedV1 = true;
 
810
        if (setTrackNum(m_tagV1, num)) {
 
811
                markTag1Changed();
 
812
                int n = checkTruncation(num, StandardTags::TF_Track);
 
813
                if (n != -1) setTrackNum(m_tagV1, n);
842
814
        }
843
815
}
844
816
 
845
817
/**
846
 
 * Set ID3v1 genre.
 
818
 * Set ID3v1 genre as text.
847
819
 *
848
 
 * @param num number to set, 0xff to remove field.
 
820
 * @param str string to set, "" to remove field, QString::null to ignore.
849
821
 */
850
 
 
851
 
void Mp3File::setGenreNumV1(int num)
 
822
void Mp3File::setGenreV1(const QString& str)
852
823
{
853
 
        if (setGenreNum(tagV1, num)) {
854
 
                changedV1 = true;
 
824
        if (!str.isNull()) {
 
825
                int num = Genres::getNumber(str);
 
826
                if (setGenreNum(m_tagV1, num)) {
 
827
                        markTag1Changed();
 
828
                }
 
829
                // if the string cannot be converted to a number, set the truncation flag
 
830
                checkTruncation(num == 0xff && !str.isEmpty() ? 1 : 0,
 
831
                                                                                StandardTags::TF_Genre, 0);
855
832
        }
856
833
}
857
834
 
860
837
 *
861
838
 * @param str string to set, "" to remove field.
862
839
 */
863
 
 
864
840
void Mp3File::setTitleV2(const QString& str)
865
841
{
866
 
        if (setTextField(tagV2, ID3FID_TITLE, str, true)) {
867
 
                changedV2 = true;
 
842
        if (setTextField(m_tagV2, ID3FID_TITLE, str, true)) {
 
843
                markTag2Changed();
868
844
        }
869
845
}
870
846
 
873
849
 *
874
850
 * @param str string to set, "" to remove field.
875
851
 */
876
 
 
877
852
void Mp3File::setArtistV2(const QString& str)
878
853
{
879
 
        if (setTextField(tagV2, ID3FID_LEADARTIST, str, true)) {
880
 
                changedV2 = true;
 
854
        if (setTextField(m_tagV2, ID3FID_LEADARTIST, str, true)) {
 
855
                markTag2Changed();
881
856
        }
882
857
}
883
858
 
886
861
 *
887
862
 * @param str string to set, "" to remove field.
888
863
 */
889
 
 
890
864
void Mp3File::setAlbumV2(const QString& str)
891
865
{
892
 
        if (setTextField(tagV2, ID3FID_ALBUM, str, true)) {
893
 
                changedV2 = true;
 
866
        if (setTextField(m_tagV2, ID3FID_ALBUM, str, true)) {
 
867
                markTag2Changed();
894
868
        }
895
869
}
896
870
 
899
873
 *
900
874
 * @param str string to set, "" to remove field.
901
875
 */
902
 
 
903
876
void Mp3File::setCommentV2(const QString& str)
904
877
{
905
 
        if (setTextField(tagV2, ID3FID_COMMENT, str, true)) {
906
 
                changedV2 = true;
 
878
        if (setTextField(m_tagV2, ID3FID_COMMENT, str, true)) {
 
879
                markTag2Changed();
907
880
        }
908
881
}
909
882
 
912
885
 *
913
886
 * @param num number to set, 0 to remove field.
914
887
 */
915
 
 
916
888
void Mp3File::setYearV2(int num)
917
889
{
918
 
        if (setYear(tagV2, num)) {
919
 
                changedV2 = true;
 
890
        if (setYear(m_tagV2, num)) {
 
891
                markTag2Changed();
920
892
        }
921
893
}
922
894
 
925
897
 *
926
898
 * @param num number to set, 0 to remove field.
927
899
 */
928
 
 
929
900
void Mp3File::setTrackNumV2(int num)
930
901
{
931
902
        int numTracks = getTotalNumberOfTracksIfEnabled();
932
 
        if (setTrackNum(tagV2, num, numTracks)) {
933
 
                changedV2 = true;
934
 
        }
935
 
}
936
 
 
937
 
/**
938
 
 * Set ID3v2 genre.
939
 
 *
940
 
 * @param num number to set, 0xff to remove field.
941
 
 */
942
 
 
943
 
void Mp3File::setGenreNumV2(int num)
944
 
{
945
 
        if (setGenreNum(tagV2, num)) {
946
 
                changedV2 = true;
 
903
        if (setTrackNum(m_tagV2, num, numTracks)) {
 
904
                markTag2Changed();
947
905
        }
948
906
}
949
907
 
954
912
 */
955
913
void Mp3File::setGenreV2(const QString& str)
956
914
{
957
 
        if (setTextField(tagV2, ID3FID_CONTENTTYPE, str, true)) {
958
 
                changedV2 = true;
 
915
        if (!str.isNull()) {
 
916
                int num = Genres::getNumber(str);
 
917
                if (num >= 0 && num != 0xff) {
 
918
                        if (setGenreNum(m_tagV2, num)) {
 
919
                                markTag2Changed();
 
920
                        }
 
921
                } else {
 
922
                        if (setTextField(m_tagV2, ID3FID_CONTENTTYPE, str, true)) {
 
923
                                markTag2Changed();
 
924
                        }
 
925
                }
959
926
        }
960
927
}
961
928
 
968
935
 */
969
936
bool Mp3File::isTagInformationRead() const
970
937
{
971
 
        return tagV1 || tagV2;
 
938
        return m_tagV1 || m_tagV2;
972
939
}
973
940
 
974
941
/**
979
946
 */
980
947
bool Mp3File::hasTagV1() const
981
948
{
982
 
        return tagV1 && tagV1->HasV1Tag();
 
949
        return m_tagV1 && m_tagV1->HasV1Tag();
983
950
}
984
951
 
985
952
/**
1000
967
 */
1001
968
bool Mp3File::hasTagV2() const
1002
969
{
1003
 
        return tagV2 && tagV2->HasV2Tag();
 
970
        return m_tagV2 && m_tagV2->HasV2Tag();
1004
971
}
1005
972
 
1006
973
/**
1012
979
QString Mp3File::getDetailInfo() const {
1013
980
        QString str("");
1014
981
        const Mp3_Headerinfo* info = NULL;
1015
 
        if (tagV1) {
1016
 
                info = tagV1->GetMp3HeaderInfo();
1017
 
        } else if (tagV2) {
1018
 
                info = tagV2->GetMp3HeaderInfo();
 
982
        if (m_tagV1) {
 
983
                info = m_tagV1->GetMp3HeaderInfo();
 
984
        } else if (m_tagV2) {
 
985
                info = m_tagV2->GetMp3HeaderInfo();
1019
986
        }
1020
987
        if (info) {
1021
988
                switch (info->version) {
1098
1065
{
1099
1066
        unsigned duration = 0;
1100
1067
        const Mp3_Headerinfo* info = NULL;
1101
 
        if (tagV1) {
1102
 
                info = tagV1->GetMp3HeaderInfo();
1103
 
        } else if (tagV2) {
1104
 
                info = tagV2->GetMp3HeaderInfo();
 
1068
        if (m_tagV1) {
 
1069
                info = m_tagV1->GetMp3HeaderInfo();
 
1070
        } else if (m_tagV2) {
 
1071
                info = m_tagV2->GetMp3HeaderInfo();
1105
1072
        }
1106
1073
        if (info && info->time > 0) {
1107
1074
                duration = info->time;
1154
1121
 */
1155
1122
QString Mp3File::getTagFormatV2() const
1156
1123
{
1157
 
        if (tagV2 && tagV2->HasV2Tag()) {
1158
 
                switch (tagV2->GetSpec()) {
 
1124
        if (m_tagV2 && m_tagV2->HasV2Tag()) {
 
1125
                switch (m_tagV2->GetSpec()) {
1159
1126
                        case ID3V2_3_0:
1160
1127
                                return "ID3v2.3.0";
1161
1128
                        case ID3V2_4_0: