Full Code of elk-audio/sushi for AI

master 08f24e9cd47c cached
458 files
3.0 MB
801.3k tokens
2165 symbols
1 requests
Download .txt
Showing preview only (3,203K chars total). Download the full file or copy to clipboard to get everything.
Repository: elk-audio/sushi
Branch: master
Commit: 08f24e9cd47c
Files: 458
Total size: 3.0 MB

Directory structure:
gitextract_9o1ns6zt/

├── .clang-format
├── .gitignore
├── CMakeLists.txt
├── CONTRIBUTING.md
├── COPYING
├── HISTORY.md
├── LICENSE.md
├── README.md
├── apps/
│   ├── CMakeLists.txt
│   └── main.cpp
├── bitbucket-pipelines.yml
├── docs/
│   └── LIBRARY.md
├── include/
│   ├── sushi/
│   │   ├── compile_time_settings.h
│   │   ├── constants.h
│   │   ├── control_interface.h
│   │   ├── control_notifications.h
│   │   ├── coreaudio_devices_dump.h
│   │   ├── elk_sentry_log_sink.h
│   │   ├── factory_interface.h
│   │   ├── offline_factory.h
│   │   ├── options.h
│   │   ├── parameter_dump.h
│   │   ├── portaudio_devices_dump.h
│   │   ├── reactive_factory.h
│   │   ├── rt_controller.h
│   │   ├── sample_buffer.h
│   │   ├── standalone_factory.h
│   │   ├── sushi.h
│   │   ├── sushi_time.h
│   │   ├── terminal_utilities.h
│   │   ├── types.h
│   │   └── utils.h
│   └── version.h.in
├── misc/
│   ├── .gitkeep
│   ├── README.md
│   └── config_files/
│       ├── arp_peakmeter_osc_broadcast.json
│       ├── config_play_arp_link_midi_out.json
│       ├── cv_lfo.json
│       ├── cv_to_cutoff.json
│       ├── cv_to_synth.json
│       ├── empty.json
│       ├── freeverb_aux.json
│       ├── fx.json
│       ├── multi_track.json
│       ├── multichannel_plugin.json
│       ├── play_arp_mda_link.json
│       ├── play_brickworks_fx.json
│       ├── play_brickworks_synth.json
│       ├── play_cv_arp.json
│       ├── play_lv2.json
│       ├── play_lv2_jx10.json
│       ├── play_master_gain.json
│       ├── play_vst2.json
│       ├── play_vst3.json
│       ├── play_wav_streamer.json
│       ├── prepost_tracks.json
│       ├── rt_midi.json
│       ├── send_return_seq.json
│       └── vst_8_ch.json
├── rpc_interface/
│   ├── CMakeLists.txt
│   ├── include/
│   │   └── sushi_rpc/
│   │       └── grpc_server.h
│   └── src/
│       ├── async_service_call_data.cpp
│       ├── async_service_call_data.h
│       ├── control_service.cpp
│       ├── control_service.h
│       └── grpc_server.cpp
├── src/
│   ├── audio_frontends/
│   │   ├── apple_coreaudio/
│   │   │   ├── apple_coreaudio_device.h
│   │   │   ├── apple_coreaudio_device.mm
│   │   │   ├── apple_coreaudio_object.cpp
│   │   │   ├── apple_coreaudio_object.h
│   │   │   ├── apple_coreaudio_system_object.h
│   │   │   ├── apple_coreaudio_utils.cpp
│   │   │   └── apple_coreaudio_utils.h
│   │   ├── apple_coreaudio_frontend.cpp
│   │   ├── apple_coreaudio_frontend.h
│   │   ├── audio_frontend_internals.h
│   │   ├── base_audio_frontend.cpp
│   │   ├── base_audio_frontend.h
│   │   ├── coreaudio_devices_dump.cpp
│   │   ├── jack_frontend.cpp
│   │   ├── jack_frontend.h
│   │   ├── offline_frontend.cpp
│   │   ├── offline_frontend.h
│   │   ├── portaudio_devices_dump.cpp
│   │   ├── portaudio_frontend.cpp
│   │   ├── portaudio_frontend.h
│   │   ├── reactive_frontend.cpp
│   │   ├── reactive_frontend.h
│   │   ├── xenomai_raspa_frontend.cpp
│   │   └── xenomai_raspa_frontend.h
│   ├── concrete_sushi.cpp
│   ├── concrete_sushi.h
│   ├── control_frontends/
│   │   ├── alsa_midi_frontend.cpp
│   │   ├── alsa_midi_frontend.h
│   │   ├── base_control_frontend.cpp
│   │   ├── base_control_frontend.h
│   │   ├── base_midi_frontend.h
│   │   ├── osc_frontend.cpp
│   │   ├── osc_frontend.h
│   │   ├── osc_utils.h
│   │   ├── oscpack_osc_messenger.cpp
│   │   ├── oscpack_osc_messenger.h
│   │   ├── reactive_midi_frontend.cpp
│   │   ├── reactive_midi_frontend.h
│   │   ├── rt_midi_frontend.cpp
│   │   └── rt_midi_frontend.h
│   ├── dsp_library/
│   │   ├── biquad_filter.cpp
│   │   ├── biquad_filter.h
│   │   ├── envelopes.h
│   │   ├── master_limiter.h
│   │   ├── sample_wrapper.h
│   │   └── value_smoother.h
│   ├── engine/
│   │   ├── audio_engine.cpp
│   │   ├── audio_engine.h
│   │   ├── audio_graph.cpp
│   │   ├── audio_graph.h
│   │   ├── base_engine.h
│   │   ├── base_event_dispatcher.h
│   │   ├── base_processor_container.h
│   │   ├── connection_storage.h
│   │   ├── controller/
│   │   │   ├── audio_graph_controller.cpp
│   │   │   ├── audio_graph_controller.h
│   │   │   ├── audio_routing_controller.cpp
│   │   │   ├── audio_routing_controller.h
│   │   │   ├── completion_sender.h
│   │   │   ├── controller.cpp
│   │   │   ├── controller.h
│   │   │   ├── controller_common.h
│   │   │   ├── cv_gate_controller.cpp
│   │   │   ├── cv_gate_controller.h
│   │   │   ├── keyboard_controller.cpp
│   │   │   ├── keyboard_controller.h
│   │   │   ├── midi_controller.cpp
│   │   │   ├── midi_controller.h
│   │   │   ├── osc_controller.cpp
│   │   │   ├── osc_controller.h
│   │   │   ├── parameter_controller.cpp
│   │   │   ├── parameter_controller.h
│   │   │   ├── program_controller.cpp
│   │   │   ├── program_controller.h
│   │   │   ├── real_time_controller.cpp
│   │   │   ├── real_time_controller.h
│   │   │   ├── session_controller.cpp
│   │   │   ├── session_controller.h
│   │   │   ├── system_controller.cpp
│   │   │   ├── system_controller.h
│   │   │   ├── timing_controller.cpp
│   │   │   ├── timing_controller.h
│   │   │   ├── transport_controller.cpp
│   │   │   └── transport_controller.h
│   │   ├── event_dispatcher.cpp
│   │   ├── event_dispatcher.h
│   │   ├── event_timer.cpp
│   │   ├── event_timer.h
│   │   ├── host_control.h
│   │   ├── json_configurator.cpp
│   │   ├── json_configurator.h
│   │   ├── json_schemas/
│   │   │   ├── cv_gate_schema.json
│   │   │   ├── events_schema.json
│   │   │   ├── host_config_schema.json
│   │   │   ├── midi_schema.json
│   │   │   ├── osc_schema.json
│   │   │   ├── state_schema.json
│   │   │   └── tracks_schema.json
│   │   ├── link_dummy.h
│   │   ├── midi_dispatcher.cpp
│   │   ├── midi_dispatcher.h
│   │   ├── midi_receiver.h
│   │   ├── parameter_manager.cpp
│   │   ├── parameter_manager.h
│   │   ├── plugin_library.cpp
│   │   ├── plugin_library.h
│   │   ├── processor_container.cpp
│   │   ├── processor_container.h
│   │   ├── receiver.cpp
│   │   ├── receiver.h
│   │   ├── track.cpp
│   │   ├── track.h
│   │   ├── transport.cpp
│   │   └── transport.h
│   ├── factories/
│   │   ├── base_factory.cpp
│   │   ├── base_factory.h
│   │   ├── offline_factory.cpp
│   │   ├── offline_factory_implementation.cpp
│   │   ├── offline_factory_implementation.h
│   │   ├── reactive_factory.cpp
│   │   ├── reactive_factory_implementation.cpp
│   │   ├── reactive_factory_implementation.h
│   │   ├── standalone_factory.cpp
│   │   ├── standalone_factory_implementation.cpp
│   │   └── standalone_factory_implementation.h
│   ├── library/
│   │   ├── base_performance_timer.h
│   │   ├── base_processor_factory.h
│   │   ├── connection_types.h
│   │   ├── event.cpp
│   │   ├── event.h
│   │   ├── event_interface.h
│   │   ├── fixed_stack.h
│   │   ├── id_generator.h
│   │   ├── internal_plugin.cpp
│   │   ├── internal_plugin.h
│   │   ├── internal_processor_factory.cpp
│   │   ├── internal_processor_factory.h
│   │   ├── lv2/
│   │   │   ├── lv2_control.cpp
│   │   │   ├── lv2_control.h
│   │   │   ├── lv2_features.cpp
│   │   │   ├── lv2_features.h
│   │   │   ├── lv2_host_nodes.h
│   │   │   ├── lv2_model.cpp
│   │   │   ├── lv2_model.h
│   │   │   ├── lv2_port.cpp
│   │   │   ├── lv2_port.h
│   │   │   ├── lv2_processor_factory.cpp
│   │   │   ├── lv2_processor_factory.h
│   │   │   ├── lv2_state.cpp
│   │   │   ├── lv2_state.h
│   │   │   ├── lv2_worker.cpp
│   │   │   ├── lv2_worker.h
│   │   │   ├── lv2_wrapper.cpp
│   │   │   └── lv2_wrapper.h
│   │   ├── midi_decoder.cpp
│   │   ├── midi_decoder.h
│   │   ├── midi_encoder.cpp
│   │   ├── midi_encoder.h
│   │   ├── parameter_dump.cpp
│   │   ├── performance_timer.cpp
│   │   ├── performance_timer.h
│   │   ├── plugin_parameters.h
│   │   ├── plugin_registry.cpp
│   │   ├── plugin_registry.h
│   │   ├── processor.cpp
│   │   ├── processor.h
│   │   ├── processor_state.cpp
│   │   ├── processor_state.h
│   │   ├── rt_event.h
│   │   ├── rt_event_fifo.h
│   │   ├── rt_event_pipe.h
│   │   ├── simple_fifo.h
│   │   ├── spinlock.h
│   │   ├── synchronised_fifo.h
│   │   ├── vst2x/
│   │   │   ├── vst2x_host_callback.cpp
│   │   │   ├── vst2x_host_callback.h
│   │   │   ├── vst2x_midi_event_fifo.h
│   │   │   ├── vst2x_plugin_loader.cpp
│   │   │   ├── vst2x_plugin_loader.h
│   │   │   ├── vst2x_processor_factory.cpp
│   │   │   ├── vst2x_processor_factory.h
│   │   │   ├── vst2x_wrapper.cpp
│   │   │   └── vst2x_wrapper.h
│   │   └── vst3x/
│   │       ├── vst3x_file_utils.cpp
│   │       ├── vst3x_file_utils.h
│   │       ├── vst3x_host_app.cpp
│   │       ├── vst3x_host_app.h
│   │       ├── vst3x_processor_factory.cpp
│   │       ├── vst3x_processor_factory.h
│   │       ├── vst3x_utils.cpp
│   │       ├── vst3x_utils.h
│   │       ├── vst3x_wrapper.cpp
│   │       └── vst3x_wrapper.h
│   ├── plugins/
│   │   ├── arpeggiator_plugin.cpp
│   │   ├── arpeggiator_plugin.h
│   │   ├── brickworks/
│   │   │   ├── bitcrusher_plugin.cpp
│   │   │   ├── bitcrusher_plugin.h
│   │   │   ├── cab_sim_plugin.cpp
│   │   │   ├── cab_sim_plugin.h
│   │   │   ├── chorus_plugin.cpp
│   │   │   ├── chorus_plugin.h
│   │   │   ├── clip_plugin.cpp
│   │   │   ├── clip_plugin.h
│   │   │   ├── combdelay_plugin.cpp
│   │   │   ├── combdelay_plugin.h
│   │   │   ├── compressor_plugin.cpp
│   │   │   ├── compressor_plugin.h
│   │   │   ├── dist_plugin.cpp
│   │   │   ├── dist_plugin.h
│   │   │   ├── drive_plugin.cpp
│   │   │   ├── drive_plugin.h
│   │   │   ├── eq3band_plugin.cpp
│   │   │   ├── eq3band_plugin.h
│   │   │   ├── flanger_plugin.cpp
│   │   │   ├── flanger_plugin.h
│   │   │   ├── fuzz_plugin.cpp
│   │   │   ├── fuzz_plugin.h
│   │   │   ├── highpass_plugin.cpp
│   │   │   ├── highpass_plugin.h
│   │   │   ├── multi_filter_plugin.cpp
│   │   │   ├── multi_filter_plugin.h
│   │   │   ├── noise_gate_plugin.cpp
│   │   │   ├── noise_gate_plugin.h
│   │   │   ├── notch_plugin.cpp
│   │   │   ├── notch_plugin.h
│   │   │   ├── phaser_plugin.cpp
│   │   │   ├── phaser_plugin.h
│   │   │   ├── ring_mod_plugin.cpp
│   │   │   ├── ring_mod_plugin.h
│   │   │   ├── saturation_plugin.cpp
│   │   │   ├── saturation_plugin.h
│   │   │   ├── simple_synth_plugin.cpp
│   │   │   ├── simple_synth_plugin.h
│   │   │   ├── tremolo_plugin.cpp
│   │   │   ├── tremolo_plugin.h
│   │   │   ├── vibrato_plugin.cpp
│   │   │   ├── vibrato_plugin.h
│   │   │   ├── wah_plugin.cpp
│   │   │   └── wah_plugin.h
│   │   ├── control_to_cv_plugin.cpp
│   │   ├── control_to_cv_plugin.h
│   │   ├── cv_to_control_plugin.cpp
│   │   ├── cv_to_control_plugin.h
│   │   ├── equalizer_plugin.cpp
│   │   ├── equalizer_plugin.h
│   │   ├── freeverb_plugin.cpp
│   │   ├── freeverb_plugin.h
│   │   ├── gain_plugin.cpp
│   │   ├── gain_plugin.h
│   │   ├── lfo_plugin.cpp
│   │   ├── lfo_plugin.h
│   │   ├── mono_summing_plugin.cpp
│   │   ├── mono_summing_plugin.h
│   │   ├── passthrough_plugin.cpp
│   │   ├── passthrough_plugin.h
│   │   ├── peak_meter_plugin.cpp
│   │   ├── peak_meter_plugin.h
│   │   ├── return_plugin.cpp
│   │   ├── return_plugin.h
│   │   ├── sample_delay_plugin.cpp
│   │   ├── sample_delay_plugin.h
│   │   ├── sample_player_plugin.cpp
│   │   ├── sample_player_plugin.h
│   │   ├── sample_player_voice.cpp
│   │   ├── sample_player_voice.h
│   │   ├── send_plugin.cpp
│   │   ├── send_plugin.h
│   │   ├── send_return_factory.cpp
│   │   ├── send_return_factory.h
│   │   ├── step_sequencer_plugin.cpp
│   │   ├── step_sequencer_plugin.h
│   │   ├── stereo_mixer_plugin.cpp
│   │   ├── stereo_mixer_plugin.h
│   │   ├── transposer_plugin.cpp
│   │   ├── transposer_plugin.h
│   │   ├── wav_streamer_plugin.cpp
│   │   ├── wav_streamer_plugin.h
│   │   ├── wav_writer_plugin.cpp
│   │   └── wav_writer_plugin.h
│   └── utils.cpp
├── test/
│   ├── CMakeLists.txt
│   ├── data/
│   │   ├── config.json
│   │   ├── config_single_stereo.json
│   │   └── master_limiter_test_data.h
│   ├── resources/
│   │   └── Info.plist.in
│   └── unittests/
│       ├── audio_frontends/
│       │   ├── apple_coreaudio_frontend_test.cpp
│       │   ├── jack_frontend_test.cpp
│       │   ├── offline_frontend_test.cpp
│       │   └── portaudio_frontend_test.cpp
│       ├── control_frontends/
│       │   ├── osc_frontend_test.cpp
│       │   └── oscpack_osc_messenger_test.cpp
│       ├── dsp_library/
│       │   ├── envelope_test.cpp
│       │   ├── master_limiter_test.cpp
│       │   ├── sample_wrapper_test.cpp
│       │   └── value_smoother_test.cpp
│       ├── engine/
│       │   ├── audio_graph_test.cpp
│       │   ├── controller_test.cpp
│       │   ├── controllers/
│       │   │   ├── audio_graph_controller_test.cpp
│       │   │   ├── audio_routing_controller_test.cpp
│       │   │   ├── midi_controller_test.cpp
│       │   │   ├── osc_controller_test.cpp
│       │   │   ├── reactive_controller_test.cpp
│       │   │   └── session_controller_test.cpp
│       │   ├── engine_test.cpp
│       │   ├── event_dispatcher_test.cpp
│       │   ├── event_timer_test.cpp
│       │   ├── factories/
│       │   │   └── factories_test.cpp
│       │   ├── json_configurator_test.cpp
│       │   ├── midi_dispatcher_test.cpp
│       │   ├── parameter_manager_test.cpp
│       │   ├── plugin_library_test.cpp
│       │   ├── processor_container_test.cpp
│       │   ├── receiver_test.cpp
│       │   ├── track_test.cpp
│       │   └── transport_test.cpp
│       ├── library/
│       │   ├── event_test.cpp
│       │   ├── fixed_stack_test.cpp
│       │   ├── id_generator_test.cpp
│       │   ├── internal_plugin_test.cpp
│       │   ├── lv2_wrapper_test.cpp
│       │   ├── midi_decoder_test.cpp
│       │   ├── midi_encoder_test.cpp
│       │   ├── parameter_dump_test.cpp
│       │   ├── performance_timer_test.cpp
│       │   ├── plugin_parameters_test.cpp
│       │   ├── processor_test.cpp
│       │   ├── rt_event_test.cpp
│       │   ├── sample_buffer_test.cpp
│       │   ├── simple_fifo_test.cpp
│       │   ├── vst2x_midi_event_fifo_test.cpp
│       │   ├── vst2x_plugin_loading_test.cpp
│       │   ├── vst2x_wrapper_test.cpp
│       │   └── vst3x_wrapper_test.cpp
│       ├── plugins/
│       │   ├── arpeggiator_plugin_test.cpp
│       │   ├── brickworks_simple_synth_test.cpp
│       │   ├── control_to_cv_plugin_test.cpp
│       │   ├── cv_to_control_plugin_test.cpp
│       │   ├── external_plugins_test.cpp
│       │   ├── plugins_test.cpp
│       │   ├── sample_player_plugin_test.cpp
│       │   ├── send_return_test.cpp
│       │   ├── step_sequencer_test.cpp
│       │   └── wav_streamer_plugin_test.cpp
│       ├── sample_test.cpp
│       └── test_utils/
│           ├── apple_coreaudio_mockup.cpp
│           ├── apple_coreaudio_mockup.h
│           ├── audio_frontend_mockup.h
│           ├── audio_graph_accessor.h
│           ├── control_mockup.h
│           ├── dummy_processor.h
│           ├── engine_mockup.h
│           ├── event_dispatcher_accessor.h
│           ├── host_control_mockup.h
│           ├── jack_mockup.cpp
│           ├── meta_schema_v4.json
│           ├── mock_event_dispatcher.h
│           ├── mock_midi_frontend.h
│           ├── mock_osc_interface.h
│           ├── mock_oscpack.h
│           ├── mock_processor_container.h
│           ├── mock_sushi.h
│           ├── plugin_accessors.h
│           ├── portaudio_mockup.cpp
│           ├── portaudio_mockup.h
│           ├── test_utils.h
│           ├── track_accessor.h
│           ├── vst2_test_plugin.cpp
│           ├── vst2_test_plugin.def
│           ├── vst2_test_plugin.h
│           ├── vst3_test_plugin.cpp
│           └── vst3_test_plugin.h
├── third-party/
│   ├── .gitkeep
│   ├── CMakeLists.txt
│   ├── fifo/
│   │   ├── CMakeLists.txt
│   │   └── include/
│   │       └── fifo/
│   │           └── circularfifo_memory_relaxed_aquire_release.h
│   ├── lv2_host/
│   │   ├── CMakeLists.txt
│   │   ├── include/
│   │   │   └── lv2_host/
│   │   │       ├── lv2_evbuf.h
│   │   │       └── lv2_symap.h
│   │   └── src/
│   │       ├── lv2_evbuf.cpp
│   │       └── lv2_symap.cpp
│   ├── optionparser/
│   │   ├── Makefile
│   │   ├── example.cpp
│   │   ├── example_arg.cc
│   │   ├── optionparser.h
│   │   ├── printUsage.h
│   │   ├── testodr1.cc
│   │   ├── testodr2.cc
│   │   ├── testparse.cpp
│   │   └── testprintusage.cpp
│   └── vst3sdk.windows.patch
├── triplets/
│   └── win-custom-x86-64.cmake
└── vcpkg.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .clang-format
================================================
# Generated from CLion C/C++ Code Style settings
BasedOnStyle: LLVM
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignOperands: true
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Always
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Always
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterReturnType: None
AlwaysBreakTemplateDeclarations: Yes
BreakBeforeBraces: Custom
BraceWrapping:
  AfterCaseLabel: false
  AfterClass: true
  AfterControlStatement: Always
  AfterEnum: true
  AfterFunction: true
  AfterNamespace: false
  AfterUnion: true
  BeforeCatch: false
  BeforeElse: true
  IndentBraces: false
  SplitEmptyFunction: false
  SplitEmptyRecord: true
BreakBeforeBinaryOperators: None
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
ColumnLimit: 0
CompactNamespaces: false
ContinuationIndentWidth: 8
IndentCaseLabels: true
IndentPPDirectives: None
IndentWidth: 4
KeepEmptyLinesAtTheStartOfBlocks: true
MaxEmptyLinesToKeep: 2
NamespaceIndentation: None
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PointerAlignment: Left
ReflowComments: false
SpaceAfterCStyleCast: true
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
TabWidth: 4
UseTab: Never
SortIncludes: Never


================================================
FILE: .gitignore
================================================
# Object files
*.o
*.ko
*.obj
*.elf

# Precompiled Headers
*.gch
*.pch

# Libraries
*.lib
*.a
*.la
*.lo

# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib

# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex

# Debug files
*.dSYM/

# Hidden files
.*
!.clang-format
!*/.gitkeep
!.gitignore

# Build and scratch directories
scratch/
*/scratch
build*/
generated/
cmake-build-*
third-party/install/
third-party/rehost/

# Windows folders
*.ini

# Python pyc
*.pyc

# CMake's compile_commnads used by clang-tools
compile_commands.json

# Log files created by running sushi from somewhere in the repository
log.txt
/vcpkg_installed/


================================================
FILE: CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.28)

# Require out-of-source builds
file(TO_CMAKE_PATH "${PROJECT_BINARY_DIR}/CMakeLists.txt" LOC_PATH)
if(EXISTS "${LOC_PATH}")
    message(FATAL_ERROR "You cannot build in a source directory (or any directory with a CMakeLists.txt file). Please make a build subdirectory. Feel free to remove CMakeCache.txt and CMakeFiles.")
endif()

#####################
#  Project Version  #
#####################

# Don't change version anywhere else. Everything is generated from this.
set(SUSHI_VERSION_MAJOR 1)
set(SUSHI_VERSION_MINOR 3)
set(SUSHI_VERSION_REVISION 0)

# Versioning for the external api(s)
# Update this to match the version above only if the external api (in include/sushi and/or rpc_interface/protos)
# has been changed. Otherwise don't update.
set(SUSHI_EXTERNAL_API_VERSION "1.2.0")

project(sushi_library
    DESCRIPTION "Headless plugin host for Elk Audio OS"
    HOMEPAGE_URL "https://github.com/elk-audio/sushi"
    LANGUAGES CXX
    VERSION ${SUSHI_VERSION_MAJOR}.${SUSHI_VERSION_MINOR}.${SUSHI_VERSION_REVISION}
)

if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE Debug)
endif()

set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})

##################################
#  Generate build information    #
##################################

# Get the latest commit hash of the working branch
execute_process(
    COMMAND git log -1 --format=%H
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
    OUTPUT_VARIABLE GIT_COMMIT_HASH
    OUTPUT_STRIP_TRAILING_WHITESPACE
)

string(TIMESTAMP BUILD_TIMESTAMP "%Y-%m-%d %H:%M")

configure_file(
    ${CMAKE_CURRENT_SOURCE_DIR}/include/version.h.in
    ${CMAKE_BINARY_DIR}/generated/version.h
)

###########################
#  Build and link options #
###########################
# The defaults enable all options and select APIs available for either Xenomai or macOS
set(SUSHI_WITH_JACK_DEFAULT OFF)
set(SUSHI_WITH_VST2_DEFAULT OFF)
set(SUSHI_WITH_VST3_DEFAULT ON)
set(SUSHI_LINK_VST3_DEFAULT ON)
set(SUSHI_WITH_LINK_DEFAULT ON)
set(SUSHI_WITH_RPC_INTERFACE_DEFAULT ON)
set(SUSHI_TWINE_STATIC_DEFAULT OFF)
set(SUSHI_AUDIO_BUFFER_SIZE_DEFAULT 64)
set(SUSHI_WITH_SENTRY_DEFAULT OFF)
set(SUSHI_SENTRY_DSN_DEFAULT "--Sentry default DSN is undefined--")
set(SUSHI_DISABLE_MULTICORE_UNIT_TESTS_DEFAULT OFF)
set(SUSHI_BUILD_STANDALONE_APP_DEFAULT ON)
set(SUSHI_BUILD_WITH_SANITIZERS_DEFAULT OFF)

set(SUSHI_RASPA_FLAVOR_DEFAULT "evl")
set(TWINE_WITH_XENOMAI_DEFAULT OFF)
set(TWINE_WITH_EVL_DEFAULT OFF)

if (APPLE)
    # macOS defaults
    set(SUSHI_WITH_RASPA_DEFAULT OFF)
    set(SUSHI_WITH_PORTAUDIO_DEFAULT OFF)
    set(SUSHI_WITH_APPLE_COREAUDIO_DEFAULT ON)
    set(SUSHI_WITH_ALSA_MIDI_DEFAULT OFF)
    set(SUSHI_WITH_RT_MIDI_DEFAULT ON)
    set(SUSHI_WITH_VST2_DEFAULT OFF)
    set(SUSHI_WITH_LV2_DEFAULT ON)
    set(SUSHI_WITH_LV2_MDA_TESTS_DEFAULT OFF)
    set(SUSHI_WITH_UNIT_TESTS_DEFAULT ON)
    set(SUSHI_BUILD_TWINE_DEFAULT ON)
    set(SUSHI_DISABLE_MULTICORE_UNIT_TESTS_DEFAULT ON)

elseif (MSVC)
    # windows defaults
    set(SUSHI_WITH_XENOMAI_DEFAULT OFF)
    set(SUSHI_WITH_PORTAUDIO_DEFAULT ON)
    set(SUSHI_WITH_ALSA_MIDI_DEFAULT OFF)
    set(SUSHI_WITH_RT_MIDI_DEFAULT ON)
    set(SUSHI_WITH_VST2_DEFAULT OFF)
    set(SUSHI_WITH_LV2_DEFAULT OFF)
    set(SUSHI_WITH_LV2_MDA_TESTS_DEFAULT OFF)
    set(SUSHI_WITH_UNIT_TESTS_DEFAULT ON)
    set(SUSHI_BUILD_TWINE_DEFAULT ON)

    add_compile_definitions(_USE_MATH_DEFINES)

elseif (CMAKE_CROSSCOMPILING)
    # Yocto cross-compilation defaults
    set(SUSHI_WITH_RASPA_DEFAULT ON)
    set(SUSHI_WITH_PORTAUDIO_DEFAULT OFF)
    set(SUSHI_WITH_APPLE_COREAUDIO_DEFAULT OFF)
    set(SUSHI_WITH_ALSA_MIDI_DEFAULT ON)
    set(SUSHI_WITH_RT_MIDI_DEFAULT OFF)
    set(SUSHI_WITH_LV2_DEFAULT ON)
    set(SUSHI_WITH_LV2_MDA_TESTS_DEFAULT OFF)
    set(SUSHI_WITH_UNIT_TESTS_DEFAULT OFF)
    set(SUSHI_BUILD_TWINE_DEFAULT OFF)

else()
    # Native Linux defaults
    set(SUSHI_WITH_JACK_DEFAULT ON)
    set(SUSHI_WITH_RASPA_DEFAULT OFF)
    set(SUSHI_WITH_PORTAUDIO_DEFAULT OFF)
    set(SUSHI_WITH_APPLE_COREAUDIO_DEFAULT OFF)
    set(SUSHI_WITH_ALSA_MIDI_DEFAULT ON)
    set(SUSHI_WITH_RT_MIDI_DEFAULT OFF)
    set(SUSHI_WITH_LV2_DEFAULT ON)
    set(SUSHI_WITH_LV2_MDA_TESTS_DEFAULT ON)
    set(SUSHI_WITH_UNIT_TESTS_DEFAULT ON)
    set(SUSHI_BUILD_TWINE_DEFAULT ON)
endif()

option(SUSHI_WITH_RASPA "Enable Raspa (xenomai) support" ${SUSHI_WITH_RASPA_DEFAULT})
option(SUSHI_WITH_JACK "Enable Jack support" ${SUSHI_WITH_JACK_DEFAULT})
option(SUSHI_WITH_PORTAUDIO "Enable PortAudio support" ${SUSHI_WITH_PORTAUDIO_DEFAULT})
option(SUSHI_WITH_APPLE_COREAUDIO "Enable Apple CoreAudio support" ${SUSHI_WITH_APPLE_COREAUDIO_DEFAULT})
option(SUSHI_WITH_ALSA_MIDI "Enable alsa midi support" ${SUSHI_WITH_ALSA_MIDI_DEFAULT})
option(SUSHI_WITH_RT_MIDI "Enable RtMidi support" ${SUSHI_WITH_RT_MIDI_DEFAULT})
option(SUSHI_WITH_VST2 "Enable Vst 2 support" ${SUSHI_WITH_VST2_DEFAULT})
option(SUSHI_WITH_VST3 "Enable Vst 3 support" ${SUSHI_WITH_VST3_DEFAULT})
option(SUSHI_LINK_VST3 "Link Vst 3 library to Sushi" ${SUSHI_LINK_VST3_DEFAULT})
option(SUSHI_WITH_LV2 "Enable LV2 support" ${SUSHI_WITH_LV2_DEFAULT})
option(SUSHI_WITH_LV2_MDA_TESTS "Include unit tests depending on LV2 drobilla MDA plugin port." ${SUSHI_WITH_LV2_MDA_TESTS_DEFAULT})
option(SUSHI_WITH_UNIT_TESTS "Build and run unit tests after compilation" ${SUSHI_WITH_UNIT_TESTS_DEFAULT})
option(SUSHI_WITH_LINK "Enable Ableton Link support" ${SUSHI_WITH_LINK_DEFAULT})
option(SUSHI_WITH_RPC_INTERFACE "Enable RPC control support" ${SUSHI_WITH_RPC_INTERFACE_DEFAULT})
option(SUSHI_BUILD_TWINE "Build included Twine library" ${SUSHI_BUILD_TWINE_DEFAULT})
option(SUSHI_TWINE_STATIC "Link against static version of TWINE library" ${SUSHI_TWINE_STATIC_DEFAULT})
option(SUSHI_WITH_SENTRY "Enable sentry.io support" ${SUSHI_WITH_SENTRY_DEFAULT})
option(SUSHI_SENTRY_DSN "Required Sentry DSN Path" ${SUSHI_SENTRY_DSN_DEFAULT})
option(SUSHI_DISABLE_MULTICORE_UNIT_TESTS "Disable unit-tests dependent on multi-core processing." ${SUSHI_DISABLE_MULTICORE_UNIT_TESTS_DEFAULT})
option(SUSHI_BUILD_STANDALONE_APP "Build standalone Sushi executable" ${SUSHI_BUILD_STANDALONE_APP_DEFAULT})
option(SUSHI_BUILD_WITH_SANITIZERS "Build Sushi with google address sanitizer on" ${SUSHI_BUILD_WITH_SANITIZERS_DEFAULT})
option(SUSHI_LINK_WITH_PIPEWIRE "Link sushi with pipewire, only use if linking with a rasba build with Pipewire support" OFF)

set(SUSHI_AUDIO_BUFFER_SIZE ${SUSHI_AUDIO_BUFFER_SIZE_DEFAULT} CACHE STRING "Set internal audio buffer size in frames")
set(SUSHI_RASPA_FLAVOR ${SUSHI_RASPA_FLAVOR_DEFAULT} CACHE STRING "Set raspa flavor. Options are xenomai or evl")

if (SUSHI_WITH_ALSA_MIDI AND SUSHI_WITH_RT_MIDI)
    message(FATAL_ERROR "Both alsa midi and RtMidi set to on. Use only one midi frontend at a time")
endif()

if (SUSHI_WITH_RASPA)
    # Determine raspa evl/xenomai variables
    if (${SUSHI_RASPA_FLAVOR} MATCHES "evl")
        message("Building with Raspa/Twine EVL support")
        set(TWINE_WITH_EVL ON CACHE BOOL "" FORCE)
    elseif (${SUSHI_RASPA_FLAVOR} MATCHES "xenomai")
        message("Building with Raspa/Twine Xenomai support.")
        message("Warning Xenomai 3 support is deprecated and will be removed in future versions")
        set(TWINE_WITH_XENOMAI ON CACHE BOOL "" FORCE)
    else ()
        message(FATAL_ERROR "Raspa flavor should be set to xenomai or evl")
    endif()
endif()

###############################
# Sub-directory configuration #
###############################

if (${SUSHI_BUILD_TWINE})
    set(TWINE_WITH_TESTS OFF CACHE BOOL "")
    add_subdirectory(twine)

    if (${SUSHI_TWINE_STATIC})
        set(TWINE_LIB twine::twine_static)
    else()
        set(TWINE_LIB twine::twine)
    endif()
    set(EXTRA_BUILD_LIBRARIES ${EXTRA_BUILD_LIBRARIES} ${TWINE_LIB})
else()
    find_package(twine 1.1)
    set(INCLUDE_DIRS ${INCLUDE_DIRS} ${TWINE_PATH})
    set(EXTRA_BUILD_LIBRARIES ${EXTRA_BUILD_LIBRARIES} ${TWINE_LIB})
    find_package(elk-warning-suppressor 0.1.0 COMPONENTS warningSuppressor)
endif()

set(ELKLOG_WITH_UNIT_TESTS OFF CACHE BOOL "")
set(ELKLOG_USE_INCLUDED_TWINE OFF CACHE BOOL "")
set(ELKLOG_TWINE_STATIC ${SUSHI_TWINE_STATIC} CACHE STRING "")
set(ELKLOG_WITH_EXAMPLES OFF CACHE BOOL "")
set(ELKLOG_MULTITHREADED_RT_LOGGING OFF CACHE BOOL "")
set(ELKLOG_FILE_SIZE 10000000 CACHE STRING "")
set(ELKLOG_RT_MESSAGE_SIZE 2048 CACHE STRING "")
set(ELKLOG_RT_QUEUE_SIZE 1024 CACHE STRING "")

add_subdirectory(elklog)

add_subdirectory(third-party EXCLUDE_FROM_ALL)

###############
# Raspa setup #
###############

if (${SUSHI_WITH_RASPA})
    find_library(RASPA_LIB
            NAMES raspa
            PATHS /usr/lib /usr/local/lib
            )
    set(EXTRA_BUILD_LIBRARIES ${EXTRA_BUILD_LIBRARIES} ${RASPA_LIB} asound)
    set(EXTRA_COMPILE_DEFINITIONS ${EXTRA_COMPILE_DEFINITIONS} -DSUSHI_BUILD_WITH_RASPA)

    if (${SUSHI_LINK_WITH_PIPEWIRE})
        set(EXTRA_BUILD_LIBRARIES ${EXTRA_BUILD_LIBRARIES} pipewire-0.3)
    endif()

    if (NOT "$ENV{CMAKE_SYSROOT}" STREQUAL "")
        set(CMAKE_SYSROOT "$ENV{CMAKE_SYSROOT}")
        message("ENV_CMAKE_SYSROOT = " $ENV{CMAKE_SYSROOT})
    endif()

    # Determine whether to link with evl or cobalt lib
    if (${SUSHI_RASPA_FLAVOR} MATCHES "xenomai")

        # External libraries:
        # explicitly link with cobalt lib
        set(XENOMAI_BASE_DIR "/usr/xenomai" CACHE STRING "xenomai base dir path")

        if (NOT "$ENV{CMAKE_SYSROOT}" STREQUAL "")
            set(CMAKE_SYSROOT "$ENV{CMAKE_SYSROOT}")
            message("ENV_CMAKE_SYSROOT = " $ENV{CMAKE_SYSROOT})
        endif()

        if (NOT "${CMAKE_SYSROOT}" STREQUAL "")
            set(XENOMAI_BASE_DIR "${CMAKE_SYSROOT}/usr/xenomai")
            message("XENOMAI_BASE_DIR is " ${XENOMAI_BASE_DIR})
        endif()

        find_library(COBALT_LIB cobalt HINTS ${XENOMAI_BASE_DIR}/lib)
        set(EXTRA_BUILD_LIBRARIES ${EXTRA_BUILD_LIBRARIES} ${COBALT_LIB})

    elseif (${SUSHI_RASPA_FLAVOR} MATCHES "evl")
        message("Building with EVL support")
        find_library(EVL_LIB
            NAMES evl
            PATHS /usr/lib /usr/local/lib
            )
        set(EXTRA_BUILD_LIBRARIES ${EXTRA_BUILD_LIBRARIES} ${EVL_LIB})
    endif()
endif()

##############
# Jack setup #
##############

if (${SUSHI_WITH_JACK})
    message("Building with Jack support.")

    # Linked libraries
    find_path(jack_dir NAMES "jack/jack.h")
    find_library(jack_lib NAMES jack)
    set(INCLUDE_DIRS ${INCLUDE_DIRS} ${jack_dir})
    set(EXTRA_BUILD_LIBRARIES ${EXTRA_BUILD_LIBRARIES} ${jack_lib})

    # Compile definitions
    set(EXTRA_COMPILE_DEFINITIONS ${EXTRA_COMPILE_DEFINITIONS} -DSUSHI_BUILD_WITH_JACK)
endif()

###################
# PortAudio setup #
###################

if (${SUSHI_WITH_PORTAUDIO})
    message("Building with PortAudio support.")

    set(EXTRA_BUILD_LIBRARIES ${EXTRA_BUILD_LIBRARIES} PortAudio)

    # Compile definitions
    set(EXTRA_COMPILE_DEFINITIONS ${EXTRA_COMPILE_DEFINITIONS} -DSUSHI_BUILD_WITH_PORTAUDIO)
endif()

if (APPLE)
    set(EXTRA_COMPILE_DEFINITIONS ${EXTRA_COMPILE_DEFINITIONS} -DSUSHI_APPLE_THREADING)

    ###################
    # CoreAudio setup #
    ###################

    if (${SUSHI_WITH_APPLE_COREAUDIO})
        message("Building with Apple CoreAudio support.")

        # Compile definitions
        set(EXTRA_COMPILE_DEFINITIONS ${EXTRA_COMPILE_DEFINITIONS} -DSUSHI_BUILD_WITH_APPLE_COREAUDIO)

        set(ADDITIONAL_APPLE_COREAUDIO_SOURCES  src/audio_frontends/apple_coreaudio/apple_coreaudio_utils.cpp
                                                src/audio_frontends/apple_coreaudio/apple_coreaudio_object.cpp
                                                src/audio_frontends/apple_coreaudio/apple_coreaudio_device.mm)

        set(EXTRA_BUILD_LIBRARIES ${EXTRA_BUILD_LIBRARIES} "-framework CoreAudio -framework Foundation")
    endif()
endif()

###################
# Alsa midi setup #
###################

if (${SUSHI_WITH_ALSA_MIDI})
    message("Building with alsa midi support.")

    # Additional sources
    set(MIDI_SOURCES src/control_frontends/alsa_midi_frontend.h src/control_frontends/alsa_midi_frontend.cpp)

    # linked libraries
    find_path(ALSA_DIR NAMES "alsa/asoundlib.h")
    find_library(ALSA_LIB NAMES asound)
    set(INCLUDE_DIRS ${INCLUDE_DIRS} ${ALSA_DIR})
    set(EXTRA_BUILD_LIBRARIES ${EXTRA_BUILD_LIBRARIES} ${ALSA_LIB})

    # Compile definitions
    set(EXTRA_COMPILE_DEFINITIONS ${EXTRA_COMPILE_DEFINITIONS} -DSUSHI_BUILD_WITH_ALSA_MIDI)
endif()

################
# RtMidi setup #
################

if (${SUSHI_WITH_RT_MIDI})
    message("Building with RtMidi support.")

    # Additional sources
    set(MIDI_SOURCES ${MIDI_SOURCES} src/control_frontends/rt_midi_frontend.cpp src/control_frontends/rt_midi_frontend.h)

    #RtMidi library
    find_package(RtMidi CONFIG REQUIRED)

    set(EXTRA_BUILD_LIBRARIES ${EXTRA_BUILD_LIBRARIES} RtMidi::rtmidi)

    set(EXTRA_COMPILE_DEFINITIONS ${EXTRA_COMPILE_DEFINITIONS} -DSUSHI_BUILD_WITH_RT_MIDI)
endif()

###############
# VST 2 setup #
###############

if (${SUSHI_WITH_VST2})
    message("Building with Vst2 support.")

    set(ADDITIONAL_VST2_SOURCES src/library/vst2x/vst2x_wrapper.h
                                src/library/vst2x/vst2x_host_callback.h
                                src/library/vst2x/vst2x_plugin_loader.h
                                src/library/vst2x/vst2x_midi_event_fifo.h
                                src/library/vst2x/vst2x_processor_factory.h
                                src/library/vst2x/vst2x_wrapper.cpp
                                src/library/vst2x/vst2x_host_callback.cpp
                                src/library/vst2x/vst2x_plugin_loader.cpp)

    # Include dirs
    if (VST_2_SDK_BASE_DIR)
        set(SUSHI_VST2_SDK_PATH ${VST_2_SDK_BASE_DIR})
    else()
        find_file(SUSHI_VST2_SDK_PATH NAMES VST2_SDK vstsdk2.4 HINTS $ENV{HOME}/workspace
                                                                     $ENV{HOME}/workspace/VST_SDK
                                                                     $ENV{HOME}/workspace/vstsdk3610_11_06_2018_build_37)
    endif()
    if (${SUSHI_VST2_SDK_PATH} STREQUAL "VST2_SDK_PATH-NOTFOUND")
        message("Warning! Could not find Steinberg SDK for VST 2.4")
    endif()

    set(INCLUDE_DIRS ${INCLUDE_DIRS} ${SUSHI_VST2_SDK_PATH}/pluginterfaces/vst2.x)

    # Compile definitions
    set(EXTRA_COMPILE_DEFINITIONS ${EXTRA_COMPILE_DEFINITIONS} -DSUSHI_BUILD_WITH_VST2 -D__cdecl=)
endif()

###############
# VST 3 setup #
###############

# TODO: use this ${SUSHI_LINK_VST3}, and when it's off, link to VST3 SDK included by JUCE.
if (${SUSHI_WITH_VST3})
    message("Building with Vst3 support.")

    # Vst 3 host:
    # Build the given Vst3 host implementation into a separate library to avoid
    # Vst specific defines leaking into our code.

    set(VST3_SDK_PATH "${PROJECT_SOURCE_DIR}/third-party/vst3sdk")
    set(VST3_HOST_SOURCES
            "${VST3_SDK_PATH}/public.sdk/source/vst/hosting/eventlist.cpp"
            "${VST3_SDK_PATH}/public.sdk/source/vst/hosting/parameterchanges.cpp"
            "${VST3_SDK_PATH}/public.sdk/source/vst/hosting/hostclasses.cpp"
            "${VST3_SDK_PATH}/public.sdk/source/vst/hosting/module.cpp"
            "${VST3_SDK_PATH}/public.sdk/source/vst/utility/stringconvert.cpp"
            "${VST3_SDK_PATH}/public.sdk/source/vst/hosting/pluginterfacesupport.cpp"
            "${VST3_SDK_PATH}/public.sdk/source/common/memorystream.cpp")

    if (MSVC)
        set(VST3_HOST_SOURCES ${VST3_HOST_SOURCES} "${VST3_SDK_PATH}/public.sdk/source/vst/hosting/module_win32.cpp")
    endif()

    if(NOT MSVC)
        set(VST3_COMPILE_FLAGS "-Wno-unused-parameter \
                                -Wno-extra \
                                -Wno-deprecated \
                                -Wno-cpp \
                                -Wno-pointer-bool-conversion \
                                -Wno-suggest-override \
                                -Wno-deprecated-declarations \
                                -Wno-shorten-64-to-32 \
                                -Wformat=0")
    endif()

    if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
        set(VST3_HOST_SOURCES ${VST3_HOST_SOURCES} "${VST3_SDK_PATH}/public.sdk/source/vst/hosting/module_linux.cpp")
        set(AUDIOHOST_PLATFORM_LIBS)
    endif()

    if (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
        set(VST3_HOST_SOURCES
            ${VST3_HOST_SOURCES}
            "${VST3_SDK_PATH}/public.sdk/source/vst/hosting/module_mac.mm")
        set(AUDIOHOST_PLATFORM_LIBS "-framework Cocoa")
        set(VST3_COMPILE_FLAGS "${VST3_COMPILE_FLAGS} -fobjc-arc -Wno-unqualified-std-cast-call")
    endif()

    add_library(vst3_host STATIC ${VST3_HOST_SOURCES})
    target_link_libraries(vst3_host PRIVATE ${AUDIOHOST_PLATFORM_LIBS} elk_vst3_extensions)
    set_target_properties(vst3_host PROPERTIES EXCLUDE_FROM_ALL true)
    target_compile_features(vst3_host PUBLIC cxx_std_20)
    if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
        set_target_properties(vst3_host PROPERTIES COMPILE_FLAGS "-DRELEASE ${VST3_COMPILE_FLAGS}")
    else()
        set_target_properties(vst3_host PROPERTIES COMPILE_FLAGS "-DDEVELOPMENT ${VST3_COMPILE_FLAGS}")
    endif()

    target_include_directories(vst3_host PRIVATE "${PROJECT_SOURCE_DIR}/third-party/vst3sdk")
    add_dependencies(vst3_host sdk)

    # Set sources
    set(ADDITIONAL_VST3_SOURCES src/library/vst3x/vst3x_wrapper.h
                                src/library/vst3x/vst3x_host_app.h
                                src/library/vst3x/vst3x_utils.h
                                src/library/vst3x/vst3x_processor_factory.h
                                src/library/vst3x/vst3x_wrapper.cpp
                                src/library/vst3x/vst3x_host_app.cpp
                                src/library/vst3x/vst3x_utils.cpp
                                src/library/vst3x/vst3x_file_utils.cpp)

    # Linked libraries
    set(EXTRA_BUILD_LIBRARIES ${EXTRA_BUILD_LIBRARIES} vst3_host sdk elk_vst3_extensions)

    # Compiler definitions
    set(EXTRA_COMPILE_DEFINITIONS ${EXTRA_COMPILE_DEFINITIONS} -DSUSHI_BUILD_WITH_VST3)


    # In yocto env / cross compiling scenarios, this is not needed as mda-vst3 plugins are
    # built already. Also, this causes an "exec-format" error since the plugins need a specific
    # method of compilation during cross compilation process.
    if (NOT CMAKE_CROSSCOMPILING)
        # Triggering mda-vst3 build - used by sample sushi json configurations under misc/config_files.
        set_target_properties(mda-vst3 PROPERTIES EXCLUDE_FROM_ALL False)
    endif()
endif()

#############
# LV2 setup #
#############

if (${SUSHI_WITH_LV2})
    message("Building with LV2 support.")

    find_package(lv2 CONFIG REQUIRED)
    find_package(PkgConfig REQUIRED)
    pkg_check_modules(LILV REQUIRED IMPORTED_TARGET lilv-0)

    set(ADDITIONAL_LV2_SOURCES src/library/lv2/lv2_wrapper.h
                               src/library/lv2/lv2_control.h
                               src/library/lv2/lv2_features.h
                               src/library/lv2/lv2_host_nodes.h
                               src/library/lv2/lv2_model.h
                               src/library/lv2/lv2_port.h
                               src/library/lv2/lv2_state.h
                               src/library/lv2/lv2_processor_factory.h
                               src/library/lv2/lv2_wrapper.cpp
                               src/library/lv2/lv2_state.cpp
                               src/library/lv2/lv2_worker.cpp
                               src/library/lv2/lv2_features.cpp
                               src/library/lv2/lv2_model.cpp
                               src/library/lv2/lv2_port.cpp
                               src/library/lv2/lv2_control.cpp)

    # Linked libraries
    set(EXTRA_BUILD_LIBRARIES ${EXTRA_BUILD_LIBRARIES} PkgConfig::LILV lv2_host)

    # Compiler definitions
    set(EXTRA_COMPILE_DEFINITIONS ${EXTRA_COMPILE_DEFINITIONS} -DSUSHI_BUILD_WITH_LV2)
endif()

##############
# gRPC setup #
##############

if (${SUSHI_WITH_RPC_INTERFACE})
    message("Building with RPC support.")

    add_subdirectory(rpc_interface)

    # Linked libraries
    set(EXTRA_BUILD_LIBRARIES ${EXTRA_BUILD_LIBRARIES} sushi_rpc)

    # Compiler definitions
    set(EXTRA_COMPILE_DEFINITIONS ${EXTRA_COMPILE_DEFINITIONS} -DSUSHI_BUILD_WITH_RPC_INTERFACE)
endif()

######################
# Ableton link setup #
######################

if (${SUSHI_WITH_LINK})
    message("Building with Ableton Link support.")

    include(third-party/link/AbletonLinkConfig.cmake)

    # Linked libraries
    set(EXTRA_BUILD_LIBRARIES ${EXTRA_BUILD_LIBRARIES} Ableton::Link)

    # Compiler definitions
    set(EXTRA_COMPILE_DEFINITIONS ${EXTRA_COMPILE_DEFINITIONS} -DSUSHI_BUILD_WITH_ABLETON_LINK)
endif()

message("Configured audio buffer size: " ${SUSHI_AUDIO_BUFFER_SIZE} " samples")

###################
# sentry.io setup #
###################

if (${SUSHI_WITH_SENTRY})
    find_package(Threads)
    find_package(ZLIB)
    find_package(sentry CONFIG REQUIRED)

    message("Building with sentry.io support.")

    if (NOT SUSHI_SENTRY_DSN)
        set(SUSHI_SENTRY_DSN ${SUSHI_SENTRY_DSN_DEFAULT} CACHE STRING "The DSN to upload the sentry logs and crash reports to, from Sushi" FORCE)
    endif()

    set(SENTRY_CRASHPAD_HANDLER_PATH "${VCPKG_INSTALLED_DIR}/osx-custom/tools/sentry-native/crashpad_handler")

    set(EXTRA_BUILD_LIBRARIES ${EXTRA_BUILD_LIBRARIES} sentry::sentry)
    set(EXTRA_COMPILE_DEFINITIONS ${EXTRA_COMPILE_DEFINITIONS} -DSUSHI_BUILD_WITH_SENTRY -DSUSHI_SENTRY_DSN="${SUSHI_SENTRY_DSN}")
endif()


####################
#  Main Target     #
####################

set(SOURCE_FILES
    src/utils.cpp
    src/audio_frontends/base_audio_frontend.cpp
    src/concrete_sushi.cpp
    src/audio_frontends/offline_frontend.cpp
    src/audio_frontends/reactive_frontend.cpp
    src/audio_frontends/jack_frontend.cpp
    src/audio_frontends/portaudio_frontend.cpp
    src/audio_frontends/apple_coreaudio_frontend.cpp
    src/audio_frontends/portaudio_devices_dump.cpp
    src/audio_frontends/coreaudio_devices_dump.cpp
    src/audio_frontends/xenomai_raspa_frontend.cpp
    src/audio_frontends/offline_frontend.cpp
    src/audio_frontends/reactive_frontend.cpp
    src/control_frontends/base_control_frontend.cpp
    src/control_frontends/oscpack_osc_messenger.cpp
    src/control_frontends/reactive_midi_frontend.cpp
    src/control_frontends/osc_frontend.cpp
    src/dsp_library/biquad_filter.cpp
    src/engine/audio_engine.cpp
    src/engine/audio_graph.cpp
    src/engine/event_dispatcher.cpp
    src/engine/track.cpp
    src/engine/midi_dispatcher.cpp
    src/engine/json_configurator.cpp
    src/engine/receiver.cpp
    src/engine/event_timer.cpp
    src/engine/transport.cpp
    src/engine/parameter_manager.cpp
    src/engine/processor_container.cpp
    src/engine/plugin_library.cpp
    src/engine/controller/controller.cpp
    src/engine/controller/system_controller.cpp
    src/engine/controller/transport_controller.cpp
    src/engine/controller/timing_controller.cpp
    src/engine/controller/keyboard_controller.cpp
    src/engine/controller/audio_graph_controller.cpp
    src/engine/controller/parameter_controller.cpp
    src/engine/controller/program_controller.cpp
    src/engine/controller/midi_controller.cpp
    src/engine/controller/audio_routing_controller.cpp
    src/engine/controller/cv_gate_controller.cpp
    src/engine/controller/osc_controller.cpp
    src/engine/controller/session_controller.cpp
    src/engine/controller/real_time_controller.cpp
    src/factories/base_factory.cpp
    src/factories/reactive_factory.cpp
    src/factories/reactive_factory_implementation.cpp
    src/factories/standalone_factory.cpp
    src/factories/standalone_factory_implementation.cpp
    src/factories/offline_factory.cpp
    src/factories/offline_factory_implementation.cpp
    src/library/event.cpp
    src/library/midi_decoder.cpp
    src/library/midi_encoder.cpp
    src/library/internal_plugin.cpp
    src/library/performance_timer.cpp
    src/library/parameter_dump.cpp
    src/library/processor.cpp
    src/library/processor_state.cpp
    src/library/plugin_registry.cpp
    src/library/internal_processor_factory.cpp
    src/library/lv2/lv2_processor_factory.cpp
    src/library/vst2x/vst2x_processor_factory.cpp
    src/library/vst3x/vst3x_processor_factory.cpp
    src/plugins/arpeggiator_plugin.cpp
    src/plugins/control_to_cv_plugin.cpp
    src/plugins/cv_to_control_plugin.cpp
    src/plugins/gain_plugin.cpp
    src/plugins/lfo_plugin.cpp
    src/plugins/passthrough_plugin.cpp
    src/plugins/equalizer_plugin.cpp
    src/plugins/freeverb_plugin.cpp
    src/plugins/peak_meter_plugin.cpp
    src/plugins/return_plugin.cpp
    src/plugins/sample_player_plugin.cpp
    src/plugins/sample_player_voice.cpp
    src/plugins/sample_delay_plugin.cpp
    src/plugins/send_plugin.cpp
    src/plugins/send_return_factory.cpp
    src/plugins/step_sequencer_plugin.cpp
    src/plugins/transposer_plugin.cpp
    src/plugins/wav_streamer_plugin.cpp
    src/plugins/wav_writer_plugin.cpp
    src/plugins/mono_summing_plugin.cpp
    src/plugins/stereo_mixer_plugin.cpp
    src/plugins/brickworks/compressor_plugin.cpp
    src/plugins/brickworks/cab_sim_plugin.cpp
    src/plugins/brickworks/ring_mod_plugin.cpp
    src/plugins/brickworks/bitcrusher_plugin.cpp
    src/plugins/brickworks/wah_plugin.cpp
    src/plugins/brickworks/eq3band_plugin.cpp
    src/plugins/brickworks/phaser_plugin.cpp
    src/plugins/brickworks/chorus_plugin.cpp
    src/plugins/brickworks/vibrato_plugin.cpp
    src/plugins/brickworks/flanger_plugin.cpp
    src/plugins/brickworks/combdelay_plugin.cpp
    src/plugins/brickworks/saturation_plugin.cpp
    src/plugins/brickworks/noise_gate_plugin.cpp
    src/plugins/brickworks/tremolo_plugin.cpp
    src/plugins/brickworks/notch_plugin.cpp
    src/plugins/brickworks/multi_filter_plugin.cpp
    src/plugins/brickworks/highpass_plugin.cpp
    src/plugins/brickworks/clip_plugin.cpp
    src/plugins/brickworks/fuzz_plugin.cpp
    src/plugins/brickworks/dist_plugin.cpp
    src/plugins/brickworks/drive_plugin.cpp
    src/plugins/brickworks/simple_synth_plugin.cpp
)

add_library(${PROJECT_NAME} STATIC "${SOURCE_FILES}"
                                   "${ADDITIONAL_APPLE_COREAUDIO_SOURCES}"
                                   "${ADDITIONAL_VST2_SOURCES}"
                                   "${ADDITIONAL_VST3_SOURCES}"
                                   "${ADDITIONAL_LV2_SOURCES}"
                                   "${MIDI_SOURCES}")

set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE CXX)

#########################
#  Include Directories  #
#########################

set(INCLUDE_DIRS ${INCLUDE_DIRS}
                 "${PROJECT_SOURCE_DIR}/src"
                 "${PROJECT_SOURCE_DIR}"
                 "${PROJECT_SOURCE_DIR}/third-party/vst3sdk"
                 "${PROJECT_SOURCE_DIR}/third-party/link/include"
                 "${PROJECT_SOURCE_DIR}/third-party/brickworks/include"
)


set(PUBLIC_INCLUDE_DIRS "${CMAKE_BINARY_DIR}" # for generated version.h
                        "${PROJECT_SOURCE_DIR}/third-party/optionparser/"
                        "${PROJECT_SOURCE_DIR}/third-party/rapidjson/include")

#################################
#  Linked libraries             #
#################################

find_package(SndFile CONFIG REQUIRED)

set(COMMON_LIBRARIES
    SndFile::sndfile
    fifo
    oscpack
    elklog
    freeverb
    elk::warningSuppressor
    ${TWINE_LIB}
)

if(NOT MSVC)
    set(COMMON_LIBRARIES ${COMMON_LIBRARIES} pthread dl)

    set_target_properties(oscpack PROPERTIES COMPILE_FLAGS "-Wno-deprecated-declarations")
endif()

if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
    set(COMMON_LIBRARIES ${COMMON_LIBRARIES} atomic)
endif()

target_include_directories(${PROJECT_NAME}
        PRIVATE
            ${INCLUDE_DIRS}
        PUBLIC
            ${PUBLIC_INCLUDE_DIRS}
            # where top-level project will look for the library's public headers
            $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
)

target_link_libraries(${PROJECT_NAME} PUBLIC ${EXTRA_BUILD_LIBRARIES} ${COMMON_LIBRARIES})

####################################
#  Compiler Flags and definitions  #
####################################

if(MSVC)
    # C5045: Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified
    #        is disabled for all - Spectre is not a concern for Sushi I don't think.

    # C4996: Deprecated warning. This was flooding the terminal,
    #        I might remove the suppression from here eventually, and out into the code again.
    target_compile_options(${PROJECT_NAME} PRIVATE /wd4996 /wd5045)
else ()
    target_compile_options(${PROJECT_NAME} PUBLIC -Wall -Wextra -Wno-psabi -fPIC -ffast-math)

    target_compile_options(${PROJECT_NAME} PRIVATE -fno-rtti)

    if (SUSHI_BUILD_WITH_SANITIZERS)
        target_compile_options(${PROJECT_NAME}  PUBLIC -fsanitize=address -g)
    endif()
endif()

target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_20)
target_compile_definitions(${PROJECT_NAME} PUBLIC -DSUSHI_CUSTOM_AUDIO_CHUNK_SIZE=${SUSHI_AUDIO_BUFFER_SIZE} ${EXTRA_COMPILE_DEFINITIONS})

#####################
#  Sub projects     #
#####################

if (${SUSHI_BUILD_STANDALONE_APP})
    add_subdirectory(apps)
endif()

######################
#  Tests subproject  #
######################

if (${SUSHI_WITH_UNIT_TESTS})
    add_subdirectory(test)
endif()


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to Elk Audio OS

## Github Issues

You can open a Github issue to signal a bug or request a new feature. Please don't create an issue to ask about general help, use the [Elk Audio Forum](https://forum.elk.audio) for generic questions and assistance.

When writing a bug report, try to be as complete as you can regarding the context:
  * Mention the version of Elk Audio OS that you are testing
  * What is your run-time setup (plugins, buffer size, audio/CV channels, sensors, etc.)
  * (if working on a plugin) what is your build environment
  * If the issue is about SUSHI, TWINE or a plugin, try to reproduce it with the SUSHI AppImage for Linux or using another audio frontend (offline, dummy)
  * Include relevant files that helps understand your issue or, better, to reproduce it

## Submitting a PR

A signed Contributor Agreement (CA) is required for submitting Pull Requests to this repository. Please contact tech@elk.audio for more information.



================================================
FILE: COPYING
================================================
                    GNU AFFERO GENERAL PUBLIC LICENSE
                       Version 3, 19 November 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.

  The licenses for most software and other practical works are designed
to take away your freedom to share and change the works.  By contrast,
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.

  Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.

  A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate.  Many developers of free software are heartened and
encouraged by the resulting cooperation.  However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.

  The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community.  It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server.  Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.

  An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals.  This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.

  The precise terms and conditions for copying, distribution and
modification follow.

                       TERMS AND CONDITIONS

  0. Definitions.

  "This License" refers to version 3 of the GNU Affero General Public License.

  "Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.

  "The Program" refers to any copyrightable work licensed under this
License.  Each licensee is addressed as "you".  "Licensees" and
"recipients" may be individuals or organizations.

  To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy.  The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.

  A "covered work" means either the unmodified Program or a work based
on the Program.

  To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy.  Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.

  To "convey" a work means any kind of propagation that enables other
parties to make or receive copies.  Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.

  An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License.  If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.

  1. Source Code.

  The "source code" for a work means the preferred form of the work
for making modifications to it.  "Object code" means any non-source
form of a work.

  A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.

  The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form.  A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.

  The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities.  However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work.  For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.

  The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.

  The Corresponding Source for a work in source code form is that
same work.

  2. Basic Permissions.

  All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met.  This License explicitly affirms your unlimited
permission to run the unmodified Program.  The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work.  This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.

  You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force.  You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright.  Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.

  Conveying under any other circumstances is permitted solely under
the conditions stated below.  Sublicensing is not allowed; section 10
makes it unnecessary.

  3. Protecting Users' Legal Rights From Anti-Circumvention Law.

  No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.

  When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.

  4. Conveying Verbatim Copies.

  You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.

  You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.

  5. Conveying Modified Source Versions.

  You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:

    a) The work must carry prominent notices stating that you modified
    it, and giving a relevant date.

    b) The work must carry prominent notices stating that it is
    released under this License and any conditions added under section
    7.  This requirement modifies the requirement in section 4 to
    "keep intact all notices".

    c) You must license the entire work, as a whole, under this
    License to anyone who comes into possession of a copy.  This
    License will therefore apply, along with any applicable section 7
    additional terms, to the whole of the work, and all its parts,
    regardless of how they are packaged.  This License gives no
    permission to license the work in any other way, but it does not
    invalidate such permission if you have separately received it.

    d) If the work has interactive user interfaces, each must display
    Appropriate Legal Notices; however, if the Program has interactive
    interfaces that do not display Appropriate Legal Notices, your
    work need not make them do so.

  A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit.  Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.

  6. Conveying Non-Source Forms.

  You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:

    a) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by the
    Corresponding Source fixed on a durable physical medium
    customarily used for software interchange.

    b) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by a
    written offer, valid for at least three years and valid for as
    long as you offer spare parts or customer support for that product
    model, to give anyone who possesses the object code either (1) a
    copy of the Corresponding Source for all the software in the
    product that is covered by this License, on a durable physical
    medium customarily used for software interchange, for a price no
    more than your reasonable cost of physically performing this
    conveying of source, or (2) access to copy the
    Corresponding Source from a network server at no charge.

    c) Convey individual copies of the object code with a copy of the
    written offer to provide the Corresponding Source.  This
    alternative is allowed only occasionally and noncommercially, and
    only if you received the object code with such an offer, in accord
    with subsection 6b.

    d) Convey the object code by offering access from a designated
    place (gratis or for a charge), and offer equivalent access to the
    Corresponding Source in the same way through the same place at no
    further charge.  You need not require recipients to copy the
    Corresponding Source along with the object code.  If the place to
    copy the object code is a network server, the Corresponding Source
    may be on a different server (operated by you or a third party)
    that supports equivalent copying facilities, provided you maintain
    clear directions next to the object code saying where to find the
    Corresponding Source.  Regardless of what server hosts the
    Corresponding Source, you remain obligated to ensure that it is
    available for as long as needed to satisfy these requirements.

    e) Convey the object code using peer-to-peer transmission, provided
    you inform other peers where the object code and Corresponding
    Source of the work are being offered to the general public at no
    charge under subsection 6d.

  A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.

  A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling.  In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage.  For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product.  A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.

  "Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source.  The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.

  If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information.  But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).

  The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed.  Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.

  Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.

  7. Additional Terms.

  "Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law.  If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.

  When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it.  (Additional permissions may be written to require their own
removal in certain cases when you modify the work.)  You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.

  Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:

    a) Disclaiming warranty or limiting liability differently from the
    terms of sections 15 and 16 of this License; or

    b) Requiring preservation of specified reasonable legal notices or
    author attributions in that material or in the Appropriate Legal
    Notices displayed by works containing it; or

    c) Prohibiting misrepresentation of the origin of that material, or
    requiring that modified versions of such material be marked in
    reasonable ways as different from the original version; or

    d) Limiting the use for publicity purposes of names of licensors or
    authors of the material; or

    e) Declining to grant rights under trademark law for use of some
    trade names, trademarks, or service marks; or

    f) Requiring indemnification of licensors and authors of that
    material by anyone who conveys the material (or modified versions of
    it) with contractual assumptions of liability to the recipient, for
    any liability that these contractual assumptions directly impose on
    those licensors and authors.

  All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10.  If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term.  If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.

  If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.

  Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.

  8. Termination.

  You may not propagate or modify a covered work except as expressly
provided under this License.  Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).

  However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.

  Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.

  Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License.  If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.

  9. Acceptance Not Required for Having Copies.

  You are not required to accept this License in order to receive or
run a copy of the Program.  Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance.  However,
nothing other than this License grants you permission to propagate or
modify any covered work.  These actions infringe copyright if you do
not accept this License.  Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.

  10. Automatic Licensing of Downstream Recipients.

  Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License.  You are not responsible
for enforcing compliance by third parties with this License.

  An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations.  If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.

  You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License.  For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.

  11. Patents.

  A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based.  The
work thus licensed is called the contributor's "contributor version".

  A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version.  For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.

  Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.

  In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement).  To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.

  If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients.  "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.

  If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.

  A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License.  You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.

  Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.

  12. No Surrender of Others' Freedom.

  If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all.  For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.

  13. Remote Network Interaction; Use with the GNU General Public License.

  Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software.  This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.

  Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work.  The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.

  14. Revised Versions of this License.

  The Free Software Foundation may publish revised and/or new versions of
the GNU Affero General Public License from time to time.  Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

  Each version is given a distinguishing version number.  If the
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation.  If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.

  If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.

  Later license versions may give you additional or different
permissions.  However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.

  15. Disclaimer of Warranty.

  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. Limitation of Liability.

  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

  17. Interpretation of Sections 15 and 16.

  If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.

Also add information on how to contact you by electronic and paper mail.

  If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source.  For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code.  There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.

  You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
<https://www.gnu.org/licenses/>.

================================================
FILE: HISTORY.md
================================================
## 1.3.0
New Features:
  * Tracks can be explicitly allocated to threads
  * Send and return plugins are now zero delay under some conditions
  * Updated vcpkg
  * Send and return plugins are now zero-delay if on the same cpu core
  * Vst3 extension apis
  * Updated gRPC api with versioning and command completion notifications
  * Updated example config files to use initial state instead of events
  * String properties can now be output only, i.e. not settable by Sushi

Fixes:
  * Warning if multiple twine workers are allocated to the same cpu core
  * Fixes for CMake 4
  * Updates for deprecated features in C++20
  * Refactored processor channel config to be less stateful
  * Fixed issue with VST2 plugins with > 16 channels
  * Vst3 non-automatable parameter bug fixed
  * Vst3 32 bit crash on load fixed

## 1.2.0

New Features:
  * Support for using Sushi as a library
  * Windows support
  * C++20 support
  * Updated Elklog
  * Updated Twine to 1.0
  * Warning suppressor library included

Fixes:
  * Improved handling of audio pause / resume
  * Xrun detection in audio frontends
  * Improved handling of processor add/delete if audio thread is not running
  * Better event lifetime management
  * EventDispatcher thread could stall if system clock changed
  * Fix for Vst2 plugins with > 16 channels
  * All example config files now uses "initial_state" to set initial parameter values

## 1.1.0

New features:
  * Added Apple CoreAudio frontend
  * Support for aggregate devices
  * Brickworks plugin suite added
  * Wave Streamer plugin
  * Freeverb plugin
  * TWINE updated to 0.4.0 with workgroup and EVL support
  * Rapidjson updated to latest master branch
  * Optimised State changes for VST3 plugins
  * Crash logging with Sentry
  * Device dump now includes sample rate and buffer size support

Fixes:
  * LV2 worker request space too small
  * LV2 logging not handled correctly
  * Incorrect velocity scaling on Midi output from LV2 plugins
  * VST3 plugin initialization order fix
  * Parameter notification fix
  * Incorrect file length display in WaveStreamer plugin
  * Seek precision fix in WaveStreamer plugin
  * Audio channel setup now only called when plugin is disabled
  * Send and return crash at exit

Breaking changes:
  * The argument --dump-portaudio-devs is changed to --dump-audio-devices and now requires a frontend to be specified (--coreaudio or --portaudio).
  * Failure to set priority and/or workgroup on macOS will cause Sushi to exit.

## 1.0.0

New features:
  * clang 13+ support
  * gcc 10+ support
  * macOS support
  * VST2 & VST3 bundle support for macOS
  * Portaudio frontend
  * RtMIDI frontend
  * MIDI clock output
  * Processor state save & reload
  * Plugin binary state setting
  * Session state save & reload
  * Refactor track modes w.r.t. channel configuration
  * "pre" and "post" tracks to process engine channels before/after dispatching them to tracks
  * Audio frontends pause/restart
  * Switch from liblo to oscpack for OSC
  * Option to set target OSC IP
  * Channel specification in send&return internal plugins
  * Extended parameter notifications, now multiple controllers can be updated easily at the same time
  * LV2 parameter output support
  * Command-line switches to disable OSC and gRPC
  * Use vcpkg to manage most of third-party dependencies
  * Refactored CMake configuration, now using SUSHI_ for options prefix
  * Ableton Link updated to v3.0.5
  * TWINE updated to v0.3.2
  * VST3 SDK updated to v3.7.6

Fixes:
  * Workaround for delayed ALSA MIDI event output
  * Crash in MIDI dispatcher when deleting track connections
  * Various JSON parsing fixes
  * Memory leak in VST3 wrapper
  * Issue with setting different samplerate from JSON and audio frontend
  * Slow response to large numbers of VST3 parameter changes
  * Peakmeter formatted level parameter scaling

Breaking changes:
  * All build options renamed to SUSHI_XXX_YYY from XXX_YYY
  * Vcpgk initalization step required at first build. See README.md
  * Track channel config has been simplified. The json "mode" member has been replaced with an integer "channels" member. To create a multibus track, an additional member "multibus" must be set to true and the number of buses specified with the "buses" member.
  * Tracks now only report number of channels (and buses in the multibus case) and input and output channels and busses are assumed to be the same.
  * All instances of "busses" in json config and grpc api has been corrected to "buses"

## 0.12.0

New Features:
  * Internal send and return plugins
  * Stereo mixer internal plugin
  * Sample delay internal plugin
  * Multi channel support in peak meter plugin
  * Timing and transport notifications
  * Processor properties support
  * Master limiter
  * Updated VST SDK to v3.7.3
  * Updated Twine to v0.2.1
  * Build support for GCC10

Fixes:
  * gRPC segfault on exit
  * Refactored plugin instantiation architecture
  * Track noise for tracks with no audio input
  * Bug where events outputted before the audio process callback were lost
  * Race condition in OSC path registration
  * LV2 plugin load crash

## 0.11.0

New Features:
  * Expanded gRPC control interface, including push-style notifications
  * Bumped recommended gRPC version
  * Dynamic loading and routing of tracks and plugins
  * Configurable OSC parameter output
  * Wav writer plugin
  * Mono summing plugin
  * Improved peak meter plugin

Fixes:
  * Aftertouch messages not forwarded in Alsa midi frontend
  * Ensuring silence when track gain is 0
  * Fix for generate script when python2.7 is missing
  * Fix to accommodate v1.16 and v1.24 of gRPC libraries
  * Raspa frontend initialisation order fix
  * Internal event system refactor
  * Controller class refactor and split into sub-controllers
  * Logging library built statically - faster compile time
  * Fix for timing sensitive unit tests
  * Audio routing bug for mono tracks

## 0.10.3

Fixes:
  * Mono tracks can now be connected to stereo output busses
  * OSC paths for gain and pan controls on tracks work again

## 0.10.2

Fixes:
  * LV2 parameter handling fix for non-sequential parameter ids

## 0.10.1

New Features:
  * LV2 worker thread extension support
  * Parameter values are now always normalised

Fixes:
  * LV2 string parameter value fix

## 0.10.0

New Features:
  * LV2 plugin support
  * Ableton Link support
  * Multiple midi input and output ports
  * Extended OSC control API making it more similar to gRPC

Fixes:
  * Updated example configuration files

## 0.9.1

New Features:
  * Plugin information dump with CL switch
  * Updated VST 3 SDK to latest 3.14

Fixes:
  * Allows plugin parameters with duplicate names
  * Events section not required anymore with any frontend

## 0.9.0

New Features:
  * CV and Gate support + related example plugins
  * Step sequencer example plugin
  * gRPC listening address configurable through command line

Fixes:
  * Parameter Units now passed correctly
  * Faster Json file loading
  * Better Json parsing error printing
  * Removed Raspalib submodule
  * Unit test fixes

## 0.8.0

New Features:
  * gRPC control API
  * Automatic clip detection on master tracks
  * Smooth track parameter controls at audio rate
  * Simple MIDI transposer internal plugin
  * Support relative mode for MIDI CCs mapping
  * (x86 / XMOS) : support in RASPA for USB Midi gadget
  * VST 2.x support is now an optional build feature
  * Support VST 3 programs
  * Added an option to automatically flush the logs at a periodic interval

Fixes:
  * TWINE: Automatic denormal handling in all threads
  * Raspa: fix for affinity of non-RT threads after initialization
  * Raspa on x86/XMOS: fixes for spurious startup synchronization
  * MIDI: explicitly convert NoteON with zero velocity to NoteOFF messages
  * Various VST 3 fixes
  * Log file can now be specified at any location
  * VST 2.x : allow host callback functions to be called during plugin initialization

## 0.7.0

  * Multicore track rendering through Twine library
  * Processor performance timings statistics
  * Dummy frontend for investigating RT safety issues in plugins

## 0.6.2

  * Fix RASPA plugin initialization issue
  * Fix parameter output from VST 2.x plugins

## 0.6.1

  * Fix: handling of track pan for multichannel plugins
  * Fix: erroneous channel handling for offline frontend

## 0.6

  * Multichannel track/buses architecture and support for VST multichannel plugins
  * Handling of events and MIDI outputs from plugins
  * Time information handling
  * Scheduling of asynchronous tasks from internal plugins
  * Arpeggiator and peak meter internal plugins
  * Many fixes and improvements to RASPA frontend and VST wrappers

## 0.5.1

  * RASPA Xenomai frontend
  * Multichannel I/O from audio frontends

## 0.5

  * VST 3.6 wrapper
  * Dynamic plugin loading

## 0.4

  * VST 2.4 wrapper
  * Xenomai offline frontend
  * More advanced MIDI routing and mapping

## 0.3

  * JACK audio frontend
  * MIDI support
  * OSC control

## 0.2

  * Events handling
  * Internal plugins (gain, eq, sampler)

## 0.1

  * Initial version
  * Offline frontend with I/O with libsndfile


================================================
FILE: LICENSE.md
================================================
#Licensing information

All SUSHI code is Copyright © 2017-2023 [Elk Audio AB], formerly [Modern Ancient Instruments Networked AB] (“Elk”) and is licensed under the [https://www.gnu.org/licenses/agpl-3.0.en.html](GNU Affero General Public License v.3) (“AGPLv3”). Such SUSHI code is considered the “Program” within the meaning of the AGPLv3.

Loading plugins or libraries into the Program, or statically or dynamically linking or interfacing other applications, plugins, or libraries with the Program, including through a network API, is making a combined work based on the Program. Thus, the AGPLv3 covers the entire combination. You may therefore propagate, convey, or make available over a network, this combined work only in full compliance with the AGPLv3, including compliance with the obligation to provide the Corresponding Source (as that term is defined and used in the AGPLv3) for this entire combination.

As a special exception, Elk gives you permission to combine the Program with plugins, libraries or applications that are either:

 * made available by you under the GNU General Public License v2 or v3, or the GNU Lesser General Public License v2 or v3; or

 * made available by you without charge or royalty under other open source or proprietary terms, regardless of whether such terms conflict or are incompatible with the AGPLv3, but only if you make available to any requesting party the Corresponding Source of such plugins, libraries, or applications without charge under license terms that permit commercial royalty-free use, modification and distribution.

This exception is an additional permission under section 7 of the AGPLv3.

#Additional Notes

The Elk name, design, and logo are trademarks or registered trademarks of Elk Audio AB. No permission to use is granted, except that you may use “[for Elk Audio OS]” for promotion of your plugin and “[Elk Powered]” for redistributions of modified versions. For any other uses, please contact  info@elk.audio.

================================================
FILE: README.md
================================================
# SUSHI
Headless plugin host for ELK Audio OS.

## Sushi as Library
Sushi can be used as a standalone terminal application, and can now also be used as a library.

For more information on the latter, refer to the [LIBRARY.md] (docs/LIBRARY.md) file in this repository.

## Usage

The Sushi standalone project, and consequently the produced binary, reside in the `./apps/` sub-folder of this repository.

See `sushi -h` for a complete list of options.
Common use cases are:

Test in offline mode with I/O from audio file:

    $ sushi -o -i input_file.wav -c config_file.json

Use Core Audio on macOS for realtime audio, with the default devices:

    $ sushi --coreaudio -c config_file.json

Use JACK for realtime audio:

    $ sushi -j -c config_file.json

With JACK, Sushi creates 8 virtual input and output ports that you can connect to other programs or system outputs.

## Sushi macOS
Since version 1.0, Sushi can be built natively for macOS as a native binary with all the dependencies statically linked to it.

There is a new Core Audio frontend (selectable with the `--coreaudio` command-line option) to interface directly with Core Audio. As an alternative, a Portaudio frontend is also available (with the `--portaudio` flag).

With Core Audio, you can select other devices than the default with the `--audio-input-device-uid` and `--audio-output-device-uid` options. To find out the right number there, you can launch Sushi with the `--dump-audio-devices` together with `--coreaudio` to get a list in JSON format printed to stdout.

MIDI support is provided through RtMidi and can access CoreMidi devices directly.

LV2 support is currently not available for macOS.

## Sushi Windows
Since version 1.2, Sushi can be built natively for Windows.

The suggested audio frontend for Windows is Portaudio (selectable with the `--portaudio` option), which can use most available sound device apis on Windows. You can select which devices to use with the `--audio-input-device` and `--audio-output-device` options. As with Core Audio, to find the id corresponding to a device, launch Sushi with the `--dump-audio-devices` option together with `--portaudio` to get a JSON formatted list printed to stdout.

By default, Portaudio does not support Asio, to build with Asio support, pass the `-DPA_USE_ASIO=ON` flag to cmake. This will download and build the Asio SDK automatically.

LV2 support is currently not available for Windows.

## Example Sushi configuration files in repository
Under `misc/config_files` in this repository, we have a large variety of example Sushi configuration files.

The first one to try to check if everything is running properly, would be this one that uses the internal sequencer & synthesizer to generate a sequence:
```
$ ./sushi --coreaudio -c config_files/play_brickworks_synth.json
```
(on Linux with JACK, replace `--coreaudio` with `--jack`).

Many of the examples use the mda-vst3 plugins which are built when building Sushi. If you are running one of the prebuilt packages (available on the releases sections on GitHub), you have everything inside the `sushi` folder there. For example, on macOS you should be able to get a simple working synthesizer with:

Otherwise, if you are building from source, the plugins used by the examples can be found under:

`build/debug/VST3/Debug`, or `build/release/VST3/Release` respectively, for debug and release builds.

To run Sushi with an example configuration, you simply invoke it while pointing to one of the above paths.

On Ubuntu that could be:
```
$ ./sushi -j -c ../../misc/config_files/play_vst3.json --base-plugin-path VST3/Debug
```

Or, from a macOS terminal:
```
$ ./sushi --coreaudio -c ../../misc/config_files/play_vst3.json --base-plugin-path VST3/Release
```

## Extra documentation
Configuration files are used for global host configs, track and plugins configuration, MIDI routing and mapping, events sequencing.

More in-depth documentation is available at the [Elk Audio OS official docs page](https://elk-audio.github.io/elk-docs/html/sushi/index.html).

## Building
Sushi builds are supported for native Linux systems, Yocto/OE cross-compiling toolchains targeting Elk Audio OS systems, and macOS.

Make sure that Sushi is cloned with the `--recursive` flag to fetch all required submodules for building. Alternatively run `git submodule update --init --recursive` after cloning.

Sushi requires a compiler with support for C++17 features. The recommended compilers are GCC version 10 or higher, and clang version 13 or higher.

### Native Linux dependencies
Sushi handles most dependencies with vcpkg (or as submodules) and will build and link with them automatically. A few dependencies are not included however and must be provided or installed system-wide. See the list below (debian packages names):

  * libasound2-dev

  * libjack-jackd2-dev

  * For VST 2:
      * Vst 2.4 SDK - Needs to be provided externally as it is not available from Steinberg anymore.

  * For LV2:
      * liblilv-dev - at least version 0.24.4. Lilv is an official wrapper for LV2.
      * lilv-utils - at least version 0.24.5.
      * lv2-dev - at least version 1.18.2. The main LV2 library.

        The official Ubuntu repositories do not have these latest versions at the time of writing. The best source for them is instead the [KX Studio repositories, which you need to enable manually](https://kx.studio/Repositories).

      * For LV2 unit tests:
          * lv2-examples - at least version 1.18.2.
          * mda-lv2 - at least version 1.2.4 of [drobilla's port](http://drobilla.net/software/mda-lv2/) - not that from Mod Devices or others.

### Building with vcpkg (native Linux & macOS)
To build from a terminal, use the commands below. Vcpkg also integrates nicely with CLion and other IDEs though must manually set the toolchain file.

```
$ mkdir build && cd build 
$ ../third-party/vcpkg/bootstrap-vcpkg.sh
$ cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../third-party/vcpkg/scripts/buildsystems/vcpkg.cmake ..
$ make 
```

This might take a while the first time since all the vcpkg dependencies will have to be built first.

**Note:** if using Cmake 4 on MacOS, you might need to set the environment variable SDKROOT to *macosx* in order to build the vcpkg dependencies correctly:
```
SDKROOT=macosx cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../third-party/vcpkg/scripts/buildsystems/vcpkg.cmake ..
```
### Building with vcpkg (Windows)
Building on Windows is similar to Posix and macOS, with the addition of the triplet configuration.
To build from a terminal, use the commands below. Vcpkg also integrates nicely with CLion and Visual Studio, though you must manually set the toolchain file for vcpkg integration.

````
$ mkdir build ; cd build
$ ../third-party/vcpkg/bootstrap-vcpkg.bat
$ cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE="../third-party/vcpkg/scripts/buildsystems/vcpkg.cmake" -DVCPKG_OVERLAY_TRIPLETS="../triplets/" -DVCPKG_TARGET_TRIPLET=win-custom-x86-64 ..
$ cmake --build ./ --config Release
````

### Building with Yocto for Elk Audio OS
Sushi can be built either with the provided [Elk Audio OS SDK](https://github.com/elk-audio/elkpi-sdk), or as part of a [full Elk Audio OS image build with bitbake](https://github.com/elk-audio/elk-audio-os-builder).

Follow the instructions in those repositories to set up a cross-compiling SDK and build Sushi for a given target.

### Useful CMake build options
Option                                | Value    | Notes
--------------------------------------|----------|------------------------------------------------------------------------------------------------------
SUSHI_AUDIO_BUFFER_SIZE               | 8 - 512  | The buffer size used in the audio processing. Needs to be a power of 2 (8, 16, 32, 64, 128...).
SUSHI_WITH_RASPA                      | on / off | Build Sushi with Xenomai RT-kernel support, only for ElkPowered hardware.
SUSHI_WITH_JACK                       | on / off | Build Sushi with Jack Audio support, only for standard Linux distributions and macOS.
SUSHI_WITH_PORTAUDIO                  | on / off | Build Sushi with Portaudio support.
SUSHI_WITH_APPLE_COREAUDIO            | on / off | Build Sushi with Apple Core Audio support.
SUSHI_WITH_ALSA_MIDI                  | on / off | Build Sushi with Alsa sequencer support for MIDI (Linux only).
SUSHI_WITH_RT_MIDI                    | on / off | Build Sushi with RtMidi support for MIDI. Cannot be selected if SUSHI_WITH_ALSA_MIDI is set.
SUSHI_WITH_LINK                       | on / off | Build Sushi with Ableton Link support.
SUSHI_WITH_VST2                       | on / off | Include support for loading Vst 2.x plugins in Sushi.
SUSHI_WITH_VST3                       | on / off | Include support for loading Vst 3.x plugins in Sushi.
SUSHI_LINK_VST3                       | on / off | Link Vst3 SDK (statically) if Vst3 is included. Turn this off if Sushi is linked statically as a library, into an application which already links Vst3's SDK.
SUSHI_WITH_LV2                        | on / off | Include support for loading LV2 plugins in Sushi.
SUSHI_WITH_RPC_INTERFACE              | on / off | Build gRPC external control interface, requires gRPC development files.
SUSHI_BUILD_TWINE                     | on / off | Build and link with the included version of [TWINE](https://github.com/elk-audio/twine), otherwise tries to link with system wide if the option is disabled.
SUSHI_TWINE_STATIC                    | on / off | Link statically against TWINE (not recommended, useful only in a few cases).
SUSHI_WITH_UNIT_TESTS                 | on / off | Build and run unit tests together with building Sushi.
SUSHI_WITH_LV2_MDA_TESTS              | on / off | Include LV2 unit tests which depends on the LV2 drobilla port of the mda plugins being installed. 
SUSHI_VST2_SDK_PATH                   | path     | Path to external Vst 2.4 SDK. Not included and required if WITH_VST2 is enabled.
SUSHI_WITH_SENTRY                     | on / off | Build Sushi with Sentry error logging support.
SUSHI_SENTRY_DSN                      | url      | URL to the default value for the Sushi Sentry logging DSN. This can still be passed as a runtime terminal argument.
SUSHI_DISABLE_MULTICORE_UNIT_TESTS    | on / off | Disable unit-tests dependent on multi-core processing.
SUSHI_BUILD_STANDALONE_APP            | on / off | Build standalone Sushi executable.
SUSHI_BUILD_WITH_SANITIZERS           | on / off | Build Sushi with google address sanitizer on. Default is off.
The default values for many of the options are platform-specific (native Linux, Yocto/OE, macOS).

_Note_:

before version 1.0, the CMake options didn't have the `SUSHI_` prefix. The old names (e.g. `WITH_JACK`) are not supported anymore and should be changed to the new format.

## Running Unit tests separately
Some Sushi's unit tests depend on test data, which is found through the environment variable `SUSHI_TEST_DATA_DIR`.
You will need to define this if you want to run the unit test explicitly, e.g. while debugging:

`$ export SUSHI_TEST_DATA_DIR=/path/to/sushi/repo/test/data`

Moreover, the battery of tests for VST3 plugin support, build and use the example plugins of the VST3 SDK.
While the automated tests running as part of the build find these plugins automatically, when running the `unit_tests` binary manually, you may need to set the working directory to: `/path/to/sushi/build_folder_name/test`,
for the path to resolve correctly.

## License
Sushi is licensed under Affero General Public License (“AGPLv3”). See [LICENSE](LICENSE.md) document for the full details of the license. For contributing code to Sushi, see [CONTRIBUTING.md](CONTRIBUTING.md).

Copyright 2017-2023 Elk Audio AB, Stockholm, Sweden.



================================================
FILE: apps/CMakeLists.txt
================================================

######################
#  Executable target #
######################

set(APP_FILES main.cpp)

if(APPLE)
    add_executable(sushi MACOSX_BUNDLE ${APP_FILES})
else()
    add_executable(sushi ${APP_FILES})
endif()

####################################
#  Compiler Flags and definitions  #
####################################

if(MSVC)
    # C4996: Deprecated warning. This was flooding the terminal,
    #        I might remove the suppression from here eventually,
    #        and out into the code again.
    set(SUSHI_COMPILE_OPTIONS /W4 /fp:fast /wd4996)
    set(APP_LINK_LIBRARIES ${APP_LINK_LIBRARIES} winmm.lib) # oscpack GetCurrentTimeMs
else()
    set(SUSHI_COMPILE_OPTIONS -Wall -Wextra -Wno-psabi -fPIC -fno-rtti -ffast-math)
endif()

target_compile_options(sushi PRIVATE ${SUSHI_COMPILE_OPTIONS})

target_link_libraries(sushi PRIVATE sushi_library ${APP_LINK_LIBRARIES})

####################
#  Install         #
####################

set(DOC_FILES_INSTALL
        "${PROJECT_SOURCE_DIR}/LICENSE.md"
        "${PROJECT_SOURCE_DIR}/README.md"
        "${PROJECT_SOURCE_DIR}/HISTORY.md"
        )

if (APPLE)
    # TODO: fix to work when not submodule
    install(CODE [[
    include(BundleUtilities)
    fixup_bundle("${CMAKE_INSTALL_PREFIX}/sushi/sushi.app" "" "")
    ]] COMPONENT Runtime)
endif()

### Custom command to copy the dynamic dependencies to the binary folder
#   Mainly for twine.dll because windows cannot find it from ../twine but
#   needs it in the same directory
if (MSVC)
    add_custom_command(TARGET sushi POST_BUILD
            COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_RUNTIME_DLLS:sushi> $<TARGET_FILE_DIR:sushi>
            COMMAND_EXPAND_LISTS)
endif()

install(TARGETS sushi RUNTIME DESTINATION bin BUNDLE DESTINATION Applications)
foreach(ITEM ${DOC_FILES_INSTALL})
    install(FILES ${ITEM} DESTINATION share/sushi/doc)
endforeach()


================================================
FILE: apps/main.cpp
================================================
/*
 * Copyright 2017-2023 Elk Audio AB
 *
 * SUSHI is free software: you can redistribute it and/or modify it under the terms of
 * the GNU Affero General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * SUSHI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE. See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License along with
 * SUSHI. If not, see http://www.gnu.org/licenses/
 */

/**
 * @brief Main entry point to Sushi
 * @copyright 2017-2023 Elk Audio AB, Stockholm
 */

#include <iostream>
#include <csignal>
#include <condition_variable>

#include "elklog/static_logger.h"

#include "sushi/utils.h"
#include "sushi/parameter_dump.h"
#include "sushi/portaudio_devices_dump.h"
#include "sushi/coreaudio_devices_dump.h"
#include "sushi/sushi.h"
#include "sushi/terminal_utilities.h"
#include "sushi/standalone_factory.h"
#include "sushi/offline_factory.h"

using namespace sushi;

ELKLOG_GET_LOGGER_WITH_MODULE_NAME("main");

/**
 * These are used for signalling that Sushi should exit, from across threads.
 * In main(), Sushi waits on this condition variable to exit.
 */
bool exit_flag = false;
std::condition_variable exit_notifier;

bool exit_condition()
{
    return exit_flag;
}

/**
 *  By invoking this method, you can signal to Sushi to exit,
 *  either through passing it to the standard signal(...) method,
 *  or through calling it directly in the code, e.g. when coming upon an unrecoverable error.
 *  When invoking this, Sushi will still wind down, cleanly close allocated resources, and flush logs.
 * @param sig the signal, e.g. SIGINT, SIGTERM.
 */
void exit_on_signal([[maybe_unused]] int sig)
{
    exit_flag = true;
    exit_notifier.notify_one();
}

/**
 * If the error encountered is so severe as to require immediate exit, invoke this, instead of exit_on_signal.
 * @param message
 */
void error_exit(const std::string& message, sushi::Status status)
{
    std::cerr << message << std::endl;
    int error_code = static_cast<int>(status);
    std::exit(error_code);
}

/**
 * Tries to start Sushi
 * @param options a SushiOptions structure
 * @return a Sushi instance, if successful - if not, the unique_ptr is empty.
 */
std::unique_ptr<Sushi> start_sushi(SushiOptions options);

void pipe_signal_handler([[maybe_unused]] int sig)
{
    ELKLOG_LOG_INFO("Pipe signal received and ignored: {}", sig);
}

static void print_sushi_headline()
{
    std::cout << "SUSHI - Copyright 2017-2023 Elk Audio AB, Stockholm" << std::endl;
    std::cout << "SUSHI is licensed under the Affero GPL 3.0. Source code is available at github.com/elk-audio" << std::endl;
}

int main(int argc, char* argv[])
{
    signal(SIGINT, exit_on_signal);
    signal(SIGTERM, exit_on_signal);
#ifndef _MSC_VER
    signal(SIGPIPE, pipe_signal_handler);
#endif
    
    // option_parser accepts arguments excluding program name,
    // so skip it if it is present.
    if (argc > 0)
    {
        argc--;
        argv++;
    }

    SushiOptions options;

    options.config_source = sushi::ConfigurationSource::FILE;

    auto option_status = parse_options(argc, argv, options);
    if (option_status == ParseStatus::ERROR)
    {
        return 1;
    }
    else if (option_status == ParseStatus::MISSING_ARGUMENTS)
    {
        return 2;
    }
    else if (option_status == ParseStatus::EXIT)
    {
        return 0;
    }

    init_logger(options);

    if (options.enable_audio_devices_dump)
    {
        if (options.frontend_type == FrontendType::PORTAUDIO)
        {
#ifdef SUSHI_BUILD_WITH_PORTAUDIO
            std::cout << sushi::generate_portaudio_devices_info_document() << std::endl;
            return 0;
#else
            std::cerr << "SUSHI not built with Portaudio support, cannot dump devices." << std::endl;
#endif
        }
        else if (options.frontend_type == FrontendType::APPLE_COREAUDIO)
        {
#ifdef SUSHI_BUILD_WITH_APPLE_COREAUDIO
            std::cout << sushi::generate_coreaudio_devices_info_document() << std::endl;
#else
            std::cerr << "SUSHI not built with Apple CoreAudio support, cannot dump devices." << std::endl;
#endif
            return 0;
        }
        else
        {
            std::cout << "No frontend specified or specified frontend not supported (please specify ." << std::endl;
            return 1;
        }
    }

    auto sushi = start_sushi(options);

    if (sushi == nullptr)
    {
        return -1;
    }

    if (options.frontend_type != FrontendType::OFFLINE)
    {
        std::mutex m;
        std::unique_lock<std::mutex> lock(m);
        exit_notifier.wait(lock, exit_condition);
    }

    sushi->stop();

    ELKLOG_LOG_INFO("Sushi exiting normally!");

    return 0;
}

std::unique_ptr<Sushi> start_sushi(SushiOptions options)
{
    std::unique_ptr<FactoryInterface> factory;

    if (options.frontend_type == FrontendType::DUMMY ||
        options.frontend_type == FrontendType::OFFLINE)
    {
        factory = std::make_unique<OfflineFactory>();
    }
    else if (options.frontend_type == FrontendType::JACK ||
             options.frontend_type == FrontendType::XENOMAI_RASPA ||
             options.frontend_type == FrontendType::APPLE_COREAUDIO ||
             options.frontend_type == FrontendType::PORTAUDIO)
    {
        factory = std::make_unique<StandaloneFactory>();
    }
    else
    {
        error_exit("Invalid frontend configuration. Reactive, or None, are not supported when standalone.",
                   Status::FRONTEND_IS_INCOMPATIBLE_WITH_STANDALONE);
    }

    // Initialising:

    auto [sushi, status] = factory->new_instance(options);

    if (status == Status::FAILED_OSC_FRONTEND_INITIALIZATION)
    {
        error_exit("Instantiating OSC server on port " + std::to_string(options.osc_server_port) + " failed.",
                   status);
    }
    else if (status != Status::OK)
    {
        auto message = to_string(status);
        if (status == Status::FAILED_INVALID_FILE_PATH)
        {
            message.append(options.config_filename);
        }

        error_exit(message, status);
    }

    if (options.enable_parameter_dump)
    {
        std::cout << sushi::generate_processor_parameter_document(sushi->controller());
        std::cout << "Parameter dump completed - exiting." << std::endl;
        std::exit(EXIT_SUCCESS);
    }
    else
    {
        print_sushi_headline();
    }

    // ...and starting:

    auto start_status = sushi->start();

    if (start_status == Status::OK)
    {
        return std::move(sushi);
    }
    else if (start_status == Status::FAILED_TO_START_RPC_SERVER)
    {
        sushi.reset();

        error_exit("Failure starting gRPC server on address " + options.grpc_listening_address, status);
    }

    return nullptr;
}

================================================
FILE: bitbucket-pipelines.yml
================================================
# Only use spaces to indent your .yml configuration.
# -----
# You can specify a custom docker image from Docker Hub as your build environment.
image: ubuntu:24.04

pipelines:
  default:
    - step:
        name: Build sushi + tests

        size: 4x

        caches:
          - vcpkg

        script:
          # Prepare system.
          - apt-get update -y
          - apt install build-essential -y
          - apt-get install -y -q libjack-jackd2-dev liblo-dev
          - apt-get install -y -q libsndfile1-dev libasound2-dev
          - apt-get install -y -q cmake git make
          - apt-get install -y -q curl zip unzip tar
          - apt-get install -y -q libgrpc++-dev protobuf-compiler-grpc
          - apt-get install -y -q liblilv-dev lilv-utils lv2-dev lv2-examples mda-lv2
          - apt-get install -y software-properties-common
          - add-apt-repository -y ppa:ubuntu-toolchain-r/test
          - export LV2_PATH=$HOME/.lv2:/usr/local/lib/lv2:/usr/lib/lv2

          # Prepare dependencies
          # Rewrite the relative submodule url as bitbucket doesn't handle relative paths correctly
          - sed -i 's/url = \.\.\(.*\)/url = git@bitbucket.org:'$BITBUCKET_TEAM'\1/g' .gitmodules
          - git submodule update --init --recursive
          # Set test data dir (for running unit test manually)
          - export SUSHI_TEST_DATA_DIR=$PWD/test/data
          # Set the number of cores to use when building
          - export BUILD_CORES=8
          # Boostrap vcpkg
          - export VCPKG_BINARY_SOURCES="clear;files,$(pwd)/vcpkgcache,readwrite"
          - ./third-party/vcpkg/bootstrap-vcpkg.sh
          - mkdir build
          - cd build
          - cmake -DCMAKE_TOOLCHAIN_FILE=../third-party/vcpkg/scripts/buildsystems/vcpkg.cmake -DWITH_XENOMAI=FALSE -DWITH_JACK=TRUE -DWITH_VST2=OFF -DSUSHI_WITH_PORTAUDIO=ON -DWITH_LV2=ON -DWITH_LV2_MDA_TESTS=ON -DTWINE_WITH_XENOMAI=OFF -DSUSHI_BUILD_WITH_SANITIZERS=OFF ..

          # Build multiple configuration and run unit tests
          # Build sushi and unit tests with default options and default buffer size (64 samples)
          - make sushi -j${BUILD_CORES}
          - make unit_tests -j${BUILD_CORES}
          # Run unit tests with some tests test disabled
          - cd test
          - ./unit_tests --gtest_filter=-TestAudioGraph.TestMultiCoreOperation:TestLv2Wrapper.TestSynchronousStateAndWorkerThreads:TestLv2Wrapper.TestMidiEventInputAndOutput
          - cd ..

          # Build with buffers size 32 samples
          - cmake -DSUSHI_AUDIO_BUFFER_SIZE=32 ..
          - make sushi -j${BUILD_CORES}
          - make unit_tests -j${BUILD_CORES}
          - cd test
          - ./unit_tests --gtest_filter=-TestAudioGraph.TestMultiCoreOperation:TestLv2Wrapper.TestSynchronousStateAndWorkerThreads:TestLv2Wrapper.TestMidiEventInputAndOutput
          - cd ..

          # Build with buffer size 128 samples
          - cmake -DSUSHI_AUDIO_BUFFER_SIZE=128 ..
          - make sushi -j${BUILD_CORES}
          - make unit_tests -j${BUILD_CORES}
          - cd test
          - ./unit_tests --gtest_filter=-TestAudioGraph.TestMultiCoreOperation:TestLv2Wrapper.TestSynchronousStateAndWorkerThreads:TestLv2Wrapper.TestMidiEventInputAndOutput
          - cd ..

          # Quick smoke test (not really working yet)
          #- ./sushi -d -c ../../misc/config_files/config_play.json&
          #- sleep 6
          #- pkill sushi

          # Build with most options disabled to test compile time configuration
          - cmake -DAUDIO_BUFFER_SIZE=64 -DSUSHI_WITH_VST2=OFF -DSUSHI_WITH_VST3=OFF -DSUSHI_WITH_LV2=OFF -DSUSHI_WITH_LV2_MDA_TESTS=OFF -DSUSHI_WITH_RT_MIDI=ON -DSUSHI_WITH_ALSA_MIDI=OFF -DSUSHI_WITH_PORTAUDIO=OFF ..
          - make sushi -j4
          - make unit_tests -j${BUILD_CORES}
          - cd test
          - ./unit_tests --gtest_filter=-TestAudioGraph.TestMultiCoreOperation
          - cd ..

definitions:
  caches:
    vcpkg: vcpkgcache


================================================
FILE: docs/LIBRARY.md
================================================
# Sushi as a Library
Using Sushi as a statically linked library is a newly developed feature.

We have considered two primary use-cases for Sushi as a library:

**Reactive:** 

Sushi running inside a plugin / other audio host, which provides the audio and MIDI frontends, passing on audio and MIDI to Sushi.

**Active:** 

Allowing the creation of standalone audio-hosts, which embed Sushi, but expand on the functionality of the terminal application we provide in `/apps`.

For the Reactive use-case, we have developed new frontends for audio and MIDI in Sushi, designed to be Reactive, as well as a new "Real-Time" Controller interface using which the necessary Sushi control is available in the audio callback. These are still in their first incarnation, and while they are definitely usable in production, they are currently missing features. That’s also why these files may still contain “TODO’s” as placeholders - to be removed as the features they refer to are added.

For the Active use-case, there are no such limitations - the full Sushi functionality is available. 

## The main limitations for the Reactive use-case are currently that:
* Sushi can only work with stereo audio I/O.
* Sushi's audio buffer size is set at compile time, using the CMake argument SUSHI_AUDIO_BUFFER_SIZE. But an audio host may have a dynamic buffer-size setting. If the buffer size doesn't match, the host needs to handle that, ensuring Sushi is only ever given audio buffers of the size defined at build-time.
* MIDI I/O to Sushi from a containing host application is not currently real-time, but asynchronous, meaning MIDI and audio synchronisation is not sample-accurate.
* For any control commands to be processes by Sushi, it needs to be receiving audio buffers regularly. When no audio callbacks are received, Sushi will also not process and control commands (e.g. those received over gRPC and OSC).

## Using Sushi as a library
For using Sushi as a library, you only need to be aware of the header files contained in the include/sushi folder, where Sushi's API is exposed. The internals are hidden away.

Some of those headers are useful only when Sushi is Passive, others only when it's Active, and others for both cases.

## Common API for Reactive and Active

Sushi has several compile-time arguments and dependencies, which apply equally to the library and standalone use. These are documented in the main [README.md](../README.md) of this repository, and will not be repeated here.

### Instantiation

The main Sushi API is defined in sushi.h.

All options for instantiating Sushi are collected in the struct **SushiOptions**. Some of its fields are enum classes - which are then also defined in sushi.h.

This file also contains the main abstract base-class for Sushi, which however cannot be instantiated directly. Instead, one of the provided factories needs to be used. Simply create a factory, and invoke the below method, passing your populated SushiOptions struct:

```c++
std::pair<std::unique_ptr<Sushi>, Status> new_instance(SushiOptions& options) override;
```

It will return a std::pair, of either a valid Sushi instance, and Status::OK, or an empty std::unique_ptr, and the Status of why instantiation failed.

Note that the SushiOptions is passed by reference to new_instance, because its contents are *suggestions*, which may be overridden if needed - in which case your options struct instance will be updated to reflect the changes made.

### Controlling during run-time

#### C++ Control API

The main control interface is exposed in **control_interface.h**.

Note that none of those classes can be instantiated directly. They are created internally in Sushi, and their instances are accessed through the **Sushi::Controller()** method, which returns a pointer to a **SushiControl** instance, that in turn will hold instances for all the interfaces defined in control_interface.h:

```C++
control::SushiControl* controller();
```

It's important to note that none of these interfaces are real-time safe. That means they are not safely callable from within an audio-callback, but should be invoked from a separate thread altogether. Sushi then schedules their effect internally so that they do not interfere with the real-time audio callback.

The C++ control API in control_interface.h is extensive and will not be further documented here. It is written so that it should be intuitively self-explanatory.

#### Remote Control API

Additionally, Sushi can be controlled over gRPC and OSC, which are both unchanged in the "sushi as library" implementation - see the documentation for this in the main [README.md](../README.md) of this repository, and the [Elk Audio GitHub page with detaled documentation](https://elk-audio.github.io/elk-docs/html/index.html).

Once Sushi is instantiated, subsequent steps vary depending on the use-case.

## Reactive use-case

You will need the following fields:

```C++
sushi::SushiOptions _sushi_options;
std::unique_ptr<sushi::RtController> _rt_controller;
std::unique_ptr<sushi::Sushi> _sushi;
sushi::ChunkSampleBuffer _sushi_buffer_in;
sushi::ChunkSampleBuffer _sushi_buffer_out;
```

### Starting Reactive Sushi

For the Reactive use-case, fetch the **RtController** from a **ReactiveFactory** instance (Sushi factories are single-use). Assuming Sushi has started successfully, this will be a non-null std::unique_ptr, meaning you are taking over the ownership of the controller.

RtController is named as such because its methods are safe to invoke during a real-time audio callback.

```C++
sushi::ReactiveFactory factory;
auto [sushi, status] = factory.new_instance(_sushi_options);
_sushi = std::move (sushi);
_rt_controller = factory.rt_controller();
```

If you are going to use MIDI, pass a callback Lambda to it through your RtController instance, so that Sushi can output MIDI data to your host:

```C++
_rt_controller->set_midi_callback(
    [&] (int output, sushi::MidiDataByte data, sushi::Time /*timestamp*/)
    { 
    		// Handle MIDI data.
    }
);
```

If you're going to host Sushi in e.g. an audio plugin, which can pass a transport position to Sushi, you need to tell Sushi to not calculate its own transport position internally:

```C++
_rt_controller->set_position_source (sushi::TransportPositionSource::EXTERNAL);
```

Finally, start Sushi, and if successful, set the sample rate. If not, address any issue and retry:

```c++
_sushi_start_status = _sushi->start();
if (_sushi_start_status == sushi::Status::OK)
{
    _sushi->set_sample_rate(_sample_rate);
    return true; // Sushi is started.
}
else
{
    _sushi = nullptr;
    _rt_controller = nullptr;
    // The factory is single use. Address the error, and perhaps retry, with a new factory instance.
}
```

For example: If you are using gRPC, it is possible that Sushi failed to start because the configured gRPC port was taken. You can then increment the port number using the utility method provided, and retry.

```C++
bool incrementation_status = _sushi_options.increment_grpc_port_number();
if (!incrementation_status)
{
    // Starting Sushi failed: gRPC address is malformed.
    break;
}
```

### Invoking Sushi in the audio callback of your host

For each audio callback invocation, you need to do the following, always using the RtController  instance.

Pass MIDI to Sushi using receive_midi.

```C++
void receive_midi(int input, MidiDataByte data, Time timestamp);
```

If you're using an external transport position source: update the Sushi transport, using the following.

```C++
void set_tempo(float tempo);
void set_time_signature(control::TimeSignature time_signature);
void set_playing_mode(control::PlayingMode mode);
bool set_current_beats(double beat_time);
bool set_current_bar_beats(double bar_beat_count);
```

Fill your sushi::**ChunkSampleBuffer** input audio buffer, and call process_audio on the RtController.

```C++
void process_audio(ChunkSampleBuffer& in_buffer,
                   ChunkSampleBuffer& out_buffer,
                   Time timestamp)
```

This will populate the out_buffer. The sushi::**Time** `timestamp` may either be calculated using your hosts playhead data, or you need to use the RtController utility to calculate it, if you're using the Sushi internal transport.

```C++
sushi::Time calculate_timestamp_from_start(float sample_rate) const
```

In which case, after the process_audio call, you will then also need to increment_samples_since_start.

```C++
void increment_samples_since_start(uint64_t sample_count, Time timestamp)
```

There is more detail to the above process to handle e.g. MIDI, or non-matching buffer sizes. We will be publishing a concrete example, showing how to implement a concrete audio plugin which wraps Sushi, in due course.

### Stopping Reactive Sushi

To stop Sushi, you'll really only need to delete the controller, call stop() on your sushi instance, and then delete that too:

```C++
if (_sushi)
{
    _rt_controller.reset();
    _sushi->stop();
    _sushi.reset();
}
```

## Active use-case

For the active use-case the Sushi API footprint is a bit smaller. You will need the following fields.

```c++
SushiOptions options;
std::unique_ptr<FactoryInterface> factory;
std::unique_ptr<Sushi> sushi;
```

Then depending on whether you plan to use an `OFFLINE` frontend, or if you want Sushi to instantiate its own Audio frontend (the options are defined in sushi::FrontendType), you will instantiate either a **StandaloneFactory**.

```C++
factory = std::make_unique<StandaloneFactory>();
```

Or an **OfflineFactory**.

```C++
factory = std::make_unique<OfflineFactory>();
```

To populate SushiOptions, we provide a utility method for parsing options from the Sushi terminal arguments, in **terminal_utilities.h**.

```C++
ParseStatus parse_options(int argc, char* argv[], sushi::SushiOptions& options);
```

From there on, you instantiate Sushi.

```C++
auto [sushi, status] = factory->new_instance(options);
```

And on success, start it.

```C++
auto start_status = sushi->start();
```

From there on, you can wait in the creating thread, until the application needs to exit, at which point you just need to invoke stop().

```C++
sushi->stop();
```

## Examples

For examples of sushi as a library:

### Active use-case

See apps/main.cpp in this repository, which shows a terminal application use-case.

### Passive use-case

See the example JUCE-based project, residing in a dedicated repository, where we demonstrate how Sushi can be wrapped in a JUCE audio plugin.

================================================
FILE: include/sushi/compile_time_settings.h
================================================
/*
 * Copyright 2017-2023 Elk Audio AB
 *
 * SUSHI is free software: you can redistribute it and/or modify it under the terms of
 * the GNU Affero General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * SUSHI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE. See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License along with
 * SUSHI. If not, see http://www.gnu.org/licenses/
 */

/**
 * @brief Methods for querying compile - time configuration (build options, version, githash, etc).
 * @Copyright 2017-2023 Elk Audio AB, Stockholm
 */

#ifndef SUSHI_COMPILE_TIME_SETTINGS_H
#define SUSHI_COMPILE_TIME_SETTINGS_H

#include <string>
#include <array>

#include "options.h"

#include "generated/version.h"

// For AUDIO_CHUNK_SIZE.
#include "constants.h"

namespace sushi {

struct CompileTimeSettings
{
    static constexpr auto sushi_version = SUSHI_STRINGIZE(SUSHI__VERSION_MAJ) "." SUSHI_STRINGIZE(SUSHI__VERSION_MIN) "." SUSHI_STRINGIZE(SUSHI__VERSION_REV);

    static constexpr auto sushi_api_version = SUSHI_EXTERNAL_API_VERSION;

    static constexpr auto git_commit_hash = SUSHI_GIT_COMMIT_HASH;

    static constexpr auto build_timestamp = SUSHI_BUILD_TIMESTAMP;

    static constexpr auto audio_chunk_size = AUDIO_CHUNK_SIZE;

    static constexpr std::array enabled_build_options = {
#ifdef SUSHI_BUILD_WITH_VST2
            "vst2",
#endif
#ifdef SUSHI_BUILD_WITH_VST3
            "vst3",
#endif
#ifdef SUSHI_BUILD_WITH_LV2
            "lv2",
#endif
#ifdef SUSHI_BUILD_WITH_JACK
            "jack",
#endif
#ifdef SUSHI_BUILD_WITH_RASPA
            "raspa",
#endif
#ifdef SUSHI_BUILD_WITH_RPC_INTERFACE
            "rpc control",
#endif
#ifdef SUSHI_BUILD_WITH_ABLETON_LINK
            "ableton link",
#endif
#ifdef SUSHI_BUILD_WITH_SENTRY
            "sentry"
#endif

// Without this entry, if all ifdefs are false, compiling will fail.
// Not as uncommon as you may think: building without LV2, VST2 and VST3 causes this for unit-tests.
#if    !defined (SUSHI_BUILD_WITH_VST2) \
    && !defined (SUSHI_BUILD_WITH_VST3) \
    && !defined (SUSHI_BUILD_WITH_LV2)  \
    && !defined (SUSHI_BUILD_WITH_JACK) \
    && !defined (SUSHI_BUILD_WITH_RASPA)\
    && !defined (SUSHI_BUILD_WITH_RPC_INTERFACE) \
    && !defined (SUSHI_BUILD_WITH_ABLETON_LINK)  \
    && !defined (SUSHI_BUILD_WITH_SENTRY)
            ""
#endif
    };
};

} // end namespace sushi

#endif // SUSHI_COMPILE_TIME_SETTINGS_H

================================================
FILE: include/sushi/constants.h
================================================
/*
 * Copyright 2017-2023 Elk Audio AB
 *
 * SUSHI is free software: you can redistribute it and/or modify it under the terms of
 * the GNU Affero General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * SUSHI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE. See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License along with
 * SUSHI. If not, see http://www.gnu.org/licenses/
 */

/**
 * @brief Compile time constants
 * @Copyright 2017-2023 Elk Audio AB, Stockholm
 */

#include <chrono>

#ifndef SUSHI_CONSTANTS_H
#define SUSHI_CONSTANTS_H

namespace sushi {

/* The number of samples to process in one chunk. It is defined as a
compile-time constant to give more room for optimizations */
#ifdef SUSHI_CUSTOM_AUDIO_CHUNK_SIZE
constexpr int AUDIO_CHUNK_SIZE = SUSHI_CUSTOM_AUDIO_CHUNK_SIZE;
#else
constexpr int AUDIO_CHUNK_SIZE = 64;
#endif

constexpr int MAX_ENGINE_CV_IO_PORTS = 4;
constexpr int MAX_ENGINE_GATE_PORTS = 8;
constexpr int MAX_ENGINE_GATE_NOTE_NO = 127;

constexpr int MAX_TRACK_CHANNELS = 16;

constexpr float PAN_GAIN_3_DB = 1.412537f;
constexpr auto GAIN_SMOOTHING_TIME = std::chrono::milliseconds(20);

constexpr int SUSHI_PPQN_TICK = 24;

/* Use in class declaration to disallow copying of this class.
 * Note that this marks copy constructor and assignment operator
 * as deleted and hence their r-value counterparts are not generated.
 *
 * In order to make a class moveable though still non-copyable,
 * implement a move constructor and move assignment operator. Default
 * copy constructor will then not be generated. Usage of this macro is
 * in this case not necessary to make the class non-copyable. But can
 * still be used for clarity.
 */
#define SUSHI_DECLARE_NON_COPYABLE(type) type(const type& other) = delete; \
                                         type& operator=(const type&) = delete;

} // end namespace sushi

#endif //SUSHI_CONSTANTS_H


================================================
FILE: include/sushi/control_interface.h
================================================
/*
 * Copyright 2017-2023 Elk Audio AB
 *
 * SUSHI is free software: you can redistribute it and/or modify it under the terms of
 * the GNU Affero General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * SUSHI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE. See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License along with
 * SUSHI. If not, see http://www.gnu.org/licenses/
 */

/**
 * @brief Abstract interface for external control of sushi over rpc, osc or similar
 * @Copyright 2017-2023 Elk Audio AB, Stockholm
 */

#ifndef SUSHI_CONTROL_INTERFACE_H
#define SUSHI_CONTROL_INTERFACE_H

#include <utility>
#include <memory>
#include <string>
#include <optional>
#include <vector>
#include <chrono>

#include "elk-warning-suppressor/warning_suppressor.hpp"

#ifdef ERROR
#undef ERROR
#endif

ELK_PUSH_WARNING
ELK_DISABLE_TRIVIAL_DESTRUCTOR_NOT_VIRTUAL

namespace sushi::control {

using Time = std::chrono::microseconds;

enum class ControlStatus
{
    OK,
    ASYNC_RESPONSE,
    ERROR,
    UNSUPPORTED_OPERATION,
    NOT_FOUND,
    OUT_OF_RANGE,
    INVALID_ARGUMENTS
};

enum class PlayingMode
{
    STOPPED,
    PLAYING,
    RECORDING
};

enum class SyncMode
{
    INTERNAL,
    MIDI,
    GATE,
    LINK
};

struct ControlResponse
{
    ControlStatus status;
    int           id;
};

struct TimeSignature
{
    int numerator;
    int denominator;
};

struct Timings
{
    float avg;
    float min;
    float max;
};

struct CpuTimings
{
    Timings main;
    std::vector<Timings> threads;
};

enum class PluginType
{
    INTERNAL,
    VST2X,
    VST3X,
    LV2
};

enum class ParameterType
{
    BOOL,
    INT,
    FLOAT
};

struct ParameterInfo
{
    int             id;
    ParameterType   type;
    std::string     label;
    std::string     name;
    std::string     unit;
    bool            automatable;
    float           min_domain_value;
    float           max_domain_value;
};

struct PropertyInfo
{
    int         id;
    std::string name;
    std::string label;
};

struct ProcessorInfo
{
    int         id;
    std::string label;
    std::string name;
    int         parameter_count;
    int         program_count;
};

struct ProgramInfo
{
    int         id;
    std::string name;
};

enum class TrackType
{
    REGULAR,
    PRE,
    POST
};

struct TrackInfo
{
    int         id;
    std::string label;
    std::string name;
    int         channels;
    int         buses;
    int         thread;
    TrackType   type;
    std::vector<int> processors;
};

struct ProcessorState
{
    std::optional<bool> bypassed;
    std::optional<int>  program;
    std::vector<std::pair<int, float>> parameters;
    std::vector<std::pair<int, std::string>> properties;
    std::vector<std::byte> binary_data;
};

struct SushiBuildInfo
{
    std::string                 version;
    std::vector<std::string>    build_options;
    int                         audio_buffer_size;
    std::string                 commit_hash;
    std::string                 build_date;
};

enum class MidiChannel
{
    MIDI_CH_1,
    MIDI_CH_2,
    MIDI_CH_3,
    MIDI_CH_4,
    MIDI_CH_5,
    MIDI_CH_6,
    MIDI_CH_7,
    MIDI_CH_8,
    MIDI_CH_9,
    MIDI_CH_10,
    MIDI_CH_11,
    MIDI_CH_12,
    MIDI_CH_13,
    MIDI_CH_14,
    MIDI_CH_15,
    MIDI_CH_16,
    MIDI_CH_OMNI
};

struct AudioConnection
{
    int track_id;
    int track_channel;
    int engine_channel;
};

struct CvConnection
{
    int track_id;
    int parameter_id;
    int cv_port_id;
};

struct GateConnection
{
    int processor_id;
    int gate_port_id;
    int channel;
    int note_no;
};

struct MidiKbdConnection
{
    int         track_id;
    MidiChannel channel;
    int         port;
    bool        raw_midi;
};

struct MidiCCConnection
{
    int         processor_id;
    int         parameter_id;
    MidiChannel channel;
    int         port;
    int         cc_number;
    int         min_range;
    int         max_range;
    bool        relative_mode;
};

struct MidiPCConnection
{
    int         processor_id;
    MidiChannel channel;
    int         port;
};

enum class NotificationType
{
    TRANSPORT_UPDATE,
    CPU_TIMING_UPDATE,
    TRACK_UPDATE,
    PROCESSOR_UPDATE,
    PARAMETER_CHANGE,
    PROPERTY_CHANGE,
    ASYNC_COMMAND_COMPLETION
};

enum class ProcessorAction
{
    ADDED,
    DELETED
};

enum class TrackAction
{
    ADDED,
    DELETED
};

enum class TransportAction
{
    PLAYING_MODE_CHANGED,
    SYNC_MODE_CHANGED,
    TIME_SIGNATURE_CHANGED,
    TEMPO_CHANGED
};

struct MidiKbdConnectionState
{
    std::string track;
    MidiChannel channel;
    int         port;
    bool        raw_midi;
};

struct MidiCCConnectionState
{
    std::string processor;
    int         parameter_id;
    MidiChannel channel;
    int         port;
    int         cc_number;
    float       min_range;
    float       max_range;
    bool        relative_mode;
};

struct MidiPCConnectionState
{
    std::string processor;
    MidiChannel channel;
    int         port;
};

struct MidiState
{
    int inputs;
    int outputs;
    std::vector<MidiKbdConnectionState> kbd_input_connections;
    std::vector<MidiKbdConnectionState> kbd_output_connections;
    std::vector<MidiCCConnectionState> cc_connections;
    std::vector<MidiPCConnectionState> pc_connections;
    std::vector<int> enabled_clock_outputs;
};

struct OscParameterState
{
    std::string processor;
    std::vector<int> parameter_ids;
};

struct OscState
{
    bool enable_all_processor_outputs;
    std::vector<OscParameterState> enabled_processor_outputs;
};

struct TrackAudioConnectionState
{
    std::string  track;
    int          track_channel;
    int          engine_channel;
};

struct EngineState
{
    float           sample_rate;
    float           tempo;
    PlayingMode     playing_mode;
    SyncMode        sync_mode;
    TimeSignature   time_signature;
    bool            input_clip_detection;
    bool            output_clip_detection;
    bool            master_limiter;
    int             used_audio_inputs;
    int             used_audio_outputs;
    std::vector<TrackAudioConnectionState> input_connections;
    std::vector<TrackAudioConnectionState> output_connections;
};

struct PluginClass
{
    std::string     name;
    std::string     label;
    std::string     uid;
    std::string     path;
    PluginType      type;
    ProcessorState  state;
};

struct TrackState
{
    std::string     name;
    std::string     label;
    int             channels;
    int             buses;
    int             thread;
    TrackType       type;
    ProcessorState  track_state;
    std::vector<PluginClass>    processors;
};

struct SessionState
{
    SushiBuildInfo      sushi_info;
    std::string         save_date;
    OscState            osc_state;
    MidiState           midi_state;
    EngineState         engine_state;
    std::vector<TrackState> tracks;
};

class SystemController
{
public:
    virtual ~SystemController() = default;

    [[nodiscard]] virtual std::string    get_sushi_version() const = 0;
    [[nodiscard]] virtual std::string    get_sushi_api_version() const = 0;
    [[nodiscard]] virtual SushiBuildInfo get_sushi_build_info() const = 0;
    [[nodiscard]] virtual int            get_input_audio_channel_count() const = 0;
    [[nodiscard]] virtual int            get_output_audio_channel_count() const = 0;

protected:
    SystemController() = default;
};

class TransportController
{
public:
    virtual ~TransportController() = default;

    [[nodiscard]] virtual float           get_samplerate() const = 0;
    [[nodiscard]] virtual PlayingMode     get_playing_mode() const = 0;
    [[nodiscard]] virtual SyncMode        get_sync_mode() const = 0;
    [[nodiscard]] virtual TimeSignature   get_time_signature() const = 0;
    [[nodiscard]] virtual float           get_tempo() const = 0;

    virtual ControlStatus       set_sync_mode(SyncMode sync_mode) = 0;
    virtual void                set_playing_mode(PlayingMode playing_mode) = 0;
    virtual ControlStatus       set_tempo(float tempo) = 0;
    virtual ControlStatus       set_time_signature(TimeSignature signature) = 0;

protected:
    TransportController() = default;
};

class TimingController
{
public:
    virtual ~TimingController() = default;

    [[nodiscard]] virtual bool                      get_timing_statistics_enabled() const = 0;
    virtual void                                    set_timing_statistics_enabled(bool enabled) = 0;

    [[nodiscard]] virtual std::pair<ControlStatus, CpuTimings> get_engine_timings() const = 0;
    [[nodiscard]] virtual std::pair<ControlStatus, Timings>    get_track_timings(int track_id) const = 0;
    [[nodiscard]] virtual std::pair<ControlStatus, Timings>    get_processor_timings(int processor_id) const = 0;

    virtual ControlStatus      reset_all_timings() = 0;
    virtual ControlStatus      reset_track_timings(int track_id) = 0;
    virtual ControlStatus      reset_processor_timings(int processor_id) = 0;

protected:
    TimingController() = default;
};

class KeyboardController
{
public:
    virtual ~KeyboardController() = default;

    virtual ControlStatus send_note_on(int track_id, int channel, int note, float velocity) = 0;
    virtual ControlStatus send_note_off(int track_id, int channel, int note, float velocity) = 0;
    virtual ControlStatus send_note_aftertouch(int track_id, int channel, int note, float value) = 0;
    virtual ControlStatus send_aftertouch(int track_id, int channel, float value) = 0;
    virtual ControlStatus send_pitch_bend(int track_id, int channel, float value) = 0;
    virtual ControlStatus send_modulation(int track_id, int channel, float value) = 0;

protected:
    KeyboardController() = default;
};

class AudioGraphController
{
public:
    virtual ~AudioGraphController() = default;

    [[nodiscard]] virtual std::vector<ProcessorInfo>                           get_all_processors() const = 0;
    [[nodiscard]] virtual std::vector<TrackInfo>                               get_all_tracks() const = 0;
    [[nodiscard]] virtual std::pair<ControlStatus, int>                        get_track_id(const std::string& track_name) const = 0;
    [[nodiscard]] virtual std::pair<ControlStatus, TrackInfo>                  get_track_info(int track_id) const = 0;
    [[nodiscard]] virtual std::pair<ControlStatus, std::vector<ProcessorInfo>> get_track_processors(int track_id) const = 0;
    [[nodiscard]] virtual std::pair<ControlStatus, int>                        get_processor_id(const std::string& processor_name) const = 0;
    [[nodiscard]] virtual std::pair<ControlStatus, ProcessorInfo>              get_processor_info(int processor_id) const = 0;
    [[nodiscard]] virtual std::pair<ControlStatus, bool>                       get_processor_bypass_state(int processor_id) const = 0;
    [[nodiscard]] virtual std::pair<ControlStatus, ProcessorState>             get_processor_state(int processor_id) const = 0;

    virtual ControlResponse set_processor_bypass_state(int processor_id, bool bypass_enabled) = 0;
    virtual ControlResponse set_processor_state(int processor_id, const ProcessorState& state) = 0;

    virtual ControlResponse create_track(const std::string& name, int channels, std::optional<int> thread) = 0;
    virtual ControlResponse create_multibus_track(const std::string& name, int buses, std::optional<int> thread) = 0;
    virtual ControlResponse create_pre_track(const std::string& name) = 0;
    virtual ControlResponse create_post_track(const std::string& name) = 0;
    virtual ControlResponse move_processor_on_track(int processor_id, int source_track_id, int dest_track_id, std::optional<int> before_processor_id) = 0;
    virtual ControlResponse create_processor_on_track(const std::string& name, const std::string& uid, const std::string& file,
                                                      PluginType type, int track_id, std::optional<int> before_processor_id) = 0;

    virtual ControlResponse delete_processor_from_track(int processor_id, int track_id) = 0;
    virtual ControlResponse delete_track(int track_id) = 0;

protected:
    AudioGraphController() = default;
};

class ProgramController
{
public:
    virtual ~ProgramController() = default;

    [[nodiscard]] virtual std::pair<ControlStatus, int>                      get_processor_current_program(int processor_id) const = 0;
    [[nodiscard]] virtual std::pair<ControlStatus, std::string>              get_processor_current_program_name(int processor_id) const = 0;
    [[nodiscard]] virtual std::pair<ControlStatus, std::string>              get_processor_program_name(int processor_id, int program_id) const = 0;
    [[nodiscard]] virtual std::pair<ControlStatus, std::vector<std::string>> get_processor_programs(int processor_id) const = 0;

    virtual ControlResponse                                       set_processor_program(int processor_id, int program_id)= 0;

protected:
    ProgramController() = default;
};

class ParameterController
{
public:
    virtual ~ParameterController() = default;

    [[nodiscard]] virtual std::pair<ControlStatus, std::vector<ParameterInfo>> get_processor_parameters(int processor_id) const = 0;
    [[nodiscard]] virtual std::pair<ControlStatus, std::vector<ParameterInfo>> get_track_parameters(int processor_id) const = 0;
    [[nodiscard]] virtual std::pair<ControlStatus, int>                        get_parameter_id(int processor_id, const std::string& parameter) const = 0;
    [[nodiscard]] virtual std::pair<ControlStatus, ParameterInfo>              get_parameter_info(int processor_id, int parameter_id) const = 0;
    [[nodiscard]] virtual std::pair<ControlStatus, float>                      get_parameter_value(int processor_id, int parameter_id) const = 0;
    [[nodiscard]] virtual std::pair<ControlStatus, float>                      get_parameter_value_in_domain(int processor_id, int parameter_id) const = 0;
    [[nodiscard]] virtual std::pair<ControlStatus, std::string>                get_parameter_value_as_string(int processor_id, int parameter_id) const = 0;

    virtual ControlStatus set_parameter_value(int processor_id, int parameter_id, float value) = 0;

    [[nodiscard]] virtual std::pair<ControlStatus, std::vector<PropertyInfo>>  get_processor_properties(int processor_id) const = 0;
    [[nodiscard]] virtual std::pair<ControlStatus, std::vector<PropertyInfo>>  get_track_properties(int processor_id) const = 0;
    [[nodiscard]] virtual std::pair<ControlStatus, int>                        get_property_id(int processor_id, const std::string& parameter) const = 0;
    [[nodiscard]] virtual std::pair<ControlStatus, PropertyInfo>               get_property_info(int processor_id, int parameter_id) const = 0;
    [[nodiscard]] virtual std::pair<ControlStatus, std::string>                get_property_value(int processor_id, int parameter_id) const = 0;

    virtual ControlStatus set_property_value(int processor_id, int parameter_id, const std::string& value) = 0;

protected:
    ParameterController() = default;
};

class MidiController
{
public:
    virtual ~MidiController() = default;

    [[nodiscard]] virtual int                            get_input_ports() const = 0;
    [[nodiscard]] virtual int                            get_output_ports() const = 0;
    [[nodiscard]] virtual std::vector<MidiKbdConnection> get_all_kbd_input_connections() const = 0;
    [[nodiscard]] virtual std::vector<MidiKbdConnection> get_all_kbd_output_connections() const = 0;
    [[nodiscard]] virtual std::vector<MidiCCConnection>  get_all_cc_input_connections() const = 0;
    [[nodiscard]] virtual std::vector<MidiPCConnection>  get_all_pc_input_connections() const = 0;
    [[nodiscard]] virtual std::pair<ControlStatus, std::vector<MidiCCConnection>> get_cc_input_connections_for_processor(int processor_id) const = 0;
    [[nodiscard]] virtual std::pair<ControlStatus, std::vector<MidiPCConnection>> get_pc_input_connections_for_processor(int processor_id) const = 0;

    [[nodiscard]] virtual bool get_midi_clock_output_enabled(int port) const = 0;
    virtual ControlStatus set_midi_clock_output_enabled(bool enabled, int port) = 0;

    virtual ControlResponse connect_kbd_input_to_track(int track_id, MidiChannel channel, int port, bool raw_midi) = 0;
    virtual ControlResponse connect_kbd_output_from_track(int track_id, MidiChannel channel, int port) = 0;
    virtual ControlResponse connect_cc_to_parameter(int processor_id, int parameter_id, MidiChannel channel, int port,
                                                    int cc_number, float min_range, float max_range, bool relative_mode) = 0;
    virtual ControlResponse connect_pc_to_processor(int processor_id, MidiChannel channel, int port) = 0;

    virtual ControlResponse disconnect_kbd_input(int track_id, MidiChannel channel, int port, bool raw_midi) = 0;
    virtual ControlResponse disconnect_kbd_output(int track_id, MidiChannel channel, int port) = 0;
    virtual ControlResponse disconnect_cc(int processor_id, MidiChannel channel, int port, int cc_number) = 0;
    virtual ControlResponse disconnect_pc(int processor_id, MidiChannel channel, int port) = 0;
    virtual ControlResponse disconnect_all_cc_from_processor(int processor_id) = 0;
    virtual ControlResponse disconnect_all_pc_from_processor(int processor_id) = 0;

protected:
    MidiController() = default;
};

class AudioRoutingController
{
public:
    virtual ~AudioRoutingController() = default;

    [[nodiscard]] virtual std::vector<AudioConnection> get_all_input_connections() const = 0;
    [[nodiscard]] virtual std::vector<AudioConnection> get_all_output_connections() const = 0;
    [[nodiscard]] virtual std::pair<ControlStatus, std::vector<AudioConnection>> get_input_connections_for_track(int track_id) const = 0;
    [[nodiscard]] virtual std::pair<ControlStatus, std::vector<AudioConnection>> get_output_connections_for_track(int track_id) const = 0;

    virtual ControlResponse                connect_input_channel_to_track(int track_id, int track_channel, int input_channel) = 0;
    virtual ControlResponse                connect_output_channel_to_track(int track_id, int track_channel, int output_channel) = 0;

    virtual ControlResponse                disconnect_input(int track_id, int track_channel, int input_channel) = 0;
    virtual ControlResponse                disconnect_output(int track_id, int track_channel, int output_channel) = 0;
    virtual ControlResponse                disconnect_all_inputs_from_track(int track_id) = 0;
    virtual ControlResponse                disconnect_all_outputs_from_track(int track_id) = 0;

protected:
    AudioRoutingController() = default;
};

class CvGateController
{
public:
    virtual ~CvGateController() = default;

    [[nodiscard]] virtual int get_cv_input_ports() const = 0;
    [[nodiscard]] virtual int get_cv_output_ports() const = 0;


    [[nodiscard]] virtual std::vector<CvConnection>   get_all_cv_input_connections() const = 0;
    [[nodiscard]] virtual std::vector<CvConnection>   get_all_cv_output_connections() const = 0;
    [[nodiscard]] virtual std::vector<GateConnection> get_all_gate_input_connections() const = 0;
    [[nodiscard]] virtual std::vector<GateConnection> get_all_gate_output_connections() const = 0;
    [[nodiscard]] virtual std::pair<ControlStatus, std::vector<CvConnection>>   get_cv_input_connections_for_processor(int processor_id) const = 0;
    [[nodiscard]] virtual std::pair<ControlStatus, std::vector<CvConnection>>   get_cv_output_connections_for_processor(int processor_id) const = 0;
    [[nodiscard]] virtual std::pair<ControlStatus, std::vector<GateConnection>> get_gate_input_connections_for_processor(int processor_id) const = 0;
    [[nodiscard]] virtual std::pair<ControlStatus, std::vector<GateConnection>> get_gate_output_connections_for_processor(int processor_id) const = 0;

    virtual ControlResponse               connect_cv_input_to_parameter(int processor_id, int parameter_id, int cv_input_id) = 0;
    virtual ControlResponse               connect_cv_output_from_parameter(int processor_id, int parameter_id, int cv_output_id) = 0;
    virtual ControlResponse               connect_gate_input_to_processor(int processor_id, int gate_input_id, int channel, int note_no) = 0;
    virtual ControlResponse               connect_gate_output_from_processor(int processor_id, int gate_output_id, int channel, int note_no) = 0;

    virtual ControlResponse               disconnect_cv_input(int processor_id, int parameter_id, int cv_input_id) = 0;
    virtual ControlResponse               disconnect_cv_output(int processor_id, int parameter_id, int cv_output_id) = 0;
    virtual ControlResponse               disconnect_gate_input(int processor_id, int gate_input_id, int channel, int note_no) = 0;
    virtual ControlResponse               disconnect_gate_output(int processor_id, int gate_output_id, int channel, int note_no) = 0;
    virtual ControlResponse               disconnect_all_cv_inputs_from_processor(int processor_id) = 0;
    virtual ControlResponse               disconnect_all_cv_outputs_from_processor(int processor_id) = 0;
    virtual ControlResponse               disconnect_all_gate_inputs_from_processor(int processor_id) = 0;
    virtual ControlResponse               disconnect_all_gate_outputs_from_processor(int processor_id) = 0;

protected:
    CvGateController() = default;
};

class OscController
{
public:
    virtual ~OscController() = default;

    [[nodiscard]] virtual std::string get_send_ip() const = 0;
    [[nodiscard]] virtual int get_send_port() const = 0;
    [[nodiscard]] virtual int get_receive_port() const = 0;
    [[nodiscard]] virtual std::vector<std::string> get_enabled_parameter_outputs() const = 0;
    virtual ControlResponse enable_output_for_parameter(int processor_id, int parameter_id) = 0;
    virtual ControlResponse disable_output_for_parameter(int processor_id, int parameter_id) = 0;
    virtual ControlResponse enable_all_output() = 0;
    virtual ControlResponse disable_all_output() = 0;

protected:
    OscController() = default;
};

class SessionController
{
public:
    virtual ~SessionController() = default;

    [[nodiscard]] virtual SessionState save_session() const = 0;
    virtual ControlResponse restore_session(const SessionState& state) = 0;
};

class ControlNotification
{
public:
    virtual ~ControlNotification() = default;

    [[nodiscard]] NotificationType type() const {return _type;}
    [[nodiscard]] Time timestamp() const {return _timestamp;}

protected:
    ControlNotification(NotificationType type, Time timestamp) : _type(type),
                                                                 _timestamp(timestamp) {}

private:
    NotificationType _type;
    Time _timestamp;
};

class ControlListener
{
public:
    virtual void notification(const ControlNotification* notification) = 0;
};

class SushiControl
{
public:
    virtual ~SushiControl() = default;

    SystemController*       system_controller() {return _system_controller;}
    TransportController*    transport_controller() {return _transport_controller;}
    TimingController*       timing_controller() {return _timing_controller;}
    KeyboardController*     keyboard_controller() {return _keyboard_controller;}
    AudioGraphController*   audio_graph_controller() {return _audio_graph_controller;}
    ProgramController*      program_controller() {return _program_controller;}
    ParameterController*    parameter_controller() {return _parameter_controller;}
    MidiController*         midi_controller() {return _midi_controller;}
    AudioRoutingController* audio_routing_controller() {return _audio_routing_controller;}
    CvGateController*       cv_gate_controller() {return _cv_gate_controller;}
    OscController*          osc_controller() {return _osc_controller;}
    SessionController*      session_controller() {return _session_controller;}

    virtual ControlStatus   subscribe_to_notifications(NotificationType type, ControlListener* listener) = 0;

protected:
    SushiControl(SystemController*       system_controller,
                 TransportController*    transport_controller,
                 TimingController*       timing_controller,
                 KeyboardController*     keyboard_controller,
                 AudioGraphController*   audio_graph_controller,
                 ProgramController*      program_controller,
                 ParameterController*    parameter_controller,
                 MidiController*         midi_controller,
                 AudioRoutingController* audio_routing_controller,
                 CvGateController*       cv_gate_controller,
                 OscController*          osc_controller,
                 SessionController*      session_controller) : _system_controller(system_controller),
                                                               _transport_controller(transport_controller),
                                                               _timing_controller(timing_controller),
                                                               _keyboard_controller(keyboard_controller),
                                                               _audio_graph_controller(audio_graph_controller),
                                                               _program_controller(program_controller),
                                                               _parameter_controller(parameter_controller),
                                                               _midi_controller(midi_controller),
                                                               _audio_routing_controller(audio_routing_controller),
                                                               _cv_gate_controller(cv_gate_controller),
                                                               _osc_controller(osc_controller),
                                                               _session_controller(session_controller){}

private:
    SystemController*           _system_controller;
    TransportController*        _transport_controller;
    TimingController*           _timing_controller;
    KeyboardController*         _keyboard_controller;
    AudioGraphController*       _audio_graph_controller;
    ProgramController*          _program_controller;
    ParameterController*        _parameter_controller;
    MidiController*             _midi_controller;
    AudioRoutingController*     _audio_routing_controller;
    CvGateController*           _cv_gate_controller;
    OscController*              _osc_controller;
    SessionController*          _session_controller;
};

} // end namespace sushi::control

ELK_POP_WARNING

#endif //SUSHI_CONTROL_INTERFACE_H


================================================
FILE: include/sushi/control_notifications.h
================================================

#ifndef SUSHI_CONTROL_NOTIFICATIONS_H
#define SUSHI_CONTROL_NOTIFICATIONS_H

#include <variant>
#include "control_interface.h"

namespace sushi::control {

using TransportNotificationValue = std::variant<float, PlayingMode, SyncMode, TimeSignature>;

class TransportNotification : public ControlNotification
{
public:
    TransportNotification(TransportAction action,
                          TransportNotificationValue value,
                          Time timestamp)
            : ControlNotification(NotificationType::TRANSPORT_UPDATE, timestamp),
              _value(value),
              _action(action) {}

    TransportAction action() const {return _action;}
    TransportNotificationValue value() const {return _value;}

private:
    TransportNotificationValue _value;
    TransportAction _action;
};

class CpuTimingNotification : public ControlNotification
{
public:
    CpuTimingNotification(const CpuTimings& timings, Time timestamp)
            : ControlNotification(NotificationType::CPU_TIMING_UPDATE, timestamp),
              _cpu_timings(timings) {}

    CpuTimingNotification(CpuTimings&& timings, Time timestamp)
            : ControlNotification(NotificationType::CPU_TIMING_UPDATE, timestamp),
              _cpu_timings(std::move(timings)) {}

    const CpuTimings& cpu_timings() const {return _cpu_timings;}

private:
    CpuTimings _cpu_timings;
};

class TrackNotification : public ControlNotification
{
public:
    TrackNotification(TrackAction action, int track_id, Time timestamp)
            : ControlNotification(NotificationType::TRACK_UPDATE, timestamp),
              _track_id(track_id),
              _action(action) {}

    int track_id() const {return _track_id;}
    TrackAction action() const {return _action;}

private:
    int _track_id;
    TrackAction _action;
};

class ProcessorNotification : public ControlNotification
{
public:
    ProcessorNotification(ProcessorAction action, int processor_id, int parent_track_id, Time timestamp)
            : ControlNotification(NotificationType::PROCESSOR_UPDATE, timestamp),
              _processor_id(processor_id),
              _parent_track_id(parent_track_id),
              _action(action) {}

    int processor_id() const {return _processor_id;}
    int parent_track_id() const {return _parent_track_id;}
    ProcessorAction action() const {return _action;}

private:
    int _processor_id;
    int _parent_track_id;
    ProcessorAction _action;
};

class ParameterChangeNotification : public ControlNotification
{
public:
    ParameterChangeNotification(int processor_id, int parameter_id, float normalized_value,
                                float domain_value, const std::string& formatted_value, Time timestamp)
    : ControlNotification(NotificationType::PARAMETER_CHANGE, timestamp),
      _processor_id(processor_id),
      _parameter_id(parameter_id),
      _normalized_value(normalized_value),
      _domain_value(domain_value),
      _formatted_value(formatted_value) {}

    int processor_id() const {return _processor_id;}
    int parameter_id() const {return _parameter_id;}
    float value() const {return _normalized_value;}
    float domain_value() const {return _domain_value;}
    const std::string& formatted_value() const {return _formatted_value;};

private:
    int _processor_id;
    int _parameter_id;
    float _normalized_value;
    float _domain_value;
    std::string _formatted_value;
};

class PropertyChangeNotification : public ControlNotification
{
public:
    PropertyChangeNotification(int processor_id, int property_id, const std::string& value, Time timestamp)
    : ControlNotification(NotificationType::PROPERTY_CHANGE, timestamp),
      _processor_id(processor_id),
      _property_id(property_id),
      _value(value) {}

    PropertyChangeNotification(int processor_id, int property_id, std::string&& value, Time timestamp)
    : ControlNotification(NotificationType::PROPERTY_CHANGE, timestamp),
      _processor_id(processor_id),
      _property_id(property_id),
      _value(value) {}

    int processor_id() const {return _processor_id;}
    int parameter_id() const {return _property_id;}
    const std::string& value() const {return _value;}

private:
    int _processor_id;
    int _property_id;
    std::string _value;
};

class CommandCompletionNotification : public ControlNotification
{
public:
    CommandCompletionNotification(ControlStatus status, int id, Time timestamp)
    : ControlNotification(NotificationType::ASYNC_COMMAND_COMPLETION, timestamp), _status(status), _id(id) {}

    ControlStatus status() const {return _status;}
    int id() const {return _id;}

private:
    ControlStatus _status;
    int           _id;
};

} // end namespace sushi::control

#endif //SUSHI_CONTROL_NOTIFICATIONS_H

================================================
FILE: include/sushi/coreaudio_devices_dump.h
================================================
/*
 * Copyright 2017-2023 Elk Audio AB
 *
 * SUSHI is free software: you can redistribute it and/or modify it under the terms of
 * the GNU Affero General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * SUSHI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE. See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License along with
 * SUSHI. If not, see http://www.gnu.org/licenses/
 */

/**
 * @brief Utility functions for dumping CoreAudio devices info
 * @Copyright 2017-2023 Elk Audio AB, Stockholm
 */

#include "rapidjson/document.h"

namespace sushi {

/**
 * @brief Retrieve CoreAudio's registered devices information.
 *        Can be queried before instantiating an actual CoreAudioFrontend
 *
 * @return Device information list in JSON format
 */
rapidjson::Document generate_coreaudio_devices_info_document();

} // end namespace sushi



================================================
FILE: include/sushi/elk_sentry_log_sink.h
================================================
/**
 * @brief An spdlog sink which wraps the Sentry logging functionality
 * @Copyright 2017-2024 Elk Audio AB, Stockholm
 */

#ifndef ELK_SENTRY_LOG_SINK_H
#define ELK_SENTRY_LOG_SINK_H

#include <iostream>
#include <mutex>

#include "spdlog/details/null_mutex.h"
#include "spdlog/sinks/base_sink.h"
#include "sentry.h"

namespace elk {

template<typename Mutex>
class SentrySink : public spdlog::sinks::base_sink<Mutex>
{
public:
    SentrySink() : spdlog::sinks::base_sink<Mutex>()
    {
    }

    ~SentrySink()
    {
    }

protected:
    void sink_it_(const spdlog::details::log_msg& msg) override
    {
        const std::string payload(msg.payload.begin(), msg.payload.end());
        const std::string logger_name(msg.logger_name.begin(), msg.logger_name.end());
        switch (msg.level)
        {
        case spdlog::level::info: _add_breadcrumb(payload, logger_name, "info"); break;
        case spdlog::level::debug: _add_breadcrumb(payload, logger_name, "debug"); break;
        case spdlog::level::warn: _add_breadcrumb(payload, logger_name, "warning"); break;
        case spdlog::level::err:
            sentry_capture_event(sentry_value_new_message_event(
            SENTRY_LEVEL_ERROR, // level
            logger_name.c_str(), // logger name
            payload.c_str() // message
            ));
            break;

        default:
            break;
        }
    }

    void flush_() override
    {
       sentry_flush(1000);
    }

private:
    void _add_breadcrumb(const std::string& message, const std::string& category, const std::string& level)
    {
        sentry_value_t crumb = sentry_value_new_breadcrumb("log", message.c_str());
        sentry_value_set_by_key(crumb, "category", sentry_value_new_string(category.c_str()));
        sentry_value_set_by_key(crumb, "level", sentry_value_new_string(level.c_str()));
        sentry_add_breadcrumb(crumb);
    }
};

using sentry_sink_mt = SentrySink<std::mutex>;
using sentry_sink_st = SentrySink<spdlog::details::null_mutex>;

}

#endif // SUSHI_SENTRY_LOG_SINK_H

================================================
FILE: include/sushi/factory_interface.h
================================================
/*
* Copyright 2017-2022 Modern Ancient Instruments Networked AB, dba Elk
*
* SUSHI is free software: you can redistribute it and/or modify it under the terms of
* the GNU Affero General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* SUSHI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with
* SUSHI. If not, see http://www.gnu.org/licenses/
*/

#ifndef FACTORY_INTERFACE_H
#define FACTORY_INTERFACE_H

#include "sushi.h"

namespace sushi {

class FactoryInterface
{
public:
    FactoryInterface() = default;
    virtual ~FactoryInterface() = default;

    [[nodiscard]] virtual std::pair<std::unique_ptr<Sushi>, Status> new_instance(SushiOptions& options) = 0;
};

} // end namespace sushi

#endif // FACTORY_INTERFACE_H


================================================
FILE: include/sushi/offline_factory.h
================================================
/*
 * Copyright 2017-2023 Elk Audio AB
 *
 * SUSHI is free software: you can redistribute it and/or modify it under the terms of
 * the GNU Affero General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * SUSHI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE. See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License along with
 * SUSHI. If not, see http://www.gnu.org/licenses/
 */

/**
 * @brief Public Sushi factory for offline use.
 * @copyright 2017-2023 Elk Audio AB, Stockholm
 */

#ifndef OFFLINE_FACTORY_H
#define OFFLINE_FACTORY_H

#include "factory_interface.h"
#include "sushi.h"

namespace sushi {

namespace internal {
class OfflineFactoryImplementation;
}

class OfflineFactory : public FactoryInterface
{
public:
    OfflineFactory();
    ~OfflineFactory() override;

    [[nodiscard]] std::pair<std::unique_ptr<Sushi>, Status> new_instance(SushiOptions& options) override;

private:
    std::unique_ptr<internal::OfflineFactoryImplementation> _implementation;
};

} // end namespace sushi

#endif // STANDALONE_FACTORY_H


================================================
FILE: include/sushi/options.h
================================================
/*
 * Copyright 2017-2023 Elk Audio AB
 *
 * SUSHI is free software: you can redistribute it and/or modify it under the terms of
 * the GNU Affero General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * SUSHI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE. See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License along with
 * SUSHI. If not, see http://www.gnu.org/licenses/
 */

/**
 * @brief Option parsing
 * @Copyright 2017-2023 Elk Audio AB, Stockholm
 */

#ifndef SUSHI_OPTIONS_H
#define SUSHI_OPTIONS_H

#include <cstdio>

#include "elk-warning-suppressor/warning_suppressor.hpp"

ELK_PUSH_WARNING
ELK_DISABLE_ZERO_AS_NULL_POINTER_CONSTANT
ELK_DISABLE_SIGN_CONVERSION
ELK_DISABLE_CONDITIONAL_UNINITIALIZED
#include "optionparser.h"
ELK_POP_WARNING

#define _SUSHI_STRINGIZE(X) #X
#define SUSHI_STRINGIZE(X) _SUSHI_STRINGIZE(X)

////////////////////////////////////////////////////////////////////////////////
// Options Defaults
////////////////////////////////////////////////////////////////////////////////

#define ELKLOG_LOG_LEVEL_DEFAULT "info"
#define ELKLOG_LOG_FILE_DEFAULT "/tmp/sushi.log"
#define SUSHI_JSON_FILENAME_DEFAULT "config.json"
#define SUSHI_JSON_STRING_DEFAULT "{}"
#define SUSHI_SAMPLE_RATE_DEFAULT 48000
#define SUSHI_JACK_CLIENT_NAME_DEFAULT "sushi"
#define SUSHI_OSC_SERVER_PORT_DEFAULT 24024
#define SUSHI_OSC_SEND_PORT_DEFAULT 24023
#define SUSHI_OSC_SEND_IP_DEFAULT "127.0.0.1"
#if defined(_MSC_VER)
    #define SUSHI_GRPC_LISTENING_PORT_DEFAULT "[::]:510"
#else
    #define SUSHI_GRPC_LISTENING_PORT_DEFAULT "[::]:51051"
#endif
#define SUSHI_PORTAUDIO_INPUT_LATENCY_DEFAULT 0.0f
#define SUSHI_PORTAUDIO_OUTPUT_LATENCY_DEFAULT 0.0f
#define SUSHI_SENTRY_CRASH_HANDLER_PATH_DEFAULT "./crashpad_handler"
#ifdef SUSHI_BUILD_WITH_SENTRY
    #define SUSHI_SENTRY_DSN_DEFAULT SUSHI_SENTRY_DSN
#else
    #define SUSHI_SENTRY_DSN_DEFAULT ""
#endif

namespace sushi {

////////////////////////////////////////////////////////////////////////////////
// Helpers for optionparse
////////////////////////////////////////////////////////////////////////////////

struct SushiArg : public optionparser::Arg
{
    static void print_error(const char* msg1, const optionparser::Option& opt, const char* msg2)
    {
        fprintf(stderr, "%s", msg1);
        fwrite(opt.name, static_cast<size_t>(opt.namelen), 1, stderr);
        fprintf(stderr, "%s", msg2);
    }

    static optionparser::ArgStatus Unknown(const optionparser::Option& option, bool msg)
    {
        if (msg)
        {
            print_error("Unknown option '", option, "'\n");
        }
        return optionparser::ARG_ILLEGAL;
    }

    static optionparser::ArgStatus NonEmpty(const optionparser::Option& option, bool msg)
    {
        if (option.arg && option.arg[0])
        {
            return optionparser::ARG_OK;
        }

        if (msg)
        {
            print_error("Option '", option, "' requires a non-empty argument\n");
        }
        return optionparser::ARG_ILLEGAL;
    }

    static optionparser::ArgStatus Numeric(const optionparser::Option& option, bool msg)
    {
        char* endptr = nullptr;
        if (option.arg != nullptr && strtol(option.arg, &endptr, 10))
        {}

        if (endptr != option.arg && *endptr == 0)
        {
          return optionparser::ARG_OK;
        }
        if (msg)
        {
            print_error("Option '", option, "' requires a numeric argument\n");
        }
        return optionparser::ARG_ILLEGAL;
    }
};

////////////////////////////////////////////////////////////////////////////////
// Command Line options descriptors
////////////////////////////////////////////////////////////////////////////////

// List here the different command line options
enum OptionIndex
{
    OPT_IDX_UNKNOWN,
    OPT_IDX_HELP,
    OPT_IDX_VERSION,
    OPT_IDX_LOG_LEVEL,
    OPT_IDX_LOG_FILE,
    OPT_IDX_LOG_FLUSH_INTERVAL,
    OPT_IDX_DUMP_PARAMETERS,
    OPT_IDX_CONFIG_FILE,
    OPT_IDX_USE_OFFLINE,
    OPT_IDX_INPUT_FILE,
    OPT_IDX_OUTPUT_FILE,
    OPT_IDX_USE_DUMMY,
    OPT_IDX_USE_PORTAUDIO,
    OPT_IDX_USE_APPLE_COREAUDIO,
    OPT_IDX_AUDIO_INPUT_DEVICE,
    OPT_IDX_AUDIO_INPUT_DEVICE_UID,
    OPT_IDX_AUDIO_OUTPUT_DEVICE,
    OPT_IDX_AUDIO_OUTPUT_DEVICE_UID,
    OPT_IDX_PA_SUGGESTED_INPUT_LATENCY,
    OPT_IDX_PA_SUGGESTED_OUTPUT_LATENCY,
    OPT_IDX_DUMP_DEVICES,
    OPT_IDX_USE_JACK,
    OPT_IDX_CONNECT_PORTS,
    OPT_IDX_JACK_CLIENT,
    OPT_IDX_JACK_SERVER,
    OPT_IDX_USE_XENOMAI_RASPA,
    OPT_IDX_XENOMAI_DEBUG_MODE_SW,
    OPT_IDX_MULTICORE_PROCESSING,
    OPT_IDX_TIMINGS_STATISTICS,
    OPT_IDX_DETAILED_TIMINGS,
    OPT_IDX_OSC_RECEIVE_PORT,
    OPT_IDX_OSC_SEND_PORT,
    OPT_IDX_OSC_SEND_IP,
    OPT_IDX_GRPC_LISTEN_ADDRESS,
    OPT_IDX_NO_OSC,
    OPT_IDX_NO_GRPC,
    OPT_IDX_BASE_PLUGIN_PATH,
    OPT_IDX_SENTRY_CRASH_HANDLER,
    OPT_IDX_SENTRY_DSN
};

// Option types (UNUSED is generally used for options that take a value as argument)
enum OptionType
{
    OPT_TYPE_UNUSED = 0,
    OPT_TYPE_DISABLED = 1,
    OPT_TYPE_ENABLED = 2
};

// Option descriptors, one for each entry of the OptionIndex enum
const optionparser::Descriptor usage[] =
{
    {
        OPT_IDX_UNKNOWN,    // index
        OPT_TYPE_UNUSED,    // type
        "",         // shortopt
        "",         // longopt
        SushiArg::Unknown, // check_arg
        "\nUSAGE: sushi -r|-j|-o|-d [options] \n\nOptions:" // help
    },
    {
        OPT_IDX_HELP,
        OPT_TYPE_UNUSED,
        "h?",
        "help",
        SushiArg::None,
        "\t\t-h --help \tPrint usage and exit."
    },
    {
        OPT_IDX_VERSION,
        OPT_TYPE_UNUSED,
        "v",
        "version",
        SushiArg::None,
        "\t\t-v --version \tPrint version information and exit."
    },
    {
        OPT_IDX_LOG_LEVEL,
        OPT_TYPE_UNUSED,
        "l",
        "log-level",
        SushiArg::NonEmpty,
        "\t\t-l <level>, --log-level=<level> \tSpecify minimum logging level, from ('debug', 'info', 'warning', 'error') [default=" ELKLOG_LOG_LEVEL_DEFAULT "]."
    },
    {
        OPT_IDX_LOG_FILE,
        OPT_TYPE_UNUSED,
        "L",
        "log-file",
        SushiArg::NonEmpty,
        "\t\t-L <filename>, --log-file=<filename> \tSpecify logging file destination [default=" ELKLOG_LOG_FILE_DEFAULT
      "]."
    },
    {
        OPT_IDX_LOG_FLUSH_INTERVAL,
        OPT_TYPE_UNUSED,
        "",
        "log-flush-interval",
        SushiArg::NonEmpty,
        "\t\t--log-flush-interval=<seconds> \tEnable flushing the log periodically and specify the interval."
    },
    {
        OPT_IDX_DUMP_PARAMETERS,
        OPT_TYPE_DISABLED,
        "",
        "dump-plugins",
        SushiArg::Optional,
        "\t\t--dump-plugins \tDump plugin and parameter data to stdout in JSON format."
    },
    {
        OPT_IDX_CONFIG_FILE,
        OPT_TYPE_UNUSED,
        "c",
        "config-file",
        SushiArg::NonEmpty,
        "\t\t-c <filename>, --config-file=<filename> \tSpecify configuration JSON file [default=" SUSHI_JSON_FILENAME_DEFAULT "]."
    },
    {
        OPT_IDX_USE_OFFLINE,
        OPT_TYPE_DISABLED,
        "o",
        "offline",
        SushiArg::Optional,
        "\t\t-o --offline \tUse offline file audio frontend."
    },
    {
        OPT_IDX_INPUT_FILE,
        OPT_TYPE_UNUSED,
        "i",
        "input",
        SushiArg::NonEmpty,
        "\t\t-i <filename>, --input=<filename> \tSpecify input file, required for --offline option."
    },
    {
        OPT_IDX_OUTPUT_FILE,
        OPT_TYPE_UNUSED,
        "O",
        "output",
        SushiArg::NonEmpty,
        "\t\t-O <filename>, --output=<filename> \tSpecify output file [default= (input_file).proc.wav]."
    },
    {
        OPT_IDX_USE_DUMMY,
        OPT_TYPE_DISABLED,
        "d",
        "dummy",
        SushiArg::Optional,
        "\t\t-d --dummy \tUse dummy audio frontend. Useful for debugging."
    },
    {
        OPT_IDX_USE_PORTAUDIO,
        OPT_TYPE_DISABLED,
        "a",
        "portaudio",
        SushiArg::Optional,
        "\t\t-a --portaudio \tUse PortAudio realtime audio frontend."
    },
    {
        OPT_IDX_USE_APPLE_COREAUDIO,
        OPT_TYPE_DISABLED,
        "",
        "coreaudio",
        SushiArg::Optional,
        "\t\t--coreaudio \tUse Apple CoreAudio realtime audio frontend."
    },
    {
        OPT_IDX_AUDIO_INPUT_DEVICE,
        OPT_TYPE_UNUSED,
        "",
        "audio-input-device",
        SushiArg::Optional,
        "\t\t--audio-input-device=<device id> \tIndex of the device to use for audio input with portaudio frontend [default=system default]"
    },
    {
        OPT_IDX_AUDIO_OUTPUT_DEVICE,
        OPT_TYPE_UNUSED,
        "",
        "audio-output-device",
        SushiArg::Optional,
        "\t\t--audio-output-device=<device id> \tIndex of the device to use for audio output with portaudio frontend [default=system default]"
    },
    {
        OPT_IDX_AUDIO_INPUT_DEVICE_UID,
        OPT_TYPE_UNUSED,
        "",
        "audio-input-device-uid",
        SushiArg::Optional,
        "\t\t--audio-input-device-uid=<device uid> \tUID of the device to use for audio input with Apple CoreAudio frontend [default=system default]"
    },
    {
        OPT_IDX_AUDIO_OUTPUT_DEVICE_UID,
        OPT_TYPE_UNUSED,
        "",
        "audio-output-device-uid",
        SushiArg::Optional,
        "\t\t--audio-output-device-uid=<device uid> \tUID of the device to use for audio output with Apple CoreAudio frontend [default=system default]"
    },
    {
        OPT_IDX_PA_SUGGESTED_INPUT_LATENCY,
        OPT_TYPE_UNUSED,
        "",
        "pa-suggested-input-latency",
        SushiArg::Optional,
        "\t\t--pa-suggested-input-latency=<latency> \tInput latency in seconds to suggest to portaudio. Will be rounded up to closest available latency depending on audio API [default=0.0]"
    },
    {
        OPT_IDX_PA_SUGGESTED_OUTPUT_LATENCY,
        OPT_TYPE_UNUSED,
        "",
        "pa-suggested-output-latency",
        SushiArg::Optional,
        "\t\t--pa-suggested-output-latency=<latency> \tOutput latency in seconds to suggest to portaudio. Will be rounded up to closest available latency depending on audio API [default=0.0]"
    },
    {
        OPT_IDX_DUMP_DEVICES,
        OPT_TYPE_DISABLED,
        "",
        "dump-audio-devices",
        SushiArg::Optional,
        "\t\t--dump-audio-devices \tDump available audio devices to stdout in JSON format. Requires a frontend to be specified."
    },
    {
        OPT_IDX_USE_JACK,
        OPT_TYPE_DISABLED,
        "j",
        "jack",
        SushiArg::Optional,
        "\t\t-j --jack \tUse Jack realtime audio frontend."
    },
    {
        OPT_IDX_CONNECT_PORTS,
        OPT_TYPE_DISABLED,
        "",
        "connect-ports",
        SushiArg::Optional,
        "\t\t--connect-ports \tTry to automatically connect Jack ports at startup."
    },
    {
        OPT_IDX_JACK_CLIENT,
        OPT_TYPE_UNUSED,
        "",
        "client-name",
        SushiArg::NonEmpty,
        "\t\t--client-name=<jack client name> \tSpecify name of Jack client [default=sushi]."
    },
    {
        OPT_IDX_JACK_SERVER,
        OPT_TYPE_UNUSED,
        "",
        "server-name",
        SushiArg::NonEmpty,
        "\t\t--server-name=<jack server name> \tSpecify name of Jack server to connect to [determined by jack if empty]."
    },
    {
        OPT_IDX_USE_XENOMAI_RASPA,
        OPT_TYPE_DISABLED,
        "r",
        "raspa",
        SushiArg::Optional,
        "\t\t-r --raspa \tUse Xenomai real-time frontend with RASPA driver."
    },
    {
        OPT_IDX_XENOMAI_DEBUG_MODE_SW,
        OPT_TYPE_DISABLED,
        "",
        "debug-mode-sw",
        SushiArg::Optional,
        "\t\t--debug-mode-sw \tBreak to debugger if a mode switch is detected (Xenomai only)."
    },
    {
        OPT_IDX_MULTICORE_PROCESSING,
        OPT_TYPE_UNUSED,
        "m",
        "multicore-processing",
        SushiArg::Numeric,
        "\t\t-m <n>, --multicore-processing=<n> \tProcess audio multithreaded with n cores [default n=1 (off)]."
    },
    {
        OPT_IDX_TIMINGS_STATISTICS,
        OPT_TYPE_DISABLED,
        "",
        "timing-statistics",
        SushiArg::Optional,
        "\t\t--timing-statistics \tEnable performance timings on all audio processors."
    },
    {
        OPT_IDX_DETAILED_TIMINGS,
        OPT_TYPE_UNUSED,
        "",
        "detailed-timings",
        SushiArg::NonEmpty,
        "\t\t--detailed-timings \tRecord timings for all audio callbacks for the given processor name. Use only for debug purposes as it will record significant amounts of data. Multiple processor names may be passed separated by semicolon"
    },
    {
        OPT_IDX_OSC_RECEIVE_PORT,
        OPT_TYPE_UNUSED,
        "p",
        "osc-rcv-port",
        SushiArg::NonEmpty,
        "\t\t-p <port> --osc-rcv-port=<port> \tPort to listen for OSC messages on [default port=" SUSHI_STRINGIZE(
         SUSHI_OSC_SERVER_PORT_DEFAULT) "]."
    },
    {
        OPT_IDX_OSC_SEND_PORT,
        OPT_TYPE_UNUSED,
        "",
        "osc-send-port",
        SushiArg::NonEmpty,
        "\t\t--osc-send-port=<port> \tPort to output OSC messages to [default port=" SUSHI_STRINGIZE(
         SUSHI_OSC_SEND_PORT_DEFAULT) "]."
    },
    {
        OPT_IDX_OSC_SEND_IP,
        OPT_TYPE_UNUSED,
        "",
        "osc-send-ip",
        SushiArg::NonEmpty,
        "\t\t--osc-send-ip=<ip> \tIP to output OSC messages to [default port=" SUSHI_STRINGIZE(
         SUSHI_OSC_SEND_IP_DEFAULT) "]."
    },
    {
        OPT_IDX_GRPC_LISTEN_ADDRESS,
        OPT_TYPE_UNUSED,
        "",
        "grpc-address",
        SushiArg::NonEmpty,
        "\t\t--grpc-address=<port> \tgRPC listening address in the format: address:port. By default accepts incoming connections from all ip:s [default port=" SUSHI_GRPC_LISTENING_PORT_DEFAULT "]."
    },
    {
        OPT_IDX_NO_OSC,
        OPT_TYPE_DISABLED,
        "",
        "no-osc",
        SushiArg::Optional,
        "\t\t--no-osc \tDisable Open Sound Control completely"
    },
    {
        OPT_IDX_NO_GRPC,
        OPT_TYPE_DISABLED,
        "",
        "no-grpc",
        SushiArg::Optional,
        "\t\t--no-grpc \tDisable gRPC Control completely"
    },
    {
        OPT_IDX_BASE_PLUGIN_PATH,
        OPT_TYPE_UNUSED,
        "",
        "base-plugin-path",
        SushiArg::NonEmpty,
        "\t\t--base-plugin-path=<path> \tSpecify a directory to be the base of plugin paths used in JSON / gRPC."
    },
    {
        OPT_IDX_SENTRY_CRASH_HANDLER,
        OPT_TYPE_UNUSED,
        "",
        "sentry-crash-handler",
        SushiArg::NonEmpty,
        "\t\t--sentry-crash-handler=<path/to/crash_handler> \tSet the path to the crash handler to use for sentry reports [default path=" SUSHI_STRINGIZE(SUSHI_SENTRY_CRASH_HANDLER_PATH_DEFAULT) "]."
    },
    {
        OPT_IDX_SENTRY_DSN,
        OPT_TYPE_UNUSED,
        "",
        "sentry-dsn",
        SushiArg::NonEmpty,
        "\t\t--sentry-dsn=<dsn.address> \tSet the DSN that sentry should upload crash logs to [default address=" SUSHI_STRINGIZE(SUSHI_SENTRY_DSN_DEFAULT) "]."
    },
    // Don't touch this one (sets default values for optionparser library)
    { 0, 0, nullptr, nullptr, nullptr, nullptr}
};

} // end namespace sushi

#endif // SUSHI_OPTIONS_H


================================================
FILE: include/sushi/parameter_dump.h
================================================
/*
 * Copyright 2017-2023 Elk Audio AB
 *
 * SUSHI is free software: you can redistribute it and/or modify it under the terms of
 * the GNU Affero General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * SUSHI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE. See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License along with
 * SUSHI. If not, see http://www.gnu.org/licenses/
 */

/**
 * @brief Utility functions for writing parameter names to a file.
 * @Copyright 2017-2023 Elk Audio AB, Stockholm
 */

#ifndef SUSHI_PARAMETER_DUMP_H
#define SUSHI_PARAMETER_DUMP_H

#include "rapidjson/document.h"

namespace sushi {

namespace control {
    class SushiControl;
}

rapidjson::Document generate_processor_parameter_document(sushi::control::SushiControl* engine_controller);

} // end namespace sushi


#endif //SUSHI_PARAMETER_DUMP_H


================================================
FILE: include/sushi/portaudio_devices_dump.h
================================================
/*
 * Copyright 2017-2023 Elk Audio AB
 *
 * SUSHI is free software: you can redistribute it and/or modify it under the terms of
 * the GNU Affero General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * SUSHI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE. See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License along with
 * SUSHI. If not, see http://www.gnu.org/licenses/
 */

/**
 * @brief Utility functions for dumping Portaudio devices info
 * @Copyright 2017-2023 Elk Audio AB, Stockholm
 */

#include "rapidjson/document.h"

namespace sushi {

/**
 * @brief Retrieve Portaudio's registered devices information.
 *        Can be queried before instantiating an actual PortaudioFrontend
 *
 * @return Device information list in JSON format
 */
rapidjson::Document generate_portaudio_devices_info_document();

} // end namespace sushi



================================================
FILE: include/sushi/reactive_factory.h
================================================
/*
 * Copyright 2017-2023 Elk Audio AB
 *
 * SUSHI is free software: you can redistribute it and/or modify it under the terms of
 * the GNU Affero General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * SUSHI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE. See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License along with
 * SUSHI. If not, see http://www.gnu.org/licenses/
 */

/**
 * @brief Public Sushi factory for reactive use.
 * @copyright 2017-2023 Elk Audio AB, Stockholm
 */

#ifndef REACTIVE_FACTORY_H
#define REACTIVE_FACTORY_H

#include "factory_interface.h"
#include "sushi.h"

namespace sushi {

namespace internal {
    class ReactiveFactoryImplementation;
}

class RtController;

class ReactiveFactory : public FactoryInterface
{
public:
    ReactiveFactory();
    ~ReactiveFactory() override;

    [[nodiscard]] std::pair<std::unique_ptr<Sushi>, Status> new_instance(SushiOptions& options) override;

    /**
     * @brief Returns an instance of a RealTimeController, if new_instance(...) completed successfully.
     *        If not, it returns an empty unique_ptr.
     * @return A unique_ptr with a RtController sub-class, or not, depending on InitStatus.
     */
    [[nodiscard]] std::unique_ptr<RtController> rt_controller();

private:
    std::unique_ptr<internal::ReactiveFactoryImplementation> _implementation;
};

} // end namespace sushi

#endif // REACTIVE_FACTORY_H


================================================
FILE: include/sushi/rt_controller.h
================================================
/*
* Copyright 2017-2022 Modern Ancient Instruments Networked AB, dba Elk
*
* SUSHI is free software: you can redistribute it and/or modify it under the terms of
* the GNU Affero General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* SUSHI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with
* SUSHI. If not, see http://www.gnu.org/licenses/
*/

#ifndef REAL_TIME_CONTROLLER_H
#define REAL_TIME_CONTROLLER_H

#include <functional>

#include "control_interface.h"
#include "sushi_time.h"
#include "types.h"
#include "sample_buffer.h"

namespace sushi {

enum class TransportPositionSource
{
    EXTERNAL,
    CALCULATED
};

using ReactiveMidiCallback = std::function<void(int output, MidiDataByte data, Time timestamp)>;

/**
 * @brief The API for the methods which can safely be called from a real-time context to interact with Sushi as a library.
 */
class RtController
{
public:
    RtController() = default;
    virtual ~RtController() = default;

    /// For Transport:
    /////////////////////////////////////////////////////////////

    /**
     * @brief Set the tempo of the Sushi transport.
     *        (can be called from a real-time context).
     * @param tempo
     */
    virtual void set_tempo(float tempo) = 0;

    /**
     * @brief Set the time signature of the Sushi transport.
     *        (can be called from a real-time context).
     * @param time_signature
     */
    virtual void set_time_signature(control::TimeSignature time_signature) = 0;

    /**
     * @brief Set the PlayingMode of the Sushi transport.
     *        (can be called from a real-time context).
     * @param mode
     */
    virtual void set_playing_mode(control::PlayingMode mode) = 0;

    /**
     * @brief Set the beat time of the Sushi transport.
     *        (can be called from a real-time context).
     * @param beat_time
     * @return true if the beat time was set, false if PositionSource is not set to EXTERNAL
     */
    virtual bool set_current_beats(double beat_time) = 0;

    /**
     * @brief Set the bar beat count of the Sushi transport.
     *        (can be called from a real-time context).
     * @param bar_beat_count
     * @return true if the bar beat time was set, false if PositionSource is not set to EXTERNAL
     */
    virtual bool set_current_bar_beats(double bar_beat_count) = 0;

    /**
     * @brief Sets which source to use for the beat count position: the internally calculated one, or the one set
     *        using the set_current_beats method below.
     * @param TransportPositionSource Enum, EXTERNAL / CALCULATED
     */
    virtual void set_position_source(TransportPositionSource ps) = 0;

    /// For Audio:
    /////////////////////////////////////////////////////////////

    /**
     * @brief Method to invoke from the host's audio callback.
     * @param in_buffer Input sample buffer
     * @param out_buffer Output sample buffer
     * @param timestamp timestamp for call
     */

    virtual void process_audio(ChunkSampleBuffer& in_buffer,
                               ChunkSampleBuffer& out_buffer,
                               Time timestamp) = 0;

    /**
     * @brief Call before the first call to process_audio() when resuming from an interrupt or xrun to
     *        notify sushi that audio processing was interrupted and that there may be gaps in the audio
     * @param duration The length of the interruption
     */
    virtual void notify_interrupted_audio(Time duration) = 0;

    /// For MIDI:
    /////////////////////////////////////////////////////////////

    /**
     * @brief Call to pass MIDI input to Sushi
     * @param input Currently assumed to always be 0 since the frontend only supports a single input device.
     * @param data MidiDataByte
     * @param timestamp Sushi Time timestamp for message
     */
    virtual void receive_midi(int input, MidiDataByte data, Time timestamp) = 0;

    /**
     * @brief Assign a callback which is invoked when a MIDI message is generated from inside Sushi.
     *        (Not safe to call from a real-time context, and should only really be called once).
     * @param callback
     */
    virtual void set_midi_callback(ReactiveMidiCallback&& callback) = 0;

    /**
     * @brief If the host doesn't provide a timestamp, this method can be used to calculate it,
     *        based on the sample count from session start.
     * @return The currently calculated Timestamp.
     */
    virtual sushi::Time calculate_timestamp_from_start(float sample_rate) const = 0;

    /**
     * @brief Call this at the end of each ProcessBlock, to update the sample count and timestamp used for
     *        time and sample offset calculations.
     * @param sample_count
     * @param timestamp
     */
    virtual void increment_samples_since_start(int64_t sample_count, Time timestamp) = 0;
};

} // end namespace sushi

#endif //REAL_TIME_CONTROLLER_H


================================================
FILE: include/sushi/sample_buffer.h
================================================
/*
 * Copyright 2017-2023 Elk Audio AB
 *
 * SUSHI is free software: you can redistribute it and/or modify it under the terms of
 * the GNU Affero General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * SUSHI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE. See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License along with
 * SUSHI. If not, see http://www.gnu.org/licenses/
 */

/**
 * @brief General purpose multichannel audio buffer class
 * @Copyright 2017-2023 Elk Audio AB, Stockholm
 */

#ifndef SUSHI_SAMPLEBUFFER_H
#define SUSHI_SAMPLEBUFFER_H

#include <algorithm>
#include <cassert>
#include <cmath>

#include "constants.h"

namespace sushi {

constexpr int LEFT_CHANNEL_INDEX = 0;
constexpr int RIGHT_CHANNEL_INDEX = 1;

template<int size>
class SampleBuffer;

template<int size>
void swap(SampleBuffer<size>& lhs, SampleBuffer<size>& rhs)
{
    std::swap(lhs._channel_count, rhs._channel_count);
    std::swap(lhs._own_buffer, rhs._own_buffer);
    std::swap(lhs._buffer, rhs._buffer);
}

template<int size>
class SampleBuffer
{
public:
    /**
     * @brief Construct a zeroed buffer with specified number of channels
     */
    explicit SampleBuffer(int channel_count) : _channel_count(channel_count),
                                               _own_buffer(true),
                                               _buffer(new float[static_cast<uint64_t>(size * channel_count)])
    {
        clear();
    }

    /**
     * @brief Construct an empty buffer object with 0 channels.
     */
    SampleBuffer() noexcept : _channel_count(0),
                              _own_buffer(true),
                              _buffer(nullptr)
    {}

    /**
     * @brief Copy constructor.
     */
    SampleBuffer(const SampleBuffer &o) : _channel_count(o._channel_count),
                                          _own_buffer(o._own_buffer)
    {
        if (o._own_buffer)
        {
            _buffer = new float[size * o._channel_count];
            std::copy(o._buffer, o._buffer + (size * o._channel_count), _buffer);
        }
        else
        {
            _buffer = o._buffer;
        }
    }

    /**
     * @brief Move constructor.
     */
    SampleBuffer(SampleBuffer &&o) noexcept : _channel_count(o._channel_count),
                                              _own_buffer(o._own_buffer),
                                              _buffer(o._buffer)
    {
        o._buffer = nullptr;
    }

    /**
     * @brief Destroy the buffer.
     */
    ~SampleBuffer()
    {
        if (_own_buffer)
        {
            delete[] _buffer;
        }
    }

    /**
     * @brief Assign to this buffer.
     */
    SampleBuffer &operator=(const SampleBuffer &o)
    {
        if (this != &o)  // Avoid self-assignment
        {
            if (_own_buffer && o._own_buffer)
            {
                if (_channel_count != o._channel_count)
                {
                    delete[] _buffer;
                    _buffer = (o._channel_count > 0)? (new float[size * o._channel_count]) : nullptr;
                    _channel_count = o._channel_count;
                }
            }
            else
            {
                /* Assigning to or from a non owning buffer is only allowed if their
                 * channel count matches. In that case the underlying sample data is
                 * copied.
                 * If their sample counts differs this might trigger a (re)allocation
                 * of the internal data buffer, This would need to be resolved by
                 * either forcing the SampleBuffer owning the data to change its
                 * channel count or turn the non-owning SampleBuffer into a normal
                 * SampleBuffer that owns its data buffer, and hence losing the
                 * connection to the SampleBuffer that originally owned the data.
                 * Both of which will have unexpected, and most likely unwanted, side
                 * effects. */
                assert(_channel_count == o._channel_count);
            }
            std::copy(o._buffer, o._buffer + (size * o._channel_count), _buffer);
        }
        return *this;
    }

    /**
     * @brief Assign to this buffer using move semantics.
     */
    SampleBuffer &operator=(SampleBuffer &&o) noexcept
    {
        if (this != &o)  // Avoid self-assignment
        {
            if (_own_buffer)
            {
                delete[] _buffer;
            }
            _channel_count = o._channel_count;
            _own_buffer = o._own_buffer;
            _buffer = o._buffer;
            o._buffer = nullptr;
        }
        return *this;
    }

    /**
     * @brief Create a SampleBuffer from another SampleBuffer, without copying or
     *        taking ownership of the data. Optionally only a subset of
     *        the source buffers channels can be wrapped.
     * @param source The SampleBuffer whose data is wrapped.
     * @param start_channel The first channel to wrap. Defaults to 0.
     * @param number_of_channels Must not exceed the channel count of the source buffer
     *                           minus start_channel.
     * @return The created, non-owning SampleBuffer.
     */
    static SampleBuffer create_non_owning_buffer(SampleBuffer& source,
                                                 int start_channel,
                                                 int number_of_channels)
    {
        assert(number_of_channels + start_channel <= source._channel_count);

        SampleBuffer buffer;
        buffer._own_buffer = false;
        buffer._channel_count = number_of_channels;
        buffer._buffer = source._buffer + size * start_channel;
        return buffer;
    }

    /**
     * @brief Defaulted version of the above function.
     */
    static SampleBuffer create_non_owning_buffer(SampleBuffer& source)
    {
        return create_non_owning_buffer(source, 0, source.channel_count());
    }

    /**
     * @brief Create a SampleBuffer by wrapping a raw data pointer.
     *
     * @param data raw pointer to data stored in the same format of SampleBuffer storage
     * @param start_channel Index of first channel to wrap.
     * @param start_channel The first channel to wrap. Defaults to 0.
     * @param number_of_channels Must not exceed the channel count of the source buffer
     *                           minus start_channel.
     * @return The created, non-owning SampleBuffer.
     */
    static SampleBuffer create_from_raw_pointer(float* data,
                                                int start_channel,
                                                int number_of_channels)
    {
        SampleBuffer buffer;
        buffer._own_buffer = false;
        buffer._channel_count = number_of_channels;
        buffer._buffer = data + size * start_channel;
        return buffer;
    }

    /**
     * @brief Zero the entire buffer
     */
    void clear()
    {
        std::fill(_buffer, _buffer + (size * _channel_count), 0.0f);
    }

    /**
    * @brief Returns a writeable pointer to a specific channel in the buffer. No bounds checking.
    */
    float* channel(int channel)
    {
        return _buffer + channel * size;
    }

    /**
    * @brief Returns a read-only pointer to a specific channel in the buffer. No bounds checking.
    */
    const float* channel(int channel) const
    {
        return _buffer + channel * size;
    }

    /**
     * @brief Gets the number of channels in the buffer.
     */
    int channel_count() const
    {
        return _channel_count;
    }

    /**
     * @brief Copy interleaved audio data from interleaved_buf to this buffer.
     */
    void from_interleaved(const float* interleaved_buf)
    {
        switch (_channel_count)
        {
            case 2:  // Most common case, others are mostly included for future compatibility
            {
                float* l_in = _buffer;
                float* r_in = _buffer + size;
                for (int n = 0; n < size; ++n)
                {
                    *l_in++ = *interleaved_buf++;
                    *r_in++ = *interleaved_buf++;
                }
                break;
            }
            case 1:
            {
                std::copy(interleaved_buf, interleaved_buf + size, _buffer);
                break;
            }
            default:
            {
                for (int n = 0; n < size; ++n)
                {
                    for (int c = 0; c < _channel_count; ++c)
                    {
                        _buffer[n + c * _channel_count] = *interleaved_buf++;
                    }
                }
            }
        }
    }

    /**
     * @brief Copy buffer data in interleaved format to interleaved_buf
     */
    void to_interleaved(float* interleaved_buf) const
    {
        switch (_channel_count)
        {
            case 2:  // Most common case, others are mostly included for future compatibility
            {
                float* l_out = _buffer;
                float* r_out = _buffer + size;
                for (int n = 0; n < size; ++n)
                {
                    *interleaved_buf++ = *l_out++;
                    *interleaved_buf++ = *r_out++;
                }
                break;
            }
            case 1:
            {
                std::copy(_buffer, _buffer + size, interleaved_buf);
                break;
            }
            default:
            {
                for (int n = 0; n < size; ++n)
                {
                    for (int c = 0; c < _channel_count; ++c)
                    {
                        *interleaved_buf++ = _buffer[n + c * size];
                    }
                }
            }
        }
    }

    /**
     * @brief Apply a fixed gain to the entire buffer.
     */
    void apply_gain(float gain)
    {
        for (int i = 0; i < size * _channel_count; ++i)
        {
            _buffer[i] *= gain;
        }
    }

    /**
    * @brief Apply a fixed gain to a given channel.
    */
    void apply_gain(float gain, int channel)
    {
        float* data = _buffer + size * channel;
        for (int i = 0; i < size; ++i)
        {
            data[i] *= gain;
        }
    }

    /**
     * @brief Replace the contents of the buffer with that of another buffer
     * @param source SampleBuffer with either 1 channel or the same number of
     *               channels as the destination buffer
     */
    void replace(const SampleBuffer &source)
    {
        assert(source.channel_count() == 1 || source.channel_count() == this->channel_count());

        if (source.channel_count() == 1) // mono input, copy to all dest channels
        {
            for (int channel = 0; channel < _channel_count; ++channel)
            {
                std::copy(source._buffer, source._buffer + size, _buffer + channel * size);
            }
        }
        else
        {
            std::copy(source._buffer, source._buffer + _channel_count * size, _buffer);
        }
    }

    /**
     * @brief Copy data channel by channel into this buffer from source buffer. No bounds checking.
     */
    void replace(int dest_channel, int source_channel, const SampleBuffer &source)
    {
        assert(source_channel < source.channel_count() && dest_channel < this->channel_count());
        std::copy(source.channel(source_channel),
                  source.channel(source_channel) + size,
                  _buffer + (dest_channel * size));
    }

    /**
     * @brief Sums the content of source into this buffer.
     * @param source SampleBuffer with either 1 channel or the same number of
     *               channels as the destination buffer
     */
    void add(const SampleBuffer &source)
    {
        assert(source.channel_count() == 1 || source.channel_count() == this->channel_count());

        if (source.channel_count() == 1) // mono input, add to all dest channels
        {
            for (int channel = 0; channel < _channel_count; ++channel)
            {
                float* dest = _buffer + size * channel;
                for (int i = 0; i < size; ++i)
                {
                    dest[i] += source._buffer[i];
                }
            }
        } else if (source.channel_count() == _channel_count)
        {
            for (int i = 0; i < size * _channel_count; ++i)
            {
                _buffer[i] += source._buffer[i];
            }
        }
    }


    /**
     * @brief Sums one channel of source buffer into one channel of the buffer.
     */
    void add(int dest_channel, int source_channel, const SampleBuffer& source)
    {
        float* source_data = source._buffer + size * source_channel;
        float* dest_data = _buffer + size * dest_channel;
        for (int i = 0; i < size; ++i)
        {
            dest_data[i] += source_data[i];
        }
    }

    /**
     * @brief Sums the content of SampleBuffer source into this buffer after applying a gain.
     *
     * source has to be either a 1 channel buffer or have the same number of channels
     * as the destination buffer.
    */
    void add_with_gain(const SampleBuffer &source, float gain)
    {
        assert(source.channel_count() == 1 || source.channel_count() == this->channel_count());

        if (source.channel_count() == 1)
        {
            for (int channel = 0; channel < _channel_count; ++channel)
            {
                float* dest = _buffer + size * channel;
                for (int i = 0; i < size; ++i)
                {
                    dest[i] += source._buffer[i] * gain;
                }
            }
        } else if (source.channel_count() == _channel_count)
        {
            for (int i = 0; i < size * _channel_count; ++i)
            {
                _buffer[i] += source._buffer[i] * gain;
            }
        }
    }

    /**
     * @brief Sums one channel of source buffer into one channel of the buffer after applying gain.
     */
    void add_with_gain(int dest_channel, int source_channel, const SampleBuffer& source, float gain)
    {
        float* source_data = source._buffer + size * source_channel;
        float* dest_data = _buffer + size * dest_channel;
        for (int i = 0; i < size; ++i)
        {
            dest_data[i] += source_data[i] * gain;
        }
    }

    /**
     * @brief Sums the content of SampleBuffer source into this buffer after applying a
     *        linear gain ramp.
     *
     * @param source The buffer to copy from. Has to be either a 1 channel buffer or have
     *        the same number of channels as this buffer
     * @param start The value to start the ramp from
     * @param end The value to end the ramp
    */
    void add_with_ramp(const SampleBuffer &source, float start, float end)
    {
        assert(source.channel_count() == 1 || source.channel_count() == _channel_count);

        float inc = (end - start) / (size - 1);
        if (source.channel_count() == 1)
        {
            for (int channel = 0; channel < _channel_count; ++channel)
            {
                float* dest = _buffer + size * channel;
                for (int i = 0; i < size; ++i)
                {
                    dest[i] += source._buffer[i] * (start + i * inc);
 
Download .txt
gitextract_9o1ns6zt/

├── .clang-format
├── .gitignore
├── CMakeLists.txt
├── CONTRIBUTING.md
├── COPYING
├── HISTORY.md
├── LICENSE.md
├── README.md
├── apps/
│   ├── CMakeLists.txt
│   └── main.cpp
├── bitbucket-pipelines.yml
├── docs/
│   └── LIBRARY.md
├── include/
│   ├── sushi/
│   │   ├── compile_time_settings.h
│   │   ├── constants.h
│   │   ├── control_interface.h
│   │   ├── control_notifications.h
│   │   ├── coreaudio_devices_dump.h
│   │   ├── elk_sentry_log_sink.h
│   │   ├── factory_interface.h
│   │   ├── offline_factory.h
│   │   ├── options.h
│   │   ├── parameter_dump.h
│   │   ├── portaudio_devices_dump.h
│   │   ├── reactive_factory.h
│   │   ├── rt_controller.h
│   │   ├── sample_buffer.h
│   │   ├── standalone_factory.h
│   │   ├── sushi.h
│   │   ├── sushi_time.h
│   │   ├── terminal_utilities.h
│   │   ├── types.h
│   │   └── utils.h
│   └── version.h.in
├── misc/
│   ├── .gitkeep
│   ├── README.md
│   └── config_files/
│       ├── arp_peakmeter_osc_broadcast.json
│       ├── config_play_arp_link_midi_out.json
│       ├── cv_lfo.json
│       ├── cv_to_cutoff.json
│       ├── cv_to_synth.json
│       ├── empty.json
│       ├── freeverb_aux.json
│       ├── fx.json
│       ├── multi_track.json
│       ├── multichannel_plugin.json
│       ├── play_arp_mda_link.json
│       ├── play_brickworks_fx.json
│       ├── play_brickworks_synth.json
│       ├── play_cv_arp.json
│       ├── play_lv2.json
│       ├── play_lv2_jx10.json
│       ├── play_master_gain.json
│       ├── play_vst2.json
│       ├── play_vst3.json
│       ├── play_wav_streamer.json
│       ├── prepost_tracks.json
│       ├── rt_midi.json
│       ├── send_return_seq.json
│       └── vst_8_ch.json
├── rpc_interface/
│   ├── CMakeLists.txt
│   ├── include/
│   │   └── sushi_rpc/
│   │       └── grpc_server.h
│   └── src/
│       ├── async_service_call_data.cpp
│       ├── async_service_call_data.h
│       ├── control_service.cpp
│       ├── control_service.h
│       └── grpc_server.cpp
├── src/
│   ├── audio_frontends/
│   │   ├── apple_coreaudio/
│   │   │   ├── apple_coreaudio_device.h
│   │   │   ├── apple_coreaudio_device.mm
│   │   │   ├── apple_coreaudio_object.cpp
│   │   │   ├── apple_coreaudio_object.h
│   │   │   ├── apple_coreaudio_system_object.h
│   │   │   ├── apple_coreaudio_utils.cpp
│   │   │   └── apple_coreaudio_utils.h
│   │   ├── apple_coreaudio_frontend.cpp
│   │   ├── apple_coreaudio_frontend.h
│   │   ├── audio_frontend_internals.h
│   │   ├── base_audio_frontend.cpp
│   │   ├── base_audio_frontend.h
│   │   ├── coreaudio_devices_dump.cpp
│   │   ├── jack_frontend.cpp
│   │   ├── jack_frontend.h
│   │   ├── offline_frontend.cpp
│   │   ├── offline_frontend.h
│   │   ├── portaudio_devices_dump.cpp
│   │   ├── portaudio_frontend.cpp
│   │   ├── portaudio_frontend.h
│   │   ├── reactive_frontend.cpp
│   │   ├── reactive_frontend.h
│   │   ├── xenomai_raspa_frontend.cpp
│   │   └── xenomai_raspa_frontend.h
│   ├── concrete_sushi.cpp
│   ├── concrete_sushi.h
│   ├── control_frontends/
│   │   ├── alsa_midi_frontend.cpp
│   │   ├── alsa_midi_frontend.h
│   │   ├── base_control_frontend.cpp
│   │   ├── base_control_frontend.h
│   │   ├── base_midi_frontend.h
│   │   ├── osc_frontend.cpp
│   │   ├── osc_frontend.h
│   │   ├── osc_utils.h
│   │   ├── oscpack_osc_messenger.cpp
│   │   ├── oscpack_osc_messenger.h
│   │   ├── reactive_midi_frontend.cpp
│   │   ├── reactive_midi_frontend.h
│   │   ├── rt_midi_frontend.cpp
│   │   └── rt_midi_frontend.h
│   ├── dsp_library/
│   │   ├── biquad_filter.cpp
│   │   ├── biquad_filter.h
│   │   ├── envelopes.h
│   │   ├── master_limiter.h
│   │   ├── sample_wrapper.h
│   │   └── value_smoother.h
│   ├── engine/
│   │   ├── audio_engine.cpp
│   │   ├── audio_engine.h
│   │   ├── audio_graph.cpp
│   │   ├── audio_graph.h
│   │   ├── base_engine.h
│   │   ├── base_event_dispatcher.h
│   │   ├── base_processor_container.h
│   │   ├── connection_storage.h
│   │   ├── controller/
│   │   │   ├── audio_graph_controller.cpp
│   │   │   ├── audio_graph_controller.h
│   │   │   ├── audio_routing_controller.cpp
│   │   │   ├── audio_routing_controller.h
│   │   │   ├── completion_sender.h
│   │   │   ├── controller.cpp
│   │   │   ├── controller.h
│   │   │   ├── controller_common.h
│   │   │   ├── cv_gate_controller.cpp
│   │   │   ├── cv_gate_controller.h
│   │   │   ├── keyboard_controller.cpp
│   │   │   ├── keyboard_controller.h
│   │   │   ├── midi_controller.cpp
│   │   │   ├── midi_controller.h
│   │   │   ├── osc_controller.cpp
│   │   │   ├── osc_controller.h
│   │   │   ├── parameter_controller.cpp
│   │   │   ├── parameter_controller.h
│   │   │   ├── program_controller.cpp
│   │   │   ├── program_controller.h
│   │   │   ├── real_time_controller.cpp
│   │   │   ├── real_time_controller.h
│   │   │   ├── session_controller.cpp
│   │   │   ├── session_controller.h
│   │   │   ├── system_controller.cpp
│   │   │   ├── system_controller.h
│   │   │   ├── timing_controller.cpp
│   │   │   ├── timing_controller.h
│   │   │   ├── transport_controller.cpp
│   │   │   └── transport_controller.h
│   │   ├── event_dispatcher.cpp
│   │   ├── event_dispatcher.h
│   │   ├── event_timer.cpp
│   │   ├── event_timer.h
│   │   ├── host_control.h
│   │   ├── json_configurator.cpp
│   │   ├── json_configurator.h
│   │   ├── json_schemas/
│   │   │   ├── cv_gate_schema.json
│   │   │   ├── events_schema.json
│   │   │   ├── host_config_schema.json
│   │   │   ├── midi_schema.json
│   │   │   ├── osc_schema.json
│   │   │   ├── state_schema.json
│   │   │   └── tracks_schema.json
│   │   ├── link_dummy.h
│   │   ├── midi_dispatcher.cpp
│   │   ├── midi_dispatcher.h
│   │   ├── midi_receiver.h
│   │   ├── parameter_manager.cpp
│   │   ├── parameter_manager.h
│   │   ├── plugin_library.cpp
│   │   ├── plugin_library.h
│   │   ├── processor_container.cpp
│   │   ├── processor_container.h
│   │   ├── receiver.cpp
│   │   ├── receiver.h
│   │   ├── track.cpp
│   │   ├── track.h
│   │   ├── transport.cpp
│   │   └── transport.h
│   ├── factories/
│   │   ├── base_factory.cpp
│   │   ├── base_factory.h
│   │   ├── offline_factory.cpp
│   │   ├── offline_factory_implementation.cpp
│   │   ├── offline_factory_implementation.h
│   │   ├── reactive_factory.cpp
│   │   ├── reactive_factory_implementation.cpp
│   │   ├── reactive_factory_implementation.h
│   │   ├── standalone_factory.cpp
│   │   ├── standalone_factory_implementation.cpp
│   │   └── standalone_factory_implementation.h
│   ├── library/
│   │   ├── base_performance_timer.h
│   │   ├── base_processor_factory.h
│   │   ├── connection_types.h
│   │   ├── event.cpp
│   │   ├── event.h
│   │   ├── event_interface.h
│   │   ├── fixed_stack.h
│   │   ├── id_generator.h
│   │   ├── internal_plugin.cpp
│   │   ├── internal_plugin.h
│   │   ├── internal_processor_factory.cpp
│   │   ├── internal_processor_factory.h
│   │   ├── lv2/
│   │   │   ├── lv2_control.cpp
│   │   │   ├── lv2_control.h
│   │   │   ├── lv2_features.cpp
│   │   │   ├── lv2_features.h
│   │   │   ├── lv2_host_nodes.h
│   │   │   ├── lv2_model.cpp
│   │   │   ├── lv2_model.h
│   │   │   ├── lv2_port.cpp
│   │   │   ├── lv2_port.h
│   │   │   ├── lv2_processor_factory.cpp
│   │   │   ├── lv2_processor_factory.h
│   │   │   ├── lv2_state.cpp
│   │   │   ├── lv2_state.h
│   │   │   ├── lv2_worker.cpp
│   │   │   ├── lv2_worker.h
│   │   │   ├── lv2_wrapper.cpp
│   │   │   └── lv2_wrapper.h
│   │   ├── midi_decoder.cpp
│   │   ├── midi_decoder.h
│   │   ├── midi_encoder.cpp
│   │   ├── midi_encoder.h
│   │   ├── parameter_dump.cpp
│   │   ├── performance_timer.cpp
│   │   ├── performance_timer.h
│   │   ├── plugin_parameters.h
│   │   ├── plugin_registry.cpp
│   │   ├── plugin_registry.h
│   │   ├── processor.cpp
│   │   ├── processor.h
│   │   ├── processor_state.cpp
│   │   ├── processor_state.h
│   │   ├── rt_event.h
│   │   ├── rt_event_fifo.h
│   │   ├── rt_event_pipe.h
│   │   ├── simple_fifo.h
│   │   ├── spinlock.h
│   │   ├── synchronised_fifo.h
│   │   ├── vst2x/
│   │   │   ├── vst2x_host_callback.cpp
│   │   │   ├── vst2x_host_callback.h
│   │   │   ├── vst2x_midi_event_fifo.h
│   │   │   ├── vst2x_plugin_loader.cpp
│   │   │   ├── vst2x_plugin_loader.h
│   │   │   ├── vst2x_processor_factory.cpp
│   │   │   ├── vst2x_processor_factory.h
│   │   │   ├── vst2x_wrapper.cpp
│   │   │   └── vst2x_wrapper.h
│   │   └── vst3x/
│   │       ├── vst3x_file_utils.cpp
│   │       ├── vst3x_file_utils.h
│   │       ├── vst3x_host_app.cpp
│   │       ├── vst3x_host_app.h
│   │       ├── vst3x_processor_factory.cpp
│   │       ├── vst3x_processor_factory.h
│   │       ├── vst3x_utils.cpp
│   │       ├── vst3x_utils.h
│   │       ├── vst3x_wrapper.cpp
│   │       └── vst3x_wrapper.h
│   ├── plugins/
│   │   ├── arpeggiator_plugin.cpp
│   │   ├── arpeggiator_plugin.h
│   │   ├── brickworks/
│   │   │   ├── bitcrusher_plugin.cpp
│   │   │   ├── bitcrusher_plugin.h
│   │   │   ├── cab_sim_plugin.cpp
│   │   │   ├── cab_sim_plugin.h
│   │   │   ├── chorus_plugin.cpp
│   │   │   ├── chorus_plugin.h
│   │   │   ├── clip_plugin.cpp
│   │   │   ├── clip_plugin.h
│   │   │   ├── combdelay_plugin.cpp
│   │   │   ├── combdelay_plugin.h
│   │   │   ├── compressor_plugin.cpp
│   │   │   ├── compressor_plugin.h
│   │   │   ├── dist_plugin.cpp
│   │   │   ├── dist_plugin.h
│   │   │   ├── drive_plugin.cpp
│   │   │   ├── drive_plugin.h
│   │   │   ├── eq3band_plugin.cpp
│   │   │   ├── eq3band_plugin.h
│   │   │   ├── flanger_plugin.cpp
│   │   │   ├── flanger_plugin.h
│   │   │   ├── fuzz_plugin.cpp
│   │   │   ├── fuzz_plugin.h
│   │   │   ├── highpass_plugin.cpp
│   │   │   ├── highpass_plugin.h
│   │   │   ├── multi_filter_plugin.cpp
│   │   │   ├── multi_filter_plugin.h
│   │   │   ├── noise_gate_plugin.cpp
│   │   │   ├── noise_gate_plugin.h
│   │   │   ├── notch_plugin.cpp
│   │   │   ├── notch_plugin.h
│   │   │   ├── phaser_plugin.cpp
│   │   │   ├── phaser_plugin.h
│   │   │   ├── ring_mod_plugin.cpp
│   │   │   ├── ring_mod_plugin.h
│   │   │   ├── saturation_plugin.cpp
│   │   │   ├── saturation_plugin.h
│   │   │   ├── simple_synth_plugin.cpp
│   │   │   ├── simple_synth_plugin.h
│   │   │   ├── tremolo_plugin.cpp
│   │   │   ├── tremolo_plugin.h
│   │   │   ├── vibrato_plugin.cpp
│   │   │   ├── vibrato_plugin.h
│   │   │   ├── wah_plugin.cpp
│   │   │   └── wah_plugin.h
│   │   ├── control_to_cv_plugin.cpp
│   │   ├── control_to_cv_plugin.h
│   │   ├── cv_to_control_plugin.cpp
│   │   ├── cv_to_control_plugin.h
│   │   ├── equalizer_plugin.cpp
│   │   ├── equalizer_plugin.h
│   │   ├── freeverb_plugin.cpp
│   │   ├── freeverb_plugin.h
│   │   ├── gain_plugin.cpp
│   │   ├── gain_plugin.h
│   │   ├── lfo_plugin.cpp
│   │   ├── lfo_plugin.h
│   │   ├── mono_summing_plugin.cpp
│   │   ├── mono_summing_plugin.h
│   │   ├── passthrough_plugin.cpp
│   │   ├── passthrough_plugin.h
│   │   ├── peak_meter_plugin.cpp
│   │   ├── peak_meter_plugin.h
│   │   ├── return_plugin.cpp
│   │   ├── return_plugin.h
│   │   ├── sample_delay_plugin.cpp
│   │   ├── sample_delay_plugin.h
│   │   ├── sample_player_plugin.cpp
│   │   ├── sample_player_plugin.h
│   │   ├── sample_player_voice.cpp
│   │   ├── sample_player_voice.h
│   │   ├── send_plugin.cpp
│   │   ├── send_plugin.h
│   │   ├── send_return_factory.cpp
│   │   ├── send_return_factory.h
│   │   ├── step_sequencer_plugin.cpp
│   │   ├── step_sequencer_plugin.h
│   │   ├── stereo_mixer_plugin.cpp
│   │   ├── stereo_mixer_plugin.h
│   │   ├── transposer_plugin.cpp
│   │   ├── transposer_plugin.h
│   │   ├── wav_streamer_plugin.cpp
│   │   ├── wav_streamer_plugin.h
│   │   ├── wav_writer_plugin.cpp
│   │   └── wav_writer_plugin.h
│   └── utils.cpp
├── test/
│   ├── CMakeLists.txt
│   ├── data/
│   │   ├── config.json
│   │   ├── config_single_stereo.json
│   │   └── master_limiter_test_data.h
│   ├── resources/
│   │   └── Info.plist.in
│   └── unittests/
│       ├── audio_frontends/
│       │   ├── apple_coreaudio_frontend_test.cpp
│       │   ├── jack_frontend_test.cpp
│       │   ├── offline_frontend_test.cpp
│       │   └── portaudio_frontend_test.cpp
│       ├── control_frontends/
│       │   ├── osc_frontend_test.cpp
│       │   └── oscpack_osc_messenger_test.cpp
│       ├── dsp_library/
│       │   ├── envelope_test.cpp
│       │   ├── master_limiter_test.cpp
│       │   ├── sample_wrapper_test.cpp
│       │   └── value_smoother_test.cpp
│       ├── engine/
│       │   ├── audio_graph_test.cpp
│       │   ├── controller_test.cpp
│       │   ├── controllers/
│       │   │   ├── audio_graph_controller_test.cpp
│       │   │   ├── audio_routing_controller_test.cpp
│       │   │   ├── midi_controller_test.cpp
│       │   │   ├── osc_controller_test.cpp
│       │   │   ├── reactive_controller_test.cpp
│       │   │   └── session_controller_test.cpp
│       │   ├── engine_test.cpp
│       │   ├── event_dispatcher_test.cpp
│       │   ├── event_timer_test.cpp
│       │   ├── factories/
│       │   │   └── factories_test.cpp
│       │   ├── json_configurator_test.cpp
│       │   ├── midi_dispatcher_test.cpp
│       │   ├── parameter_manager_test.cpp
│       │   ├── plugin_library_test.cpp
│       │   ├── processor_container_test.cpp
│       │   ├── receiver_test.cpp
│       │   ├── track_test.cpp
│       │   └── transport_test.cpp
│       ├── library/
│       │   ├── event_test.cpp
│       │   ├── fixed_stack_test.cpp
│       │   ├── id_generator_test.cpp
│       │   ├── internal_plugin_test.cpp
│       │   ├── lv2_wrapper_test.cpp
│       │   ├── midi_decoder_test.cpp
│       │   ├── midi_encoder_test.cpp
│       │   ├── parameter_dump_test.cpp
│       │   ├── performance_timer_test.cpp
│       │   ├── plugin_parameters_test.cpp
│       │   ├── processor_test.cpp
│       │   ├── rt_event_test.cpp
│       │   ├── sample_buffer_test.cpp
│       │   ├── simple_fifo_test.cpp
│       │   ├── vst2x_midi_event_fifo_test.cpp
│       │   ├── vst2x_plugin_loading_test.cpp
│       │   ├── vst2x_wrapper_test.cpp
│       │   └── vst3x_wrapper_test.cpp
│       ├── plugins/
│       │   ├── arpeggiator_plugin_test.cpp
│       │   ├── brickworks_simple_synth_test.cpp
│       │   ├── control_to_cv_plugin_test.cpp
│       │   ├── cv_to_control_plugin_test.cpp
│       │   ├── external_plugins_test.cpp
│       │   ├── plugins_test.cpp
│       │   ├── sample_player_plugin_test.cpp
│       │   ├── send_return_test.cpp
│       │   ├── step_sequencer_test.cpp
│       │   └── wav_streamer_plugin_test.cpp
│       ├── sample_test.cpp
│       └── test_utils/
│           ├── apple_coreaudio_mockup.cpp
│           ├── apple_coreaudio_mockup.h
│           ├── audio_frontend_mockup.h
│           ├── audio_graph_accessor.h
│           ├── control_mockup.h
│           ├── dummy_processor.h
│           ├── engine_mockup.h
│           ├── event_dispatcher_accessor.h
│           ├── host_control_mockup.h
│           ├── jack_mockup.cpp
│           ├── meta_schema_v4.json
│           ├── mock_event_dispatcher.h
│           ├── mock_midi_frontend.h
│           ├── mock_osc_interface.h
│           ├── mock_oscpack.h
│           ├── mock_processor_container.h
│           ├── mock_sushi.h
│           ├── plugin_accessors.h
│           ├── portaudio_mockup.cpp
│           ├── portaudio_mockup.h
│           ├── test_utils.h
│           ├── track_accessor.h
│           ├── vst2_test_plugin.cpp
│           ├── vst2_test_plugin.def
│           ├── vst2_test_plugin.h
│           ├── vst3_test_plugin.cpp
│           └── vst3_test_plugin.h
├── third-party/
│   ├── .gitkeep
│   ├── CMakeLists.txt
│   ├── fifo/
│   │   ├── CMakeLists.txt
│   │   └── include/
│   │       └── fifo/
│   │           └── circularfifo_memory_relaxed_aquire_release.h
│   ├── lv2_host/
│   │   ├── CMakeLists.txt
│   │   ├── include/
│   │   │   └── lv2_host/
│   │   │       ├── lv2_evbuf.h
│   │   │       └── lv2_symap.h
│   │   └── src/
│   │       ├── lv2_evbuf.cpp
│   │       └── lv2_symap.cpp
│   ├── optionparser/
│   │   ├── Makefile
│   │   ├── example.cpp
│   │   ├── example_arg.cc
│   │   ├── optionparser.h
│   │   ├── printUsage.h
│   │   ├── testodr1.cc
│   │   ├── testodr2.cc
│   │   ├── testparse.cpp
│   │   └── testprintusage.cpp
│   └── vst3sdk.windows.patch
├── triplets/
│   └── win-custom-x86-64.cmake
└── vcpkg.json
Download .txt
Showing preview only (201K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (2165 symbols across 395 files)

FILE: apps/main.cpp
  function exit_condition (line 47) | bool exit_condition()
  function exit_on_signal (line 59) | void exit_on_signal([[maybe_unused]] int sig)
  function error_exit (line 69) | void error_exit(const std::string& message, sushi::Status status)
  function pipe_signal_handler (line 83) | void pipe_signal_handler([[maybe_unused]] int sig)
  function print_sushi_headline (line 88) | static void print_sushi_headline()
  function main (line 94) | int main(int argc, char* argv[])
  function start_sushi (line 178) | std::unique_ptr<Sushi> start_sushi(SushiOptions options)

FILE: include/sushi/compile_time_settings.h
  function namespace (line 34) | namespace sushi {

FILE: include/sushi/constants.h
  function namespace (line 26) | namespace sushi {

FILE: include/sushi/control_interface.h
  type class (line 44) | enum class
  type class (line 55) | enum class
  type class (line 62) | enum class
  type ControlResponse (line 70) | struct ControlResponse
  type TimeSignature (line 76) | struct TimeSignature
  type Timings (line 82) | struct Timings
  type CpuTimings (line 89) | struct CpuTimings
  type class (line 95) | enum class
  type class (line 103) | enum class
  type ParameterInfo (line 110) | struct ParameterInfo
  type PropertyInfo (line 122) | struct PropertyInfo
  type ProcessorInfo (line 129) | struct ProcessorInfo
  type ProgramInfo (line 138) | struct ProgramInfo
  type class (line 144) | enum class
  type TrackInfo (line 151) | struct TrackInfo
  type ProcessorState (line 163) | struct ProcessorState
  type SushiBuildInfo (line 172) | struct SushiBuildInfo
  type class (line 181) | enum class
  type AudioConnection (line 202) | struct AudioConnection
  type CvConnection (line 209) | struct CvConnection
  type GateConnection (line 216) | struct GateConnection
  type MidiKbdConnection (line 224) | struct MidiKbdConnection
  type MidiCCConnection (line 232) | struct MidiCCConnection
  type MidiPCConnection (line 244) | struct MidiPCConnection
  type class (line 251) | enum class
  type class (line 262) | enum class
  type class (line 268) | enum class
  type class (line 274) | enum class
  type MidiKbdConnectionState (line 282) | struct MidiKbdConnectionState
  type MidiCCConnectionState (line 290) | struct MidiCCConnectionState
  type MidiPCConnectionState (line 302) | struct MidiPCConnectionState
  type MidiState (line 309) | struct MidiState
  type OscParameterState (line 320) | struct OscParameterState
  type OscState (line 326) | struct OscState
  type TrackAudioConnectionState (line 332) | struct TrackAudioConnectionState
  type EngineState (line 339) | struct EngineState
  type PluginClass (line 355) | struct PluginClass
  type TrackState (line 365) | struct TrackState
  type SessionState (line 377) | struct SessionState
  function virtual (line 427) | [[nodiscard]] virtual bool                      get_timing_statistics_en...
  function virtual (line 463) | [[nodiscard]] virtual std::vector<ProcessorInfo>                        ...
  function class (line 507) | class ParameterController
  function virtual (line 631) | [[nodiscard]] virtual std::string get_send_ip() const = 0;

FILE: include/sushi/control_notifications.h
  function namespace (line 8) | namespace sushi::control {
  function class (line 30) | class CpuTimingNotification : public ControlNotification
  function class (line 47) | class TrackNotification : public ControlNotification
  function class (line 63) | class ProcessorNotification : public ControlNotification
  function class (line 82) | class ParameterChangeNotification : public ControlNotification
  function class (line 108) | class PropertyChangeNotification : public ControlNotification
  function class (line 133) | class CommandCompletionNotification : public ControlNotification

FILE: include/sushi/coreaudio_devices_dump.h
  function namespace (line 23) | namespace sushi {

FILE: include/sushi/elk_sentry_log_sink.h
  function namespace (line 16) | namespace elk {

FILE: include/sushi/factory_interface.h
  function namespace (line 21) | namespace sushi {

FILE: include/sushi/offline_factory.h
  function namespace (line 27) | namespace sushi {

FILE: include/sushi/options.h
  function namespace (line 65) | namespace sushi {

FILE: include/sushi/parameter_dump.h
  function namespace (line 26) | namespace sushi {

FILE: include/sushi/portaudio_devices_dump.h
  function namespace (line 23) | namespace sushi {

FILE: include/sushi/reactive_factory.h
  function namespace (line 27) | namespace sushi {

FILE: include/sushi/rt_controller.h
  function TransportPositionSource (line 28) | enum class TransportPositionSource

FILE: include/sushi/sample_buffer.h
  function namespace (line 30) | namespace sushi {
  function SampleBuffer (line 171) | static SampleBuffer create_non_owning_buffer(SampleBuffer& source,
  function SampleBuffer (line 187) | static SampleBuffer create_non_owning_buffer(SampleBuffer& source)
  function SampleBuffer (line 202) | static SampleBuffer create_from_raw_pointer(float* data,
  function clear (line 216) | void clear()
  function from_interleaved (line 248) | void from_interleaved(const float* interleaved_buf)
  function to_interleaved (line 284) | void to_interleaved(float* interleaved_buf) const
  function apply_gain (line 320) | void apply_gain(float gain)
  function apply_gain (line 331) | void apply_gain(float gain, int channel)
  function replace (line 345) | void replace(const SampleBuffer &source)
  function replace (line 365) | void replace(int dest_channel, int source_channel, const SampleBuffer &s...
  function add (line 378) | void add(const SampleBuffer &source)
  function add (line 405) | void add(int dest_channel, int source_channel, const SampleBuffer& source)
  function add_with_gain (line 421) | void add_with_gain(const SampleBuffer &source, float gain)
  function add_with_gain (line 447) | void add_with_gain(int dest_channel, int source_channel, const SampleBuf...
  function add_with_ramp (line 466) | void add_with_ramp(const SampleBuffer &source, float start, float end)
  function add_with_ramp (line 499) | void add_with_ramp(int dest_channel, int source_channel, const SampleBuf...
  function ramp (line 515) | void ramp(float start, float end)
  function ramp_up (line 531) | void ramp_up()
  function ramp_down (line 539) | void ramp_down()
  function count_clipped_samples (line 549) | int count_clipped_samples(int channel) const
  function calc_peak_value (line 568) | float calc_peak_value(int channel) const
  function calc_rms_value (line 585) | float calc_rms_value(int channel) const
  type SampleBuffer (line 606) | typedef SampleBuffer<AUDIO_CHUNK_SIZE> ChunkSampleBuffer;

FILE: include/sushi/standalone_factory.h
  function namespace (line 27) | namespace sushi {

FILE: include/sushi/sushi.h
  function namespace (line 35) | namespace control {
  function namespace (line 39) | namespace internal::engine {
  function namespace (line 43) | namespace internal::audio_frontend {
  function namespace (line 48) | namespace internal::midi_frontend {
  type class (line 53) | enum class
  type class (line 65) | enum class
  function Status (line 76) | enum class Status : int

FILE: include/sushi/sushi_time.h
  function namespace (line 26) | namespace sushi {

FILE: include/sushi/terminal_utilities.h
  function namespace (line 28) | namespace sushi {

FILE: include/sushi/types.h
  function namespace (line 28) | namespace sushi {
  function class (line 68) | class RtDeletable

FILE: include/sushi/utils.h
  function namespace (line 29) | namespace sushi {

FILE: rpc_interface/include/sushi_rpc/grpc_server.h
  function namespace (line 36) | namespace grpc {
  function namespace (line 43) | namespace sushi_rpc {

FILE: rpc_interface/src/async_service_call_data.cpp
  type sushi_rpc (line 25) | namespace sushi_rpc {
    function BlocklistKey (line 27) | inline BlocklistKey create_key(int parameter_id, int processor_id)
    class SubscribeToUpdatesCallData<TransportUpdate, GenericVoidValue> (line 106) | class SubscribeToUpdatesCallData<TransportUpdate, GenericVoidValue>
    class SubscribeToUpdatesCallData<CpuTimings, GenericVoidValue> (line 107) | class SubscribeToUpdatesCallData<CpuTimings, GenericVoidValue>
    class SubscribeToUpdatesCallData<TrackUpdate, GenericVoidValue> (line 108) | class SubscribeToUpdatesCallData<TrackUpdate, GenericVoidValue>
    class SubscribeToUpdatesCallData<ProcessorUpdate, GenericVoidValue> (line 109) | class SubscribeToUpdatesCallData<ProcessorUpdate, GenericVoidValue>
    class SubscribeToUpdatesCallData<ParameterUpdate, ParameterNotificationBlocklist> (line 110) | class SubscribeToUpdatesCallData<ParameterUpdate, ParameterNotificatio...
    class SubscribeToUpdatesCallData<PropertyValue, PropertyNotificationBlocklist> (line 111) | class SubscribeToUpdatesCallData<PropertyValue, PropertyNotificationBl...
    class SubscribeToUpdatesCallData<AsyncCommandResponse, GenericVoidValue> (line 112) | class SubscribeToUpdatesCallData<AsyncCommandResponse, GenericVoidValue>

FILE: rpc_interface/src/async_service_call_data.h
  function CallStatus (line 70) | enum class CallStatus
  function proceed (line 100) | void proceed() override;
  function _subscribe (line 140) | void _subscribe() override;
  function _subscribe (line 160) | void _subscribe() override;
  function _subscribe (line 180) | void _subscribe() override;
  function _subscribe (line 200) | void _subscribe() override;
  function _subscribe (line 220) | void _subscribe() override;

FILE: rpc_interface/src/control_service.cpp
  type sushi_rpc (line 27) | namespace sushi_rpc {
    function to_grpc (line 30) | inline sushi_rpc::ParameterType::Type to_grpc(const sushi::control::Pa...
    function to_grpc (line 41) | inline sushi_rpc::PlayingMode::Mode to_grpc(const sushi::control::Play...
    function MidiChannel_Channel (line 52) | inline MidiChannel_Channel to_grpc(const sushi::control::MidiChannel c...
    function to_sushi_ext (line 77) | inline sushi::control::MidiChannel to_sushi_ext(const MidiChannel_Chan...
    function to_sushi_ext (line 102) | inline sushi::control::PlayingMode to_sushi_ext(const sushi_rpc::Playi...
    function to_grpc (line 113) | inline sushi_rpc::SyncMode::Mode to_grpc(const sushi::control::SyncMod...
    function to_sushi_ext (line 124) | inline sushi::control::SyncMode to_sushi_ext(const sushi_rpc::SyncMode...
    function to_grpc (line 135) | inline sushi_rpc::TrackType::Type to_grpc(const sushi::control::TrackT...
    function to_sushi_ext (line 146) | inline sushi::control::TrackType to_sushi_ext(const sushi_rpc::TrackTy...
    function to_grpc_status (line 171) | inline grpc::Status to_grpc_status(sushi::control::ControlStatus statu...
    function to_grpc (line 202) | inline sushi_rpc::CommandStatus::Status to_grpc(sushi::control::Contro...
    function to_grpc (line 217) | inline void to_grpc(CommandResponse& dest, const sushi::control::Contr...
    function to_grpc (line 223) | inline void to_grpc(CommandResponse& dest, const sushi::control::Contr...
    function to_grpc (line 229) | inline void to_grpc(ParameterInfo& dest, const sushi::control::Paramet...
    function to_grpc (line 243) | inline void to_grpc(PropertyInfo& dest, const sushi::control::Property...
    function to_grpc (line 250) | inline void to_grpc(sushi_rpc::ProcessorInfo& dest, const sushi::contr...
    function to_grpc (line 259) | inline void to_grpc(sushi_rpc::MidiKbdConnection& dest, const sushi::c...
    function to_grpc (line 267) | inline void to_grpc(sushi_rpc::MidiCCConnection& dest, const sushi::co...
    function to_grpc (line 280) | inline void to_grpc(sushi_rpc::MidiPCConnection& dest, const sushi::co...
    function to_grpc (line 287) | inline void to_grpc(sushi_rpc::TrackInfo& dest, const sushi::control::...
    function to_grpc (line 302) | inline void to_grpc(sushi_rpc::Timings& dest, const sushi::control::Ti...
    function to_grpc (line 309) | inline void to_grpc(sushi_rpc::CpuTimings& dest, const sushi::control:...
    function to_grpc (line 318) | inline void to_grpc(sushi_rpc::AudioConnection& dest, const sushi::con...
    function to_grpc (line 325) | inline sushi_rpc::PluginType::Type to_grpc(const sushi::control::Plugi...
    function to_sushi_ext (line 337) | inline sushi::control::PluginType to_sushi_ext(const sushi_rpc::Plugin...
    function to_grpc (line 349) | inline void to_grpc(sushi_rpc::ProcessorState& dest, sushi::control::P...
    function to_sushi_ext (line 383) | inline void to_sushi_ext(sushi::control::ProcessorState& dest, const s...
    function to_grpc (line 412) | inline void to_grpc(sushi_rpc::SushiBuildInfo& dest, sushi::control::S...
    function to_sushi_ext (line 426) | inline void to_sushi_ext(sushi::control::SushiBuildInfo& dest, const s...
    function to_grpc (line 440) | inline void to_grpc(sushi_rpc::OscParameterState& dest, sushi::control...
    function to_sushi_ext (line 450) | inline sushi::control::OscParameterState to_sushi_ext(const sushi_rpc:...
    function to_grpc (line 458) | inline void to_grpc(sushi_rpc::OscState& dest, sushi::control::OscStat...
    function to_sushi_ext (line 469) | inline void to_sushi_ext(sushi::control::OscState& dest, const sushi_r...
    function to_grpc (line 479) | inline void to_grpc(sushi_rpc::MidiKbdConnectionState& dest, sushi::co...
    function to_sushi_ext (line 487) | inline sushi::control::MidiKbdConnectionState to_sushi_ext(const sushi...
    function to_grpc (line 497) | inline void to_grpc(sushi_rpc::MidiCCConnectionState& dest, sushi::con...
    function to_sushi_ext (line 509) | inline sushi::control::MidiCCConnectionState to_sushi_ext(const sushi_...
    function to_grpc (line 522) | inline void to_grpc(sushi_rpc::MidiPCConnectionState& dest, sushi::con...
    function to_sushi_ext (line 529) | inline sushi::control::MidiPCConnectionState to_sushi_ext(const sushi_...
    function to_grpc (line 538) | inline void to_grpc(sushi_rpc::MidiState& dest, sushi::control::MidiSt...
    function to_sushi_ext (line 578) | inline void to_sushi_ext(sushi::control::MidiState& dest, const sushi_...
    function to_grpc (line 608) | inline void to_grpc(sushi_rpc::TrackAudioConnectionState& dest, sushi:...
    function to_sushi_ext (line 615) | inline sushi::control::TrackAudioConnectionState to_sushi_ext(const su...
    function to_grpc (line 624) | inline void to_grpc(sushi_rpc::EngineState& dest, sushi::control::Engi...
    function to_sushi_ext (line 653) | inline void to_sushi_ext(sushi::control::EngineState& dest, const sush...
    function to_grpc (line 679) | inline void to_grpc(sushi_rpc::PluginClass& dest, sushi::control::Plug...
    function to_sushi_ext (line 689) | inline sushi::control::PluginClass to_sushi_ext(const sushi_rpc::Plugi...
    function to_grpc (line 701) | inline void to_grpc(sushi_rpc::TrackState& dest, sushi::control::Track...
    function to_sushi_ext (line 719) | inline sushi::control::TrackState to_sushi_ext(const sushi_rpc::TrackS...
    function to_grpc (line 737) | inline void to_grpc(sushi_rpc::SessionState& dest, sushi::control::Ses...
    function to_sushi_ext (line 753) | inline void to_sushi_ext(sushi::control::SessionState& dest, const sus...

FILE: rpc_interface/src/control_service.h
  function namespace (line 38) | namespace sushi_rpc {

FILE: rpc_interface/src/grpc_server.cpp
  type sushi_rpc (line 28) | namespace sushi_rpc {

FILE: src/audio_frontends/apple_coreaudio/apple_coreaudio_device.h
  function class (line 33) | class AudioDevice : public AudioObject

FILE: src/audio_frontends/apple_coreaudio/apple_coreaudio_object.cpp
  type apple_coreaudio (line 22) | namespace apple_coreaudio {
    function AudioObjectID (line 33) | AudioObjectID AudioObject::get_audio_object_id() const
    function UInt32 (line 48) | UInt32 AudioObject::get_property_data_size(AudioObjectID audio_object_...
    function UInt32 (line 62) | UInt32 AudioObject::get_property_data(AudioObjectID audio_object_id, c...
    function UInt32 (line 105) | UInt32 AudioObject::get_property_data_size(const AudioObjectPropertyAd...
    function UInt32 (line 110) | UInt32 AudioObject::get_property_data(const AudioObjectPropertyAddress...
    function OSStatus (line 135) | OSStatus AudioObject::_audio_object_property_listener_proc(AudioObject...
    function T (line 242) | T AudioObject::get_property(AudioObjectID audio_object_id, const Audio...

FILE: src/audio_frontends/apple_coreaudio/apple_coreaudio_object.h
  function namespace (line 29) | namespace apple_coreaudio {

FILE: src/audio_frontends/apple_coreaudio/apple_coreaudio_system_object.h
  function namespace (line 26) | namespace apple_coreaudio {

FILE: src/audio_frontends/apple_coreaudio/apple_coreaudio_utils.cpp
  type apple_coreaudio (line 18) | namespace apple_coreaudio {
    function cf_string_to_std_string (line 20) | std::string cf_string_to_std_string(const CFStringRef& cf_string_ref)

FILE: src/audio_frontends/apple_coreaudio/apple_coreaudio_utils.h
  function namespace (line 78) | namespace apple_coreaudio {

FILE: src/audio_frontends/apple_coreaudio_frontend.cpp
  type sushi::internal::audio_frontend (line 30) | namespace sushi::internal::audio_frontend {
    function get_coreaudio_output_device_name (line 32) | std::optional<std::string> get_coreaudio_output_device_name(std::optio...
    function AudioFrontendStatus (line 77) | AudioFrontendStatus AppleCoreAudioFrontend::init(BaseAudioFrontendConf...
    function AudioFrontendStatus (line 229) | AudioFrontendStatus AppleCoreAudioFrontend::configure_audio_channels(c...
  type sushi::internal::audio_frontend (line 424) | namespace sushi::internal::audio_frontend {
    function get_coreaudio_output_device_name (line 32) | std::optional<std::string> get_coreaudio_output_device_name(std::optio...
    function AudioFrontendStatus (line 77) | AudioFrontendStatus AppleCoreAudioFrontend::init(BaseAudioFrontendConf...
    function AudioFrontendStatus (line 229) | AudioFrontendStatus AppleCoreAudioFrontend::configure_audio_channels(c...

FILE: src/audio_frontends/apple_coreaudio_frontend.h
  function namespace (line 35) | namespace sushi::internal::audio_frontend {
  function namespace (line 103) | namespace sushi::internal::audio_frontend {

FILE: src/audio_frontends/audio_frontend_internals.h
  function namespace (line 27) | namespace sushi::internal::audio_frontend {

FILE: src/audio_frontends/base_audio_frontend.cpp
  type sushi::internal::audio_frontend (line 27) | namespace sushi::internal::audio_frontend {
    function AudioFrontendStatus (line 31) | AudioFrontendStatus BaseAudioFrontend::init(BaseAudioFrontendConfigura...

FILE: src/audio_frontends/base_audio_frontend.h
  type class (line 32) | enum class
  type BaseAudioFrontendConfiguration (line 46) | struct BaseAudioFrontendConfiguration
  function Time (line 127) | Time _last_process_time{Time(0)};

FILE: src/audio_frontends/coreaudio_devices_dump.cpp
  type sushi (line 32) | namespace sushi {
    function generate_coreaudio_devices_info_document (line 36) | rapidjson::Document generate_coreaudio_devices_info_document()
    function generate_coreaudio_devices_info_document (line 119) | rapidjson::Document generate_coreaudio_devices_info_document()
  type sushi (line 117) | namespace sushi {
    function generate_coreaudio_devices_info_document (line 36) | rapidjson::Document generate_coreaudio_devices_info_document()
    function generate_coreaudio_devices_info_document (line 119) | rapidjson::Document generate_coreaudio_devices_info_document()

FILE: src/audio_frontends/jack_frontend.cpp
  type sushi::internal::audio_frontend (line 29) | namespace sushi::internal::audio_frontend {
    function AudioFrontendStatus (line 33) | AudioFrontendStatus JackFrontend::init(BaseAudioFrontendConfiguration*...
    function AudioFrontendStatus (line 85) | AudioFrontendStatus JackFrontend::setup_client(const std::string& clie...
    function AudioFrontendStatus (line 135) | AudioFrontendStatus JackFrontend::setup_sample_rate()
    function AudioFrontendStatus (line 152) | AudioFrontendStatus JackFrontend::setup_ports()
    function AudioFrontendStatus (line 186) | AudioFrontendStatus JackFrontend::setup_cv_ports()
    function AudioFrontendStatus (line 220) | AudioFrontendStatus JackFrontend::connect_ports()
    function AudioFrontendStatus (line 394) | AudioFrontendStatus JackFrontend::init(BaseAudioFrontendConfiguration*)
  type sushi::internal::audio_frontend (line 388) | namespace sushi::internal::audio_frontend {
    function AudioFrontendStatus (line 33) | AudioFrontendStatus JackFrontend::init(BaseAudioFrontendConfiguration*...
    function AudioFrontendStatus (line 85) | AudioFrontendStatus JackFrontend::setup_client(const std::string& clie...
    function AudioFrontendStatus (line 135) | AudioFrontendStatus JackFrontend::setup_sample_rate()
    function AudioFrontendStatus (line 152) | AudioFrontendStatus JackFrontend::setup_ports()
    function AudioFrontendStatus (line 186) | AudioFrontendStatus JackFrontend::setup_cv_ports()
    function AudioFrontendStatus (line 220) | AudioFrontendStatus JackFrontend::connect_ports()
    function AudioFrontendStatus (line 394) | AudioFrontendStatus JackFrontend::init(BaseAudioFrontendConfiguration*)

FILE: src/audio_frontends/jack_frontend.h
  function BaseAudioFrontendConfiguration (line 35) | struct JackFrontendConfiguration : public BaseAudioFrontendConfiguration
  function virtual (line 60) | virtual ~JackFrontend()
  function rt_process_callback (line 72) | static int rt_process_callback(jack_nframes_t nframes, void *arg)
  function samplerate_callback (line 83) | static int samplerate_callback(jack_nframes_t nframes, void *arg)
  function latency_callback (line 88) | static void latency_callback(jack_latency_callback_mode_t mode, void *arg)
  function namespace (line 157) | namespace sushi::internal::audio_frontend {

FILE: src/audio_frontends/offline_frontend.cpp
  type sushi::internal::audio_frontend (line 31) | namespace sushi::internal::audio_frontend {
    function fill_buffer_with_noise (line 44) | void fill_buffer_with_noise(ChunkSampleBuffer& buffer, random_device& ...
    function fill_cv_buffer_with_noise (line 57) | void fill_cv_buffer_with_noise(engine::ControlBuffer& buffer, random_d...
    function AudioFrontendStatus (line 65) | AudioFrontendStatus OfflineFrontend::init(BaseAudioFrontendConfigurati...
    function time_to_sample_offset (line 161) | int time_to_sample_offset(Time chunk_end_time, Time event_time, float ...
    function ELK_PUSH_WARNING (line 238) | ELK_PUSH_WARNING

FILE: src/audio_frontends/offline_frontend.h
  function namespace (line 34) | namespace sushi::internal::audio_frontend {

FILE: src/audio_frontends/portaudio_devices_dump.cpp
  type sushi (line 28) | namespace sushi {
    function generate_portaudio_devices_info_document (line 38) | rapidjson::Document generate_portaudio_devices_info_document()

FILE: src/audio_frontends/portaudio_frontend.cpp
  type sushi::internal::audio_frontend (line 35) | namespace sushi::internal::audio_frontend {
    function get_portaudio_output_device_name (line 39) | std::optional<std::string> get_portaudio_output_device_name(std::optio...
    function AudioFrontendStatus (line 65) | AudioFrontendStatus PortAudioFrontend::init(BaseAudioFrontendConfigura...
    function AudioFrontendStatus (line 318) | AudioFrontendStatus PortAudioFrontend::_initialize_portaudio()
    function AudioFrontendStatus (line 334) | AudioFrontendStatus PortAudioFrontend::_configure_audio_channels(const...
    function AudioFrontendStatus (line 495) | AudioFrontendStatus PortAudioFrontend::init(BaseAudioFrontendConfigura...
  type sushi::internal::audio_frontend (line 490) | namespace sushi::internal::audio_frontend {
    function get_portaudio_output_device_name (line 39) | std::optional<std::string> get_portaudio_output_device_name(std::optio...
    function AudioFrontendStatus (line 65) | AudioFrontendStatus PortAudioFrontend::init(BaseAudioFrontendConfigura...
    function AudioFrontendStatus (line 318) | AudioFrontendStatus PortAudioFrontend::_initialize_portaudio()
    function AudioFrontendStatus (line 334) | AudioFrontendStatus PortAudioFrontend::_configure_audio_channels(const...
    function AudioFrontendStatus (line 495) | AudioFrontendStatus PortAudioFrontend::init(BaseAudioFrontendConfigura...

FILE: src/audio_frontends/portaudio_frontend.h
  type PortaudioDeviceInfo (line 57) | struct PortaudioDeviceInfo
  type PortAudioFrontendConfiguration (line 65) | struct PortAudioFrontendConfiguration
  function suggested_output_latency (line 85) | float suggested_output_latency{0.0f};
  function rt_process_callback (line 112) | static int rt_process_callback(const void* input,
  function cleanup (line 136) | void cleanup() override;
  function _audio_input_channels (line 216) | int _audio_input_channels {0}
  function _audio_output_channels (line 217) | int _audio_output_channels {0}
  function _cv_input_channels (line 218) | int _cv_input_channels {0}
  function _cv_output_channels (line 219) | int _cv_output_channels {0}
  function _stream_initialized (line 225) | bool _stream_initialized {false};
  function namespace (line 251) | namespace sushi::internal::audio_frontend {

FILE: src/audio_frontends/reactive_frontend.cpp
  type sushi::internal::audio_frontend (line 27) | namespace sushi::internal::audio_frontend {
    function AudioFrontendStatus (line 31) | AudioFrontendStatus ReactiveFrontend::init(BaseAudioFrontendConfigurat...

FILE: src/audio_frontends/reactive_frontend.h
  function namespace (line 34) | namespace sushi::internal::audio_frontend {

FILE: src/audio_frontends/xenomai_raspa_frontend.cpp
  type sushi::internal::audio_frontend (line 31) | namespace sushi::internal::audio_frontend {
    function AudioFrontendStatus (line 45) | AudioFrontendStatus XenomaiRaspaFrontend::init(BaseAudioFrontendConfig...
    function AudioFrontendStatus (line 154) | AudioFrontendStatus XenomaiRaspaFrontend::config_audio_channels(const ...
    function AudioFrontendStatus (line 211) | AudioFrontendStatus XenomaiRaspaFrontend::init(BaseAudioFrontendConfig...
  type sushi::internal::audio_frontend (line 204) | namespace sushi::internal::audio_frontend {
    function AudioFrontendStatus (line 45) | AudioFrontendStatus XenomaiRaspaFrontend::init(BaseAudioFrontendConfig...
    function AudioFrontendStatus (line 154) | AudioFrontendStatus XenomaiRaspaFrontend::config_audio_channels(const ...
    function AudioFrontendStatus (line 211) | AudioFrontendStatus XenomaiRaspaFrontend::init(BaseAudioFrontendConfig...

FILE: src/audio_frontends/xenomai_raspa_frontend.h
  function BaseAudioFrontendConfiguration (line 31) | struct XenomaiRaspaFrontendConfiguration : public BaseAudioFrontendConfi...
  function virtual (line 47) | virtual ~XenomaiRaspaFrontend()
  function rt_process_callback (line 65) | static void rt_process_callback(float* input, float* output, void* data)
  function cleanup (line 73) | void cleanup() override;

FILE: src/concrete_sushi.cpp
  type sushi (line 33) | namespace sushi {
    function to_string (line 76) | std::string to_string(Status status)
    type internal (line 126) | namespace internal {
      function Status (line 139) | Status ConcreteSushi::start()

FILE: src/concrete_sushi.h
  function namespace (line 32) | namespace sushi_rpc {
  function namespace (line 36) | namespace sushi::internal {

FILE: src/control_frontends/alsa_midi_frontend.cpp
  type sushi::internal::midi_frontend (line 33) | namespace sushi::internal::midi_frontend {
    function create_port (line 38) | int create_port(snd_seq_t* seq, int queue, const std::string& name, bo...
    function is_midi_for_sushi (line 82) | bool is_midi_for_sushi(snd_seq_event_type_t type)
    function Time (line 291) | Time AlsaMidiFrontend::_to_sushi_time(const snd_seq_real_time_t* alsa_...
    function snd_seq_real_time_t (line 297) | snd_seq_real_time_t AlsaMidiFrontend::_to_alsa_time(Time timestamp)

FILE: src/control_frontends/alsa_midi_frontend.h
  function namespace (line 36) | namespace sushi::internal::midi_frontend {

FILE: src/control_frontends/base_control_frontend.cpp
  type sushi::internal::control_frontend (line 24) | namespace sushi::internal::control_frontend {

FILE: src/control_frontends/base_control_frontend.h
  function ControlFrontendStatus (line 32) | enum class ControlFrontendStatus

FILE: src/control_frontends/base_midi_frontend.h
  function namespace (line 30) | namespace sushi::internal::midi_frontend {

FILE: src/control_frontends/osc_frontend.cpp
  type sushi::internal (line 28) | namespace sushi::internal {
    type control_frontend (line 42) | namespace control_frontend {
      function ControlFrontendStatus (line 106) | ControlFrontendStatus OSCFrontend::init()
      function OscState (line 234) | OscState OSCFrontend::save_state() const
      function OscConnection (line 323) | OscConnection* OSCFrontend::_connect_kb_to_track(const Processor* pr...
      function OscConnection (line 350) | OscConnection* OSCFrontend::_connect_to_bypass_state(const Processor...
      function OscConnection (line 371) | OscConnection* OSCFrontend::_connect_to_program_change(const Process...
      function OscConnection (line 391) | OscConnection* OSCFrontend::_connect_to_parameter(const std::string&...
      function OscConnection (line 417) | OscConnection* OSCFrontend::_connect_to_property(const std::string& ...

FILE: src/control_frontends/osc_frontend.h
  function namespace (line 37) | namespace osc
  function class (line 46) | class OscState
  type OscConnection (line 67) | struct OscConnection
  function ControlFrontendStatus (line 88) | ControlFrontendStatus init() override;
  function stop (line 136) | void stop() override {_stop_server();}
  function send_port (line 143) | int send_port() const;
  function set_connect_from_all_parameters (line 149) | void set_connect_from_all_parameters(bool connect) {_connect_from_all_pa...

FILE: src/control_frontends/osc_utils.h
  type class (line 33) | enum class
  function class (line 50) | class BaseOscMessenger

FILE: src/control_frontends/oscpack_osc_messenger.cpp
  type sushi::internal (line 23) | namespace sushi::internal {
    type osc (line 27) | namespace osc

FILE: src/control_frontends/oscpack_osc_messenger.h
  function namespace (line 42) | namespace sushi::internal::osc

FILE: src/control_frontends/reactive_midi_frontend.cpp
  type sushi::internal::midi_frontend (line 31) | namespace sushi::internal::midi_frontend {

FILE: src/control_frontends/reactive_midi_frontend.h
  function namespace (line 30) | namespace sushi::internal::midi_frontend {

FILE: src/control_frontends/rt_midi_frontend.cpp
  type sushi::internal::midi_frontend (line 36) | namespace sushi::internal::midi_frontend {
    function midi_callback (line 38) | void midi_callback([[maybe_unused]]double deltatime, std::vector<unsig...

FILE: src/control_frontends/rt_midi_frontend.h
  function namespace (line 32) | namespace sushi::internal::midi_frontend {

FILE: src/dsp_library/biquad_filter.cpp
  type sushi::dsp::biquad (line 31) | namespace sushi::dsp::biquad {
    function process_one_pole (line 35) | inline float process_one_pole(const OnePoleCoefficients coefficients, ...
    function calc_biquad_peak (line 41) | void calc_biquad_peak(Coefficients& filter, float samplerate, float fr...
    function calc_biquad_lowpass (line 58) | void calc_biquad_lowpass(Coefficients&  filter, float samplerate, floa...

FILE: src/dsp_library/biquad_filter.h
  type Coefficients (line 30) | struct Coefficients
  type DelayRegisters (line 39) | struct DelayRegisters
  type OnePoleCoefficients (line 45) | struct OnePoleCoefficients
  function OnePoleCoefficients (line 89) | OnePoleCoefficients _smoothing_coefficients{0.0f, 0.0f};

FILE: src/dsp_library/envelopes.h
  function class (line 42) | class AdsrEnvelope
  function gate (line 146) | void gate(bool gate)
  function finished (line 168) | bool finished()
  function reset (line 175) | void reset()
  function _decay_factor (line 183) | float _decay_factor {0}
  function _sustain_level (line 184) | float _sustain_level {1}
  function _current_level (line 186) | float _current_level {0}
  function _samplerate (line 187) | float _samplerate {44100};

FILE: src/dsp_library/master_limiter.h
  function reset (line 70) | void reset()
  function process (line 82) | inline void process(const float* input, float* output)
  function _write_idx (line 103) | int _write_idx{0}
  function init (line 127) | void init(float sample_rate)
  function process (line 142) | void process(const float* input, float* output)
  function _attack_time (line 182) | float _attack_time{0.0};

FILE: src/dsp_library/sample_wrapper.h
  function namespace (line 26) | namespace sushi::dsp {

FILE: src/dsp_library/value_smoother.h
  function namespace (line 28) | namespace sushi::internal {
  function set (line 72) | void set(T value)
  function set_direct (line 95) | void set_direct(T target_value)
  function T (line 123) | T next_value()
  function stationary (line 156) | [[nodiscard]] bool stationary() const
  function set_lag_time (line 173) | void set_lag_time(std::chrono::duration<float, std::ratio<1,1>> lag_time...
  type LinearSpecific (line 179) | struct LinearSpecific
  type FilterSpecific (line 185) | struct FilterSpecific
  function _update_internals (line 195) | void _update_internals(std::chrono::duration<float, std::ratio<1,1>> lag...

FILE: src/engine/audio_engine.cpp
  type sushi::internal::engine (line 32) | namespace sushi::internal::engine {
    function EngineReturnStatus (line 52) | EngineReturnStatus to_engine_status(ProcessorReturnCode processor_status)
    function EngineReturnStatus (line 162) | EngineReturnStatus AudioEngine::set_cv_input_channels(int channels)
    function EngineReturnStatus (line 171) | EngineReturnStatus AudioEngine::set_cv_output_channels(int channels)
    function EngineReturnStatus (line 180) | EngineReturnStatus AudioEngine::connect_audio_input_channel(int input_...
    function EngineReturnStatus (line 185) | EngineReturnStatus AudioEngine::connect_audio_output_channel(int outpu...
    function EngineReturnStatus (line 190) | EngineReturnStatus AudioEngine::disconnect_audio_input_channel(int eng...
    function EngineReturnStatus (line 195) | EngineReturnStatus AudioEngine::disconnect_audio_output_channel(int en...
    function EngineReturnStatus (line 210) | EngineReturnStatus AudioEngine::connect_audio_input_bus(int input_bus,...
    function EngineReturnStatus (line 220) | EngineReturnStatus AudioEngine::connect_audio_output_bus(int output_bu...
    function EngineReturnStatus (line 230) | EngineReturnStatus AudioEngine::connect_cv_to_parameter(const std::str...
    function EngineReturnStatus (line 257) | EngineReturnStatus AudioEngine::connect_cv_from_parameter(const std::s...
    function EngineReturnStatus (line 284) | EngineReturnStatus AudioEngine::connect_gate_to_processor(const std::s...
    function EngineReturnStatus (line 308) | EngineReturnStatus AudioEngine::connect_gate_from_processor(const std:...
    function EngineReturnStatus (line 331) | EngineReturnStatus AudioEngine::connect_gate_to_sync(int /*gate_input_...
    function EngineReturnStatus (line 337) | EngineReturnStatus AudioEngine::connect_sync_to_gate(int /*gate_output...
    function EngineReturnStatus (line 360) | EngineReturnStatus AudioEngine::_register_processor(std::shared_ptr<Pr...
    function EngineReturnStatus (line 549) | EngineReturnStatus AudioEngine::send_rt_event_to_processor(const RtEve...
    function EngineReturnStatus (line 555) | EngineReturnStatus AudioEngine::_send_control_event(RtEvent& event)
    function EngineReturnStatus (line 612) | EngineReturnStatus AudioEngine::delete_track(ObjectId track_id)
    function EngineReturnStatus (line 704) | EngineReturnStatus AudioEngine::add_plugin_to_track(ObjectId plugin_id,
    function EngineReturnStatus (line 766) | EngineReturnStatus AudioEngine::remove_plugin_from_track(ObjectId plug...
    function EngineReturnStatus (line 814) | EngineReturnStatus AudioEngine::delete_plugin(ObjectId plugin_id)
    function EngineReturnStatus (line 850) | EngineReturnStatus AudioEngine::_register_new_track(const std::string&...
    function EngineReturnStatus (line 930) | EngineReturnStatus AudioEngine::_connect_audio_channel(int engine_chan...
    function EngineReturnStatus (line 997) | EngineReturnStatus AudioEngine::_disconnect_audio_channel(int engine_c...
    function print_single_timings_for_node (line 1265) | void print_single_timings_for_node(std::fstream& f, performance::Perfo...
    function RealtimeState (line 1421) | RealtimeState update_state(RealtimeState current_state)

FILE: src/engine/audio_engine.h
  function class (line 56) | class ClipDetector
  function EngineReturnStatus (line 170) | EngineReturnStatus disconnect_audio_output_channel(int engine_channel,
  function enable_input_clip_detection (line 433) | void enable_input_clip_detection(bool enabled) override
  function enable_output_clip_detection (line 451) | void enable_output_clip_detection(bool enabled) override
  function enable_master_limiter (line 469) | void enable_master_limiter(bool enabled) override
  function BaseProcessorContainer (line 498) | const BaseProcessorContainer* processor_container() override
  type class (line 518) | enum class
  function BitSet32 (line 636) | BitSet32 _prev_gate_values{0}
  function BitSet32 (line 637) | BitSet32 _outgoing_gate_values{0}
  function _log_timing_print_counter (line 654) | int  _log_timing_print_counter{0}
  function _output_clip_detection_enabled (line 657) | bool _output_clip_detection_enabled{false};

FILE: src/engine/audio_graph.cpp
  type sushi::internal::engine (line 26) | namespace sushi::internal::engine {
    function external_render_callback (line 35) | void external_render_callback(void* data)

FILE: src/engine/audio_graph.h
  function namespace (line 32) | namespace sushi::internal::engine {

FILE: src/engine/base_engine.h
  function namespace (line 45) | namespace sushi::internal::engine {
  function virtual (line 300) | virtual EngineReturnStatus remove_plugin_from_track(ObjectId /*plugin_id*/,
  function delete_plugin (line 306) | delete_plugin(ObjectId /*plugin_id*/)
  function virtual (line 311) | virtual dispatcher::BaseEventDispatcher* event_dispatcher()
  function virtual (line 316) | virtual engine::Transport* transport()
  function virtual (line 321) | virtual performance::BasePerformanceTimer* performance_timer()
  function virtual (line 326) | virtual const BaseProcessorContainer* processor_container()
  function virtual (line 331) | virtual void enable_input_clip_detection(bool /*enabled*/) {}
  function virtual (line 333) | virtual void enable_output_clip_detection(bool /*enabled*/) {}
  function virtual (line 339) | virtual void enable_master_limiter(bool /*enabled*/) {}
  function virtual (line 343) | virtual void update_timings() {}
  function virtual (line 345) | virtual void notify_interrupted_audio(Time /*duration*/) {}
  function _audio_inputs (line 349) | int _audio_inputs{0}
  function _audio_outputs (line 350) | int _audio_outputs{0}
  function _cv_inputs (line 351) | int _cv_inputs{0}
  function _cv_outputs (line 352) | int _cv_outputs{0};

FILE: src/engine/base_event_dispatcher.h
  function Status (line 30) | enum class Status

FILE: src/engine/base_processor_container.h
  function namespace (line 32) | namespace sushi::internal::engine {

FILE: src/engine/connection_storage.h
  function namespace (line 34) | namespace sushi::internal {

FILE: src/engine/controller/audio_graph_controller.cpp
  type sushi::internal::engine::controller_impl (line 29) | namespace sushi::internal::engine::controller_impl {
    function to_external (line 31) | inline control::ProcessorInfo to_external(const Processor* proc)
    function to_external (line 40) | inline control::TrackInfo to_external(const Track* track, std::vector<...

FILE: src/engine/controller/audio_graph_controller.h
  function namespace (line 30) | namespace sushi::internal::engine { class CompletionSender;}
  function namespace (line 32) | namespace sushi::internal::engine::controller_impl {

FILE: src/engine/controller/audio_routing_controller.cpp
  type sushi::internal::engine::controller_impl (line 28) | namespace sushi::internal::engine::controller_impl {
    function to_external (line 30) | inline control::AudioConnection to_external(const AudioConnection& con)

FILE: src/engine/controller/audio_routing_controller.h
  function namespace (line 29) | namespace sushi::internal::engine::controller_impl {

FILE: src/engine/controller/completion_sender.h
  function namespace (line 28) | namespace sushi::internal::engine {

FILE: src/engine/controller/controller.cpp
  type sushi::internal::engine (line 32) | namespace sushi::internal::engine {
    function to_external_status (line 34) | control::ControlStatus to_external_status(int status)

FILE: src/engine/controller/controller.h
  function namespace (line 47) | namespace sushi::internal {

FILE: src/engine/controller/controller_common.h
  type CompletionData (line 28) | struct CompletionData
  function namespace (line 34) | namespace sushi::internal::engine::controller_impl {

FILE: src/engine/controller/cv_gate_controller.cpp
  type sushi::internal::engine::controller_impl (line 25) | namespace sushi::internal::engine::controller_impl {
    function ELK_PUSH_WARNING (line 27) | ELK_PUSH_WARNING

FILE: src/engine/controller/cv_gate_controller.h
  function namespace (line 30) | namespace sushi::internal::engine::controller_impl {

FILE: src/engine/controller/keyboard_controller.cpp
  type sushi::internal::engine::controller_impl (line 27) | namespace sushi::internal::engine::controller_impl {

FILE: src/engine/controller/keyboard_controller.h
  function namespace (line 29) | namespace sushi::internal::engine::controller_impl {

FILE: src/engine/controller/midi_controller.cpp
  type sushi::internal::engine::controller_impl (line 27) | namespace sushi::internal::engine::controller_impl {
    function map_status (line 29) | inline int map_status(midi_dispatcher::MidiDispatcherStatus status)
    function populate_cc_connection (line 53) | control::MidiCCConnection populate_cc_connection(const midi_dispatcher...
    function populate_pc_connection (line 69) | control::MidiPCConnection populate_pc_connection(const midi_dispatcher...

FILE: src/engine/controller/midi_controller.h
  function namespace (line 31) | namespace sushi::internal::engine::controller_impl {

FILE: src/engine/controller/osc_controller.cpp
  type sushi::internal::engine::controller_impl (line 23) | namespace sushi::internal::engine::controller_impl {

FILE: src/engine/controller/osc_controller.h
  function class (line 33) | class OscController : public control::OscController

FILE: src/engine/controller/parameter_controller.cpp
  type sushi::internal::engine::controller_impl (line 29) | namespace sushi::internal::engine::controller_impl {
    function to_external (line 31) | inline control::ParameterType to_external(const ParameterType type)
    function _read_parameters (line 42) | inline std::vector<control::ParameterInfo> _read_parameters(const Proc...
    function _read_properties (line 66) | inline std::vector<control::PropertyInfo> _read_properties(const Proce...

FILE: src/engine/controller/parameter_controller.h
  function namespace (line 29) | namespace sushi::internal::engine {

FILE: src/engine/controller/program_controller.cpp
  type sushi::internal::engine::controller_impl (line 27) | namespace sushi::internal::engine::controller_impl {

FILE: src/engine/controller/program_controller.h
  function namespace (line 31) | namespace sushi::internal::engine::controller_impl {

FILE: src/engine/controller/real_time_controller.cpp
  type sushi::internal (line 25) | namespace sushi::internal

FILE: src/engine/controller/real_time_controller.h
  function namespace (line 27) | namespace audio_frontend
  function namespace (line 32) | namespace midi_frontend
  function namespace (line 37) | namespace engine
  function _samples_since_start (line 96) | int64_t _samples_since_start {0}
  function _tempo (line 98) | float _tempo {0}

FILE: src/engine/controller/session_controller.cpp
  type sushi::internal::engine::controller_impl (line 37) | namespace sushi::internal::engine::controller_impl {
    function to_external (line 39) | inline control::TrackAudioConnectionState to_external(const AudioConne...
    function to_external (line 49) | inline control::MidiKbdConnectionState to_external(const midi_dispatch...
    function to_external (line 60) | inline control::MidiKbdConnectionState to_external(const midi_dispatch...
    function to_external (line 71) | inline control::MidiCCConnectionState to_external(const midi_dispatche...
    function to_external (line 86) | inline control::MidiPCConnectionState to_external(const midi_dispatche...
    function to_internal (line 96) | inline void to_internal(control_frontend::OscState& dest, const contro...
    function to_external (line 105) | inline void to_external(control::OscState& dest, const control_fronten...

FILE: src/engine/controller/session_controller.h
  function namespace (line 33) | namespace sushi::internal::engine::controller_impl {

FILE: src/engine/controller/system_controller.cpp
  type sushi::internal::engine::controller_impl (line 25) | namespace sushi::internal::engine::controller_impl {

FILE: src/engine/controller/system_controller.h
  function namespace (line 27) | namespace sushi::internal::engine::controller_impl {

FILE: src/engine/controller/timing_controller.cpp
  type sushi::internal::engine::controller_impl (line 27) | namespace sushi::internal::engine::controller_impl {
    function to_external (line 32) | inline control::Timings to_external(performance::ProcessTimings& inter...

FILE: src/engine/controller/timing_controller.h
  function namespace (line 29) | namespace sushi::internal::engine::controller_impl {

FILE: src/engine/controller/transport_controller.cpp
  type sushi::internal::engine::controller_impl (line 29) | namespace sushi::internal::engine::controller_impl {

FILE: src/engine/controller/transport_controller.h
  function namespace (line 29) | namespace sushi::internal::engine::controller_impl {

FILE: src/engine/event_dispatcher.cpp
  type sushi::internal::dispatcher (line 26) | namespace sushi::internal::dispatcher {
    function Status (line 88) | Status EventDispatcher::subscribe_to_keyboard_events(EventPoster* rece...
    function Status (line 100) | Status EventDispatcher::subscribe_to_parameter_change_notifications(Ev...
    function Status (line 112) | Status EventDispatcher::subscribe_to_engine_notifications(EventPoster*...
    function Status (line 318) | Status EventDispatcher::unsubscribe_from_keyboard_events(EventPoster* ...
    function Status (line 333) | Status EventDispatcher::unsubscribe_from_parameter_change_notification...
    function Status (line 348) | Status EventDispatcher::unsubscribe_from_engine_notifications(EventPos...

FILE: src/engine/event_dispatcher.h
  function namespace (line 36) | namespace sushi::internal::engine {
  function namespace (line 40) | namespace sushi::internal::dispatcher {

FILE: src/engine/event_timer.cpp
  type sushi::internal::event_timer (line 29) | namespace sushi::internal::event_timer {
    function Time (line 34) | inline Time calc_chunk_time(float samplerate)
    function Time (line 59) | Time EventTimer::real_time_from_sample_offset(int offset) const

FILE: src/engine/event_timer.h
  function set_incoming_time (line 66) | void set_incoming_time(Time timestamp) {_incoming_chunk_time.store(times...
  function set_outgoing_time (line 73) | void set_outgoing_time(Time timestamp) {_outgoing_chunk_time = timestamp...
  function Time (line 78) | Time                _outgoing_chunk_time{IMMEDIATE_PROCESS};

FILE: src/engine/host_control.h
  function namespace (line 29) | namespace sushi::internal {

FILE: src/engine/json_configurator.cpp
  type sushi::internal::jsonconfig (line 36) | namespace sushi::internal::jsonconfig {
    function JsonConfigReturnStatus (line 156) | JsonConfigReturnStatus JsonConfigurator::load_host_config()
    function JsonConfigReturnStatus (line 249) | JsonConfigReturnStatus JsonConfigurator::load_tracks()
    function JsonConfigReturnStatus (line 289) | JsonConfigReturnStatus JsonConfigurator::load_midi()
    function JsonConfigReturnStatus (line 474) | JsonConfigReturnStatus JsonConfigurator::load_osc()
    function JsonConfigReturnStatus (line 527) | JsonConfigReturnStatus JsonConfigurator::load_cv_gate()
    function JsonConfigReturnStatus (line 632) | JsonConfigReturnStatus JsonConfigurator::load_events()
    function JsonConfigReturnStatus (line 672) | JsonConfigReturnStatus JsonConfigurator::load_initial_state()
    function JsonConfigReturnStatus (line 769) | JsonConfigReturnStatus JsonConfigurator::_make_track(const rapidjson::...
    function JsonConfigReturnStatus (line 955) | JsonConfigReturnStatus JsonConfigurator::_load_data(const std::string&...
    function JsonConfigReturnStatus (line 974) | JsonConfigReturnStatus JsonConfigurator::_connect_audio_to_track(const...
    function JsonConfigReturnStatus (line 1027) | JsonConfigReturnStatus JsonConfigurator::_add_plugin(const rapidjson::...

FILE: src/engine/json_configurator.h
  type class (line 43) | enum class
  type class (line 56) | enum class
  type ControlConfig (line 69) | struct ControlConfig
  function class (line 81) | class JsonConfigurator

FILE: src/engine/link_dummy.h
  function namespace (line 25) | namespace sushi::internal::engine {
  function commitAppSessionState (line 53) | void commitAppSessionState(SessionState /*state*/) {}
  function class (line 54) | class SessionState
  function requestBeatAtTime (line 63) | void requestBeatAtTime(double /*beat*/, std::chrono::microseconds /*time...
  function forceBeatAtTime (line 64) | void forceBeatAtTime(double /*beat*/, std::chrono::microseconds /*time*/...
  function setIsPlaying (line 65) | void setIsPlaying(bool /*isPlaying*/, std::chrono::microseconds /*time*/...
  function requestBeatAtStartPlayingTime (line 68) | void requestBeatAtStartPlayingTime(double /*beat*/, double /*quantum*/) {}
  function setIsPlayingAndRequestBeatAtTime (line 69) | void setIsPlayingAndRequestBeatAtTime(bool /*isPlaying*/, std::chrono::m...

FILE: src/engine/midi_dispatcher.cpp
  type sushi::internal::midi_dispatcher (line 31) | namespace sushi::internal::midi_dispatcher {
    function make_note_on_event (line 35) | inline std::unique_ptr<Event> make_note_on_event(const InputConnection...
    function make_note_off_event (line 48) | inline std::unique_ptr<Event> make_note_off_event(const InputConnectio...
    function make_note_aftertouch_event (line 56) | inline std::unique_ptr<Event> make_note_aftertouch_event(const InputCo...
    function make_aftertouch_event (line 64) | inline std::unique_ptr<Event> make_aftertouch_event(const InputConnect...
    function make_modulation_event (line 72) | inline std::unique_ptr<Event> make_modulation_event(const InputConnect...
    function make_pitch_bend_event (line 80) | inline std::unique_ptr<Event> make_pitch_bend_event(const InputConnect...
    function make_wrapped_midi_event (line 88) | inline std::unique_ptr<Event> make_wrapped_midi_event(const InputConne...
    function make_param_change_event (line 98) | inline std::unique_ptr<Event> make_param_change_event(InputConnection& c,
    function make_program_change_event (line 126) | inline std::unique_ptr<Event> make_program_change_event(const InputCon...
    function MidiDispatcherStatus (line 153) | MidiDispatcherStatus MidiDispatcher::connect_cc_to_parameter(int midi_...
    function MidiDispatcherStatus (line 183) | MidiDispatcherStatus MidiDispatcher::disconnect_cc_from_parameter(int ...
    function MidiDispatcherStatus (line 214) | MidiDispatcherStatus MidiDispatcher::disconnect_all_cc_from_processor(...
    function MidiDispatcherStatus (line 256) | MidiDispatcherStatus MidiDispatcher::connect_pc_to_processor(int midi_...
    function MidiDispatcherStatus (line 278) | MidiDispatcherStatus MidiDispatcher::disconnect_pc_from_processor(int ...
    function MidiDispatcherStatus (line 307) | MidiDispatcherStatus MidiDispatcher::disconnect_all_pc_from_processor(...
    function MidiDispatcherStatus (line 342) | MidiDispatcherStatus MidiDispatcher::connect_kb_to_track(int midi_input,
    function MidiDispatcherStatus (line 364) | MidiDispatcherStatus MidiDispatcher::disconnect_kb_from_track(int midi...
    function MidiDispatcherStatus (line 441) | MidiDispatcherStatus MidiDispatcher::connect_raw_midi_to_track(int mid...
    function MidiDispatcherStatus (line 463) | MidiDispatcherStatus MidiDispatcher::disconnect_raw_midi_from_track(in...
    function MidiDispatcherStatus (line 492) | MidiDispatcherStatus MidiDispatcher::connect_track_to_output(int midi_...
    function MidiDispatcherStatus (line 520) | MidiDispatcherStatus MidiDispatcher::disconnect_track_from_output(int ...
    function MidiDispatcherStatus (line 574) | MidiDispatcherStatus MidiDispatcher::enable_midi_clock(bool enabled, i...

FILE: src/engine/midi_dispatcher.h
  function namespace (line 39) | namespace sushi::internal {

FILE: src/engine/midi_receiver.h
  function namespace (line 26) | namespace sushi::internal::midi_receiver {

FILE: src/engine/parameter_manager.cpp
  type sushi::internal (line 25) | namespace sushi::internal {
    function send_parameter_notification (line 27) | inline void send_parameter_notification(ObjectId processor_id,

FILE: src/engine/parameter_manager.h
  function namespace (line 34) | namespace sushi::internal {

FILE: src/engine/plugin_library.cpp
  type sushi::internal::engine (line 22) | namespace sushi::internal::engine {

FILE: src/engine/plugin_library.h
  function namespace (line 26) | namespace sushi::internal::engine {

FILE: src/engine/processor_container.cpp
  type sushi::internal::engine (line 25) | namespace sushi::internal::engine {

FILE: src/engine/processor_container.h
  function namespace (line 34) | namespace sushi::internal::engine {

FILE: src/engine/receiver.cpp
  type sushi::internal::receiver (line 29) | namespace sushi::internal::receiver {

FILE: src/engine/receiver.h
  function namespace (line 30) | namespace sushi::internal::receiver {

FILE: src/engine/track.cpp
  type sushi::internal::engine (line 25) | namespace sushi::internal::engine {
    function calc_l_r_gain (line 32) | inline std::pair<float, float> calc_l_r_gain(float gain, float pan)
    function ProcessorReturnCode (line 81) | ProcessorReturnCode Track::init(float sample_rate)

FILE: src/engine/track.h
  type class (line 44) | enum class
  function ChunkSampleBuffer (line 105) | ChunkSampleBuffer input_bus(int bus)
  function ChunkSampleBuffer (line 116) | ChunkSampleBuffer output_bus(int bus)
  function ChunkSampleBuffer (line 127) | ChunkSampleBuffer input_channel(int index)
  function ChunkSampleBuffer (line 138) | ChunkSampleBuffer output_channel(int index)
  function ext_render_function (line 172) | static void ext_render_function(void* arg)
  function PanMode (line 195) | enum class PanMode

FILE: src/engine/transport.cpp
  type sushi::internal::engine (line 40) | namespace sushi::internal::engine {
    class RtSafeClock (line 56) | class RtSafeClock
      method micros (line 59) | [[nodiscard]] std::chrono::microseconds micros() const
    class SushiLink (line 69) | class SushiLink : public ::ableton::BasicLink<RtSafeClock>
      method SushiLink (line 74) | explicit SushiLink(double bpm) : ::ableton::BasicLink<Clock>(bpm) { }
    function peer_callback (line 81) | void peer_callback([[maybe_unused]] size_t peers)
    function tempo_callback (line 86) | void tempo_callback([[maybe_unused]] double tempo)
    function start_stop_callback (line 91) | void start_stop_callback([[maybe_unused]] bool playing)
    function valid_time_signature (line 96) | inline bool valid_time_signature(const TimeSignature& sig)

FILE: src/engine/transport.h
  function namespace (line 40) | namespace ableton {class Link;}
  type class (line 44) | enum class
  type class (line 51) | enum class
  function set_latency (line 82) | void set_latency(Time output_latency)
  function set_sample_rate (line 144) | void set_sample_rate(float sample_rate) { _samplerate = sample_rate; }
  function set_position_source (line 220) | void set_position_source(PositionSource position_source) {_position_sour...
  function PositionSource (line 226) | [[nodiscard]] PositionSource position_source() { return _position_source; }
  function set_current_beats (line 233) | void set_current_beats(double beat_count) { _beat_count = beat_count; }
  function set_current_bar_beats (line 240) | void set_current_bar_beats(double bar_beat_count) { _current_bar_beat_co...
  function _sample_count (line 261) | int64_t         _sample_count {0}
  function Time (line 262) | Time            _time {0}
  function Time (line 263) | Time            _latency {0}
  function _bar_start_beat_count (line 266) | double          _bar_start_beat_count {0}
  function _beats_per_chunk (line 267) | double          _beats_per_chunk {0}
  function _beats_per_bar (line 268) | double          _beats_per_bar {0}
  function _samplerate (line 269) | float           _samplerate {0}
  function _last_tick_sent (line 271) | double          _last_tick_sent {0}
  function TimeSignature (line 278) | TimeSignature   _time_signature {4, 4};

FILE: src/factories/base_factory.cpp
  type sushi::internal (line 36) | namespace sushi::internal {
    function Status (line 131) | Status BaseFactory::_configure_from_file(SushiOptions& options)
    function Status (line 145) | Status BaseFactory::_configure_from_json(SushiOptions& options)
    function Status (line 179) | Status BaseFactory::_configure_with_defaults(SushiOptions& options)
    function Status (line 190) | Status BaseFactory::_configure_timing_options(const SushiOptions& opti...
    function Status (line 210) | Status BaseFactory::_configure_engine(SushiOptions& options,
    function Status (line 255) | Status BaseFactory::_load_json_configuration(jsonconfig::JsonConfigura...
    function Status (line 293) | Status BaseFactory::_set_up_control([[maybe_unused]] const SushiOption...

FILE: src/factories/base_factory.h
  function namespace (line 33) | namespace engine {
  function namespace (line 38) | namespace audio_frontend {
  function namespace (line 43) | namespace midi_frontend {
  function namespace (line 47) | namespace midi_dispatcher {
  function namespace (line 51) | namespace control_frontend {
  function namespace (line 55) | namespace jsonconfig {

FILE: src/factories/offline_factory.cpp
  type sushi (line 25) | namespace sushi {

FILE: src/factories/offline_factory_implementation.cpp
  type sushi::internal (line 37) | namespace sushi::internal {
    function Status (line 65) | Status OfflineFactoryImplementation::_setup_audio_frontend(const Sushi...
    function Status (line 94) | Status OfflineFactoryImplementation::_set_up_midi([[maybe_unused]] con...
    function Status (line 107) | Status OfflineFactoryImplementation::_load_json_events([[maybe_unused]...

FILE: src/factories/offline_factory_implementation.h
  function namespace (line 29) | namespace sushi::internal {

FILE: src/factories/reactive_factory.cpp
  type sushi (line 26) | namespace sushi

FILE: src/factories/reactive_factory_implementation.cpp
  type sushi::internal (line 42) | namespace sushi::internal {
    function Status (line 72) | Status ReactiveFactoryImplementation::_setup_audio_frontend([[maybe_un...
    function Status (line 86) | Status ReactiveFactoryImplementation::_set_up_midi([[maybe_unused]] co...
    function Status (line 100) | Status ReactiveFactoryImplementation::_load_json_events([[maybe_unused...

FILE: src/factories/reactive_factory_implementation.h
  function namespace (line 30) | namespace sushi_rpc {
  function namespace (line 34) | namespace sushi::internal {

FILE: src/factories/standalone_factory.cpp
  type sushi (line 25) | namespace sushi {

FILE: src/factories/standalone_factory_implementation.cpp
  type sushi::internal (line 53) | namespace sushi::internal {
    function Status (line 83) | Status
    function Status (line 162) | Status StandaloneFactoryImplementation::_set_up_midi([[maybe_unused]] ...
    function Status (line 192) | Status StandaloneFactoryImplementation::_load_json_events([[maybe_unus...

FILE: src/factories/standalone_factory_implementation.h
  function namespace (line 29) | namespace sushi_rpc {
  function namespace (line 33) | namespace sushi::internal {

FILE: src/library/base_performance_timer.h
  function ProcessTimings (line 28) | struct ProcessTimings

FILE: src/library/base_processor_factory.h
  function namespace (line 27) | namespace sushi::internal {

FILE: src/library/connection_types.h
  function namespace (line 26) | namespace sushi::internal {

FILE: src/library/event.cpp
  function ELK_PUSH_WARNING (line 32) | ELK_PUSH_WARNING

FILE: src/library/event.h
  function namespace (line 37) | namespace engine {class BaseEngine;}
  function namespace (line 39) | namespace dispatcher
  function namespace (line 50) | namespace EventStatus {
  function set_completion_cb (line 93) | void set_completion_cb(EventCompletionCallback callback, void* data)
  function virtual (line 113) | [[nodiscard]] virtual RtEvent to_rt_event(int /*sample_offset*/) const {...
  function EventId (line 155) | EventId                 _id{EventIdGenerator::new_id()};
  function class (line 162) | class KeyboardEvent : public Event
  function MidiDataByte (line 224) | MidiDataByte midi_data() {return _midi_data;}
  function class (line 235) | class ParameterChangeEvent : public Event
  function class (line 435) | class PropertyChangeEvent : public EngineEvent
  function class (line 454) | class SetEngineTempoEvent : public EngineEvent
  function class (line 466) | class SetEngineTimeSignatureEvent : public EngineEvent
  function class (line 478) | class SetEnginePlayingModeStateEvent : public EngineEvent
  function class (line 490) | class SetEngineSyncModeEvent : public EngineEvent
  function class (line 502) | class AsynchronousWorkEvent : public Event
  function class (line 515) | class AsynchronousProcessorWorkEvent : public AsynchronousWorkEvent
  function class (line 538) | class AsynchronousBlobDeleteEvent : public AsynchronousWorkEvent
  function class (line 550) | class AsynchronousDeleteEvent : public AsynchronousWorkEvent
  function class (line 567) | class ParameterChangeNotificationEvent : public Event
  function class (line 602) | class PropertyChangeNotificationEvent : public Event
  function class (line 627) | class EngineNotificationEvent : public Event
  type class (line 663) | enum class
  function class (line 682) | class AudioGraphNotificationEvent : public EngineNotificationEvent

FILE: src/library/event_interface.h
  function namespace (line 27) | namespace sushi::internal {

FILE: src/library/fixed_stack.h
  function namespace (line 28) | namespace sushi {

FILE: src/library/id_generator.h
  function std (line 31) | static std::atomic<T> counter{0}
  type ObjectId (line 36) | typedef uint32_t ObjectId;
  function class (line 38) | class ProcessorIdGenerator : public BaseIdGenerator<ObjectId>
  type EventId (line 41) | typedef uint16_t EventId;
  function class (line 43) | class EventIdGenerator : public BaseIdGenerator<EventId>

FILE: src/library/internal_plugin.cpp
  type sushi::internal (line 29) | namespace sushi::internal {
    function FloatParameterValue (line 39) | FloatParameterValue* InternalPlugin::register_float_parameter(const st...
    function IntParameterValue (line 68) | IntParameterValue* InternalPlugin::register_int_parameter(const std::s...
    function BoolParameterValue (line 97) | BoolParameterValue* InternalPlugin::register_bool_parameter(const std:...
    function ProcessorReturnCode (line 302) | ProcessorReturnCode InternalPlugin::set_property_value(ObjectId proper...
    function ProcessorReturnCode (line 318) | ProcessorReturnCode InternalPlugin::set_state(ProcessorState* state, b...
    function ProcessorState (line 347) | ProcessorState InternalPlugin::save_state() const
    function PluginInfo (line 378) | PluginInfo InternalPlugin::info() const

FILE: src/library/internal_plugin.h
  function namespace (line 32) | namespace sushi::internal {

FILE: src/library/internal_processor_factory.cpp
  type sushi::internal (line 62) | namespace sushi::internal {
    class BaseInternalPlugFactory (line 67) | class BaseInternalPlugFactory
    class InternalFactory (line 76) | class InternalFactory : public BaseInternalPlugFactory
      method uid (line 79) | std::string_view uid() const override
      method create (line 84) | std::shared_ptr<Processor> create(const HostControl &host_control) o...

FILE: src/library/internal_processor_factory.h
  function namespace (line 25) | namespace sushi::internal {

FILE: src/library/lv2/lv2_control.cpp
  type sushi::internal::lv2 (line 20) | namespace sushi::internal::lv2 {
    function ControlID (line 24) | ControlID ControlID::new_port_control(Port* port, Model* model, uint32...
    function ControlID (line 105) | ControlID ControlID::new_property_control(Model* model, const LilvNode...

FILE: src/library/lv2/lv2_control.h
  type ScalePoint (line 30) | struct ScalePoint
  type class (line 37) | enum class
  type ControlID (line 44) | struct ControlID
  function LV2_URID (line 59) | LV2_URID property {0}
  function index (line 60) | int index {0}
  function is_writable (line 73) | bool is_writable {false}; // Writable (input)

FILE: src/library/lv2/lv2_features.cpp
  type sushi::internal::lv2 (line 29) | namespace sushi::internal::lv2 {
    function Port (line 33) | Port* port_by_symbol(Model* model, const char* sym)
    function lv2_log (line 49) | int lv2_log(LV2_Log_Handle handle,
    function lv2_vprintf (line 94) | int lv2_vprintf(LV2_Log_Handle handle,
    function lv2_printf (line 109) | int lv2_printf(LV2_Log_Handle handle,
    function LV2_URID (line 149) | LV2_URID map_uri(LV2_URID_Map_Handle handle, const char* uri)
    function init_feature (line 161) | void init_feature(LV2_Feature* const dest, const char* const URI, void...

FILE: src/library/lv2/lv2_features.h
  function namespace (line 55) | namespace sushi::internal::lv2 {

FILE: src/library/lv2/lv2_host_nodes.h
  function namespace (line 38) | namespace sushi::internal::lv2 {

FILE: src/library/lv2/lv2_model.cpp
  type sushi::internal::lv2 (line 42) | namespace sushi::internal::lv2 {
    function ProcessorReturnCode (line 145) | ProcessorReturnCode Model::load_plugin(const LilvPlugin* plugin_handle...
    function Port (line 282) | Port Model::_create_port(const LilvPlugin* plugin, int port_index, flo...
    function LILV_FOREACH (line 314) | LILV_FOREACH(nodes, p, properties)
    function State (line 431) | State* Model::state()
    function LILV_FOREACH (line 492) | LILV_FOREACH(nodes, f, required_features)
    function LilvWorld (line 514) | LilvWorld* Model::lilv_world()
    function LilvInstance (line 519) | LilvInstance* Model::plugin_instance()
    function LilvPlugin (line 524) | const LilvPlugin* Model::plugin_class()
    function Port (line 539) | Port* Model::get_port(int index)
    function HostNodes (line 554) | const HostNodes* Model::nodes()
    function LV2_URIDs (line 559) | const LV2_URIDs& Model::urids()
    function LV2_URID_Map (line 564) | LV2_URID_Map& Model::get_map()
    function LV2_URID_Unmap (line 569) | LV2_URID_Unmap& Model::get_unmap()
    function LV2_URID (line 574) | LV2_URID Model::map(const char* uri)
    function LV2_Atom_Forge (line 588) | LV2_Atom_Forge& Model::forge()
    function PlayState (line 628) | PlayState Model::play_state() const
    function Worker (line 709) | Worker* Model::worker()
    function Worker (line 714) | Worker* Model::state_worker()
    function LV2_Wrapper (line 724) | LV2_Wrapper* Model::wrapper()

FILE: src/library/lv2/lv2_model.h
  type ControlID (line 48) | struct ControlID
  type ControlChange (line 54) | struct ControlChange
  type LV2_URIDs (line 62) | struct LV2_URIDs
  type class (line 98) | enum class
  type HostFeatures (line 105) | struct HostFeatures
  function _control_input_index (line 257) | int _control_input_index{0}
  function _plugin_latency (line 259) | int _plugin_latency{0}
  function _sample_rate (line 271) | float _sample_rate{0}
  function _position (line 292) | uint32_t _position{0}
  function _bpm (line 293) | float _bpm{0}
  function LilvState (line 297) | LilvState* _state_to_set{nullptr};

FILE: src/library/lv2/lv2_port.cpp
  type sushi::internal::lv2 (line 29) | namespace sushi::internal::lv2 {
    function PortFlow (line 147) | PortFlow Port::flow() const
    function PortType (line 152) | PortType Port::type() const
    function LilvPort (line 157) | const LilvPort* Port::lilv_port()

FILE: src/library/lv2/lv2_port.h
  type class (line 38) | enum class
  type class (line 45) | enum class
  function _show_hidden (line 104) | bool _show_hidden{true};

FILE: src/library/lv2/lv2_processor_factory.cpp
  type sushi::internal::lv2 (line 28) | namespace sushi::internal::lv2 {

FILE: src/library/lv2/lv2_processor_factory.h
  function namespace (line 25) | namespace sushi::internal::lv2 {

FILE: src/library/lv2/lv2_state.cpp
  type sushi::internal::lv2 (line 26) | namespace sushi::internal::lv2 {
    function populate_preset_list (line 31) | static int populate_preset_list(Model* model, const LilvNode *node, co...
    function LILV_FOREACH (line 133) | LILV_FOREACH(nodes, i, presets)
    function LILV_FOREACH (line 164) | LILV_FOREACH(nodes, i, presets)
    function set_port_value (line 282) | void set_port_value(const char* port_symbol,

FILE: src/library/lv2/lv2_state.h
  function namespace (line 34) | namespace sushi::internal::lv2 {

FILE: src/library/lv2/lv2_worker.cpp
  type sushi::internal::lv2 (line 19) | namespace sushi::internal::lv2 {
    function LV2_Worker_Status (line 27) | static LV2_Worker_Status lv2_worker_respond(LV2_Worker_Respond_Handle ...
    function LV2_Worker_Status (line 41) | LV2_Worker_Status Worker::schedule(LV2_Worker_Schedule_Handle handle, ...
    function Lv2WorkerFifo (line 133) | Lv2WorkerFifo& Worker::requests()
    function Lv2WorkerFifo (line 138) | Lv2WorkerFifo& Worker::responses()
    function LV2_Worker_Interface (line 143) | const LV2_Worker_Interface* Worker::iface()

FILE: src/library/lv2/lv2_worker.h
  function namespace (line 26) | namespace sushi::internal::lv2 {
  function class (line 44) | class Worker

FILE: src/library/lv2/lv2_wrapper.cpp
  type sushi::internal::lv2 (line 36) | namespace sushi::internal::lv2 {
    function LilvWorld (line 60) | LilvWorld* LilvWorldWrapper::world()
    function ProcessorReturnCode (line 76) | ProcessorReturnCode LV2_Wrapper::init(float sample_rate)
    function ParameterDescriptor (line 133) | const ParameterDescriptor* LV2_Wrapper::parameter_from_id(ObjectId id)...
    function ProcessorReturnCode (line 263) | ProcessorReturnCode LV2_Wrapper::set_program(int program)
    function ProcessorReturnCode (line 282) | ProcessorReturnCode LV2_Wrapper::set_state(ProcessorState* state, bool...
    function ProcessorState (line 355) | ProcessorState LV2_Wrapper::save_state() const
    function PluginInfo (line 362) | PluginInfo LV2_Wrapper::info() const
    function MidiDataByte (line 832) | MidiDataByte LV2_Wrapper::_convert_event_to_midi_buffer(RtEvent& event)
    function LilvPlugin (line 938) | const LilvPlugin* LV2_Wrapper::_plugin_handle_from_URI(const std::stri...

FILE: src/library/lv2/lv2_wrapper.h
  function class (line 66) | class LilvWorldWrapper
  function ChunkSampleBuffer (line 189) | ChunkSampleBuffer _dummy_input{1}
  function ChunkSampleBuffer (line 191) | ChunkSampleBuffer _dummy_output{1}
  function _to_domain (line 215) | static float _to_domain(float value_normalized, float min_domain, float ...
  function _to_normalized (line 220) | static float _to_normalized(float value, float min_domain, float max_dom...
  function _min_normalized (line 225) | static constexpr float _min_normalized{0.0f};

FILE: src/library/midi_decoder.cpp
  type sushi::internal::midi (line 25) | namespace sushi::internal::midi {
    function realtime_msg (line 64) | inline bool realtime_msg(MidiDataByte data)
    function MessageType (line 69) | MessageType decode_common_messages(MidiDataByte data)
    function MessageType (line 99) | MessageType decode_realtime_message(MidiDataByte data)
    function MessageType (line 128) | MessageType decode_control_change_type(MidiDataByte data)
    function MessageType (line 180) | MessageType decode_message_type(MidiDataByte data)
    function NoteOffMessage (line 222) | NoteOffMessage decode_note_off(MidiDataByte data)
    function NoteOnMessage (line 231) | NoteOnMessage decode_note_on(MidiDataByte data)
    function PolyKeyPressureMessage (line 240) | PolyKeyPressureMessage decode_poly_key_pressure(MidiDataByte data)
    function ControlChangeMessage (line 249) | ControlChangeMessage decode_control_change(MidiDataByte data)
    function ProgramChangeMessage (line 258) | ProgramChangeMessage decode_program_change(MidiDataByte data)
    function ChannelPressureMessage (line 266) | ChannelPressureMessage decode_channel_pressure(MidiDataByte data)
    function PitchBendMessage (line 274) | PitchBendMessage decode_pitch_bend(MidiDataByte data)
    function TimeCodeMessage (line 282) | TimeCodeMessage decode_time_code(MidiDataByte data)
    function SongPositionMessage (line 290) | SongPositionMessage decode_song_position(MidiDataByte data)
    function SongSelectMessage (line 297) | SongSelectMessage decode_song_select(MidiDataByte data)

FILE: src/library/midi_decoder.h
  function MidiDataByte (line 53) | inline MidiDataByte to_midi_data_byte(const uint8_t* data, int size)
  type MidiChannel (line 66) | enum MidiChannel
  function MessageType (line 90) | enum class MessageType

FILE: src/library/midi_encoder.cpp
  type sushi::internal::midi (line 26) | namespace sushi::internal::midi {
    function MidiDataByte (line 46) | MidiDataByte encode_note_on(int channel, int note, float velocity)
    function MidiDataByte (line 56) | MidiDataByte encode_note_off(int channel, int note, float velocity)
    function MidiDataByte (line 66) | MidiDataByte encode_poly_key_pressure(int channel, int note, float pre...
    function MidiDataByte (line 76) | MidiDataByte encode_control_change(int channel, int controller, float ...
    function MidiDataByte (line 86) | MidiDataByte encode_channel_pressure(int channel, float value)
    function MidiDataByte (line 96) | MidiDataByte encode_pitch_bend(int channel, float value)
    function MidiDataByte (line 107) | MidiDataByte encode_program_change(int channel, int program)
    function MidiDataByte (line 117) | MidiDataByte encode_start_message()
    function MidiDataByte (line 122) | MidiDataByte encode_stop_message()
    function MidiDataByte (line 127) | MidiDataByte encode_continue_message()
    function MidiDataByte (line 132) | MidiDataByte encode_timing_clock()
    function MidiDataByte (line 137) | MidiDataByte encode_active_sensing()
    function MidiDataByte (line 142) | MidiDataByte encode_reset_message()

FILE: src/library/midi_encoder.h
  function namespace (line 26) | namespace sushi::internal::midi {

FILE: src/library/parameter_dump.cpp
  type sushi (line 28) | namespace sushi {
    function generate_processor_parameter_document (line 30) | rapidjson::Document generate_processor_parameter_document(sushi::contr...

FILE: src/library/performance_timer.cpp
  type sushi::internal::performance (line 27) | namespace sushi::internal::performance {
    function ProcessTimings (line 140) | ProcessTimings PerformanceTimer::_calculate_timings(const std::vector<...
    function ProcessTimings (line 157) | ProcessTimings PerformanceTimer::_merge_timings(ProcessTimings prev_ti...

FILE: src/library/performance_timer.h
  function namespace (line 39) | namespace sushi::internal::performance {

FILE: src/library/plugin_parameters.h
  function namespace (line 35) | namespace sushi::internal {
  function class (line 338) | class CubicWarpPreProcessor : public FloatParameterPreProcessor
  function to_normalized (line 350) | float to_normalized(float value) override
  function ParameterDescriptor (line 376) | [[nodiscard]] ParameterDescriptor* descriptor() const {return _descriptor;}
  function set (line 378) | void set(float value_normalized)
  function set_processed (line 384) | void set_processed(float value_processed)
  function ParameterDescriptor (line 414) | ParameterDescriptor* descriptor() const {return _descriptor;}
  function set_values (line 416) | void set_values(bool value, bool raw_value) { _processed_value = value; ...
  function set (line 417) | void set(bool value) { _processed_value = value;}
  function ParameterDescriptor (line 421) | ParameterDescriptor* _descriptor{nullptr};
  function class (line 429) | class ParameterStorage

FILE: src/library/plugin_registry.cpp
  type sushi::internal (line 23) | namespace sushi::internal {

FILE: src/library/plugin_registry.h
  function namespace (line 31) | namespace sushi::internal {
  function class (line 41) | class PluginRegistry

FILE: src/library/processor.cpp
  type sushi::internal (line 9) | namespace sushi::internal {
    function ProcessorReturnCode (line 18) | ProcessorReturnCode Processor::connect_cv_from_parameter(ObjectId para...
    function ProcessorReturnCode (line 45) | ProcessorReturnCode Processor::connect_gate_from_processor(int gate_ou...
    function EventId (line 182) | EventId Processor::request_non_rt_task(AsyncWorkCallback callback)

FILE: src/library/processor.h
  function namespace (line 38) | namespace sushi::internal {
  function virtual (line 288) | virtual ProcessorReturnCode set_property_value(ObjectId /*property_id*/,...
  function set_program (line 344) | set_program(int /*program*/) {return ProcessorReturnCode::UNSUPPORTED_OP...
  function virtual (line 394) | virtual ProcessorReturnCode set_state(ProcessorState* /*state*/, bool /*...
  function virtual (line 399) | virtual ProcessorState save_state() const
  function output_event (line 438) | void output_event(const RtEvent& event)
  function _max_input_channels (line 501) | int _max_input_channels{0}
  function _max_output_channels (line 502) | int _max_output_channels{0}
  function _current_input_channels (line 504) | int _current_input_channels{0}
  function _current_output_channels (line 505) | int _current_output_channels{0}
  function _current_processing_thread (line 507) | int _current_processing_thread{0}
  function ObjectId (line 518) | ObjectId _id{ProcessorIdGenerator::new_id()};
  function explicit (line 560) | explicit BypassManager(bool bypassed_by_default) :
  function explicit (line 563) | explicit BypassManager(bool bypassed_by_default, std::chrono::millisecon...
  function set_bypass (line 580) | void set_bypass(bool bypass_enabled, float sample_rate)
  function ramp_output (line 611) | void ramp_output(ChunkSampleBuffer& output_buffer)
  function chunks_to_ramp (line 636) | [[nodiscard]] int chunks_to_ramp(float sample_rate) const
  type class (line 642) | enum class
  function BypassState (line 650) | BypassState _state{BypassState::NOT_BYPASSED};

FILE: src/library/processor_state.cpp
  type sushi::internal (line 23) | namespace sushi::internal {

FILE: src/library/processor_state.h
  function class (line 35) | class ProcessorState

FILE: src/library/rt_event.h
  function namespace (line 35) | namespace sushi::internal {
  function class (line 193) | class WrappedMidiRtEvent : public BaseRtEvent
  function class (line 207) | class GateRtEvent : public BaseRtEvent
  function class (line 225) | class CvRtEvent : public BaseRtEvent
  function class (line 247) | class ParameterChangeRtEvent : public BaseRtEvent
  function class (line 275) | class DataPayloadRtEvent : public BaseRtEvent
  function class (line 302) | class PropertyChangeRtEvent : public BaseRtEvent
  function RtDeletable (line 317) | RtDeletable* deletable_value() const {return _data;}
  function class (line 328) | class DataPropertyChangeRtEvent : public DataPayloadRtEvent
  function class (line 349) | class ProcessorCommandRtEvent : public BaseRtEvent
  function class (line 369) | class ProcessorStateRtEvent : public BaseRtEvent
  function class (line 385) | class ProcessorNotifyRtEvent : public BaseRtEvent
  function class (line 406) | class ReturnableRtEvent : public BaseRtEvent
  function class (line 430) | class ProcessorOperationRtEvent : public ReturnableRtEvent
  function class (line 441) | class TrackRtEvent : public ReturnableRtEvent
  function class (line 457) | class ProcessorReorderRtEvent : public ReturnableRtEvent
  function class (line 480) | class AsyncWorkRtEvent: public ReturnableRtEvent
  function class (line 494) | class AsyncWorkRtCompletionEvent : public ProcessorCommandRtEvent
  function class (line 540) | class SynchronisationRtEvent : public BaseRtEvent
  function class (line 553) | class TempoRtEvent : public BaseRtEvent
  function class (line 566) | class TimeSignatureRtEvent : public BaseRtEvent
  function PlayingMode (line 578) | enum class PlayingMode
  function SyncMode (line 598) | enum class SyncMode
  function class (line 620) | class TimingTickRtEvent : public BaseRtEvent
  function class (line 633) | class ClipNotificationRtEvent : public BaseRtEvent
  function is_keyboard_event (line 1294) | inline bool is_keyboard_event(const RtEvent& event)
  function is_engine_control_event (line 1305) | inline bool is_engine_control_event(const RtEvent& event)
  function is_returnable_event (line 1316) | inline bool is_returnable_event(const RtEvent& event)

FILE: src/library/rt_event_fifo.h
  function class (line 42) | class RtSafeRtEventFifo : public RtEventPipe
  function send_event (line 81) | void send_event(const RtEvent &event) override {SimpleFifo<RtEvent, size...

FILE: src/library/rt_event_pipe.h
  function namespace (line 35) | namespace sushi::internal {

FILE: src/library/simple_fifo.h
  function namespace (line 32) | namespace sushi::internal {

FILE: src/library/spinlock.h
  function namespace (line 31) | namespace sushi::internal {

FILE: src/library/synchronised_fifo.h
  function push (line 38) | void push(T&& message)
  function T (line 45) | T pop()
  function wait_for_data (line 53) | void wait_for_data(const std::chrono::milliseconds& timeout)
  function empty (line 62) | bool empty()

FILE: src/library/vst2x/vst2x_host_callback.cpp
  type sushi::internal::vst2 (line 28) | namespace sushi::internal::vst2 {
    function VstIntPtr (line 32) | VstIntPtr VSTCALLBACK host_callback(AEffect* effect, VstInt32 opcode, ...

FILE: src/library/vst2x/vst2x_host_callback.h
  type AEffect (line 34) | typedef AEffect *(*plugin_entry_proc)(audioMasterCallback host);

FILE: src/library/vst2x/vst2x_midi_event_fifo.h
  function namespace (line 48) | namespace sushi::internal::vst2 {

FILE: src/library/vst2x/vst2x_plugin_loader.cpp
  type sushi::internal::vst2 (line 63) | namespace sushi::internal::vst2 {
    function LibraryHandle (line 69) | LibraryHandle PluginLoader::get_library_handle_for_plugin(const std::s...
    function AEffect (line 87) | AEffect* PluginLoader::load_plugin(LibraryHandle library_handle)
    function LibraryHandle (line 127) | LibraryHandle PluginLoader::get_library_handle_for_plugin(const std::s...
    function AEffect (line 151) | AEffect* PluginLoader::load_plugin(LibraryHandle library_handle)
    function LibraryHandle (line 207) | LibraryHandle PluginLoader::get_library_handle_for_plugin(const std::s...
    function AEffect (line 225) | AEffect* PluginLoader::load_plugin(LibraryHandle library_handle)

FILE: src/library/vst2x/vst2x_plugin_loader.h
  function namespace (line 65) | namespace sushi::internal::vst2 {

FILE: src/library/vst2x/vst2x_processor_factory.cpp
  type sushi::internal::vst2 (line 29) | namespace sushi::internal::vst2 {

FILE: src/library/vst2x/vst2x_processor_factory.h
  function namespace (line 26) | namespace sushi::internal::vst2 {

FILE: src/library/vst2x/vst2x_wrapper.cpp
  type sushi::internal::vst2 (line 36) | namespace sushi::internal::vst2 {
    function ProcessorReturnCode (line 49) | ProcessorReturnCode Vst2xWrapper::init(float sample_rate)
    function ProcessorReturnCode (line 238) | ProcessorReturnCode Vst2xWrapper::set_program(int program)
    function VstTimeInfo (line 412) | VstTimeInfo* Vst2xWrapper::time_info()
    function ProcessorReturnCode (line 467) | ProcessorReturnCode Vst2xWrapper::set_state(ProcessorState* state, boo...
    function ProcessorState (line 500) | ProcessorState Vst2xWrapper::save_state() const
    function PluginInfo (line 528) | PluginInfo Vst2xWrapper::info() const
    function VstSpeakerArrangementType (line 565) | VstSpeakerArrangementType arrangement_from_channels(int channels)

FILE: src/library/vst2x/vst2x_wrapper.h
  function class (line 45) | class Vst2xWrapper : public Processor
  function ProcessorState (line 107) | ProcessorState save_state() const override;
  function ChunkSampleBuffer (line 180) | ChunkSampleBuffer _dummy_input {1}
  function ChunkSampleBuffer (line 181) | ChunkSampleBuffer _dummy_output {1}
  function _has_binary_programs (line 184) | bool _has_binary_programs{false};

FILE: src/library/vst3x/vst3x_file_utils.cpp
  type sushi::internal::vst3 (line 40) | namespace sushi::internal::vst3 {
    function make_safe_folder_name (line 47) | std::string make_safe_folder_name(std::string name)
    function is_hidden (line 58) | bool is_hidden(const std::filesystem::directory_entry& entry)
    function get_executable_path (line 67) | std::filesystem::path get_executable_path()
    function get_platform_locations (line 97) | std::vector<std::filesystem::path> get_platform_locations()
    function get_platform_locations (line 123) | std::vector<std::filesystem::path> get_platform_locations()
    function get_platform_locations (line 140) | std::vector<std::filesystem::path> get_platform_locations()
    function extract_preset_name (line 158) | std::string extract_preset_name(const std::filesystem::path& path)
    function add_patches (line 165) | void add_patches(const std::filesystem::path& path, std::vector<std::f...
    function scan_for_presets (line 192) | std::vector<std::filesystem::path> scan_for_presets(const std::string&...

FILE: src/library/vst3x/vst3x_file_utils.h
  function namespace (line 26) | namespace sushi::internal::vst3 {

FILE: src/library/vst3x/vst3x_host_app.cpp
  type sushi::internal::vst3 (line 46) | namespace sushi::internal::vst3 {
    class ConnectionProxy (line 128) | class ConnectionProxy : public Steinberg::FObject, public Steinberg::V...
      method ConnectionProxy (line 133) | explicit ConnectionProxy(Steinberg::Vst::IConnectionPoint* src_conne...

FILE: src/library/vst3x/vst3x_host_app.h
  function namespace (line 51) | namespace vst3 {

FILE: src/library/vst3x/vst3x_processor_factory.cpp
  function ELK_POP_WARNING (line 35) | ELK_POP_WARNING

FILE: src/library/vst3x/vst3x_processor_factory.h
  function namespace (line 27) | namespace sushi::internal::vst3 {

FILE: src/library/vst3x/vst3x_utils.cpp
  type sushi::internal::vst3 (line 23) | namespace sushi::internal::vst3 {
    function convert_note_on_event (line 42) | Steinberg::Vst::Event convert_note_on_event(const KeyboardRtEvent* event)
    function convert_note_off_event (line 60) | Steinberg::Vst::Event convert_note_off_event(const KeyboardRtEvent* ev...
    function convert_aftertouch_event (line 77) | Steinberg::Vst::Event convert_aftertouch_event(const KeyboardRtEvent* ...

FILE: src/library/vst3x/vst3x_utils.h
  function namespace (line 48) | namespace sushi::internal::vst3 {

FILE: src/library/vst3x/vst3x_wrapper.cpp
  type sushi::internal::vst3 (line 45) | namespace sushi::internal::vst3 {
    function to_ascii_str (line 58) | std::string to_ascii_str(Steinberg::Vst::String128 wchar_buffer)
    function ProcessorReturnCode (line 86) | ProcessorReturnCode Vst3xWrapper::init(float sample_rate)
    function ParameterDescriptor (line 319) | const ParameterDescriptor* Vst3xWrapper::parameter_from_id(ObjectId id...
    function ProcessorReturnCode (line 383) | ProcessorReturnCode Vst3xWrapper::set_property_value(ObjectId property...
    function ProcessorReturnCode (line 479) | ProcessorReturnCode Vst3xWrapper::set_program(int program)
    function ProcessorReturnCode (line 534) | ProcessorReturnCode Vst3xWrapper::set_state(ProcessorState* state, boo...
    function ProcessorState (line 583) | ProcessorState Vst3xWrapper::save_state() const
    function PluginInfo (line 600) | PluginInfo Vst3xWrapper::info() const
    function ProcessorReturnCode (line 609) | ProcessorReturnCode Vst3xWrapper::_setup()
    function EventId (line 1181) | EventId Vst3xWrapper::request_async_work(AsyncWorkCallback callback, v...
    function speaker_arr_from_channels (line 1202) | Steinberg::Vst::SpeakerArrangement speaker_arr_from_channels(int chann...

FILE: src/library/vst3x/vst3x_wrapper.h
  function class (line 60) | class Vst3xWrapper : public Processor
  type ParameterUpdate (line 207) | struct ParameterUpdate
  type PropertyInfo (line 213) | struct PropertyInfo
  function audio_thread_notification (line 216) | bool audio_thread_notification{false};
  function _program_count (line 224) | int _program_count{0}
  function _current_program (line 225) | int _current_program{0}
  function SushiProcessData (line 245) | SushiProcessData _process_data{&_in_event_list,

FILE: src/plugins/arpeggiator_plugin.cpp
  type sushi::internal::arpeggiator_plugin (line 25) | namespace sushi::internal::arpeggiator_plugin {
    function ProcessorReturnCode (line 50) | ProcessorReturnCode ArpeggiatorPlugin::init(float sample_rate)

FILE: src/plugins/arpeggiator_plugin.h
  function class (line 34) | class Arpeggiator

FILE: src/plugins/brickworks/bitcrusher_plugin.cpp
  type sushi::internal::bitcrusher_plugin (line 25) | namespace sushi::internal::bitcrusher_plugin {
    function ProcessorReturnCode (line 51) | ProcessorReturnCode BitcrusherPlugin::init(float sample_rate)

FILE: src/plugins/brickworks/bitcrusher_plugin.h
  function configure (line 51) | void configure(float sample_rate) override
  function _sample_rate (line 70) | float _sample_rate{0};

FILE: src/plugins/brickworks/cab_sim_plugin.cpp
  type sushi::internal::cab_sim_plugin (line 25) | namespace sushi::internal::cab_sim_plugin {
    function ProcessorReturnCode (line 56) | ProcessorReturnCode CabSimPlugin::init(float sample_rate)

FILE: src/plugins/brickworks/cab_sim_plugin.h
  function namespace (line 31) | namespace sushi::internal::cab_sim_plugin {

FILE: src/plugins/brickworks/chorus_plugin.cpp
  type sushi::internal::chorus_plugin (line 25) | namespace sushi::internal::chorus_plugin {
    function ProcessorReturnCode (line 57) | ProcessorReturnCode ChorusPlugin::init(float sample_rate)

FILE: src/plugins/brickworks/chorus_plugin.h
  function _sample_rate (line 64) | float _sample_rate{0}

FILE: src/plugins/brickworks/clip_plugin.cpp
  type sushi::internal::clip_plugin (line 25) | namespace sushi::internal::clip_plugin {
    function ProcessorReturnCode (line 51) | ProcessorReturnCode ClipPlugin::init(float sample_rate)

FILE: src/plugins/brickworks/clip_plugin.h
  function namespace (line 32) | namespace sushi::internal::clip_plugin {

FILE: src/plugins/brickworks/combdelay_plugin.cpp
  type sushi::internal::comb_plugin (line 25) | namespace sushi::internal::comb_plugin {
    function ProcessorReturnCode (line 66) | ProcessorReturnCode CombPlugin::init(float sample_rate)

FILE: src/plugins/brickworks/combdelay_plugin.h
  function _sample_rate (line 64) | float _sample_rate{0}

FILE: src/plugins/brickworks/compressor_plugin.cpp
  type sushi::internal::compressor_plugin (line 25) | namespace sushi::internal::compressor_plugin {
    function ProcessorReturnCode (line 68) | ProcessorReturnCode CompressorPlugin::init(float sample_rate)

FILE: src/plugins/brickworks/compressor_plugin.h
  function namespace (line 31) | namespace sushi::internal::compressor_plugin {

FILE: src/plugins/brickworks/dist_plugin.cpp
  type sushi::internal::dist_plugin (line 25) | namespace sushi::internal::dist_plugin {
    function ProcessorReturnCode (line 56) | ProcessorReturnCode DistPlugin::init(float sample_rate)

FILE: src/plugins/brickworks/dist_plugin.h
  function namespace (line 32) | namespace sushi::internal::dist_plugin {

FILE: src/plugins/brickworks/drive_plugin.cpp
  type sushi::internal::drive_plugin (line 25) | namespace sushi::internal::drive_plugin {
    function ProcessorReturnCode (line 56) | ProcessorReturnCode DrivePlugin::init(float sample_rate)

FILE: src/plugins/brickworks/drive_plugin.h
  function namespace (line 32) | namespace sushi::internal::drive_plugin {

FILE: src/plugins/brickworks/eq3band_plugin.cpp
  type sushi::internal::eq3band_plugin (line 25) | namespace sushi::internal::eq3band_plugin {
    function ProcessorReturnCode (line 88) | ProcessorReturnCode Eq3bandPlugin::init(float sample_rate)

FILE: src/plugins/brickworks/eq3band_plugin.h
  function namespace (line 33) | namespace sushi::internal::eq3band_plugin {

FILE: src/plugins/brickworks/flanger_plugin.cpp
  type sushi::internal::flanger_plugin (line 25) | namespace sushi::internal::flanger_plugin {
    function ProcessorReturnCode (line 57) | ProcessorReturnCode FlangerPlugin::init(float sample_rate)

FILE: src/plugins/brickworks/flanger_plugin.h
  function _sample_rate (line 64) | float _sample_rate{0}

FILE: src/plugins/brickworks/fuzz_plugin.cpp
  type sushi::internal::fuzz_plugin (line 25) | namespace sushi::internal::fuzz_plugin {
    function ProcessorReturnCode (line 51) | ProcessorReturnCode FuzzPlugin::init(float sample_rate)

FILE: src/plugins/brickworks/fuzz_plugin.h
  function namespace (line 32) | namespace sushi::internal::fuzz_plugin {

FILE: src/plugins/brickworks/highpass_plugin.cpp
  type sushi::internal::highpass_plugin (line 25) | namespace sushi::internal::highpass_plugin {
    function ProcessorReturnCode (line 46) | ProcessorReturnCode HighPassPlugin::init(float sample_rate)

FILE: src/plugins/brickworks/highpass_plugin.h
  function namespace (line 31) | namespace sushi::internal::highpass_plugin {

FILE: src/plugins/brickworks/multi_filter_plugin.cpp
  type sushi::internal::multi_filter_plugin (line 25) | namespace sushi::internal::multi_filter_plugin {
    function ProcessorReturnCode (line 71) | ProcessorReturnCode MultiFilterPlugin::init(float sample_rate)

FILE: src/plugins/brickworks/multi_filter_plugin.h
  function namespace (line 31) | namespace sushi::internal::multi_filter_plugin {

FILE: src/plugins/brickworks/noise_gate_plugin.cpp
  type sushi::internal::noise_gate_plugin (line 25) | namespace sushi::internal::noise_gate_plugin {
    function ProcessorReturnCode (line 61) | ProcessorReturnCode NoiseGatePlugin::init(float sample_rate)

FILE: src/plugins/brickworks/noise_gate_plugin.h
  function namespace (line 31) | namespace sushi::internal::noise_gate_plugin {

FILE: src/plugins/brickworks/notch_plugin.cpp
  type sushi::internal::notch_plugin (line 25) | namespace sushi::internal::notch_plugin {
    function ProcessorReturnCode (line 51) | ProcessorReturnCode NotchPlugin::init(float sample_rate)

FILE: src/plugins/brickworks/notch_plugin.h
  function namespace (line 31) | namespace sushi::internal::notch_plugin {

FILE: src/plugins/brickworks/phaser_plugin.cpp
  type sushi::internal::phaser_plugin (line 25) | namespace sushi::internal::phaser_plugin {
    function ProcessorReturnCode (line 56) | ProcessorReturnCode PhaserPlugin::init(float sample_rate)

FILE: src/plugins/brickworks/phaser_plugin.h
  function namespace (line 31) | namespace sushi::internal::phaser_plugin {

FILE: src/plugins/brickworks/ring_mod_plugin.cpp
  type sushi::internal::ring_mod_plugin (line 28) | namespace sushi::internal::ring_mod_plugin {
    function ProcessorReturnCode (line 54) | ProcessorReturnCode RingModPlugin::init(float sample_rate)

FILE: src/plugins/brickworks/ring_mod_plugin.h
  function namespace (line 32) | namespace sushi::internal::ring_mod_plugin {

FILE: src/plugins/brickworks/saturation_plugin.cpp
  type sushi::internal::saturation_plugin (line 25) | namespace sushi::internal::saturation_plugin {
    function ProcessorReturnCode (line 51) | ProcessorReturnCode SaturationPlugin::init(float sample_rate)

FILE: src/plugins/brickworks/saturation_plugin.h
  function namespace (line 32) | namespace sushi::internal::saturation_plugin {

FILE: src/plugins/brickworks/simple_synth_plugin.cpp
  type sushi::internal::simple_synth_plugin (line 29) | namespace sushi::internal::simple_synth_plugin {
    function ProcessorReturnCode (line 90) | ProcessorReturnCode SimpleSynthPlugin::init(float sample_rate)

FILE: src/plugins/brickworks/simple_synth_plugin.h
  function ChunkSampleBuffer (line 72) | ChunkSampleBuffer _render_buffer {1}
  function ChunkSampleBuffer (line 73) | ChunkSampleBuffer _aux_buffer {1}
  function bw_phase_gen_coeffs (line 85) | bw_phase_gen_coeffs _phase_gen_coeffs {}
  function bw_phase_gen_state (line 86) | bw_phase_gen_state  _phase_gen_state {}
  function bw_osc_pulse_coeffs (line 87) | bw_osc_pulse_coeffs _osc_pulse_coeffs {}
  function bw_osc_filt_state (line 88) | bw_osc_filt_state   _osc_filt_state {}
  function bw_svf_coeffs (line 89) | bw_svf_coeffs       _svf_coeffs {}
  function bw_svf_state (line 90) | bw_svf_state        _svf_state {}
  function bw_env_gen_coeffs (line 91) | bw_env_gen_coeffs   _env_gen_coeffs {}
  function bw_env_gen_state (line 92) | bw_env_gen_state    _env_gen_state {}
  function _note (line 96) | int _note {69};

FILE: src/plugins/brickworks/tremolo_plugin.cpp
  type sushi::internal::tremolo_plugin (line 25) | namespace sushi::internal::tremolo_plugin {
    function ProcessorReturnCode (line 51) | ProcessorReturnCode TremoloPlugin::init(float sample_rate)

FILE: src/plugins/brickworks/tremolo_plugin.h
  function namespace (line 31) | namespace sushi::internal::tremolo_plugin {

FILE: src/plugins/brickworks/vibrato_plugin.cpp
  type sushi::internal::vibrato_plugin (line 25) | namespace sushi::internal::vibrato_plugin {
    function ProcessorReturnCode (line 57) | ProcessorReturnCode VibratoPlugin::init(float sample_rate)

FILE: src/plugins/brickworks/vibrato_plugin.h
  function _sample_rate (line 64) | float _sample_rate{0}

FILE: src/plugins/brickworks/wah_plugin.cpp
  type sushi::internal::wah_plugin (line 25) | namespace sushi::internal::wah_plugin {
    function ProcessorReturnCode (line 46) | ProcessorReturnCode WahPlugin::init(float sample_rate)

FILE: src/plugins/brickworks/wah_plugin.h
  function namespace (line 31) | namespace sushi::internal::wah_plugin {

FILE: src/plugins/control_to_cv_plugin.cpp
  type sushi::internal::control_to_cv_plugin (line 26) | namespace sushi::internal::control_to_cv_plugin {
    function ProcessorReturnCode (line 85) | ProcessorReturnCode ControlToCvPlugin::init(float sample_rate)
    function pitch_to_cv (line 246) | float pitch_to_cv(float value)

FILE: src/plugins/control_to_cv_plugin.h
  function namespace (line 36) | namespace sushi::internal::control_to_cv_plugin {

FILE: src/plugins/cv_to_control_plugin.cpp
  type sushi::internal::cv_to_control_plugin (line 27) | namespace sushi::internal::cv_to_control_plugin {
    function ProcessorReturnCode (line 80) | ProcessorReturnCode CvToControlPlugin::init(float sample_rate)
    function cv_to_pitch (line 204) | std::pair<int, float> cv_to_pitch(float value)

FILE: src/plugins/cv_to_control_plugin.h
  function namespace (line 36) | namespace sushi::internal::cv_to_control_plugin {

FILE: src/plugins/equalizer_plugin.cpp
  type sushi::internal::equalizer_plugin (line 25) | namespace sushi::internal::equalizer_plugin {
    function ProcessorReturnCode (line 56) | ProcessorReturnCode EqualizerPlugin::init(float sample_rate)

FILE: src/plugins/equalizer_plugin.h
  function namespace (line 30) | namespace sushi::internal::equalizer_plugin {

FILE: src/plugins/freeverb_plugin.cpp
  type sushi::internal::freeverb_plugin (line 28) | namespace sushi::internal::freeverb_plugin {
    function ProcessorReturnCode (line 76) | ProcessorReturnCode FreeverbPlugin::init(float sample_rate)

FILE: src/plugins/freeverb_plugin.h
  function namespace (line 31) | namespace sushi::internal::freeverb_plugin {

FILE: src/plugins/gain_plugin.cpp
  type sushi::internal::gain_plugin (line 25) | namespace sushi::internal::gain_plugin {

FILE: src/plugins/gain_plugin.h
  function namespace (line 29) | namespace sushi::internal::gain_plugin {

FILE: src/plugins/lfo_plugin.cpp
  type sushi::internal::lfo_plugin (line 26) | namespace sushi::internal::lfo_plugin {
    function ProcessorReturnCode (line 46) | ProcessorReturnCode LfoPlugin::init(float sample_rate)

FILE: src/plugins/lfo_plugin.h
  function namespace (line 29) | namespace sushi::internal::lfo_plugin {

FILE: src/plugins/mono_summing_plugin.cpp
  type sushi::internal::mono_summing_plugin (line 23) | namespace sushi::internal::mono_summing_plugin {

FILE: src/plugins/mono_summing_plugin.h
  function namespace (line 30) | namespace sushi::internal::mono_summing_plugin {

FILE: src/plugins/passthrough_plugin.cpp
  type sushi::internal::passthrough_plugin (line 23) | namespace sushi::internal::passthrough_plugin {

FILE: src/plugins/passthrough_plugin.h
  function namespace (line 30) | namespace sushi::internal::passthrough_plugin {

FILE: src/plugins/peak_meter_plugin.cpp
  type sushi::internal::peak_meter_plugin (line 26) | namespace sushi::internal::peak_meter_plugin {
    function to_normalised_dB (line 43) | inline float to_normalised_dB(float gain)
    function ProcessorReturnCode (line 104) | ProcessorReturnCode PeakMeterPlugin::init(float sample_rate)

FILE: src/plugins/peak_meter_plugin.h
  function namespace (line 32) | namespace sushi::internal::peak_meter_plugin {

FILE: src/plugins/return_plugin.cpp
  type sushi::internal::return_plugin (line 30) | namespace sushi::internal::return_plugin {
    function ProcessorReturnCode (line 97) | ProcessorReturnCode ReturnPlugin::init(float sample_rate)

FILE: src/plugins/return_plugin.h
  function namespace (line 38) | namespace send_plugin { class SendPlugin; }
  function ChunkSampleBuffer (line 92) | ChunkSampleBuffer*                    _active_out{&_buffers[1]};

FILE: src/plugins/sample_delay_plugin.cpp
  type sushi::internal::sample_delay_plugin (line 23) | namespace sushi::internal::sample_delay_plugin {

FILE: src/plugins/sample_delay_plugin.h
  function namespace (line 33) | namespace sushi::internal::sample_delay_plugin {

FILE: src/plugins/sample_player_plugin.cpp
  type sushi::internal::sample_player_plugin (line 28) | namespace sushi::internal::sample_player_plugin {
    function BlobData (line 36) | BlobData load_sample_file(const std::string& file_name)
    function ProcessorReturnCode (line 111) | ProcessorReturnCode SamplePlayerPlugin::init(float sample_rate)
    function ProcessorReturnCode (line 269) | ProcessorReturnCode SamplePlayerPlugin::set_property_value(ObjectId pr...

FILE: src/plugins/sample_player_plugin.h
  function _dummy_sample (line 67) | float   _dummy_sample {0.0f};

FILE: src/plugins/sample_player_voice.cpp
  type sushi::internal::sample_player_voice (line 26) | namespace sushi::internal::sample_player_voice {

FILE: src/plugins/sample_player_voice.h
  type class (line 34) | enum class
  function set_samplerate (line 54) | void set_samplerate(float samplerate)
  function set_sample (line 65) | void set_sample(dsp::Sample* sample) {_sample = sample;}
  function set_envelope (line 70) | void set_envelope(float attack, float decay, float sustain, float release)
  function active (line 79) | bool active() {return (_state != SamplePlayMode::STOPPED);}
  function stopping (line 85) | bool stopping() {return _state == SamplePlayMode::STOPPING;}
  function current_note (line 91) | int current_note() {return _current_note;}
  function SamplePlayMode (line 122) | SamplePlayMode _state{SamplePlayMode::STOPPED};

FILE: src/plugins/send_plugin.cpp
  type sushi::internal::send_plugin (line 33) | namespace sushi::internal::send_plugin {
    function ProcessorReturnCode (line 94) | ProcessorReturnCode SendPlugin::init(float sample_rate)
    function ProcessorReturnCode (line 180) | ProcessorReturnCode SendPlugin::set_property_value(ObjectId property_i...

FILE: src/plugins/send_plugin.h
  function namespace (line 34) | namespace sushi::internal {

FILE: src/plugins/send_return_factory.cpp
  type sushi::internal (line 27) | namespace sushi::internal {

FILE: src/plugins/send_return_factory.h
  function namespace (line 30) | namespace sushi::internal {

FILE: src/plugins/step_sequencer_plugin.cpp
  type sushi::internal::step_sequencer_plugin (line 25) | namespace sushi::internal::step_sequencer_plugin {
    function ProcessorReturnCode (line 61) | ProcessorReturnCode StepSequencerPlugin::init(float sample_rate)
    function samples_per_qn (line 175) | float samples_per_qn(float tempo, float samplerate)
    function snap_to_scale (line 180) | int snap_to_scale(int note, const std::array<int, 12>& scale)

FILE: src/plugins/step_sequencer_plugin.h
  function namespace (line 32) | namespace sushi::internal::step_sequencer_plugin {

FILE: src/plugins/stereo_mixer_plugin.cpp
  type sushi::internal::stereo_mixer_plugin (line 25) | namespace sushi::internal::stereo_mixer_plugin {
    function calc_l_r_gain (line 40) | inline std::pair<float, float> calc_l_r_gain(float gain, float pan)
    function ProcessorReturnCode (line 105) | ProcessorReturnCode StereoMixerPlugin::init(float sample_rate)

FILE: src/plugins/stereo_mixer_plugin.h
  function namespace (line 30) | namespace sushi::internal::stereo_mixer_plugin {

FILE: src/plugins/transposer_plugin.cpp
  type sushi::internal::transposer_plugin (line 27) | namespace sushi::internal::transposer_plugin {
    function ProcessorReturnCode (line 52) | ProcessorReturnCode TransposerPlugin::init(float /*sample_rate*/)
    function MidiDataByte (line 105) | MidiDataByte TransposerPlugin::_transpose_midi(MidiDataByte midi_msg)

FILE: src/plugins/transposer_plugin.h
  function namespace (line 30) | namespace sushi::internal::transposer_plugin {

FILE: src/plugins/wav_streamer_plugin.cpp
  type sushi::internal::wav_streamer_plugin (line 25) | namespace sushi::internal::wav_streamer_plugin {
    function exp_approx (line 40) | inline float exp_approx(float x, float range)
    function T (line 48) | inline T catmull_rom_cubic_int(T frac_pos, T d0, T d1, T d2, T d3)
    function fill_stereo_block (line 59) | int64_t fill_stereo_block(SNDFILE* file, AudioBlock* block, bool looping)
    function fill_mono_block (line 84) | int64_t fill_mono_block(SNDFILE* file, AudioBlock* block, bool looping)
    function fill_remainder (line 113) | void fill_remainder(AudioBlock* block, std::array<std::array<float, 2>...
    function ProcessorReturnCode (line 185) | ProcessorReturnCode WavStreamerPlugin::init(float sample_rate)
    function ProcessorReturnCode (line 284) | ProcessorReturnCode WavStreamerPlugin::set_property_value(ObjectId pro...
    function StreamingMode (line 440) | StreamingMode WavStreamerPlugin::_update_mode(StreamingMode current)

FILE: src/plugins/wav_streamer_plugin.h
  type class (line 37) | enum class
  function RtDeletable (line 58) | struct AudioBlock : public RtDeletable
  function _sample_rate (line 156) | float _sample_rate {0}
  function _file_samplerate (line 157) | float _file_samplerate {0}
  function _file_length (line 158) | float _file_length {1}
  function _file_idx (line 159) | int   _file_idx {0}
  function SF_INFO (line 165) | SF_INFO     _file_info {}
  function AudioBlock (line 171) | AudioBlock* _current_block {nullptr};

FILE: src/plugins/wav_writer_plugin.cpp
  type sushi::internal::wav_writer_plugin (line 27) | namespace sushi::internal::wav_writer_plugin {
    function ProcessorReturnCode (line 59) | ProcessorReturnCode WavWriterPlugin::init(float sample_rate)
    function WavWriterStatus (line 114) | WavWriterStatus WavWriterPlugin::_start_recording()
    function WavWriterStatus (line 134) | WavWriterStatus WavWriterPlugin::_stop_recording()

FILE: src/plugins/wav_writer_plugin.h
  type WavWriterStatus (line 43) | enum WavWriterStatus : int
  function non_rt_callback (line 66) | static int non_rt_callback(void* data, EventId id)
  function SNDFILE (line 86) | SNDFILE* _output_file {nullptr};

FILE: src/utils.cpp
  type sushi (line 41) | namespace sushi {
    function read_file (line 53) | std::optional<std::string> read_file(const std::string& path)
    function init_logger (line 68) | void init_logger([[maybe_unused]] const SushiOptions& options)

FILE: test/unittests/audio_frontends/apple_coreaudio_frontend_test.cpp
  class TestAppleCoreAudioFrontend (line 20) | class TestAppleCoreAudioFrontend : public ::testing::Test
    method SetUp (line 23) | void SetUp() override
    method expect_calls_to_get_cf_string_property (line 28) | void expect_calls_to_get_cf_string_property(AudioObjectID expected_aud...
    method expect_calls_to_set_property (line 50) | void expect_calls_to_set_property(AudioObjectID expected_audio_object_...
    method expect_calls_to_get_property (line 69) | void expect_calls_to_get_property(AudioObjectID expected_audio_object_...
    method expect_calls_for_getting_output_device_name (line 86) | void expect_calls_for_getting_output_device_name(AudioObjectID expecte...
  function TEST_F (line 144) | TEST_F(TestAppleCoreAudioFrontend, audio_object_property_address_equality)
  function TEST_F (line 155) | TEST_F(TestAppleCoreAudioFrontend, cf_string_to_std_string)
  class MockAudioObject (line 164) | class MockAudioObject : public apple_coreaudio::AudioObject
    method MockAudioObject (line 167) | explicit MockAudioObject(AudioObjectID audio_object_id) : AudioObject(...
  function TEST_F (line 172) | TEST_F(TestAppleCoreAudioFrontend, AudioObject_get_audio_object_id)
  function TEST_F (line 181) | TEST_F(TestAppleCoreAudioFrontend, AudioObject_is_valid)
  function TEST_F (line 192) | TEST_F(TestAppleCoreAudioFrontend, AudioObject_has_property)
  function TEST_F (line 203) | TEST_F(TestAppleCoreAudioFrontend, AudioObject_is_property_settable)
  function TEST_F (line 220) | TEST_F(TestAppleCoreAudioFrontend, AudioObject_get_property_data_size)
  function TEST_F (line 231) | TEST_F(TestAppleCoreAudioFrontend, AudioObject_get_property_data)
  function TEST_F (line 244) | TEST_F(TestAppleCoreAudioFrontend, AudioObject_set_property_data)
  function TEST_F (line 254) | TEST_F(TestAppleCoreAudioFrontend, AudioObject_get_property)
  function TEST_F (line 294) | TEST_F(TestAppleCoreAudioFrontend, AudioObject_set_property)
  function TEST_F (line 338) | TEST_F(TestAppleCoreAudioFrontend, AudioObject_get_cf_string_property)
  function TEST_F (line 361) | TEST_F(TestAppleCoreAudioFrontend, AudioObject_get_property_array)
  function TEST_F (line 411) | TEST_F(TestAppleCoreAudioFrontend, AudioObject_add_property_listener)
  function TEST_F (line 449) | TEST_F(TestAppleCoreAudioFrontend, AudioSystemObject_get_audio_devices)
  function TEST_F (line 482) | TEST_F(TestAppleCoreAudioFrontend, AudioSystemObject_get_default_device_id)
  function OSStatus (line 529) | static OSStatus dummy_audio_device_io_proc(AudioObjectID,
  function TEST_F (line 542) | TEST_F(TestAppleCoreAudioFrontend, AudioDevice_start_io)
  function TEST_F (line 569) | TEST_F(TestAppleCoreAudioFrontend, AudioDevice_stop_io)
  function TEST_F (line 587) | TEST_F(TestAppleCoreAudioFrontend, AudioDevice_get_name)
  function TEST_F (line 601) | TEST_F(TestAppleCoreAudioFrontend, AudioDevice_get_uid)
  function TEST_F (line 615) | TEST_F(TestAppleCoreAudioFrontend, AudioDevice_get_num_channels)
  function TEST_F (line 663) | TEST_F(TestAppleCoreAudioFrontend, AudioDevice_set_buffer_frame_size)
  function TEST_F (line 677) | TEST_F(TestAppleCoreAudioFrontend, AudioDevice_set_nominal_sample_rate)
  function TEST_F (line 691) | TEST_F(TestAppleCoreAudioFrontend, AudioDevice_get_nominal_sample_rate)
  function TEST_F (line 703) | TEST_F(TestAppleCoreAudioFrontend, AudioDevice_get_device_latency)
  function TEST_F (line 719) | TEST_F(TestAppleCoreAudioFrontend, AudioDevice_get_stream_latency)
  function TEST_F (line 762) | TEST_F(TestAppleCoreAudioFrontend, AudioDevice_get_selected_stream_latency)
  function TEST_F (line 796) | TEST_F(TestAppleCoreAudioFrontend, AudioDevice_get_clock_domain_id)
  function TEST_F (line 806) | TEST_F(TestAppleCoreAudioFrontend, AudioDevice_get_related_devices)
  function TEST_F (line 834) | TEST_F(TestAppleCoreAudioFrontend, AudioDevice_get_num_streams)
  function TEST_F (line 872) | TEST_F(TestAppleCoreAudioFrontend, AudioDevice_is_aggregate_device)

FILE: test/unittests/audio_frontends/jack_frontend_test.cpp
  type sushi::internal::audio_frontend (line 26) | namespace sushi::internal::audio_frontend {
    class JackFrontendAccessor (line 27) | class JackFrontendAccessor
      method JackFrontendAccessor (line 30) | explicit JackFrontendAccessor(JackFrontend* f) : _friend(f) {}
      method jack_client_t (line 32) | jack_client_t* client()
  class TestJackFrontend (line 42) | class TestJackFrontend : public ::testing::Test
    method TestJackFrontend (line 45) | TestJackFrontend() = default;
    method SetUp (line 47) | void SetUp() override
    method TearDown (line 53) | void TearDown() override
  function TEST_F (line 64) | TEST_F(TestJackFrontend, TestOperation)

FILE: test/unittests/audio_frontends/offline_frontend_test.cpp
  type sushi::internal::audio_frontend (line 25) | namespace sushi::internal::audio_frontend
    class OfflineFrontendAccessor (line 28) | class OfflineFrontendAccessor
      method OfflineFrontendAccessor (line 31) | explicit OfflineFrontendAccessor(OfflineFrontend& f) : _friend(f) {}
  class TestOfflineFrontend (line 44) | class TestOfflineFrontend : public ::testing::Test
    method TestOfflineFrontend (line 47) | TestOfflineFrontend() = default;
    method SetUp (line 49) | void SetUp() override
  function TEST_F (line 64) | TEST_F(TestOfflineFrontend, TestWavProcessing)
  function TEST_F (line 111) | TEST_F(TestOfflineFrontend, TestInvalidInputFile)
  function TEST_F (line 118) | TEST_F(TestOfflineFrontend, TestMonoMode)
  function TEST_F (line 137) | TEST_F(TestOfflineFrontend, TestAddSequencerEvents)
  function TEST_F (line 171) | TEST_F(TestOfflineFrontend, TestNoiseGeneration)
  function TEST (line 192) | TEST(TestAudioFrontendInternals, TestRampCvOutput)

FILE: test/unittests/audio_frontends/portaudio_frontend_test.cpp
  type sushi::internal::audio_frontend (line 17) | namespace sushi::internal::audio_frontend
    class PortaudioFrontendAccessor (line 20) | class PortaudioFrontendAccessor
      method PortaudioFrontendAccessor (line 23) | explicit PortaudioFrontendAccessor(PortAudioFrontend& f) : _friend(f...
      method stream_initialized (line 25) | [[nodiscard]] bool stream_initialized() const
      method PaStream (line 30) | PaStream* stream()
  class TestPortAudioFrontend (line 49) | class TestPortAudioFrontend : public ::testing::Test
    method TestPortAudioFrontend (line 52) | TestPortAudioFrontend()
    method SetUp (line 55) | void SetUp() override
    method TearDown (line 63) | void TearDown() override
  function TEST_F (line 80) | TEST_F(TestPortAudioFrontend, TestInitSuccess)
  function TEST_F (line 101) | TEST_F(TestPortAudioFrontend, TestInitFailOnPaInit)
  function TEST_F (line 111) | TEST_F(TestPortAudioFrontend, TestInitFailGetDeviceCount)
  function TEST_F (line 123) | TEST_F(TestPortAudioFrontend, TestInitiFailSamplerate)
  function TEST_F (line 143) | TEST_F(TestPortAudioFrontend, TestInitiFailOpenStream)
  function TEST_F (line 163) | TEST_F(TestPortAudioFrontend, TestRun)
  function TEST_F (line 170) | TEST_F(TestPortAudioFrontend, TestProcess)
  function TEST_F (line 200) | TEST_F(TestPortAudioFrontend, TestGetDeviceName)

FILE: test/unittests/control_frontends/osc_frontend_test.cpp
  type sushi::internal::control_frontend (line 29) | namespace sushi::internal::control_frontend
    class OSCFrontendAccessor (line 32) | class OSCFrontendAccessor
      method OSCFrontendAccessor (line 35) | explicit OSCFrontendAccessor(OSCFrontend& f) : _friend(f) {}
      method set_processor_container (line 37) | void set_processor_container(const engine::BaseProcessorContainer* c...
      method OscConnection (line 42) | OscConnection* connect_to_parameter(const std::string& processor_name,
      method OscConnection (line 50) | OscConnection* connect_to_property(const std::string& processor_name,
      method OscConnection (line 58) | OscConnection* connect_kb_to_track(const Processor* processor)
      method OscConnection (line 63) | OscConnection* connect_to_program_change(const Processor* processor)
      method OscConnection (line 68) | OscConnection* connect_to_bypass_state(const Processor* processor)
  class TestOSCFrontend (line 91) | class TestOSCFrontend : public ::testing::Test
    method TestOSCFrontend (line 94) | TestOSCFrontend() = default;
    method SetUp (line 96) | void SetUp() override
    method TearDown (line 151) | void TearDown() override
  function TEST_F (line 174) | TEST_F(TestOSCFrontend, TestFailedInit)
  function TEST_F (line 180) | TEST_F(TestOSCFrontend, TestConnectFromAllParameters)
  function TEST_F (line 197) | TEST_F(TestOSCFrontend, TestAddAndRemoveConnectionsForProcessor)
  function TEST_F (line 226) | TEST_F(TestOSCFrontend, TestAddAndRemoveConnectionsForTrack)
  function TEST_F (line 261) | TEST_F(TestOSCFrontend, TestConnectParameterChange)
  function TEST_F (line 272) | TEST_F(TestOSCFrontend, TestConnectPropertyChange)
  function TEST_F (line 283) | TEST_F(TestOSCFrontend, TestAddKbdToTrack)
  function TEST_F (line 297) | TEST_F(TestOSCFrontend, TestConnectProgramChange)
  function TEST_F (line 307) | TEST_F(TestOSCFrontend, TestSetBypassState)
  function TEST_F (line 318) | TEST_F(TestOSCFrontend, TestParamChangeNotification)
  function TEST_F (line 366) | TEST_F(TestOSCFrontend, TestStateHandling)
  function TEST (line 391) | TEST(TestOSCFrontendInternal, TestMakeSafePath)

FILE: test/unittests/control_frontends/oscpack_osc_messenger_test.cpp
  type sushi::internal::osc (line 33) | namespace sushi::internal::osc
    class Accessor (line 36) | class Accessor
      method Accessor (line 39) | explicit Accessor(OscpackOscMessenger& f) : _friend(f) {}
      method OSC_CALLBACK_HANDLE (line 41) | [[nodiscard]] OSC_CALLBACK_HANDLE last_generated_handle() const
      method ProcessMessage (line 51) | void ProcessMessage(const oscpack::ReceivedMessage& m, const IpEndpo...
  class TestOscpackOscMessenger (line 83) | class TestOscpackOscMessenger : public ::testing::Test
    method TestOscpackOscMessenger (line 86) | TestOscpackOscMessenger() {}
    method SetUp (line 88) | void SetUp() override
  function TEST_F (line 115) | TEST_F(TestOscpackOscMessenger, TestAddAndRemoveConnections)
  function TEST_F (line 156) | TEST_F(TestOscpackOscMessenger, TestSendParameterChange)
  function TEST_F (line 186) | TEST_F(TestOscpackOscMessenger, TestSendPropertyChange)
  function TEST_F (line 215) | TEST_F(TestOscpackOscMessenger, TestSendNoteOn)
  function TEST_F (line 245) | TEST_F(TestOscpackOscMessenger, TestSendNoteOff)
  function TEST_F (line 275) | TEST_F(TestOscpackOscMessenger, TestSendNoteAftertouch)
  function TEST_F (line 305) | TEST_F(TestOscpackOscMessenger, TestSendKeyboardModulation)
  function TEST_F (line 335) | TEST_F(TestOscpackOscMessenger, TestSendKeyboardPitchBend)
  function TEST_F (line 364) | TEST_F(TestOscpackOscMessenger, TestSendKeyboardAftertouch)
  function TEST_F (line 393) | TEST_F(TestOscpackOscMessenger, TestSendProgramChange)
  function TEST_F (line 421) | TEST_F(TestOscpackOscMessenger, TestSetBypassState)
  function TEST_F (line 448) | TEST_F(TestOscpackOscMessenger, TestSetTempo)
  function TEST_F (line 468) | TEST_F(TestOscpackOscMessenger, TestSetTimeSignature)
  function TEST_F (line 489) | TEST_F(TestOscpackOscMessenger, TestSetPlayingMode)
  function TEST_F (line 509) | TEST_F(TestOscpackOscMessenger, TestSetSyncMode)
  function TEST_F (line 529) | TEST_F(TestOscpackOscMessenger, TestSetTimingStatisticsEnabled)
  function TEST_F (line 550) | TEST_F(TestOscpackOscMessenger, TestResetAllTimings)
  function TEST_F (line 567) | TEST_F(TestOscpackOscMessenger, TestResetProcessorTimings)
  function TEST_F (line 588) | TEST_F(TestOscpackOscMessenger, TestSendFloat)
  function TEST_F (line 597) | TEST_F(TestOscpackOscMessenger, TestSendInt)

FILE: test/unittests/dsp_library/envelope_test.cpp
  class TestADSREnvelope (line 11) | class TestADSREnvelope : public ::testing::Test
    method TestADSREnvelope (line 14) | TestADSREnvelope() = default;
    method SetUp (line 16) | void SetUp() override
  function TEST_F (line 25) | TEST_F(TestADSREnvelope, TestNormalOperation)
  function TEST_F (line 53) | TEST_F(TestADSREnvelope, TestParameterLimits)

FILE: test/unittests/dsp_library/master_limiter_test.cpp
  class TestUpSampler (line 10) | class TestUpSampler : public ::testing::Test
    method TestUpSampler (line 13) | TestUpSampler() = default;
    method SetUp (line 14) | void SetUp() override
  function TEST_F (line 22) | TEST_F(TestUpSampler, UpSampling)
  class TestMasterLimiter (line 36) | class TestMasterLimiter : public ::testing::Test
    method TestMasterLimiter (line 39) | TestMasterLimiter() = default;
    method SetUp (line 40) | void SetUp() override
  function TEST_F (line 48) | TEST_F(TestMasterLimiter, Limit)

FILE: test/unittests/dsp_library/sample_wrapper_test.cpp
  class TestSampleWrapper (line 11) | class TestSampleWrapper : public ::testing::Test
    method TestSampleWrapper (line 14) | TestSampleWrapper() = default;
  function TEST_F (line 19) | TEST_F(TestSampleWrapper, TestSampleInterpolation)

FILE: test/unittests/dsp_library/value_smoother_test.cpp
  function test_common (line 14) | void test_common(ValueSmoother<T, mode>& module_under_test)
  class ValueSmootherTest (line 32) | class ValueSmootherTest : public ::testing::Test
    method ValueSmootherTest (line 35) | ValueSmootherTest() = default;
    method SetUp (line 37) | void SetUp() override
  function TEST_F (line 49) | TEST_F(ValueSmootherTest, TestLinearFloat)
  function TEST_F (line 57) | TEST_F(ValueSmootherTest, TestExpFloat)
  function TEST_F (line 71) | TEST_F(ValueSmootherTest, TestExponentialFloat)

FILE: test/unittests/engine/audio_graph_test.cpp
  class TestAudioGraph (line 23) | class TestAudioGraph : public ::testing::Test
    method TestAudioGraph (line 27) | TestAudioGraph() = default;
    method SetUp (line 29) | void SetUp(int cores)
  function TEST_F (line 47) | TEST_F(TestAudioGraph, TestSingleCoreOperation)
  function TEST_F (line 80) | TEST_F(TestAudioGraph, TestMultiCoreOperation)
  function TEST_F (line 114) | TEST_F(TestAudioGraph, TestMaxNumberOfTracks)

FILE: test/unittests/engine/controller_test.cpp
  class ControllerTest (line 30) | class ControllerTest : public ::testing::Test
    method ControllerTest (line 33) | ControllerTest() = default;
    method SetUp (line 35) | void SetUp() override
  function TEST_F (line 63) | TEST_F(ControllerTest, TestMainEngineControls)
  function TEST_F (line 116) | TEST_F(ControllerTest, TestKeyboardControls)
  function TEST_F (line 129) | TEST_F(ControllerTest, TestTrackControls)
  function TEST_F (line 198) | TEST_F(ControllerTest, TestProcessorControls)
  function TEST_F (line 259) | TEST_F(ControllerTest, TestParameterControls)

FILE: test/unittests/engine/controllers/audio_graph_controller_test.cpp
  class AudioGraphControllerTest (line 15) | class AudioGraphControllerTest : public ::testing::Test
    method AudioGraphControllerTest (line 18) | AudioGraphControllerTest() = default;
    method SetUp (line 20) | void SetUp() override
  function TEST_F (line 39) | TEST_F(AudioGraphControllerTest, TestGettingProcessors)
  function TEST_F (line 86) | TEST_F(AudioGraphControllerTest, TestCreatingAndRemovingTracks)
  function TEST_F (line 133) | TEST_F(AudioGraphControllerTest, TestCreatingAndRemovingProcessors)

FILE: test/unittests/engine/controllers/audio_routing_controller_test.cpp
  class AudioRoutingControllerTest (line 15) | class AudioRoutingControllerTest : public ::testing::Test
    method AudioRoutingControllerTest (line 18) | AudioRoutingControllerTest() = default;
    method SetUp (line 20) | void SetUp() override
  function TEST_F (line 39) | TEST_F(AudioRoutingControllerTest, TestGettingAudioRouting)
  function TEST_F (line 90) | TEST_F(AudioRoutingControllerTest, TestSettingAudioRouting)
  function TEST_F (line 137) | TEST_F(AudioRoutingControllerTest, TestRemovingAudioRouting)

FILE: test/unittests/engine/controllers/midi_controller_test.cpp
  class MidiControllerEventTestFrontend (line 33) | class MidiControllerEventTestFrontend : public ::testing::Test
    method MidiControllerEventTestFrontend (line 36) | MidiControllerEventTestFrontend() = default;
    method SetUp (line 38) | void SetUp() override
  function TEST_F (line 53) | TEST_F(MidiControllerEventTestFrontend, TestKbdInputConectionDisconnection)
  function TEST_F (line 86) | TEST_F(MidiControllerEventTestFrontend, TestKbdInputConectionDisconnecti...
  function TEST_F (line 113) | TEST_F(MidiControllerEventTestFrontend, TestKbdOutputConectionDisconnect...
  function TEST_F (line 157) | TEST_F(MidiControllerEventTestFrontend, TestCCDataConnectionDisconnection)
  function TEST_F (line 278) | TEST_F(MidiControllerEventTestFrontend, TestPCDataConnectionDisconnection)
  function TEST_F (line 370) | TEST_F(MidiControllerEventTestFrontend, TestSettingClockOutput)

FILE: test/unittests/engine/controllers/osc_controller_test.cpp
  class OscControllerEventTestFrontend (line 30) | class OscControllerEventTestFrontend : public ::testing::Test
    method OscControllerEventTestFrontend (line 33) | OscControllerEventTestFrontend() = default;
    method SetUp (line 35) | void SetUp() override
  function TEST_F (line 62) | TEST_F(OscControllerEventTestFrontend, TestBasicPolling)
  function TEST_F (line 75) | TEST_F(OscControllerEventTestFrontend, TestEnablingAndDisablingOfOSCOutput)

FILE: test/unittests/engine/controllers/reactive_controller_test.cpp
  type sushi::internal (line 33) | namespace sushi::internal {
    class RtControllerAccessor (line 35) | class RtControllerAccessor
      method RtControllerAccessor (line 38) | explicit RtControllerAccessor(RealTimeController& f) : _friend(f) {}
      method tempo (line 40) | [[nodiscard]] float tempo() const
      method time_signature (line 50) | [[nodiscard]] sushi::TimeSignature time_signature() const
      method playing_mode (line 55) | [[nodiscard]] control::PlayingMode playing_mode() const
  class ReactiveControllerTestFrontend (line 77) | class ReactiveControllerTestFrontend : public ::testing::Test
    method crank_event_loop_once (line 80) | void crank_event_loop_once()
    method ReactiveControllerTestFrontend (line 87) | ReactiveControllerTestFrontend() = default;
    method SetUp (line 89) | void SetUp() override
  function TEST_F (line 127) | TEST_F(ReactiveControllerTestFrontend, TestRtControllerAudioCalls)
  function TEST_F (line 143) | TEST_F(ReactiveControllerTestFrontend, TestRtControllerTransportCalls)
  function TEST_F (line 197) | TEST_F(ReactiveControllerTestFrontend, TestRtControllerMidiCalls)

FILE: test/unittests/engine/controllers/session_controller_test.cpp
  type sushi::internal::engine::controller_impl (line 16) | namespace sushi::internal::engine::controller_impl
    class Accessor (line 19) | class Accessor
      method Accessor (line 22) | explicit Accessor(SessionController& f) : _friend(f) {}
      method save_build_info (line 24) | [[nodiscard]] control::SushiBuildInfo save_build_info() const
      method save_midi_state (line 29) | [[nodiscard]] control::MidiState save_midi_state() const
      method save_engine_state (line 34) | [[nodiscard]] control::EngineState save_engine_state() const
      method save_tracks (line 39) | [[nodiscard]] std::vector<control::TrackState> save_tracks() const
      method clear_all_tracks (line 44) | void clear_all_tracks()
  class SessionControllerTest (line 65) | class SessionControllerTest : public ::testing::Test
    method SessionControllerTest (line 68) | SessionControllerTest() = default;
    method SetUp (line 70) | void SetUp() override
  function TEST_F (line 99) | TEST_F(SessionControllerTest, TestEmptyEngineState)
  function TEST_F (line 106) | TEST_F(SessionControllerTest, TestSaveSushiInfo)
  function TEST_F (line 116) | TEST_F(SessionControllerTest, TestSaveOscState)
  function TEST_F (line 121) | TEST_F(SessionControllerTest, TestSaveMidiState)
  function TEST_F (line 180) | TEST_F(SessionControllerTest, TestSaveEngineState)
  function TEST_F (line 228) | TEST_F(SessionControllerTest, TestSaveTracks)
  function TEST_F (line 268) | TEST_F(SessionControllerTest, TestSaveAndRestore)

FILE: test/unittests/engine/engine_test.cpp
  type sushi::internal::engine (line 18) | namespace sushi::internal::engine
    class AudioEngineAccessor (line 21) | class AudioEngineAccessor
      method AudioEngineAccessor (line 24) | explicit AudioEngineAccessor(AudioEngine& f) : _friend(f) {}
      method AudioGraph (line 26) | [[nodiscard]] AudioGraph& audio_graph()
      method ProcessorContainer (line 31) | [[nodiscard]] ProcessorContainer& processors()
      method remove_connections_from_track (line 41) | void remove_connections_from_track(ObjectId track_id)
  class TestClipDetector (line 61) | class TestClipDetector : public ::testing::Test
    method TestClipDetector (line 64) | TestClipDetector() = default;
    method SetUp (line 66) | void SetUp() override
  function TEST_F (line 74) | TEST_F(TestClipDetector, TestClipping)
  class TestEngine (line 112) | class TestEngine : public ::testing::Test
    method TestEngine (line 115) | TestEngine() = default;
    method SetUp (line 117) | void SetUp() override
  function TEST_F (line 137) | TEST_F(TestEngine, TestProcess)
  function TEST_F (line 185) | TEST_F(TestEngine, TestOutputMixing)
  function TEST_F (line 210) | TEST_F(TestEngine, TestCreateEmptyTrack)
  function TEST_F (line 240) | TEST_F(TestEngine, TestCreatePreAndPostTracks)
  function TEST_F (line 265) | TEST_F(TestEngine, TestCreateTrackOnThread)
  function TEST_F (line 284) | TEST_F(TestEngine, TestAddAndRemovePlugin)
  function TEST_F (line 393) | TEST_F(TestEngine, TestSetSamplerate)
  function TEST_F (line 419) | TEST_F(TestEngine, TestRealtimeConfiguration)
  function TEST_F (line 491) | TEST_F(TestEngine, TestAudioConnections)
  function TEST_F (line 555) | TEST_F(TestEngine, TestSetCvChannels)
  function TEST_F (line 567) | TEST_F(TestEngine, TestCvRouting)
  function TEST_F (line 609) | TEST_F(TestEngine, TestGateRouting)
  function TEST_F (line 658) | TEST_F(TestEngine, TestMasterTrackProcessing)

FILE: test/unittests/engine/event_dispatcher_test.cpp
  function dummy_callback_1 (line 24) | void dummy_callback_1(void* /*arg*/, Event* /*event*/, int status)
  function dummy_callback_2 (line 31) | void dummy_callback_2(void* /*arg*/, Event* /*event*/, int status)
  function dummy_processor_callback (line 38) | int dummy_processor_callback(void* /*arg*/, EventId /*id*/)
  class DummyPoster (line 44) | class DummyPoster : public EventPoster
    method process (line 47) | int process(Event* /*event*/) override
    method event_received (line 53) | bool event_received()
  class TestEventDispatcher (line 67) | class TestEventDispatcher : public ::testing::Test
    method crank_event_loop_once (line 70) | void crank_event_loop_once()
    method TestEventDispatcher (line 77) | TestEventDispatcher() = default;
    method SetUp (line 79) | void SetUp() override
    method TearDown (line 88) | void TearDown() override
  function TEST_F (line 102) | TEST_F(TestEventDispatcher, TestInstantiation)
  function TEST_F (line 110) | TEST_F(TestEventDispatcher, TestRegisteringAndDeregistering)
  function TEST_F (line 143) | TEST_F(TestEventDispatcher, TestFromRtEventNoteOnEvent)
  function TEST_F (line 154) | TEST_F(TestEventDispatcher, TestFromRtEventParameterChangeNotification)
  function TEST_F (line 164) | TEST_F(TestEventDispatcher, TestEngineNotificationForwarding)
  function TEST_F (line 176) | TEST_F(TestEventDispatcher, TestCompletionCallback)
  function TEST_F (line 191) | TEST_F(TestEventDispatcher, TestAsyncCallbackFromProcessor)
  function TEST_F (line 216) | TEST_F(TestEventDispatcher, TestEventProcessingOrder)
  class TestWorker (line 245) | class TestWorker : public ::testing::Test
    method crank_event_loop_once (line 248) | void crank_event_loop_once()
    method TestWorker (line 255) | TestWorker() = default;
    method TearDown (line 257) | void TearDown() override
  function TEST_F (line 268) | TEST_F(TestWorker, TestEventQueueingAndProcessing)

FILE: test/unittests/engine/event_timer_test.cpp
  function TEST (line 14) | TEST(TestEventTimerInternal, TestCalcChunkTime)
  class TestEventTimer (line 22) | class TestEventTimer : public ::testing::Test
    method TestEventTimer (line 25) | TestEventTimer() = default;
  function TEST_F (line 30) | TEST_F(TestEventTimer, TestToOffsetConversion)
  function TEST_F (line 57) | TEST_F(TestEventTimer, TestToRealTimesConversion)

FILE: test/unittests/engine/factories/factories_test.cpp
  type sushi::internal::audio_frontend (line 32) | namespace sushi::internal::audio_frontend {
    function AudioFrontendStatus (line 39) | AudioFrontendStatus PortAudioFrontend::init(BaseAudioFrontendConfigura...
  type sushi::internal (line 74) | namespace sushi::internal
    function TEST (line 77) | TEST (TestTerminalUtils, TestStringTokenizer)
    class ConcreteSushiAccessor (line 98) | class ConcreteSushiAccessor
      method ConcreteSushiAccessor (line 101) | explicit ConcreteSushiAccessor(ConcreteSushi& f) : _friend(f) {}
  class ReactiveFactoryTest (line 158) | class ReactiveFactoryTest : public ::testing::Test
    method ReactiveFactoryTest (line 161) | ReactiveFactoryTest() = default;
    method SetUp (line 163) | void SetUp() override
  function TEST_F (line 178) | TEST_F(ReactiveFactoryTest, TestReactiveFactoryWithDefaultConfig)
  function TEST_F (line 210) | TEST_F(ReactiveFactoryTest, TestPassiveFactoryWithConfigFile)
  class OfflineFactoryTest (line 250) | class OfflineFactoryTest : public ::testing::Test
    method OfflineFactoryTest (line 253) | OfflineFactoryTest() = default;
    method SetUp (line 255) | void SetUp() override
  function TEST_F (line 270) | TEST_F(OfflineFactoryTest, TestOfflineFactoryWithDefaultConfig)
  function TEST_F (line 300) | TEST_F(OfflineFactoryTest, TestOfflineFactoryWithConfigFile)
  class StandaloneFactoryTest (line 337) | class StandaloneFactoryTest : public ::testing::Test
    method StandaloneFactoryTest (line 340) | StandaloneFactoryTest() = default;
    method SetUp (line 342) | void SetUp() override
    method TearDown (line 362) | void TearDown() override
  function TEST_F (line 377) | TEST_F(StandaloneFactoryTest, TestStandaloneFactoryWithDefaultConfig)
  function TEST_F (line 423) | TEST_F(StandaloneFactoryTest, TestStandaloneFactoryWithConfigFile)

FILE: test/unittests/engine/json_configurator_test.cpp
  type sushi::internal::midi_dispatcher (line 20) | namespace sushi::internal::midi_dispatcher
    class Accessor (line 23) | class Accessor
      method Accessor (line 26) | explicit Accessor(MidiDispatcher& f) : _friend(f) {}
  type sushi::internal::jsonconfig (line 54) | namespace sushi::internal::jsonconfig
    class Accessor (line 57) | class Accessor
      method Accessor (line 60) | explicit Accessor(JsonConfigurator& f) : _friend(f) {}
      method JsonConfigReturnStatus (line 62) | [[nodiscard]] JsonConfigReturnStatus make_track(const rapidjson::Val...
      method validate_against_schema (line 67) | static bool validate_against_schema(rapidjson::Value& config, JsonSe...
      method parse_section (line 72) | std::pair<JsonConfigReturnStatus, const rapidjson::Value&> parse_sec...
  class TestJsonConfigurator (line 96) | class TestJsonConfigurator : public ::testing::Test
    method TestJsonConfigurator (line 99) | TestJsonConfigurator() = default;
    method SetUp (line 101) | void SetUp() override
  function JsonConfigReturnStatus (line 134) | JsonConfigReturnStatus TestJsonConfigurator::_make_track(const rapidjson...
  function TEST_F (line 139) | TEST_F(TestJsonConfigurator, TestLoadAudioConfig)
  function TEST_F (line 149) | TEST_F(TestJsonConfigurator, TestLoadHostConfig)
  function TEST_F (line 156) | TEST_F(TestJsonConfigurator, TestLoadTracks)
  function TEST_F (line 178) | TEST_F(TestJsonConfigurator, TestLoadMidi)
  function TEST_F (line 194) | TEST_F(TestJsonConfigurator, TestLoadOsc)
  function TEST_F (line 228) | TEST_F(TestJsonConfigurator, TestLoadCvGateControl)
  function TEST_F (line 237) | TEST_F(TestJsonConfigurator, TestLoadInitialState)
  function TEST_F (line 252) | TEST_F(TestJsonConfigurator, TestMakeChain)
  function TEST_F (line 301) | TEST_F(TestJsonConfigurator, TestValidJsonSchema)
  function TEST_F (line 315) | TEST_F(TestJsonConfigurator, TestHostConfigSchema)
  function TEST_F (line 334) | TEST_F(TestJsonConfigurator, TestPluginChainSchema)
  function TEST_F (line 365) | TEST_F(TestJsonConfigurator, TestPluginSchema)
  function TEST_F (line 426) | TEST_F(TestJsonConfigurator, TestMidiSchema)
  function TEST_F (line 445) | TEST_F(TestJsonConfigurator, TestCvGateSchema)
  function TEST_F (line 473) | TEST_F(TestJsonConfigurator, TestInititalStateSchema)
  function TEST_F (line 501) | TEST_F(TestJsonConfigurator, TestLoadEventList)
  function TEST (line 511) | TEST(TestSchemaValidation, TestSchemaMetaValidation)

FILE: test/unittests/engine/midi_dispatcher_test.cpp
  function TEST (line 30) | TEST(TestMidiDispatcherEventCreation, TestMakeNoteOnEvent)
  function TEST (line 45) | TEST(TestMidiDispatcherEventCreation, TestMakeNoteOnWithZeroVelEvent)
  function TEST (line 60) | TEST(TestMidiDispatcherEventCreation, TestMakeNoteOffEvent)
  function TEST (line 75) | TEST(TestMidiDispatcherEventCreation, TestMakeWrappedMidiEvent)
  function TEST (line 91) | TEST(TestMidiDispatcherEventCreation, TestMakeParameterChangeEvent)
  function TEST (line 103) | TEST(TestMidiDispatcherEventCreation, TestMakeProgramChangeEvent)
  class TestMidiDispatcher (line 114) | class TestMidiDispatcher : public ::testing::Test
    method TestMidiDispatcher (line 117) | TestMidiDispatcher() = default;
    method SetUp (line 119) | void SetUp() override
  function TEST_F (line 130) | TEST_F(TestMidiDispatcher, TestKeyboardDataConnection)
  function TEST_F (line 186) | TEST_F(TestMidiDispatcher, TestKeyboardDataOutConnection)
  function TEST_F (line 246) | TEST_F(TestMidiDispatcher, TestTransportOutputs)
  function TEST_F (line 273) | TEST_F(TestMidiDispatcher, TestRawDataConnection)
  function TEST_F (line 319) | TEST_F(TestMidiDispatcher, TestCCDataConnection)
  function TEST_F (line 414) | TEST_F(TestMidiDispatcher, TestProgramChangeConnection)

FILE: test/unittests/engine/parameter_manager_test.cpp
  type sushi::internal (line 15) | namespace sushi::internal
    class ParameterManagerAccessor (line 18) | class ParameterManagerAccessor
      method ParameterManagerAccessor (line 21) | explicit ParameterManagerAccessor(ParameterManager& plugin) : _plugi...
  class TestParameterManager (line 72) | class TestParameterManager : public ::testing::Test
    method TestParameterManager (line 77) | TestParameterManager() = default;
    method SetUp (line 79) | void SetUp() override
  function TEST_F (line 108) | TEST_F(TestParameterManager, TestEventCreation)
  function TEST_F (line 114) | TEST_F(TestParameterManager, TestParameterUpdates)
  function TEST_F (line 148) | TEST_F(TestParameterManager, TestProcessorUpdates)
  function TEST_F (line 170) | TEST_F(TestParameterManager, TestErrorHandling)

FILE: test/unittests/engine/plugin_library_test.cpp
  class TestPluginLibrary (line 18) | class TestPluginLibrary : public ::testing::Test
    method TestPluginLibrary (line 21) | TestPluginLibrary() = default;
  function TEST_F (line 27) | TEST_F(TestPluginLibrary, TestAbsolutePath)
  function TEST_F (line 36) | TEST_F(TestPluginLibrary, TestEmptyPath)
  function TEST_F (line 43) | TEST_F(TestPluginLibrary, TestPathConcatenation)

FILE: test/unittests/engine/processor_container_test.cpp
  class TestProcessorContainer (line 18) | class TestProcessorContainer : public ::testing::Test
    method TestProcessorContainer (line 21) | TestProcessorContainer() {}
  function TEST_F (line 27) | TEST_F(TestProcessorContainer, TestAddingAndRemoving)
  function TEST_F (line 67) | TEST_F(TestProcessorContainer, TestTrackManagement)

FILE: test/unittests/engine/receiver_test.cpp
  class TestAsyncReceiver (line 13) | class TestAsyncReceiver : public ::testing::Test
    method TestAsyncReceiver (line 16) | TestAsyncReceiver() = default;
  function TEST_F (line 23) | TEST_F(TestAsyncReceiver, TestBasicHandling)
  function TEST_F (line 33) | TEST_F(TestAsyncReceiver, TestMultipleEvents)

FILE: test/unittests/engine/track_test.cpp
  class TrackTest (line 20) | class TrackTest : public ::testing::Test
    method TrackTest (line 23) | TrackTest() = default;
    method SetUp (line 25) | void SetUp() override
  function TEST_F (line 41) | TEST_F(TrackTest, TestMultibusSetup)
  function TEST_F (line 50) | TEST_F(TrackTest, TestAddAndRemove)
  function TEST_F (line 74) | TEST_F(TrackTest, TestNestedBypass)
  function TEST_F (line 82) | TEST_F(TrackTest, TestEmptyChainRendering)
  function TEST_F (line 91) | TEST_F(TrackTest, TestRenderingWithProcessors)
  function TEST_F (line 107) | TEST_F(TrackTest, TestPanAndGain)
  function TEST_F (line 138) | TEST_F(TrackTest, TestPanAndGainPerBus)
  function TEST_F (line 185) | TEST_F(TrackTest, TestGainOnly)
  function TEST_F (line 223) | TEST_F(TrackTest, TestMute)
  function TEST_F (line 252) | TEST_F(TrackTest, TestEventProcessing)
  function TEST_F (line 276) | TEST_F(TrackTest, TestEventForwarding)
  function TEST_F (line 305) | TEST_F(TrackTest, TestSilenceUnusedChannels)
  function TEST (line 328) | TEST(TestStandAloneFunctions, TesPanAndGainCalculation)

FILE: test/unittests/engine/transport_test.cpp
  class TestTransport (line 15) | class TestTransport : public ::testing::Test
    method TestTransport (line 18) | TestTransport() = default;
  function TEST_F (line 25) | TEST_F(TestTransport, TestBasicQuerying)
  function TEST_F (line 66) | TEST_F(TestTransport, TestTimeline44Time)
  function TEST_F (line 103) | TEST_F(TestTransport, TestTimeline44TimeWithExternalPositionSource)
  function TEST_F (line 127) | TEST_F(TestTransport, TestTimeline68Time)
  function TEST_F (line 159) | TEST_F(TestTransport, TestPlayStateChange)
  function TEST_F (line 185) | TEST_F(TestTransport, TestNotifications)

FILE: test/unittests/library/event_test.cpp
  function dummy_processor_callback (line 15) | static int dummy_processor_callback(void* /*arg*/, EventId /*id*/)
  function TEST (line 20) | TEST(EventTest, TestToRtEvent)
  function TEST (line 109) | TEST(EventTest, TestFromRtEvent)

FILE: test/unittests/library/fixed_stack_test.cpp
  type sushi (line 7) | namespace sushi
    class FixedStackAccessor (line 11) | class FixedStackAccessor
      method FixedStackAccessor (line 14) | explicit FixedStackAccessor(FixedStack<T, storage_capacity>& f) : _f...
  class TestFixedStack (line 31) | class TestFixedStack : public ::testing::Test
    method TestFixedStack (line 34) | TestFixedStack() = default;
  function TEST_F (line 41) | TEST_F(TestFixedStack, TestPush)
  function TEST_F (line 55) | TEST_F(TestFixedStack, TestPop)

FILE: test/unittests/library/id_generator_test.cpp
  function TEST (line 7) | TEST(BaseIdGeneratorTest, GenerateNewUid)

FILE: test/unittests/library/internal_plugin_test.cpp
  type sushi::internal (line 14) | namespace sushi::internal
    class InternalPluginAccessor (line 17) | class InternalPluginAccessor
      method InternalPluginAccessor (line 20) | explicit InternalPluginAccessor(InternalPlugin& plugin) : _plugin(pl...
      method send_property_to_realtime (line 27) | void send_property_to_realtime(ObjectId property_id, const std::stri...
      method send_data_to_realtime (line 32) | void send_data_to_realtime(BlobData data, int id)
  class TestPlugin (line 46) | class TestPlugin : public InternalPlugin
    method TestPlugin (line 49) | explicit TestPlugin(HostControl host_control) : InternalPlugin(host_co...
    method process_audio (line 54) | void process_audio(const ChunkSampleBuffer &in_buffer, ChunkSampleBuff...
  class InternalPluginTest (line 61) | class InternalPluginTest : public ::testing::Test
    method InternalPluginTest (line 64) | InternalPluginTest() = default;
    method SetUp (line 66) | void SetUp() override
  function TEST_F (line 82) | TEST_F(InternalPluginTest, TestInstanciation)
  function TEST_F (line 87) | TEST_F(InternalPluginTest, TestParameterRegistration)
  function TEST_F (line 111) | TEST_F(InternalPluginTest, TestDuplicateParameterNames)
  function TEST_F (line 123) | TEST_F(InternalPluginTest, TestBoolParameterHandling)
  function TEST_F (line 148) | TEST_F(InternalPluginTest, TestIntParameterHandling)
  function TEST_F (line 186) | TEST_F(InternalPluginTest, TestFloatParameterHandling)
  function TEST_F (line 220) | TEST_F(InternalPluginTest, TestPropertyHandling)
  function TEST_F (line 240) | TEST_F(InternalPluginTest, TestSendingPropertyToRealtime)
  function TEST_F (line 262) | TEST_F(InternalPluginTest, TestSendingDataToRealtime)
  function TEST_F (line 278) | TEST_F(InternalPluginTest, TestStateHandling)
  function TEST_F (line 303) | TEST_F(InternalPluginTest, TestRtStateHandling)
  function TEST_F (line 355) | TEST_F(InternalPluginTest, TestStateSaving)
  function TEST_F (line 387) | TEST_F(InternalPluginTest, TestKeyboardEventPassthrough)

FILE: test/unittests/library/lv2_wrapper_test.cpp
  class TestLv2Wrapper (line 83) | class TestLv2Wrapper : public ::testing::Test
    method TestLv2Wrapper (line 87) | TestLv2Wrapper()
    method ProcessorReturnCode (line 90) | ProcessorReturnCode SetUp(const std::string& plugin_URI)
    method TearDown (line 116) | void TearDown()
  function TEST_F (line 130) | TEST_F(TestLv2Wrapper, TestLV2PluginInvalidURI)
  function TEST_F (line 149) | TEST_F(TestLv2Wrapper, TestLV2PluginInteraction)
  function TEST_F (line 184) | TEST_F(TestLv2Wrapper, TestProcessingWithParameterChanges)
  function TEST_F (line 211) | TEST_F(TestLv2Wrapper, TestBypassProcessing)
  function TEST_F (line 242) | TEST_F(TestLv2Wrapper, TestMidiEventInputAndOutput)
  function TEST_F (line 292) | TEST_F(TestLv2Wrapper, TestTimeInfo)
  function TEST_F (line 320) | TEST_F(TestLv2Wrapper, TestSynchronousStateAndWorkerThreads)
  function TEST_F (line 479) | TEST_F(TestLv2Wrapper, TestSynth)
  function TEST_F (line 549) | TEST_F(TestLv2Wrapper, TestStateHandling)
  function TEST_F (line 587) | TEST_F(TestLv2Wrapper, TestBinaryStateSaving)
  function TEST_F (line 618) | TEST_F(TestLv2Wrapper, TestLv2Logging)

FILE: test/unittests/library/midi_decoder_test.cpp
  function TEST (line 29) | TEST (MidiDecoderTest, TestDecodeMessageType) {
  function TEST (line 53) | TEST (MidiDecoderTest, TestDecodeChannel)
  function TEST (line 58) | TEST (MidiDecoderTest, TestDecodeNoteOff)
  function TEST (line 66) | TEST (MidiDecoderTest, TestDecodeNoteOn)
  function TEST (line 74) | TEST (MidiDecoderTest, TestDecodePolyKeyPressure)
  function TEST (line 82) | TEST (ControlChangeMessage, TestDecodeControlChange)
  function TEST (line 90) | TEST (ProgramChangeMessage, TestDecodeProgramChange)
  function TEST (line 97) | TEST (MidiDecoderTest, TestDecodeChannelPressure)
  function TEST (line 104) | TEST (MidiDecoderTest, TestDecodePitchBend)
  function TEST (line 111) | TEST (MidiDecoderTest, TestDecodeTimeCode)
  function TEST (line 118) | TEST (MidiDecoderTest, TestDecodeSongPosition)
  function TEST (line 124) | TEST (MidiDecoderTest, TestDecodeSongSelect)

FILE: test/unittests/library/midi_encoder_test.cpp
  function TEST (line 9) | TEST(TestMidiEncoder, EncodeNoteOn)
  function TEST (line 18) | TEST(TestMidiEncoder, EncodeNoteOff)
  function TEST (line 27) | TEST(TestMidiEncoder, EncodePolyKeyPressure)
  function TEST (line 36) | TEST(TestMidiEncoder, EncodeControlChange)
  function TEST (line 45) | TEST(TestMidiEncoder, EncodeChannelPressure)
  function TEST (line 54) | TEST(TestMidiEncoder, EncodePitchBend)
  function TEST (line 67) | TEST(TestMidiEncoder, EncodeProgramChange)
  function TEST (line 76) | TEST(TestMidiEncoder, EncodeStartMessage)
  function TEST (line 85) | TEST(TestMidiEncoder, EncodeStopMessage)
  function TEST (line 94) | TEST(TestMidiEncoder, EncodeContinueMessage)
  function TEST (line 103) | TEST(TestMidiEncoder, EncodeTimingClock)
  function TEST (line 112) | TEST(TestMidiEncoder, EncodeActiveSensing)
  function TEST (line 121) | TEST(TestMidiEncoder, EncodeResetMessage)

FILE: test/unittests/library/parameter_dump_test.cpp
  function ELK_PUSH_WARNING (line 9) | ELK_PUSH_WARNING

FILE: test/unittests/library/performance_timer_test.cpp
  type sushi::internal::performance (line 7) | namespace sushi::internal::performance
    class Accessor (line 10) | class Accessor
      method Accessor (line 13) | explicit Accessor(PerformanceTimer& f) : _friend(f) {}
      method update_timings (line 21) | void update_timings()
  function virtual_wait (line 38) | performance::TimePoint virtual_wait(const performance::TimePoint& tp, in...
  function run_test_scenario (line 45) | void run_test_scenario(PerformanceTimer& timer)
  class TestPerformanceTimer (line 64) | class TestPerformanceTimer : public ::testing::Test
    method TestPerformanceTimer (line 67) | TestPerformanceTimer() = default;
    method SetUp (line 69) | void SetUp() override
  function TEST_F (line 82) | TEST_F(TestPerformanceTimer, TestOperation)
  function TEST_F (line 108) | TEST_F(TestPerformanceTimer, TestClearRecords)

FILE: test/unittests/library/plugin_parameters_test.cpp
  class TestdBToLinPreProcessor (line 9) | class TestdBToLinPreProcessor : public ::testing::Test
    method TestdBToLinPreProcessor (line 12) | TestdBToLinPreProcessor() {}
  function TEST_F (line 17) | TEST_F(TestdBToLinPreProcessor, TestProcessing)
  class TestLinTodBPreProcessor (line 24) | class TestLinTodBPreProcessor : public ::testing::Test
    method TestLinTodBPreProcessor (line 27) | TestLinTodBPreProcessor() {}
  function TEST_F (line 32) | TEST_F(TestLinTodBPreProcessor, TestProcessing)
  class TestCubicWarpPreProcessor (line 39) | class TestCubicWarpPreProcessor : public ::testing::Test
    method TestCubicWarpPreProcessor (line 42) | TestCubicWarpPreProcessor() {}
  function TEST_F (line 47) | TEST_F(TestCubicWarpPreProcessor, TestProcessing)
  function TEST_F (line 54) | TEST_F(TestCubicWarpPreProcessor, TestIdentity)
  class TestParameter (line 65) | class TestParameter : public ::testing::Test
    method TestParameter (line 68) | TestParameter() {}
  function TEST_F (line 101) | TEST_F(TestParameter, TestTypeNameAndLabel)
  function TEST (line 134) | TEST(TestParameterValue, TestSet)

FILE: test/unittests/library/processor_test.cpp
  type sushi::internal (line 16) | namespace sushi::internal
    class ProcessorAccessor (line 19) | class ProcessorAccessor
      method ProcessorAccessor (line 22) | explicit ProcessorAccessor(Processor& plugin) : _friend(plugin) {}
      method register_parameter (line 24) | [[nodiscard]] bool register_parameter(ParameterDescriptor* parameter)
      method make_unique_parameter_name (line 29) | [[nodiscard]] std::string make_unique_parameter_name(const std::stri...
      method bypass_process (line 34) | void bypass_process(const ChunkSampleBuffer& in_buffer, ChunkSampleB...
      method maybe_output_cv_value (line 39) | [[nodiscard]] bool maybe_output_cv_value(ObjectId parameter_id, floa...
      method maybe_output_gate_event (line 44) | [[nodiscard]] bool maybe_output_gate_event(int channel, int note, bo...
  class ProcessorTest (line 60) | class ProcessorTest : public Processor
    method ProcessorTest (line 63) | explicit ProcessorTest(HostControl host_control) : Processor(host_cont...
    method process_audio (line 71) | void process_audio(const ChunkSampleBuffer& /*in_buffer*/,
    method process_event (line 74) | void process_event(const RtEvent& /*event*/) override {}
  class TestProcessor (line 78) | class TestProcessor : public ::testing::Test
    method TestProcessor (line 81) | TestProcessor() = default;
    method SetUp (line 83) | void SetUp() override
    method TearDown (line 90) | void TearDown() override
  function TEST_F (line 102) | TEST_F(TestProcessor, TestBasicProperties)
  function TEST_F (line 115) | TEST_F(TestProcessor, TestParameterHandling)
  function TEST_F (line 137) | TEST_F(TestProcessor, TestDuplicateParameterNames)
  function TEST_F (line 148) | TEST_F(TestProcessor, TestBypassProcessing)
  function TEST_F (line 172) | TEST_F(TestProcessor, TestCvOutput)
  function TEST_F (line 199) | TEST_F(TestProcessor, TestGateOutput)
  class TestBypassManager (line 223) | class TestBypassManager : public ::testing::Test
    method TestBypassManager (line 226) | TestBypassManager() = default;
  function TEST_F (line 231) | TEST_F(TestBypassManager, TestOperation)
  function TEST_F (line 250) | TEST_F(TestBypassManager, TestSetBypassRampTime)
  function TEST_F (line 267) | TEST_F(TestBypassManager, TestRamping)
  function TEST_F (line 315) | TEST_F(TestBypassManager, TestCrossfade)

FILE: test/unittests/library/rt_event_test.cpp
  function TEST (line 10) | TEST (TestRealtimeEvents, TestFactoryFunction)
  function TEST (line 246) | TEST (TestRealtimeEvents, TestMidiFactoryFunction)
  function TEST (line 312) | TEST(TestRealtimeEvents, TestReturnableEvents)
  function TEST (line 327) | TEST(TestRealtimeEvents, TestIsKeyboardEvent)

FILE: test/unittests/library/sample_buffer_test.cpp
  function TEST (line 10) | TEST(TestSampleBuffer, TestCopying)
  function TEST (line 27) | TEST(TestSampleBuffer, TestAssignement)
  function TEST (line 70) | TEST(TestSampleBuffer, TestNonOwningBuffer)
  function TEST (line 93) | TEST(TestSampleBuffer, TestCreateFromRawPointer)
  function TEST (line 110) | TEST(TestSampleBuffer, TestAssigningNonOwningBuffer)
  function TEST (line 143) | TEST(TestSampleBuffer, TestSwap)
  function TEST (line 157) | TEST(TestSampleBuffer, TestInitialization)
  function TEST (line 166) | TEST(TestSampleBuffer, TestDeinterleaving)
  function TEST (line 188) | TEST(TestSampleBuffer, TestInterleaving)
  function TEST (line 222) | TEST (TestSampleBuffer, TestGain)
  function TEST (line 248) | TEST(TestSampleBuffer,TestReplace)
  function TEST (line 267) | TEST (TestSampleBuffer, TestAdd)
  function TEST (line 301) | TEST (TestSampleBuffer, TestAddWithGain)
  function TEST (line 343) | TEST (TestSampleBuffer, TestRamping)
  function TEST (line 368) | TEST (TestSampleBuffer, TestAddWithRamp)
  function TEST (line 416) | TEST (TestSampleBuffer, TestCountClippedSamples)
  function TEST (line 428) | TEST (TestSampleBuffer, TestPeakCalculation)
  function TEST (line 440) | TEST (TestSampleBuffer, TestRMSCalculation)

FILE: test/unittests/library/simple_fifo_test.cpp
  class TestSimpleFifo (line 10) | class TestSimpleFifo : public ::testing::Test
    method TestSimpleFifo (line 13) | TestSimpleFifo() {}
  function TEST_F (line 18) | TEST_F(TestSimpleFifo, TestOperation)
  function TEST_F (line 45) | TEST_F(TestSimpleFifo, TestClear)
  function TEST_F (line 56) | TEST_F(TestSimpleFifo, TestPopAndPush)

FILE: test/unittests/library/vst2x_midi_event_fifo_test.cpp
  class TestVst2xMidiEventFIFO (line 13) | class TestVst2xMidiEventFIFO : public ::testing::Test
    method TestVst2xMidiEventFIFO (line 16) | TestVst2xMidiEventFIFO() = default;
    method SetUp (line 18) | void SetUp() override
  function TEST_F (line 31) | TEST_F(TestVst2xMidiEventFIFO, TestNonOverflowingBehaviour)
  function TEST_F (line 43) | TEST_F(TestVst2xMidiEventFIFO, TestFlush)
  function TEST_F (line 50) | TEST_F(TestVst2xMidiEventFIFO, TestOverflow)
  function TEST_F (line 73) | TEST_F(TestVst2xMidiEventFIFO, TestFlushAfterOverflow)
  function TEST_F (line 98) | TEST_F(TestVst2xMidiEventFIFO, TestNoteOnCreation)
  function TEST_F (line 111) | TEST_F(TestVst2xMidiEventFIFO, TestNoteOffCreation)
  function TEST_F (line 124) | TEST_F(TestVst2xMidiEventFIFO, TestNoteAftertouchCreation)
  function TEST_F (line 137) | TEST_F(TestVst2xMidiEventFIFO, TestWrappedMidiCreation)

FILE: test/unittests/library/vst2x_plugin_loading_test.cpp
  class TestVst2xPluginLoading (line 16) | class TestVst2xPluginLoading : public ::testing::Test
    method TestVst2xPluginLoading (line 19) | TestVst2xPluginLoading():
  function TEST_F (line 28) | TEST_F(TestVst2xPluginLoading, TestPluginRegistryVst2xLoading)
  function TEST_F (line 46) | TEST_F(TestVst2xPluginLoading, TestLoadPlugin)

FILE: test/unittests/library/vst2x_wrapper_test.cpp
  type sushi::internal::vst2 (line 12) | namespace sushi::internal::vst2
    class Vst2xWrapperAccessor (line 15) | class Vst2xWrapperAccessor
      method Vst2xWrapperAccessor (line 18) | explicit Vst2xWrapperAccessor(Vst2xWrapper& f) : _friend(f) {}
      method can_do_soft_bypass (line 20) | [[nodiscard]] bool can_do_soft_bypass() const
      method AEffect (line 25) | AEffect* plugin_handle()
      method sample_rate (line 30) | [[nodiscard]] float sample_rate() const
      method notify_parameter_change (line 35) | void notify_parameter_change(VstInt32 parameter_index, float value)
      method notify_parameter_change_rt (line 40) | void notify_parameter_change_rt(VstInt32 parameter_index, float value)
  class TestVst2xWrapper (line 87) | class TestVst2xWrapper : public ::testing::Test
    method TestVst2xWrapper (line 91) | TestVst2xWrapper() = default;
    method SetUp (line 93) | void SetUp(const std::string& plugin_path)
  function TEST_F (line 116) | TEST_F(TestVst2xWrapper, TestSetName)
  function TEST_F (line 123) | TEST_F(TestVst2xWrapper, TestSetChannels)
  function TEST_F (line 133) | TEST_F(TestVst2xWrapper, TestParameterInitialization)
  function TEST_F (line 144) | TEST_F(TestVst2xWrapper, TestPluginCanDos)
  function TEST_F (line 150) | TEST_F(TestVst2xWrapper, TestParameterSetViaEvent)
  function TEST_F (line 159) | TEST_F(TestVst2xWrapper, TestProcess)
  function TEST_F (line 170) | TEST_F(TestVst2xWrapper, TestMonoProcess)
  function TEST_F (line 191) | TEST_F(TestVst2xWrapper, TestProcessingWithParameterChanges)
  function TEST_F (line 213) | TEST_F(TestVst2xWrapper, TestBypassProcessing)
  function TEST_F (line 242) | TEST_F(TestVst2xWrapper, TestTimeInfo)
  function TEST_F (line 263) | TEST_F(TestVst2xWrapper, TestMidiEvents)
  function TEST_F (line 285) | TEST_F(TestVst2xWrapper, TestConfigurationChange)
  function TEST_F (line 292) | TEST_F(TestVst2xWrapper, TestParameterChangeNotifications)
  function TEST_F (line 302) | TEST_F(TestVst2xWrapper, TestRTParameterChangeNotifications)
  function TEST_F (line 315) | TEST_F(TestVst2xWrapper, TestProgramManagement)
  function TEST_F (line 337) | TEST_F(TestVst2xWrapper, TestStateHandling)
  function TEST_F (line 381) | TEST_F(TestVst2xWrapper, TestStateSaving)

FILE: test/unittests/library/vst3x_wrapper_test.cpp
  type sushi::internal::vst3 (line 18) | namespace sushi::internal::vst3
    class Vst3xWrapperAccessor (line 21) | class Vst3xWrapperAccessor
      method Vst3xWrapperAccessor (line 24) | explicit Vst3xWrapperAccessor(Vst3xWrapper& f) : _friend(f) {}
      method inject_plugin (line 26) | bool inject_plugin(Steinberg::Vst::IComponent* component, const std:...
      method SushiProcessData (line 53) | SushiProcessData& process_data()
      method PluginInstance (line 58) | PluginInstance& instance()
      method forward_events (line 63) | void forward_events(Steinberg::Vst::ProcessData& data)
      method sample_rate (line 68) | float sample_rate()
      method fill_processing_context (line 73) | void fill_processing_context()
      method forward_params (line 78) | void forward_params(Steinberg::Vst::ProcessData& data)
  function TEST (line 111) | TEST(TestVst3xPluginInstance, TestLoadPlugin)
  function TEST (line 126) | TEST(TestVst3xPluginInstance, TestLoadPluginFromErroneousFilename)
  function TEST (line 142) | TEST(TestVst3xRtState, TestOperation)
  class TestVst3xWrapper (line 173) | class TestVst3xWrapper : public ::testing::Test
    method TestVst3xWrapper (line 177) | TestVst3xWrapper() = default;
    method SetUp (line 180) | void SetUp(const char* plugin_file, const char* plugin_name)
    method SetUp (line 199) | void SetUp(test_utils::Vst3TestPlugin* plugin)
  function TEST_F (line 224) | TEST_F(TestVst3xWrapper, TestLoadAndInitPlugin)
  function TEST_F (line 249) | TEST_F(TestVst3xWrapper, TestProcessing)
  function TEST_F (line 269) | TEST_F(TestVst3xWrapper, TestBypassProcessing)
  function TEST_F (line 296) | TEST_F(TestVst3xWrapper, TestEventForwarding)
  function TEST_F (line 335) | TEST_F(TestVst3xWrapper, TestConfigurationChange)
  function TEST_F (line 342) | TEST_F(TestVst3xWrapper, TestTimeInfo)
  function TEST_F (line 367) | TEST_F(TestVst3xWrapper, TestParameterHandling)
  function TEST_F (line 393) | TEST_F(TestVst3xWrapper, TestOutputParameterHandling)
  function TEST_F (line 418) | TEST_F(TestVst3xWrapper, TestGateOutput)
  function TEST_F (line 445) | TEST_F(TestVst3xWrapper, TestCVOutput)
  function TEST_F (line 470) | TEST_F(TestVst3xWrapper, TestStateHandling)
  function TEST_F (line 531) | TEST_F(TestVst3xWrapper, TestMultipleStates)
  function TEST_F (line 592) | TEST_F(TestVst3xWrapper, TestBinaryStateSaving)
  function TEST_F (line 619) | TEST_F(TestVst3xWrapper, TestExtensionInterfaceEnumeration)
  function TEST_F (line 639) | TEST_F(TestVst3xWrapper, TestStringProperties)
  function TEST_F (line 713) | TEST_F(TestVst3xWrapper, TestAsyncWork)
  class TestVst3xUtils (line 737) | class TestVst3xUtils : public ::testing::Test
    method TestVst3xUtils (line 740) | TestVst3xUtils() {}
  function TEST_F (line 743) | TEST_F(TestVst3xUtils, TestNoteOnConversion)
  function TEST_F (line 760) | TEST_F(TestVst3xUtils, TestNoteOffConversion)
  function TEST_F (line 776) | TEST_F(TestVst3xUtils, TestAftertouchConversion)
  function TEST (line 791) | TEST(TestVst3xUtilFunctions, TestMakeSafeFolderName)
  function TEST (line 796) | TEST(TestVst3xUtilFunctions, TestIsHidden)
  function TEST (line 808) | TEST(TestVst3xUtilFunctions, TestScanForPresets)
  function TEST (line 816) | TEST(TestVst3xUtilFunctions, TestGetExecutablePath)
  function TEST (line 825) | TEST(TestVst3xUtilFunctions, TestGetPlatformLocations)
  function TEST (line 835) | TEST(TestVst3xUtilFunctions, TestExtractPresetName)

FILE: test/unittests/plugins/arpeggiator_plugin_test.cpp
  class TestArpeggiator (line 16) | class TestArpeggiator : public ::testing::Test
    method TestArpeggiator (line 19) | TestArpeggiator() = default;
  function TEST_F (line 25) | TEST_F(TestArpeggiator, TestOperation)
  function TEST_F (line 49) | TEST_F(TestArpeggiator, TestHold)
  class TestArpeggiatorPlugin (line 75) | class TestArpeggiatorPlugin : public ::testing::Test
    method TestArpeggiatorPlugin (line 78) | TestArpeggiatorPlugin() = default;
    method SetUp (line 80) | void SetUp() override
    method TearDown (line 88) | void TearDown() override
  function TEST_F (line 99) | TEST_F(TestArpeggiatorPlugin, TestOutput)

FILE: test/unittests/plugins/brickworks_simple_synth_test.cpp
  type sushi::internal::simple_synth_plugin (line 14) | namespace sushi::internal::simple_synth_plugin
    class Accessor (line 17) | class Accessor
      method Accessor (line 20) | explicit Accessor(SimpleSynthPlugin& plugin) : _plugin(plugin) {}
      method FloatParameterValue (line 22) | [[nodiscard]] FloatParameterValue* decay()
      method FloatParameterValue (line 27) | [[nodiscard]] FloatParameterValue* release()
  class TestSimpleSynthPlugin (line 45) | class TestSimpleSynthPlugin : public ::testing::Test
    method SetUp (line 49) | void SetUp() override
  function TEST_F (line 67) | TEST_F(TestSimpleSynthPlugin, TestInstantiation)
  function TEST_F (line 75) | TEST_F(TestSimpleSynthPlugin, TestProcessing)
  function TEST_F (line 97) | TEST_F(TestSimpleSynthPlugin, TestNoteOnandOffSameCallback)
  function TEST_F (line 114) | TEST_F(TestSimpleSynthPlugin, TestNoNaNsUnderStress)

FILE: test/unittests/plugins/control_to_cv_plugin_test.cpp
  function TEST (line 15) | TEST(ControlToCvPluginTestExternalFunctions, TestPitchToCv)
  class ControlToCvPluginTest (line 21) | class ControlToCvPluginTest : public ::testing::Test
    method ControlToCvPluginTest (line 24) | ControlToCvPluginTest() = default;
    method SetUp (line 26) | void SetUp() override
  function TEST_F (line 38) | TEST_F(ControlToCvPluginTest, TestMonophonicMode)
  function TEST_F (line 111) | TEST_F(ControlToCvPluginTest, TestPolyphonicMode)
  function TEST_F (line 229) | TEST_F(ControlToCvPluginTest, TestPitchBend)
  function TEST_F (line 266) | TEST_F(ControlToCvPluginTest, TestModulation)

FILE: test/unittests/plugins/cv_to_control_plugin_test.cpp
  function TEST (line 13) | TEST(CvToControlPluginTestExternalFunctions, TestCvToPitch)
  class CvToControlPluginTest (line 20) | class CvToControlPluginTest : public ::testing::Test
    method CvToControlPluginTest (line 23) | CvToControlPluginTest() = default;
    method SetUp (line 25) | void SetUp() override
  function TEST_F (line 37) | TEST_F(CvToControlPluginTest, TestMonophonicMode)
  function TEST_F (line 84) | TEST_F(CvToControlPluginTest, TestPitchBendMode)
  function TEST_F (line 121) | TEST_F(CvToControlPluginTest, TestVelocity)
  function TEST_F (line 141) | TEST_F(CvToControlPluginTest, TestPolyphony)

FILE: test/unittests/plugins/external_plugins_test.cpp
  type sushi::internal::bitcrusher_plugin (line 39) | namespace sushi::internal::bitcrusher_plugin
    class Accessor (line 42) | class Accessor
      method Accessor (line 45) | explicit Accessor(BitcrusherPlugin& plugin) : _plugin(plugin) {}
      method FloatParameterValue (line 47) | [[nodiscard]] FloatParameterValue* samplerate_ratio()
      method IntParameterValue (line 52) | [[nodiscard]] IntParameterValue* bit_depth()
  function instantiate_plugin (line 77) | std::tuple<ProcessorReturnCode, ProcessorReturnCode, std::shared_ptr<Pro...
  function set_plugin_random_parameters (line 102) | void set_plugin_random_parameters(Processor* plugin,
  function test_fx_plugin_silencein_silenceout (line 115) | void test_fx_plugin_silencein_silenceout(const std::string& uid, float e...
  function test_fx_plugin_noisein_notnan (line 139) | void test_fx_plugin_noisein_notnan(const std::string& uid)
  function test_fx_plugin_buffers_not_overflow (line 164) | void test_fx_plugin_buffers_not_overflow(const std::string& uid)
  function test_fx_plugin_instantiation (line 191) | void test_fx_plugin_instantiation(const std::string& uid,
  function TEST (line 251) | TEST(TestExternalPlugins, TestNoiseGateInstantiation)
  function TEST (line 256) | TEST(TestExternalPlugins, TestNoiseGateNoiseInNotNaN)
  function TEST (line 261) | TEST(TestExternalPlugins, TestNoiseGateBuffersDontOverflow)
  class TestBitcrusherPlugin (line 270) | class TestBitcrusherPlugin : public ::testing::Test
    method TestBitcrusherPlugin (line 273) | TestBitcrusherPlugin()
    method SetUp (line 278) | void SetUp() override
    method SetRandomParameters (line 290) | void SetRandomParameters()
  function TEST_F (line 306) | TEST_F(TestBitcrusherPlugin, TestInstantiation)
  function TEST_F (line 314) | TEST_F(TestBitcrusherPlugin, TestSilenceInSilenceOut)
  function TEST_F (line 328) | TEST_F(TestBitcrusherPlugin, TestNoiseInputNotNan)

FILE: test/unittests/plugins/plugins_test.cpp
  class TestPassthroughPlugin (line 28) | class TestPassthroughPlugin : public ::testing::Test
    method TestPassthroughPlugin (line 31) | TestPassthroughPlugin() = default;
    method SetUp (line 33) | void SetUp() override
  function TEST_F (line 44) | TEST_F(TestPassthroughPlugin, TestInstantiation)
  function TEST_F (line 49) | TEST_F(TestPassthroughPlugin, TestInitialization)
  function TEST_F (line 58) | TEST_F(TestPassthroughPlugin, TestProcess)
  class TestGainPlugin (line 74) | class TestGainPlugin : public ::testing::Test
    method TestGainPlugin (line 77) | TestGainPlugin() = default;
    method SetUp (line 79) | void SetUp() override
  function TEST_F (line 97) | TEST_F(TestGainPlugin, TestInstantiation)
  function TEST_F (line 105) | TEST_F(TestGainPlugin, TestChannelSetup)
  function TEST_F (line 116) | TEST_F(TestGainPlugin, TestProcess)
  class TestEqualizerPlugin (line 127) | class TestEqualizerPlugin : public ::testing::Test
    method TestEqualizerPlugin (line 130) | TestEqualizerPlugin() = default;
    method SetUp (line 132) | void SetUp() override
  function TEST_F (line 150) | TEST_F(TestEqualizerPlugin, TestInstantiation)
  function TEST_F (line 157) | TEST_F(TestEqualizerPlugin, TestChannelSetup)
  function TEST_F (line 168) | TEST_F(TestEqualizerPlugin, TestProcess)
  class TestPeakMeterPlugin (line 192) | class TestPeakMeterPlugin : public ::testing::Test
    method TestPeakMeterPlugin (line 195) | TestPeakMeterPlugin() = default;
    method SetUp (line 197) | void SetUp() override
  function TEST_F (line 212) | TEST_F(TestPeakMeterPlugin, TestInstantiation)
  function TEST_F (line 219) | TEST_F(TestPeakMeterPlugin, TestProcess)
  function TEST_F (line 256) | TEST_F(TestPeakMeterPlugin, TestClipDetection)
  function TEST (line 301) | TEST(TestPeakMeterPluginInternal, TestTodBConversion)
  class TestLfoPlugin (line 310) | class TestLfoPlugin : public ::testing::Test
    method TestLfoPlugin (line 313) | TestLfoPlugin() = default;
    method SetUp (line 315) | void SetUp() override
  function TEST_F (line 329) | TEST_F(TestLfoPlugin, TestInstantiation)
  function TEST_F (line 336) | TEST_F(TestLfoPlugin, TestProcess)
  class TestWavWriterPlugin (line 358) | class TestWavWriterPlugin : public ::testing::Test
    method TestWavWriterPlugin (line 361) | TestWavWriterPlugin() = default;
    method SetUp (line 363) | void SetUp() override
  function TEST_F (line 384) | TEST_F(TestWavWriterPlugin, TestInitialization)
  function TEST_F (line 392) | TEST_F(TestWavWriterPlugin, TestProcess)
  class TestMonoSummingPlugin (line 451) | class TestMonoSummingPlugin : public ::testing::Test
    method TestMonoSummingPlugin (line 454) | TestMonoSummingPlugin() = default;
    method SetUp (line 456) | void SetUp() override
  function TEST_F (line 471) | TEST_F(TestMonoSummingPlugin, TestInitialization)
  function TEST_F (line 479) | TEST_F(TestMonoSummingPlugin, TestProcess)
  class TestSampleDelayPlugin (line 498) | class TestSampleDelayPlugin : public ::testing::Test
    method TestSampleDelayPlugin (line 501) | TestSampleDelayPlugin() = default;
    method SetUp (line 503) | void SetUp() override
  function TEST_F (line 517) | TEST_F(TestSampleDelayPlugin, TestInitialization)
  function TEST_F (line 525) | TEST_F(TestSampleDelayPlugin, TestProcess)
  class TestStereoMixerPlugin (line 569) | class TestStereoMixerPlugin : public ::testing::Test
    method TestStereoMixerPlugin (line 572) | TestStereoMixerPlugin() = default;
    method SetUp (line 574) | void SetUp() override
    method WaitForStableParameters (line 586) | void WaitForStableParameters()
  function TEST_F (line 616) | TEST_F(TestStereoMixerPlugin, TestInitialization)
  function TEST_F (line 623) | TEST_F(TestStereoMixerPlugin, TestProcess)

FILE: test/unittests/plugins/sample_player_plugin_test.cpp
  type sushi::internal::sample_player_plugin (line 12) | namespace sushi::internal::sample_player_plugin
    class Accessor (line 15) | class Accessor
      method Accessor (line 18) | explicit Accessor(SamplePlayerPlugin& plugin) : _plugin(plugin) {}
  class TestSamplerVoice (line 50) | class TestSamplerVoice : public ::testing::Test
    method SetUp (line 53) | void SetUp() override
  function TEST_F (line 64) | TEST_F(TestSamplerVoice, TestInitialConditions)
  function TEST_F (line 73) | TEST_F(TestSamplerVoice, TestNoteOn)
  function TEST_F (line 90) | TEST_F(TestSamplerVoice, TestNoteOff)
  class TestSamplePlayerPlugin (line 110) | class TestSamplePlayerPlugin : public ::testing::Test
    method TestSamplePlayerPlugin (line 113) | TestSamplePlayerPlugin() = default;
    method SetUp (line 115) | void SetUp() override
    method TearDown (line 124) | void TearDown() override
  function TEST_F (line 134) | TEST_F(TestSamplePlayerPlugin, TestSampleLoading)
  function TEST_F (line 161) | TEST_F(TestSamplePlayerPlugin, TestProcessing)
  function TEST_F (line 171) | TEST_F(TestSamplePlayerPlugin, TestEventProcessing)

FILE: test/unittests/plugins/send_return_test.cpp
  type sushi::internal::send_plugin (line 12) | namespace sushi::internal::send_plugin
    class Accessor (line 15) | class Accessor
      method Accessor (line 18) | explicit Accessor(SendPlugin& plugin) : _plugin(plugin) {}
      method set_destination (line 25) | void set_destination(return_plugin::ReturnPlugin* destination)
  type sushi::internal::return_plugin (line 36) | namespace sushi::internal::return_plugin
    class Accessor (line 39) | class Accessor
      method Accessor (line 42) | explicit Accessor(ReturnPlugin& plugin) : _plugin(plugin) {}
      method swap_buffers (line 44) | void swap_buffers()
  function TEST (line 62) | TEST(TestSendReturnFactory, TestFactoryCreation)
  class TestSendReturnPlugins (line 90) | class TestSendReturnPlugins : public ::testing::Test
    method TestSendReturnPlugins (line 93) | TestSendReturnPlugins() = default;
    method SetUp (line 95) | void SetUp() override
  function TEST_F (line 117) | TEST_F(TestSendReturnPlugins, TestDestinationSetting)
  function TEST_F (line 139) | TEST_F(TestSendReturnPlugins, TestProcessing)
  function TEST_F (line 159) | TEST_F(TestSendReturnPlugins, TestZeroDelayProcessing)
  function TEST_F (line 181) | TEST_F(TestSendReturnPlugins, TestMultipleSends)
  function TEST_F (line 210) | TEST_F(TestSendReturnPlugins, TestSelectiveChannelSending)
  function TEST_F (line 286) | TEST_F(TestSendReturnPlugins, TestRampedProcessing)

FILE: test/unittests/plugins/step_sequencer_test.cpp
  class TestStepSequencerPlugin (line 12) | class TestStepSequencerPlugin : public ::testing::Test
    method TestStepSequencerPlugin (line 15) | TestStepSequencerPlugin() = default;
    method SetUp (line 17) | void SetUp() override
  function TEST_F (line 29) | TEST_F(TestStepSequencerPlugin, TestOutput)

FILE: test/unittests/plugins/wav_streamer_plugin_test.cpp
  function TEST (line 20) | TEST(TestWaveStreamerPluginInternal, TestGainScaleFunction)
  class TestWaveStreamerPlugin (line 28) | class TestWaveStreamerPlugin : public ::testing::Test
    method SetUp (line 31) | void SetUp() override
    method LoadFile (line 41) | void LoadFile(const std::string& file)
  function TEST_F (line 54) | TEST_F(TestWaveStreamerPlugin, TestInstantiation)
  function TEST_F (line 66) | TEST_F(TestWaveStreamerPlugin, TestWaveLoadingAndPlaying)

FILE: test/unittests/sample_test.cpp
  function TEST (line 4) | TEST (SampleTest, SimpleTestCase) {
  class SampleTestCase (line 10) | class SampleTestCase : public ::testing::Test
    method SampleTestCase (line 13) | SampleTestCase() = default;
    method SetUp (line 15) | void SetUp() override {}
    method TearDown (line 17) | void TearDown() override {}
  function TEST_F (line 20) | TEST_F(SampleTestCase, SampleTest)

FILE: test/unittests/test_utils/apple_coreaudio_mockup.cpp
  function OSStatus (line 10) | OSStatus AudioDeviceCreateIOProcID(AudioObjectID audio_object_id,
  function OSStatus (line 22) | OSStatus AudioDeviceDestroyIOProcID(AudioObjectID audio_object_id, Audio...
  function OSStatus (line 27) | OSStatus AudioDeviceStart(AudioObjectID audio_object_id, AudioDeviceIOPr...
  function OSStatus (line 32) | OSStatus AudioDeviceStop(AudioObjectID audio_object_id, AudioDeviceIOPro...
  function OSStatus (line 37) | OSStatus AudioObjectGetPropertyData(AudioObjectID audio_object_id,
  function OSStatus (line 53) | OSStatus AudioObjectSetPropertyData(AudioObjectID audio_object_id,
  function OSStatus (line 69) | OSStatus AudioObjectGetPropertyDataSize(AudioObjectID audio_object_id,
  function Boolean (line 83) | Boolean AudioObjectHasProperty(AudioObjectID audio_object_id, const Audi...
  function OSStatus (line 88) | OSStatus AudioObjectIsPropertySettable(AudioObjectID audio_object_id,
  function OSStatus (line 95) | OSStatus AudioObjectAddPropertyListener(AudioObjectID audio_object_id,
  function OSStatus (line 103) | OSStatus AudioObjectRemovePropertyListener(AudioObjectID audio_object_id,

FILE: test/unittests/test_utils/apple_coreaudio_mockup.h
  function class (line 8) | class AppleAudioHardwareMockup

FILE: test/unittests/test_utils/audio_frontend_mockup.h
  function class (line 12) | class AudioFrontendMockup : public BaseAudioFrontend

FILE: test/unittests/test_utils/audio_graph_accessor.h
  function namespace (line 6) | namespace sushi::internal::engine

FILE: test/unittests/test_utils/control_mockup.h
  function ParameterInfo (line 14) | const ParameterInfo parameter_1{0, ParameterType::INT, "param 1", "param...
  function ParameterInfo (line 15) | const ParameterInfo parameter_2{1, ParameterType::FLOAT, "param 2", "par...
  function ParameterInfo (line 16) | const ParameterInfo parameter_3{2, ParameterType::BOOL, "param 3", "para...
  function TrackInfo (line 24) | const TrackInfo track1{0, "track 1", "track 1", 0, 0, 0, TrackType::REGU...
  function TrackInfo (line 25) | const TrackInfo track2{1, "track 2", "track 2", 1, 1, 1, TrackType::REGU...
  function was_recently_called (line 52) | bool was_recently_called()
  function clear_recent_call (line 57) | void clear_recent_call()
  function force_return_status (line 62) | void force_return_status(ControlStatus status)
  function ControlStatus (line 71) | ControlStatus _return_status{DEFAULT_CONTROL_STATUS};
  function override (line 409) | const override
  function override (line 414) | const override
  function override (line 419) | const override
  function override (line 424) | const override
  function ControlResponse (line 429) | ControlResponse set_processor_program(int processor_id, int program_id) ...
  function override (line 440) | const override
  function override (line 445) | const override
  function override (line 499) | const override
  function override (line 527) | const override
  function override (line 532) | const override
  function override (line 537) | const override
  function override (line 542) | const override
  function override (line 548) | const override
  function override (line 554) | const override
  function get_midi_clock_output_enabled (line 559) | bool get_midi_clock_output_enabled(int /*port*/) const override
  function ControlStatus (line 564) | ControlStatus set_midi_clock_output_enabled(bool /*enabled*/, int /*port...
  function ControlResponse (line 569) | ControlResponse connect_kbd_input_to_track(int /*track_id*/, MidiChannel...
  function ControlResponse (line 574) | ControlResponse connect_kbd_output_from_track(int /*track_id*/, MidiChan...
  function ControlResponse (line 579) | ControlResponse connect_cc_to_parameter(int /*processor_id*/,
  function ControlResponse (line 591) | ControlResponse connect_pc_to_processor(int /*processor_id*/, MidiChanne...
  function ControlResponse (line 596) | ControlResponse disconnect_kbd_input(int /*track_id*/, MidiChannel /*cha...
  function ControlResponse (line 601) | ControlResponse disconnect_kbd_output(int /*track_id*/, MidiChannel /*ch...
  function ControlResponse (line 606) | ControlResponse disconnect_cc(int /*processor_id*/, MidiChannel /*channe...
  function ControlResponse (line 611) | ControlResponse disconnect_pc(int /*processor_id*/, MidiChannel /*channe...
  function ControlResponse (line 616) | ControlResponse disconnect_all_cc_from_processor(int /*processor_id*/) o...
  function ControlResponse (line 621) | ControlResponse disconnect_all_pc_from_processor(int /*processor_id*/) o...
  function override (line 630) | const override
  function override (line 635) | const override
  function override (line 640) | const override
  function override (line 645) | const override
  function ControlResponse (line 650) | ControlResponse connect_input_channel_to_track(int /*track_id*/, int /*t...
  function ControlResponse (line 655) | ControlResponse connect_output_channel_to_track(int /*track_id*/, int /*...
  function ControlResponse (line 660) | ControlResponse disconnect_input(int /*track_id*/, int /*track_channel*/...
  function ControlResponse (line 665) | ControlResponse disconnect_output(int /*track_id*/, int /*track_channel*...
  function ControlResponse (line 670) | ControlResponse disconnect_all_inputs_from_track(int /*track_id*/) override
  function ControlResponse (line 675) | ControlResponse disconnect_all_outputs_from_track(int /*track_id*/) over...
  function override (line 688) | const override
  function override (line 693) | const override
  function override (line 698) | const override
  function override (line 703) | const override
  function override (line 709) | const override
  function override (line 715) | const override
  function override (line 721) | const override
  function override (line 727) | const override
  function ControlResponse (line 732) | ControlResponse connect_cv_input_to_parameter(int /*processor_id*/, int ...
  function ControlResponse (line 737) | ControlResponse connect_cv_output_from_parameter(int /*processor_id*/, i...
  function ControlResponse (line 742) | ControlResponse connect_gate_input_to_processor(int /*processor_id*/, in...
  function ControlResponse (line 747) | ControlResponse connect_gate_output_from_processor(int /*processor_id*/,...
  function ControlResponse (line 752) | ControlResponse disconnect_cv_input(int /*processor_id*/, int /*paramete...
  function ControlResponse (line 757) | ControlResponse disconnect_cv_output(int /*processor_id*/, int /*paramet...
  function ControlResponse (line 762) | ControlResponse disconnect_gate_input(int /*processor_id*/, int /*gate_i...
  function ControlResponse (line 767) | ControlResponse disconnect_gate_output(int /*processor_id*/, int /*gate_...
  function ControlResponse (line 772) | ControlResponse disconnect_all_cv_inputs_from_processor(int /*processor_...
  function ControlResponse (line 777) | ControlResponse disconnect_all_cv_outputs_from_processor(int /*processor...
  function ControlResponse (line 782) | ControlResponse disconnect_all_gate_inputs_from_processor(int /*processo...
  function ControlResponse (line 787) | ControlResponse disconnect_all_gate_outputs_from_processor(int /*process...
  function override (line 802) | const override
  function ControlResponse (line 807) | ControlResponse enable_output_for_parameter(int /*processor_id*/, int /*...
  function ControlResponse (line 812) | ControlResponse disable_output_for_parameter(int /*processor_id*/, int /...
  function ControlResponse (line 817) | ControlResponse enable_all_output() override
  function ControlResponse (line 822) | ControlResponse disable_all_output() override
  function class (line 843) | class ControlMockup : public SushiControl
  function SystemControllerMockup (line 884) | SystemControllerMockup* system_controller_mockup()
  function TransportControllerMockup (line 889) | TransportControllerMockup* transport_controller_mockup()
  function TimingControllerMockup (line 894) | TimingControllerMockup* timing_controller_mockup()
  function KeyboardControllerMockup (line 899) | KeyboardControllerMockup* keyboard_controller_mockup()
  function AudioGraphControllerMockup (line 904) | AudioGraphControllerMockup* audio_graph_controller_mockup()
  function ProgramControllerMockup (line 909) | ProgramControllerMockup* program_controller_mockup()
  function ParameterControllerMockup (line 914) | ParameterControllerMockup* parameter_controller_mockup()
  function MidiControllerMockup (line 919) | MidiControllerMockup* midi_controller_mockup()
  function AudioRoutingControllerMockup (line 924) | AudioRoutingControllerMockup* audio_routing_controller_mockup()
  function CvGateControllerMockup (line 929) | CvGateControllerMockup* cv_gate_controller_mockup()
  function OscControllerMockup (line 934) | OscControllerMockup* osc_controller_mockup()
  function SessionControllerMockup (line 939) | SessionControllerMockup* session_controller_mockup()

FILE: test/unittests/test_utils/dummy_processor.h
  function class (line 8) | class DummyProcessor : public Processor
  function ProcessorReturnCode (line 22) | ProcessorReturnCode init(float /* sample_rate */) override
  function process_event (line 27) | void process_event(const RtEvent& /*event*/) override {}
  function process_audio (line 28) | void process_audio(const sushi::ChunkSampleBuffer& in_buffer, sushi::Chu...
  function class (line 34) | class DummyMonoProcessor : public DummyProcessor

FILE: test/unittests/test_utils/engine_mockup.h
  function run (line 36) | void run() override {}
  function stop (line 37) | void stop() override {}
  function set_sample_rate (line 39) | void set_sample_rate(float /*sample_rate*/) override {}
  function set_time (line 40) | void set_time(Time /*timestamp*/) override {}
  function dispatch (line 42) | int dispatch(std::unique_ptr<Event> /*event*/) override
  function post_event (line 47) | void post_event(std::unique_ptr<Event> event) override
  function got_event (line 56) | bool got_event()
  function execute_engine_event (line 76) | int execute_engine_event(BaseEngine* engine)
  function send_with_completion_notification (line 122) | int send_with_completion_notification([[maybe_unused]] std::unique_ptr<E...
  function add_processor (line 139) | bool add_processor(std::shared_ptr<Processor> /*processor*/) override {r...
  function add_track (line 141) | bool add_track(std::shared_ptr<Track> /*track*/) override {return true;}
  function remove_processor (line 143) | bool remove_processor(ObjectId /*id*/) override {return true;}
  function remove_track (line 145) | bool remove_track(ObjectId /*track_id*/) override {return true;}
  function add_to_track (line 147) | bool add_to_track(std::shared_ptr<Processor> /*processor*/, ObjectId /*t...
  function remove_from_track (line 149) | bool remove_from_track(ObjectId /*processor_id*/, ObjectId /*track_id*/)...
  function processor_exists (line 151) | bool processor_exists(ObjectId /*id*/) const override {return true;}
  function processor_exists (line 153) | bool processor_exists(const std::string& /*name*/) const override {retur...
  function override (line 155) | const override {return {_processor};}
  function override (line 157) | const override {return _processor;}
  function EngineReturnStatus (line 213) | EngineReturnStatus send_rt_event_to_processor(const RtEvent& /*event*/) ...
  function BaseProcessorContainer (line 224) | const BaseProcessorContainer* processor_container() override
  function got_rt_event (line 231) | bool got_rt_event{false};
  function class (line 248) | class DummyMidiFrontend : public sushi::internal::midi_frontend::BaseMid...

FILE: test/unittests/test_utils/event_dispatcher_accessor.h
  function namespace (line 7) | namespace sushi::internal::dispatcher

FILE: test/unittests/test_utils/jack_mockup.cpp
  type _jack_port (line 13) | struct _jack_port
  type _jack_client (line 18) | struct _jack_client
  function jack_client_t (line 26) | jack_client_t * jack_client_open (const char* /*client_name*/,
  function jack_client_close (line 34) | int jack_client_close (jack_client_t *client)
  function jack_nframes_t (line 40) | jack_nframes_t jack_get_sample_rate(jack_client_t* /*client*/)
  function jack_port_t (line 45) | jack_port_t * jack_port_register (jack_client_t* client,
  function jack_set_process_callback (line 55) | int jack_set_process_callback (jack_client_t* client,
  function jack_set_sample_rate_callback (line 64) | int jack_set_sample_rate_callback (jack_client_t* /*client*/,
  function jack_set_latency_callback (line 72) | int jack_set_latency_callback (jack_client_t* /*client*/,
  function jack_activate (line 79) | int jack_activate (jack_client_t* client)
  function jack_midi_get_event_count (line 90) | uint32_t jack_midi_get_event_count(void* /*port_buffer*/)
  function jack_midi_event_get (line 95) | int jack_midi_event_get(jack_midi_event_t *event,
  function jack_get_cycle_times (line 105) | int jack_get_cycle_times(const jack_client_t* /*client*/, jack_nframes_t...
  function jack_port_get_latency_range (line 115) | void jack_port_get_latency_range (jack_port_t* /*port*/, jack_latency_ca...
  function jack_connect (line 134) | int jack_connect (jack_client_t* /*client*/,
  function jack_free (line 146) | void jack_free(void* /*ptr*/) {}

FILE: test/unittests/test_utils/mock_event_dispatcher.h
  function class (line 12) | class MockEventDispatcher : public dispatcher::BaseEventDispatcher

FILE: test/unittests/test_utils/mock_midi_frontend.h
  function class (line 15) | class MockMidiFrontend : public midi_frontend::BaseMidiFrontend

FILE: test/unittests/test_utils/mock_osc_interface.h
  function class (line 27) | class MockOscInterface: public BaseOscMessenger

FILE: test/unittests/test_utils/mock_oscpack.h
  function class (line 23) | class IpEndpointName
  function class (line 32) | class PacketListener
  function class (line 39) | class UdpTransmitSocket
  function class (line 53) | class UdpListeningReceiveSocket
  function namespace (line 79) | namespace osc

FILE: test/unittests/test_utils/mock_processor_container.h
  function class (line 16) | class MockProcessorContainer : public engine::BaseProcessorContainer

FILE: test/unittests/test_utils/mock_sushi.h
  function namespace (line 28) | namespace sushi
  function class (line 36) | class MockSushi : public AbstractSushi

FILE: test/unittests/test_utils/plugin_accessors.h
  function namespace (line 10) | namespace sushi::internal::gain_plugin
  function class (line 32) | class Accessor
  function namespace (line 66) | namespace sushi::internal::stereo_mixer_plugin
  function namespace (line 130) | namespace sushi::internal::wav_writer_plugin

FILE: test/unittests/test_utils/portaudio_mockup.cpp
  function PaError (line 5) | PaError Pa_Initialize()
  function PaError (line 10) | PaError Pa_Terminate()
  function Pa_GetDeviceCount (line 20) | int Pa_GetDeviceCount()
  function Pa_GetDefaultInputDevice (line 25) | int Pa_GetDefaultInputDevice()
  function Pa_GetDefaultOutputDevice (line 30) | int Pa_GetDefaultOutputDevice()
  function PaDeviceInfo (line 35) | const PaDeviceInfo* Pa_GetDeviceInfo(int device_index)
  function PaHostApiInfo (line 40) | const PaHostApiInfo* Pa_GetHostApiInfo(int api_index)
  function PaError (line 45) | PaError Pa_IsFormatSupported(const PaStreamParameters* input,
  function PaTime (line 52) | PaTime Pa_GetStreamTime(PaStream* stream)
  function PaError (line 57) | PaError Pa_IsStreamActive(PaStream* stream)
  function PaError (line 62) | PaError Pa_OpenStream(PaStream** stream,
  function PaError (line 81) | PaError Pa_StartStream(PaStream* stream)
  function PaError (line 86) | PaError Pa_StopStream(PaStream* stream)
  function PaStreamInfo (line 91) | const PaStreamInfo* Pa_GetStreamInfo(PaStream* stream)

FILE: test/unittests/test_utils/portaudio_mockup.h
  function class (line 10) | class MockPortAudio

FILE: test/unittests/test_utils/test_utils.h
  function assert_buffer_value (line 51) | void assert_buffer_value(float value, const SampleBuffer <size> &buffer)
  function assert_buffer_value (line 63) | void assert_buffer_value(float value, const SampleBuffer<size>& buffer, ...
  function assert_buffer_non_null (line 75) | void assert_buffer_non_null(const SampleBuffer <size> &buffer)
  function assert_buffer_not_nan (line 89) | void assert_buffer_not_nan(const SampleBuffer <size> &buffer)
  function std (line 100) | inline std::string get_data_dir_path()

FILE: test/unittests/test_utils/track_accessor.h
  function namespace (line 6) | namespace sushi::internal::engine {

FILE: test/unittests/test_utils/vst2_test_plugin.cpp
  function AudioEffect (line 7) | AudioEffect* createEffectInstance(audioMasterCallback audioMaster)
  type test_utils (line 12) | namespace test_utils {
    function VstInt32 (line 126) | VstInt32 Vst2TestPlugin::getVendorVersion()
    function VstInt32 (line 159) | VstInt32 Vst2TestPlugin::getProgram()
    function VstInt32 (line 179) | VstInt32 Vst2TestPlugin::processEvents(VstEvents* events)

FILE: test/unittests/test_utils/vst2_test_plugin.h
  function namespace (line 14) | namespace test_utils {

FILE: test/unittests/test_utils/vst3_test_plugin.cpp
  type test_utils (line 11) | namespace test_utils {
    function test_callback (line 29) | Steinberg::int32 test_callback(void* data, Steinberg::uint16 id)

FILE: test/unittests/test_utils/vst3_test_plugin.h
  function class (line 75) | class Vst3TestPlugin

FILE: third-party/fifo/include/fifo/circularfifo_memory_relaxed_aquire_release.h
  function namespace (line 28) | namespace memory_relaxed_aquire_release {
  function virtual (line 42) | virtual ~CircularFifo() {}
  function wasEmpty (line 47) | bool wasEmpty() const;

FILE: third-party/lv2_host/include/lv2_host/lv2_evbuf.h
  function namespace (line 23) | namespace lv2_host {

FILE: third-party/lv2_host/include/lv2_host/lv2_symap.h
  function namespace (line 31) | namespace lv2_host {

FILE: third-party/lv2_host/src/lv2_evbuf.cpp
  type lv2_host (line 26) | namespace lv2_host {
    type LV2_Evbuf_Impl (line 28) | struct LV2_Evbuf_Impl
    function lv2_evbuf_pad_size (line 36) | static inline uint32_t lv2_evbuf_pad_size(uint32_t size)
    function LV2_Evbuf (line 41) | LV2_Evbuf* lv2_evbuf_new(uint32_t capacity, uint32_t atom_Chunk, uint3...
    function lv2_evbuf_free (line 52) | void lv2_evbuf_free(LV2_Evbuf *evbuf)
    function lv2_evbuf_reset (line 57) | void lv2_evbuf_reset(LV2_Evbuf *evbuf, bool input)
    function lv2_evbuf_get_size (line 71) | uint32_t lv2_evbuf_get_size(LV2_Evbuf *evbuf)
    function LV2_Evbuf_Iterator (line 85) | LV2_Evbuf_Iterator lv2_evbuf_begin(LV2_Evbuf *evbuf)
    function LV2_Evbuf_Iterator (line 91) | LV2_Evbuf_Iterator lv2_evbuf_end(LV2_Evbuf *evbuf)
    function lv2_evbuf_is_valid (line 98) | bool lv2_evbuf_is_valid(LV2_Evbuf_Iterator iter)
    function LV2_Evbuf_Iterator (line 103) | LV2_Evbuf_Iterator lv2_evbuf_next(LV2_Evbuf_Iterator iter)
    function lv2_evbuf_get (line 122) | bool lv2_evbuf_get(LV2_Evbuf_Iterator iter,
    function lv2_evbuf_write (line 149) | bool lv2_evbuf_write(LV2_Evbuf_Iterator *iter,

FILE: third-party/lv2_host/src/lv2_symap.cpp
  type lv2_host (line 41) | namespace lv2_host {
    type SymapImpl (line 43) | struct SymapImpl
    function Symap (line 62) | Symap* symap_new(void)
    function symap_free (line 71) | void symap_free(Symap *map)
    function symap_search (line 100) | static uint32_t symap_search(const Symap *map, const char *sym, bool *...
    function symap_try_map (line 147) | uint32_t symap_try_map(Symap *map, const char *sym)
    function symap_map (line 161) | uint32_t symap_map(Symap *map, const char *sym)

FILE: third-party/optionparser/example.cpp
  type optionIndex (line 19) | enum  optionIndex { UNKNOWN, HELP, PLUS }
  function main (line 32) | int main(int argc, char* argv[])

FILE: third-party/optionparser/example_arg.cc
  type Arg (line 19) | struct Arg: public option::Arg
    method printError (line 21) | static void printError(const char* msg1, const option::Option& opt, co...
    method Unknown (line 28) | static option::ArgStatus Unknown(const option::Option& option, bool msg)
    method Required (line 34) | static option::ArgStatus Required(const option::Option& option, bool msg)
    method NonEmpty (line 43) | static option::ArgStatus NonEmpty(const option::Option& option, bool msg)
    method Numeric (line 52) | static option::ArgStatus Numeric(const option::Option& option, bool msg)
  type optionIndex (line 64) | enum  optionIndex { UNKNOWN, HELP, OPTIONAL, REQUIRED, NUMERIC, NONEMPTY }
  function main (line 99) | int main(int argc, char* argv[])

FILE: third-party/optionparser/optionparser.h
  function namespace (line 225) | namespace optionparser
  function Option (line 819) | static Option* tag(Option* ptr)
  function Option (line 824) | static Option* untag(Option* ptr)
  function isTagged (line 829) | static bool isTagged(Option* ptr)
  function Optional (line 889) | struct Arg
  type Stats (line 916) | struct Stats
  function class (line 1046) | class Parser
  function optionsCount (line 1186) | int optionsCount()
  function nonOptionsCount (line 1205) | int nonOptionsCount()
  function error (line 1249) | bool error()
  type Action (line 1257) | struct Action
  function streq (line 1281) | static bool streq(const char* st1, const char* st2)
  function streqabbr (line 1313) | static bool streqabbr(const char* st1, const char* st2, long long min)
  function instr (line 1331) | static bool instr(char ch, const char* st)
  function shift (line 1343) | static void shift(const char** args, int count)
  function Action (line 1359) | struct Parser::Action
  function perform (line 1408) | bool perform(Option&)
  function perform (line 1448) | bool perform(Option& option)
  function finished (line 1466) | bool finished(int numargs, const char** args)
  function parse (line 1481) | inline void Parser::parse(bool gnu, const Descriptor usage[], int argc, ...
  function add (line 1488) | inline void Stats::add(bool gnu, const Descriptor usage[], int argc, con...
  function workhorse (line 1505) | inline bool Parser::workhorse(bool gnu, const Descriptor usage[], int nu...
  function OStreamWriter (line 1690) | struct PrintUsageImplementation
  function virtual (line 1758) | virtual void operator()(const char* str, int size)
  function userstream (line 1763) | TemporaryWriter(const Temporary& u) :
  function virtual (line 1781) | virtual void operator()(const char* str, int size)
  function virtual (line 1802) | virtual void operator()(const char* str, int size)
  function upmax (line 1817) | static void upmax(int& i1, int i2)
  function indent (line 1833) | static void indent(IStringWriter& write, int& x, int want_x)
  function isWideChar (line 1869) | static bool isWideChar(unsigned ch)
  function class (line 1916) | class LinePartIterator
  function restartTable (line 1993) | void restartTable()
  function nextRow (line 2005) | bool nextRow()
  function restartRow (line 2036) | void restartRow()
  function next (line 2055) | bool next()
  function column (line 2127) | int column()
  function line (line 2136) | int line()
  function length (line 2144) | int length()
  function screenLength (line 2153) | int screenLength()
  function class (line 2191) | class LineWrapper

FILE: third-party/optionparser/printUsage.h
  function class (line 9) | class UsageMsg{

FILE: third-party/optionparser/testodr1.cc
  function bar (line 33) | exte
Condensed preview — 458 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,250K chars).
[
  {
    "path": ".clang-format",
    "chars": 1963,
    "preview": "# Generated from CLion C/C++ Code Style settings\nBasedOnStyle: LLVM\nAccessModifierOffset: -4\nAlignAfterOpenBracket: Alig"
  },
  {
    "path": ".gitignore",
    "chars": 642,
    "preview": "# Object files\n*.o\n*.ko\n*.obj\n*.elf\n\n# Precompiled Headers\n*.gch\n*.pch\n\n# Libraries\n*.lib\n*.a\n*.la\n*.lo\n\n# Shared object"
  },
  {
    "path": "CMakeLists.txt",
    "chars": 29730,
    "preview": "cmake_minimum_required(VERSION 3.28)\n\n# Require out-of-source builds\nfile(TO_CMAKE_PATH \"${PROJECT_BINARY_DIR}/CMakeList"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 973,
    "preview": "# Contributing to Elk Audio OS\n\n## Github Issues\n\nYou can open a Github issue to signal a bug or request a new feature. "
  },
  {
    "path": "COPYING",
    "chars": 34522,
    "preview": "                    GNU AFFERO GENERAL PUBLIC LICENSE\n                       Version 3, 19 November 2007\n\n Copyright (C)"
  },
  {
    "path": "HISTORY.md",
    "chars": 9164,
    "preview": "## 1.3.0\nNew Features:\n  * Tracks can be explicitly allocated to threads\n  * Send and return plugins are now zero delay "
  },
  {
    "path": "LICENSE.md",
    "chars": 1985,
    "preview": "#Licensing information\n\nAll SUSHI code is Copyright © 2017-2023 [Elk Audio AB], formerly [Modern Ancient Instruments Net"
  },
  {
    "path": "README.md",
    "chars": 11779,
    "preview": "# SUSHI\nHeadless plugin host for ELK Audio OS.\n\n## Sushi as Library\nSushi can be used as a standalone terminal applicati"
  },
  {
    "path": "apps/CMakeLists.txt",
    "chars": 1877,
    "preview": "\n######################\n#  Executable target #\n######################\n\nset(APP_FILES main.cpp)\n\nif(APPLE)\n    add_execut"
  },
  {
    "path": "apps/main.cpp",
    "chars": 6997,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "bitbucket-pipelines.yml",
    "chars": 3960,
    "preview": "# Only use spaces to indent your .yml configuration.\n# -----\n# You can specify a custom docker image from Docker Hub as "
  },
  {
    "path": "docs/LIBRARY.md",
    "chars": 10497,
    "preview": "# Sushi as a Library\nUsing Sushi as a statically linked library is a newly developed feature.\n\nWe have considered two pr"
  },
  {
    "path": "include/sushi/compile_time_settings.h",
    "chars": 2702,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "include/sushi/constants.h",
    "chars": 2184,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "include/sushi/control_interface.h",
    "chars": 26969,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "include/sushi/control_notifications.h",
    "chars": 4762,
    "preview": "\n#ifndef SUSHI_CONTROL_NOTIFICATIONS_H\n#define SUSHI_CONTROL_NOTIFICATIONS_H\n\n#include <variant>\n#include \"control_inter"
  },
  {
    "path": "include/sushi/coreaudio_devices_dump.h",
    "chars": 1143,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "include/sushi/elk_sentry_log_sink.h",
    "chars": 2047,
    "preview": "/**\n * @brief An spdlog sink which wraps the Sentry logging functionality\n * @Copyright 2017-2024 Elk Audio AB, Stockhol"
  },
  {
    "path": "include/sushi/factory_interface.h",
    "chars": 1081,
    "preview": "/*\n* Copyright 2017-2022 Modern Ancient Instruments Networked AB, dba Elk\n*\n* SUSHI is free software: you can redistribu"
  },
  {
    "path": "include/sushi/offline_factory.h",
    "chars": 1336,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "include/sushi/options.h",
    "chars": 15567,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "include/sushi/parameter_dump.h",
    "chars": 1136,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "include/sushi/portaudio_devices_dump.h",
    "chars": 1143,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "include/sushi/reactive_factory.h",
    "chars": 1699,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "include/sushi/rt_controller.h",
    "chars": 5245,
    "preview": "/*\n* Copyright 2017-2022 Modern Ancient Instruments Networked AB, dba Elk\n*\n* SUSHI is free software: you can redistribu"
  },
  {
    "path": "include/sushi/sample_buffer.h",
    "chars": 19583,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "include/sushi/standalone_factory.h",
    "chars": 1364,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "include/sushi/sushi.h",
    "chars": 10316,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "include/sushi/sushi_time.h",
    "chars": 1457,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "include/sushi/terminal_utilities.h",
    "chars": 9314,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "include/sushi/types.h",
    "chars": 2309,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "include/sushi/utils.h",
    "chars": 1571,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "include/version.h.in",
    "chars": 398,
    "preview": "#ifndef __version_h__\n#define __version_h__\n\n#define SUSHI__VERSION_MAJ  @SUSHI_VERSION_MAJOR@\n#define SUSHI__VERSION_MI"
  },
  {
    "path": "misc/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "misc/README.md",
    "chars": 820,
    "preview": "# Misc folder - example configurations\n\nThis folder contains some example JSON config files for Sushi, and some data (e."
  },
  {
    "path": "misc/config_files/arp_peakmeter_osc_broadcast.json",
    "chars": 1526,
    "preview": "{\n    \"host_config\" : {\n        \"samplerate\" : 48000,\n        \"tempo_sync\" : \"ableton_link\",\n        \"playing_mode\" : \"p"
  },
  {
    "path": "misc/config_files/config_play_arp_link_midi_out.json",
    "chars": 1007,
    "preview": "{\n    \"host_config\" : {\n        \"samplerate\" : 48000,\n        \"tempo_sync\" : \"ableton_link\",\n        \"playing_mode\" : \"p"
  },
  {
    "path": "misc/config_files/cv_lfo.json",
    "chars": 800,
    "preview": "{\n    \"host_config\" : {\n        \"samplerate\" : 48000,\n        \"cv_inputs\" : 0,\n        \"cv_outputs\" :4\n    },\n    \"track"
  },
  {
    "path": "misc/config_files/cv_to_cutoff.json",
    "chars": 1307,
    "preview": "{\n    \"host_config\" : {\n        \"samplerate\" : 48000,\n        \"cv_inputs\" : 2,\n        \"cv_outputs\" :4\n    },\n    \"track"
  },
  {
    "path": "misc/config_files/cv_to_synth.json",
    "chars": 1431,
    "preview": "{\n    \"host_config\" : {\n        \"samplerate\" : 48000,\n        \"cv_inputs\" : 2,\n        \"cv_outputs\" : 0\n    },\n    \"trac"
  },
  {
    "path": "misc/config_files/empty.json",
    "chars": 738,
    "preview": "{\n    \"host_config\" : {\n        \"samplerate\" : 48000\n    },\n    \"tracks\" : [\n        {\n            \"name\" : \"main\",\n    "
  },
  {
    "path": "misc/config_files/freeverb_aux.json",
    "chars": 2031,
    "preview": "{\n    \"host_config\" : {\n        \"samplerate\" : 48000,\n        \"playing_mode\" : \"playing\"\n    },\n    \"tracks\" : [\n       "
  },
  {
    "path": "misc/config_files/fx.json",
    "chars": 1356,
    "preview": "{\n    \"host_config\" : {\n        \"samplerate\" : 48000\n    },\n    \"tracks\" : [\n        {\n            \"name\" : \"main\",\n    "
  },
  {
    "path": "misc/config_files/multi_track.json",
    "chars": 2449,
    "preview": "{\n    \"host_config\" : {\n        \"samplerate\" : 48000\n    },\n    \"tracks\" : [\n        {\n            \"name\" : \"guitar\",\n  "
  },
  {
    "path": "misc/config_files/multichannel_plugin.json",
    "chars": 1289,
    "preview": "{\n    \"host_config\" : {\n        \"samplerate\" : 48000\n    },\n    \"tracks\" : [\n        {\n            \"name\" : \"main\",\n    "
  },
  {
    "path": "misc/config_files/play_arp_mda_link.json",
    "chars": 1388,
    "preview": "{\n    \"host_config\" : {\n        \"samplerate\" : 48000,\n        \"tempo_sync\" : \"ableton_link\",\n        \"playing_mode\" : \"p"
  },
  {
    "path": "misc/config_files/play_brickworks_fx.json",
    "chars": 5910,
    "preview": "{\n    \"host_config\" : {\n        \"samplerate\" : 48000,\n        \"playing_mode\" : \"playing\"\n    },\n    \"tracks\" : [\n       "
  },
  {
    "path": "misc/config_files/play_brickworks_synth.json",
    "chars": 1738,
    "preview": "{\n    \"host_config\" : {\n        \"samplerate\" : 48000,\n        \"tempo\" : 140.0,\n        \"playing_mode\" : \"playing\"\n    },"
  },
  {
    "path": "misc/config_files/play_cv_arp.json",
    "chars": 1288,
    "preview": "{\n    \"host_config\" : {\n        \"samplerate\" : 48000,\n        \"cv_inputs\" : 0,\n        \"cv_outputs\" : 4\n    },\n    \"trac"
  },
  {
    "path": "misc/config_files/play_lv2.json",
    "chars": 972,
    "preview": "{\n    \"host_config\" : {\n        \"samplerate\" : 48000,\n        \"tempo_sync\" : \"internal\",\n        \"playing_mode\" : \"playi"
  },
  {
    "path": "misc/config_files/play_lv2_jx10.json",
    "chars": 956,
    "preview": "{\n    \"host_config\" : {\n        \"samplerate\" : 48000\n    },\n    \"tracks\" : [\n        {\n            \"name\" : \"main\",\n    "
  },
  {
    "path": "misc/config_files/play_master_gain.json",
    "chars": 1427,
    "preview": "{\n    \"host_config\" : {\n        \"samplerate\" : 48000,\n        \"playing_mode\" : \"playing\"\n    },\n    \"tracks\" : [\n       "
  },
  {
    "path": "misc/config_files/play_vst2.json",
    "chars": 1841,
    "preview": "{\n    \"host_config\" : {\n        \"samplerate\" : 44100,\n        \"playing_mode\" : \"playing\",\n        \"tempo_sync\" : \"intern"
  },
  {
    "path": "misc/config_files/play_vst3.json",
    "chars": 985,
    "preview": "{\n    \"host_config\" : {\n        \"samplerate\" : 48000\n    },\n    \"tracks\" : [\n        {\n            \"name\" : \"main\",\n    "
  },
  {
    "path": "misc/config_files/play_wav_streamer.json",
    "chars": 815,
    "preview": "{\n    \"host_config\" : {\n        \"samplerate\" : 48000,\n        \"tempo_sync\" : \"internal\",\n        \"playing_mode\" : \"playi"
  },
  {
    "path": "misc/config_files/prepost_tracks.json",
    "chars": 1204,
    "preview": "{\n    \"host_config\" : {\n        \"samplerate\" : 48000\n    },\n    \"osc\" : {\n        \"enable_all_processor_outputs\" : true\n"
  },
  {
    "path": "misc/config_files/rt_midi.json",
    "chars": 1292,
    "preview": "{\n    \"host_config\" : {\n        \"samplerate\" : 48000,\n        \"audio_clip_detection\" : {\n            \"inputs\" : true,\n  "
  },
  {
    "path": "misc/config_files/send_return_seq.json",
    "chars": 4419,
    "preview": "{\n    \"host_config\" : {\n        \"samplerate\" : 48000,\n        \"playing_mode\" : \"playing\"\n    },\n    \"tracks\" : [\n       "
  },
  {
    "path": "misc/config_files/vst_8_ch.json",
    "chars": 2968,
    "preview": "{\n    \"host_config\" : {\n        \"samplerate\" : 48000\n    },\n    \"tracks\" : [\n        {\n            \"name\" : \"main (Piano"
  },
  {
    "path": "rpc_interface/CMakeLists.txt",
    "chars": 2364,
    "preview": "####################\n#  CMake packages  #\n####################\n\nfind_package(gRPC REQUIRED)\n\n\n##########################"
  },
  {
    "path": "rpc_interface/include/sushi_rpc/grpc_server.h",
    "chars": 3708,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "rpc_interface/src/async_service_call_data.cpp",
    "chars": 10090,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "rpc_interface/src/async_service_call_data.h",
    "chars": 8472,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "rpc_interface/src/control_service.cpp",
    "chars": 112020,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "rpc_interface/src/control_service.h",
    "chars": 29711,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "rpc_interface/src/grpc_server.cpp",
    "chars": 6085,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/audio_frontends/apple_coreaudio/apple_coreaudio_device.h",
    "chars": 10549,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/audio_frontends/apple_coreaudio/apple_coreaudio_device.mm",
    "chars": 18810,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/audio_frontends/apple_coreaudio/apple_coreaudio_object.cpp",
    "chars": 9513,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/audio_frontends/apple_coreaudio/apple_coreaudio_object.h",
    "chars": 12463,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/audio_frontends/apple_coreaudio/apple_coreaudio_system_object.h",
    "chars": 2377,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/audio_frontends/apple_coreaudio/apple_coreaudio_utils.cpp",
    "chars": 2951,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/audio_frontends/apple_coreaudio/apple_coreaudio_utils.h",
    "chars": 4411,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/audio_frontends/apple_coreaudio_frontend.cpp",
    "chars": 15468,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/audio_frontends/apple_coreaudio_frontend.h",
    "chars": 5018,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/audio_frontends/audio_frontend_internals.h",
    "chars": 3109,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/audio_frontends/base_audio_frontend.cpp",
    "chars": 3768,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/audio_frontends/base_audio_frontend.h",
    "chars": 4427,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/audio_frontends/coreaudio_devices_dump.cpp",
    "chars": 5037,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/audio_frontends/jack_frontend.cpp",
    "chars": 14252,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/audio_frontends/jack_frontend.h",
    "chars": 6150,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/audio_frontends/offline_frontend.cpp",
    "chars": 9392,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/audio_frontends/offline_frontend.h",
    "chars": 3448,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/audio_frontends/portaudio_devices_dump.cpp",
    "chars": 4022,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/audio_frontends/portaudio_frontend.cpp",
    "chars": 16815,
    "preview": "/*\n * Copyright 2017-2024 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/audio_frontends/portaudio_frontend.h",
    "chars": 10206,
    "preview": "/*\n * Copyright 2017-2024 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/audio_frontends/reactive_frontend.cpp",
    "chars": 3452,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/audio_frontends/reactive_frontend.h",
    "chars": 3495,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/audio_frontends/xenomai_raspa_frontend.cpp",
    "chars": 7617,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/audio_frontends/xenomai_raspa_frontend.h",
    "chars": 4268,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/concrete_sushi.cpp",
    "chars": 6176,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/concrete_sushi.h",
    "chars": 3147,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/control_frontends/alsa_midi_frontend.cpp",
    "chars": 10574,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/control_frontends/alsa_midi_frontend.h",
    "chars": 2486,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/control_frontends/base_control_frontend.cpp",
    "chars": 3941,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/control_frontends/base_control_frontend.h",
    "chars": 2866,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/control_frontends/base_midi_frontend.h",
    "chars": 2177,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/control_frontends/osc_frontend.cpp",
    "chars": 23453,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/control_frontends/osc_frontend.h",
    "chars": 9288,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/control_frontends/osc_utils.h",
    "chars": 4493,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/control_frontends/oscpack_osc_messenger.cpp",
    "chars": 18424,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/control_frontends/oscpack_osc_messenger.h",
    "chars": 5245,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/control_frontends/reactive_midi_frontend.cpp",
    "chars": 2237,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/control_frontends/reactive_midi_frontend.h",
    "chars": 2627,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/control_frontends/rt_midi_frontend.cpp",
    "chars": 7275,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/control_frontends/rt_midi_frontend.h",
    "chars": 2136,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/dsp_library/biquad_filter.cpp",
    "chars": 4798,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/dsp_library/biquad_filter.h",
    "chars": 2329,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/dsp_library/envelopes.h",
    "chars": 5935,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/dsp_library/master_limiter.h",
    "chars": 6525,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/dsp_library/sample_wrapper.h",
    "chars": 2311,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/dsp_library/value_smoother.h",
    "chars": 7381,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/audio_engine.cpp",
    "chars": 52435,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/audio_engine.h",
    "chars": 27448,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/audio_graph.cpp",
    "chars": 5302,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/audio_graph.h",
    "chars": 4842,
    "preview": "#ifndef SUSHI_AUDIO_GRAPH_H\n#define SUSHI_AUDIO_GRAPH_H\n\n/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free soft"
  },
  {
    "path": "src/engine/base_engine.h",
    "chars": 10565,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/base_event_dispatcher.h",
    "chars": 2377,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/base_processor_container.h",
    "chars": 2803,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/connection_storage.h",
    "chars": 5828,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/controller/audio_graph_controller.cpp",
    "chars": 18677,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/controller/audio_graph_controller.h",
    "chars": 4238,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/controller/audio_routing_controller.cpp",
    "chars": 10300,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/controller/audio_routing_controller.h",
    "chars": 2609,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/controller/completion_sender.h",
    "chars": 1845,
    "preview": "/*\n* Copyright 2017-2025 Elk Audio AB\n*\n* SUSHI is free software: you can redistribute it and/or modify it under the ter"
  },
  {
    "path": "src/engine/controller/controller.cpp",
    "chars": 15463,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/controller/controller.h",
    "chars": 5133,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/controller/controller_common.h",
    "chars": 9599,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/controller/cv_gate_controller.cpp",
    "chars": 4968,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/controller/cv_gate_controller.h",
    "chars": 3883,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/controller/keyboard_controller.cpp",
    "chars": 4203,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/controller/keyboard_controller.h",
    "chars": 1986,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/controller/midi_controller.cpp",
    "chars": 16239,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/controller/midi_controller.h",
    "chars": 4909,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/controller/osc_controller.cpp",
    "chars": 5553,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/controller/osc_controller.h",
    "chars": 2158,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/controller/parameter_controller.cpp",
    "chars": 12421,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/controller/parameter_controller.h",
    "chars": 3246,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/controller/program_controller.cpp",
    "chars": 4639,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/controller/program_controller.h",
    "chars": 2103,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/controller/real_time_controller.cpp",
    "chars": 4407,
    "preview": "/*\n* Copyright 2017-2022 Modern Ancient Instruments Networked AB, dba Elk\n*\n* SUSHI is free software: you can redistribu"
  },
  {
    "path": "src/engine/controller/real_time_controller.h",
    "chars": 3262,
    "preview": "/*\n* Copyright 2017-2022 Modern Ancient Instruments Networked AB, dba Elk\n*\n* SUSHI is free software: you can redistribu"
  },
  {
    "path": "src/engine/controller/session_controller.cpp",
    "chars": 21353,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/controller/session_controller.h",
    "chars": 3216,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/controller/system_controller.cpp",
    "chars": 2000,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/controller/system_controller.h",
    "chars": 1723,
    "preview": "/*\n * Copyright 2017-2025 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/controller/timing_controller.cpp",
    "chars": 3941,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/controller/timing_controller.h",
    "chars": 2112,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/controller/transport_controller.cpp",
    "chars": 3541,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/controller/transport_controller.h",
    "chars": 2018,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/event_dispatcher.cpp",
    "chars": 13941,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/event_dispatcher.h",
    "chars": 4627,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/event_timer.cpp",
    "chars": 2220,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/event_timer.h",
    "chars": 2830,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/host_control.h",
    "chars": 2566,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/json_configurator.cpp",
    "chars": 40437,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/json_configurator.h",
    "chars": 8738,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/json_schemas/cv_gate_schema.json",
    "chars": 5059,
    "preview": "R\"(\n{\n  \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n  \"title\": \"Sushi MIDI JSON Schema\",\n  \"description\": \"JSO"
  },
  {
    "path": "src/engine/json_schemas/events_schema.json",
    "chars": 2249,
    "preview": "R\"(\n{\n  \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n  \"title\": \"Sushi Events JSON Schema\",\n  \"description\": \"J"
  },
  {
    "path": "src/engine/json_schemas/host_config_schema.json",
    "chars": 3106,
    "preview": "R\"(\n{\n  \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n  \"title\": \"Sushi Host Config JSON Schema\",\n  \"description"
  },
  {
    "path": "src/engine/json_schemas/midi_schema.json",
    "chars": 3870,
    "preview": "R\"(\n{\n  \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n  \"title\": \"Sushi MIDI JSON Schema\",\n  \"description\": \"JSO"
  },
  {
    "path": "src/engine/json_schemas/osc_schema.json",
    "chars": 1444,
    "preview": "R\"(\n{\n  \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n  \"title\": \"Sushi OSC JSON Schema\",\n  \"description\": \"JSON"
  },
  {
    "path": "src/engine/json_schemas/state_schema.json",
    "chars": 1070,
    "preview": "R\"(\n{\n  \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n  \"title\": \"Sushi Plugin Chain JSON Schema\",\n  \"descriptio"
  },
  {
    "path": "src/engine/json_schemas/tracks_schema.json",
    "chars": 5061,
    "preview": "R\"(\n{\n  \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n  \"title\": \"Sushi Plugin Chain JSON Schema\",\n  \"descriptio"
  },
  {
    "path": "src/engine/link_dummy.h",
    "chars": 3046,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/midi_dispatcher.cpp",
    "chars": 40437,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/midi_dispatcher.h",
    "chars": 15031,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/midi_receiver.h",
    "chars": 1162,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/parameter_manager.cpp",
    "chars": 7762,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/parameter_manager.h",
    "chars": 4306,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/plugin_library.cpp",
    "chars": 1617,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/plugin_library.h",
    "chars": 1838,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/processor_container.cpp",
    "chars": 8677,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/processor_container.h",
    "chars": 7576,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/receiver.cpp",
    "chars": 2380,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/receiver.h",
    "chars": 1751,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/track.cpp",
    "chars": 17502,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/track.h",
    "chars": 7423,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/transport.cpp",
    "chars": 14075,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/engine/transport.h",
    "chars": 11360,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/factories/base_factory.cpp",
    "chars": 10903,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/factories/base_factory.h",
    "chars": 5179,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/factories/offline_factory.cpp",
    "chars": 1205,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/factories/offline_factory_implementation.cpp",
    "chars": 4538,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/factories/offline_factory_implementation.h",
    "chars": 1884,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/factories/reactive_factory.cpp",
    "chars": 1359,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/factories/reactive_factory_implementation.cpp",
    "chars": 4117,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/factories/reactive_factory_implementation.h",
    "chars": 2670,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/factories/standalone_factory.cpp",
    "chars": 1231,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/factories/standalone_factory_implementation.cpp",
    "chars": 8548,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/factories/standalone_factory_implementation.h",
    "chars": 1999,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/library/base_performance_timer.h",
    "chars": 3649,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/library/base_processor_factory.h",
    "chars": 1784,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/library/connection_types.h",
    "chars": 2291,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/library/event.cpp",
    "chars": 14671,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/library/event.h",
    "chars": 27912,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/library/event_interface.h",
    "chars": 1571,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/library/fixed_stack.h",
    "chars": 2420,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/library/id_generator.h",
    "chars": 1267,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  },
  {
    "path": "src/library/internal_plugin.cpp",
    "chars": 16418,
    "preview": "/*\n * Copyright 2017-2023 Elk Audio AB\n *\n * SUSHI is free software: you can redistribute it and/or modify it under the "
  }
]

// ... and 258 more files (download for full content)

About this extraction

This page contains the full source code of the elk-audio/sushi GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 458 files (3.0 MB), approximately 801.3k tokens, and a symbol index with 2165 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!