1
0
Fork 0
forked from hanez/xtc

Phase 11: Complete and verify the minimal music-making workflow

This commit is contained in:
Johannes Findeisen 2026-10-27 03:25:04 +01:00
commit 461689dd44
12 changed files with 463 additions and 25 deletions

View file

@ -21,6 +21,7 @@
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 seek_result = XTC_OK;
xtc_result open_result = XTC_OK, start_result = XTC_OK, stop_result = XTC_OK, close_result = XTC_OK;
xtc_result status_result = XTC_OK, submit_result = XTC_OK;
unsigned int submissions = 0U;
@ -80,7 +81,7 @@ void reset()
{
CHECK(alive == 0U);
open_result = start_result = stop_result = close_result = status_result = XTC_OK;
submit_result = XTC_OK;
submit_result = seek_result = XTC_OK;
engine_status = {};
engine_status.sample_rate = 48000U;
engine_status.buffer_frames = 1024U;
@ -115,7 +116,7 @@ xtc_result xtc_backend_get_status(const xtc_backend *backend, xtc_backend_status
return status_result;
}
xtc_result xtc_backend_seek(xtc_backend *, uint64_t sample)
{ engine_status.sample_position = sample; return handle.running ? XTC_ERR_INVALID_STATE : XTC_OK; }
{ if (handle.running) return XTC_ERR_INVALID_STATE; if (seek_result != XTC_OK) return seek_result; engine_status.sample_position = sample; return XTC_OK; }
xtc_result xtc_backend_submit(xtc_backend *backend, const xtc_graph *graph)
{
CHECK(backend == &handle && graph != nullptr);
@ -167,6 +168,26 @@ int main(int argc, char **argv)
CHECK(contains(&window, "running — modular graph"));
press(stop);
CHECK(stops == 1U && play->active() && !stop->active());
auto *pause = find(&window, "Pause");
auto *home = find(&window, "To start");
CHECK(pause && home && !pause->active() && home->active());
engine_status.sample_position = 48000;
press(play);
CHECK(pause->active());
CHECK(window.pause_playback() == XTC_OK && engine_status.sample_position == 48000);
CHECK(timeline(&window)->position() == 1920 && play->active() && !pause->active());
press(play);
CHECK(engine_status.sample_position == 48000); // Resume does not rewind.
stop_result = XTC_ERR_IO;
CHECK(window.return_to_start() == XTC_ERR_IO && engine_status.sample_position == 48000);
CHECK(!play->active() && stop->active());
stop_result = XTC_OK;
seek_result = XTC_ERR_IO;
CHECK(window.return_to_start() == XTC_ERR_IO && engine_status.sample_position == 48000);
CHECK(play->active() && !stop->active());
seek_result = XTC_OK;
press(home);
CHECK(engine_status.sample_position == 0 && timeline(&window)->position() == 0);
start_result = XTC_ERR_IO;
press(play);
CHECK(contains(&window, "Start engine failed: I/O error"));
@ -277,8 +298,10 @@ int main(int argc, char **argv)
CHECK(window.save_project(filename.c_str()) == XTC_OK);
const xtc_project *retained = sequence->project();
CHECK(window.open_project("/missing/xtc-project") == XTC_ERR_IO && sequence->project() == retained);
press(play);
submit_result = XTC_ERR_CAPACITY;
CHECK(window.open_project(filename.c_str()) == XTC_ERR_CAPACITY && sequence->project() == retained);
CHECK(play->active() && !stop->active()); // Failed install refreshed stopped state.
submit_result = XTC_OK;
press(find(&window, "Delete region/track"));
CHECK(window.open_project(filename.c_str()) == XTC_OK);
@ -292,6 +315,10 @@ int main(int argc, char **argv)
CHECK(window.record_audio(take.c_str()) == XTC_OK && handle.recorder != nullptr);
CHECK(canvas->add_node(XTC_NODE_GAIN) == XTC_ERR_INVALID_STATE);
CHECK(window.save_project(filename.c_str()) == XTC_ERR_INVALID_STATE);
CHECK(!pause->active() && !home->active());
CHECK(window.pause_playback() == XTC_ERR_INVALID_STATE);
CHECK(window.return_to_start() == XTC_ERR_INVALID_STATE);
CHECK(window.new_project() == XTC_ERR_INVALID_STATE);
window.do_callback();
CHECK(window.shown() && contains(&window, "Stop recording before closing"));
float recorded[64]; for (float &value : recorded) value = 0.25f;