6#include "dsp/position.h"
7#include "gui/dsp/arranger_object.h"
8#include "gui/dsp/automation_point.h"
9#include "gui/dsp/colored_object.h"
10#include "gui/dsp/loopable_object.h"
11#include "gui/dsp/muteable_object.h"
12#include "gui/dsp/named_object.h"
13#include "gui/dsp/timeline_object.h"
14#include "utils/format.h"
35#define DEFINE_REGION_QML_PROPERTIES(ClassType) \
37 DEFINE_LOOPABLE_OBJECT_QML_PROPERTIES (ClassType) \
38 DEFINE_NAMEABLE_OBJECT_QML_PROPERTIES (ClassType) \
39 DEFINE_COLORED_OBJECT_QML_PROPERTIES (ClassType) \
71template <
typename RegionT>
74template <
typename RegionT>
92 std::variant<MidiRegion, ChordRegion, AutomationRegion, AudioRegion>;
93using RegionPtrVariant = to_pointer_variant<RegionVariant>;
97 std::same_as<T, MidiRegion> || std::same_as<T, ChordRegion>;
107 :
virtual public TimelineObject,
108 virtual public NamedObject,
109 virtual public MuteableObject,
110 virtual public LoopableObject,
114 ~Region ()
override =
default;
116 bool is_midi ()
const {
return get_type () == Type::MidiRegion; }
117 bool is_audio ()
const {
return get_type () == Type::AudioRegion; }
118 bool is_automation ()
const {
return get_type () == Type::AutomationRegion; }
119 bool is_chord ()
const {
return get_type () == Type::ChordRegion; }
126 bool has_link_group ()
const {
return link_group_.has_value (); }
155 bool * is_loop)
const;
181 bool include_region_end =
false);
184 Region (ArrangerObjectRegistry &object_registry)
185 : object_registry_ (object_registry)
188 Q_DISABLE_COPY_MOVE (
Region)
193 static constexpr std::string_view kLinkGroupKey =
"linkGroup";
194 friend void to_json (nlohmann::json &j,
const Region ®ion)
196 j[kLinkGroupKey] = region.link_group_;
198 friend void from_json (
const nlohmann::json &j, Region ®ion)
200 j.at (kLinkGroupKey).get_to (region.link_group_);
204 ArrangerObjectRegistry &object_registry_;
208 std::optional<int> link_group_;
240template <
typename RegionT>
class RegionImpl :
virtual public Region
243 RegionImpl ()
noexcept { }
246 ~RegionImpl ()
override =
default;
247 Z_DISABLE_COPY_MOVE (RegionImpl)
249 using RegionTPtr = RegionT *;
251 static constexpr bool is_midi ()
253 return std::is_same_v<RegionT, MidiRegion>;
255 static constexpr bool is_audio ()
257 return std::is_same_v<RegionT, AudioRegion>;
259 static constexpr bool is_automation ()
261 return std::is_same_v<RegionT, AutomationRegion>;
263 static constexpr bool is_chord ()
265 return std::is_same_v<RegionT, ChordRegion>;
267 static constexpr bool is_laned ()
269 return std::is_same_v<MidiRegion, RegionT>
270 || std::is_same_v<AudioRegion, RegionT>;
273 static constexpr bool has_children ()
275 return !std::is_same_v<RegionT, AudioRegion>;
278 using ChildT = RegionChildType_t<RegionT>;
279 using ChildTPtr = ChildT *;
288 for (
auto * obj : self.get_children_view ())
290 children.push_back (obj);
314 TrackPtrVariant track_var,
316 bool note_off_at_end,
317 bool is_note_off_for_loop_or_region_end,
321 auto get_object_ptr (
const ArrangerObject::Uuid
id)
const
324 return std::get<ChildT *> (
325 get_arranger_object_registry ().find_by_id_or_throw (
id));
327 auto get_object_ptr (
const ArrangerObjectUuidReference &
id)
const
330 return std::get<ChildT *> (
id.get_object ());
334 auto * get_region_owner (
this const RegionT &self)
336 if constexpr (is_laned ())
338 auto &lane = self.get_lane ();
339 return std::addressof (lane);
341 else if constexpr (is_automation ())
344 [&] (
auto &&automatable_track) -> AutomationTrack * {
345 using TrackT = base_type<
decltype (automatable_track)>;
346 if constexpr (std::derived_from<TrackT, AutomatableTrack>)
349 automatable_track->get_automation_tracklist ()
350 .get_automation_track_by_port_id (self.automatable_port_id_);
355 throw std::runtime_error (
"Invalid track");
360 else if constexpr (is_chord ())
362 return std::get<ChordTrack *> (self.get_track ());
367 auto &get_arranger_object_registry ()
const {
return object_registry_; }
368 auto &get_arranger_object_registry () {
return object_registry_; }
376 z_debug (
"removing all children from {} ", self.get_name ());
378 auto vec = self.get_children_vector ();
379 for (
auto &obj : vec)
381 self.remove_object (obj.id ());
389 return insert_clone_to_project_at_index (-1, fire_events);
394 return insert_clone_to_project_at_index (-1,
true);
424 for (
auto * obj : self.get_children_view ())
426 obj->set_region_and_index (self);
460 void create_link_group_if_none ();
464 insert_clone_to_project_at_index (
int index,
bool fire_events)
const;
478 [[gnu::hot]]
void send_note_offs (
481 bool is_note_off_for_loop_or_region_end)
const
484 const RegionT &get_derived ()
const
486 return static_cast<const RegionT &
> (*this);
488 RegionT &get_derived () {
return static_cast<RegionT &
> (*this); }
491template <
typename RegionT>
495DEFINE_ENUM_FORMATTER (
498 QT_TRANSLATE_NOOP_UTF8 (
"MusicalMode",
"Inherit"),
499 QT_TRANSLATE_NOOP_UTF8 (
"MusicalMode",
"Off"),
500 QT_TRANSLATE_NOOP_UTF8 (
"MusicalMode",
"On"));
504 "Region[id: {}, name: {}, "
505 "<{}> to <{}> ({} frames, {} ticks) - loop end <{}> - link group {}"
514 std::variant<MidiRegion, ChordRegion, AutomationRegion, AudioRegion>;
515using RegionPtrVariant = to_pointer_variant<RegionVariant>;
517template <
typename RegionT>
auto get_position() const
Getter.
An AudioRegion represents a region of audio within a Track.
Interface for a track that has automatable parameters.
An automation point inside an AutomationTrack.
Represents an automation region, which contains a collection of automation points.
PositionProxy * end_pos_
End Position, if the object has one.
The ChordObject class represents a chord inside a ChordRegion.
dsp::Position loop_end_pos_
End position of the clip loop, relative to the object's start.
A MIDI note inside a Region shown in the piano roll.
A Region containing MIDI events.
utils::Utf8String get_name() const
Returns the name of the object.
ArrangerObjectPtrVariant add_clone_to_project(bool fire_events) const final
Appends the ArrangerObject to where it belongs in the project (eg, a Track), without taking into acco...
void stretch(double ratio)
Stretch the region's contents.
void fill_midi_events(TrackPtrVariant track_var, const EngineProcessTimeInfo &time_nfo, bool note_off_at_end, bool is_note_off_for_loop_or_region_end, dsp::MidiEventVector &midi_events) const
Fills MIDI event queue from this MIDI or Chord region.
ArrangerObjectPtrVariant insert_clone_to_project() const final
Inserts the object where it belongs in the project (eg, a Track).
void remove_all_children(this RegionT &self)
Removes all children objects from the region.
static RegionT * at_position(const Track *track, const AutomationTrack *at, dsp::Position pos)
Returns the region at the given position in the given Track.
void append_children(this RegionT &self, std::vector< RegionOwnedObject * > &children)
Fills the given vector with all the children of this region.
bool get_muted(bool check_parent) const override
Gets the mute status of the object.
void set_link_group(int group_idx, bool update_identifier)
Sets the link group to the region.
void unlink()
Removes the link group from the region, if any.
void update_identifier(this ChordRegion &self)
A group of linked regions.
A region (clip) is an object on the timeline that contains either MidiNote's or AudioClip's.
double stretch_ratio_
Used during arranger UI overlay actions.
signed_frame_t timeline_frames_to_local(signed_frame_t timeline_frames, bool normalize) const
Converts frames on the timeline (global) to local frames (in the clip).
bool is_recording()
Returns if this region is currently being recorded onto.
static std::optional< ArrangerObjectPtrVariant > get_at_pos(dsp::Position pos, Track *track, AutomationTrack *at, bool include_region_end=false)
Returns the region at the given position, if any.
RegionLinkGroup * get_link_group()
Returns the region's link group.
int bounce_
Set to ON during bouncing if this region should be included.
bool stretching_
Whether currently running the stretching algorithm.
void get_frames_till_next_loop_or_end(signed_frame_t timeline_frames, signed_frame_t *ret_frames, bool *is_loop) const
Returns the number of frames until the next loop end point or the end of the region.
void update_link_group()
Updates all other regions in the region link group, if any.
double before_length_
The length before stretching, in ticks.
Represents a track in the project.
A lock-free thread-safe vector of MidiEvents.
Represents the position of an object.
signed_frame_t frames_
Position in frames (samples).
double ticks_
Precise total number of ticks.
MusicalMode
Musical mode setting for audio regions.
@ On
Musical mode on - auto-stretch when BPM changes.
@ Inherit
Inherit from global musical mode setting.
#define DEFINE_OBJECT_FORMATTER(obj_type, function_prefix, formatter_func)
Defines a formatter for the given object type.
int_fast64_t signed_frame_t
Signed type for frame index.
Common struct to pass around during processing to avoid repeating the data in function arguments.