Phase 7: Add MIDI clips, instrument and piano roll
This commit is contained in:
parent
8a37090b81
commit
cacc086805
38 changed files with 1373 additions and 74 deletions
|
|
@ -1,6 +1,7 @@
|
|||
#include "../../src/gui/main_window.hpp"
|
||||
#include "../../src/gui/graph_widget.hpp"
|
||||
#include "../../src/gui/sequencer_widget.hpp"
|
||||
#include "../../src/gui/piano_roll.hpp"
|
||||
#include <unistd.h>
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/Fl_Box.H>
|
||||
|
|
@ -16,7 +17,7 @@
|
|||
|
||||
/* Fake only the public C backend boundary. Real FLTK widgets, callbacks and
|
||||
* timers run under Xvfb; no server/device is required or touched. */
|
||||
struct xtc_backend { int running = 0; xtc_plan *plan = nullptr; xtc_audio_plan *audio = nullptr; xtc_recorder *recorder = nullptr; };
|
||||
struct xtc_backend { int running = 0; xtc_plan *plan = nullptr; xtc_audio_plan *audio = nullptr; xtc_midi_plan *midi = nullptr; xtc_recorder *recorder = nullptr; };
|
||||
namespace {
|
||||
xtc_backend handle;
|
||||
xtc_result open_result = XTC_OK, start_result = XTC_OK, stop_result = XTC_OK, close_result = XTC_OK;
|
||||
|
|
@ -59,7 +60,7 @@ SequencerWidget *timeline(Fl_Group *group)
|
|||
}
|
||||
return nullptr;
|
||||
}
|
||||
void gesture(SequencerWidget *s, int left, int top, int dx, int dy)
|
||||
void gesture(Fl_Widget *s, int left, int top, int dx, int dy)
|
||||
{
|
||||
int old_x = Fl::e_x, old_y = Fl::e_y, old_key = Fl::e_keysym;
|
||||
Fl::e_x = s->x() + left; Fl::e_y = s->y() + top; Fl::e_keysym = FL_Button + FL_LEFT_MOUSE;
|
||||
|
|
@ -98,7 +99,7 @@ xtc_result xtc_backend_close(xtc_backend *backend)
|
|||
{
|
||||
if (backend == nullptr) return XTC_OK;
|
||||
++closes;
|
||||
if (close_result == XTC_OK) { CHECK(alive == 1U); --alive; handle.running = 0; xtc_plan_destroy(handle.plan); handle.plan = nullptr; xtc_audio_plan_destroy(handle.audio); handle.audio = nullptr; }
|
||||
if (close_result == XTC_OK) { CHECK(alive == 1U); --alive; handle.running = 0; xtc_plan_destroy(handle.plan); handle.plan = nullptr; xtc_audio_plan_destroy(handle.audio); handle.audio = nullptr; xtc_midi_plan_destroy(handle.midi); handle.midi = nullptr; }
|
||||
return close_result;
|
||||
}
|
||||
xtc_result xtc_backend_start(xtc_backend *backend)
|
||||
|
|
@ -126,13 +127,17 @@ xtc_result xtc_backend_submit(xtc_backend *backend, const xtc_graph *graph)
|
|||
++engine_status.submitted_revision;
|
||||
return XTC_OK;
|
||||
}
|
||||
xtc_result xtc_backend_panic(xtc_backend *) { xtc_midi_plan_panic(handle.midi, engine_status.sample_position); return XTC_OK; }
|
||||
xtc_result xtc_backend_prepare_project(xtc_backend *backend, const xtc_project *project)
|
||||
{
|
||||
xtc_audio_plan *plan = nullptr;
|
||||
xtc_midi_plan *midi = nullptr;
|
||||
xtc_result r = xtc_audio_plan_create(project, 48000, &plan);
|
||||
if (r == XTC_OK) r = xtc_midi_plan_create(project, 48000, &midi);
|
||||
if (r == XTC_OK) r = xtc_backend_submit(backend, xtc_project_graph(project));
|
||||
if (r != XTC_OK) { xtc_audio_plan_destroy(plan); return r; }
|
||||
if (r != XTC_OK) { xtc_audio_plan_destroy(plan); xtc_midi_plan_destroy(midi); return r; }
|
||||
xtc_audio_plan_destroy(handle.audio); handle.audio = plan;
|
||||
xtc_midi_plan_destroy(handle.midi); handle.midi = midi;
|
||||
engine_status.asset_issues = static_cast<unsigned int>(xtc_audio_plan_issues(plan, nullptr));
|
||||
return XTC_OK;
|
||||
}
|
||||
|
|
@ -300,6 +305,29 @@ int main(int argc, char **argv)
|
|||
CHECK(unlink(take.c_str()) == 0);
|
||||
CHECK(window.open_project(filename.c_str()) == XTC_OK && contains(&window, "Missing/unreadable audio"));
|
||||
CHECK(window.import_audio("/missing/xtc-audio.wav") == XTC_ERR_IO);
|
||||
press(find(&window, "Add MIDI clip"));
|
||||
CHECK(window.open_piano_roll() == XTC_OK);
|
||||
auto *roll = window.piano_roll(); CHECK(roll != nullptr);
|
||||
int saved_x = Fl::e_x, saved_y = Fl::e_y, saved_key = Fl::e_keysym;
|
||||
Fl::e_x = roll->x() + 112; Fl::e_y = roll->y() + 1110; Fl::e_keysym = FL_Button + FL_LEFT_MOUSE;
|
||||
CHECK(roll->handle(FL_PUSH) == 1); (void)roll->handle(FL_RELEASE);
|
||||
Fl::e_x = saved_x; Fl::e_y = saved_y; Fl::e_keysym = saved_key;
|
||||
gesture(roll, 130, 1110, 24, -16); // Move one sixteenth and a semitone.
|
||||
gesture(roll, 230, 1094, 48, 0); // Extend right edge by half a beat.
|
||||
xtc_note_info drawn{}; size_t note_count;
|
||||
CHECK(xtc_project_note_count(sequence->project(), ¬e_count) == XTC_OK && note_count == 1);
|
||||
CHECK(xtc_project_get_note(sequence->project(), 0, &drawn) == XTC_OK &&
|
||||
drawn.start_tick == 720 && drawn.length_tick == 1440 && drawn.pitch == 61);
|
||||
CHECK(window.save_project(filename.c_str()) == XTC_OK);
|
||||
CHECK(window.open_project(filename.c_str()) == XTC_OK);
|
||||
CHECK(xtc_project_get_note(sequence->project(), 0, &drawn) == XTC_OK && drawn.pitch == 61 && drawn.start_tick == 720);
|
||||
float instrument[32], heard[32];
|
||||
CHECK(xtc_midi_plan_render(handle.midi, 18000, nullptr, 0, instrument, 32) == XTC_OK && instrument[1] > 0);
|
||||
CHECK(xtc_plan_process_sources(handle.plan, nullptr, nullptr, instrument, heard, 32) == XTC_OK && heard[1] == instrument[1]);
|
||||
engine_status.sample_position = 18032;
|
||||
press(find(&window, "Panic"));
|
||||
CHECK(xtc_midi_plan_render(handle.midi, 18032, nullptr, 0, instrument, 32) == XTC_OK && instrument[0] == 0);
|
||||
engine_status.sample_position = 0;
|
||||
CHECK(unlink(filename.c_str()) == 0 && rmdir(directory) == 0);
|
||||
engine_status.xruns = 3U;
|
||||
engine_status.processed_blocks = 123U;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue