feat(workspace): open selected track inserts directly (phase 90)

This commit is contained in:
Johannes Findeisen 2026-11-06 02:02:44 +01:00
commit e6cf7023fb
7 changed files with 200 additions and 4 deletions

View file

@ -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

View file

@ -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.

View file

@ -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.

View file

@ -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

View file

@ -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<MainWindow *>(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;i<count;++i) {
xtc_track_info info{};xtc_project_get_track(project_.get(),i,&info);
if(info.id!=track)continue;
if(info.is_bus)return XTC_ERR_UNSUPPORTED;
track_inserts_->select_track(track);tabs_->value(track_inserts_);tabs_->redraw();return XTC_OK;
}
return XTC_ERR_NOT_FOUND;
}

View file

@ -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. */

View file

@ -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<Fl_Menu_Bar *>(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")) {