2#include "trkn/tracktion.hh"
20 int32 next_note_id_ = 0;
23 aseclip_ (aseclip), clip_state_ (aseclip_.clip_->state), tempo_state_ (aseclip_.clip_->edit.tempoSequence.getState())
36 std::erase_if (note_states_, [] (
const auto &entry) {
return entry.second.getReferenceCount() == 1; });
42 for (
const auto &entry : note_states_)
43 if (entry.second == note.state)
51 note_states_.emplace (
id, note.state);
53 return { id, note.getNoteNumber(), note.getStartBeat().inBeats(), note.getLengthBeats().inBeats(),
54 note.getVelocity(), note.getColour(), note.isMute() };
59 auto entry = note_states_.find (
id);
60 return entry == note_states_.end() ? nullptr : sequence.getNoteFor (entry->second);
65 if (tree == clip_state_ || tree.
isAChildOf (clip_state_))
74 if (tree.
hasType (te::IDs::NOTE))
76 if (tree == tempo_state_ || tree.
isAChildOf (tempo_state_))
83 if (property == tracktion::engine::IDs::name)
85 else if (property == tracktion::engine::IDs::start ||
86 property == tracktion::engine::IDs::length ||
87 property == tracktion::engine::IDs::offset)
93 else if (property == tracktion::engine::IDs::mute)
95 else if (property == tracktion::engine::IDs::volDb || property == tracktion::engine::IDs::gain)
97 else if (property == tracktion::engine::IDs::pan)
105 void valueTreeChildOrderChanged (
juce::ValueTree&,
int,
int)
override {}
110ClipImpl::ClipImpl (tracktion::Clip &clip) :
118ClipImpl::from_trkn (tracktion::Clip &c)
120 ClipImpl *clip = find_ase_obj<ClipImpl> (c);
122 return shared_ptr_cast<ClipImpl> (clip);
123 ClipImplP clipp = ClipImpl::make_shared (c);
130 state_listener_ =
nullptr;
134ClipImpl::clip_index ()
const
136 if (
auto c = clip_.get())
137 if (
auto timpl = find_ase_obj<TrackImpl> (c->getTrack()))
138 return timpl->clip_index (*
this);
143ClipImpl::name ()
const
145 return clip_.get() ? clip_->getName().toStdString() :
"";
152 clip_->edit.getUndoManager().beginNewTransaction (
"Set Clip Name");
157ClipImpl::position ()
const
160 const auto p = clip_->getPosition();
161 return { { p.time.getStart().inSeconds(), p.time.getEnd().inSeconds() }, p.offset.inSeconds() };
165ClipImpl::position (
const ClipPosition &position)
168 clip_->edit.getUndoManager().beginNewTransaction (
"Set Clip Position");
169 clip_->setPosition ({ { tracktion::TimePosition::fromSeconds (position.time.start),
170 tracktion::TimePosition::fromSeconds (position.time.end) },
171 tracktion::TimeDuration::fromSeconds (position.offset) });
181ClipImpl::all_notes (
const ClipNoteS ¬es)
184 ClipNoteS batch = all_notes();
186 for (
auto ¬e : batch)
187 note.length_beats = 0;
188 for (
auto note : notes)
191 batch.push_back (note);
197ClipImpl::all_notes ()
const
202 state_listener_->prune_notes();
203 for (
auto note : mclip->getSequence().getNotes())
204 notes.push_back (state_listener_->describe_note (*note));
211 return clip_.get() ? clip_->getStartBeat().inBeats() : 0;
217 warning (
"Clip.start_beat is read-only; assign Clip.position");
223 return clip_.get() ? clip_->getEndBeat().inBeats() : 0;
229 warning (
"Clip.end_beat is read-only; assign Clip.position");
236 return clip_->isMuted();
243 auto &um = clip_->edit.getUndoManager();
244 um.beginNewTransaction (
"Set Clip Muted");
245 clip_->setMuted (
muted);
254 return mclip->getVolumeDb();
265 auto &um = clip_->edit.getUndoManager();
266 um.beginNewTransaction (
"Set Clip Volume");
269 mclip->setVolumeDb (db);
293 clip_->edit.getUndoManager().beginNewTransaction (
"Set Clip Pan");
294 aclip->setPan (panval);
300 StringS props = {
"end_beat",
"start_beat" };
316ClipImpl::update_telemetry ()
323 auto *clip = clip_.get();
326 clip->removeFromParent();
329 state_listener_ =
nullptr;
340 auto &sequence = mclip->getSequence();
341 auto &um = clip_->edit.getUndoManager();
343 um.beginNewTransaction (
juce::String (undogroup.
empty() ?
"Change Notes" : undogroup));
344 ClipNoteS changed (batch.size());
345 state_listener_->prune_notes();
347 for (
size_t i = 0; i < batch.size(); i++)
349 const auto ¬e = batch[i];
350 if (note.id > 0 && note.length_beats == 0)
351 if (
auto n = state_listener_->find_note (sequence, note.id))
354 sequence.removeNote (*n, &um);
358 for (
size_t i = 0; i < batch.size(); i++)
360 const auto ¬e = batch[i];
361 if (note.id > 0 && note.length_beats != 0)
362 if (
auto n = state_listener_->find_note (sequence, note.id))
364 n->setStartAndLength (tracktion::BeatPosition::fromBeats (note.start_beat),
365 tracktion::BeatDuration::fromBeats (note.length_beats), &um);
366 n->setNoteNumber (note.note_number, &um);
367 n->setVelocity (note.velocity, &um);
368 n->setColour (note.colour, &um);
369 n->setMute (note.mute, &um);
370 changed[i] = state_listener_->describe_note (*n);
374 for (
size_t i = 0; i < batch.size(); i++)
376 const auto ¬e = batch[i];
377 if (note.id <= 0 && note.length_beats != 0)
378 if (
auto n = sequence.addNote (note.note_number, tracktion::BeatPosition::fromBeats (note.start_beat),
379 tracktion::BeatDuration::fromBeats (note.length_beats), note.velocity, note.colour, &um))
381 n->setMute (note.mute, &um);
382 changed[i] = state_listener_->describe_note (*n);
ClipNoteS list_all_notes() override
List all notes of this Clip, changes on notify:notes.
float pan() const override
Get audio clip pan (-1.0 to 1.0), 0 for other clips.
StringS read_only_properties() const override
List x()/x (v) properties that this object can't change, their setters ignore the value or warn.
bool muted() const override
Check if clip is muted.
TelemetryFieldS telemetry() const override
Retrieve clip telemetry locations.
ClipNoteS change_batch(const ClipNoteS ¬es, const String &undogroup) override
Insert id <= 0, delete length_beats == 0; emits notify:notes and notify:all_notes.
double end_beat() const override
Clip end in Tracktion beats, changes on notify:end_beat.
float volume() const override
Get clip volume in dB.
double start_beat() const override
Clip start in Tracktion beats, changes on notify:start_beat.
void remove_self() override
Remove self from parent container.
void emit_notify(const String &detail) override
Emit notify:detail, multiple notifications maybe coalesced if a CoalesceNotifies instance exists.
void remove_self() override
Remove self from parent container.
Mimick tracktion::engine::SafeSelectable<> for tracktion::Selectable descendants.
bool hasType(const Identifier &typeName) const noexcept
bool isAChildOf(const ValueTree &possibleParent) const noexcept
void addListener(Listener *listener)
void removeListener(Listener *listener)
float getPan() const noexcept
float getGainDB() const noexcept
#define assert_return(expr,...)
Return from the current function if expr is unmet and issue an assertion warning.
#define return_unless(cond,...)
Return silently if cond does not evaluate to true with return value ...
The Anklang C++ API namespace.
int32_t int32
A 32-bit signed integer.
void register_ase_obj(VirtualBase *ase_impl, tracktion::Selectable &selectable)
Helper: register AseImpl with a tracktion Selectable via ase_obj_.
std::string String
Convenience alias for std::string.
void unregister_ase_obj(VirtualBase *ase_impl, tracktion::Selectable *selectable)
Helper: unregister AseImpl from a tracktion Selectable (selectable may be nullptr)
A Tracktion MIDI note with a session handle for edits.