49 bool loopEnabled READ loopEnabled WRITE setLoopEnabled NOTIFY
52 bool recordEnabled READ recordEnabled WRITE setRecordEnabled NOTIFY
55 bool punchEnabled READ punchEnabled WRITE setPunchEnabled NOTIFY
58 zrythm::dsp::ITransport::PlayState playState READ getPlayState WRITE
59 setPlayState NOTIFY playStateChanged)
65 loopStartPosition CONSTANT)
74 punchOutPosition CONSTANT)
79 static constexpr auto REPEATED_BACKWARD_MS = au::milli (units::seconds) (240);
164 std::pair<units::sample_t, units::sample_t> loop_range,
165 std::pair<units::sample_t, units::sample_t> punch_range,
166 units::sample_t playhead_position,
169 PlayState play_state,
173 : loop_range_ (loop_range), punch_range_ (punch_range),
174 playhead_position_ (playhead_position),
177 play_state_ (play_state), loop_enabled_ (loop_enabled),
182 std::pair<units::sample_t, units::sample_t>
187 std::pair<units::sample_t, units::sample_t>
192 PlayState get_play_state () const noexcept
override {
return play_state_; }
196 return playhead_position_;
198 bool loop_enabled () const noexcept
override {
return loop_enabled_; }
200 bool punch_enabled () const noexcept
override {
return punch_enabled_; }
203 return recording_enabled_;
208 return recording_preroll_frames_remaining_;
213 return metronome_countin_frames_remaining_;
216 void set_play_state (dsp::ITransport::PlayState play_state)
218 play_state_ = play_state;
220 void set_position (units::sample_t position)
222 playhead_position_ = position;
224 void consume_metronome_countin_samples (units::sample_t samples)
226 metronome_countin_frames_remaining_ -= samples;
228 void consume_recording_preroll_samples (units::sample_t samples)
230 recording_preroll_frames_remaining_ -= samples;
234 std::pair<units::sample_t, units::sample_t> loop_range_;
235 std::pair<units::sample_t, units::sample_t> punch_range_;
236 units::sample_t playhead_position_;
237 units::sample_t recording_preroll_frames_remaining_;
238 units::sample_t metronome_countin_frames_remaining_;
239 PlayState play_state_;
242 bool recording_enabled_;
246 const dsp::TempoMap &tempo_map,
248 QObject * parent =
nullptr);
254 bool loopEnabled ()
const {
return loop_enabled (); }
255 void setLoopEnabled (
bool enabled);
256 Q_SIGNAL
void loopEnabledChanged (
bool enabled);
259 void setRecordEnabled (
bool enabled);
260 Q_SIGNAL
void recordEnabledChanged (
bool enabled);
262 bool punchEnabled ()
const {
return punch_enabled (); }
263 void setPunchEnabled (
bool enabled);
264 Q_SIGNAL
void punchEnabledChanged (
bool enabled);
266 PlayState getPlayState ()
const;
267 void setPlayState (PlayState state);
268 Q_SIGNAL
void playStateChanged (PlayState state);
270 dsp::PlayheadQmlWrapper * playhead ()
const
272 return playhead_adapter_.get ();
274 dsp::AtomicPositionQmlAdapter * cuePosition ()
const
276 return cue_position_adapter_.get ();
278 dsp::AtomicPositionQmlAdapter * loopStartPosition ()
const
280 return loop_start_position_adapter_.get ();
282 dsp::AtomicPositionQmlAdapter * loopEndPosition ()
const
284 return loop_end_position_adapter_.get ();
288 return punch_in_position_adapter_.get ();
292 return punch_out_position_adapter_.get ();
303 Q_INVOKABLE
void requestRoll () [[clang::blocking]];
325 return playhead_.position_during_processing_rounded ();
328 std::pair<units::sample_t, units::sample_t>
331 return std::make_pair (
332 loop_start_position_.get_samples (), loop_end_position_.get_samples ());
335 std::pair<units::sample_t, units::sample_t>
338 return std::make_pair (
339 punch_in_position_.get_samples (), punch_out_position_.get_samples ());
342 PlayState get_play_state () const noexcept
override {
return play_state_; }
344 bool loop_enabled () const noexcept
override {
return loop_; }
345 bool punch_enabled () const noexcept
override {
return punch_mode_; }
349 return recording_preroll_frames_remaining_;
353 return countin_frames_remaining_;
358 Q_INVOKABLE
bool isRolling ()
const
360 return play_state_ == PlayState::Rolling;
363 Q_INVOKABLE
bool isPaused ()
const
365 return play_state_ == PlayState::Paused;
374 void set_play_state_rt_safe (PlayState state);
388 void move_playhead (units::precise_tick_t target_ticks,
bool set_cue_point);
400 std::vector<units::precise_tick_t> marker_ticks;
401 static_assert (__cpp_lib_containers_ranges >= 202202L);
402 marker_ticks.append_range (extra_markers);
403 marker_ticks.emplace_back (cue_position_.get_ticks ());
404 marker_ticks.emplace_back (loop_start_position_.get_ticks ());
405 marker_ticks.emplace_back (loop_end_position_.get_ticks ());
406 marker_ticks.emplace_back ();
407 std::ranges::sort (marker_ticks);
412 const auto &[index, marker_tick] :
413 marker_ticks | utils::views::enumerate | std::views::reverse)
415 if (marker_tick >= playhead_.position_ticks ())
419 isRolling () && index > 0
420 && (playhead_.get_tempo_map ().tick_to_seconds (
421 playhead_.position_ticks ())
422 - playhead_.get_tempo_map ().tick_to_seconds (marker_tick))
423 < REPEATED_BACKWARD_MS)
434 for (
auto &marker : marker_ticks)
445 bool position_is_inside_punch_range (units::sample_t pos);
447 auto playhead_ticks_before_pause () const [[clang::blocking]]
449 return playhead_before_pause_;
459 assert (countin_frames_remaining_ >= samples);
460 countin_frames_remaining_ -= samples;
470 assert (recording_preroll_frames_remaining_ >= samples);
471 recording_preroll_frames_remaining_ -= samples;
474 auto get_snapshot ()
const
476 return TransportSnapshot{
489 friend void init_from (
491 const Transport &other,
495 static constexpr auto kPlayheadKey =
"playheadPosition"sv;
496 static constexpr auto kCuePosKey =
"cuePosition"sv;
497 static constexpr auto kLoopStartPosKey =
"loopStartPosition"sv;
498 static constexpr auto kLoopEndPosKey =
"loopEndPosition"sv;
499 static constexpr auto kPunchInPosKey =
"punchInPosition"sv;
500 static constexpr auto kPunchOutPosKey =
"punchOutPosition"sv;
501 friend void to_json (nlohmann::json &j,
const Transport &transport);
502 friend void from_json (
const nlohmann::json &j, Transport &transport);
508 bool can_user_move_playhead ()
const;
512 dsp::Playhead playhead_;
513 utils::QObjectUniquePtr<dsp::PlayheadQmlWrapper> playhead_adapter_;
515 std::unique_ptr<dsp::AtomicPosition::TimeConversionFunctions>
516 time_conversion_funcs_;
519 dsp::AtomicPosition cue_position_;
520 utils::QObjectUniquePtr<dsp::AtomicPositionQmlAdapter> cue_position_adapter_;
523 dsp::AtomicPosition loop_start_position_;
524 utils::QObjectUniquePtr<dsp::AtomicPositionQmlAdapter>
525 loop_start_position_adapter_;
528 dsp::AtomicPosition loop_end_position_;
529 utils::QObjectUniquePtr<dsp::AtomicPositionQmlAdapter>
530 loop_end_position_adapter_;
533 dsp::AtomicPosition punch_in_position_;
534 utils::QObjectUniquePtr<dsp::AtomicPositionQmlAdapter>
535 punch_in_position_adapter_;
538 dsp::AtomicPosition punch_out_position_;
539 utils::QObjectUniquePtr<dsp::AtomicPositionQmlAdapter>
540 punch_out_position_adapter_;
546 bool punch_mode_{
false };
550 bool recording_{
false };
553 units::sample_t recording_preroll_frames_remaining_;
556 units::sample_t countin_frames_remaining_;
563 units::precise_tick_t playhead_before_pause_;
566 PlayState play_state_{ PlayState::Paused };
575 QTimer * property_notification_timer_ =
nullptr;
576 std::atomic<bool> needs_property_notification_{
false };