1 #pragma once
2
3 #include <taglib/tag.h>
4 #include <taglib/tstringlist.h>
5
6 #include <QByteArray>
7 #include <QFlags>
8 #include <QImage>
9 #include <QString>
10
11 #if defined(__EXTRA_METADATA__)
12 // UUID -> QString
13 #include "util/compatibility.h"
14 #endif // __EXTRA_METADATA__
15
16 // TagLib has support for the Ogg Opus file format since version 1.9
17 #define TAGLIB_HAS_OPUSFILE \
18 ((TAGLIB_MAJOR_VERSION > 1) || ((TAGLIB_MAJOR_VERSION == 1) && (TAGLIB_MINOR_VERSION >= 9)))
19
20 // TagLib has support for hasID3v2Tag()/ID3v2Tag() for WAV files since version 1.9
21 #define TAGLIB_HAS_WAV_ID3V2TAG \
22 (TAGLIB_MAJOR_VERSION > 1) || ((TAGLIB_MAJOR_VERSION == 1) && (TAGLIB_MINOR_VERSION >= 9))
23
24 #include "track/trackmetadata.h"
25
26 namespace mixxx {
27
28 namespace taglib {
29
30 QString toQString(
31 const TagLib::String& tString);
32
33 TagLib::String toTString(
34 const QString& qString);
35
36 /// Returns the first element of TagLib string list that is not empty.
37 TagLib::String firstNonEmptyStringListItem(
38 const TagLib::StringList& strList);
39
40 /// Returns a QByteArray that owns the data.
toQByteArray(const TagLib::ByteVector & tByteVector)41 inline QByteArray toQByteArray(
42 const TagLib::ByteVector& tByteVector) {
43 return QByteArray(
44 tByteVector.data(),
45 tByteVector.size());
46 }
47
48 /// Returns a QByteArray that directly accesses the underlying byte vector!
toQByteArrayRaw(const TagLib::ByteVector & tByteVector)49 inline QByteArray toQByteArrayRaw(
50 const TagLib::ByteVector& tByteVector) {
51 return QByteArray::fromRawData(
52 tByteVector.data(),
53 tByteVector.size());
54 }
55
toTByteVector(const QByteArray & byteArray)56 inline TagLib::ByteVector toTByteVector(
57 const QByteArray& byteArray) {
58 if (byteArray.isNull()) {
59 return TagLib::ByteVector();
60 } else {
61 return TagLib::ByteVector(byteArray.constData(), byteArray.size());
62 }
63 }
64
65 #if defined(__EXTRA_METADATA__)
uuidToTString(const QUuid & uuid)66 inline TagLib::String uuidToTString(
67 const QUuid& uuid) {
68 return toTString(uuidToNullableStringWithoutBraces(uuid));
69 }
70 #endif // __EXTRA_METADATA__
71
formatBpm(const TrackMetadata & trackMetadata)72 inline QString formatBpm(
73 const TrackMetadata& trackMetadata) {
74 return Bpm::valueToString(
75 trackMetadata.getTrackInfo().getBpm().getValue());
76 }
77
78 bool parseBpm(
79 TrackMetadata* pTrackMetadata,
80 const QString& sBpm);
81
formatReplayGainGain(const ReplayGain & replayGain)82 inline QString formatReplayGainGain(
83 const ReplayGain& replayGain) {
84 return ReplayGain::ratioToString(replayGain.getRatio());
85 }
86
formatReplayGainPeak(const ReplayGain & replayGain)87 inline QString formatReplayGainPeak(
88 const ReplayGain& replayGain) {
89 return ReplayGain::peakToString(replayGain.getPeak());
90 }
91
formatTrackGain(const TrackMetadata & trackMetadata)92 inline QString formatTrackGain(
93 const TrackMetadata& trackMetadata) {
94 return formatReplayGainGain(
95 trackMetadata.getTrackInfo().getReplayGain());
96 }
97
98 bool parseTrackGain(
99 TrackMetadata* pTrackMetadata,
100 const QString& dbGain);
101
formatTrackPeak(const TrackMetadata & trackMetadata)102 inline QString formatTrackPeak(
103 const TrackMetadata& trackMetadata) {
104 return formatReplayGainPeak(
105 trackMetadata.getTrackInfo().getReplayGain());
106 }
107
108 bool parseTrackPeak(
109 TrackMetadata* pTrackMetadata,
110 const QString& strPeak);
111
112 #if defined(__EXTRA_METADATA__)
formatAlbumGain(const TrackMetadata & trackMetadata)113 inline QString formatAlbumGain(
114 const TrackMetadata& trackMetadata) {
115 return formatReplayGainGain(trackMetadata.getAlbumInfo().getReplayGain());
116 }
117
118 bool parseAlbumGain(
119 TrackMetadata* pTrackMetadata,
120 const QString& dbGain);
121
formatAlbumPeak(const TrackMetadata & trackMetadata)122 inline QString formatAlbumPeak(
123 const TrackMetadata& trackMetadata) {
124 return formatReplayGainPeak(trackMetadata.getAlbumInfo().getReplayGain());
125 }
126
127 bool parseAlbumPeak(
128 TrackMetadata* pTrackMetadata,
129 const QString& strPeak);
130 #endif // __EXTRA_METADATA__
131
132 bool parseSeratoBeatGrid(
133 TrackMetadata* pTrackMetadata,
134 const QByteArray& data,
135 FileType fileType);
136
137 bool parseSeratoBeatGrid(
138 TrackMetadata* pTrackMetadata,
139 const TagLib::String& data,
140 FileType fileType);
141
142 bool parseSeratoMarkers(
143 TrackMetadata* pTrackMetadata,
144 const QByteArray& data,
145 FileType fileType);
146
147 bool parseSeratoMarkers(
148 TrackMetadata* pTrackMetadata,
149 const TagLib::String& data,
150 FileType fileType);
151
152 bool parseSeratoMarkers2(
153 TrackMetadata* pTrackMetadata,
154 const QByteArray& data,
155 FileType fileType);
156
157 bool parseSeratoMarkers2(
158 TrackMetadata* pTrackMetadata,
159 const TagLib::String& data,
160 FileType fileType);
161
162 TagLib::String dumpSeratoBeatGrid(
163 const TrackMetadata& trackMetadata,
164 FileType fileType);
165
166 TagLib::String dumpSeratoMarkers(
167 const TrackMetadata& trackMetadata,
168 FileType fileType);
169
170 TagLib::String dumpSeratoMarkers2(
171 const TrackMetadata& trackMetadata,
172 FileType fileType);
173
174 inline QImage loadImageFromByteVector(
175 const TagLib::ByteVector& imageData,
176 const char* format = nullptr) {
177 return QImage::fromData(
178 // char -> uchar
179 reinterpret_cast<const uchar*>(imageData.data()),
180 imageData.size(),
181 format);
182 }
183
184 /// Bitmask of optional tag fields that should NOT be read from the
185 /// common part of the tag through TagLib::Tag.
186 /// Usage: The write functions for ID3v2, MP4, APE and XiphComment tags
187 /// have specialized code for some or all of the corresponding tag fields
188 /// and the common implementation sometime doesn't work as expected.
189 enum class ReadTagFlag {
190 OmitNone = 0,
191 OmitComment = 1 << 0,
192 };
193
194 Q_DECLARE_FLAGS(ReadTagMask, ReadTagFlag)
195
196 Q_DECLARE_OPERATORS_FOR_FLAGS(ReadTagMask)
197
198 void importTrackMetadataFromTag(
199 TrackMetadata* pTrackMetadata,
200 const TagLib::Tag& tag,
201 ReadTagMask readMask = ReadTagFlag::OmitNone);
202
203 /// Bitmask of optional tag fields that should NOT be written into the
204 /// common part of the tag through TagLib::Tag. For future extension
205 /// it is safer to explicitly specify these exceptions!
206 /// Usage: The write functions for ID3v2, MP4, APE and XiphComment tags
207 /// have specialized code for some or all of the corresponding tag fields
208 /// and it is not needed or even dangerous to use the common setters of
209 /// TagLib::Tag.
210 enum class WriteTagFlag {
211 OmitNone = 0,
212 OmitComment = 1 << 0,
213 OmitTrackNumber = 1 << 1,
214 OmitYear = 1 << 2,
215 };
216
217 Q_DECLARE_FLAGS(WriteTagMask, WriteTagFlag)
218
219 Q_DECLARE_OPERATORS_FOR_FLAGS(WriteTagMask)
220
221 void exportTrackMetadataIntoTag(
222 TagLib::Tag* pTag,
223 const TrackMetadata& trackMetadata,
224 WriteTagMask writeMask);
225
226 } // namespace taglib
227
228 } // namespace mixxx
229