Loading...
Searching...
No Matches
Switches.hpp
1#pragma once
2#include <Fx/Looper/Transport.hpp>
3
4#include <ossia/network/value/value.hpp>
5#include <ossia/network/value/value_conversion.hpp>
6
7#include <halp/controls.hpp>
8#include <halp/grid_chooser.hpp>
9#include <halp/layout.hpp>
10#include <halp/meta.hpp>
11#include <halp/static_string.hpp>
12
13#include <avnd/common/enum_reflection.hpp>
14
15#include <algorithm>
16#include <array>
17#include <cstdint>
18#include <optional>
19#include <string_view>
20#include <utility>
21
41namespace Nodes::Looper
42{
45template <auto F, int Columns>
47{
48 halp_meta(layout, halp::layouts::control)
49 static constexpr int columns() noexcept { return Columns; }
50 decltype(F) model = F;
51};
52
54template <halp::static_string Name, typename Enum, Enum Init>
56{
57 static clang_buggy_consteval auto name() { return std::string_view{Name.value}; }
58 enum widget
59 {
60 combobox
61 };
62 struct range
63 {
64 decltype(avnd::enum_names<Enum>()) values = avnd::enum_names<Enum>();
65 Enum init = Init;
66 };
67 Enum value = Init;
68 operator Enum() const noexcept { return value; }
69 auto& operator=(Enum t) noexcept
70 {
71 value = t;
72 return *this;
73 }
74};
75
78
80inline std::string_view mode_label(LoopMode m) noexcept
81{
82 static constexpr std::array<std::string_view, 4> names{
83 "Play", "Record", "Overdub", "Stop"};
84 const auto i = std::size_t(m);
85 return i < names.size() ? names[i] : names[3];
86}
87
89template <typename Field, typename V>
90void show_control(Field& f, V v)
91{
92 f.value = v;
93 if(f.update_controller)
94 f.update_controller(v);
95}
96
97template <typename Field>
98void show_mode(Field& f, LoopMode m)
99{
100 f.value = m;
101 if(f.update_controller)
102 f.update_controller(mode_label(m));
103}
104
116{
118 bool arrived{};
120 bool streamed{};
122 LoopMode left{LoopMode::Stop};
124 LoopMode last_in{LoopMode::Stop};
125 LoopMode shown{LoopMode::Stop};
126};
127
128template <typename Field>
129void read_loop(Field& f, transport& t, loop_input& l, bool empty)
130{
131 const bool arrived = std::exchange(l.arrived, false) || f.value != l.left;
132 if(arrived)
133 {
134 const LoopMode v = f.value;
135 const bool repeated = l.streamed && v == l.last_in;
136 if(!repeated && v != t.wanted)
137 t.ask(v, empty);
138 l.last_in = v;
139 }
140 l.streamed = arrived;
141}
142
144template <typename Field>
145void show_loop(Field& f, const transport& t, loop_input& l)
146{
147 if(t.wanted != l.shown)
148 {
149 l.shown = t.wanted;
150 show_mode(f, l.shown);
151 }
152 l.left = f.value;
153}
154
158{
159 static clang_buggy_consteval auto name() { return std::string_view{"After record"}; }
160 static constexpr std::string_view former_name() noexcept { return "Post-action"; }
161 enum widget
162 {
163 enumeration,
164 list,
165 combobox
166 };
167 struct range
168 {
169 std::string_view values[2] = {"Play", "Overdub"};
170 AfterRecord init = AfterRecord::Play;
171 };
172 AfterRecord value = AfterRecord::Play;
173 operator AfterRecord() const noexcept { return value; }
174 auto& operator=(AfterRecord t) noexcept
175 {
176 value = t;
177 return *this;
178 }
179 halp_meta(
180 description,
181 "What a recording gives way to when it ends: when its bars run out, "
182 "when the buffer is full, or by Rec / Play / Dub. Play plays the loop; "
183 "Overdub overdubs it from the very frame the recording ends on, so that "
184 "what is held goes on without a gap. Setting Mode ends a recording into "
185 "the mode it is set to.")
186};
187
191{
192 static clang_buggy_consteval auto name() { return std::string_view{"Start from"}; }
193 static constexpr std::string_view former_name() noexcept { return "Restart"; }
194 static constexpr std::array<std::string_view, 3> former_values() noexcept
195 {
196 return {"Always", "Recording", "In phase"};
197 }
198 enum widget
199 {
200 enumeration,
201 list,
202 combobox
203 };
204 struct range
205 {
206 std::string_view values[3] = {"Loop start", "Where it was", "In phase"};
208 };
210 operator StartFrom() const noexcept { return value; }
211 auto& operator=(StartFrom t) noexcept
212 {
213 value = t;
214 return *this;
215 }
216 halp_meta(
217 description,
218 "Where the loop is read from when the mode changes. Loop start reads "
219 "it from its beginning again; Where it was lets playing and overdubbing "
220 "carry on from where the playhead is, so that Play, Overdub and Play "
221 "again stay in time. In phase carries on as well, and a loop played "
222 "again after a stop, or when the score starts or jumps, is where it "
223 "would be had it kept playing with the timeline. A recording always "
224 "starts at the loop's start.")
225};
226
228struct quantif_selector : halp::grid_chooser<"Quantize", quantif_grid, "loop">
229{
230 using grid_chooser::operator=;
231 static constexpr std::string_view former_name() noexcept { return "Quantif"; }
232
236 static ossia::value upgrade_value(const ossia::value& old)
237 {
238 const auto t = old.get_type();
239 if(t != ossia::val_type::FLOAT && t != ossia::val_type::INT
240 && t != ossia::val_type::BOOL)
241 return old;
242 const halp::grid_value g = legacy_grid(ossia::convert<float>(old));
243 return ossia::vec2f{float(g.value), float(int(g.unit))};
244 }
245 static constexpr halp::grid_value legacy_grid(float whole_note_fraction) noexcept
246 {
247 if(!(whole_note_fraction > 0.f))
248 return {};
249 if(whole_note_fraction > 1.f - 1e-6f && whole_note_fraction < 1.f + 1e-6f)
250 return halp::grid_value::bars(1.);
251 return halp::grid_value::note(whole_note_fraction);
252 }
253
254 halp_meta(
255 description,
256 "Waits for the next point of this grid before changing mode, so a loop "
257 "starts and ends in time: a time, a note value (1/1 is a whole note, "
258 "four quarters), a number of bars, or the loop itself. Loop waits for "
259 "the loop to come round to its start; before there is a loop, for the "
260 "length the recording will have, Record bars bars (one bar when Record "
261 "bars is 0). None changes at once.")
262};
263
265inline constexpr halp::grid_setup note_grid{
266 .units = halp::grid_units::note, .init = halp::grid_value::note(0.25)};
267
270struct note_grid_selector : halp::grid_chooser<"Note grid", note_grid>
271{
272 using grid_chooser::operator=;
273 static constexpr std::string_view former_name() noexcept { return "Grid"; }
274
278 static ossia::value upgrade_value(const ossia::value& old)
279 {
280 const auto t = old.get_type();
281 if(t != ossia::val_type::FLOAT && t != ossia::val_type::INT
282 && t != ossia::val_type::BOOL)
283 return old;
284 const float f = ossia::convert<float>(old);
285 const double v = f > 0.f ? f : note_grid.init.value;
286 return ossia::vec2f{float(v), float(int(halp::grid_unit::note))};
287 }
288
289 halp_meta(
290 description,
291 "The note value the notes are pulled towards when played back, as far "
292 "as Strength says.")
293};
294
296 : enum_combobox<"At max layers", AtMaxLayers, AtMaxLayers::MergeIntoNewest>
297{
298 using enum_combobox::operator=;
299 struct range
300 {
301 std::string_view values[3]
302 = {"Merge oldest", "Merge into newest", "Replace a muted layer"};
304 };
305 halp_meta(
306 description,
307 "What a pass does when there are Max layers already. Merge oldest "
308 "merges the two oldest layers into one, losing their undo. Merge into "
309 "newest merges the pass into the newest layer once it ends: undo still "
310 "takes it out, until the next pass starts. Replace a muted layer drops "
311 "the oldest muted layer for the pass, else the newest layer.")
312};
313
314struct rec_play_dub_button : halp::impulse_button<"Rec / Play / Dub">
315{
316 halp_meta(
317 description,
318 "One button for the whole loop: records an empty loop, ends the recording "
319 "into what After record says, overdubs a playing loop, and does what "
320 "After overdub says while overdubbing. A stopped loop plays. Pressed "
321 "again before the grid, each press is taken up on a grid point of its "
322 "own.")
323};
324
325struct stop_at_selector : enum_combobox<"Stop at", StopAt, StopAt::Grid>
326{
327 using enum_combobox::operator=;
328 struct range
329 {
330 std::string_view values[3] = {"Grid", "Loop end", "Now"};
331 StopAt init = StopAt::Grid;
332 };
333 halp_meta(
334 description,
335 "When a stop is taken up, from Stop, Play / Stop or Mode: on the next "
336 "point of the grid, once the loop has played to its end, or at once.")
337};
338
340 : enum_combobox<"After overdub", AfterOverdub, after_overdub_default>
341{
342 using enum_combobox::operator=;
343 struct range
344 {
345 std::string_view values[2] = {"Play", "New layer"};
347 };
348 halp_meta(
349 description,
350 "What Rec / Play / Dub does while overdubbing: go back to playing, or "
351 "go on overdubbing in a new layer, as New layer does.")
352};
353
354struct play_stop_button : halp::impulse_button<"Play / Stop">
355{
356 halp_meta(description, "Plays a stopped loop; stops it in any other mode.")
357};
358
359struct record_button : halp::impulse_button<"Record">
360{
361 halp_meta(
362 description,
363 "Sets Mode to Record: records an empty loop, overdubs one that has "
364 "something in it. Clear the loop first to record a new one. Retrigger "
365 "starts a recording again.")
366};
367
368struct overdub_button : halp::impulse_button<"Overdub">
369{
370 halp_meta(
371 description,
372 "Sets Mode to Overdub. On an empty loop, records it, and the recording "
373 "then gives way to overdubbing.")
374};
375
376struct play_button : halp::impulse_button<"Play">
377{
378 halp_meta(description, "Sets Mode to Play.")
379};
380
381struct stop_button : halp::impulse_button<"Stop">
382{
383 halp_meta(description, "Sets Mode to Stop.")
384};
385
386struct new_layer_button : halp::impulse_button<"New layer">
387{
388 halp_meta(
389 description,
390 "While overdubbing, ends the layer on the grid and goes on overdubbing "
391 "in a new one, without the playhead moving. Does nothing otherwise.")
392};
393
394struct retrigger_button : halp::impulse_button<"Retrigger">
395{
396 halp_meta(
397 description,
398 "Goes back to the start of the loop on the grid, in the same mode: an "
399 "overdub goes on from there in the same layer. While recording, starts "
400 "the recording again, its bars and tempo counted from there.")
401};
402
403struct previous_layer_button : halp::impulse_button<"Previous layer">
404{
405 halp_meta(
406 description,
407 "Selects the layer before the one Layer says, which Mute layer, Erase "
408 "layer and Solo layer act on. The view outlines it.")
409};
410
411struct next_layer_button : halp::impulse_button<"Next layer">
412{
413 halp_meta(description, "Selects the layer after the one Layer says.")
414};
415
416struct mute_layer_button : halp::impulse_button<"Mute layer">
417{
418 halp_meta(
419 description,
420 "Mutes the layer Layer says, or unmutes it, on the grid, as the m of "
421 "its lane does. A muted layer is kept but not heard: it takes nothing "
422 "from the layers under it, is not in the mix of a take, and still has "
423 "its file in a take written as layers.")
424};
425
426struct erase_layer_button : halp::impulse_button<"Erase layer">
427{
428 halp_meta(
429 description,
430 "Removes the layer Layer says, on the grid, as the x of its lane does. "
431 "The layer being overdubbed is dropped and the overdub goes on in a new "
432 "one, as with Undo.")
433};
434
435struct solo_layer_button : halp::impulse_button<"Solo layer">
436{
437 halp_meta(
438 description,
439 "Mutes every layer but the one Layer says, on the grid. Pressed again "
440 "on that layer, the layers get back the mutes they had, unless a mute "
441 "or an erase changed them since; on another layer, solos that one.")
442};
443
444struct reverse_button : halp::impulse_button<"Toggle reverse">
445{
446 halp_meta(description, "Turns Reverse on, or off, on the grid.")
447};
448
449struct half_speed_button : halp::impulse_button<"Half speed">
450{
451 halp_meta(description, "Sets Speed to x1/2, or back to x1 when it is x1/2, on the grid.")
452};
453
454struct double_speed_button : halp::impulse_button<"Double speed">
455{
456 halp_meta(description, "Sets Speed to x2, or back to x1 when it is x2, on the grid.")
457};
458
461{
462 static constexpr int max_passes = 256;
463 std::array<bool, max_passes> muted{};
465 int count{-1};
466 int pass{-1};
467
468 void forget() noexcept { count = -1; }
469
471 template <typename Engine>
472 bool still_soloed(const Engine& e) const noexcept
473 {
474 if(count < 0 || e.looper_passes() != count)
475 return false;
476 for(int i = 0; i < count; i++)
477 if(e.looper_muted(i) != (i != pass))
478 return false;
479 return true;
480 }
481
483 template <typename Engine>
484 void toggle(Engine& e, int selected)
485 {
486 const bool soloed = still_soloed(e);
487 if(soloed && selected == pass)
488 {
489 for(int i = 0; i < count; i++)
490 e.looper_set_muted(i, muted[i]);
491 forget();
492 return;
493 }
494 const int n = std::min(e.looper_passes(), max_passes);
495 if(selected < 0 || selected >= n)
496 return;
497 // From one solo to another, the mutes to give back are the ones from
498 // before the first.
499 if(!soloed)
500 for(int i = 0; i < n; i++)
501 muted[i] = e.looper_muted(i);
502 for(int i = 0; i < n; i++)
503 e.looper_set_muted(i, i != selected);
504 count = n;
505 pass = selected;
506 }
507};
508
512{
513 enum kind_t : uint8_t
514 {
515 mute,
516 erase,
517 solo
518 } kind;
519 int pass;
520 int layers;
521};
522
529{
530 static constexpr int max_actions = 16;
531 std::array<layer_action, max_actions> actions{};
532 int action_count{};
533 bool reverse{};
534 std::optional<float> speed;
535 solo_memory soloed;
538
539 void reset() noexcept
540 {
541 action_count = 0;
542 reverse = false;
543 speed.reset();
544 }
545
546 void add(layer_action a, transport& t) noexcept
547 {
548 if(action_count < max_actions)
549 actions[action_count++] = a;
550 t.request_point();
551 }
552
555 template <typename Inputs, typename Engine>
556 void read(Inputs& in, transport& t, Engine& e, bool empty)
557 {
558 const auto press = [&](TransportAction a) {
559 t.press(a, empty, in.after_record.value, in.after_overdub.value);
560 };
561 const auto set_loop = [&](LoopMode m) {
562 if(t.wanted != m || t.queued())
563 t.ask(m, empty);
564 };
565 if(in.rec_play_dub.value)
567 if(in.play_stop.value)
569 if(in.play.value)
570 set_loop(LoopMode::Play);
571 if(in.stop.value)
572 set_loop(LoopMode::Stop);
573 if(in.record.value)
574 set_loop(LoopMode::Record);
575 if(in.overdub.value)
576 set_loop(LoopMode::Overdub);
577 if(in.new_layer.value)
579 if(in.retrigger.value)
581
582 if(const int n = e.looper_passes();
583 n > 0 && (in.next_layer.value || in.previous_layer.value))
584 {
585 const int step = (in.next_layer.value ? 1 : 0) - (in.previous_layer.value ? 1 : 0);
586 show_control(in.layer, std::clamp(std::clamp(in.layer.value, 1, n) + step, 1, n));
587 }
588
589 if(in.mute_layer.value)
590 add({layer_action::mute, -1, -1}, t);
591 if(in.erase_layer.value)
592 add({layer_action::erase, -1, -1}, t);
593 if(in.solo_layer.value)
594 add({layer_action::solo, -1, -1}, t);
595
596 bool asked = false;
597 if(in.reverse_toggle.value)
598 reverse = !reverse, asked = true;
599 // From the speed a change still waiting for the grid leaves.
600 const auto toggle_speed = [&](float to) {
601 const float from = speed ? *speed : in.speed.value;
602 speed = from == to ? 1.f : to;
603 asked = true;
604 };
605 if(in.half_speed.value)
606 toggle_speed(0.5f);
607 if(in.double_speed.value)
608 toggle_speed(2.f);
609 if(asked)
610 t.request_point();
611 }
612
614 template <typename Inputs, typename Engine>
615 void apply(Inputs& in, Engine& e)
616 {
617 for(int i = 0; i < action_count; i++)
618 {
619 const auto& a = actions[i];
620 const int n = e.looper_passes();
621 if(a.layers >= 0 && a.layers != n)
622 continue;
623 // A Layer past the layers there are names none.
624 const int pass = a.pass >= 0 ? a.pass : in.layer.value - 1;
625 switch(a.kind)
626 {
627 case layer_action::mute:
628 e.looper_mute(pass);
629 break;
630 case layer_action::erase:
631 e.looper_erase(pass);
632 break;
633 case layer_action::solo:
634 soloed.toggle(e, pass);
635 break;
636 }
637 follow(in, e.looper_passes());
638 }
639 action_count = 0;
640 if(std::exchange(reverse, false))
641 show_control(in.reverse, !in.reverse.value);
642 if(speed)
643 show_control(in.speed, *std::exchange(speed, std::nullopt));
644 }
645
648 template <typename Inputs>
649 void follow(Inputs& in, int passes)
650 {
651 const int was = std::exchange(seen_passes, passes);
652 if(passes > was)
653 show_control(in.layer, passes);
654 else if(passes > 0 && in.layer.value > passes)
655 show_control(in.layer, passes);
656 }
657
659 template <typename Inputs>
660 void removed(Inputs& in, int pass)
661 {
662 seen_passes = std::max(0, seen_passes - 1);
663 if(pass < in.layer.value - 1 && in.layer.value > 1)
664 show_control(in.layer, in.layer.value - 1);
665 }
666
670 template <typename Inputs>
671 void merged(Inputs& in, int at)
672 {
673 seen_passes = std::max(0, seen_passes - 1);
674 if(in.layer.value - 1 > at && in.layer.value > 1)
675 show_control(in.layer, in.layer.value - 1);
676 }
677
680 template <typename Inputs>
681 void inserted(Inputs& in, int pass, int passes)
682 {
683 if(pass <= in.layer.value - 1 && in.layer.value < passes)
684 show_control(in.layer, in.layer.value + 1);
685 }
686
690 template <typename Inputs, typename Log>
691 void follow_merges(Inputs& in, Log& log)
692 {
693 if(log.count > 0)
694 soloed.forget();
695 for(int i = 0; i < log.count; i++)
696 merged(in, log.at[i]);
697 log.count = 0;
698 }
699};
700
704template <typename Ins>
706{
707 halp_meta(name, "Switches")
708 halp_meta(layout, halp::layouts::hbox)
709 halp_meta(alignment, halp::alignments::left)
710 halp_meta(spacing, 6)
711 struct
712 {
713 halp_meta(name, "One button")
714 halp_meta(layout, halp::layouts::section)
715 halp_meta(alignment, halp::alignments::left)
716 halp_meta(spacing, 6)
717 struct
718 {
719 halp_meta(layout, halp::layouts::grid)
720 halp_meta(alignment, halp::alignments::left)
721 halp_meta(spacing, 6)
722 halp_meta(columns, 2)
723 halp::item<&Ins::rec_play_dub> rec_play_dub;
724 halp::item<&Ins::play_stop> play_stop;
725 halp::item<&Ins::after_record> after_record;
726 halp::item<&Ins::after_overdub> after_overdub;
727 halp::item<&Ins::stop_at> stop_at;
728 } buttons;
729 } one_button;
730 struct
731 {
732 halp_meta(name, "Transport")
733 halp_meta(layout, halp::layouts::section)
734 halp_meta(alignment, halp::alignments::left)
735 halp_meta(spacing, 6)
736 struct
737 {
738 halp_meta(layout, halp::layouts::grid)
739 halp_meta(alignment, halp::alignments::left)
740 halp_meta(spacing, 6)
741 halp_meta(columns, 2)
742 halp::item<&Ins::play> play;
743 halp::item<&Ins::stop> stop;
744 halp::item<&Ins::record> record;
745 halp::item<&Ins::overdub> overdub;
746 halp::item<&Ins::new_layer> new_layer;
747 halp::item<&Ins::retrigger> retrigger;
748 } buttons;
749 } transport;
750};
751
754template <typename Ins>
756{
757 halp_meta(name, "Layers")
758 halp_meta(layout, halp::layouts::grid)
759 halp_meta(alignment, halp::alignments::left)
760 halp_meta(spacing, 6)
761 halp_meta(columns, 3)
762 halp::item<&Ins::undo> undo;
763 halp::item<&Ins::redo> redo;
764 halp::item<&Ins::clear> clear;
765 halp::item<&Ins::layer> layer;
766 halp::item<&Ins::previous_layer> previous_layer;
767 halp::item<&Ins::next_layer> next_layer;
768 halp::item<&Ins::mute_layer> mute_layer;
769 halp::item<&Ins::erase_layer> erase_layer;
770 halp::item<&Ins::solo_layer> solo_layer;
771};
772
776template <typename Ins>
778{
779 halp_meta(name, "Speed")
780 halp_meta(layout, halp::layouts::vbox)
781 halp_meta(alignment, halp::alignments::left)
782 halp_meta(spacing, 6)
783 struct
784 {
785 halp_meta(layout, halp::layouts::grid)
786 halp_meta(alignment, halp::alignments::left)
787 halp_meta(spacing, 6)
788 halp_meta(columns, 3)
789 halp::item<&Ins::speed> speed;
790 halp::item<&Ins::reverse> reverse;
791 halp::item<&Ins::follow_tempo> follow_tempo;
792 } controls;
793 struct
794 {
795 halp_meta(layout, halp::layouts::grid)
796 halp_meta(alignment, halp::alignments::left)
797 halp_meta(spacing, 6)
798 halp_meta(columns, 3)
799 halp::item<&Ins::reverse_toggle> reverse;
800 halp::item<&Ins::half_speed> half_speed;
801 halp::item<&Ins::double_speed> double_speed;
802 } switches;
803};
804}
Link of score with the OSSIA API execution engine.
Definition CurveConversion.hpp:8
Definition AudioLayers.hpp:14
AfterRecord
Definition score-plugin-fx/Fx/Looper/Transport.hpp:86
void show_control(Field &f, V v)
Sets a control from the audio thread, and shows it in the UI.
Definition Switches.hpp:90
std::string_view mode_label(LoopMode m) noexcept
The name Mode shows a mode by.
Definition Switches.hpp:80
StopAt
When a stop is taken up.
Definition score-plugin-fx/Fx/Looper/Transport.hpp:93
@ Grid
On the next point of the grid, as any change of mode.
AtMaxLayers
What a pass that would make more layers than Max layers does.
Definition score-plugin-fx/Fx/Looper/Transport.hpp:138
@ MergeIntoNewest
The pass is merged into the newest layer once it ends.
constexpr AfterOverdub after_overdub_default
What Rec / Play / Dub does while overdubbing until the setting is changed.
Definition Switches.hpp:77
void show_loop(Field &f, const transport &t, loop_input &l)
Mode shows what is asked for, once the tick has run.
Definition Switches.hpp:145
TransportAction
Definition score-plugin-fx/Fx/Looper/Transport.hpp:109
@ Retrigger
Back to the loop's start, in the same mode.
@ NewLayer
While overdubbing, ends the layer and starts another.
@ PlayStop
Plays a stopped loop, stops anything else.
@ RecPlayDub
Records an empty loop, then plays, overdubs, plays again.
StartFrom
Definition score-plugin-fx/Fx/Looper/Transport.hpp:121
@ WhereItWas
Only a recording does; playing and overdubbing carry straight on.
constexpr halp::grid_setup note_grid
The note values the MIDI looper's notes are pulled to.
Definition Switches.hpp:265
AfterOverdub
What Rec / Play / Dub does while overdubbing.
Definition score-plugin-fx/Fx/Looper/Transport.hpp:101
Definition Switches.hpp:341
Definition Switches.hpp:158
Definition Switches.hpp:297
Definition Switches.hpp:455
Definition Switches.hpp:63
An enumeration shown as a combobox: compact where the choices are many.
Definition Switches.hpp:56
Definition Switches.hpp:427
Definition Switches.hpp:450
Definition Switches.hpp:47
Definition Switches.hpp:512
Definition Switches.hpp:756
Definition Switches.hpp:116
LoopMode last_in
The last value that came in.
Definition Switches.hpp:124
bool arrived
A value came in this tick, whatever it was.
Definition Switches.hpp:118
bool streamed
One came in on the tick before.
Definition Switches.hpp:120
LoopMode left
What the control held at the end of the last tick.
Definition Switches.hpp:122
Definition Switches.hpp:417
Definition Switches.hpp:387
Definition Switches.hpp:412
Definition Switches.hpp:271
static ossia::value upgrade_value(const ossia::value &old)
Definition Switches.hpp:278
Definition Switches.hpp:369
Definition Switches.hpp:377
Definition Switches.hpp:355
Definition Switches.hpp:404
The grid a change of mode waits for. The Quantif of older scores.
Definition Switches.hpp:229
static ossia::value upgrade_value(const ossia::value &old)
Definition Switches.hpp:236
Definition Switches.hpp:315
Definition Switches.hpp:360
Definition Switches.hpp:395
Definition Switches.hpp:445
Definition Switches.hpp:436
The mutes the layers had before a solo, to give them back.
Definition Switches.hpp:461
bool still_soloed(const Engine &e) const noexcept
The layers are muted as the solo left them.
Definition Switches.hpp:472
int count
Passes when the solo was made, -1 when there is none to undo.
Definition Switches.hpp:465
void toggle(Engine &e, int selected)
Solos selected, or unsolos it when it is the layer soloed.
Definition Switches.hpp:484
Definition Switches.hpp:778
Definition Switches.hpp:191
Definition Switches.hpp:329
Definition Switches.hpp:326
Definition Switches.hpp:382
Definition Switches.hpp:706
Definition Switches.hpp:529
int seen_passes
Passes when Layer was last made to follow them.
Definition Switches.hpp:537
void apply(Inputs &in, Engine &e)
On the grid point.
Definition Switches.hpp:615
void follow_merges(Inputs &in, Log &log)
Definition Switches.hpp:691
void merged(Inputs &in, int at)
Definition Switches.hpp:671
void follow(Inputs &in, int passes)
Definition Switches.hpp:649
void read(Inputs &in, transport &t, Engine &e, bool empty)
Definition Switches.hpp:556
void removed(Inputs &in, int pass)
Pass pass went from the layers: the one Layer says keeps its place.
Definition Switches.hpp:660
void inserted(Inputs &in, int pass, int passes)
Definition Switches.hpp:681
Definition score-plugin-fx/Fx/Looper/Transport.hpp:269
void ask(LoopMode m, bool empty) noexcept
Definition score-plugin-fx/Fx/Looper/Transport.hpp:366
bool queued() const noexcept
Changes queued after the one waiting for the grid.
Definition score-plugin-fx/Fx/Looper/Transport.hpp:448
LoopMode wanted
Definition score-plugin-fx/Fx/Looper/Transport.hpp:273
void request_point() noexcept
Definition score-plugin-fx/Fx/Looper/Transport.hpp:445
void press(TransportAction a, bool empty, AfterRecord after_record, AfterOverdub after) noexcept
Definition score-plugin-fx/Fx/Looper/Transport.hpp:394