-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Expand file tree
/
Copy pathtrackrecord.h
More file actions
203 lines (170 loc) · 7.48 KB
/
trackrecord.h
File metadata and controls
203 lines (170 loc) · 7.48 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
#pragma once
#include "library/coverart.h"
#include "proto/keys.pb.h"
#include "track/cue.h"
#include "track/keys.h"
#include "track/keyutils.h"
#include "track/playcounter.h"
#include "track/trackid.h"
#include "track/trackmetadata.h"
#include "util/color/rgbcolor.h"
// Forward declaration for accessing m_headerParsed
class TrackDAO;
namespace mixxx {
/// Effect of updating a property with a new value.
enum class UpdateResult {
/// The value has been updated and changed.
Updated,
/// The value didn't change and has not been updated.
Unchanged,
/// The provided value is invalid or insonsistent with
/// any existing value(s) and has been rejected, i.e.
/// the current value didn't change either.
Rejected,
};
// Properties of tracks that are stored in the database.
class TrackRecord final {
// Properties that parsed from and (optionally) written back to their
// source, i.e. the corresponding file
MIXXX_DECL_PROPERTY(TrackMetadata, metadata, Metadata)
// The unique ID of track. This value is only set once after the track
// has been inserted or is loaded from the library DB.
MIXXX_DECL_PROPERTY(TrackId, id, Id)
// Both import and export of metadata can be tracked by a single time
// stamp, the direction doesn't matter. The value should be set to the
// modification time stamp provided by the metadata source. This would
// enable us to update the metadata of all tracks in the database after
// the external metadata has been modified, i.e. if the corresponding
// files have been modified.
MIXXX_DECL_PROPERTY(QDateTime, sourceSynchronizedAt, SourceSynchronizedAt)
MIXXX_DECL_PROPERTY(CoverInfoRelative, coverInfo, CoverInfo)
MIXXX_DECL_PROPERTY(QDateTime, dateAdded, DateAdded)
MIXXX_DECL_PROPERTY(QString, fileType, FileType)
MIXXX_DECL_PROPERTY(QString, url, Url)
MIXXX_DECL_PROPERTY(PlayCounter, playCounter, PlayCounter)
MIXXX_DECL_PROPERTY(RgbColor::optional_t, color, Color)
MIXXX_DECL_PROPERTY(mixxx::audio::FramePos, mainCuePosition, MainCuePosition)
MIXXX_DECL_PROPERTY(int, rating, Rating)
MIXXX_DECL_PROPERTY(bool, bpmLocked, BpmLocked)
public:
// Data migration: Reload track total from file tags if not initialized
// yet. The added column "tracktotal" has been initialized with the
// default value "//".
// See also: Schema revision 26 in schema.xml
// Public only for testing purposes!
static const QString kTrackTotalPlaceholder;
explicit TrackRecord(TrackId id = TrackId());
TrackRecord(TrackRecord&&) = default;
TrackRecord(const TrackRecord&) = default;
/*non-virtual*/ ~TrackRecord() = default;
TrackRecord& operator=(TrackRecord&&) = default;
TrackRecord& operator=(const TrackRecord&) = default;
static constexpr int kMinRating = 0;
static constexpr int kMaxRating = 5;
static constexpr int kNoRating = kMinRating;
static bool isValidRating(int rating) {
return rating >= kMinRating && rating <= kMaxRating;
}
bool hasRating() const {
return getRating() != kNoRating;
}
void setKeys(Keys keys);
void resetKeys() {
setKeys(Keys());
}
const Keys& getKeys() const {
return m_keys;
}
// Key text will be stored as StandardID3v2
// Invalid Keys are rejected and empty string deletes the key
UpdateResult updateGlobalKeyNormalizeText(
const QString& keyText,
track::io::key::Source keySource);
enum class SourceSyncStatus {
/// The metadata has not been imported yet.
Void,
/// The metadata has been imported once, but until Mixxx 2.4 no
/// synchronization time stamps have been stored in the database
/// that allow to monitor the modification time of the file.
Unknown,
/// The metadata in Mixxx is up-to-date, i.e. not older than the
/// last modification time stamp of the underlying file.
Synchronized,
/// The metadata in Mixxx is older than the metadata stored in file tags
/// and should be re-imported.
Outdated,
/// The status could not be determined for whatever reason,
/// e.g. inaccessible file, ...
Undefined,
};
SourceSyncStatus checkSourceSyncStatus(
const FileInfo& fileInfo) const;
bool replaceMetadataFromSource(
TrackMetadata&& importedMetadata,
const QDateTime& sourceSynchronizedAt);
// Merge the current metadata with new and additional properties
// imported from the file. Since these properties are not (yet)
// stored in the library or have been added later all existing
// data must be preserved and never be overwritten! This allows
// a gradual migration by selectively reimporting the required
// data when needed.
//
// Returns true if any property has been modified or false otherwise.
bool mergeExtraMetadataFromSource(
const TrackMetadata& importedMetadata);
/// Update the stream info after opening the audio stream during
/// a session.
/// Returns true if the corresponding metadata properties have been
/// updated and false otherwise.
bool updateStreamInfoFromSource(
mixxx::audio::StreamInfo streamInfoFromSource);
/// Check if the stream info is supposed to be reliable and accurate.
/// TODO: Also flag the stream info as "accurate" in the database and
/// invoke updateStreamInfoFromSource() accordingly when loading tracks
/// from the database.
bool hasStreamInfoFromSource() const {
return static_cast<bool>(m_streamInfoFromSource);
}
const std::optional<audio::StreamInfo>& getStreamInfoFromSource() const {
return m_streamInfoFromSource;
}
private:
// TODO: Remove this dependency
friend class ::Track;
bool updateSourceSynchronizedAt(
const QDateTime& sourceSynchronizedAt);
Keys m_keys;
// TODO: Use TrackMetadata as single source of truth and do not
// store this information redundantly.
//
// PROPOSAL (as implemented by https://gitlab.com/uklotzde/aoide-rs):
// This redesign requires to track the status of some or all track
// metadata (which includes the stream info properties) by a set of
// bitflags:
// - UNRELIABLE = 0 (default)
// Parsed from file tags which are considered inaccurate and
// are often imprecise
// - RELIABLE = 1 << 0
// Reported by a decoder when opening an audio/video stream for
// reading. Nevertheless different decoders may report slightly
// differing values.
// - LOCKED = 1 << 1
// Locked metadata will not be updated automatically, neither when
// parsing file tags nor when decoding an audio/video stream.
// While locked the stale flag is never set.
// - STALE = 1 << 2
// Stale metadata should be re-imported depending on the other flags.
std::optional<audio::StreamInfo> m_streamInfoFromSource;
friend class ::TrackDAO;
bool m_headerParsed; // deprecated, replaced by sourceSynchronizedAt
/// Equality comparison
///
/// Exception: The member m_streamInfoFromSource must not be considered
/// for equality comparisons! It is only needed for verifying consistency
/// during updates and as a flags when a track is loaded.
friend bool operator==(const TrackRecord& lhs, const TrackRecord& rhs);
};
inline bool operator!=(const TrackRecord& lhs, const TrackRecord& rhs) {
return !(lhs == rhs);
}
} // namespace mixxx