diff --git a/ase/Makefile.mk b/ase/Makefile.mk index d3f6075b..f86c0a3c 100644 --- a/ase/Makefile.mk +++ b/ase/Makefile.mk @@ -2,49 +2,26 @@ include $(wildcard $>/ase/*.d) CLEANDIRS += $(wildcard $>/ase/ $>/lib/) -include ase/tests/Makefile.mk - # == ase/ *.cc file sets == +ase/AnklangSynthEngine.sources ::= ase/main.cc ase/jackdriver.sources ::= ase/driver-jack.cc ase/gtk2wrap.sources ::= ase/gtk2wrap.cc -ase/noglob.cc ::= ase/main.cc $(ase/gtk2wrap.sources) $(ase/jackdriver.sources) -ase/libsources.cc ::= $(filter-out $(ase/noglob.cc), $(wildcard ase/*.cc)) -ase/libsources.c ::= $(wildcard ase/*.c) -ase/include.deps ::= $>/ase/sysconfig.h - -# == AnklangSynthEngine definitions == -lib/AnklangSynthEngine ::= $>/lib/AnklangSynthEngine -ase/AnklangSynthEngine.sources ::= ase/main.cc $(ase/libsources.cc) $(ase/libsources.c) -ase/AnklangSynthEngine.gensrc ::= $(strip \ - $>/ase/api.jsonipc.cc \ - $>/ase/blake3impl.c \ - $>/ase/blake3avx512.c \ - $>/ase/blake3avx2.c \ - $>/ase/blake3sse41.c \ - $>/ase/blake3sse2.c \ -) -ase/AnklangSynthEngine.objects ::= $(sort \ - $(call BUILDDIR_O, $(ase/AnklangSynthEngine.sources)) \ - $(call SOURCE2_O, $(ase/AnklangSynthEngine.gensrc)) \ - $(ase/tests/objects) \ -) -ase/AnklangSynthEngine.objects += $(devices/4ase.objects) -ALL_TARGETS += $(lib/AnklangSynthEngine) - -# == AnklangSynthEngine-fma == -$(lib/AnklangSynthEngine)-fma: - $(QGEN) - $Q $(MAKE) INSN=fma builddir=$>/fma $>/fma/lib/AnklangSynthEngine - $Q $(CP) -v $>/fma/lib/AnklangSynthEngine.map $@.map - $Q $(CP) -v $>/fma/lib/AnklangSynthEngine $@ -ifeq ($(MODE)+$(INSN),production+sse) -ALL_TARGETS += $(lib/AnklangSynthEngine)-fma -# Iff MODE=production and INSN=sse (i.e. release builds), -# also build an FMA variant of the sound engine. -endif +ase/noglob.sources ::= $(ase/AnklangSynthEngine.sources) $(ase/gtk2wrap.sources) $(ase/jackdriver.sources) +ase/common.ccsources ::= $(filter-out $(ase/noglob.sources), $(wildcard ase/*.cc)) +ase/common.csources ::= $(wildcard ase/*.c) +ase/sysconfig.dep ::= $>/ase/sysconfig.h +ASE_EXTERNAL_INCLUDES := $(strip \ + -Iexternal/clap/include \ + -Iexternal/libsndfile/include \ + -Iexternal/liquidsfz/lib \ + -Iexternal/pandaresampler/include \ + -Iexternal/rapidjson/include \ + -Iexternal/websocketpp \ +) # also used by clang-tidy +ase/object.includes ::= $(ASE_EXTERNAL_INCLUDES) -I$> -I$>/external/ $(ASEDEPS_CFLAGS) # == ase/api.jsonipc.cc == -$>/ase/api.jsonipc.cc: ase/api.hh jsonipc/cxxjip.py $(ase/include.deps) | $>/ase/ # ase/Makefile.mk +$>/ase/api.jsonipc.cc: ase/api.hh jsonipc/cxxjip.py $(ase/sysconfig.dep) | $>/ase/ # ase/Makefile.mk $(QGEN) $Q echo '#include ' > $@.tmp $Q echo '#include ' >> $@.tmp @@ -52,25 +29,6 @@ $>/ase/api.jsonipc.cc: ase/api.hh jsonipc/cxxjip.py $(ase/include.deps) | $>/ase $Q echo '[[maybe_unused]] static bool init_jsonipc = (jsonipc_4_api_hh(), 0);' >> $@.tmp $Q mv $@.tmp $@ -# == ase/buildversion-$(version_short).cc == -ase/buildsum != echo '$(sharedir)' | sha256sum - | sed -r 's/(.{12}).*/$(version_short).mk\1/' -ase/buildversion.cc := $>/ase/buildversion-$(ase/buildsum).cc -$(ase/buildversion.cc): | $>/ase/ # $(GITCOMMITDEPS) - $(QGEN) - $Q echo '// make $@' > $@.tmp - $Q echo '#include ' >>$@.tmp - $Q echo 'namespace Ase {' >>$@.tmp - $Q echo 'const int ase_major_version = $(version_major);' >>$@.tmp - $Q echo 'const int ase_minor_version = $(version_minor);' >>$@.tmp - $Q echo 'const int ase_micro_version = $(version_micro);' >>$@.tmp - $Q echo 'const char *const ase_version_long = "$(version_short)+g$(version_hash) ($(INSN))";' >>$@.tmp - $Q echo 'const char *const ase_version_short = "$(version_short)";' >>$@.tmp - $Q echo 'const char *const ase_gettext_domain = "anklang-$(version_short)";' >>$@.tmp - $Q echo 'const char *const ase_sharedir = "$(sharedir)";' >>$@.tmp - $Q echo '} // Ase' >>$@.tmp - $Q mv $@.tmp $@ -ase/AnklangSynthEngine.objects += $(ase/buildversion.cc:.cc=.o) - # == ase/sysconfig.h == $>/ase/sysconfig.h: $(config-stamps) | $>/ase/ # ase/Makefile.mk $(QGEN) @@ -135,17 +93,57 @@ CLEANDIRS += $>/sndfile/ CLEANFILES += $>/lib/libsndfile.* ase/sndfile.cc: $>/lib/libsndfile.so # includes $>/sndfile/src/config.h +# == Common Sources == +ase/common.sources ::= $(ase/common.ccsources) $(ase/common.csources) +ase/generated.sources ::= $(strip \ + $>/ase/api.jsonipc.cc \ + $>/ase/blake3impl.c \ + $>/ase/blake3avx512.c \ + $>/ase/blake3avx2.c \ + $>/ase/blake3sse41.c \ + $>/ase/blake3sse2.c \ +) + +# == ase/buildversion-$(version_short).cc == +ase/buildsum != echo '$(sharedir)' | sha256sum - | sed -r 's/(.{12}).*/$(version_short).mk\1/' +ase/buildversion.cc := $>/ase/buildversion-$(ase/buildsum).cc +$(ase/buildversion.cc): | $>/ase/ # $(GITCOMMITDEPS) + $(QGEN) + $Q echo '// make $@' > $@.tmp + $Q echo '#include ' >>$@.tmp + $Q echo 'namespace Ase {' >>$@.tmp + $Q echo 'const int ase_major_version = $(version_major);' >>$@.tmp + $Q echo 'const int ase_minor_version = $(version_minor);' >>$@.tmp + $Q echo 'const int ase_micro_version = $(version_micro);' >>$@.tmp + $Q echo 'const char *const ase_version_long = "$(version_short)+g$(version_hash) ($(INSN))";' >>$@.tmp + $Q echo 'const char *const ase_version_short = "$(version_short)";' >>$@.tmp + $Q echo 'const char *const ase_gettext_domain = "anklang-$(version_short)";' >>$@.tmp + $Q echo 'const char *const ase_sharedir = "$(sharedir)";' >>$@.tmp + $Q echo '} // Ase' >>$@.tmp + $Q mv $@.tmp $@ +ase/generated.sources += $(ase/buildversion.cc) + +# == object deps == +ase/object.deps = $(ase/sysconfig.dep) $(ase/libase.deps) +ase/common.objects ::= $(sort \ + $(call BUILDDIR_O, $(ase/common.sources)) \ + $(call SOURCE2_O, $(ase/generated.sources)) \ +) +$(ase/common.objects): $(ase/object.deps) +$(ase/common.objects): EXTRA_INCLUDES ::= $(ase/object.includes) +$(devices/4ase.objects): $(ase/object.deps) +$(devices/4ase.objects): EXTRA_INCLUDES ::= $(ase/object.includes) +# Work around legacy code in external/websocketpp/*.hpp +ase/websocket.cc.FLAGS = -Wno-deprecated-dynamic-exception-spec -Wno-sign-promo +# Allow tests in mathutils.cc +ase/mathutils.cc.CTIDY_FLAGS = --checks=-clang-analyzer-security.FloatLoopCounter + # == AnklangSynthEngine == -ASE_EXTERNAL_INCLUDES := $(strip \ - -Iexternal/clap/include \ - -Iexternal/libsndfile/include \ - -Iexternal/liquidsfz/lib \ - -Iexternal/pandaresampler/include \ - -Iexternal/rapidjson/include \ - -Iexternal/websocketpp \ -) # also used by clang-tidy -$(ase/AnklangSynthEngine.objects): $(ase/include.deps) $(ase/libase.deps) -$(ase/AnklangSynthEngine.objects): EXTRA_INCLUDES ::= $(ASE_EXTERNAL_INCLUDES) -I$> -I$>/external/ $(ASEDEPS_CFLAGS) +lib/AnklangSynthEngine ::= $>/lib/AnklangSynthEngine +ase/AnklangSynthEngine.objects ::= $(call BUILDDIR_O, $(ase/AnklangSynthEngine.sources)) +$(ase/AnklangSynthEngine.objects): $(ase/object.deps) +$(ase/AnklangSynthEngine.objects): EXTRA_INCLUDES ::= $(ase/object.includes) +ase/AnklangSynthEngine.objects += $(ase/common.objects) $(devices/4ase.objects) $(lib/AnklangSynthEngine): $>/lib/libsndfile.so | $>/lib/ $(call BUILD_PROGRAM, \ $(lib/AnklangSynthEngine), \ @@ -153,15 +151,24 @@ $(call BUILD_PROGRAM, \ $(lib/libase.so), \ $(BOOST_SYSTEM_LIBS) $(ASEDEPS_LIBS) $(ALSA_LIBS) -lzstd -ldl $>/lib/libsndfile.so, \ ../lib) -# Work around legacy code in external/websocketpp/*.hpp -ase/websocket.cc.FLAGS = -Wno-deprecated-dynamic-exception-spec -Wno-sign-promo -# Allow tests in mathutils.cc -ase/mathutils.cc.CTIDY_FLAGS = --checks=-clang-analyzer-security.FloatLoopCounter +ALL_TARGETS += $(lib/AnklangSynthEngine) + +# == AnklangSynthEngine-fma == +$(lib/AnklangSynthEngine)-fma: + $(QGEN) + $Q $(MAKE) INSN=fma builddir=$>/fma $>/fma/lib/AnklangSynthEngine + $Q $(CP) -v $>/fma/lib/AnklangSynthEngine.map $@.map + $Q $(CP) -v $>/fma/lib/AnklangSynthEngine $@ +ifeq ($(MODE)+$(INSN),production+sse) + # Iff MODE=production and INSN=sse (i.e. release builds), + # also build an FMA variant of the sound engine. + ALL_TARGETS += $(lib/AnklangSynthEngine)-fma +endif # == jackdriver.so == lib/jackdriver.so ::= $>/lib/jackdriver.so ase/jackdriver.objects ::= $(call BUILDDIR_O, $(ase/jackdriver.sources)) -$(ase/jackdriver.objects): $(ase/include.deps) +$(ase/jackdriver.objects): $(ase/sysconfig.dep) $(ase/jackdriver.objects): EXTRA_INCLUDES ::= -I$> $(lib/jackdriver.so).LDFLAGS ::= -Wl,--unresolved-symbols=ignore-in-object-files ifneq ('','$(ANKLANG_JACK_LIBS)') @@ -180,7 +187,7 @@ lib/gtk2wrap.so ::= $>/lib/gtk2wrap.so ase/gtk2wrap.objects ::= $(call BUILDDIR_O, $(ase/gtk2wrap.sources)) $(ase/gtk2wrap.objects): EXTRA_INCLUDES ::= -I$> $(GTK2_CFLAGS) $(ase/gtk2wrap.objects): EXTRA_CXXFLAGS ::= -Wno-deprecated -Wno-deprecated-declarations -$(ase/gtk2wrap.objects): $(ase/include.deps) +$(ase/gtk2wrap.objects): $(ase/sysconfig.dep) $(call BUILD_SHARED_LIB, \ $(lib/gtk2wrap.so), \ $(ase/gtk2wrap.objects), \ diff --git a/ase/tests/benchmarks.cc b/ase/benchmarks.cc similarity index 99% rename from ase/tests/benchmarks.cc rename to ase/benchmarks.cc index c9e4e27b..287fcc35 100644 --- a/ase/tests/benchmarks.cc +++ b/ase/benchmarks.cc @@ -1,9 +1,9 @@ // This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0 -#include "../testing.hh" -#include "../unicode.hh" -#include "../memory.hh" -#include "../loft.hh" -#include "../internal.hh" +#include "testing.hh" +#include "unicode.hh" +#include "memory.hh" +#include "loft.hh" +#include "internal.hh" #include #include diff --git a/ase/engine.cc b/ase/engine.cc index a92ccb23..bf0965c4 100644 --- a/ase/engine.cc +++ b/ase/engine.cc @@ -953,12 +953,12 @@ apply_driver_preferences () main_loop->exec_once (97, &engine_driver_set_timerid, []() { String pcm_driver = pcm_driver_pref.gets(); - if (!main_config.pcm_override.empty()) - pcm_driver = main_config.pcm_override; + if (!App.pcm_override.empty()) + pcm_driver = App.pcm_override; StringS midis = { midi1_driver_pref.gets(), midi2_driver_pref.gets(), midi3_driver_pref.gets(), midi4_driver_pref.gets(), }; - if (!main_config.midi_override.empty()) - midis = { main_config.midi_override, "null", "null", "null", }; - main_config.engine->update_drivers (pcm_driver, synth_latency_pref.getn(), midis); + if (!App.midi_override.empty()) + midis = { App.midi_override, "null", "null", "null", }; + App.engine->update_drivers (pcm_driver, synth_latency_pref.getn(), midis); }); } diff --git a/ase/main.cc b/ase/main.cc index f646bc3a..2cb3fc73 100644 --- a/ase/main.cc +++ b/ase/main.cc @@ -30,9 +30,16 @@ static void print_class_tree (); namespace Ase { +struct MainAppImpl : MainApp { + MainAppImpl (); +}; +MainAppImpl main_app; +const MainApp &App = main_app; + +MainAppImpl::MainAppImpl() +{} + MainLoopP main_loop; -MainConfig main_config_; -const MainConfig &main_config = main_config_; static int embedding_fd = -1; static bool arg_js_api = false; static bool arg_class_tree = false; @@ -156,11 +163,9 @@ static constexpr int jsbin_logflags = 1 | 256; static StringS check_test_names; -static MainConfig -parse_args (int *argcp, char **argv) +static void +parse_args (int *argcp, char **argv, MainAppImpl &config) { - MainConfig config; - if (0) // allow jsipc logging via ASE_DEBUG ? { config.jsonapi_logflags |= debug_key_enabled ("jsbin") ? jsbin_logflags : 0; @@ -194,7 +199,7 @@ parse_args (int *argcp, char **argv) } else if (strcmp ("--check", argv[i]) == 0) { - config.mode = MainConfig::CHECK_INTEGRITY_TESTS; + config.mode = MainApp::CHECK_INTEGRITY_TESTS; ase_fatal_warnings = assertion_failed_fatal = true; printerr ("CHECK_INTEGRITY_TESTS…\n"); } @@ -208,7 +213,7 @@ parse_args (int *argcp, char **argv) { const char *eq = strchr (argv[i], '='); const char *arg = eq ? eq + 1 : i+1 < argc ? argv[++i] : nullptr; - config.mode = MainConfig::CHECK_INTEGRITY_TESTS; + config.mode = MainApp::CHECK_INTEGRITY_TESTS; ase_fatal_warnings = assertion_failed_fatal = true; if (arg) check_test_names.push_back (arg); @@ -294,7 +299,6 @@ parse_args (int *argcp, char **argv) } *argcp = e; } - return config; } static String @@ -361,8 +365,6 @@ handle_autostop (const LoopState &state) return false; } -} // Ase - static void init_sigpipe() { @@ -441,6 +443,8 @@ prefault_pages (size_t stacksize, size_t heapsize) stack[i] = 1; } +} // Ase + int main (int argc, char *argv[]) { @@ -465,17 +469,16 @@ main (int argc, char *argv[]) if (!setlocale (LC_ALL, "")) perror ("setlocale: locale not supported by libc"); + // parse args and config + parse_args (&argc, argv, main_app); + // prepare main event loop (needed before parse_args) main_loop = MainLoop::create(); // handle loft preallocation needs main_loop->exec_dispatcher (dispatch_loft_lowmem, EventLoop::PRIORITY_CEILING); - // parse args and config (needs main_loop) - main_config_ = parse_args (&argc, argv); - const MainConfig &config = main_config_; - // load preferences unless --norc was given - if (!config.norc) + if (!App.norc) Preference::load_preferences (true); const auto B1 = color (BOLD); @@ -495,7 +498,7 @@ main (int argc, char *argv[]) // load drivers and dump device list load_registered_drivers(); - if (config.list_drivers) + if (App.list_drivers) { Ase::Driver::EntryVec entries; printout ("%s", _("Available PCM drivers:\n")); @@ -533,7 +536,7 @@ main (int argc, char *argv[]) // start audio engine AudioEngine &audio_engine = make_audio_engine (main_loop_wakeup, 48000, SpeakerArrangement::STEREO); - main_config_.engine = &audio_engine; + main_app.engine = &audio_engine; audio_engine.start_threads (); /*const uint loopdispatcherid =*/ main_loop->exec_dispatcher ([&audio_engine] (const LoopState &state) -> bool { @@ -554,7 +557,7 @@ main (int argc, char *argv[]) // load projects ProjectImplP preload_project; - for (const auto &filename : config.args) + for (const auto &filename : App.args) { preload_project = ProjectImpl::create (Path::basename (filename)); Error error = Error::NO_MEMORY; @@ -566,8 +569,8 @@ main (int argc, char *argv[]) } // open Jsonapi socket - auto wss = WebSocketServer::create (jsonapi_make_connection, config.jsonapi_logflags); - main_config_.web_socket_server = &*wss; + auto wss = WebSocketServer::create (jsonapi_make_connection, App.jsonapi_logflags); + main_app.web_socket_server = &*wss; wss->http_dir (anklang_runpath (RPath::INSTALLDIR, "/ui/")); wss->http_alias ("/User/Controller", anklang_home_dir ("/Controller")); wss->http_alias ("/Builtin/Controller", anklang_runpath (RPath::INSTALLDIR, "/Controller")); @@ -576,7 +579,7 @@ main (int argc, char *argv[]) const int xport = embedding_fd >= 0 ? 0 : 1777; const String subprotocol = xport ? "" : make_auth_string(); jsonapi_require_auth (subprotocol); - if (main_config.mode == MainConfig::SYNTHENGINE) { + if (App.mode == MainApp::SYNTHENGINE) { const char *host = "127.0.0.1"; wss->listen (host, xport, [] () { main_loop->quit (-1); }); log ("Main: listen on: %s:%u", host, xport); @@ -628,29 +631,29 @@ main (int argc, char *argv[]) } // start output capturing - if (config.outputfile) + if (App.outputfile) { std::shared_ptr callbacks = std::make_shared(); - log ("Main: Start caputure: %s", config.outputfile); - config.engine->queue_capture_start (*callbacks, config.outputfile, true); + log ("Main: Start caputure: %s", App.outputfile); + App.engine->queue_capture_start (*callbacks, App.outputfile, true); auto job = [callbacks] () { for (const auto &callback : *callbacks) callback(); }; - config.engine->async_jobs += job; + App.engine->async_jobs += job; } // start auto play - if (config.play_autostart && preload_project) + if (App.play_autostart && preload_project) main_loop->exec_idle ([preload_project] () { log ("Main: starting playback (auto)"); - preload_project->start_playback (config.play_autostop); + preload_project->start_playback (App.play_autostop); }); // handle automatic shutdown main_loop->exec_dispatcher (handle_autostop); // run test suite - if (main_config.mode == MainConfig::CHECK_INTEGRITY_TESTS) + if (App.mode == MainApp::CHECK_INTEGRITY_TESTS) main_loop->exec_now (run_tests_and_quit); // run main event loop and catch SIGUSR2 @@ -660,14 +663,14 @@ main (int argc, char *argv[]) // cleanup wss->shutdown(); // close socket, allow no more calls - main_config_.web_socket_server = nullptr; + main_app.web_socket_server = nullptr; wss = nullptr; // halt audio engine, join its threads, dispatch cleanups audio_engine.set_project (nullptr); audio_engine.stop_threads(); main_loop->iterate_pending(); - main_config_.engine = nullptr; + main_app.engine = nullptr; log ("Main: exiting: %d", exitcode); return exitcode; @@ -694,7 +697,7 @@ job_queue_tests() { bool seen_engine_job = false, seen_deleter = false; // enqueue job with deleter into engine - AudioEngine *e = main_config_.engine; + AudioEngine *e = App.engine; std::shared_ptr vp = { nullptr, [e,&seen_deleter] (void*) { printerr (" job_queue_tests: Run Deleter (in_engine=%d)\n", e->thread_id == std::this_thread::get_id()); seen_deleter = true; diff --git a/ase/main.hh b/ase/main.hh index fb676d88..887da77a 100644 --- a/ase/main.hh +++ b/ase/main.hh @@ -11,8 +11,8 @@ namespace Ase { -// == MainConfig == -struct MainConfig { +// == MainApp == +struct MainApp { AudioEngine *engine = nullptr; String pcm_override, midi_override; WebSocketServer *web_socket_server = nullptr; @@ -28,7 +28,7 @@ struct MainConfig { enum ModeT { SYNTHENGINE, CHECK_INTEGRITY_TESTS }; ModeT mode = SYNTHENGINE; }; -extern const MainConfig &main_config; +extern const MainApp &App; // == Jobs & main loop == extern MainLoopP main_loop; diff --git a/ase/project.cc b/ase/project.cc index a3c18f89..7cdaeaff 100644 --- a/ase/project.cc +++ b/ase/project.cc @@ -742,8 +742,8 @@ void ProjectImpl::start_playback (double autostop) { assert_return (!discarded_); - assert_return (main_config.engine); - AudioEngine &engine = *main_config.engine; + assert_return (App.engine); + AudioEngine &engine = *App.engine; ProjectImplP selfp = shared_ptr_cast (this); // keep alive while engine changes refcounts ProjectImplP oldp = engine.get_project(); // keep alive while engine changes refs if (oldp != selfp) diff --git a/ase/server.cc b/ase/server.cc index 2f4b8fb4..28ede0ae 100644 --- a/ase/server.cc +++ b/ase/server.cc @@ -168,8 +168,8 @@ Server::dir_crawler (const String &cwd) ResourceCrawlerP Server::url_crawler (const String &url) { - if (main_config.web_socket_server) { - String dir = main_config.web_socket_server->map_url (url); + if (App.web_socket_server) { + String dir = App.web_socket_server->map_url (url); if (!dir.empty()) return FileCrawler::make_shared (dir, false, false); } @@ -179,7 +179,7 @@ Server::url_crawler (const String &url) String Server::engine_stats () { - const String s = main_config.engine->engine_stats (0); + const String s = App.engine->engine_stats (0); printerr ("Server::engine_stats:\n%s\n", s); return s; } diff --git a/ase/tests/Makefile.mk b/ase/tests/Makefile.mk deleted file mode 100644 index fcdc9188..00000000 --- a/ase/tests/Makefile.mk +++ /dev/null @@ -1,10 +0,0 @@ -# This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0 -include $(wildcard $>/ase/tests/*.d) -CLEANDIRS += $(wildcard $>/ase/tests/) - -# == ase/tests/ file sets == -ase/tests/ccsources ::= $(wildcard ase/tests/*.cc) -ase/tests/objects ::= $(call BUILDDIR_O, $(ase/tests/ccsources)) - -# == ase/tests/ dependencies == -$(ase/tests/objects): | $>/ase/tests/ diff --git a/ase/track.cc b/ase/track.cc index 482737ac..6fbbfbb4 100644 --- a/ase/track.cc +++ b/ase/track.cc @@ -87,7 +87,7 @@ TrackImpl::_set_parent (GadgetImpl *parent) DeviceImpl::_set_parent (project); if (project) { - AudioEngine *engine = main_config.engine; + AudioEngine *engine = App.engine; assert_return (!midi_prod_); midi_prod_ = create_processor_device (*engine, "Ase::MidiLib::MidiProducerImpl", true); assert_return (midi_prod_); diff --git a/ui/b/devicepanel.js b/ui/b/devicepanel.js index ba375e2c..ddc11c08 100644 --- a/ui/b/devicepanel.js +++ b/ui/b/devicepanel.js @@ -124,7 +124,7 @@ class BDevicePanel extends LitComponent { let info_promise; if (changed_props.has ('track')) { this.chain_ = null; - const track_fecth_device = async () => { + const track_fetch_device = async () => { const chain = await this.track.access_device(); const devicetypes = await list_device_types (chain); this.devicetypes = devicetypes; @@ -132,7 +132,7 @@ class BDevicePanel extends LitComponent { this.request_update(); }; if (this.track) - track_fecth_device(); + track_fetch_device(); } } async activate (uri)