Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serato Markers Integration for Track Color/BPM lock #2499

Merged
merged 11 commits into from Mar 5, 2020

Conversation

Holzhaus
Copy link
Member

@Holzhaus Holzhaus commented Feb 13, 2020

This adds support for reading the Serato Markers_ and Serato Markers2 tag that are written by Serato and contains Cues, Loops, Track Color, etc.

This PR supersedes #2473 and depends on #2495. As @daschuer suggested I removed export support for now.

IMPORTANT: You need to apply this patch to enable the actual integration:

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 59564fa2c0..614b65a808 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -698,6 +698,7 @@ add_library(mixxx-lib STATIC EXCLUDE_FROM_ALL
 set_target_properties(mixxx-lib PROPERTIES AUTOMOC ON AUTOUIC ON)
 target_include_directories(mixxx-lib PUBLIC src "${CMAKE_CURRENT_BINARY_DIR}/src")
 target_compile_definitions(mixxx-lib PRIVATE SETTINGS_FILE="mixxx.cfg")
+target_compile_definitions(mixxx-lib PUBLIC __EXTRA_METADATA__)
 if(UNIX AND NOT APPLE)
   target_compile_definitions(mixxx-lib PRIVATE SETTINGS_PATH=".mixxx/")
 endif()

@Holzhaus
Copy link
Member Author

Holzhaus commented Feb 13, 2020

I need some help here. For importing cue positons I need the track's sample rate. However, I cannot use track->getSampleRate() when the file tags are read, because according to a comment in the source code the sample rate will be adjusted by the audio decoder after import from file tags. Any ideas how to solve this? Can we postpone the parsing of the serato tags until after this has happend?

@uklotzde
Copy link
Contributor

uklotzde commented Feb 13, 2020

I need some help here. For importing cue positons I need the track's sample rate. However, I cannot use track->getSampleRate() when the file tags are read, because according to a comment in the source code the sample rate will be adjusted by the audio decoder after import from file tags. Any ideas how to solve this? Can we postpone the parsing of the serato tags until after this has happend?

Mixxx's format for storing the position of cue points in samples is unfortunate. I guess there will be no easy solution other than some dirty hack. In the long term we need to migrate from samples (integer) to time units (floating-point).

The sample rate from the tags is not reliable and may be missing or differ from the sample rate of the actual audio stream. This property is only available after actually opening the stream with a decoder.

@uklotzde
Copy link
Contributor

The correct sample rate must then be passed to the tag reader as an additional parameter for performing these conversions. The tag reader must not make any assumptions how this sample rate is determined.

src/track/track.cpp Outdated Show resolved Hide resolved
@Holzhaus
Copy link
Member Author

@uklotzde thanks for reviewing. Note that only the last 3 commits are new on this branch. Most of the changes actually belong to #2495, so I makes sense to review that one too. I'll probably rebase sooner or later this branch and it would be a shame if comments get lost.

@Holzhaus
Copy link
Member Author

The sample rate from the tags is not reliable and may be missing or differ from the sample rate of the actual audio stream. This property is only available after actually opening the stream with a decoder.

I'm still struggling to find the proper spot for doing this. Seems wrong to read metadata here: https://github.com/mixxxdj/mixxx/blob/master/src/sources/soundsourceproxy.cpp#L526

@uklotzde
Copy link
Contributor

The sample rate from the tags is not reliable and may be missing or differ from the sample rate of the actual audio stream. This property is only available after actually opening the stream with a decoder.

I'm still struggling to find the proper spot for doing this. Seems wrong to read metadata here: https://github.com/mixxxdj/mixxx/blob/master/src/sources/soundsourceproxy.cpp#L526

I agree that this is an ugly side effect. But it is the only opportunity where we could update the metadata with the actual properties. Any ideas how to improve this? Return the audio properties to the caller?

We need to ensure somehow that the Track object gets updated when the corresponding audio stream is opened for the first time! Otherwise the audio properties have to be considered stale.

The SoundSourceProxy needs to hold a (smart) pointer to the track to ensure that no file tags are written while the audio stream is read.

@uklotzde
Copy link
Contributor

The sample rate from the tags is not reliable and may be missing or differ from the sample rate of the actual audio stream. This property is only available after actually opening the stream with a decoder.

I'm still struggling to find the proper spot for doing this. Seems wrong to read metadata here: https://github.com/mixxxdj/mixxx/blob/master/src/sources/soundsourceproxy.cpp#L526

Extracting the audio stream properties from TrackRecord turns out to be more tedious than expected. This is required as a first step to sort out the dependencies.

@Holzhaus
Copy link
Member Author

Apart from the problem that the sample rate is incorrect, I also need a way to get the Track dependency out of the Serato classes.

I was planning to have a QList<CuePointer> getCues(int sampleRate) function that returns cues, then set them via Track::setCuePoints(QList<CuePointer>)); from inside the Track object. That way we wouldn't need to depend on the Track Object at all. That doesn't work though because

  1. The Cue constructor is private, and
  2. it also requires passing the TrackId.

I'm not sure how to solve this. Should I create a new CueInfo class that is used by Cue like Track uses TrackInfo? Or is there a better way to do this?

@Holzhaus
Copy link
Member Author

@uklotzde What do you think?

@uklotzde
Copy link
Contributor

uklotzde commented Feb 25, 2020

@uklotzde What do you think?

Difficult question. I'm biased after I already failed and finally gave up on fixing the cue control code 😬

@Holzhaus Holzhaus mentioned this pull request Feb 28, 2020
@Holzhaus Holzhaus force-pushed the serato-markers-integration branch 5 times, most recently from 7482342 to e448b84 Compare February 28, 2020 18:39
@Holzhaus
Copy link
Member Author

Holzhaus commented Mar 1, 2020

Merge? This is ifdef'ed behind __EXTRA_METADATA__ anyway.

src/track/serato/tags.cpp Outdated Show resolved Hide resolved
return RgbColor(0x999998);
}

if (value == 0x99999a) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many of those magic codes/numbers appear repeatedly and in pairs. Would it make sense to define some constants for them?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about that, too, but decided against it - mainly because I couldn't find fitting names ;-)

src/track/serato/tags.h Outdated Show resolved Hide resolved
Copy link
Contributor

@uklotzde uklotzde left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: Test that dumping empty markers produces empty byte arrays. This is required when exporting the markers into file tags.

@Holzhaus
Copy link
Member Author

Holzhaus commented Mar 1, 2020

TODO: Test that dumping empty markers produces empty byte arrays. This is required when exporting the markers into file tags.

Like this? 27871cb

@Holzhaus
Copy link
Member Author

Holzhaus commented Mar 3, 2020

TODO: Test that dumping empty markers produces empty byte arrays. This is required when exporting the markers into file tags.

I fixed the SeratoMarkers2 default constructor and added tests to make sure that empty QByteArrays are returned when calling dump().

@Holzhaus Holzhaus requested a review from uklotzde March 3, 2020 09:10
@Holzhaus
Copy link
Member Author

Holzhaus commented Mar 4, 2020

Anything else to do here?

@uklotzde
Copy link
Contributor

uklotzde commented Mar 5, 2020

LGTM. No CI failures expected. Thank you Jan!!

@uklotzde uklotzde merged commit fdaacca into mixxxdj:master Mar 5, 2020
@Holzhaus
Copy link
Member Author

Holzhaus commented Mar 5, 2020

@uklotzde Thanks for all the thorough reviews!

@Holzhaus Holzhaus added this to Done in 2.3 release Mar 14, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
2.3 release
  
Done
Development

Successfully merging this pull request may close these issues.

None yet

2 participants