docs: refresh all screenshots and illustrate phase 58–68 workflows
10
Makefile
|
|
@ -554,3 +554,13 @@ test-next-daw: $(BUILD_DIR)/test_next_daw
|
|||
test: test-next-daw
|
||||
test-gui-next-daw: $(BUILD_DIR)/test_gui
|
||||
XTC_TEST_MODERN_EDITING_ONLY=1 XTC_TEST_NEXT_DAW_ONLY=1 xvfb-run -a -s "-screen 0 1280x800x24" ./$(BUILD_DIR)/test_gui
|
||||
|
||||
# Optional documentation capture; requires Xvfb, ImageMagick import and xdotool.
|
||||
$(BUILD_DIR)/capture_screenshots: $(BUILD_DIR)/tools/capture_screenshots.o $(BUILD_DIR)/src/gui/main_window.o $(BUILD_DIR)/src/gui/graph_widget.o $(BUILD_DIR)/src/gui/sequencer_widget.o $(BUILD_DIR)/src/gui/piano_roll.o $(BUILD_DIR)/src/gui/mixer_widget.o $(BUILD_DIR)/src/gui/plugin_dialog.o $(BUILD_DIR)/libxtc.a
|
||||
$(CXX) $(LDFLAGS) -o $@ $^ $(FLTK_LIBS) $(JACK_LIBS) -lm -ldl
|
||||
|
||||
.PHONY: screenshots
|
||||
screenshots: $(BUILD_DIR)/capture_screenshots $(BUILD_DIR)/plugin-fixture.so $(BUILD_DIR)/clap-synth-fixture.clap $(BUILD_DIR)/vst2-synth-fixture.so $(BUILD_DIR)/vst3-synth-fixture.so
|
||||
xvfb-run -a -s "-screen 0 1440x960x24" ./$(BUILD_DIR)/capture_screenshots "$(CURDIR)/screenshots"
|
||||
|
||||
-include $(BUILD_DIR)/tools/capture_screenshots.d
|
||||
|
|
|
|||
|
|
@ -1673,6 +1673,12 @@ add no dependencies or callback I/O/allocation. See
|
|||
behavior. Human listening, physical hardware, arbitrary third-party plugins and
|
||||
feature parity with commercial DAWs remain unqualified.
|
||||
|
||||
All application screenshots were refreshed after Phase 68. The
|
||||
[screenshot gallery](../screenshots/README.md) includes controls and results for
|
||||
every phase from 58 through 68, plus refreshed existing views and detached
|
||||
editors. The optional `make screenshots` target reproduces the captures using
|
||||
real FLTK widgets and isolated demonstration data.
|
||||
|
||||
---
|
||||
|
||||
## Recommended Execution Order
|
||||
|
|
|
|||
|
|
@ -1,24 +1,49 @@
|
|||
# xtc screenshots
|
||||
|
||||
Captured from the Phase 38 FLTK application on 2026-10-28, with Phase 39
|
||||
transport, mixer, arrangement and command captures refreshed on 2026-10-30 using
|
||||
a virtual X11 screen. Images show actual rendered widgets, without mockups or image edits.
|
||||
All captures refreshed from the Phase 68 FLTK application on 2026-11-06.
|
||||
These are actual rendered application windows and menus on a 1440 × 960 virtual
|
||||
X11 screen, without mockups, compositing or image edits.
|
||||
|
||||

|
||||

|
||||
|
||||
Internal instrument dropdowns show Soft Keys and Sub Bass; internal delay and
|
||||
reverb captures show the actual editable effect controls.
|
||||
The temporary demonstration project starts from
|
||||
`examples/projects/modern-session.xtc`, adding Intro/Verse/Chorus/Outro markers,
|
||||
a routed music bus and gain automation. Editing results use the real control
|
||||
APIs and GUI history/preparation paths. Original projects, media and user
|
||||
configuration are not overwritten. Black margins are the virtual desktop;
|
||||
floating views show the actual detached windows together.
|
||||
|
||||
The arrangement uses `examples/projects/modern-session.xtc`. Mixer captures add
|
||||
a bus, routing, pan/level settings and automation. The playing view shows actual
|
||||
JACK callback meters; additional captures show the minimum 1220 × 720 layout and
|
||||
a larger session scrolled to its final channels, with the master monitor pinned.
|
||||
The audio view adds a temporary generated waveform. Plugin views use the
|
||||
repository's LADSPA, CLAP, VST2 and VST3 test fixtures; these are demonstration
|
||||
plugins, not commercial instruments. Preferences show application defaults and
|
||||
the staged loop. The command palette shows the available application actions.
|
||||
The workspace now includes direct BPM editing, a live track inspector and
|
||||
arrangement navigation. No user configuration or example project was overwritten.
|
||||
## New arrangement and composition workflows
|
||||
|
||||
| Phase | Feature | Captures |
|
||||
| --- | --- | --- |
|
||||
| 58 | Persistent named arrangement markers | [Ruler](arrangement-markers.png), [marker editor](marker-edit.png) |
|
||||
| 59 | Section navigation and looping | [Current section loop](section-navigation.png) |
|
||||
| 60 | Ripple time insertion/removal | [Controls](ripple-time.png), [inserted gap](ripple-result.png) |
|
||||
| 61 | Complete track duplication | [Independent layered track](track-duplication.png) |
|
||||
| 62 | Nondestructive MIDI splitting | [Split clip](midi-split.png) |
|
||||
| 63 | MIDI clip consolidation | [Consolidated clip](midi-consolidation.png) |
|
||||
| 64 | Seeded MIDI humanization | [Timing, velocity and seed](midi-humanize.png) |
|
||||
| 65 | Chord construction | [Intervals](midi-chord-builder.png), [generated notes](midi-chords-result.png) |
|
||||
| 66 | Offline arpeggio generation | [Step, gate and direction](midi-arpeggio.png), [written pattern](midi-arpeggio-result.png) |
|
||||
| 67 | Audio peak normalization | [Target dBFS](audio-normalization.png), [normalized clip](audio-normalization-result.png) |
|
||||
| 68 | Portable media collection | [New destination folder](project-collection.png) |
|
||||
|
||||
Collection is also executed by the capture tool into its temporary directory;
|
||||
the screenshot shows its destination prompt, not a file browser or progress UI.
|
||||
See [COMPOSITION_WORKFLOWS.md](../docs/COMPOSITION_WORKFLOWS.md) for precise
|
||||
behavior, limits and commands. The screenshots illustrate implemented workflows;
|
||||
they do not establish feature parity with other DAWs.
|
||||
|
||||
## Refreshed application views
|
||||
|
||||
All pre-existing images below were recaptured. Mixer playback meters come from
|
||||
real JACK callbacks. The minimum-size capture uses a 1220 × 720 main window;
|
||||
the scrolled view adds twelve tracks. Audio views import the repository's
|
||||
`original-pluck.wav` and apply clip gain/fades. Plugin views use repository test
|
||||
fixtures, not commercial plugins. Internal instrument menus and delay/reverb
|
||||
editors show the real available devices and controls. The command palette uses
|
||||
the current application action list.
|
||||
|
||||
- [Sequencer loop](sequencer-loop.png)
|
||||
- [Mixer automation](mixer-automation.png)
|
||||
|
|
@ -55,5 +80,25 @@ arrangement navigation. No user configuration or example project was overwritten
|
|||
- [Detached mixer](mixer-detached.png)
|
||||
- [Workspace with transport and mixer detached](workspace-detached.png)
|
||||
|
||||
|
||||
- [Detached sequencer](sequencer-detached.png)
|
||||
- [Detached modular graph](graph-detached.png)
|
||||
|
||||
Detach panels from the View menu; close a floating window or use its Dock button
|
||||
to return it to the main window. The main arrangement uses the freed toolbar space.
|
||||
to return it to the main window.
|
||||
|
||||
## Reproduce the gallery
|
||||
|
||||
From the repository root, run:
|
||||
|
||||
```sh
|
||||
make BUILD_DIR=build/next-daw screenshots
|
||||
```
|
||||
|
||||
This optional documentation target requires the existing FLTK/JACK build
|
||||
prerequisites, a running JACK server, Xvfb (`xvfb-run`), ImageMagick (`import`) and
|
||||
`xdotool`. It builds the repository plugin fixtures, runs
|
||||
[the capture tool](../tools/capture_screenshots.cpp), and replaces the gallery
|
||||
PNGs. All demonstration edits and collection outputs use an automatically removed
|
||||
temporary directory; no preferences are saved. It neither installs dependencies
|
||||
nor starts/reconfigures the audio server.
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 84 KiB |
BIN
screenshots/arrangement-markers.png
Normal file
|
After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 87 KiB |
BIN
screenshots/audio-normalization-result.png
Normal file
|
After Width: | Height: | Size: 81 KiB |
BIN
screenshots/audio-normalization.png
Normal file
|
After Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 77 KiB |
BIN
screenshots/graph-detached.png
Normal file
|
After Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 87 KiB |
BIN
screenshots/marker-edit.png
Normal file
|
After Width: | Height: | Size: 85 KiB |
BIN
screenshots/midi-arpeggio-result.png
Normal file
|
After Width: | Height: | Size: 63 KiB |
BIN
screenshots/midi-arpeggio.png
Normal file
|
After Width: | Height: | Size: 82 KiB |
BIN
screenshots/midi-chord-builder.png
Normal file
|
After Width: | Height: | Size: 81 KiB |
BIN
screenshots/midi-chords-result.png
Normal file
|
After Width: | Height: | Size: 63 KiB |
BIN
screenshots/midi-consolidation.png
Normal file
|
After Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 116 KiB |
BIN
screenshots/midi-humanize.png
Normal file
|
After Width: | Height: | Size: 83 KiB |
BIN
screenshots/midi-split.png
Normal file
|
After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 85 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 2.2 MiB After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 54 KiB |
BIN
screenshots/project-collection.png
Normal file
|
After Width: | Height: | Size: 86 KiB |
BIN
screenshots/ripple-result.png
Normal file
|
After Width: | Height: | Size: 78 KiB |
BIN
screenshots/ripple-time.png
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
screenshots/section-navigation.png
Normal file
|
After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 81 KiB |
BIN
screenshots/sequencer-detached.png
Normal file
|
After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 78 KiB |
BIN
screenshots/track-duplication.png
Normal file
|
After Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 71 KiB |
|
|
@ -1207,7 +1207,7 @@ void MainWindow::view_callback(Fl_Widget *widget, void *view)
|
|||
*/
|
||||
void MainWindow::about_callback(Fl_Widget *, void *)
|
||||
{
|
||||
fl_message("%s %s\nModular audio workstation\nPhase 12: timing, transitions and audio quality.",
|
||||
fl_message("%s %s\nModular audio workstation\nArrangement markers, MIDI composition, audio editing and modular mixing.",
|
||||
XTC_PROJECT_NAME, XTC_VERSION_STRING);
|
||||
}
|
||||
|
||||
|
|
|
|||
96
tools/capture_screenshots.cpp
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
/* Optional documentation tool: real FLTK widgets and real backend, isolated data. */
|
||||
#include "../src/gui/main_window.hpp"
|
||||
#include "../src/gui/sequencer_widget.hpp"
|
||||
#include "../src/gui/mixer_widget.hpp"
|
||||
#include "../src/gui/piano_roll.hpp"
|
||||
#include "../src/gui/plugin_dialog.hpp"
|
||||
#include "../src/gui/plugin_library.hpp"
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/Fl_Tabs.H>
|
||||
#include <FL/Fl_Menu_Bar.H>
|
||||
#include <FL/Fl_Button.H>
|
||||
#include <FL/Fl_Choice.H>
|
||||
#include <FL/Fl_Scroll.H>
|
||||
#include <FL/x.H>
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <stdexcept>
|
||||
#include <functional>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace {
|
||||
MainWindow *main_window;
|
||||
std::string destination;
|
||||
void check(xtc_result r) {if(r!=XTC_OK)throw std::runtime_error(xtc_result_string(r));}
|
||||
void pump() {auto end=std::chrono::steady_clock::now()+std::chrono::milliseconds(180);while(std::chrono::steady_clock::now()<end)Fl::wait(.01);}
|
||||
template<class T> T *first(Fl_Group &g) {for(int i=0;i<g.children();++i){auto *c=g.child(i);if(auto *t=dynamic_cast<T *>(c))return t;if(auto *n=dynamic_cast<Fl_Group *>(c))if(auto *t=first<T>(*n))return t;}return nullptr;}
|
||||
Fl_Widget *named(Fl_Group &g,const char *label) {for(int i=0;i<g.children();++i){auto *c=g.child(i);if(c->label()&&!strcmp(c->label(),label))return c;if(auto *n=dynamic_cast<Fl_Group *>(c))if(auto *w=named(*n,label))return w;}return nullptr;}
|
||||
void tab(const char *label) {auto *page=named(*main_window,label);if(!page)throw std::runtime_error(label);auto *tabs=dynamic_cast<Fl_Tabs *>(page->parent());if(!tabs)throw std::runtime_error("Tab parent");tabs->value(page);tabs->redraw();pump();}
|
||||
void capture(const char *name) {Fl::flush();pump();std::string command="import -window root '"+destination+"/"+name+".png'";if(system(command.c_str()))throw std::runtime_error("ImageMagick capture failed");std::printf("Captured %s\n",name);std::fflush(stdout);}
|
||||
struct Modal {const char *name;const char *page;};
|
||||
void modal_capture(void *data) {auto *job=static_cast<Modal *>(data);auto *w=Fl::modal();if(!w||w==main_window)throw std::runtime_error("Expected a modal dialog");if(job->page){auto *tabs=first<Fl_Tabs>(*w);auto *page=named(*w,job->page);if(!tabs||!page)throw std::runtime_error(job->page);tabs->value(page);tabs->redraw();}capture(job->name);auto *cancel=named(*w,"Cancel");if(!cancel)cancel=named(*w,"Close");if(!cancel)cancel=named(*w,"OK");if(cancel)cancel->do_callback();else w->do_callback();}
|
||||
void dialog(const char *name,std::function<void()> action,const char *page=nullptr) {Modal job{name,page};Fl::add_timeout(.3,modal_capture,&job);action();Fl::remove_timeout(modal_capture,&job);pump();}
|
||||
void menu(const char *path) {auto *bar=first<Fl_Menu_Bar>(*main_window);const auto *item=bar->find_item(path);if(!item)throw std::runtime_error(path);bar->picked(item);}
|
||||
void piano_view() {
|
||||
check(main_window->open_piano_roll());
|
||||
auto *piano=main_window->piano_roll();
|
||||
if(auto *scroll=dynamic_cast<Fl_Scroll *>(piano->parent()))scroll->scroll_to(0,50*16);
|
||||
size_t count=0;check(xtc_project_note_count(piano->project(),&count));
|
||||
for(size_t i=0;i<count;++i){xtc_note_info note{};check(xtc_project_get_note(piano->project(),i,¬e));if(note.clip_id==piano->clip()){piano->select_note(note.id);break;}}
|
||||
piano->redraw();pump();
|
||||
}
|
||||
void button(const char *name) {auto *b=named(*main_window,name);if(!b)throw std::runtime_error(name);b->do_callback();pump();}
|
||||
}
|
||||
int main(int argc,char **argv) {
|
||||
if(argc!=2){std::fprintf(stderr,"Usage: capture_screenshots OUTPUT_DIRECTORY (absolute, no apostrophes)\n");return 1;}
|
||||
destination=argv[1];if(destination.empty()||destination[0]!='/'||destination.find('\'')!=std::string::npos)return 1;
|
||||
try {
|
||||
std::filesystem::create_directories(destination);
|
||||
char temp[]="/tmp/xtc-screenshots-XXXXXX";if(!mkdtemp(temp))return 1;std::string root=temp;
|
||||
struct Cleanup {std::string path;~Cleanup(){std::filesystem::remove_all(path);}} cleanup{root};
|
||||
xtc_project *p=nullptr;check(xtc_project_create(&p));check(xtc_project_load(p,"examples/projects/modern-session.xtc"));
|
||||
for(auto pair:{std::pair<uint64_t,const char *>{0,"Intro"},{3840,"Verse"},{7680,"Chorus"},{11520,"Outro"}})check(xtc_project_set_marker(p,pair.first,pair.second));
|
||||
uint64_t bus;check(xtc_project_add_bus(p,"Music bus",&bus));check(xtc_project_route_track(p,0,bus));
|
||||
xtc_automation_point a{0,0,XTC_AUTOMATION_GAIN,.65f,0};check(xtc_project_set_automation(p,&a));a.tick=3840;a.value=1;check(xtc_project_set_automation(p,&a));a.tick=7680;a.value=.8f;check(xtc_project_set_automation(p,&a));
|
||||
std::string project=root+"/composition.xtc";check(xtc_project_save(p,project.c_str()));xtc_project_destroy(p);
|
||||
MainWindow window(false,"");main_window=&window;window.resize(0,0,1400,900);window.show();check(window.open_project(project.c_str()));pump();
|
||||
auto *s=first<SequencerWidget>(window);if(!s)throw std::runtime_error("Sequencer missing");
|
||||
auto reset=[&](){window.reset_layout();check(window.open_project(project.c_str()));window.resize(0,20,1400,900);tab("Sequencer");s->select(0,0);s->position(0);check(window.set_loop(3840,7680,true));window.fit_song();pump();};
|
||||
reset();capture("overview");capture("sequencer-loop");capture("arrangement-markers");
|
||||
s->position(4800);check(window.loop_section());capture("section-navigation");
|
||||
dialog("marker-edit",[&]{s->marker_dialog();});
|
||||
dialog("ripple-time",[&]{s->ripple_dialog(false);});
|
||||
s->position(7680);check(s->ripple_time(1920,false));capture("ripple-result");reset();
|
||||
check(s->duplicate_track("Keys layered"));capture("track-duplication");reset();
|
||||
s->position(1920);check(s->split_selection());capture("midi-split");
|
||||
s->select_all_clips(); // Consolidation requires one track; reset to just the two halves.
|
||||
s->select(0,0);size_t tracks=0,clips=0;xtc_project_get_counts(s->project(),&tracks,&clips);
|
||||
for(size_t i=0;i<clips;++i){xtc_clip_info c{};xtc_project_get_clip(s->project(),i,&c);if(c.track_id==0&&c.start_tick==1920)s->toggle_clip(c.id);}
|
||||
check(s->merge_midi());capture("midi-consolidation");reset();
|
||||
dialog("midi-humanize",[&]{s->humanize_dialog();});dialog("midi-chord-builder",[&]{s->chord_dialog();});dialog("midi-arpeggio",[&]{s->arpeggio_dialog();});
|
||||
check(s->make_chord({4,7}));piano_view();capture("midi-chords-result");check(s->arpeggiate(240,70,false));piano_view();capture("midi-arpeggio-result");reset();
|
||||
piano_view();capture("piano-roll-velocity");window.detach_piano(false);reset();
|
||||
dialog("commands",[&]{window.show_commands();});
|
||||
tab("Mixer");capture("mixer-automation");button("Play");pump();capture("mixer-playing");button("Stop");
|
||||
window.resize(0,0,1220,720);pump();capture("mixer-minimum-size");window.resize(0,0,1400,900);
|
||||
for(int i=0;i<12;++i){check(window.create_track(false));}
|
||||
tab("Mixer");auto *scroll=first<Fl_Scroll>(*window.mixer());if(scroll)scroll->scroll_to(std::max(0,static_cast<int>(window.mixer()->strip_count())*156-scroll->w()),0);pump();capture("mixer-scrolled-session");reset();
|
||||
tab("Modular Graph");capture("modular-graph");reset();
|
||||
window.detach_transport(true);pump();capture("transport-detached");window.detach_mixer(true);pump();capture("workspace-detached");capture("mixer-detached");reset();
|
||||
window.detach_editor(0,true);pump();capture("sequencer-detached");reset();tab("Modular Graph");window.detach_editor(1,true);pump();capture("graph-detached");reset();
|
||||
char wave[4096];if(!realpath("examples/projects/original-pluck.wav",wave))throw std::runtime_error("Missing WAV");check(window.create_track(false));check(window.import_audio(wave));check(s->set_zoom(192));check(s->audio_properties(.8f,240,480));pump();capture("sequencer-audio-waveform");
|
||||
dialog("audio-clip-properties",[&]{s->audio_properties_dialog();});dialog("audio-normalization",[&]{s->normalize_dialog();});check(s->normalize_audio(.25f));capture("audio-normalization-result");
|
||||
dialog("project-collection",[&]{menu("File/Collect project media...");});check(window.collect_project((root+"/portable").c_str()));
|
||||
dialog("loop-range",[&]{button("Loop range...");});dialog("midi-controller-mapping",[&]{menu("Audio/MIDI controller mapping");});dialog("about",[&]{menu("Help/About");});
|
||||
for(const char *section:{"audio","plugins","interface","editing","project_defaults","transport"}){std::string file="preferences-"+std::string(section);for(char &c:file)if(c==' ')c='_';dialog(file.c_str(),[&]{window.show_preferences();},section);}
|
||||
xtc_settings settings=window.settings();std::string fixtures=std::filesystem::canonical(argv[0]).parent_path().string();snprintf(settings.ladspa_paths,sizeof(settings.ladspa_paths),"%s",fixtures.c_str());settings.clap_paths[0]=settings.vst2_paths[0]=settings.vst3_paths[0]=0;
|
||||
dialog("plugin-library",[&]{std::string path;xtc_choose_plugin_file(settings,path);});
|
||||
for(auto entry:{std::pair<const char *,const char *>{"plugin-descriptors","plugin-fixture.so"},{"clap-instrument-descriptors","clap-synth-fixture.clap"},{"vst2-instrument-descriptors","vst2-synth-fixture.so"},{"vst3-instrument-descriptors","vst3-synth-fixture.so"}}){unsigned int index=0;dialog(entry.first,[&]{xtc_choose_plugin((fixtures+"/"+entry.second).c_str(),48000,index,strcmp(entry.first,"plugin-descriptors")!=0);});}
|
||||
for(auto entry:{std::pair<const char *,unsigned int>{"internal-delay",2},{"internal-reverb",3},{"plugin-controls",2}}){xtc_plugin_spec spec{},edited{};xtc_plugin_details details{};if(!strcmp(entry.first,"plugin-controls"))check(xtc_plugin_probe((fixtures+"/plugin-fixture.so").c_str(),0,48000,&spec));else check(xtc_plugin_probe_format(XTC_PLUGIN_BUILTIN,XTC_BUILTIN_PATH,entry.second,48000,&spec));check(xtc_plugin_describe(&spec,48000,&details));dialog(entry.first,[&]{xtc_edit_plugin(spec,details,edited);});}
|
||||
reset();auto *choice=s->instrument_choice(0);if(!choice)throw std::runtime_error("Instrument menu missing");Fl::add_timeout(.3,[](void*){capture("internal-instruments");if(system("xdotool key Escape"))std::abort();});choice->menu()->pulldown(choice->x(),choice->y(),choice->w(),choice->h(),choice->mvalue(),choice);
|
||||
window.do_callback();std::puts("All documentation captures completed.");return 0;
|
||||
} catch(const std::exception &e){std::fprintf(stderr,"Screenshot capture failed: %s\n",e.what());return 1;}
|
||||
}
|
||||