-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathtag.h
341 lines (306 loc) · 11 KB
/
tag.h
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
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
#ifndef TAG_PARSER_TAG_H
#define TAG_PARSER_TAG_H
#include "./tagtarget.h"
#include "./tagtype.h"
#include "./tagvalue.h"
#include <c++utilities/io/binaryreader.h>
#include <cstdint>
#include <memory>
#include <string>
#include <type_traits>
namespace TagParser {
/*!
* \brief Specifies the field.
*
* These "known" fields are used to specify a field without using
* the field identifier used by the underlying tag type.
*
* Not all fields are supported by all tag types (see Tag::supportsField()).
*
* Mapping proposed by HAK: https://wiki.hydrogenaud.io/index.php?title=Tag_Mapping
*
* There is a great overlap between KnownField::ContentType found in Matroska tags and KnownField::MediaType
* found in MP4/iTunes tags. They don't seem to be quite identical especially since KnownField::MediaType is
* just a (quite format specific enumeration). So these fields are treated distinctly.
*
* There is an overlap between KnownField::LawRating found in Matroska tags and KnownField::ContentRating
* found in MP4/iTunes tags. They don't seem to be quite identical especially since KnownField::ContentRating
* is just a (quite format specific enumeration). So these fields are treated distinctly.
*
* \sa Tag::type()
*/
enum class KnownField : unsigned int {
Invalid = std::numeric_limits<unsigned int>::max(), /**< invalid field name, do not map this value when subclassing Tag */
Title = 0, /**< title */
Album, /**< album/collection */
Artist, /**< artist/band */
Genre, /**< genre */
Comment, /**< comment */
Bpm, /**< beats per minute */
Bps, /**< beats per second */
Lyricist, /**< lyricist */
TrackPosition, /**< track/part number and total track/part count */
DiskPosition, /**< disk number and total disk count */
PartNumber, /**< track/part number */
TotalParts, /**< total track/part count */
Encoder, /**< encoder */
RecordDate, /**< record date */
Performers, /**< performers */
Length, /**< length */
Language, /**< language */
EncoderSettings, /**< encoder settings */
Lyrics, /**< lyrics */
SynchronizedLyrics, /**< synchronized lyrics */
Grouping, /**< grouping */
RecordLabel, /**< record label */
Cover, /**< cover */
Composer, /**< composer */
Rating, /**< rating */
Description, /**< description */
Vendor, /**< vendor */
AlbumArtist, /**< album artist */
ReleaseDate, /**< release date */
Subtitle, /**< subtitle */
LeadPerformer, /** lead performer */
Arranger, /** the person who arranged the piece */
Conductor, /** conductor */
Director, /** director */
AssistantDirector, /** assistant director */
DirectorOfPhotography, /** director of photography */
SoundEngineer, /** sound engineer */
ArtDirector, /** art director */
ProductionDesigner, /** production designer */
Choregrapher, /** choregrapher */
CostumeDesigner, /** costume designer */
Actor, /** actor */
Character, /** character */
WrittenBy, /** written by */
ScreenplayBy, /** screenplay by */
EditedBy, /** edited by */
Producer, /** producer */
Coproducer, /** coproducer */
ExecutiveProducer, /** executive producer */
DistributedBy, /** distributed by */
MasteredBy, /** mastered by */
EncodedBy, /** encoded by */
MixedBy, /** mixed by */
RemixedBy, /** remixed by */
ProductionStudio, /** production studio */
ThanksTo, /** thanks to */
Publisher, /** publisher */
Mood, /** mood */
OriginalMediaType, /** original media type, e.g. DVD, CD, drawing, ... */
ContentType, /** content type, e.g. documentary vs. cartoon vs. music video (only used by Matroska so far) */
Subject, /** subject */
Keywords, /** keywords */
Summary, /** summary */
Synopsis, /** synopsis */
InitialKey, /** initial key */
Period, /** period */
LawRating, /** law rating, e.g. P, R, X in the USA or an age in other countries or a URI defining a logo */
EncodingDate, /** encoding date */
TaggingDate, /** tagging date */
OriginalReleaseDate, /** original release date */
DigitalizationDate, /** digitalization date */
WritingDate, /** writing date */
PurchasingDate, /** purchasing date */
RecordingLocation, /** recording location */
CompositionLocation, /** composition location */
ComposerNationality, /** composer nationality */
PlayCounter, /** play counter */
Measure, /** measure */
Tuning, /** tuning */
ISRC, /** International Standard Recording Code */
MCDI, /** binary dump of the TOC of the CDROM that this item was taken from */
ISBN, /** International Standard Book Number */
Barcode, /** barcode */
CatalogNumber, /** catalog number */
LabelCode, /** label code */
LCCN, /** Library of Congress Control Number */
IMDB, /** Internet Movie Database ID */
TMDB, /** The Movie DB “movie_id” or “tv_id” identifier for movies/TV shows */
TVDB, /** The TV Database “Series ID” or “Episode ID” identifier for TV shows */
PurchaseItem, /** purchase item URL */
PurchaseInfo, /** purchase info */
PurchaseOwner, /** purchase owner */
PurchasePrice, /** purchase price */
PurchaseCurrency, /** purchase currency */
Copyright, /** copyright */
ProductionCopyright, /** production copyright */
License, /** license */
TermsOfUse, /** terms of use */
PublisherWebpage, /** the publisher's official webpage */
StoreDescription, /** store description */
MediaType, /** the media type, e.g. movie vs. music vs. audiobook (only used by MP4 so far) */
PerformerWebpage, /** the URL to the performer's website or a website generally related to the tagged file */
ContentRating, /** whether the content is rated "clean" or "explicit" (only used by MP4 so far) */
};
/*!
* \brief The first valid entry in the TagParser::KnownField enum.
*/
constexpr KnownField firstKnownField = KnownField::Title;
/*!
* \brief The last valid entry in the TagParser::KnownField enum.
*/
constexpr KnownField lastKnownField = KnownField::ContentRating;
/*!
* \brief The number of valid entries in the TagParser::KnownField enum.
*/
constexpr unsigned int knownFieldArraySize = static_cast<unsigned int>(lastKnownField) + 1;
/*!
* \brief Returns whether the specified \a field is deprecated and should not be used anymore.
*/
constexpr bool isKnownFieldDeprecated(KnownField field)
{
CPP_UTILITIES_UNUSED(field)
return false;
}
/*!
* \brief Returns the next known field skipping any deprecated fields. Returns KnownField::Invalid if there is not next field.
*/
constexpr KnownField nextKnownField(KnownField field)
{
const auto next = field == lastKnownField ? KnownField::Invalid : static_cast<KnownField>(static_cast<int>(field) + 1);
return isKnownFieldDeprecated(next) ? nextKnownField(next) : next;
}
struct TagPrivate;
class TAG_PARSER_EXPORT Tag {
public:
virtual ~Tag();
virtual TagType type() const;
virtual std::string_view typeName() const;
std::string toString() const;
virtual TagTextEncoding proposedTextEncoding() const;
virtual bool canEncodingBeUsed(TagTextEncoding encoding) const;
virtual const TagValue &value(KnownField field) const = 0;
virtual std::vector<const TagValue *> values(KnownField field) const;
virtual bool setValue(KnownField field, const TagValue &value) = 0;
virtual bool setValues(KnownField field, const std::vector<TagValue> &values);
virtual bool hasField(KnownField field) const = 0;
virtual void removeAllFields() = 0;
const std::string &version() const;
std::uint64_t size() const;
virtual bool supportsTarget() const;
const TagTarget &target() const;
TagTarget &target();
void setTarget(const TagTarget &target);
virtual TagTargetLevel targetLevel() const;
std::string_view targetLevelName() const;
bool isTargetingLevel(TagTargetLevel tagTargetLevel) const;
std::string targetString() const;
virtual std::size_t fieldCount() const = 0;
virtual bool supportsField(KnownField field) const = 0;
virtual TagDataType proposedDataType(KnownField field) const;
virtual bool supportsDescription(KnownField field) const;
virtual bool supportsMimeType(KnownField field) const;
virtual bool supportsMultipleValues(KnownField field) const;
virtual std::size_t insertValues(const Tag &from, bool overwrite);
virtual void ensureTextValuesAreProperlyEncoded() = 0;
protected:
Tag();
std::string m_version;
std::uint64_t m_size;
std::unique_ptr<TagPrivate> m_p;
TagTarget m_target;
};
inline TagType Tag::type() const
{
return TagType::Unspecified;
}
inline std::string_view Tag::typeName() const
{
return "unspecified";
}
inline TagTextEncoding Tag::proposedTextEncoding() const
{
return TagTextEncoding::Latin1;
}
inline bool Tag::canEncodingBeUsed(TagTextEncoding encoding) const
{
return encoding == proposedTextEncoding();
}
inline const std::string &Tag::version() const
{
return m_version;
}
inline std::uint64_t Tag::size() const
{
return m_size;
}
inline bool Tag::supportsTarget() const
{
return false;
}
inline const TagTarget &Tag::target() const
{
return m_target;
}
inline TagTarget &Tag::target()
{
return m_target;
}
inline void Tag::setTarget(const TagTarget &target)
{
m_target = target;
}
inline TagTargetLevel Tag::targetLevel() const
{
return TagTargetLevel::Unspecified;
}
inline std::string_view Tag::targetLevelName() const
{
return supportsTarget() ? tagTargetLevelName(targetLevel()) : std::string_view();
}
inline bool Tag::isTargetingLevel(TagTargetLevel tagTargetLevel) const
{
return !supportsTarget() || static_cast<std::uint8_t>(targetLevel()) >= static_cast<std::uint8_t>(tagTargetLevel);
}
inline std::string Tag::targetString() const
{
return target().toString(targetLevel());
}
inline TagDataType Tag::proposedDataType(KnownField field) const
{
switch (field) {
case KnownField::Bpm:
case KnownField::Bps:
case KnownField::PartNumber:
case KnownField::TotalParts:
case KnownField::PlayCounter:
return TagDataType::Integer;
case KnownField::Cover:
return TagDataType::Picture;
case KnownField::Length:
return TagDataType::TimeSpan;
case KnownField::TrackPosition:
case KnownField::DiskPosition:
return TagDataType::PositionInSet;
case KnownField::Genre:
return TagDataType::StandardGenreIndex;
case KnownField::MCDI:
return TagDataType::Binary;
case KnownField::Rating:
// could also be a plain integer but popularity should generally be used (and can be converted
// to an integer)
return TagDataType::Popularity;
case KnownField::SynchronizedLyrics:
// not supported
return TagDataType::Undefined;
default:
return TagDataType::Text;
}
}
inline bool Tag::supportsDescription(KnownField) const
{
return false;
}
inline bool Tag::supportsMimeType(KnownField) const
{
return false;
}
inline bool Tag::supportsMultipleValues(KnownField) const
{
return false;
}
} // namespace TagParser
#endif // TAG_PARSER_TAG_H