summaryrefslogtreecommitdiffstats
path: root/include/djinterop/track.hpp
blob: ff649cca416296d140f4b204b29bee27a7b4043d (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
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
/*
    This file is part of libdjinterop.

    libdjinterop is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    libdjinterop is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with libdjinterop.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once
#ifndef DJINTEROP_TRACK_HPP
#define DJINTEROP_TRACK_HPP

#if __cplusplus < 201703L
#error This library needs at least a C++17 compliant compiler
#endif

#include <array>
#include <chrono>
#include <cstdint>
#include <memory>
#include <stdexcept>
#include <string>
#include <vector>

#include <djinterop/config.hpp>
#include <djinterop/musical_key.hpp>
#include <djinterop/optional.hpp>
#include <djinterop/performance_data.hpp>
#include <djinterop/semantic_version.hpp>

namespace djinterop
{
class database;
class crate;
class track_impl;

/// The `track_import_info` struct holds information about a track in a
/// different, external Engine Library database.  This can be associated with a
/// track if it was imported into the current database from another one.
struct track_import_info
{
    // TODO (mr-smidge): Refactor to remove Engine-specific details.

    /// The UUID of the external Engine Library database.
    std::string external_db_uuid;

    /// The id of the track in the external Engine Library database.
    int64_t external_track_id;
};

/// A `track` object is a handle to a track stored in a database. As long as it
/// lives, the corresponding database connection is kept open.
///
/// `track` objects can be copied and assigned cheaply, resulting in multiple
/// handles to the same actual track.
///
/// The read/write operations provided by this class directly access the
/// database.
///
/// A `track` object becomes invalid if the track gets deleted by
/// `database::remove_track()`. After that, you must not call any methods on the
/// `track` object, except for destructing it, or assigning to it.
class DJINTEROP_PUBLIC track
{
public:
    /// Copy constructor
    track(const track& other) noexcept;

    /// Destructor
    ~track();

    /// Copy assignment operator
    track& operator=(const track& other) noexcept;

    std::vector<beatgrid_marker> adjusted_beatgrid() const;

    void set_adjusted_beatgrid(std::vector<beatgrid_marker> beatgrid) const;

    double adjusted_main_cue() const;

    void set_adjusted_main_cue(double sample_offset) const;

    /// Returns the album name (metadata) of the track
    stdx::optional<std::string> album() const;

    /// Sets the album name (metadata) of the track
    void set_album(stdx::optional<std::string> album) const;
    void set_album(std::string album) const;

    /// Returns the ID of the `album_art` associated to the track
    ///
    /// If the track doesn't have an associated `album_art`, then `nullopt`
    /// is returned.
    /// TODO (haslersn): Return an `album_art` object instead.
    stdx::optional<int64_t> album_art_id() const;

    /// Sets the ID of the `album_art` associated to the track
    /// TODO (haslersn): Pass an `album_art` object instead.
    void set_album_art_id(stdx::optional<int64_t> album_art_id) const;
    void set_album_art_id(int64_t album_art_id) const;

    /// Returns the artist (metadata) of the track
    stdx::optional<std::string> artist() const;

    /// Sets the artist (metadata) of the track
    void set_artist(stdx::optional<std::string> artist) const;
    void set_artist(std::string artist) const;

    stdx::optional<double> average_loudness() const;

    void set_average_loudness(stdx::optional<double> average_loudness) const;
    void set_average_loudness(double average_loudness) const;

    /// Returns the bitrate (metadata) of the track
    stdx::optional<int64_t> bitrate() const;

    /// Sets the bitrate (metadata) of the track
    void set_bitrate(stdx::optional<int64_t> bitrate) const;
    void set_bitrate(int64_t bitrate) const;

    /// Returns the BPM (metadata) of the track, rounded to the nearest integer
    stdx::optional<double> bpm() const;

    /// Sets the BPM (metadata) of the track, rounded to the nearest integer
    void set_bpm(stdx::optional<double> bpm) const;
    void set_bpm(double bpm) const;

    /// Returns the comment associated to the track (metadata)
    stdx::optional<std::string> comment() const;

    /// Sets the comment associated to the track (metadata)
    void set_comment(stdx::optional<std::string> comment) const;
    void set_comment(std::string comment) const;

    /// Returns the composer (metadata) of the track
    stdx::optional<std::string> composer() const;

    /// Sets the composer (metadata) of the track
    void set_composer(stdx::optional<std::string> composer) const;
    void set_composer(std::string composer) const;

    /// Returns the crates containing the track
    std::vector<crate> containing_crates() const;

    /// Returns the database containing the track
    database db() const;

    std::vector<beatgrid_marker> default_beatgrid() const;

    void set_default_beatgrid(std::vector<beatgrid_marker> beatgrid) const;

    double default_main_cue() const;

    void set_default_main_cue(double sample_offset) const;

    /// Returns the duration (metadata) of the track
    stdx::optional<std::chrono::milliseconds> duration() const;

    /// Returns the file extension part of `track::relative_path()`
    ///
    /// An empty string is returned if the file doesn't have an extension.
    std::string file_extension() const;

    /// Returns the filename part of `track::relative_path()` (including the
    /// file extension)
    std::string filename() const;

    /// Returns the genre (metadata) of the track
    stdx::optional<std::string> genre() const;

    /// Sets the genre (metadata) of the track
    void set_genre(stdx::optional<std::string> genre) const;
    void set_genre(std::string genre) const;

    stdx::optional<hot_cue> hot_cue_at(int32_t index) const;

    void set_hot_cue_at(int32_t index, stdx::optional<hot_cue> cue) const;
    void set_hot_cue_at(int32_t index, hot_cue cue) const;

    std::array<stdx::optional<hot_cue>, 8> hot_cues() const;

    void set_hot_cues(std::array<stdx::optional<hot_cue>, 8> cues) const;

    /// Returns the ID of this track
    ///
    /// The ID is used internally in the database and is unique for tracks
    /// contained in the same database.
    int64_t id() const;

    /// TODO (haslersn): Document this method.
    stdx::optional<track_import_info> import_info() const;

    /// TODO (haslersn): Document these methods.
    void set_import_info(
        const stdx::optional<track_import_info>& import_info) const;
    void set_import_info(const track_import_info& import_info) const;

    /// Returns `true` iff `*this` is valid as described in the class comment
    bool is_valid() const;

    /// Returns the key (metadata) of the track
    stdx::optional<musical_key> key() const;

    /// Sets the key (metadata) of the track
    void set_key(stdx::optional<musical_key> key) const;
    void set_key(musical_key key) const;

    /// Get the time at which this track was last accessed
    ///
    /// Note that on VFAT filesystems, the access time is ceiled to just a date,
    /// and loses any time precision.
    stdx::optional<std::chrono::system_clock::time_point> last_accessed_at()
        const;

    /// TODO (haslersn): Document these methods.
    void set_last_accessed_at(
        stdx::optional<std::chrono::system_clock::time_point> last_accessed_at)
        const;
    void set_last_accessed_at(
        std::chrono::system_clock::time_point last_accessed_at) const;

    /// Get the time of last attribute modification of this track's file
    ///
    /// Note that this is the attribute modification time, not the data
    /// modification time, i.e. ctime not mtime.
    stdx::optional<std::chrono::system_clock::time_point> last_modified_at()
        const;

    /// TODO (haslersn): Document these methods.
    void set_last_modified_at(
        stdx::optional<std::chrono::system_clock::time_point> last_modified_at)
        const;
    void set_last_modified_at(
        std::chrono::system_clock::time_point last_modified_at) const;

    /// Returns the time at which the track was last played
    stdx::optional<std::chrono::system_clock::time_point> last_played_at()
        const;

    /// Sets the time at which the track was last played
    void set_last_played_at(
        stdx::optional<std::chrono::system_clock::time_point> time) const;
    void set_last_played_at(std::chrono::system_clock::time_point time) const;

    stdx::optional<loop> loop_at(int32_t index) const;

    void set_loop_at(int32_t index, stdx::optional<loop> l) const;
    void set_loop_at(int32_t index, loop l) const;

    std::array<stdx::optional<loop>, 8> loops() const;

    void set_loops(std::array<stdx::optional<loop>, 8> loops) const;

    std::vector<waveform_entry> overview_waveform() const;

    /// Returns the publisher (metadata) of the track
    stdx::optional<std::string> publisher() const;

    /// Sets the publisher (metadata) of the track
    void set_publisher(stdx::optional<std::string> publisher) const;
    void set_publisher(std::string publisher) const;

    /// Get the required number of samples per waveform entry.
    ///
    /// The waveform for a track is provided merely as a set of waveform points,
    /// and so the scale of it is only meaningful when a relationship between
    /// the waveform and the samples it represents is known.  This method
    /// provides the required number of samples per waveform entry that should
    /// be understood when constructing or reading waveforms.
    int64_t required_waveform_samples_per_entry() const;

    /// Get the path to this track's file on disk, relative to the music
    /// database.
    std::string relative_path() const;

    /// TODO (haslersn): Document this method.
    void set_relative_path(std::string relative_path) const;

    stdx::optional<sampling_info> sampling() const;

    void set_sampling(stdx::optional<sampling_info> sample_rate) const;
    void set_sampling(sampling_info sample_rate) const;

    /// Returns the title (metadata) of the track
    stdx::optional<std::string> title() const;