From e6cf7023fb796ab5e615bd585b1f24306e5722eb Mon Sep 17 00:00:00 2001 From: hanez Date: Fri, 6 Nov 2026 02:02:44 +0100 Subject: [PATCH] feat(workspace): open selected track inserts directly (phase 90) --- README.md | 4 +- docs/CREATIVE_WORKFLOWS.md | 12 +++ docs/ROADMAP.md | 150 +++++++++++++++++++++++++++++++++ docs/TRACK_INSERTS.md | 2 +- src/gui/main_window.cpp | 20 ++++- src/gui/main_window.hpp | 1 + tests/integration/test_gui.cpp | 15 ++++ 7 files changed, 200 insertions(+), 4 deletions(-) create mode 100644 docs/CREATIVE_WORKFLOWS.md diff --git a/README.md b/README.md index 0ce21d7..2961e22 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ Import WAV (Ctrl+I) creates playable clips; Add region creates silent placeholde Record captures JACK input to a chosen WAV; Stop finalizes and adds the take. Save the project after recording. External asset paths must remain available; select a missing clip and use File/Relink selected audio to repair it. -Add MIDI clip on an existing track, then open Piano roll (Ctrl+4) to draw notes. +Add MIDI clip on an existing track, then open Piano roll (or Ctrl+5 for the selected track) to draw notes. Connect a MIDI source to the JACK `midi_in` port for live playing; Panic/F9 silences held notes. See [MIDI workflow and limits](docs/MIDI.md). See [audio workflow and limits](docs/AUDIO_FILES.md) and the @@ -173,7 +173,7 @@ full contract and test/qualification limits. Phases 80–89 add a compact sequencer Create menu, optional track inspector and -per-track modular effect chains. Open **View → Track inserts** (Ctrl+4) to add, +per-track modular effect chains. Open **View → Track inserts** (or Ctrl+5 for the selected track) to add, search, reorder, bypass, inspect and mix mono LADSPA/VST2/VST3/CLAP effects or internal devices. Chains support undo, presets, audio/MIDI rendering and export. Projects save format 17 and read formats 1–17. See diff --git a/docs/CREATIVE_WORKFLOWS.md b/docs/CREATIVE_WORKFLOWS.md new file mode 100644 index 0000000..331b1d1 --- /dev/null +++ b/docs/CREATIVE_WORKFLOWS.md @@ -0,0 +1,12 @@ +# Creative workflow additions (Phases 90–99) + +These features prioritize fast musical experiments and retain the existing +control-thread preparation and project undo model. They introduce no dependency +or project-format change. Each phase is qualified separately in ROADMAP.md. + +## Selected track inserts + +**Track → Show selected track inserts** (Ctrl+5) opens the sequencer or active +mixer selection directly. Bus inserts are unsupported; no selection leaves the +workspace unchanged. **View → Track inserts** still opens the rack independently. +Ctrl+4 remains the piano-roll command, resolving the earlier shortcut collision. diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 84909ba..f5ccb10 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -2052,6 +2052,156 @@ DAWs are not claimed. See TRACK_INSERTS.md and KNOWN_LIMITATIONS.md. --- +## Phase 90 — Selected Track Effect Access + +### Goal +Open the sequencer or mixer selection directly in Track inserts with a dedicated shortcut, preserving the piano-roll shortcut and rejecting bus/no selection. + +### Tasks and acceptance criteria +- [x] Implement the workflow with bounded validation, safe preparation and documented limits. +- [x] Pass meaningful core and/or GUI checks, including error and undo behavior. +- [x] Document results and commit this phase separately. + +### Implementation status +Implemented: selected sequencer/mixer track opens directly in the insert workspace with Ctrl+5; the original piano-roll Ctrl+4 is preserved. Invalid/no track leaves the view unchanged and buses reject. Baseline core suite, warning-enabled GUI build and focused selection/context/shortcut tests passed. + +--- + +## Phase 91 — Duplicate Effect Slots + +### Goal +Duplicate an effect adjacent to its slot with copied parameters, automation, wet amount and bypass; prepare transactionally, enforce the eight-slot limit and support undo. + +### Tasks and acceptance criteria +- [ ] Implement the workflow with bounded validation, safe preparation and documented limits. +- [ ] Pass meaningful core and/or GUI checks, including error and undo behavior. +- [ ] Document results and commit this phase separately. + +### Implementation status +Planned. + +--- + +## Phase 92 — Track Chain Clipboard + +### Goal +Copy and paste independent chain metadata between tracks, with explicit replacement, undo and document-lifecycle cleanup. Clipboard operations must not load modules. + +### Tasks and acceptance criteria +- [ ] Implement the workflow with bounded validation, safe preparation and documented limits. +- [ ] Pass meaningful core and/or GUI checks, including error and undo behavior. +- [ ] Document results and commit this phase separately. + +### Implementation status +Planned. + +--- + +## Phase 93 — Effect Chain A/B Comparison + +### Goal +Capture and recall two track-bound effect configurations, with clear readiness indicators, safe preparation, undo and cleanup on document replacement. + +### Tasks and acceptance criteria +- [ ] Implement the workflow with bounded validation, safe preparation and documented limits. +- [ ] Pass meaningful core and/or GUI checks, including error and undo behavior. +- [ ] Document results and commit this phase separately. + +### Implementation status +Planned. + +--- + +## Phase 94 — Creative Chain Templates + +### Goal +Offer original dependency-free Slapback, Dub Echo and Ambient Space starting points using internal devices, including safe replacement and editable controls. + +### Tasks and acceptance criteria +- [ ] Implement the workflow with bounded validation, safe preparation and documented limits. +- [ ] Pass meaningful core and/or GUI checks, including error and undo behavior. +- [ ] Document results and commit this phase separately. + +### Implementation status +Planned. + +--- + +## Phase 95 — Bulk Rack Actions + +### Goal +Enable all inserts, bypass all inserts or clear a chain as single undoable prepared edits, retaining output gain and respecting recording/error restrictions. + +### Tasks and acceptance criteria +- [ ] Implement the workflow with bounded validation, safe preparation and documented limits. +- [ ] Pass meaningful core and/or GUI checks, including error and undo behavior. +- [ ] Document results and commit this phase separately. + +### Implementation status +Planned. + +--- + +## Phase 96 — Live Meters in the Insert Workspace + +### Goal +Display selected-track stereo sample peaks and a resettable clip indicator from the existing single backend meter reader, with clear post-fader labeling and offline/stopped handling. + +### Tasks and acceptance criteria +- [ ] Implement the workflow with bounded validation, safe preparation and documented limits. +- [ ] Pass meaningful core and/or GUI checks, including error and undo behavior. +- [ ] Document results and commit this phase separately. + +### Implementation status +Planned. + +--- + +## Phase 97 — Tap Tempo + +### Goal +Provide a transport Tap button backed by a bounded C99 rolling interval estimator, with timeout/reset, sensible tempo limits and undoable project tempo adoption. + +### Tasks and acceptance criteria +- [ ] Implement the workflow with bounded validation, safe preparation and documented limits. +- [ ] Pass meaningful core and/or GUI checks, including error and undo behavior. +- [ ] Document results and commit this phase separately. + +### Implementation status +Planned. + +--- + +## Phase 98 — One-Action Audio Crossfades + +### Goal +Apply matching linear boundary fades to two partially overlapping audio clips on one track, preserving source files and opposite fades. Reject ambiguous layouts transactionally and provide one undo step. + +### Tasks and acceptance criteria +- [ ] Implement the workflow with bounded validation, safe preparation and documented limits. +- [ ] Pass meaningful core and/or GUI checks, including error and undo behavior. +- [ ] Document results and commit this phase separately. + +### Implementation status +Planned. + +--- + +## Phase 99 — MIDI Chord Strumming + +### Goal +Spread simultaneous chord notes in pitch order with a user-selected tick spacing and direction, preserving original ends and rejecting source overflow atomically. Expose a musical editing command with undo. + +### Tasks and acceptance criteria +- [ ] Implement the workflow with bounded validation, safe preparation and documented limits. +- [ ] Pass meaningful core and/or GUI checks, including error and undo behavior. +- [ ] Document results and commit this phase separately. + +### Implementation status +Planned. + +--- + ## Recommended Execution Order Reorder the phases when the audit reveals a blocking dependency. Do not mark a phase complete merely because code exists: its acceptance criteria must be demonstrated by builds, tests, or documented manual verification. diff --git a/docs/TRACK_INSERTS.md b/docs/TRACK_INSERTS.md index 1d0e75b..2a9852f 100644 --- a/docs/TRACK_INSERTS.md +++ b/docs/TRACK_INSERTS.md @@ -28,7 +28,7 @@ plugin state on seeks follows the existing host contract. Bus inserts and tracks containing both audio assets and MIDI reject preparation explicitly. Live unassigned sine monitoring remains a separate master input. -Open **View → Track inserts** (Ctrl+4) and choose a track. **Add effect** offers +Open **View → Track inserts** (or Ctrl+5 for the selected track) and choose a track. **Add effect** offers internal Delay/Reverb and the plugin library. The left rack shows signal order; the graph displays the actual generated graph compiled by playback. Wiring in this view is read-only: edit the rack to preserve the serial chain. The global diff --git a/src/gui/main_window.cpp b/src/gui/main_window.cpp index 0d83e4c..459e9b2 100644 --- a/src/gui/main_window.cpp +++ b/src/gui/main_window.cpp @@ -500,7 +500,8 @@ MainWindow::MainWindow(bool prompt_unsaved,const char *configuration) track_inserts_=new TrackInsertsPanel(216,158,1056,546,this); tabs_->end(); tabs_->value(sequencer); - menu->add("View/Track inserts",FL_CTRL+'4',view_callback,track_inserts_); + menu->add("View/Track inserts",0,view_callback,track_inserts_); + menu->add("Track/Show selected track inserts",FL_CTRL+'5',[](Fl_Widget *,void *c){auto *w=static_cast(c);auto r=w->open_track_inserts();if(r!=XTC_OK)w->report_error("Select an audio or MIDI track to open inserts",r);},this); menu->add("View/Sequencer", FL_CTRL + '1', view_callback, sequencer); menu->add("View/Mixer", FL_CTRL + '2', view_callback, mixer); menu->add("View/Modular Graph", FL_CTRL + '3', view_callback, graph); @@ -2728,3 +2729,20 @@ xtc_result MainWindow::add_track_effect(uint64_t track,const char *file,unsigned slot.enabled=1;slot.wet=1;chain.slots[chain.count++]=slot; return set_track_chain(track,chain); } + +xtc_result MainWindow::open_track_inserts(uint64_t track) +{ + if(track==UINT64_MAX) { + bool mixer_context=tabs_->value()==mixer_page_ || + (mixer_detached_ && Fl::focus() && Fl::focus()->window()==mixer_window_.get()); + track=mixer_context ? mixer_->selected_track() : sequencer_->selected_track(); + } + size_t count=0,clips=0;xtc_project_get_counts(project_.get(),&count,&clips); + for(size_t i=0;iselect_track(track);tabs_->value(track_inserts_);tabs_->redraw();return XTC_OK; + } + return XTC_ERR_NOT_FOUND; +} diff --git a/src/gui/main_window.hpp b/src/gui/main_window.hpp index 5f1815c..da420f5 100644 --- a/src/gui/main_window.hpp +++ b/src/gui/main_window.hpp @@ -36,6 +36,7 @@ class MainWindow : public Fl_Double_Window { xtc_result add_track_effect(uint64_t track,const char *file,unsigned int index); TrackInsertsPanel *track_inserts() const {return track_inserts_;} void show_track_inspector(bool visible); + xtc_result open_track_inserts(uint64_t track=UINT64_MAX); /* One undoable candidate edit. MIDI also adds a one-bar clip at the cursor. * Preparation stops/resets transport; recording and failed candidates retain * the current document. No engine/model changes happen in audio callbacks. */ diff --git a/tests/integration/test_gui.cpp b/tests/integration/test_gui.cpp index 7eedfb6..4f1f28e 100644 --- a/tests/integration/test_gui.cpp +++ b/tests/integration/test_gui.cpp @@ -216,6 +216,20 @@ static int sample_editor_tests() CHECK(window.undo()==XTC_OK);CHECK(xtc_project_get_counts(s->project(),&tracks,&clips)==XTC_OK && clips==1); window.do_callback();std::puts("Sample editor GUI selection/processing/adoption/slicing/undo passed.");return failures ? 1 : 0; } +int creative_workflow_tests() +{ + reset();MainWindow window(false,"");window.show();pump();auto *s=timeline(&window);auto *panel=window.track_inserts(); + CHECK(window.open_track_inserts()==XTC_ERR_NOT_FOUND); + CHECK(window.create_track(false)==XTC_OK);auto first_track=s->selected_track(); + CHECK(window.create_track(false)==XTC_OK);auto second_track=s->selected_track(); + CHECK(window.open_track_inserts()==XTC_OK && panel->selected_track()==second_track); + auto *bar=dynamic_cast(window.child(0));CHECK(bar); + CHECK(bar->find_item("Track/Show selected track inserts")->shortcut()==FL_CTRL+'5'); + CHECK(bar->find_item("View/Piano roll")->shortcut()==FL_CTRL+'4'); + window.mixer()->select_track(first_track);bar->picked(bar->find_item("View/Mixer")); + CHECK(window.open_track_inserts()==XTC_OK && panel->selected_track()==first_track); + window.do_callback();puts("Creative workflow GUI checks passed.");return failures ? 1 : 0; +} int track_insert_tests() { CHECK(xtc_plugin_file_matches("/usr/lib/vst3/ZamEQ2.vst3/Contents/x86_64-linux/ZamEQ2.so","zameq",3)); @@ -281,6 +295,7 @@ int track_insert_tests() } int main(int argc, char **argv) { + if(std::getenv("XTC_TEST_CREATIVE_ONLY"))return creative_workflow_tests(); if(std::getenv("XTC_TEST_TRACK_FX_ONLY"))return track_insert_tests(); if(std::getenv("XTC_TEST_SAMPLE_EDITOR_ONLY"))return sample_editor_tests(); if(!std::getenv("XTC_TEST_MODERN_EDITING_ONLY")) {