-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Expand file tree
/
Copy pathmarkers.h
More file actions
208 lines (173 loc) · 6.02 KB
/
markers.h
File metadata and controls
208 lines (173 loc) · 6.02 KB
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
#pragma once
#include <QByteArray>
#include <QDataStream>
#include <QList>
#include <memory>
#include <optional>
#include "track/cueinfo.h"
#include "track/serato/color.h"
#include "track/taglib/trackmetadata_file.h"
#include "util/types.h"
namespace mixxx {
class SeratoMarkersEntry;
typedef std::shared_ptr<SeratoMarkersEntry> SeratoMarkersEntryPointer;
class SeratoMarkersEntry {
public:
/// We didn't encounter other type IDs as those listed here (e.g. "2") yet.
/// Apparently these are not used.
enum class TypeId : quint8 {
/// Used for unset cue points
Unknown = 0,
/// Used for set cue points
Cue = 1,
/// Used for saved loops (both set and unset ones)
Loop = 3,
};
SeratoMarkersEntry(
bool hasStartPosition,
int startPosition,
bool hasEndPosition,
int endPosition,
SeratoStoredHotcueColor color,
quint8 type,
bool isLocked)
: m_color(color),
m_hasStartPosition(hasStartPosition),
m_hasEndPosition(hasEndPosition),
m_isLocked(isLocked),
m_startPosition(startPosition),
m_endPosition(endPosition),
m_type(type) {
}
~SeratoMarkersEntry() = default;
QByteArray dumpID3() const;
QByteArray dumpMP4() const;
static SeratoMarkersEntryPointer parseID3(const QByteArray& data);
static SeratoMarkersEntryPointer parseMP4(const QByteArray& data);
quint8 type() const {
return m_type;
}
SeratoMarkersEntry::TypeId typeId() const {
SeratoMarkersEntry::TypeId typeId = SeratoMarkersEntry::TypeId::Unknown;
switch (static_cast<SeratoMarkersEntry::TypeId>(type())) {
case SeratoMarkersEntry::TypeId::Unknown:
// This seems to be an unset Hotcue (i.e. without a position)
case SeratoMarkersEntry::TypeId::Cue:
typeId = SeratoMarkersEntry::TypeId::Cue;
break;
case SeratoMarkersEntry::TypeId::Loop:
typeId = SeratoMarkersEntry::TypeId::Loop;
break;
}
return typeId;
}
SeratoStoredHotcueColor getColor() const {
return m_color;
}
bool isLocked() const {
return m_isLocked;
}
bool hasStartPosition() const {
return m_hasStartPosition;
}
quint32 getStartPosition() const {
return m_startPosition;
}
bool hasEndPosition() const {
return m_hasEndPosition;
}
quint32 getEndPosition() const {
return m_endPosition;
}
private:
SeratoStoredHotcueColor m_color;
bool m_hasStartPosition;
bool m_hasEndPosition;
;
bool m_isLocked;
quint32 m_startPosition;
quint32 m_endPosition;
quint8 m_type;
};
inline bool operator==(const SeratoMarkersEntry& lhs, const SeratoMarkersEntry& rhs) {
return (lhs.dumpID3() == rhs.dumpID3());
}
inline bool operator!=(const SeratoMarkersEntry& lhs, const SeratoMarkersEntry& rhs) {
return !(lhs == rhs);
}
inline QDebug operator<<(QDebug dbg, const SeratoMarkersEntry& arg) {
dbg << "type =" << arg.type();
if (arg.hasStartPosition()) {
dbg << "startPosition =" << arg.getStartPosition();
}
if (arg.hasEndPosition()) {
dbg << "endPosition =" << arg.getEndPosition();
}
return dbg << "color =" << arg.getColor()
<< "isLocked =" << arg.isLocked();
}
/// DTO for storing information from the SeratoMarkers_ tags used by the Serato
/// DJ Pro software.
///
/// This class includes functions for formatting and parsing SeratoMarkers_
/// metadata according to the specification:
/// https://github.com/Holzhaus/serato-tags/blob/main/docs/serato_markers_.md
class SeratoMarkers final {
public:
SeratoMarkers() = default;
/// Parse a binary Serato representation of the "Markers_" data from a
/// `QByteArray` and write the results to the `SeratoMarkers` instance.
/// The `fileType` parameter determines the exact format of the data being
/// used.
static bool parse(
SeratoMarkers* seratoMarkers,
const QByteArray& data,
taglib::FileType fileType);
/// Create a binary Serato representation of the "Markers_" data suitable
/// for `fileType` and dump it into a `QByteArray`. The content of that
/// byte array can be used for round-trip tests or written to the
/// appropriate tag to make it accessible to Serato.
QByteArray dump(taglib::FileType fileType) const;
bool isEmpty() const {
return m_entries.isEmpty() && !m_pTrackColor;
}
const QList<SeratoMarkersEntryPointer>& getEntries() const {
return m_entries;
}
void setEntries(QList<SeratoMarkersEntryPointer> entries) {
m_entries = std::move(entries);
}
/// Always returns a color if the tag is present (i.e. `isEmpty()` is
/// false).
const std::optional<SeratoStoredTrackColor>& getTrackColor() const {
return m_pTrackColor;
}
void setTrackColor(const SeratoStoredTrackColor& color) {
m_pTrackColor = color;
}
QList<CueInfo> getCues() const;
void setCues(const QList<CueInfo>& cueInfos);
private:
static bool parseID3(
SeratoMarkers* seratoMarkers,
const QByteArray& data);
static bool parseMP4(
SeratoMarkers* seratoMarkers,
const QByteArray& base64EncodedData);
QByteArray dumpID3() const;
QByteArray dumpMP4() const;
QList<SeratoMarkersEntryPointer> m_entries;
std::optional<SeratoStoredTrackColor> m_pTrackColor;
};
inline bool operator==(const SeratoMarkers& lhs, const SeratoMarkers& rhs) {
return (lhs.getEntries() == rhs.getEntries());
}
inline bool operator!=(const SeratoMarkers& lhs, const SeratoMarkers& rhs) {
return !(lhs == rhs);
}
inline QDebug operator<<(QDebug dbg, const SeratoMarkers& arg) {
return dbg << "entries =" << arg.getEntries().length();
}
} // namespace mixxx
Q_DECLARE_TYPEINFO(mixxx::SeratoMarkers, Q_MOVABLE_TYPE);
Q_DECLARE_METATYPE(mixxx::SeratoMarkers)