From 29b7a757214fdd15a99b35d42b619f9068e78abd Mon Sep 17 00:00:00 2001 From: haslersn Date: Sun, 7 Jun 2020 18:55:01 +0200 Subject: default.nix: Add sqlite as dependency --- default.nix | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/default.nix b/default.nix index 88c2fe4..17f27a0 100644 --- a/default.nix +++ b/default.nix @@ -6,8 +6,8 @@ let name = "git-clang-format"; version = "2019-06-21"; src = fetchurl { - url = "https://raw.githubusercontent.com/llvm-mirror/clang/2bb8e0fe002e8ffaa9ce5fa58034453c94c7e208/tools/clang-format/git-clang-format"; - sha256 = "1kby36i80js6rwi11v3ny4bqsi6i44b9yzs23pdcn9wswffx1nlf"; + url = "https://raw.githubusercontent.com/llvm-mirror/clang/e8c2d2746b1e718b607b78a830534fd3a981d250/tools/clang-format/git-clang-format"; + sha256 = "sha256:1wp7zw2jgpgnv9cr648nlk6gs26yadvs14qnll3vnay1y0n79nd7"; executable = true; }; nativeBuildInputs = [ @@ -42,6 +42,7 @@ stdenv.mkDerivation { outputs = [ "out" "dev" ]; buildInputs = [ boost + sqlite zlib ]; } -- cgit v1.2.3 From 8d6ca822074e33f8189d22ccdab565f88e5db7b0 Mon Sep 17 00:00:00 2001 From: haslersn Date: Sun, 7 Jun 2020 18:58:38 +0200 Subject: .clang-format: The key `Delimiter` doesn't exist anymore --- .clang-format | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.clang-format b/.clang-format index a90ead2..2112752 100644 --- a/.clang-format +++ b/.clang-format @@ -94,7 +94,7 @@ PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 200 PointerAlignment: Left RawStringFormats: - - Delimiter: 'pb' + - Delimiters: [ 'pb' ] Language: TextProto BasedOnStyle: google ReflowComments: true -- cgit v1.2.3 From 080d336106dd9560b3d6f4d6e9ff59fd6c6f710e Mon Sep 17 00:00:00 2001 From: haslersn Date: Sun, 7 Jun 2020 18:55:51 +0200 Subject: enginelibrary: Check that encoded and subsequently decoded perfdata matches the original --- include/djinterop/performance_data.hpp | 42 +++++++++++++ src/djinterop/enginelibrary/el_track_impl.cpp | 6 ++ src/djinterop/enginelibrary/el_track_impl.hpp | 13 +++- .../enginelibrary/performance_data_format.hpp | 72 +++++++++++++++++----- 4 files changed, 118 insertions(+), 15 deletions(-) diff --git a/include/djinterop/performance_data.hpp b/include/djinterop/performance_data.hpp index 67e22e2..620e676 100644 --- a/include/djinterop/performance_data.hpp +++ b/include/djinterop/performance_data.hpp @@ -35,12 +35,26 @@ struct sampling_info { double sample_rate = 0; // usually 44100.0 or 48000.0 int64_t sample_count = 0; + + friend bool operator==( + const sampling_info& first, const sampling_info& second) noexcept + { + return first.sample_rate == second.sample_rate && + first.sample_count == second.sample_count; + } }; struct beatgrid_marker { int32_t index = 0; double sample_offset = 0; + + friend bool operator==( + const beatgrid_marker& first, const beatgrid_marker& second) noexcept + { + return first.index == second.index && + first.sample_offset == second.sample_offset; + } }; struct hot_cue @@ -48,6 +62,13 @@ struct hot_cue std::string label; double sample_offset = 0; pad_color color; + + friend bool operator==(const hot_cue& first, const hot_cue& second) noexcept + { + return first.label == second.label && + first.sample_offset == second.sample_offset && + first.color == second.color; + } }; struct loop @@ -56,12 +77,26 @@ struct loop double start_sample_offset = 0; double end_sample_offset = 0; pad_color color; + + friend bool operator==(const loop& first, const loop& second) noexcept + { + return first.label == second.label && + first.start_sample_offset == second.start_sample_offset && + first.end_sample_offset == second.end_sample_offset && + first.color == second.color; + } }; struct waveform_point { uint8_t value = 0; uint8_t opacity = 255; + + friend bool operator==( + const waveform_point& first, const waveform_point& second) noexcept + { + return first.value == second.value && first.opacity == second.opacity; + } }; /** @@ -82,6 +117,13 @@ struct waveform_entry waveform_point low; waveform_point mid; waveform_point high; + + friend bool operator==( + const waveform_entry& first, const waveform_entry& second) noexcept + { + return first.low == second.low && first.mid == second.mid && + first.high == second.high; + } }; } // namespace djinterop diff --git a/src/djinterop/enginelibrary/el_track_impl.cpp b/src/djinterop/enginelibrary/el_track_impl.cpp index fe1ddca..61fc142 100644 --- a/src/djinterop/enginelibrary/el_track_impl.cpp +++ b/src/djinterop/enginelibrary/el_track_impl.cpp @@ -201,6 +201,12 @@ overview_waveform_data el_track_impl::get_overview_waveform_data() void el_track_impl::set_overview_waveform_data(overview_waveform_data data) { + for (auto&& entry : data.waveform) + { + entry.low.opacity = 255; + entry.mid.opacity = 255; + entry.high.opacity = 255; + } set_perfdata("overviewWaveFormData", data); } diff --git a/src/djinterop/enginelibrary/el_track_impl.hpp b/src/djinterop/enginelibrary/el_track_impl.hpp index bd934e1..f1964ae 100644 --- a/src/djinterop/enginelibrary/el_track_impl.hpp +++ b/src/djinterop/enginelibrary/el_track_impl.hpp @@ -135,6 +135,17 @@ public: template void set_perfdata(const char* column_name, const T& content) { + auto encoded_content = content.encode(); + // Check that subsequent reads can correctly decode what we are about to + // write. + if (!(T::decode(encoded_content) == content)) + { + throw std::logic_error{ + "Data supplied for column " + std::string(column_name) + + " is not invariant under encoding and subsequent decoding. " + "This is a bug in libdjinterop."}; + } + bool found = false; storage_->db << "SELECT COUNT(*) FROM PerformanceData WHERE id = ?" << id() >> @@ -182,7 +193,7 @@ public: storage_->db << (std::string{"UPDATE PerformanceData SET "} + column_name + " = ?, isAnalyzed = 1 WHERE id = ?") - << content.encode() << id(); + << encoded_content << id(); } beat_data get_beat_data(); diff --git a/src/djinterop/enginelibrary/performance_data_format.hpp b/src/djinterop/enginelibrary/performance_data_format.hpp index e96fb71..acf1cb6 100644 --- a/src/djinterop/enginelibrary/performance_data_format.hpp +++ b/src/djinterop/enginelibrary/performance_data_format.hpp @@ -33,23 +33,39 @@ namespace enginelibrary { struct beat_data { - beat_data() noexcept = default; - boost::optional sampling; std::vector default_beatgrid; std::vector adjusted_beatgrid; + beat_data() noexcept = default; + + friend bool operator==( + const beat_data& first, const beat_data& second) noexcept + { + return first.sampling == second.sampling && + first.default_beatgrid == second.default_beatgrid && + first.adjusted_beatgrid == second.adjusted_beatgrid; + } + std::vector encode() const; static beat_data decode(const std::vector& compressed_data); }; struct high_res_waveform_data { - high_res_waveform_data() noexcept = default; - double samples_per_entry; std::vector waveform; + high_res_waveform_data() noexcept = default; + + friend bool operator==( + const high_res_waveform_data& first, + const high_res_waveform_data& second) noexcept + { + return first.samples_per_entry == second.samples_per_entry && + first.waveform == second.waveform; + } + std::vector encode() const; static high_res_waveform_data decode( const std::vector& compressed_data); @@ -57,10 +73,16 @@ struct high_res_waveform_data struct loops_data { - loops_data() = default; - std::array, 8> loops; // Don't use curly braces here! + loops_data() noexcept = default; + + friend bool operator==( + const loops_data& first, const loops_data& second) noexcept + { + return first.loops == second.loops; + } + std::vector encode() const; static loops_data decode( const std::vector& raw_data); // not compressed @@ -68,11 +90,19 @@ struct loops_data struct overview_waveform_data { - overview_waveform_data() noexcept = default; - double samples_per_entry; std::vector waveform; + overview_waveform_data() noexcept = default; + + friend bool operator==( + const overview_waveform_data& first, + const overview_waveform_data& second) noexcept + { + return first.samples_per_entry == second.samples_per_entry && + first.waveform == second.waveform; + } + std::vector encode() const; static overview_waveform_data decode( const std::vector& compressed_data); @@ -80,27 +110,41 @@ struct overview_waveform_data struct quick_cues_data { - quick_cues_data() = default; - std::array, 8> hot_cues; double adjusted_main_cue = 0; double default_main_cue = 0; - std::vector encode() const; + quick_cues_data() noexcept = default; + + friend bool operator==( + const quick_cues_data& first, const quick_cues_data& second) noexcept + { + return first.hot_cues == second.hot_cues && + first.adjusted_main_cue == second.adjusted_main_cue && + first.default_main_cue == second.default_main_cue; + } + std::vector encode() const; static quick_cues_data decode(const std::vector& compressed_data); }; struct track_data { - track_data() noexcept = default; - boost::optional sampling; boost::optional average_loudness; // range (0, 1] boost::optional key; - std::vector encode() const; + track_data() noexcept = default; + + friend bool operator==( + const track_data& first, const track_data& second) noexcept + { + return first.sampling == second.sampling && + first.average_loudness == second.average_loudness && + first.key == second.key; + } + std::vector encode() const; static track_data decode(const std::vector& compressed_data); }; -- cgit v1.2.3 From 7ccad9190781e38ca9557af4d6e33348a6e422d9 Mon Sep 17 00:00:00 2001 From: haslersn Date: Sun, 7 Jun 2020 21:30:02 +0200 Subject: enginelibrary: Allow reading beat data even if the beatgrid is malformed This way malformed Engine Prime libraries can be salvaged in some cases. --- src/djinterop/enginelibrary/performance_data_format.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/djinterop/enginelibrary/performance_data_format.cpp b/src/djinterop/enginelibrary/performance_data_format.cpp index e346448..58a9a42 100644 --- a/src/djinterop/enginelibrary/performance_data_format.cpp +++ b/src/djinterop/enginelibrary/performance_data_format.cpp @@ -193,8 +193,21 @@ beat_data beat_data::decode(const std::vector& compressed_data) // TODO (haslersn): print a warning that "Is beat data set" is not 1 } - std::tie(result.default_beatgrid, ptr) = decode_beatgrid(ptr, end); - std::tie(result.adjusted_beatgrid, ptr) = decode_beatgrid(ptr, end); + try + { + std::vector default_beatgrid; + std::vector adjusted_beatgrid; + std::tie(default_beatgrid, ptr) = decode_beatgrid(ptr, end); + std::tie(adjusted_beatgrid, ptr) = decode_beatgrid(ptr, end); + // If there's an exception, then the following will intentially not be + // executed. + result.default_beatgrid = std::move(default_beatgrid); + result.adjusted_beatgrid = std::move(adjusted_beatgrid); + } + catch (const std::invalid_argument& e) + { + // TODO (haslersn): print a warning with e.what(). + } if (ptr != end) { -- cgit v1.2.3 From c2a03d814283bcbeb78f03711aa6216cc105eaa3 Mon Sep 17 00:00:00 2001 From: haslersn <33969028+haslersn@users.noreply.github.com> Date: Fri, 12 Jun 2020 12:14:53 +0200 Subject: einginelibrary: In el_track_impl::set_overview_waveform_data, add explanatory comment Co-authored-by: Adam Szmigin --- src/djinterop/enginelibrary/el_track_impl.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/djinterop/enginelibrary/el_track_impl.cpp b/src/djinterop/enginelibrary/el_track_impl.cpp index 61fc142..3ab3d7e 100644 --- a/src/djinterop/enginelibrary/el_track_impl.cpp +++ b/src/djinterop/enginelibrary/el_track_impl.cpp @@ -201,6 +201,9 @@ overview_waveform_data el_track_impl::get_overview_waveform_data() void el_track_impl::set_overview_waveform_data(overview_waveform_data data) { + // As the overview waveform does not store opacity, it is defaulted to 255 + // when read back. If we also set it to 255 here, we can apply a check in + // `set_perfdata` that a round-trip encode/decode gives the same data. for (auto&& entry : data.waveform) { entry.low.opacity = 255; -- cgit v1.2.3 From 95ca21ee6cc7c58694c64feee27e24d8aed74f78 Mon Sep 17 00:00:00 2001 From: haslersn Date: Fri, 12 Jun 2020 13:02:59 +0200 Subject: enginelibrary: Roundtrip check failure is not necessarily due to libdjinterop bug --- src/djinterop/enginelibrary/el_track_impl.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/djinterop/enginelibrary/el_track_impl.hpp b/src/djinterop/enginelibrary/el_track_impl.hpp index f1964ae..bf82ee6 100644 --- a/src/djinterop/enginelibrary/el_track_impl.hpp +++ b/src/djinterop/enginelibrary/el_track_impl.hpp @@ -140,6 +140,9 @@ public: // write. if (!(T::decode(encoded_content) == content)) { + // TODO (haslersn): As soon as warnings are implemented, add the + // wording similar to "Either you got a warning above which tells + // you what is wrong, or this is a bug in libdjinterop." throw std::logic_error{ "Data supplied for column " + std::string(column_name) + " is not invariant under encoding and subsequent decoding. " -- cgit v1.2.3