summaryrefslogtreecommitdiffstats
path: root/src/track/taglib/trackmetadata_common.h
blob: 69d62f327040dc73585461f85af9714969d1fac1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
#pragma once

#include <taglib/tag.h>
#include <taglib/tstringlist.h>

#include <QByteArray>
#include <QFlags>
#include <QImage>
#include <QString>

#if defined(__EXTRA_METADATA__)
// UUID -> QString
#include "util/compatibility.h"
#endif // __EXTRA_METADATA__

// TagLib has support for the Ogg Opus file format since version 1.9
#define TAGLIB_HAS_OPUSFILE \
    ((TAGLIB_MAJOR_VERSION > 1) || ((TAGLIB_MAJOR_VERSION == 1) && (TAGLIB_MINOR_VERSION >= 9)))

// TagLib has support for hasID3v2Tag()/ID3v2Tag() for WAV files since version 1.9
#define TAGLIB_HAS_WAV_ID3V2TAG \
    (TAGLIB_MAJOR_VERSION > 1) || ((TAGLIB_MAJOR_VERSION == 1) && (TAGLIB_MINOR_VERSION >= 9))

#include "track/trackmetadata.h"

namespace mixxx {

namespace taglib {

QString toQString(
        const TagLib::String& tString);

TagLib::String toTString(
        const QString& qString);

/// Returns the first element of TagLib string list that is not empty.
TagLib::String firstNonEmptyStringListItem(
        const TagLib::StringList& strList);

/// Returns a QByteArray that owns the data.
inline QByteArray toQByteArray(
        const TagLib::ByteVector& tByteVector) {
        return QByteArray(
                tByteVector.data(),
                tByteVector.size());
}

/// Returns a QByteArray that directly accesses the underlying byte vector!
inline QByteArray toQByteArrayRaw(
        const TagLib::ByteVector& tByteVector) {
        return QByteArray::fromRawData(
                tByteVector.data(),
                tByteVector.size());
}

inline TagLib::ByteVector toTByteVector(
        const QByteArray& byteArray) {
    if (byteArray.isNull()) {
        return TagLib::ByteVector();
    } else {
        return TagLib::ByteVector(byteArray.constData(), byteArray.size());
    }
}

#if defined(__EXTRA_METADATA__)
inline TagLib::String uuidToTString(
        const QUuid& uuid) {
    return toTString(uuidToNullableStringWithoutBraces(uuid));
}
#endif // __EXTRA_METADATA__

inline QString formatBpm(
        const TrackMetadata& trackMetadata) {
    return Bpm::valueToString(
            trackMetadata.getTrackInfo().getBpm().getValue());
}

bool parseBpm(
        TrackMetadata* pTrackMetadata,
        const QString& sBpm);

inline QString formatReplayGainGain(
        const ReplayGain& replayGain) {
    return ReplayGain::ratioToString(replayGain.getRatio());
}

inline QString formatReplayGainPeak(
        const ReplayGain& replayGain) {
    return ReplayGain::peakToString(replayGain.getPeak());
}

inline QString formatTrackGain(
        const TrackMetadata& trackMetadata) {
    return formatReplayGainGain(
            trackMetadata.getTrackInfo().getReplayGain());
}

bool parseTrackGain(
        TrackMetadata* pTrackMetadata,
        const QString& dbGain);

inline QString formatTrackPeak(
        const TrackMetadata& trackMetadata) {
    return formatReplayGainPeak(
            trackMetadata.getTrackInfo().getReplayGain());
}

bool parseTrackPeak(
        TrackMetadata* pTrackMetadata,
        const QString& strPeak);

#if defined(__EXTRA_METADATA__)
inline QString formatAlbumGain(
        const TrackMetadata& trackMetadata) {
    return formatReplayGainGain(trackMetadata.getAlbumInfo().getReplayGain());
}

bool parseAlbumGain(
        TrackMetadata* pTrackMetadata,
        const QString& dbGain);

inline QString formatAlbumPeak(
        const TrackMetadata& trackMetadata) {
    return formatReplayGainPeak(trackMetadata.getAlbumInfo().getReplayGain());
}

bool parseAlbumPeak(
        TrackMetadata* pTrackMetadata,
        const QString& strPeak);
#endif // __EXTRA_METADATA__

bool parseSeratoBeatGrid(
        TrackMetadata* pTrackMetadata,
        const QByteArray& data,
        FileType fileType);

bool parseSeratoBeatGrid(
        TrackMetadata* pTrackMetadata,
        const TagLib::String& data,
        FileType fileType);

bool parseSeratoMarkers(
        TrackMetadata* pTrackMetadata,
        const QByteArray& data,
        FileType fileType);

bool parseSeratoMarkers(
        TrackMetadata* pTrackMetadata,
        const TagLib::String& data,
        FileType fileType);

bool parseSeratoMarkers2(
        TrackMetadata* pTrackMetadata,
        const QByteArray& data,
        FileType fileType);

bool parseSeratoMarkers2(
        TrackMetadata* pTrackMetadata,
        const TagLib::String& data,
        FileType fileType);

TagLib::String dumpSeratoBeatGrid(
        const TrackMetadata& trackMetadata,
        FileType fileType);

TagLib::String dumpSeratoMarkers(
        const TrackMetadata& trackMetadata,
        FileType fileType);

TagLib::String dumpSeratoMarkers2(
        const TrackMetadata& trackMetadata,
        FileType fileType);

inline QImage loadImageFromByteVector(
        const TagLib::ByteVector& imageData,
        const char* format = nullptr) {
    return QImage::fromData(
            // char -> uchar
            reinterpret_cast<const uchar*>(imageData.data()),
            imageData.size(),
            format);
}

/// Bitmask of optional tag fields that should NOT be read from the
/// common part of the tag through TagLib::Tag.
/// Usage: The write functions for ID3v2, MP4, APE and XiphComment tags
/// have specialized code for some or all of the corresponding tag fields
/// and the common implementation sometime doesn't work as expected.
enum class ReadTagFlag {
    OmitNone = 0,
    OmitComment = 1 << 0,
};

Q_DECLARE_FLAGS(ReadTagMask, ReadTagFlag)

Q_DECLARE_OPERATORS_FOR_FLAGS(ReadTagMask)

void importTrackMetadataFromTag(
        TrackMetadata* pTrackMetadata,
        const TagLib::Tag& tag,
        ReadTagMask readMask = ReadTagFlag::OmitNone);

/// Bitmask of optional tag fields that should NOT be written into the
/// common part of the tag through TagLib::Tag. For future extension
/// it is safer to explicitly specify these exceptions!
/// Usage: The write functions for ID3v2, MP4, APE and XiphComment tags
/// have specialized code for some or all of the corresponding tag fields
/// and it is not needed or even dangerous to use the common setters of
/// TagLib::Tag.
enum class WriteTagFlag {
    OmitNone = 0,
    OmitComment = 1 << 0,
    OmitTrackNumber = 1 << 1,
    OmitYear = 1 << 2,
};

Q_DECLARE_FLAGS(WriteTagMask, WriteTagFlag)

Q_DECLARE_OPERATORS_FOR_FLAGS(WriteTagMask)

void exportTrackMetadataIntoTag(
        TagLib::Tag* pTag,
        const TrackMetadata& trackMetadata,
        WriteTagMask writeMask);

} // namespace taglib

} // namespace mixxx