├── .gitignore ├── .gitmodules ├── DEVELOPERS.md ├── LICENSE ├── README.md ├── SourceSampler ├── Builds │ ├── ELKAudioOS │ │ ├── Makefile │ │ └── make_helpers │ │ │ ├── arch_detection.cpp │ │ │ ├── juce_LinuxSubprocessHelper.cpp │ │ │ └── juce_SimpleBinaryBuilder.cpp │ ├── LinuxMakefile │ │ ├── Makefile │ │ └── make_helpers │ │ │ ├── arch_detection.cpp │ │ │ ├── juce_LinuxSubprocessHelper.cpp │ │ │ └── juce_SimpleBinaryBuilder.cpp │ ├── MacOSX │ │ ├── AUv3_AppExtension.entitlements │ │ ├── Icon.icns │ │ ├── Info-AU.plist │ │ ├── Info-AUv3_AppExtension.plist │ │ ├── Info-Standalone_Plugin.plist │ │ ├── Info-VST.plist │ │ ├── Info-VST3.plist │ │ ├── Info-VST3_Manifest_Helper.plist │ │ ├── RecentFilesMenuTemplate.nib │ │ └── SourceSampler.xcodeproj │ │ │ └── project.pbxproj │ └── iOS │ │ ├── AUv3_AppExtension.entitlements │ │ ├── All.entitlements │ │ ├── Icon.icns │ │ ├── Info-AUv3_AppExtension.plist │ │ ├── Info-Standalone_Plugin.plist │ │ ├── LaunchScreen.storyboard │ │ ├── Shared_Code.entitlements │ │ ├── SourceSampler.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ ├── SourceSampler - AUv3 AppExtension.xcscheme │ │ │ ├── SourceSampler - All.xcscheme │ │ │ ├── SourceSampler - Shared Code.xcscheme │ │ │ └── SourceSampler - Standalone Plugin.xcscheme │ │ ├── SourceSampler │ │ └── Images.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-29.png │ │ │ ├── Icon-29@2x.png │ │ │ ├── Icon-29@3x.png │ │ │ ├── Icon-60@2x.png │ │ │ ├── Icon-72.png │ │ │ ├── Icon-72@2x.png │ │ │ ├── Icon-76.png │ │ │ ├── Icon-76@2x.png │ │ │ ├── Icon-83.5@2x.png │ │ │ ├── Icon-@3x.png │ │ │ ├── Icon-AppStore-1024.png │ │ │ ├── Icon-Notification-20@2x.png │ │ │ ├── Icon-Notification-20@3x.png │ │ │ ├── Icon-Notifications-20.png │ │ │ ├── Icon-Notifications-20@2x.png │ │ │ ├── Icon-Small-1.png │ │ │ ├── Icon-Small-50.png │ │ │ ├── Icon-Small-50@2x.png │ │ │ ├── Icon-Small@2x-1.png │ │ │ ├── Icon-Spotlight-40.png │ │ │ ├── Icon-Spotlight-40@2x-1.png │ │ │ ├── Icon-Spotlight-40@2x.png │ │ │ ├── Icon-Spotlight-40@3x.png │ │ │ ├── Icon.png │ │ │ └── Icon@2x.png │ │ │ └── LaunchImage.launchimage │ │ │ ├── Contents.json │ │ │ ├── LaunchImage-ipad-landscape-1x.png │ │ │ ├── LaunchImage-ipad-landscape-2x.png │ │ │ ├── LaunchImage-ipad-portrait-1x.png │ │ │ ├── LaunchImage-ipad-portrait-2x.png │ │ │ ├── LaunchImage-iphone-2x.png │ │ │ └── LaunchImage-iphone-retina4.png │ │ └── Standalone_Plugin.entitlements ├── JuceLibraryCode │ ├── AppConfig.h │ ├── JuceHeader.h │ ├── JucePluginDefines.h │ ├── ReadMe.txt │ ├── include_juce_audio_basics.cpp │ ├── include_juce_audio_basics.mm │ ├── include_juce_audio_devices.cpp │ ├── include_juce_audio_devices.mm │ ├── include_juce_audio_formats.cpp │ ├── include_juce_audio_formats.mm │ ├── include_juce_audio_plugin_client_AAX.cpp │ ├── include_juce_audio_plugin_client_AAX.mm │ ├── include_juce_audio_plugin_client_AAX_utils.cpp │ ├── include_juce_audio_plugin_client_ARA.cpp │ ├── include_juce_audio_plugin_client_AU_1.mm │ ├── include_juce_audio_plugin_client_AU_2.mm │ ├── include_juce_audio_plugin_client_AUv3.mm │ ├── include_juce_audio_plugin_client_LV2.cpp │ ├── include_juce_audio_plugin_client_LV2.mm │ ├── include_juce_audio_plugin_client_Standalone.cpp │ ├── include_juce_audio_plugin_client_Unity.cpp │ ├── include_juce_audio_plugin_client_VST2.cpp │ ├── include_juce_audio_plugin_client_VST2.mm │ ├── include_juce_audio_plugin_client_VST3.cpp │ ├── include_juce_audio_plugin_client_VST3.mm │ ├── include_juce_audio_processors.cpp │ ├── include_juce_audio_processors.mm │ ├── include_juce_audio_processors_ara.cpp │ ├── include_juce_audio_processors_lv2_libs.cpp │ ├── include_juce_audio_utils.cpp │ ├── include_juce_audio_utils.mm │ ├── include_juce_core.cpp │ ├── include_juce_core.mm │ ├── include_juce_cryptography.cpp │ ├── include_juce_cryptography.mm │ ├── include_juce_data_structures.cpp │ ├── include_juce_data_structures.mm │ ├── include_juce_dsp.cpp │ ├── include_juce_dsp.mm │ ├── include_juce_events.cpp │ ├── include_juce_events.mm │ ├── include_juce_graphics.cpp │ ├── include_juce_graphics.mm │ ├── include_juce_gui_basics.cpp │ ├── include_juce_gui_basics.mm │ ├── include_juce_gui_extra.cpp │ ├── include_juce_gui_extra.mm │ └── include_juce_osc.cpp ├── Resources │ ├── localhost.crt │ ├── localhost.key │ ├── ui_plugin_ws.html │ └── ui_plugin_ws_lazy.html ├── Source │ ├── FreesoundAPI.cpp │ ├── FreesoundAPI.h │ ├── PluginEditor.cpp │ ├── PluginEditor.h │ ├── PluginProcessor.cpp │ ├── PluginProcessor.h │ ├── ServerInterface.h │ ├── SourceSampler.cpp │ ├── SourceSampler.h │ ├── SourceSamplerSound.cpp │ ├── SourceSamplerSound.h │ ├── SourceSamplerSynthesiser.cpp │ ├── SourceSamplerSynthesiser.h │ ├── SourceSamplerVoice.cpp │ ├── SourceSamplerVoice.h │ ├── api_key.example.h │ ├── defines_source.h │ └── helpers_source.h ├── SourceSampler.jucer ├── data_for_code_gen.csv └── generate_code.py ├── SourceShepherdPush2Controller ├── app.py ├── definitions.py ├── modes │ ├── __init__.py │ ├── clip_edit_mode.py │ ├── clip_triggering_mode.py │ ├── generator_algorithms.py │ ├── main_controls_mode.py │ ├── melodic_mode.py │ ├── midi_cc_mode.py │ ├── preset_selection_mode.py │ ├── rhythmic_mode.py │ ├── settings_mode.py │ ├── slice_notes_mode.py │ ├── sound_edit_mode.py │ └── track_selection_mode.py ├── requirements.txt └── utils.py ├── docs ├── SOURCE diagram.key ├── SOURCE-complementary-UI.png ├── SOURCE-main-diagram-elk.png ├── SOURCE-main-diagram-plugin.png ├── SOURCE-photo.png ├── class_diagram.png ├── icon.png ├── logos.afdesign ├── ra_logo_web.png ├── simulator.png ├── source_600.png ├── source_logo.png ├── source_logo_headline.png └── upf_logo_web.png ├── elk_platform ├── build_system │ └── custom-esdk-launch.py ├── config │ ├── sensei.service │ ├── source.service │ ├── source_sensei_config.json │ ├── source_sushi_config.json │ └── sushi.service └── ui_app │ ├── elk_bridge.py │ ├── elk_ui_custom.py │ ├── freesound_interface.py │ ├── helpers.py │ ├── html │ ├── index.html │ ├── simulator.html │ └── usage_log.html │ ├── main │ ├── requirements.txt │ ├── resources │ ├── FuturaHeavyfont.ttf │ ├── LiberationMono-Regular.ttf │ ├── logo_oled_fs.png │ ├── logo_oled_ra.png │ ├── logo_oled_ra_b.png │ └── logo_oled_upf.png │ ├── sound_downloader.py │ ├── system_stats.py │ └── ui_state_manager │ ├── __init__.py │ ├── constants.py │ ├── manager.py │ ├── states.py │ ├── states_base.py │ ├── states_home.py │ └── states_sound_selected.py ├── fabfile.py ├── pysource ├── __init__.py ├── helpers.py ├── pysource.py └── state_synchronizer.py └── requirements_fabfile.txt /.gitignore: -------------------------------------------------------------------------------- 1 | start_source_shepherd.sh 2 | .DS_Store 3 | build 4 | xcuserdata/ 5 | *.pyc 6 | __pycache__ 7 | VST2_SDK 8 | api_key.h 9 | elk_platform/static 10 | freesound_api_key.py 11 | freesound_api_key_dev.py 12 | recent_queries_and_filters.json 13 | sound_usage_log 14 | tokens.json 15 | sm_settings.json 16 | last_commit_info 17 | frame/ 18 | .idea 19 | SourceSampler/Projucer alias 20 | SourceSampler/Builds/MacOSX/SourceSampler.xcodeproj/project.xcworkspace/contents.xcworkspacedata 21 | ui_plugin_copy.html 22 | BinaryData.cpp 23 | BinaryData.h 24 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "SourceSampler/3rdParty/JUCE"] 2 | path = SourceSampler/3rdParty/JUCE 3 | url = https://github.com/juce-framework/JUCE 4 | [submodule "SourceSampler/3rdParty/twine"] 5 | path = SourceSampler/3rdParty/twine 6 | url = https://github.com/elk-audio/twine 7 | [submodule "SourceSampler/3rdParty/ff_meters"] 8 | path = SourceSampler/3rdParty/ff_meters 9 | url = https://github.com/ffont/ff_meters.git 10 | [submodule "SourceSampler/3rdParty/Simple-WebSocket-Server"] 11 | path = SourceSampler/3rdParty/Simple-WebSocket-Server 12 | url = https://gitlab.com/eidheim/Simple-WebSocket-Server.git 13 | [submodule "SourceSampler/3rdParty/asio"] 14 | path = SourceSampler/3rdParty/asio 15 | url = https://github.com/chriskohlhoff/asio.git 16 | [submodule "SourceSampler/3rdParty/Simple-Web-Server"] 17 | path = SourceSampler/3rdParty/Simple-Web-Server 18 | url = https://gitlab.com/eidheim/Simple-Web-Server.git 19 | [submodule "SourceSampler/3rdParty/shepherd"] 20 | path = SourceSampler/3rdParty/shepherd 21 | url = https://github.com/ffont/shepherd.git 22 | [submodule "SourceShepherdPush2Controller/modes/GrooveTransformerExample"] 23 | path = SourceShepherdPush2Controller/modes/GrooveTransformerExample 24 | url = https://github.com/behzadhaki/GrooveTransformerExample.git 25 | [submodule "SourceSampler/3rdParty/signalsmith-stretch"] 26 | path = SourceSampler/3rdParty/signalsmith-stretch 27 | url = https://github.com/Signalsmith-Audio/signalsmith-stretch 28 | -------------------------------------------------------------------------------- /SourceSampler/Builds/ELKAudioOS/make_helpers/arch_detection.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ============================================================================== 3 | 4 | This file is part of the JUCE library. 5 | Copyright (c) 2022 - Raw Material Software Limited 6 | 7 | JUCE is an open source library subject to commercial or open-source 8 | licensing. 9 | 10 | By using JUCE, you agree to the terms of both the JUCE 7 End-User License 11 | Agreement and JUCE Privacy Policy. 12 | 13 | End User License Agreement: www.juce.com/juce-7-licence 14 | Privacy Policy: www.juce.com/juce-privacy-policy 15 | 16 | Or: You may also use this code under the terms of the GPL v3 (see 17 | www.gnu.org/licenses). 18 | 19 | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER 20 | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE 21 | DISCLAIMED. 22 | 23 | ============================================================================== 24 | */ 25 | 26 | #if defined(__arm__) || defined(__TARGET_ARCH_ARM) || defined(_M_ARM) || defined(_M_ARM64) || defined(__aarch64__) || defined(__ARM64__) 27 | 28 | #if defined(_M_ARM64) || defined(__aarch64__) || defined(__ARM64__) 29 | #error JUCE_ARCH aarch64 30 | #elif (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM == 8) || defined(__ARMv8__) || defined(__ARMv8_A__) 31 | #error JUCE_ARCH armv8l 32 | #elif (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM == 7) || defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) || defined(_ARM_ARCH_7) || defined(__CORE_CORTEXA__) 33 | #error JUCE_ARCH armv7l 34 | #elif (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM == 6) || defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6M__) 35 | #error JUCE_ARCH armv6l 36 | #elif (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM == 5) || defined(__ARM_ARCH_5TEJ__) 37 | #error JUCE_ARCH armv5l 38 | #else 39 | #error JUCE_ARCH arm 40 | #endif 41 | 42 | #elif defined(__i386) || defined(__i386__) || defined(_M_IX86) 43 | 44 | #error JUCE_ARCH i386 45 | 46 | #elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64) 47 | 48 | #error JUCE_ARCH x86_64 49 | 50 | #elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64) 51 | 52 | #error JUCE_ARCH ia64 53 | 54 | #elif defined(__mips) || defined(__mips__) || defined(_M_MRX000) 55 | 56 | #if defined(_MIPS_ARCH_MIPS64) || defined(__mips64) 57 | #error JUCE_ARCH mips64 58 | #else 59 | #error JUCE_ARCH mips 60 | #endif 61 | 62 | #elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__) || defined(_ARCH_COM) || defined(_ARCH_PWR) || defined(_ARCH_PPC) || defined(_M_MPPC) || defined(_M_PPC) 63 | 64 | #if defined(__ppc64__) || defined(__powerpc64__) || defined(__64BIT__) 65 | #error JUCE_ARCH ppc64 66 | #else 67 | #error JUCE_ARCH ppc 68 | #endif 69 | 70 | #elif defined(__riscv) 71 | 72 | #if __riscv_xlen == 64 73 | #error JUCE_ARCH riscv64 74 | #else 75 | #error JUCE_ARCH riscv 76 | #endif 77 | 78 | #else 79 | 80 | #error JUCE_ARCH unknown 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /SourceSampler/Builds/ELKAudioOS/make_helpers/juce_LinuxSubprocessHelper.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ============================================================================== 3 | 4 | This file is part of the JUCE library. 5 | Copyright (c) 2022 - Raw Material Software Limited 6 | 7 | JUCE is an open source library subject to commercial or open-source 8 | licensing. 9 | 10 | By using JUCE, you agree to the terms of both the JUCE 7 End-User License 11 | Agreement and JUCE Privacy Policy. 12 | 13 | End User License Agreement: www.juce.com/juce-7-licence 14 | Privacy Policy: www.juce.com/juce-privacy-policy 15 | 16 | Or: You may also use this code under the terms of the GPL v3 (see 17 | www.gnu.org/licenses). 18 | 19 | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER 20 | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE 21 | DISCLAIMED. 22 | 23 | ============================================================================== 24 | */ 25 | 26 | #include 27 | 28 | int main (int argc, const char* const* argv) 29 | { 30 | if (argc >= 3) 31 | if (auto* handle = dlopen (argv[1], RTLD_LAZY)) 32 | if (auto* function = reinterpret_cast (dlsym (handle, argv[2]))) 33 | return function (argc - 3, argv + 3); 34 | 35 | return 1; 36 | } 37 | -------------------------------------------------------------------------------- /SourceSampler/Builds/LinuxMakefile/make_helpers/arch_detection.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ============================================================================== 3 | 4 | This file is part of the JUCE library. 5 | Copyright (c) 2022 - Raw Material Software Limited 6 | 7 | JUCE is an open source library subject to commercial or open-source 8 | licensing. 9 | 10 | By using JUCE, you agree to the terms of both the JUCE 7 End-User License 11 | Agreement and JUCE Privacy Policy. 12 | 13 | End User License Agreement: www.juce.com/juce-7-licence 14 | Privacy Policy: www.juce.com/juce-privacy-policy 15 | 16 | Or: You may also use this code under the terms of the GPL v3 (see 17 | www.gnu.org/licenses). 18 | 19 | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER 20 | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE 21 | DISCLAIMED. 22 | 23 | ============================================================================== 24 | */ 25 | 26 | #if defined(__arm__) || defined(__TARGET_ARCH_ARM) || defined(_M_ARM) || defined(_M_ARM64) || defined(__aarch64__) || defined(__ARM64__) 27 | 28 | #if defined(_M_ARM64) || defined(__aarch64__) || defined(__ARM64__) 29 | #error JUCE_ARCH aarch64 30 | #elif (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM == 8) || defined(__ARMv8__) || defined(__ARMv8_A__) 31 | #error JUCE_ARCH armv8l 32 | #elif (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM == 7) || defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) || defined(_ARM_ARCH_7) || defined(__CORE_CORTEXA__) 33 | #error JUCE_ARCH armv7l 34 | #elif (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM == 6) || defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6M__) 35 | #error JUCE_ARCH armv6l 36 | #elif (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM == 5) || defined(__ARM_ARCH_5TEJ__) 37 | #error JUCE_ARCH armv5l 38 | #else 39 | #error JUCE_ARCH arm 40 | #endif 41 | 42 | #elif defined(__i386) || defined(__i386__) || defined(_M_IX86) 43 | 44 | #error JUCE_ARCH i386 45 | 46 | #elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64) 47 | 48 | #error JUCE_ARCH x86_64 49 | 50 | #elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64) 51 | 52 | #error JUCE_ARCH ia64 53 | 54 | #elif defined(__mips) || defined(__mips__) || defined(_M_MRX000) 55 | 56 | #if defined(_MIPS_ARCH_MIPS64) || defined(__mips64) 57 | #error JUCE_ARCH mips64 58 | #else 59 | #error JUCE_ARCH mips 60 | #endif 61 | 62 | #elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__) || defined(_ARCH_COM) || defined(_ARCH_PWR) || defined(_ARCH_PPC) || defined(_M_MPPC) || defined(_M_PPC) 63 | 64 | #if defined(__ppc64__) || defined(__powerpc64__) || defined(__64BIT__) 65 | #error JUCE_ARCH ppc64 66 | #else 67 | #error JUCE_ARCH ppc 68 | #endif 69 | 70 | #elif defined(__riscv) 71 | 72 | #if __riscv_xlen == 64 73 | #error JUCE_ARCH riscv64 74 | #else 75 | #error JUCE_ARCH riscv 76 | #endif 77 | 78 | #else 79 | 80 | #error JUCE_ARCH unknown 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /SourceSampler/Builds/LinuxMakefile/make_helpers/juce_LinuxSubprocessHelper.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ============================================================================== 3 | 4 | This file is part of the JUCE library. 5 | Copyright (c) 2022 - Raw Material Software Limited 6 | 7 | JUCE is an open source library subject to commercial or open-source 8 | licensing. 9 | 10 | By using JUCE, you agree to the terms of both the JUCE 7 End-User License 11 | Agreement and JUCE Privacy Policy. 12 | 13 | End User License Agreement: www.juce.com/juce-7-licence 14 | Privacy Policy: www.juce.com/juce-privacy-policy 15 | 16 | Or: You may also use this code under the terms of the GPL v3 (see 17 | www.gnu.org/licenses). 18 | 19 | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER 20 | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE 21 | DISCLAIMED. 22 | 23 | ============================================================================== 24 | */ 25 | 26 | #include 27 | 28 | int main (int argc, const char* const* argv) 29 | { 30 | if (argc >= 3) 31 | if (auto* handle = dlopen (argv[1], RTLD_LAZY)) 32 | if (auto* function = reinterpret_cast (dlsym (handle, argv[2]))) 33 | return function (argc - 3, argv + 3); 34 | 35 | return 1; 36 | } 37 | -------------------------------------------------------------------------------- /SourceSampler/Builds/MacOSX/AUv3_AppExtension.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SourceSampler/Builds/MacOSX/Icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/MacOSX/Icon.icns -------------------------------------------------------------------------------- /SourceSampler/Builds/MacOSX/Info-AU.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | NSAppTransportSecurity 7 | 8 | NSAllowsArbitraryLoads 9 | 10 | NSAllowsArbitraryLoadsForMedia 11 | 12 | NSAllowsArbitraryLoadsInWebContent 13 | 14 | NSAllowsLocalNetworking 15 | 16 | 17 | CFBundleExecutable 18 | ${EXECUTABLE_NAME} 19 | CFBundleIconFile 20 | Icon.icns 21 | CFBundleIdentifier 22 | com.RitaAurora.SourceSampler 23 | CFBundleName 24 | SourceSampler 25 | CFBundleDisplayName 26 | SourceSampler 27 | CFBundlePackageType 28 | BNDL 29 | CFBundleSignature 30 | ???? 31 | CFBundleShortVersionString 32 | 0.7 33 | CFBundleVersion 34 | 0.7 35 | NSHumanReadableCopyright 36 | 37 | NSHighResolutionCapable 38 | 39 | AudioComponents 40 | 41 | 42 | name 43 | Music Technology Group: SourceSampler 44 | description 45 | SourceSampler 46 | factoryFunction 47 | SourceSamplerAUFactory 48 | manufacturer 49 | RaAu 50 | type 51 | aumu 52 | subtype 53 | SoSa 54 | version 55 | 1792 56 | resourceUsage 57 | 58 | network.client 59 | 60 | temporary-exception.files.all.read-write 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /SourceSampler/Builds/MacOSX/Info-AUv3_AppExtension.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | NSAppTransportSecurity 7 | 8 | NSAllowsArbitraryLoads 9 | 10 | NSAllowsArbitraryLoadsForMedia 11 | 12 | NSAllowsArbitraryLoadsInWebContent 13 | 14 | NSAllowsLocalNetworking 15 | 16 | 17 | CFBundleExecutable 18 | ${EXECUTABLE_NAME} 19 | CFBundleIconFile 20 | Icon.icns 21 | CFBundleIdentifier 22 | com.RitaAurora.SourceSampler.SourceSamplerAUv3 23 | CFBundleName 24 | SourceSampler 25 | CFBundleDisplayName 26 | SourceSampler 27 | CFBundlePackageType 28 | XPC! 29 | CFBundleSignature 30 | ???? 31 | CFBundleShortVersionString 32 | 0.7 33 | CFBundleVersion 34 | 0.7 35 | NSHumanReadableCopyright 36 | 37 | NSHighResolutionCapable 38 | 39 | NSExtension 40 | 41 | NSExtensionPrincipalClass 42 | SourceSamplerAUFactoryAUv3 43 | NSExtensionPointIdentifier 44 | com.apple.AudioUnit-UI 45 | NSExtensionAttributes 46 | 47 | AudioComponents 48 | 49 | 50 | name 51 | Music Technology Group: SourceSampler 52 | description 53 | SourceSampler 54 | factoryFunction 55 | SourceSamplerAUFactoryAUv3 56 | manufacturer 57 | RaAu 58 | type 59 | aumu 60 | subtype 61 | SoSa 62 | version 63 | 1792 64 | sandboxSafe 65 | 66 | tags 67 | 68 | Synth 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /SourceSampler/Builds/MacOSX/Info-Standalone_Plugin.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | NSAppTransportSecurity 7 | 8 | NSAllowsArbitraryLoads 9 | 10 | NSAllowsArbitraryLoadsForMedia 11 | 12 | NSAllowsArbitraryLoadsInWebContent 13 | 14 | NSAllowsLocalNetworking 15 | 16 | 17 | CFBundleExecutable 18 | ${EXECUTABLE_NAME} 19 | CFBundleIconFile 20 | Icon.icns 21 | CFBundleIdentifier 22 | com.RitaAurora.SourceSampler 23 | CFBundleName 24 | SourceSampler 25 | CFBundleDisplayName 26 | SourceSampler 27 | CFBundlePackageType 28 | APPL 29 | CFBundleSignature 30 | ???? 31 | CFBundleShortVersionString 32 | 0.7 33 | CFBundleVersion 34 | 0.7 35 | NSHumanReadableCopyright 36 | 37 | NSHighResolutionCapable 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /SourceSampler/Builds/MacOSX/Info-VST.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | NSAppTransportSecurity 7 | 8 | NSAllowsArbitraryLoads 9 | 10 | NSAllowsArbitraryLoadsForMedia 11 | 12 | NSAllowsArbitraryLoadsInWebContent 13 | 14 | NSAllowsLocalNetworking 15 | 16 | 17 | CFBundleExecutable 18 | ${EXECUTABLE_NAME} 19 | CFBundleIconFile 20 | Icon.icns 21 | CFBundleIdentifier 22 | com.RitaAurora.SourceSampler 23 | CFBundleName 24 | SourceSampler 25 | CFBundleDisplayName 26 | SourceSampler 27 | CFBundlePackageType 28 | BNDL 29 | CFBundleSignature 30 | ???? 31 | CFBundleShortVersionString 32 | 0.7 33 | CFBundleVersion 34 | 0.7 35 | NSHumanReadableCopyright 36 | 37 | NSHighResolutionCapable 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /SourceSampler/Builds/MacOSX/Info-VST3.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | NSAppTransportSecurity 7 | 8 | NSAllowsArbitraryLoads 9 | 10 | NSAllowsArbitraryLoadsForMedia 11 | 12 | NSAllowsArbitraryLoadsInWebContent 13 | 14 | NSAllowsLocalNetworking 15 | 16 | 17 | CFBundleExecutable 18 | ${EXECUTABLE_NAME} 19 | CFBundleIconFile 20 | Icon.icns 21 | CFBundleIdentifier 22 | com.RitaAurora.SourceSampler 23 | CFBundleName 24 | SourceSampler 25 | CFBundleDisplayName 26 | SourceSampler 27 | CFBundlePackageType 28 | BNDL 29 | CFBundleSignature 30 | ???? 31 | CFBundleShortVersionString 32 | 0.7 33 | CFBundleVersion 34 | 0.7 35 | NSHumanReadableCopyright 36 | 37 | NSHighResolutionCapable 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /SourceSampler/Builds/MacOSX/Info-VST3_Manifest_Helper.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | NSAppTransportSecurity 7 | 8 | NSAllowsArbitraryLoads 9 | 10 | NSAllowsArbitraryLoadsForMedia 11 | 12 | NSAllowsArbitraryLoadsInWebContent 13 | 14 | NSAllowsLocalNetworking 15 | 16 | 17 | CFBundleExecutable 18 | ${EXECUTABLE_NAME} 19 | CFBundleIconFile 20 | Icon.icns 21 | CFBundleIdentifier 22 | com.RitaAurora.SourceSampler 23 | CFBundleName 24 | SourceSampler 25 | CFBundleDisplayName 26 | SourceSampler 27 | CFBundlePackageType 28 | 29 | CFBundleSignature 30 | 31 | CFBundleShortVersionString 32 | 0.7 33 | CFBundleVersion 34 | 0.7 35 | NSHumanReadableCopyright 36 | 37 | NSHighResolutionCapable 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /SourceSampler/Builds/MacOSX/RecentFilesMenuTemplate.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/MacOSX/RecentFilesMenuTemplate.nib -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/AUv3_AppExtension.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.application-groups 6 | 7 | group.ritaiaurora.source 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/All.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.application-groups 6 | 7 | group.ritaiaurora.source 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/Icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/Icon.icns -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/Info-AUv3_AppExtension.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | NSAppTransportSecurity 7 | 8 | NSAllowsArbitraryLoads 9 | 10 | NSAllowsArbitraryLoadsForMedia 11 | 12 | NSAllowsArbitraryLoadsInWebContent 13 | 14 | NSAllowsLocalNetworking 15 | 16 | 17 | LSRequiresIPhoneOS 18 | 19 | UIViewControllerBasedStatusBarAppearance 20 | 21 | UILaunchStoryboardName 22 | LaunchScreen 23 | CFBundleExecutable 24 | ${EXECUTABLE_NAME} 25 | CFBundleIdentifier 26 | com.RitaAurora.SourceSampler.SourceSamplerAUv3 27 | CFBundleName 28 | SourceSampler 29 | CFBundleDisplayName 30 | SourceSampler 31 | CFBundlePackageType 32 | XPC! 33 | CFBundleSignature 34 | ???? 35 | CFBundleShortVersionString 36 | 0.7 37 | CFBundleVersion 38 | 0.7 39 | NSHumanReadableCopyright 40 | 41 | NSHighResolutionCapable 42 | 43 | UISupportsDocumentBrowser 44 | 45 | NSExtension 46 | 47 | NSExtensionPrincipalClass 48 | SourceSamplerAUFactoryAUv3 49 | NSExtensionPointIdentifier 50 | com.apple.AudioUnit-UI 51 | NSExtensionAttributes 52 | 53 | AudioComponents 54 | 55 | 56 | name 57 | Music Technology Group: SourceSampler 58 | description 59 | SourceSampler 60 | factoryFunction 61 | SourceSamplerAUFactoryAUv3 62 | manufacturer 63 | RaAu 64 | type 65 | aumu 66 | subtype 67 | SoSa 68 | version 69 | 1792 70 | sandboxSafe 71 | 72 | tags 73 | 74 | Synth 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/Info-Standalone_Plugin.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | NSAppTransportSecurity 7 | 8 | NSAllowsArbitraryLoads 9 | 10 | NSAllowsArbitraryLoadsForMedia 11 | 12 | NSAllowsArbitraryLoadsInWebContent 13 | 14 | NSAllowsLocalNetworking 15 | 16 | 17 | LSRequiresIPhoneOS 18 | 19 | UIViewControllerBasedStatusBarAppearance 20 | 21 | UILaunchStoryboardName 22 | LaunchScreen 23 | CFBundleExecutable 24 | ${EXECUTABLE_NAME} 25 | CFBundleIdentifier 26 | com.RitaAurora.SourceSampler 27 | CFBundleName 28 | SourceSampler 29 | CFBundleDisplayName 30 | SourceSampler 31 | CFBundlePackageType 32 | APPL 33 | CFBundleSignature 34 | ???? 35 | CFBundleShortVersionString 36 | 0.7 37 | CFBundleVersion 38 | 0.7 39 | NSHumanReadableCopyright 40 | 41 | NSHighResolutionCapable 42 | 43 | UISupportsDocumentBrowser 44 | 45 | UIRequiresFullScreen 46 | 47 | UISupportedInterfaceOrientations 48 | 49 | UIInterfaceOrientationPortrait 50 | UIInterfaceOrientationLandscapeLeft 51 | UIInterfaceOrientationLandscapeRight 52 | 53 | UIBackgroundModes 54 | 55 | audio 56 | bluetooth-central 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/Shared_Code.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.application-groups 6 | 7 | group.ritaiaurora.source 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler.xcodeproj/xcshareddata/xcschemes/SourceSampler - AUv3 AppExtension.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 6 | 9 | 10 | 16 | 22 | 23 | 24 | 30 | 36 | 37 | 38 | 39 | 40 | 46 | 47 | 59 | 61 | 67 | 68 | 69 | 70 | 77 | 79 | 85 | 86 | 87 | 88 | 90 | 91 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler.xcodeproj/xcshareddata/xcschemes/SourceSampler - All.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 42 | 43 | 49 | 50 | 56 | 57 | 58 | 59 | 61 | 62 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler.xcodeproj/xcshareddata/xcschemes/SourceSampler - Shared Code.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 42 | 43 | 49 | 50 | 56 | 57 | 58 | 59 | 61 | 62 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler.xcodeproj/xcshareddata/xcschemes/SourceSampler - Standalone Plugin.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 42 | 44 | 50 | 51 | 52 | 53 | 59 | 61 | 67 | 68 | 69 | 70 | 72 | 73 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "idiom": "iphone", 5 | "size": "20x20", 6 | "filename": "Icon-Notification-20@2x.png", 7 | "scale": "2x" 8 | }, 9 | { 10 | "idiom": "iphone", 11 | "size": "20x20", 12 | "filename": "Icon-Notification-20@3x.png", 13 | "scale": "3x" 14 | }, 15 | { 16 | "idiom": "iphone", 17 | "size": "29x29", 18 | "filename": "Icon-29.png", 19 | "scale": "1x" 20 | }, 21 | { 22 | "idiom": "iphone", 23 | "size": "29x29", 24 | "filename": "Icon-29@2x.png", 25 | "scale": "2x" 26 | }, 27 | { 28 | "idiom": "iphone", 29 | "size": "29x29", 30 | "filename": "Icon-29@3x.png", 31 | "scale": "3x" 32 | }, 33 | { 34 | "idiom": "iphone", 35 | "size": "40x40", 36 | "filename": "Icon-Spotlight-40@2x.png", 37 | "scale": "2x" 38 | }, 39 | { 40 | "idiom": "iphone", 41 | "size": "40x40", 42 | "filename": "Icon-Spotlight-40@3x.png", 43 | "scale": "3x" 44 | }, 45 | { 46 | "idiom": "iphone", 47 | "size": "60x60", 48 | "filename": "Icon-60@2x.png", 49 | "scale": "2x" 50 | }, 51 | { 52 | "idiom": "iphone", 53 | "size": "60x60", 54 | "filename": "Icon-@3x.png", 55 | "scale": "3x" 56 | }, 57 | { 58 | "idiom": "ipad", 59 | "size": "20x20", 60 | "filename": "Icon-Notifications-20.png", 61 | "scale": "1x" 62 | }, 63 | { 64 | "idiom": "ipad", 65 | "size": "20x20", 66 | "filename": "Icon-Notifications-20@2x.png", 67 | "scale": "2x" 68 | }, 69 | { 70 | "idiom": "ipad", 71 | "size": "29x29", 72 | "filename": "Icon-Small-1.png", 73 | "scale": "1x" 74 | }, 75 | { 76 | "idiom": "ipad", 77 | "size": "29x29", 78 | "filename": "Icon-Small@2x-1.png", 79 | "scale": "2x" 80 | }, 81 | { 82 | "idiom": "ipad", 83 | "size": "40x40", 84 | "filename": "Icon-Spotlight-40.png", 85 | "scale": "1x" 86 | }, 87 | { 88 | "idiom": "ipad", 89 | "size": "40x40", 90 | "filename": "Icon-Spotlight-40@2x-1.png", 91 | "scale": "2x" 92 | }, 93 | { 94 | "idiom": "ipad", 95 | "size": "76x76", 96 | "filename": "Icon-76.png", 97 | "scale": "1x" 98 | }, 99 | { 100 | "idiom": "ipad", 101 | "size": "76x76", 102 | "filename": "Icon-76@2x.png", 103 | "scale": "2x" 104 | }, 105 | { 106 | "idiom": "ipad", 107 | "size": "83.5x83.5", 108 | "filename": "Icon-83.5@2x.png", 109 | "scale": "2x" 110 | }, 111 | { 112 | "idiom": "ios-marketing", 113 | "size": "1024x1024", 114 | "filename": "Icon-AppStore-1024.png", 115 | "scale": "1x" 116 | } 117 | ], 118 | "info": { 119 | "version": 1, 120 | "author": "xcode" 121 | } 122 | } -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-29.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-29@2x.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-29@3x.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-72.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-72@2x.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-76.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-83.5@2x.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-@3x.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-AppStore-1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-AppStore-1024.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-Notification-20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-Notification-20@2x.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-Notification-20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-Notification-20@3x.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-Notifications-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-Notifications-20.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-Notifications-20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-Notifications-20@2x.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-Small-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-Small-1.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-Small-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-Small-50.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-Small-50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-Small-50@2x.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-Small@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-Small@2x-1.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-Spotlight-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-Spotlight-40.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-Spotlight-40@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-Spotlight-40@2x-1.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-Spotlight-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-Spotlight-40@2x.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-Spotlight-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon-Spotlight-40@3x.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/AppIcon.appiconset/Icon@2x.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "orientation": "portrait", 5 | "idiom": "iphone", 6 | "extent": "full-screen", 7 | "minimum-system-version": "7.0", 8 | "scale": "2x", 9 | "filename": "LaunchImage-iphone-2x.png" 10 | }, 11 | { 12 | "orientation": "portrait", 13 | "idiom": "iphone", 14 | "extent": "full-screen", 15 | "minimum-system-version": "7.0", 16 | "scale": "2x", 17 | "filename": "LaunchImage-iphone-retina4.png", 18 | "subtype": "retina4" 19 | }, 20 | { 21 | "orientation": "portrait", 22 | "idiom": "ipad", 23 | "extent": "full-screen", 24 | "minimum-system-version": "7.0", 25 | "scale": "1x", 26 | "filename": "LaunchImage-ipad-portrait-1x.png" 27 | }, 28 | { 29 | "orientation": "landscape", 30 | "idiom": "ipad", 31 | "extent": "full-screen", 32 | "minimum-system-version": "7.0", 33 | "scale": "1x", 34 | "filename": "LaunchImage-ipad-landscape-1x.png" 35 | }, 36 | { 37 | "orientation": "portrait", 38 | "idiom": "ipad", 39 | "extent": "full-screen", 40 | "minimum-system-version": "7.0", 41 | "scale": "2x", 42 | "filename": "LaunchImage-ipad-portrait-2x.png" 43 | }, 44 | { 45 | "orientation": "landscape", 46 | "idiom": "ipad", 47 | "extent": "full-screen", 48 | "minimum-system-version": "7.0", 49 | "scale": "2x", 50 | "filename": "LaunchImage-ipad-landscape-2x.png" 51 | } 52 | ], 53 | "info": { 54 | "version": 1, 55 | "author": "xcode" 56 | } 57 | } -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/LaunchImage.launchimage/LaunchImage-ipad-landscape-1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/LaunchImage.launchimage/LaunchImage-ipad-landscape-1x.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/LaunchImage.launchimage/LaunchImage-ipad-landscape-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/LaunchImage.launchimage/LaunchImage-ipad-landscape-2x.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/LaunchImage.launchimage/LaunchImage-ipad-portrait-1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/LaunchImage.launchimage/LaunchImage-ipad-portrait-1x.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/LaunchImage.launchimage/LaunchImage-ipad-portrait-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/LaunchImage.launchimage/LaunchImage-ipad-portrait-2x.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/LaunchImage.launchimage/LaunchImage-iphone-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/LaunchImage.launchimage/LaunchImage-iphone-2x.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/LaunchImage.launchimage/LaunchImage-iphone-retina4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceSampler/Builds/iOS/SourceSampler/Images.xcassets/LaunchImage.launchimage/LaunchImage-iphone-retina4.png -------------------------------------------------------------------------------- /SourceSampler/Builds/iOS/Standalone_Plugin.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.application-groups 6 | 7 | group.ritaiaurora.source 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/JuceHeader.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | This is the header file that your files should include in order to get all the 7 | JUCE library headers. You should avoid including the JUCE headers directly in 8 | your own source files, because that wouldn't pick up the correct configuration 9 | options for your app. 10 | 11 | */ 12 | 13 | #pragma once 14 | 15 | #include "AppConfig.h" 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | 34 | #if defined (JUCE_PROJUCER_VERSION) && JUCE_PROJUCER_VERSION < JUCE_VERSION 35 | /** If you've hit this error then the version of the Projucer that was used to generate this project is 36 | older than the version of the JUCE modules being included. To fix this error, re-save your project 37 | using the latest version of the Projucer or, if you aren't using the Projucer to manage your project, 38 | remove the JUCE_PROJUCER_VERSION define. 39 | */ 40 | #error "This project was last saved using an outdated version of the Projucer! Re-save this project with the latest version to fix this error." 41 | #endif 42 | 43 | 44 | #if ! JUCE_DONT_DECLARE_PROJECTINFO 45 | namespace ProjectInfo 46 | { 47 | const char* const projectName = "SourceSampler"; 48 | const char* const companyName = "Music Technology Group"; 49 | const char* const versionString = "0.7"; 50 | const int versionNumber = 0x700; 51 | } 52 | #endif 53 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/JucePluginDefines.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #pragma once 9 | 10 | //============================================================================== 11 | // Audio plugin settings.. 12 | 13 | #ifndef JucePlugin_Build_VST 14 | #define JucePlugin_Build_VST 0 15 | #endif 16 | #ifndef JucePlugin_Build_VST3 17 | #define JucePlugin_Build_VST3 0 18 | #endif 19 | #ifndef JucePlugin_Build_AU 20 | #define JucePlugin_Build_AU 0 21 | #endif 22 | #ifndef JucePlugin_Build_AUv3 23 | #define JucePlugin_Build_AUv3 1 24 | #endif 25 | #ifndef JucePlugin_Build_AAX 26 | #define JucePlugin_Build_AAX 0 27 | #endif 28 | #ifndef JucePlugin_Build_Standalone 29 | #define JucePlugin_Build_Standalone 1 30 | #endif 31 | #ifndef JucePlugin_Build_Unity 32 | #define JucePlugin_Build_Unity 0 33 | #endif 34 | #ifndef JucePlugin_Build_LV2 35 | #define JucePlugin_Build_LV2 0 36 | #endif 37 | #ifndef JucePlugin_Enable_IAA 38 | #define JucePlugin_Enable_IAA 0 39 | #endif 40 | #ifndef JucePlugin_Enable_ARA 41 | #define JucePlugin_Enable_ARA 0 42 | #endif 43 | #ifndef JucePlugin_Name 44 | #define JucePlugin_Name "SourceSampler" 45 | #endif 46 | #ifndef JucePlugin_Desc 47 | #define JucePlugin_Desc "SourceSampler" 48 | #endif 49 | #ifndef JucePlugin_Manufacturer 50 | #define JucePlugin_Manufacturer "Music Technology Group" 51 | #endif 52 | #ifndef JucePlugin_ManufacturerWebsite 53 | #define JucePlugin_ManufacturerWebsite "http://mtg.upf.edu" 54 | #endif 55 | #ifndef JucePlugin_ManufacturerEmail 56 | #define JucePlugin_ManufacturerEmail "frederic.font@upf.edu" 57 | #endif 58 | #ifndef JucePlugin_ManufacturerCode 59 | #define JucePlugin_ManufacturerCode 0x52614175 60 | #endif 61 | #ifndef JucePlugin_PluginCode 62 | #define JucePlugin_PluginCode 0x536f5361 63 | #endif 64 | #ifndef JucePlugin_IsSynth 65 | #define JucePlugin_IsSynth 1 66 | #endif 67 | #ifndef JucePlugin_WantsMidiInput 68 | #define JucePlugin_WantsMidiInput 1 69 | #endif 70 | #ifndef JucePlugin_ProducesMidiOutput 71 | #define JucePlugin_ProducesMidiOutput 1 72 | #endif 73 | #ifndef JucePlugin_IsMidiEffect 74 | #define JucePlugin_IsMidiEffect 0 75 | #endif 76 | #ifndef JucePlugin_EditorRequiresKeyboardFocus 77 | #define JucePlugin_EditorRequiresKeyboardFocus 0 78 | #endif 79 | #ifndef JucePlugin_Version 80 | #define JucePlugin_Version 0.7 81 | #endif 82 | #ifndef JucePlugin_VersionCode 83 | #define JucePlugin_VersionCode 0x700 84 | #endif 85 | #ifndef JucePlugin_VersionString 86 | #define JucePlugin_VersionString "0.7" 87 | #endif 88 | #ifndef JucePlugin_VSTUniqueID 89 | #define JucePlugin_VSTUniqueID JucePlugin_PluginCode 90 | #endif 91 | #ifndef JucePlugin_VSTCategory 92 | #define JucePlugin_VSTCategory kPlugCategSynth 93 | #endif 94 | #ifndef JucePlugin_Vst3Category 95 | #define JucePlugin_Vst3Category "Instrument|Synth" 96 | #endif 97 | #ifndef JucePlugin_AUMainType 98 | #define JucePlugin_AUMainType 'aumu' 99 | #endif 100 | #ifndef JucePlugin_AUSubType 101 | #define JucePlugin_AUSubType JucePlugin_PluginCode 102 | #endif 103 | #ifndef JucePlugin_AUExportPrefix 104 | #define JucePlugin_AUExportPrefix SourceSamplerAU 105 | #endif 106 | #ifndef JucePlugin_AUExportPrefixQuoted 107 | #define JucePlugin_AUExportPrefixQuoted "SourceSamplerAU" 108 | #endif 109 | #ifndef JucePlugin_AUManufacturerCode 110 | #define JucePlugin_AUManufacturerCode JucePlugin_ManufacturerCode 111 | #endif 112 | #ifndef JucePlugin_CFBundleIdentifier 113 | #define JucePlugin_CFBundleIdentifier com.RitaAurora.SourceSampler 114 | #endif 115 | #ifndef JucePlugin_AAXIdentifier 116 | #define JucePlugin_AAXIdentifier com.MusicTechnologyGroup.SourceSampler 117 | #endif 118 | #ifndef JucePlugin_AAXManufacturerCode 119 | #define JucePlugin_AAXManufacturerCode JucePlugin_ManufacturerCode 120 | #endif 121 | #ifndef JucePlugin_AAXProductId 122 | #define JucePlugin_AAXProductId JucePlugin_PluginCode 123 | #endif 124 | #ifndef JucePlugin_AAXCategory 125 | #define JucePlugin_AAXCategory 2048 126 | #endif 127 | #ifndef JucePlugin_AAXDisableBypass 128 | #define JucePlugin_AAXDisableBypass 0 129 | #endif 130 | #ifndef JucePlugin_AAXDisableMultiMono 131 | #define JucePlugin_AAXDisableMultiMono 0 132 | #endif 133 | #ifndef JucePlugin_IAAType 134 | #define JucePlugin_IAAType 0x61757269 135 | #endif 136 | #ifndef JucePlugin_IAASubType 137 | #define JucePlugin_IAASubType JucePlugin_PluginCode 138 | #endif 139 | #ifndef JucePlugin_IAAName 140 | #define JucePlugin_IAAName "Music Technology Group: SourceSampler" 141 | #endif 142 | #ifndef JucePlugin_VSTNumMidiInputs 143 | #define JucePlugin_VSTNumMidiInputs 16 144 | #endif 145 | #ifndef JucePlugin_VSTNumMidiOutputs 146 | #define JucePlugin_VSTNumMidiOutputs 16 147 | #endif 148 | #ifndef JucePlugin_ARAContentTypes 149 | #define JucePlugin_ARAContentTypes 0 150 | #endif 151 | #ifndef JucePlugin_ARATransformationFlags 152 | #define JucePlugin_ARATransformationFlags 0 153 | #endif 154 | #ifndef JucePlugin_ARAFactoryID 155 | #define JucePlugin_ARAFactoryID "com.MusicTechnologyGroup.SourceSampler.factory" 156 | #endif 157 | #ifndef JucePlugin_ARADocumentArchiveID 158 | #define JucePlugin_ARADocumentArchiveID "com.MusicTechnologyGroup.SourceSampler.aradocumentarchive.0.7" 159 | #endif 160 | #ifndef JucePlugin_ARACompatibleArchiveIDs 161 | #define JucePlugin_ARACompatibleArchiveIDs "" 162 | #endif 163 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/ReadMe.txt: -------------------------------------------------------------------------------- 1 | 2 | Important Note!! 3 | ================ 4 | 5 | The purpose of this folder is to contain files that are auto-generated by the Projucer, 6 | and ALL files in this folder will be mercilessly DELETED and completely re-written whenever 7 | the Projucer saves your project. 8 | 9 | Therefore, it's a bad idea to make any manual changes to the files in here, or to 10 | put any of your own files in here if you don't want to lose them. (Of course you may choose 11 | to add the folder's contents to your version-control system so that you can re-merge your own 12 | modifications after the Projucer has saved its changes). 13 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_audio_basics.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_audio_basics.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_audio_devices.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_audio_devices.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_audio_formats.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_audio_formats.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_audio_plugin_client_AAX.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_audio_plugin_client_AAX.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_audio_plugin_client_AAX_utils.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_audio_plugin_client_ARA.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_audio_plugin_client_AU_1.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_audio_plugin_client_AU_2.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_audio_plugin_client_AUv3.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_audio_plugin_client_LV2.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_audio_plugin_client_LV2.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_audio_plugin_client_Standalone.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_audio_plugin_client_Unity.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_audio_plugin_client_VST2.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_audio_plugin_client_VST2.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_audio_plugin_client_VST3.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_audio_plugin_client_VST3.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_audio_processors.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_audio_processors.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_audio_processors_ara.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_audio_processors_lv2_libs.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_audio_utils.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_audio_utils.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_core.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_core.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_cryptography.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_cryptography.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_data_structures.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_data_structures.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_dsp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_dsp.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_events.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_events.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_graphics.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_graphics.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_gui_basics.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_gui_basics.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_gui_extra.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_gui_extra.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/JuceLibraryCode/include_juce_osc.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /SourceSampler/Resources/localhost.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIC5TCCAc2gAwIBAgIJALieRiCs2CKJMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV 3 | BAMMCWxvY2FsaG9zdDAeFw0yMDA5MjAxNTE5NThaFw0yMDEwMjAxNTE5NThaMBQx 4 | EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC 5 | ggEBALXLAtyKRQfO7/NkEivn4JFzPXvpEKF+Yg3tXJdw3kUIoxBppyxQMwxKQvmw 6 | fe5K2XYEvFysHYJ/CBzylg0x4ggTV+wyJOHjWOefOOtNBY/4mtP6T0uoeNvQVL6z 7 | NxMYUgarVyg5YrQLUBU0n8WmEnjLDLVdMbypAiulaBQfVrh2YOxwRLz8qT7Ba4Xp 8 | m5S/++McBHe6vzdXgibDdYE2QUoPN004xmEMMgMwZzbt8XDuV03Nc7SHThounYVe 9 | NzfcRgux0h+5KbIrq4PX1AGBow8g5YVjalMDXTpWXqeG2ySvPyVeHLd/tijvTqm9 10 | NfTKhUdnkfOgJF2Fc96eSgZbFw0CAwEAAaM6MDgwFAYDVR0RBA0wC4IJbG9jYWxo 11 | b3N0MAsGA1UdDwQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0B 12 | AQsFAAOCAQEAqi/J8LBJ1zSDJQb2XurLdvBUU24+MYcxxWuE526aHGq2DCQ6h9lf 13 | Cf9BgE08YNX57O7UGdm+YbjKxgRBh+mEhgovJKEwt5o2RXkjNZzow4f16OXPGhN8 14 | bOZOZyJKXQSQlMoBYjxonh3ICPFTuBx6xUV4b+E4oR88kVMw93eFmq+7hiHyhzNh 15 | KaQaWqvzyOLj9RQ0/37ZDKrhUJAF6vc0g1DXNFipqx7yj4bMoFjwXsldicdwgkqP 16 | SDlseQDmf+k6IKeW35mN19vzLsSGasnKDFacNPNAi/7EBdkP0BeM3BKW3NH7/F/k 17 | KjJrb6mfenZ5F7cPxc82/J0hEO/mrdW6yg== 18 | -----END CERTIFICATE----- 19 | -------------------------------------------------------------------------------- /SourceSampler/Resources/localhost.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC1ywLcikUHzu/z 3 | ZBIr5+CRcz176RChfmIN7VyXcN5FCKMQaacsUDMMSkL5sH3uStl2BLxcrB2Cfwgc 4 | 8pYNMeIIE1fsMiTh41jnnzjrTQWP+JrT+k9LqHjb0FS+szcTGFIGq1coOWK0C1AV 5 | NJ/FphJ4ywy1XTG8qQIrpWgUH1a4dmDscES8/Kk+wWuF6ZuUv/vjHAR3ur83V4Im 6 | w3WBNkFKDzdNOMZhDDIDMGc27fFw7ldNzXO0h04aLp2FXjc33EYLsdIfuSmyK6uD 7 | 19QBgaMPIOWFY2pTA106Vl6nhtskrz8lXhy3f7Yo706pvTX0yoVHZ5HzoCRdhXPe 8 | nkoGWxcNAgMBAAECggEBAIEk+CJuA74ZTzLrq1EPh+QsJsiI+GyRWN0l+zoGT5Bh 9 | I148gCslyi33735r1/pZqASENr/q8YfL8JqH5vr2rekovLQppzPlizn4Tboy3Dm7 10 | 1Vmzn3NS+pDFff5/WCezhkoAnIkRw0G+K6T03m/Nm5++N4f77aJlugoBll99J+Ef 11 | 2xh4HCkXBBUxVomU12ddHHDMLaotYc5htCloGxoIjOjtPQjITo/U4FRlrb/uQiAZ 12 | 6OVo9vVa7XEv2E/ugqYFqXR3Bn2/8pic6zpSoq1sgr4Ol8uPqSBPgDrlc49AZD+y 13 | 73uB8+S09lOak/DAB8DxOeXAfD7fMVa394V/rzFZEwECgYEA8cVjPJAZnTBJkfRL 14 | Trb+gMP4bF+B44v3C71QzFBN80lBFoWRkP1VgIV9pn9t85+WzS2miEwXWUDfWxqj 15 | 9HocRBWM54v+qRxK7SzQmH4w0XkTsZZW2GWxZpOSyVJRePFOYUR174i0KUUzQJK4 16 | ggcvWrDFiainoH+oPVdw1fL04s0CgYEAwH344xBeuLIwD6jLA+dZG15vmWa+C8+x 17 | R0yKQ4U/V8nAhOYhVjzTK3zcxy9yebuntxYQE4H8EBPV5AuH2f1Ah7h61/+XxWA1 18 | WK4KF322KFtj6WNPTDXBeQyk/IWaL/WLktjjNYJ1KT19RiyYXa6kL1yBN2+qj03n 19 | E4QCW1e9hUECgYBjr62BNTE6fMR45699XzqEwUjW9nJJ7lYIgyCjfaEGZPfvX1dr 20 | 3ui4O1JZqkUdpHm7U81MeYNPC86Mc+mSTh8Fe5VDi5ePBtll/YpstetPE4spOAHK 21 | 6/M/hi2J0OVC5swYku/Fuin+ske1okltY6UE0cpBPkcPiFNIJ5ugu7J5KQKBgCo6 22 | +OGH89/9Z8HnvDJtDQWOIFm9SrB4rmIADs1lbFIsNwpxGps62PFPgXhJlonSe6cV 23 | Ng2xlMVKNMDFLtbKUt/zvy+oKXnp84ozFI+2ysHr2u2XFgyYNowCFCg6f2tKKYbc 24 | Amz45A9aKCO/IOZcrDSfzNGGtBqgcrO7YHD9vNyBAoGBAO84NIe6nIrM3QovReEZ 25 | MAVwjyGuIbotb0gzZj7SMm+ysgXdwhO9bGWqVP3vC5B908Sf7Hm12lQboIXmAc5k 26 | yipzw+R4uRTjPJjDDK4RWGHCe8aA22vTnLK9N7UCN7x0E3kA3A4LTHpo6dwCy6uL 27 | EST7pljFIvbtbk3ckpvLOHwM 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /SourceSampler/Source/PluginEditor.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ============================================================================== 3 | 4 | This file was auto-generated! 5 | 6 | It contains the basic framework code for a JUCE plugin editor. 7 | 8 | ============================================================================== 9 | */ 10 | 11 | #include "PluginProcessor.h" 12 | #include "PluginEditor.h" 13 | #include "BinaryData.h" 14 | #if INCLUDE_SEQUENCER 15 | #include "defines_shepherd.h" 16 | #endif 17 | 18 | 19 | //============================================================================== 20 | SourceSamplerAudioProcessorEditor::SourceSamplerAudioProcessorEditor (SourceSamplerAudioProcessor& p) 21 | : AudioProcessorEditor (&p), processor (p) 22 | { 23 | processor.source.addActionListener(this); 24 | 25 | // Copy bundled HTML plugin file to dcuments folder so we can load it 26 | #if ELK_BUILD 27 | juce::File baseLocation = juce::File(ELK_SOURCE_TMP_LOCATION); 28 | #else 29 | #if USE_APP_GROUP_ID 30 | juce::File baseLocation = juce::File::getContainerForSecurityApplicationGroupIdentifier(APP_GROUP_ID).getChildFile((juce::String)SOURCE_APP_DIRECTORY_NAME + "/tmp"); 31 | #else 32 | juce::File baseLocation = juce::File::getSpecialLocation(juce::File::userDocumentsDirectory).getChildFile((juce::String)SOURCE_APP_DIRECTORY_NAME + "/tmp"); 33 | #endif 34 | 35 | #endif 36 | if (!baseLocation.exists()){ 37 | baseLocation.createDirectory(); 38 | } 39 | juce::File uiHtmlFile = baseLocation.getChildFile("ui_plugin_ws").withFileExtension("html"); 40 | #if USE_LAZY_UI 41 | uiHtmlFile.replaceWithData(BinaryData::ui_plugin_ws_lazy_html , BinaryData::ui_plugin_ws_lazy_htmlSize); 42 | #else 43 | uiHtmlFile.replaceWithData(BinaryData::ui_plugin_ws_html , BinaryData::ui_plugin_ws_htmlSize); 44 | #endif 45 | uiHTMLFilePath = uiHtmlFile.getFullPathName(); 46 | 47 | openInBrowser.addListener(this); 48 | openInBrowser.setButtonText("Open UI in browser"); 49 | addAndMakeVisible (openInBrowser); 50 | 51 | #if INCLUDE_SEQUENCER 52 | openSequencerInBrowser.addListener(this); 53 | openSequencerInBrowser.setButtonText("Open sequencer UI in browser"); 54 | addAndMakeVisible (openSequencerInBrowser); 55 | #endif 56 | 57 | reloadUI.addListener(this); 58 | reloadUI.setButtonText("Reload UI"); 59 | addAndMakeVisible (reloadUI); 60 | 61 | explanation.setText("Looks like there were some problems loading the UI, most probably due to untrusted SSL certificates. " 62 | "Please, click the \"Open UI in browser\" button below to open Source UI in your default web browser. " 63 | "Once there, you'll be asked whether or not you want to trust the SSL self-sertificate for localhost. " 64 | "If you trust the certificate and continue loading the page, you should see a fully usable Source UI in " 65 | "your browser. Close your browser, come back to this window and click \"Reload UI\". You should now be " 66 | "seeing the plugin UI normally. Once the certificate is trusted, you should not be seeing this problem again " 67 | "when using Source in the same computer. If this does not fix the problem but you can see the UI in the browser, " 68 | "you can use the UI from there (Source will work fine).", juce::dontSendNotification); 69 | explanation.setJustificationType(juce::Justification::topLeft); 70 | addAndMakeVisible (explanation); 71 | 72 | #if !ELK_BUILD 73 | browser.setEditorPointer(this); 74 | addAndMakeVisible(browser); 75 | browser.goToURL(makeUIURL().toString(true)); 76 | #endif 77 | 78 | setSize(10, 10); // This is reset later 79 | setResizable(false, false); 80 | } 81 | 82 | SourceSamplerAudioProcessorEditor::~SourceSamplerAudioProcessorEditor() 83 | { 84 | processor.source.removeActionListener(this); 85 | 86 | #if !ELK_BUILD 87 | browser.editor.release(); 88 | #endif 89 | } 90 | 91 | juce::URL SourceSamplerAudioProcessorEditor::makeUIURL(){ 92 | #if USE_SSL_FOR_HTTP_AND_WS 93 | juce::String useWss = "1"; 94 | #else 95 | juce::String useWss = "0"; 96 | #endif 97 | #if INCLUDE_SEQUENCER 98 | juce::String withSequencer = "1"; 99 | #else 100 | juce::String withSequencer = "0"; 101 | #endif 102 | #if USING_DIRECT_COMMUNICATION_METHOD 103 | bool useDC = true; 104 | #else 105 | bool useDC = false; 106 | #endif 107 | juce::URL url = juce::URL("file://" + uiHTMLFilePath).withParameter("wsPort", (juce::String)processor.source.getServerInterfaceWSPort()).withParameter("useWss", useWss).withParameter("httpPort", (juce::String)processor.source.getServerInterfaceHttpPort()).withParameter("withSequencer", withSequencer).withParameter("useDC", useDC ? "1": "0"); 108 | DBG("> Satic UI URL: " << url.toString(true)); 109 | return url; 110 | } 111 | 112 | void SourceSamplerAudioProcessorEditor::buttonClicked (juce::Button* button){ 113 | if (button == &openInBrowser){ 114 | makeUIURL().launchInDefaultBrowser(); 115 | #if INCLUDE_SEQUENCER 116 | } else if (button == &openSequencerInBrowser){ 117 | juce::URL(DEV_UI_SIMULATOR_URL).launchInDefaultBrowser(); 118 | #endif 119 | } else if (button == &reloadUI){ 120 | #if !ELK_BUILD 121 | hadBrowserError = false; // Reset browser error property 122 | browser.goToURL(makeUIURL().toString(true)); 123 | resized(); 124 | #endif 125 | } 126 | } 127 | 128 | //============================================================================== 129 | void SourceSamplerAudioProcessorEditor::paint (juce::Graphics& g) 130 | { 131 | g.fillAll (getLookAndFeel().findColour (juce::ResizableWindow::backgroundColourId)); 132 | } 133 | 134 | void SourceSamplerAudioProcessorEditor::resized() 135 | { 136 | #if !ELK_BUILD 137 | if (!hadBrowserError){ 138 | #if !JUCE_IOS 139 | float width = 980; 140 | float height = 800; 141 | #else 142 | float width = getWidth(); 143 | float height = getHeight(); 144 | #endif 145 | #if JUCE_DEBUG && !JUCE_IOS 146 | setSize(width, height + 20); 147 | openInBrowser.setBounds(5, 0, 150, 20); 148 | #if INCLUDE_SEQUENCER 149 | openSequencerInBrowser.setBounds(160, 0, 150, 20); 150 | #endif 151 | browser.setBounds(0, 20, width, height); 152 | #else 153 | setSize(width, height); 154 | browser.setBounds(0, 0, width, height); 155 | #endif 156 | } else { 157 | browser.setBounds(0, 0, 0, 0); 158 | explanation.setBounds(10, 10, 590, 150); 159 | openInBrowser.setBounds(10, 160, 150, 20); 160 | #if INCLUDE_SEQUENCER 161 | openSequencerInBrowser.setBounds(165, 160, 150, 20); 162 | #endif 163 | reloadUI.setBounds(320, 160, 90, 20); 164 | setSize(600, 190); 165 | } 166 | #endif 167 | 168 | /* 169 | // NOTE: the code below was to make a "open UI in browser" button when running as a 170 | // plugin and in MACOS because of issues with the non-https server. Now I have implemented 171 | // an https server so this is not needed. Still, the self-signed certificate needs to be 172 | // approved using a real browser or the WebBrowserComponent won't load the UI. 173 | 174 | if (juce::JUCEApplicationBase::isStandaloneApp()){ 175 | #if !ELK_BUILD 176 | browser.setBounds(getLocalBounds()); 177 | #endif 178 | 179 | } else { 180 | #if JUCE_MAC 181 | openInBrowser.setBounds(10, 10, 120, 20); 182 | setSize(600, 100); 183 | #else 184 | #if !ELK_BUILD 185 | browser.setBounds(getLocalBounds()); 186 | #endif 187 | #endif 188 | }*/ 189 | } 190 | 191 | void SourceSamplerAudioProcessorEditor::actionListenerCallback (const juce::String &message) 192 | { 193 | #if !ELK_BUILD 194 | browser.sendMessage(message); 195 | #endif 196 | } 197 | -------------------------------------------------------------------------------- /SourceSampler/Source/PluginEditor.h: -------------------------------------------------------------------------------- 1 | /* 2 | ============================================================================== 3 | 4 | This file was auto-generated! 5 | 6 | It contains the basic framework code for a JUCE plugin editor. 7 | 8 | ============================================================================== 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | #include "PluginProcessor.h" 15 | 16 | //============================================================================== 17 | /** 18 | */ 19 | 20 | class SourceSamplerAudioProcessorEditor; 21 | 22 | #if !ELK_BUILD 23 | class CustomWebBrowserComponent: public juce::WebBrowserComponent 24 | { 25 | public: 26 | ~CustomWebBrowserComponent(){} 27 | 28 | void setEditorPointer(SourceSamplerAudioProcessorEditor* _editor) 29 | { 30 | editor.reset(_editor); 31 | } 32 | 33 | void sendMessage (const juce::String message) 34 | { 35 | // Send message from backend to frontend 36 | juce::String url = "javascript:messageFromBackend('" + message + "')"; 37 | goToURL (url); 38 | } 39 | 40 | inline bool pageAboutToLoad (const juce::String& newURL) override; 41 | inline bool pageLoadHadNetworkError (const juce::String& errorInfo) override; 42 | 43 | std::unique_ptr editor; 44 | const juce::String urlSchema = "juce://"; 45 | }; 46 | #endif 47 | 48 | 49 | class SourceSamplerAudioProcessorEditor : public juce::AudioProcessorEditor, 50 | public juce::Button::Listener, 51 | public juce::ActionListener 52 | { 53 | public: 54 | SourceSamplerAudioProcessorEditor (SourceSamplerAudioProcessor&); 55 | ~SourceSamplerAudioProcessorEditor(); 56 | 57 | juce::URL makeUIURL(); 58 | 59 | void buttonClicked (juce::Button* button) override; 60 | 61 | //============================================================================== 62 | void paint (juce::Graphics&) override; 63 | void resized() override; 64 | 65 | bool hadBrowserError = false; 66 | 67 | void actionListenerCallback (const juce::String &message) override; 68 | 69 | void triggerActionInProcessor (const juce::String actionMessage) { 70 | processor.source.actionListenerCallback(actionMessage); 71 | } 72 | 73 | private: 74 | // This reference is provided as a quick way for your editor to 75 | // access the processor object that created it. 76 | SourceSamplerAudioProcessor& processor; 77 | #if !ELK_BUILD 78 | CustomWebBrowserComponent browser; // ELK compialtion fails if using WebBrowserComponent 79 | #endif 80 | juce::TextButton openInBrowser; 81 | juce::TextButton reloadUI; 82 | juce::Label explanation; 83 | juce::String uiHTMLFilePath; 84 | #if INCLUDE_SEQUENCER 85 | juce::TextButton openSequencerInBrowser; 86 | #endif 87 | 88 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SourceSamplerAudioProcessorEditor) 89 | }; 90 | 91 | 92 | #if !ELK_BUILD 93 | bool CustomWebBrowserComponent::pageLoadHadNetworkError (const juce::String& errorInfo) 94 | { 95 | if (editor != nullptr){ 96 | editor->hadBrowserError = true; 97 | editor->resized(); 98 | } 99 | return true; 100 | } 101 | 102 | bool CustomWebBrowserComponent::pageAboutToLoad (const juce::String& newURL) 103 | { 104 | if (newURL.startsWith (urlSchema)) { 105 | // Receive mesage from frontend to backend 106 | auto messageString = juce::URL::removeEscapeChars (newURL.substring (urlSchema.length())); 107 | #if USING_DIRECT_COMMUNICATION_METHOD 108 | if (editor != nullptr){ 109 | editor->triggerActionInProcessor(messageString); 110 | } 111 | #endif 112 | return false; 113 | } else { 114 | return true; 115 | } 116 | } 117 | #endif 118 | -------------------------------------------------------------------------------- /SourceSampler/Source/PluginProcessor.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ============================================================================== 3 | 4 | This file was auto-generated! 5 | 6 | It contains the basic framework code for a JUCE plugin processor. 7 | 8 | ============================================================================== 9 | */ 10 | 11 | #include "PluginProcessor.h" 12 | #include "PluginEditor.h" 13 | 14 | #if INCLUDE_SEQUENCER 15 | #include "defines_shepherd.h" 16 | #endif 17 | 18 | 19 | //============================================================================== 20 | SourceSamplerAudioProcessor::SourceSamplerAudioProcessor() 21 | #ifndef JucePlugin_PreferredChannelConfigurations 22 | : AudioProcessor (BusesProperties() 23 | #if ! JucePlugin_IsMidiEffect 24 | #if ! JucePlugin_IsSynth 25 | .withInput ("Input", juce::AudioChannelSet::stereo(), true) 26 | #endif 27 | .withOutput ("Output", juce::AudioChannelSet::stereo(), true) 28 | #endif 29 | ) 30 | #endif 31 | { 32 | source.setTotalNumOutputChannels(getTotalNumOutputChannels()); 33 | #if INCLUDE_SEQUENCER 34 | sequencerCombinedBuffer.ensureSize(512 * 10); 35 | #endif 36 | } 37 | 38 | SourceSamplerAudioProcessor::~SourceSamplerAudioProcessor() 39 | { 40 | } 41 | 42 | 43 | //============================================================================== 44 | const juce::String SourceSamplerAudioProcessor::getName() const 45 | { 46 | return JucePlugin_Name; 47 | } 48 | 49 | bool SourceSamplerAudioProcessor::acceptsMidi() const 50 | { 51 | #if JucePlugin_WantsMidiInput 52 | return true; 53 | #else 54 | return false; 55 | #endif 56 | } 57 | 58 | bool SourceSamplerAudioProcessor::producesMidi() const 59 | { 60 | #if JucePlugin_ProducesMidiOutput 61 | return true; 62 | #else 63 | return false; 64 | #endif 65 | } 66 | 67 | bool SourceSamplerAudioProcessor::isMidiEffect() const 68 | { 69 | #if JucePlugin_IsMidiEffect 70 | return true; 71 | #else 72 | return false; 73 | #endif 74 | } 75 | 76 | double SourceSamplerAudioProcessor::getTailLengthSeconds() const 77 | { 78 | return 0.0; 79 | } 80 | 81 | int SourceSamplerAudioProcessor::getNumPrograms() 82 | { 83 | return 128; 84 | } 85 | 86 | int SourceSamplerAudioProcessor::getCurrentProgram() 87 | { 88 | return source.currentPresetIndex; 89 | } 90 | 91 | void SourceSamplerAudioProcessor::setCurrentProgram (int index) 92 | { 93 | source.loadPresetFromIndex(index); 94 | } 95 | 96 | const juce::String SourceSamplerAudioProcessor::getProgramName (int index) 97 | { 98 | return source.getPresetNameByIndex(index); 99 | } 100 | 101 | void SourceSamplerAudioProcessor::changeProgramName (int index, const juce::String& newName) 102 | { 103 | source.renamePreset(index, newName); 104 | } 105 | 106 | 107 | //============================================================================== 108 | void SourceSamplerAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock) 109 | { 110 | source.prepareToPlay(sampleRate, samplesPerBlock); 111 | #if INCLUDE_SEQUENCER 112 | sequencer.prepareSequencer(samplesPerBlock, sampleRate); 113 | #endif 114 | } 115 | 116 | void SourceSamplerAudioProcessor::releaseResources() 117 | { 118 | source.releaseResources(); 119 | } 120 | 121 | #ifndef JucePlugin_PreferredChannelConfigurations 122 | bool SourceSamplerAudioProcessor::isBusesLayoutSupported (const BusesLayout& layouts) const 123 | { 124 | #if JucePlugin_IsMidiEffect 125 | ignoreUnused (layouts); 126 | return true; 127 | #else 128 | // This is the place where you check if the layout is supported. 129 | // In this template code we only support mono or stereo. 130 | if (layouts.getMainOutputChannelSet() != juce::AudioChannelSet::mono() 131 | && layouts.getMainOutputChannelSet() != juce::AudioChannelSet::stereo()) 132 | return false; 133 | 134 | // This checks if the input layout matches the output layout 135 | #if ! JucePlugin_IsSynth 136 | if (layouts.getMainOutputChannelSet() != layouts.getMainInputChannelSet()) 137 | return false; 138 | #endif 139 | 140 | return true; 141 | #endif 142 | } 143 | #endif 144 | 145 | void SourceSamplerAudioProcessor::processBlock (juce::AudioBuffer& buffer, juce::MidiBuffer& midiMessages) 146 | { 147 | #if INCLUDE_SEQUENCER 148 | int sliceNumSamples = buffer.getNumSamples(); 149 | sequencer.getNextMIDISlice(sliceNumSamples); 150 | sequencerCombinedBuffer.clear(); 151 | for (auto deviceData: *sequencer.getMidiOutDevices()){ 152 | if (deviceData != nullptr && deviceData->name == INTERNAL_OUTPUT_MIDI_DEVICE_NAME){ 153 | sequencerCombinedBuffer.addEvents(deviceData->buffer, 0, sliceNumSamples, 0); 154 | } 155 | } 156 | midiMessages.addEvents(sequencerCombinedBuffer, 0, sliceNumSamples, 0); // Combine sequencer MIDI messages with plugin's input message stream 157 | #endif 158 | source.processBlock(buffer, midiMessages); 159 | } 160 | 161 | //============================================================================== 162 | bool SourceSamplerAudioProcessor::hasEditor() const 163 | { 164 | return true; // (change this to false if you choose to not supply an editor) 165 | } 166 | 167 | juce::AudioProcessorEditor* SourceSamplerAudioProcessor::createEditor() 168 | { 169 | return new SourceSamplerAudioProcessorEditor (*this); 170 | } 171 | 172 | void SourceSamplerAudioProcessor::getStateInformation (juce::MemoryBlock& destData) 173 | { 174 | // Save current state information to memory block 175 | std::unique_ptr xml ( source.state.createXml()); 176 | DBG("> Running getStateInformation"); 177 | DBG(xml->toString()); // Print state for debugging purposes (print it nicely indented) 178 | copyXmlToBinary (*xml, destData); 179 | } 180 | 181 | void SourceSamplerAudioProcessor::setStateInformation (const void* data, int sizeInBytes) 182 | { 183 | // Called by the plugin host to load state stored in host into plugin 184 | DBG("> Running setStateInformation"); 185 | std::unique_ptr xmlState (getXmlFromBinary (data, sizeInBytes)); 186 | if (xmlState.get() != nullptr){ 187 | source.loadPresetFromStateInformation(juce::ValueTree::fromXml(*xmlState.get())); 188 | } 189 | } 190 | 191 | //============================================================================== 192 | // This creates new instances of the plugin.. 193 | juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter() 194 | { 195 | return new SourceSamplerAudioProcessor(); 196 | } 197 | -------------------------------------------------------------------------------- /SourceSampler/Source/PluginProcessor.h: -------------------------------------------------------------------------------- 1 | /* 2 | ============================================================================== 3 | 4 | This file was auto-generated! 5 | 6 | It contains the basic framework code for a JUCE plugin processor. 7 | 8 | ============================================================================== 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | #include "SourceSampler.h" 15 | #if INCLUDE_SEQUENCER 16 | #include "Sequencer.h" 17 | #endif 18 | 19 | 20 | //============================================================================== 21 | /** 22 | */ 23 | class SourceSamplerAudioProcessor : public juce::AudioProcessor 24 | { 25 | public: 26 | //============================================================================== 27 | SourceSamplerAudioProcessor(); 28 | ~SourceSamplerAudioProcessor(); 29 | 30 | //============================================================================== 31 | void prepareToPlay (double sampleRate, int samplesPerBlock) override; 32 | void releaseResources() override; 33 | 34 | #ifndef JucePlugin_PreferredChannelConfigurations 35 | bool isBusesLayoutSupported (const BusesLayout& layouts) const override; 36 | #endif 37 | 38 | void processBlock (juce::AudioBuffer&, juce::MidiBuffer&) override; 39 | 40 | //============================================================================== 41 | juce::AudioProcessorEditor* createEditor() override; 42 | bool hasEditor() const override; 43 | 44 | //============================================================================== 45 | const juce::String getName() const override; 46 | bool acceptsMidi() const override; 47 | bool producesMidi() const override; 48 | bool isMidiEffect() const override; 49 | double getTailLengthSeconds() const override; 50 | 51 | //============================================================================== 52 | int getNumPrograms() override; 53 | int getCurrentProgram() override; 54 | void setCurrentProgram (int index) override; 55 | const juce::String getProgramName (int index) override; 56 | void changeProgramName (int index, const juce::String& newName) override; 57 | 58 | //============================================================================== 59 | void getStateInformation (juce::MemoryBlock& destData) override; 60 | void setStateInformation (const void* data, int sizeInBytes) override; 61 | 62 | SourceSampler source; 63 | 64 | #if INCLUDE_SEQUENCER 65 | Sequencer sequencer; 66 | juce::MidiBuffer sequencerCombinedBuffer; 67 | #endif 68 | 69 | private: 70 | 71 | //============================================================================== 72 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SourceSamplerAudioProcessor) 73 | }; 74 | -------------------------------------------------------------------------------- /SourceSampler/Source/SourceSamplerSynthesiser.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ============================================================================== 3 | 4 | SourceSamplerVoice.cpp 5 | Created: 3 Sep 2020 2:13:36pm 6 | Author: Frederic Font Corbera 7 | 8 | ============================================================================== 9 | */ 10 | 11 | #include "SourceSamplerSynthesiser.h" 12 | 13 | 14 | SourceSamplerSynthesiser::SourceSamplerSynthesiser() 15 | { 16 | setSamplerVoices(maxNumVoices); 17 | 18 | // Configure effects chain 19 | juce::Reverb::Parameters reverbParameters; 20 | reverbParameters.roomSize = 0.5f; 21 | reverbParameters.damping = 0.5f; 22 | reverbParameters.wetLevel = 0.0f; 23 | reverbParameters.dryLevel = 1.0f; 24 | reverbParameters.width = 1.0f; 25 | reverbParameters.freezeMode = 0.0f; 26 | auto& reverb = fxChain.get(); 27 | reverb.setParameters(reverbParameters); 28 | } 29 | 30 | void SourceSamplerSynthesiser::setSamplerVoices(int nVoices) 31 | { 32 | // Clear existing voices and re-create new ones 33 | clearVoices(); 34 | for (auto i = 0; i < juce::jmin(maxNumVoices, nVoices); ++i) 35 | addVoice (new SourceSamplerVoice); 36 | 37 | // Prepare newly created voices if processing specs are given (re-prepare voices) 38 | if (currentNumChannels > 0 ){ 39 | // This is a big UGLY, might find a better fix for the future. The issue is that the sampler.prepare method (which in its turn 40 | // calls voices' prepare method) is only called once when plugin processor hits "prepareToPlay". Later on, if we remove and re-create 41 | // voices, these are never prepared and the tmpVoiceBuffer is never allocated (and processing chain is not prepared either). To 42 | // fix this, we store processing specs in the sampler object (num channels, sample rate, block size) so that everytime voice 43 | // objects are deleted and created, we can already prepare them. These specs are stored the first time "sampler.prepare" is called 44 | // because it is the first time sampler actually knows about what sample rate, block size and num channels shold work on. 45 | // HOWEVER, when we call "sampler.setSamplerVoices" the first time, the processing specs have not been stored yet, so we need to 46 | // add a check here to not call prepare on the voices with the default values of currentBlockSize, currentNumChannels and 47 | // getSampleRate() whcih are meaningless (=0) and will throw errors. 48 | for (auto* v : voices) 49 | dynamic_cast (v)->prepare ({ getSampleRate(), (juce::uint32) currentBlockSize, (juce::uint32) currentNumChannels }); 50 | } 51 | 52 | setNoteStealingEnabled (true); 53 | } 54 | 55 | void SourceSamplerSynthesiser::prepare (const juce::dsp::ProcessSpec& spec) noexcept 56 | { 57 | // Store current processing specs to be later used for voice processing and re-preparing 58 | currentNumChannels = spec.numChannels; 59 | currentBlockSize = spec.maximumBlockSize; 60 | setCurrentPlaybackSampleRate (spec.sampleRate); 61 | 62 | for (auto* v : voices) 63 | dynamic_cast (v)->prepare (spec); 64 | 65 | fxChain.prepare (spec); 66 | } 67 | 68 | //============================================================================== 69 | 70 | void SourceSamplerSynthesiser::noteOn (const int midiChannel, 71 | const int midiNoteNumber, 72 | const float velocity) 73 | { 74 | const juce::ScopedLock sl (lock); 75 | int velocityInMidiRange = (int)std::round(127.0 * velocity); 76 | for (auto* sound : sounds) 77 | { 78 | if (sound->appliesToNote (midiNoteNumber) && dynamic_cast(sound)->appliesToVelocity(velocityInMidiRange) && sound->appliesToChannel (midiChannel)) 79 | { 80 | //DBG(midiNoteNumber << "," << velocityInMidiRange << ": " << dynamic_cast(sound)->getSoundName()); 81 | // If hitting a note that's still ringing, stop it first (it could be 82 | // still playing because of the sustain or sostenuto pedal). 83 | for (auto* voice : voices) 84 | if (voice->getCurrentlyPlayingNote() == midiNoteNumber && voice->isPlayingChannel (midiChannel) && dynamic_cast(voice)->getCurrentlyPlayingSourceSamplerSound()->getSourceSound()->getUUID() == dynamic_cast(sound)->getSourceSound()->getUUID()) 85 | stopVoice (voice, 1.0f, true); // Only allow one single instance of SourceSamplerSound type per voice 86 | auto* voice = findFreeVoice (sound, midiChannel, midiNoteNumber, isNoteStealingEnabled()); 87 | dynamic_cast(voice)->setModWheelValue(lastModWheelValue); 88 | startVoice (voice, sound, midiChannel, midiNoteNumber, velocity); 89 | } 90 | } 91 | } 92 | 93 | void SourceSamplerSynthesiser::handleMidiEvent (const juce::MidiMessage& m) 94 | { 95 | const int channel = m.getChannel(); 96 | 97 | if (m.isNoteOn()) 98 | { 99 | noteOn (channel, m.getNoteNumber(), m.getFloatVelocity()); 100 | } 101 | else if (m.isNoteOff()) 102 | { 103 | noteOff (channel, m.getNoteNumber(), m.getFloatVelocity(), true); 104 | } 105 | else if (m.isAllNotesOff() || m.isAllSoundOff()) 106 | { 107 | allNotesOff (channel, true); 108 | } 109 | else if (m.isPitchWheel()) 110 | { 111 | const int wheelPos = m.getPitchWheelValue(); 112 | lastPitchWheelValues [channel - 1] = wheelPos; 113 | handlePitchWheel (channel, wheelPos); 114 | } 115 | else if (m.isAftertouch()) 116 | { 117 | handleAftertouch (channel, m.getNoteNumber(), m.getAfterTouchValue()); 118 | } 119 | else if (m.isChannelPressure()) 120 | { 121 | handleChannelPressure (channel, m.getChannelPressureValue()); 122 | } 123 | else if (m.isController()) 124 | { 125 | int number = m.getControllerNumber(); 126 | int value = m.getControllerValue(); 127 | 128 | // Store last value for mod wheel (used when triggering new notes) 129 | if (number == 1){ 130 | lastModWheelValue = value; 131 | } 132 | 133 | // Handle controller in active voices 134 | handleController (channel, number, value); 135 | 136 | // Check midi mappings for the loaded sounds and update parameters if needed 137 | for (auto* s : sounds) 138 | { 139 | if (auto* sound = dynamic_cast (s)){ 140 | sound->getSourceSound()->applyMidiCCModulations(channel, number, value); 141 | } 142 | } 143 | } 144 | else if (m.isProgramChange()) 145 | { 146 | int index = m.getProgramChangeNumber(); // Preset index, this is 0-based so MIDI value 0 will be also 0 here 147 | juce::String actionMessage = juce::String(ACTION_LOAD_PRESET) + ":" + (juce::String)index; 148 | sendActionMessage(actionMessage); 149 | } 150 | } 151 | 152 | void SourceSamplerSynthesiser::renderVoices (juce::AudioBuffer< float > &outputAudio, int startSample, int numSamples) 153 | { 154 | Synthesiser::renderVoices (outputAudio, startSample, numSamples); 155 | auto block = juce::dsp::AudioBlock (outputAudio); 156 | auto blockToUse = block.getSubBlock ((size_t) startSample, (size_t) numSamples); 157 | auto contextToUse = juce::dsp::ProcessContextReplacing (blockToUse); 158 | fxChain.process (contextToUse); 159 | } 160 | 161 | //============================================================================== 162 | 163 | void SourceSamplerSynthesiser::setReverbParameters (juce::Reverb::Parameters params) { 164 | auto& reverb = fxChain.get(); 165 | reverb.setParameters(params); 166 | } 167 | -------------------------------------------------------------------------------- /SourceSampler/Source/SourceSamplerSynthesiser.h: -------------------------------------------------------------------------------- 1 | /* 2 | ============================================================================== 3 | 4 | SourceSamplerVoice.h 5 | Created: 3 Sep 2020 2:13:36pm 6 | Author: Frederic Font Corbera 7 | 8 | ============================================================================== 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | #include "helpers_source.h" 15 | #include "SourceSamplerVoice.h" 16 | #include "SourceSamplerSound.h" 17 | 18 | 19 | 20 | class SourceSamplerSynthesiser: public juce::Synthesiser, 21 | public juce::ActionBroadcaster 22 | { 23 | public: 24 | SourceSamplerSynthesiser(); 25 | 26 | static constexpr auto maxNumVoices = 32; 27 | void setSamplerVoices(int nVoices); 28 | void prepare (const juce::dsp::ProcessSpec& spec) noexcept; 29 | 30 | //============================================================================== 31 | void noteOn (const int midiChannel, 32 | const int midiNoteNumber, 33 | const float velocity) override; 34 | void handleMidiEvent (const juce::MidiMessage& m) override; 35 | 36 | //============================================================================== 37 | void setReverbParameters (juce::Reverb::Parameters params); 38 | 39 | private: 40 | //============================================================================== 41 | void renderVoices (juce::AudioBuffer< float > &outputAudio, int startSample, int numSamples) override; 42 | enum 43 | { 44 | reverbIndex 45 | }; 46 | int lastModWheelValue = 0; 47 | int currentNumChannels = 0; 48 | int currentBlockSize = 0; 49 | juce::dsp::ProcessorChain fxChain; 50 | }; 51 | -------------------------------------------------------------------------------- /SourceSampler/Source/SourceSamplerVoice.h: -------------------------------------------------------------------------------- 1 | /* 2 | ============================================================================== 3 | 4 | SourceSamplerVoice.h 5 | Created: 23 Mar 2022 1:38:24pm 6 | Author: Frederic Font Corbera 7 | 8 | ============================================================================== 9 | */ 10 | 11 | #pragma once 12 | #include 13 | #include "helpers_source.h" 14 | #include "SourceSamplerSound.h" 15 | 16 | 17 | class SourceSamplerVoice: public juce::SynthesiserVoice 18 | { 19 | public: 20 | //============================================================================== 21 | SourceSamplerVoice(); 22 | 23 | ~SourceSamplerVoice() override; 24 | 25 | //============================================================================== 26 | bool canPlaySound (juce::SynthesiserSound*) override; 27 | 28 | void updateParametersFromSourceSamplerSound(SourceSamplerSound* sound); 29 | 30 | void startNote (int midiNoteNumber, float velocity, juce::SynthesiserSound*, int pitchWheel) override; 31 | void stopNote (float velocity, bool allowTailOff) override; 32 | 33 | void pitchWheelMoved (int newValue) override; 34 | void controllerMoved (int controllerNumber, int newValue) override; 35 | void aftertouchChanged (int newAftertouchValue) override; 36 | void channelPressureChanged (int newChannelPressureValue) override; 37 | 38 | void renderNextBlock (juce::AudioBuffer&, int startSample, int numSamples) override; 39 | using SynthesiserVoice::renderNextBlock; 40 | 41 | //============================================================================== 42 | void prepare (const juce::dsp::ProcessSpec& spec); 43 | 44 | float getPlayingPositionPercentage(); 45 | int getNoteIndex(int midiNote); 46 | 47 | SourceSamplerSound* getCurrentlyPlayingSourceSamplerSound() const noexcept; 48 | 49 | void setModWheelValue(int newValue); 50 | 51 | 52 | private: 53 | int pluginNumChannelsSize = 0; 54 | int currentlyPlayedNoteIndex = 0; 55 | 56 | int currentModWheelValue = 0; // Configured on noteONn and updated when modwheel is moved. This is needed to make modWheel modulationm persist across voices 57 | float currentNoteVelocity = 1.0; 58 | 59 | //============================================================================== 60 | // Sample reading and rendering 61 | bool playheadDirectionIsForward = true; // true = forward, false = backward 62 | float targetPlayheadSamplePosition = 0; // only used in "freeze" mode 63 | double pitchRatio = 0; 64 | double pitchModSemitones = 0; // For aftertouch, modulation wheel 65 | double pitchBendModSemitones = 0; 66 | double playheadSamplePosition = 0; 67 | double playheadSamplePositionMod = 0; 68 | float pan = 0; 69 | float lgain = 0, rgain = 0; 70 | juce::ADSR adsr; 71 | juce::ADSR adsrFilter; 72 | 73 | //============================================================================== 74 | // ProcessorChain (filter, pan and master gain) 75 | enum 76 | { 77 | filterIndex, 78 | masterGainIndex 79 | }; 80 | juce::dsp::ProcessorChain, juce::dsp::Gain> processorChain; 81 | juce::AudioBuffer tmpVoiceBuffer; // used for processing voice contents in each process block, then adding to the main output buffer 82 | 83 | float filterCutoff = 20000.0f; 84 | float filterRessonance = 0.0f; 85 | float filterCutoffMod = 0.0f; // For aftertouch, modulation wheel 86 | float gainMod = 1.0f; // For aftertouch, modulation wheel 87 | int startPositionSample = 0; 88 | int endPositionSample = 0; 89 | int loopStartPositionSample = 0; 90 | int fixedLoopStartPositionSample = 0; 91 | int loopEndPositionSample = 0; 92 | int fixedLoopEndPositionSample = 0; 93 | bool hasNotYetPassedLoopStartPositionForTheFirstTime = true; 94 | 95 | // NOTE: the default values of the parameters above do not really matter because they'll be overriden by 96 | // the loaded sonund defaults 97 | 98 | juce::AudioBuffer debugBuffer; // Used only to store samples for debugging purposes 99 | int debugBufferCurrentPosition = 0; 100 | bool isRecordingToDebugBuffer = false; 101 | void startRecordingToDebugBuffer(int bufferSize); 102 | void writeToDebugBuffer(float sample); 103 | void endRecordingToDebugBuffer(juce::String outFilename); 104 | bool debugBufferFinishedRecording = false; 105 | 106 | JUCE_LEAK_DETECTOR (SourceSamplerVoice) 107 | }; 108 | -------------------------------------------------------------------------------- /SourceSampler/Source/api_key.example.h: -------------------------------------------------------------------------------- 1 | /* 2 | ============================================================================== 3 | 4 | api_key.h 5 | Created: 10 Sep 2019 5:48:01pm 6 | Author: Frederic Font Corbera 7 | 8 | ============================================================================== 9 | */ 10 | 11 | #pragma once 12 | 13 | #define FREESOUND_API_KEY "YOUR_API_KEY_HERE" 14 | -------------------------------------------------------------------------------- /SourceSampler/data_for_code_gen.csv: -------------------------------------------------------------------------------- 1 | name;type;min;max;default;midiCCenabled; 2 | launchMode;int;0;4;0;;gate,loop,loop ping-pong,trigger,freeze 3 | startPosition;float;0;1;0;1;percentage position 4 | endPosition;float;0;1;1;1;percentage position 5 | loopStartPosition;float;0;1;0;1;percentage position 6 | loopEndPosition;float;0;1;1;1;percentage position 7 | loopXFadeNSamples;int;10;100000;500;;n samples 8 | reverse;int;0;1;0;;1=reverse 9 | noteMappingMode;int;0;3;0;;pitch/slice/both/repeat (repeat means sounds is not altered at all) 10 | numSlices;int;0;100;0;;0=auto per n notes, 1=auto per onsets, 2-100=from 2 to 100 equally spaced slices 11 | playheadPosition;float;0;1;0;1;this is only used in “freeze” mode, and represents the playhead position from 0=sound start, to 1=sound end 12 | freezePlayheadSpeed;float;1;5000;100;1;speed modifier for the max speed at which playhead moves into the direction of target playhead in freeze mode 13 | filterCutoff;float;10;20000;20000;1; 14 | filterRessonance;float;0;1;0;1; 15 | filterKeyboardTracking;float;0;1;0;; 16 | filterAttack;float;0.0;1.0;0.01;;seconds 17 | filterDecay;float;0.0;1.0;0.0;;seconds 18 | filterSustain;float;0.0;1.0;1.0;;amount 19 | filterRelease;float;0.0;1.0;0.01;;seconds 20 | filterADSR2CutoffAmt;float;0;100;1;; 21 | gain;float;-80;12;-10;1;db 22 | attack;float;0.0;1.0;0.01;;seconds 23 | decay;float;0.0;1.0;0.0;;seconds 24 | sustain;float;0.0;1.0;1.0;;amount 25 | release;float;0.0;1.0;0.01;;seconds 26 | pan;float;-1;1;0;1; 27 | pitch;float;-36;36;0;1;semitones (with respect to midi root note) 28 | pitchBendRangeUp;float;0;36;12;;semitones 29 | pitchBendRangeDown;float;0;36;12;;semitones 30 | mod2CutoffAmt;float;0;100;10;; 31 | mod2GainAmt;float;-12;12;6;;gain amount to be added with AT (in dB) 32 | mod2PitchAmt;float;-12;12;0;;semitones 33 | mod2PlayheadPos;float;0;1;0;; 34 | vel2CutoffAmt;float;0;100;0;;velocity to cutoff amount (multiplier to cutoff frequency) 35 | vel2GainAmt;float;0;1;0.5;;percentage of how much velocity affects gain 36 | velSensitivity;float;0;6;1.0;;modifier to velocity values applies as X^velSensitivity 37 | midiChannel;int;0;16;0;;global,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 38 | pitchShift;float;-36;36;0;0;semitones (with respect to midi root note) 39 | timeStretch;float;0.1;4.0;1.0;0;time stretch ratio (1=no change, 2=2x slower) -------------------------------------------------------------------------------- /SourceShepherdPush2Controller/modes/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/SourceShepherdPush2Controller/modes/__init__.py -------------------------------------------------------------------------------- /SourceShepherdPush2Controller/modes/generator_algorithms.py: -------------------------------------------------------------------------------- 1 | import random 2 | import numpy as np 3 | 4 | try: 5 | import os, sys 6 | # Add specific directory to python so we can import groove transformer from its folders 7 | sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'GrooveTransformerExample/')) 8 | from .GrooveTransformerExample.helpers import load_mgt_model, predict_using_h_v_o, strip_note_from_hvo 9 | with_gt = True 10 | except ImportError as e: 11 | print('Can\'t load pytorch, groove transformer algorithm will not work: {}'.format(e)) 12 | with_gt = False 13 | 14 | from utils import clamp 15 | 16 | 17 | class GeneratorAlogorithm(object): 18 | parameters = [] 19 | name = '' 20 | clip_edit_mode = None 21 | 22 | def __init__(self, clip_edit_mode): 23 | self.clip_edit_mode = clip_edit_mode # Keep reference to ClipEditMode object so we can acces state details and other related stuff 24 | for key, param_data in self.parameters.items(): 25 | param_data.update({'name': key, 'value': param_data['default']}) 26 | 27 | def get_algorithm_parameters(self): 28 | return list(self.parameters.values()) 29 | 30 | def generate_sequence(self): 31 | raise NotImplementedError 32 | 33 | def update_parameter_value(self, name, increment): 34 | # increment will be the increment sent form the encoder moving. small increments are -1/+1 35 | self.parameters[name]['value'] = clamp( 36 | self.parameters[name]['value'] + increment * self.parameters[name]['increment_scale'], 37 | self.parameters[name]['min'], 38 | self.parameters[name]['max'], 39 | ) 40 | 41 | 42 | class RandomGeneratorAlgorithm(GeneratorAlogorithm): 43 | name = 'Rnd+' 44 | parameters = { 45 | 'length': {'display_name': 'LENGTH', 'type': float, 'min': 1.0, 'max': 32.0, 'default': 8.0, 46 | 'increment_scale': 1.0}, 47 | 'density': {'display_name': 'DENSITY', 'type': int, 'min': 1, 'max': 15, 'default': 5, 'increment_scale': 1}, 48 | 'max_duration': {'display_name': 'MAX DUR', 'type': float, 'min': 0.1, 'max': 10.0, 'default': 0.5, 49 | 'increment_scale': 0.125}, 50 | } 51 | 52 | def generate_sequence(self): 53 | if self.parameters['length']['value'] > 0.0: 54 | new_clip_length = self.parameters['length']['value'] 55 | else: 56 | new_clip_length = random.randint(5, 13) 57 | random_sequence = [] 58 | for i in range(0, abs(self.parameters['density']['value'] + random.randint(-2, 2))): 59 | timestamp = (new_clip_length - 0.5) * random.random() 60 | duration = max(0.1, random.random() * self.parameters['max_duration']['value']) 61 | random_sequence.append( 62 | {'type': 1, 'midiNote': random.randint(64, 85), 'midiVelocity': 1.0, 'timestamp': timestamp, 63 | 'duration': duration} 64 | ) 65 | return random_sequence, new_clip_length 66 | 67 | 68 | class GrooveTransfomer(GeneratorAlogorithm): 69 | name = 'GTrans' 70 | parameters = { 71 | 'threshold': {'display_name': 'DENSITY', 'type': float, 'min': 0.0, 'max': 1.0, 'default': 0.5, 72 | 'increment_scale': 0.1}, 73 | } 74 | 75 | gt_model = None 76 | 77 | drum_mappings = { 78 | "KICK": [36], 79 | "SNARE": [38], 80 | "HH_CLOSED": [42], 81 | "HH_OPEN": [46], 82 | "TOM_3_LO": [43], 83 | "TOM_2_MID": [47], 84 | "TOM_1_HI": [50], 85 | "CRASH": [49], 86 | "RIDE": [51] 87 | } 88 | 89 | sampling_thresholds = { 90 | "KICK": 0.5, 91 | "SNARE": 0.5, 92 | "HH_CLOSED": 0.5, 93 | "HH_OPEN": 0.5, 94 | "TOM_3_LO": 0.5, 95 | "TOM_2_MID": 0.5, 96 | "TOM_1_HI": 0.5, 97 | "CRASH": 0.5, 98 | "RIDE": 0.5 99 | } 100 | 101 | max_counts_allowed = { 102 | "KICK": 16, 103 | "SNARE": 8, 104 | "HH_CLOSED": 32, 105 | "HH_OPEN": 32, 106 | "TOM_3_LO": 32, 107 | "TOM_2_MID": 32, 108 | "TOM_1_HI": 32, 109 | "CRASH": 32, 110 | "RIDE": 32, 111 | } 112 | 113 | def __init__(self, *args, **kwargs): 114 | super().__init__(*args, **kwargs) 115 | if with_gt: 116 | print('Loading GrooveTransformer models...') 117 | model_index = 1 118 | assert model_index in range(1, 5), "model_index must be in range 1 to 4" 119 | model_path = "modes/GrooveTransformerExample/model/checkpoints/model{}.pth".format(model_index) 120 | self.gt_model = load_mgt_model(model_path) 121 | 122 | def generate_sequence(self): 123 | if self.gt_model is not None: 124 | 125 | input_groove_hits = [round(np.random.rand(), 0) for _ in range(32)] 126 | input_groove_velocities = [round(np.random.random(), 2) if input_groove_hits[ix] == 1 else 0 for ix in range(32)] 127 | input_groove_offsets = [round(np.random.random() - 0.5, 2) if input_groove_hits[ix] == 1 else 0 for ix in range(32)] 128 | 129 | input_clip = self.clip_edit_mode.clip 130 | if input_clip is not None and input_clip.clip_length_in_beats is not 0.0 and len(input_clip.sequence_events) > 0: 131 | ''' 132 | [1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0] 133 | [0.12, 0.96, 0.73, 0, 0, 0.6, 0.7, 0, 0.22, 0, 0.46, 0, 0.55, 0.51, 0, 0, 0.41, 0.55, 0, 0.31, 0.64, 0.62, 0.32, 0.0, 0.91, 0.32, 0.76, 0.43, 0, 0.24, 0.2, 0] 134 | [-0.31, 0.28, 0.17, 0, 0, 0.17, -0.25, 0, -0.44, 0, 0.23, 0, -0.24, -0.01, 0, 0, -0.47, -0.39, 0, 0.04, -0.38, 0.39, -0.12, 0.26, -0.06, 0.26, 0.49, -0.04, 0, -0.28, -0.49, 0] 135 | ''' 136 | input_groove_hits = [0.0 for _ in range(32)] 137 | input_groove_velocities = [0.0 for _ in range(32)] 138 | input_groove_offsets = [0.0 for _ in range(32)] 139 | 140 | for sequence_event in input_clip.sequence_events: 141 | timestamp_in_32_scale = sequence_event.timestamp * 4.0 142 | timestamp_position_in_tensor = int(round(timestamp_in_32_scale)) 143 | if timestamp_position_in_tensor < 32: 144 | input_groove_hits[timestamp_position_in_tensor] = 1.0 145 | input_groove_velocities[timestamp_position_in_tensor] = 1.0 146 | input_groove_offsets[timestamp_position_in_tensor] = timestamp_position_in_tensor - timestamp_in_32_scale # Not sure what units I should use here for offset (is it 1/32 of the beat?) 147 | else: 148 | pass # Ignore sequence events beyond the 8 beats (32.0 in 32 times scale) 149 | 150 | h, v, o = predict_using_h_v_o( 151 | trained_model=self.gt_model, 152 | input_h=input_groove_hits, 153 | input_v=input_groove_velocities, 154 | input_o=input_groove_offsets, 155 | voice_thresholds=[1.0 - self.parameters['threshold']['value'] for _ in range(0, len(self.sampling_thresholds))], #self.sampling_thresholds.values(), 156 | voice_max_count_allowed=self.max_counts_allowed.values()) 157 | 158 | notes = strip_note_from_hvo(h=h, v=v, o=o, drum_map=self.drum_mappings) 159 | sequence_length = 8.0 160 | sequence_notes = [] 161 | for note in notes: 162 | sequence_notes.append( 163 | {'type': 1, 164 | 'midiNote': int(note['pitch'][0]), 165 | 'midiVelocity': float(note['velocity'][0]), 166 | 'timestamp': float(note['quantizedTime'][0]), 167 | 'uTime': float(note['offset'][0]) / 4.0, 168 | 'duration': 0.1}) 169 | return sequence_notes, sequence_length 170 | 171 | else: 172 | print('Can\'t generate new sequence with GrooveTransfomer as pytorch is not available') 173 | return None, None 174 | -------------------------------------------------------------------------------- /SourceShepherdPush2Controller/modes/preset_selection_mode.py: -------------------------------------------------------------------------------- 1 | import definitions 2 | import push2_python 3 | import os 4 | import json 5 | 6 | 7 | class PresetSelectionMode(definitions.ShepherdControllerMode): 8 | 9 | xor_group = 'pads' 10 | 11 | favourtie_presets = {} 12 | 13 | current_page = 0 14 | 15 | page_left_button = push2_python.constants.BUTTON_LEFT 16 | page_right_button = push2_python.constants.BUTTON_RIGHT 17 | 18 | buttons_used = [page_left_button, page_right_button] 19 | 20 | def initialize(self, settings=None): 21 | if os.path.exists(definitions.FAVOURITE_PRESETS_FILE_PATH): 22 | self.favourtie_presets = json.load(open(definitions.FAVOURITE_PRESETS_FILE_PATH)) 23 | 24 | def new_track_selected(self): 25 | self.current_page = 0 26 | self.app.pads_need_update = True 27 | self.app.buttons_need_update = True 28 | 29 | def add_favourite_preset(self, preset_number, bank_number): 30 | device_short_name = self.app.track_selection_mode.get_current_track_device_short_name() 31 | if device_short_name not in self.favourtie_presets: 32 | self.favourtie_presets[device_short_name] = [] 33 | self.favourtie_presets[device_short_name].append((preset_number, bank_number)) 34 | json.dump(self.favourtie_presets, open(definitions.FAVOURITE_PRESETS_FILE_PATH, 'w')) # Save to file 35 | 36 | def remove_favourite_preset(self, preset_number, bank_number): 37 | device_short_name = self.app.track_selection_mode.get_current_track_device_short_name() 38 | if device_short_name in self.favourtie_presets: 39 | self.favourtie_presets[device_short_name] = \ 40 | [(fp_preset_number, fp_bank_number) for fp_preset_number, fp_bank_number in self.favourtie_presets[device_short_name] 41 | if preset_number != fp_preset_number or bank_number != fp_bank_number] 42 | json.dump(self.favourtie_presets, open(definitions.FAVOURITE_PRESETS_FILE_PATH, 'w')) # Save to file 43 | 44 | def preset_num_in_favourites(self, preset_number, bank_number): 45 | device_short_name = self.app.track_selection_mode.get_current_track_device_short_name() 46 | if device_short_name not in self.favourtie_presets: 47 | return False 48 | for fp_preset_number, fp_bank_number in self.favourtie_presets[device_short_name]: 49 | if preset_number == fp_preset_number and bank_number == fp_bank_number: 50 | return True 51 | return False 52 | 53 | def get_current_page(self): 54 | # Returns the current page of presets being displayed in the pad grid 55 | # page 0 = bank 0, presets 0-63 56 | # page 1 = bank 0, presets 64-127 57 | # page 2 = bank 1, presets 0-63 58 | # page 3 = bank 1, presets 64-127 59 | # ... 60 | # The number of total available pages depends on the synth. 61 | return self.current_page 62 | 63 | def get_num_banks(self): 64 | # Returns the number of available banks of the selected device 65 | return self.app.track_selection_mode.get_current_track_device_info().get('n_banks', 1) 66 | 67 | def get_bank_names(self): 68 | # Returns list of bank names 69 | return self.app.track_selection_mode.get_current_track_device_info().get('bank_names', None) 70 | 71 | def get_num_pages(self): 72 | # Returns the number of available preset pages per device (2 per bank) 73 | return self.get_num_banks() * 2 74 | 75 | def next_page(self): 76 | if self.current_page < self.get_num_pages() - 1: 77 | self.current_page += 1 78 | else: 79 | self.current_page = self.get_num_pages() - 1 80 | self.app.pads_need_update = True 81 | self.app.buttons_need_update = True 82 | self.notify_status_in_display() 83 | 84 | def prev_page(self): 85 | if self.current_page > 0: 86 | self.current_page -= 1 87 | else: 88 | self.current_page = 0 89 | self.app.pads_need_update = True 90 | self.app.buttons_need_update = True 91 | self.notify_status_in_display() 92 | 93 | def has_prev_next_pages(self): 94 | has_next = False 95 | has_prev = False 96 | if self.get_current_page() < self.get_num_pages() - 1: 97 | has_next = True 98 | if self.get_current_page() > 0: 99 | has_prev = True 100 | return (has_prev, has_next) 101 | 102 | def pad_ij_to_bank_and_preset_num(self, pad_ij): 103 | preset_num = (self.get_current_page() % 2) * 64 + pad_ij[0] * 8 + pad_ij[1] 104 | bank_num = self.get_current_page() // 2 105 | return (preset_num, bank_num) 106 | 107 | def notify_status_in_display(self): 108 | bank_number = self.get_current_page() // 2 + 1 109 | bank_names = self.get_bank_names() 110 | if bank_names is not None: 111 | bank_name = bank_names[bank_number - 1] 112 | else: 113 | bank_name = bank_number 114 | self.app.add_display_notification("Preset selection: bank {0}, presets {1}".format( 115 | bank_name, 116 | '1-64' if self.get_current_page() % 2 == 0 else '65-128' 117 | )) 118 | 119 | def activate(self): 120 | self.update_buttons() 121 | self.update_pads() 122 | self.notify_status_in_display() 123 | 124 | def deactivate(self): 125 | # Run supperclass deactivate to set all used buttons to black 126 | super().deactivate() 127 | # Also set all pads to black 128 | self.app.push.pads.set_all_pads_to_color(color=definitions.BLACK) 129 | 130 | def update_buttons(self): 131 | show_prev, show_next = self.has_prev_next_pages() 132 | self.set_button_color_if_expression(self.page_left_button, show_prev) 133 | self.set_button_color_if_expression(self.page_right_button, show_next) 134 | 135 | def update_pads(self): 136 | device_short_name = self.app.track_selection_mode.get_current_track_device_short_name() 137 | track_color = self.app.track_selection_mode.get_current_track_color() 138 | color_matrix = [] 139 | for i in range(0, 8): 140 | row_colors = [] 141 | for j in range(0, 8): 142 | cell_color = track_color 143 | preset_num, bank_num = self.pad_ij_to_bank_and_preset_num((i, j)) 144 | if not self.preset_num_in_favourites(preset_num, bank_num): 145 | cell_color = f'{cell_color}_darker2' # If preset not in favourites, use a darker version of the track color 146 | row_colors.append(cell_color) 147 | color_matrix.append(row_colors) 148 | self.push.pads.set_pads_color(color_matrix) 149 | 150 | def on_pad_pressed(self, pad_n, pad_ij, velocity, shift=False, select=False, long_press=False, double_press=False): 151 | preset_num, bank_num = self.pad_ij_to_bank_and_preset_num(pad_ij) 152 | if long_press: 153 | # Add/remove preset to favourites, don't send any MIDI 154 | if not self.preset_num_in_favourites(preset_num, bank_num): 155 | self.add_favourite_preset(preset_num, bank_num) 156 | else: 157 | self.remove_favourite_preset(preset_num, bank_num) 158 | else: 159 | # Send midi message to select the bank and preset 160 | try: 161 | track = self.session.tracks[self.app.track_selection_mode.selected_track] 162 | hardware_device = track.get_output_hardware_device() 163 | if hardware_device is not None: 164 | hardware_device.load_preset(bank_num, preset_num) 165 | 166 | bank_names = self.get_bank_names() 167 | if bank_names is not None: 168 | bank_name = bank_names[bank_num] 169 | else: 170 | bank_name = bank_num + 1 171 | self.app.add_display_notification("Selected bank {0}, preset {1}".format( 172 | bank_name, # Show 1-indexed value 173 | preset_num + 1 # Show 1-indexed value 174 | )) 175 | except IndexError: 176 | pass 177 | 178 | self.app.pads_need_update = True 179 | return True # Prevent other modes to get this event 180 | 181 | def on_button_pressed(self, button_name, shift=False, select=False, long_press=False, double_press=False): 182 | if button_name in [self.page_left_button, self.page_right_button]: 183 | show_prev, show_next = self.has_prev_next_pages() 184 | if button_name == self.page_left_button and show_prev: 185 | self.prev_page() 186 | elif button_name == self.page_right_button and show_next: 187 | self.next_page() 188 | return True 189 | -------------------------------------------------------------------------------- /SourceShepherdPush2Controller/modes/rhythmic_mode.py: -------------------------------------------------------------------------------- 1 | import definitions 2 | import push2_python.constants 3 | 4 | from .melodic_mode import MelodicMode 5 | 6 | 7 | class RhythmicMode(MelodicMode): 8 | 9 | rhythmic_notes_matrix = [ 10 | [64, 65, 66, 67, 96, 97, 98, 99], 11 | [60, 61, 62, 63, 92, 93, 94, 95], 12 | [56, 57, 58, 59, 88, 89, 90, 91], 13 | [52, 53, 54, 55, 84, 85, 86, 87], 14 | [48, 49, 50, 51, 80, 81, 82, 83], 15 | [44, 45, 46, 47, 76, 77, 78, 79], 16 | [40, 41, 42, 43, 72, 73, 74, 75], 17 | [36, 37, 38, 39, 68, 69, 70, 71] 18 | ] 19 | 20 | def get_settings_to_save(self): 21 | return {} 22 | 23 | def pad_ij_to_midi_note(self, pad_ij): 24 | return self.rhythmic_notes_matrix[pad_ij[0]][pad_ij[1]] 25 | 26 | def update_octave_buttons(self): 27 | # Rhythmic does not have octave buttons 28 | pass 29 | 30 | def update_pads(self): 31 | color_matrix = [] 32 | for i in range(0, 8): 33 | row_colors = [] 34 | for j in range(0, 8): 35 | corresponding_midi_note = self.pad_ij_to_midi_note([i, j]) 36 | cell_color = definitions.BLACK 37 | if i >= 4 and j < 4: 38 | # This is the main 4x4 grid 39 | cell_color = self.app.track_selection_mode.get_current_track_color() 40 | elif i >= 4 and j >= 4: 41 | cell_color = definitions.GRAY_LIGHT 42 | elif i < 4 and j < 4: 43 | cell_color = definitions.GRAY_LIGHT 44 | elif i < 4 and j >= 4: 45 | cell_color = definitions.GRAY_LIGHT 46 | if self.is_midi_note_being_played(corresponding_midi_note): 47 | cell_color = definitions.NOTE_ON_COLOR 48 | 49 | row_colors.append(cell_color) 50 | color_matrix.append(row_colors) 51 | 52 | self.push.pads.set_pads_color(color_matrix) 53 | 54 | def on_button_pressed(self, button_name, shift=False, select=False, long_press=False, double_press=False): 55 | if button_name == push2_python.constants.BUTTON_OCTAVE_UP or button_name == push2_python.constants.BUTTON_OCTAVE_DOWN: 56 | # Don't react to octave up/down buttons as these are not used in rhythm mode 57 | pass 58 | else: 59 | # For the other buttons, refer to the base class 60 | super().on_button_pressed(button_name, shift, select, long_press, double_press) 61 | -------------------------------------------------------------------------------- /SourceShepherdPush2Controller/modes/slice_notes_mode.py: -------------------------------------------------------------------------------- 1 | import definitions 2 | import push2_python.constants 3 | 4 | from .melodic_mode import MelodicMode 5 | 6 | 7 | class SliceNotesMode(MelodicMode): 8 | 9 | start_note = 0 10 | color_groups = [ 11 | definitions.GREEN, 12 | definitions.YELLOW, 13 | definitions.ORANGE, 14 | definitions.RED, 15 | definitions.PINK, 16 | definitions.PURPLE, 17 | definitions.CYAN, 18 | definitions.BLUE 19 | ] 20 | 21 | def get_settings_to_save(self): 22 | return {} 23 | 24 | def pad_ij_to_midi_note(self, pad_ij): 25 | return self.start_note + 8 * (7 - pad_ij[0]) + pad_ij[1] 26 | 27 | def update_pads(self): 28 | color_matrix = [] 29 | for i in range(0, 8): 30 | row_colors = [] 31 | for j in range(0, 8): 32 | corresponding_midi_note = self.pad_ij_to_midi_note([i, j]) 33 | midi_16_note_groups_idx = corresponding_midi_note // 16 34 | if midi_16_note_groups_idx % 2 == 0: 35 | cell_color = self.app.track_selection_mode.get_current_track_color() 36 | else: 37 | cell_color = definitions.WHITE 38 | if self.is_midi_note_being_played(corresponding_midi_note): 39 | cell_color = definitions.NOTE_ON_COLOR 40 | row_colors.append(cell_color) 41 | color_matrix.append(row_colors) 42 | 43 | self.push.pads.set_pads_color(color_matrix) 44 | 45 | def on_button_pressed(self, button_name, shift=False, select=False, long_press=False, double_press=False): 46 | if button_name == push2_python.constants.BUTTON_OCTAVE_UP: 47 | self.start_note += 16 48 | if self.start_note > 128 - 16 * 4: 49 | self.start_note = 128 - 16 * 4 50 | self.app.pads_need_update = True 51 | self.update_pads_backend_mapping() 52 | self.app.add_display_notification("MIDI notes range: {0} to {1}".format( 53 | self.pad_ij_to_midi_note((7, 0)), 54 | self.pad_ij_to_midi_note((0, 7)), 55 | )) 56 | return True 57 | 58 | elif button_name == push2_python.constants.BUTTON_OCTAVE_DOWN: 59 | self.start_note -= 16 60 | if self.start_note < 0: 61 | self.start_note = 0 62 | self.app.pads_need_update = True 63 | self.update_pads_backend_mapping() 64 | self.app.add_display_notification("MIDI notes range: {0} to {1}".format( 65 | self.pad_ij_to_midi_note((7, 0)), 66 | self.pad_ij_to_midi_note((0, 7)), 67 | )) 68 | return True 69 | 70 | else: 71 | # For the other buttons, refer to the base class 72 | super().on_button_pressed(button_name, shift, select, long_press, double_press) 73 | -------------------------------------------------------------------------------- /SourceShepherdPush2Controller/modes/sound_edit_mode.py: -------------------------------------------------------------------------------- 1 | import definitions 2 | import push2_python 3 | 4 | from definitions import ShepherdControllerMode 5 | from utils import show_text, draw_knob 6 | 7 | 8 | class SoundEditMode(ShepherdControllerMode): 9 | 10 | tabs_button_names = [ 11 | push2_python.constants.BUTTON_UPPER_ROW_1, 12 | push2_python.constants.BUTTON_UPPER_ROW_2, 13 | push2_python.constants.BUTTON_UPPER_ROW_3, 14 | push2_python.constants.BUTTON_UPPER_ROW_4, 15 | push2_python.constants.BUTTON_UPPER_ROW_5, 16 | push2_python.constants.BUTTON_UPPER_ROW_6, 17 | push2_python.constants.BUTTON_UPPER_ROW_7, 18 | push2_python.constants.BUTTON_UPPER_ROW_8 19 | ] 20 | page_left_button = push2_python.constants.BUTTON_PAGE_LEFT 21 | page_right_button = push2_python.constants.BUTTON_PAGE_RIGHT 22 | 23 | buttons_used = tabs_button_names + [page_left_button, page_right_button] 24 | current_tab = 0 25 | 26 | tabs = [ 27 | {}, 28 | {}, 29 | {} 30 | ] 31 | 32 | def get_current_track_color_helper(self): 33 | return self.app.track_selection_mode.get_current_track_color() 34 | 35 | def get_should_show_next_prev_page_buttons(self): 36 | show_prev = False 37 | if self.current_tab > 0: 38 | show_prev = True 39 | show_next = False 40 | if self.current_tab + 1 < len(self.tabs): 41 | show_next = True 42 | return show_prev, show_next 43 | 44 | def activate(self): 45 | self.update_buttons() 46 | 47 | def update_buttons(self): 48 | for count, name in enumerate(self.tabs_button_names): 49 | self.set_button_color_if_expression(name, count < len(self.tabs), false_color=definitions.BLACK) 50 | show_prev, show_next = self.get_should_show_next_prev_page_buttons() 51 | self.set_button_color_if_expression(self.page_left_button, show_prev) 52 | self.set_button_color_if_expression(self.page_right_button, show_next) 53 | 54 | def update_display(self, ctx, w, h): 55 | if not self.app.is_mode_active(self.app.settings_mode) and \ 56 | not self.app.is_mode_active(self.app.clip_triggering_mode) and \ 57 | not self.app.is_mode_active(self.app.clip_edit_mode): 58 | # If settings mode is active, don't draw the upper parts of the screen because settings page will 59 | # "cover them" 60 | 61 | current_track_color = self.get_current_track_color_helper() 62 | 63 | # Draw tab names 64 | tab_names = ["Tab {}".format(count + 1) for count, _ in enumerate(self.tabs)] 65 | if tab_names: 66 | height = 20 67 | for i, tab_name in enumerate(tab_names): 68 | show_text(ctx, i, 0, tab_name, background_color=definitions.RED) 69 | is_selected = self.current_tab == i 70 | if is_selected: 71 | background_color = current_track_color 72 | font_color = definitions.BLACK 73 | else: 74 | background_color = definitions.BLACK 75 | font_color = current_track_color 76 | show_text(ctx, i, 0, tab_name, height=height, 77 | font_color=font_color, background_color=background_color) 78 | 79 | # TODO: Draw actual controls 80 | sound_name = self.app.source_interface.get_sound_property(self.app.track_selection_mode.selected_track, 'name_sound', default='Unknown sound') 81 | show_text(ctx, 0, 25, sound_name, height=30, 82 | font_color=current_track_color, background_color=definitions.BLACK) 83 | 84 | def on_button_pressed(self, button_name, shift=False, select=False, long_press=False, double_press=False): 85 | if button_name in self.tabs_button_names: 86 | idx = self.tabs_button_names.index(button_name) 87 | if idx < len(self.tabs): 88 | self.current_tab = idx 89 | return True 90 | 91 | elif button_name in [self.page_left_button, self.page_right_button]: 92 | show_prev, show_next = self.get_should_show_next_prev_page_buttons() 93 | if button_name == self.page_left_button and show_prev: 94 | self.current_tab -= 1 95 | elif button_name == self.page_right_button and show_next: 96 | self.current_tab += 1 97 | return True 98 | -------------------------------------------------------------------------------- /SourceShepherdPush2Controller/modes/track_selection_mode.py: -------------------------------------------------------------------------------- 1 | import definitions 2 | import push2_python 3 | import os 4 | import json 5 | 6 | from utils import show_text 7 | 8 | import pyshepherd.pyshepherd 9 | 10 | 11 | class TrackSelectionMode(definitions.ShepherdControllerMode): 12 | 13 | devices_info = {} 14 | 15 | track_button_names = [ 16 | push2_python.constants.BUTTON_LOWER_ROW_1, 17 | push2_python.constants.BUTTON_LOWER_ROW_2, 18 | push2_python.constants.BUTTON_LOWER_ROW_3, 19 | push2_python.constants.BUTTON_LOWER_ROW_4, 20 | push2_python.constants.BUTTON_LOWER_ROW_5, 21 | push2_python.constants.BUTTON_LOWER_ROW_6, 22 | push2_python.constants.BUTTON_LOWER_ROW_7, 23 | push2_python.constants.BUTTON_LOWER_ROW_8 24 | ] 25 | selected_track = 0 26 | 27 | def get_selected_track(self): 28 | return self.session.get_track_by_idx(self.selected_track) 29 | 30 | def initialize(self, settings=None): 31 | if settings is not None: 32 | pass 33 | 34 | self.load_hardware_devices_info() 35 | 36 | def load_hardware_devices_info(self): 37 | """ 38 | This method loads hardware device (aka instrument) definitions from definition files. 39 | These contain some information about the device which is useful to show a proper UI (for 40 | example, a list of midi CC parameter mappings). 41 | """ 42 | print('Loading hardware device definitions...') 43 | try: 44 | for filename in os.listdir(definitions.DEVICE_DEFINITION_FOLDER): 45 | if filename.endswith('.json'): 46 | device_short_name = filename.replace('.json', '') 47 | self.devices_info[device_short_name] = json.load(open(os.path.join(definitions.DEVICE_DEFINITION_FOLDER, filename))) 48 | print('- {}'.format(device_short_name)) 49 | except FileNotFoundError: 50 | # No definitions file present 51 | pass 52 | 53 | def get_settings_to_save(self): 54 | return {} 55 | 56 | def get_all_distinct_device_short_names(self): 57 | return list(set([track.output_hardware_device_name for track in self.session.tracks])) 58 | 59 | def get_current_track_device_info(self): 60 | return self.devices_info.get(self.get_selected_track().output_hardware_device_name, {}) 61 | 62 | def get_current_track_device_short_name(self): 63 | return self.get_selected_track().output_hardware_device_name 64 | 65 | def get_track_color(self, track: pyshepherd.pyshepherd.Track): 66 | try: 67 | track_idx = [idx for idx, t in enumerate(self.session.tracks) if track.uuid == t.uuid][0] 68 | except IndexError: 69 | track_idx = 0 70 | return definitions.COLORS_NAMES[track_idx % 8] 71 | 72 | def get_current_track_color(self): 73 | return self.get_track_color(self.get_selected_track()) 74 | 75 | def get_current_track_color_rgb(self): 76 | return definitions.get_color_rgb_float(self.get_current_track_color()) 77 | 78 | def load_current_default_layout(self): 79 | if self.get_current_track_device_info().get('default_layout', definitions.LAYOUT_MELODIC) == definitions.LAYOUT_MELODIC: 80 | self.app.set_melodic_mode() 81 | elif self.get_current_track_device_info().get('default_layout', definitions.LAYOUT_MELODIC) == definitions.LAYOUT_RHYTHMIC: 82 | self.app.set_rhythmic_mode() 83 | elif self.get_current_track_device_info().get('default_layout', definitions.LAYOUT_MELODIC) == definitions.LAYOUT_SLICES: 84 | self.app.set_slice_notes_mode() 85 | 86 | def clean_currently_notes_being_played(self): 87 | if self.app.is_mode_active(self.app.melodic_mode): 88 | self.app.melodic_mode.remove_all_notes_being_played() 89 | elif self.app.is_mode_active(self.app.rhyhtmic_mode): 90 | self.app.rhyhtmic_mode.remove_all_notes_being_played() 91 | 92 | def send_select_track(self, track_idx): 93 | # Enabled input monitoring for the selected track only 94 | tracks = self.session.tracks 95 | for i in range(0, len(tracks)): 96 | tracks[i].set_input_monitoring(i == track_idx) 97 | 98 | def select_track(self, track_idx): 99 | # Selects a track 100 | # Note that if this is called from a mode from the same xor group with melodic/rhythmic modes, 101 | # that other mode will be deactivated. 102 | track = self.session.get_track_by_idx(track_idx) 103 | if track is not None: 104 | self.selected_track = track_idx 105 | self.send_select_track(self.selected_track) 106 | self.clean_currently_notes_being_played() 107 | try: 108 | self.app.preset_selection_mode.new_track_selected() 109 | self.app.clip_triggering_mode.new_track_selected() 110 | self.app.melodic_mode.send_all_note_offs_to_lumi() 111 | except AttributeError: 112 | # Might fail if MIDICCMode/PresetSelectionMode/ClipTriggeringMode not initialized 113 | pass 114 | track.set_active_ui_notes_monitoring() 115 | 116 | def activate(self): 117 | self.update_buttons() 118 | self.update_pads() 119 | self.select_track(self.selected_track) 120 | 121 | def deactivate(self): 122 | for button_name in self.track_button_names: 123 | self.push.buttons.set_button_color(button_name, definitions.BLACK) 124 | 125 | def update_buttons(self): 126 | for count, name in enumerate(self.track_button_names): 127 | color = self.get_track_color(self.session.tracks[count]) 128 | self.push.buttons.set_button_color(name, color) 129 | 130 | def update_display(self, ctx, w, h): 131 | # Draw track selector labels 132 | height = 20 133 | for i in range(0, len(self.session.tracks)): 134 | track_color = self.get_track_color(self.session.tracks[i]) 135 | if self.selected_track == i: 136 | background_color = track_color 137 | font_color = definitions.BLACK 138 | else: 139 | background_color = definitions.BLACK 140 | font_color = track_color 141 | track = self.session.get_track_by_idx(i) 142 | device_short_name = track.output_hardware_device_name 143 | if track.input_monitoring: 144 | device_short_name = '+' + device_short_name 145 | show_text(ctx, i, h - height, device_short_name, height=height, 146 | font_color=font_color, background_color=background_color) 147 | 148 | def on_button_pressed(self, button_name, shift=False, select=False, long_press=False, double_press=False): 149 | if button_name in self.track_button_names: 150 | track_idx = self.track_button_names.index(button_name) 151 | track = self.session.get_track_by_idx(track_idx) 152 | if track is not None: 153 | if long_press: 154 | # Toggle input monitoring 155 | if track.input_monitoring: 156 | track.set_input_monitoring(False) 157 | else: 158 | track.set_input_monitoring(True) 159 | else: 160 | if not shift: 161 | # If button shift not pressed, select the track 162 | self.select_track(self.track_button_names.index(button_name)) 163 | else: 164 | # If button shift pressed, send all notes off to that track 165 | try: 166 | track = self.session.tracks[track_idx] 167 | hardware_device = track.get_output_hardware_device() 168 | if hardware_device is not None: 169 | hardware_device.all_notes_off() 170 | except IndexError: 171 | pass 172 | -------------------------------------------------------------------------------- /SourceShepherdPush2Controller/requirements.txt: -------------------------------------------------------------------------------- 1 | git+https://github.com/ffont/push2-python 2 | pycairo 3 | psutil 4 | websocket-client 5 | lxml 6 | bs4 7 | mido 8 | torch # Optional ,needed for groove transformer to run 9 | numpy -------------------------------------------------------------------------------- /docs/SOURCE diagram.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/docs/SOURCE diagram.key -------------------------------------------------------------------------------- /docs/SOURCE-complementary-UI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/docs/SOURCE-complementary-UI.png -------------------------------------------------------------------------------- /docs/SOURCE-main-diagram-elk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/docs/SOURCE-main-diagram-elk.png -------------------------------------------------------------------------------- /docs/SOURCE-main-diagram-plugin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/docs/SOURCE-main-diagram-plugin.png -------------------------------------------------------------------------------- /docs/SOURCE-photo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/docs/SOURCE-photo.png -------------------------------------------------------------------------------- /docs/class_diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/docs/class_diagram.png -------------------------------------------------------------------------------- /docs/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/docs/icon.png -------------------------------------------------------------------------------- /docs/logos.afdesign: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/docs/logos.afdesign -------------------------------------------------------------------------------- /docs/ra_logo_web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/docs/ra_logo_web.png -------------------------------------------------------------------------------- /docs/simulator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/docs/simulator.png -------------------------------------------------------------------------------- /docs/source_600.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/docs/source_600.png -------------------------------------------------------------------------------- /docs/source_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/docs/source_logo.png -------------------------------------------------------------------------------- /docs/source_logo_headline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/docs/source_logo_headline.png -------------------------------------------------------------------------------- /docs/upf_logo_web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/docs/upf_logo_web.png -------------------------------------------------------------------------------- /elk_platform/build_system/custom-esdk-launch.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # esdk-launch.py 4 | # 5 | # Copyright (C) 2016 Intel Corporation 6 | # 7 | # This program is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License version 2 as 9 | # published by the Free Software Foundation. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along 17 | # with this program; if not, write to the Free Software Foundation, Inc., 18 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | import argparse 20 | import os 21 | import sys 22 | import glob 23 | import subprocess 24 | import tempfile 25 | import shutil 26 | import stat 27 | 28 | 29 | class EsdkLaunchError(Exception): 30 | pass 31 | 32 | 33 | def download_esdk(url, dest): 34 | cmd = "curl -# -o {} {}".format(dest, url).split() 35 | 36 | try: 37 | print "Attempting to download {}".format(url) 38 | subprocess.check_call(cmd, stdout=sys.stdout, stderr=sys.stderr) 39 | except subprocess.CalledProcessError: 40 | errormsg = 'Unable to download "{}".'.format(args.url) 41 | raise EsdkLaunchError(errormsg) 42 | 43 | 44 | def setup_esdk(installer, dest): 45 | cmd = "{} -d {} -y".format(installer, dest).split() 46 | try: 47 | subprocess.check_call(cmd, stdout=sys.stdout, stderr=sys.stderr) 48 | except subprocess.CalledProcessError: 49 | errormsg = 'Unable to setup sdk.'.format(args.url) 50 | raise EsdkLaunchError(errormsg) 51 | 52 | 53 | parser = argparse.ArgumentParser() 54 | 55 | parser.add_argument("--url", help="url of the extensible sdk installer") 56 | parser.add_argument("--workdir", default='/workdir', 57 | help="Directory containing the prepared extensible sdk. " 58 | "Or the location to prepare the sdk if url is " 59 | "specfied.") 60 | 61 | args = parser.parse_args() 62 | 63 | try: 64 | if not os.path.exists(args.workdir): 65 | os.mkdir(args.workdir) 66 | 67 | setupscript = glob.glob(os.path.join(args.workdir, "environment-setup-*")) 68 | esdkfound = setupscript and os.path.exists(os.path.join(args.workdir, 69 | "sysroots")) 70 | 71 | if esdkfound and args.url: 72 | errormsg = ('An extensible sdk was found in {} yet "--url" was also ' 73 | 'specified. Cowardly refusing to overwrite existing sdk.') 74 | errormsg = errormsg.format(args.workdir) 75 | raise EsdkLaunchError(errormsg) 76 | 77 | elif not esdkfound and not args.url: 78 | errormsg = ('An extensible sdk was not found in {}. "--url" must be ' 79 | 'specified.') 80 | errormsg = errormsg.format(args.workdir) 81 | raise EsdkLaunchError(errormsg) 82 | 83 | if args.url: 84 | # Add a special mechanism for installing directly from the file 85 | # rather than trying to download. For example let's say a user had 86 | # already downloaded a large sdk installer to the workdir. Even 87 | # copying the file using curl with FILE: might take a while and will 88 | # also use more space. 89 | # 90 | # So if the "url" starts with "/" then treat it as something that 91 | # should directly be installed. 92 | if args.url.startswith('/'): 93 | esdk_installer = args.url 94 | else: 95 | tempdir = tempfile.mkdtemp(prefix="esdk-download", 96 | dir=args.workdir) 97 | esdk_installer = os.path.join(tempdir, "esdk-installer.sh") 98 | download_esdk(args.url, esdk_installer) 99 | 100 | oldmode = os.stat(esdk_installer).st_mode 101 | os.chmod(esdk_installer, stat.S_IXUSR | oldmode) 102 | 103 | setup_esdk(esdk_installer, args.workdir) 104 | setupscript = glob.glob(os.path.join(args.workdir, 105 | "environment-setup-*")) 106 | 107 | # Since we don't want the user to have to download a very large image 108 | # again if the install fails, we don't delete the tmpdir on failure. 109 | try: 110 | shutil.rmtree(tempdir, ignore_errors=True) 111 | except NameError: 112 | pass 113 | 114 | # Source the environment setup script and run bash 115 | # NOTE: the flag DJUCE_HEADLESS_PLUGIN_CLIENT is only needed for JUCE5 builds, but we always add it anyway 116 | path_to_makefile = os.environ['CC_PATH_TO_MAKEFILE'] 117 | config = os.environ.get('CC_CONFIG', 'Release') 118 | print('Cross-compiling with:\n CC_CONFIG={0}\n CC_PATH_TO_MAKEFILE={1}'.format(config, path_to_makefile)) 119 | cmd = 'bash -c'.split() 120 | args = """ 121 | cd {0}; 122 | . {1}; 123 | cd {2} 124 | unset LD_LIBRARY_PATH 125 | source /workdir/environment-setup-aarch64-elk-linux 126 | export CXXFLAGS="-O3 -pipe -ffast-math -feliminate-unused-debug-types -funroll-loops" 127 | AR=aarch64-elk-linux-ar make -j2 CONFIG={3} CFLAGS="-DJUCE_HEADLESS_PLUGIN_CLIENT=1 -DELK_BUILD=1 -Wno-psabi" TARGET_ARCH="-mcpu=cortex-a72 -mtune=cortex-a72" -i 128 | """.format(args.workdir, setupscript[0], path_to_makefile, config) 129 | os.execvp(cmd[0], cmd + [args]) 130 | 131 | except EsdkLaunchError as e: 132 | print e 133 | sys.exit(1) 134 | -------------------------------------------------------------------------------- /elk_platform/config/sensei.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=sensei starting service 3 | After=load-drivers.service 4 | ConditionPathExists=/dev/rtdm/shiftreg_rtdm 5 | 6 | [Service] 7 | Type=simple 8 | RemainAfterExit=yes 9 | WorkingDirectory=/udata/ 10 | Environment=LD_LIBRARY_PATH=/usr/xenomai/lib 11 | ExecStart=/usr/bin/sensei -f /udata/source/config/source_sensei_config.json 12 | User=mind 13 | 14 | [Install] 15 | WantedBy=multi-user.target -------------------------------------------------------------------------------- /elk_platform/config/source.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=source glue app starting service 3 | After=load-drivers.service 4 | ConditionPathExists=/dev/rtdm/audio_rtdm 5 | 6 | [Service] 7 | Type=simple 8 | RemainAfterExit=no 9 | WorkingDirectory=/udata/source/ui_app/ 10 | ExecStart=python3 main 11 | User=mind 12 | Restart=always 13 | RestartSec=3 14 | 15 | [Install] 16 | WantedBy=multi-user.target -------------------------------------------------------------------------------- /elk_platform/config/source_sushi_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "host_config": { 3 | "samplerate": 48000 4 | }, 5 | "tracks": [ 6 | { 7 | "name": "main", 8 | "mode": "stereo", 9 | "inputs": [], 10 | "outputs": [ 11 | { 12 | "engine_bus": 0, 13 | "track_bus": 0 14 | } 15 | ], 16 | "plugins": [ 17 | { 18 | "path": "/udata/source/plugin/SourceSamplerVST2.so", 19 | "name": "SourceSampler", 20 | "type": "vst2x", 21 | "uid": "SourceSampler" 22 | } 23 | ] 24 | } 25 | ] 26 | } -------------------------------------------------------------------------------- /elk_platform/config/sushi.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=sushi starting service 3 | After=source.service 4 | # We start sushi after source so that the glue app is running and can receive download requests from the plugin when it starts and loads first preset 5 | # source.service is triggered after audio driver is ready, therefore sushi.service will also be called when audio driver is ready 6 | 7 | [Service] 8 | Type=simple 9 | RemainAfterExit=no 10 | WorkingDirectory=/udata/ 11 | Environment=LD_LIBRARY_PATH=/usr/xenomai/lib 12 | ExecStart=/usr/bin/sushi -r --multicore-processing=3 -c /udata/source/config/source_sushi_config.json 13 | User=mind 14 | Restart=always 15 | RestartSec=3 16 | 17 | [Install] 18 | WantedBy=multi-user.target -------------------------------------------------------------------------------- /elk_platform/ui_app/elk_ui_custom.py: -------------------------------------------------------------------------------- 1 | """ elk_ui.py 2 | 3 | Utility class to handle the UI on Elk Pi hats in a Pythonic way. 4 | """ 5 | 6 | __copyright__ = "Copyright (C) 2020 Modern Ancient Instruments Networked AB, dba Elk" 7 | __license__ = "GPL-3.0" 8 | 9 | import math 10 | import time 11 | import os.path 12 | import liblo 13 | 14 | from demo_opts import get_device as get_display_device 15 | import luma.core.render as render 16 | 17 | ###################### 18 | # Module Constants # 19 | ###################### 20 | 21 | # Control config 22 | N_FADERS = 4 23 | N_BUTTONS = 9 24 | N_LEDS = 9 25 | LED_BASE_IDX = 1 26 | LED_FADER_IDXS = [10, 12, 11, None] 27 | ANALOG_SENSORS_MIN_ABS_DIFF = (1.0 / 128) 28 | ROT_ENC_ID = 23 29 | 30 | # OSC ports 31 | SENSEI_TO_BRIDGE_PORT = 23023 32 | BRIDGE_TO_SENSEI_PORT = 23024 33 | 34 | # OSC paths 35 | FADER_PATH_PREFIX = "/sensors/analog/fader_" 36 | BUTTON_PATH_PREFIX = "/sensors/digital/button_" 37 | ROT_ENC_BUTTON_PATH = "/sensors/digital/rot_enc_button" 38 | ROT_ENC_PATH = "/sensors/analog/rot_enc" 39 | POTENTIOMETER_PATH = "/sensors/analog/pot_A" 40 | 41 | # OLED display 42 | DISPLAY_CONFIG = ["--display", "ssd1306", "--i2c-port", "0", "--i2c-address", "0x3C", "--width", "128", "--height", "64"] 43 | RESET_PIN_INDEX = 31 44 | 45 | 46 | #################### 47 | # Public classes # 48 | #################### 49 | 50 | class ElkUIController(object): 51 | """ Utility class to access controls and LEDs / displays on the UI hat for Elk Pi. 52 | 53 | Inputs are handled through callbacks passed at initialization time. 54 | 55 | Outputs (LEDs & OLED display) can be controlled via the set_* methods. 56 | 57 | The refresh() method needs to be called periodically (e.g., every 20-30 ms) 58 | to refresh the OLED display. 59 | """ 60 | 61 | def __init__(self, 62 | faders_callback, 63 | buttons_callback, 64 | encoder_button_callback, 65 | encoder_callback, 66 | pot_callback, 67 | sensei_ctrl_port=SENSEI_TO_BRIDGE_PORT, 68 | sensei_led_port=BRIDGE_TO_SENSEI_PORT): 69 | """ Initialization. 70 | 71 | Inputs: 72 | faders_callback : function with args (fader_idx, val) 73 | Will be invoked when an analog fader is moved. 74 | Callback arguments: 75 | fader_idx : int (0 = A, 1 = B, 2 = C, 3 = D) 76 | val : fader value from 0.0 to 1.0 77 | 78 | buttons_callback : function with args (button_idx, val) 79 | It will be invoked whenever a button is pressed or released. 80 | Callback arguments: 81 | button_idx : index of the button (0..8) 82 | val : button status (1=pressed, 0=released) 83 | 84 | encoder_button_callback : callback to invoke when rotary encoder button is pressed 85 | Callback arguments: 86 | val : button status (1=pressed, 0=released) 87 | 88 | 89 | encoder_callback : function with a single argument (direction) 90 | Will be invoked when the encoder is rotated. 91 | Callback arguments: 92 | direction : +1 if turned right, -1 if turned left 93 | 94 | sensei_ctrl_port : UDP port for incoming OSC messages from Sensei 95 | 96 | sensei_led_port : UDP port to output LED changes to Sensei 97 | """ 98 | self._osc_server = liblo.ServerThread(sensei_ctrl_port) 99 | self._sensei_address = ('localhost', sensei_led_port) 100 | 101 | self._btn_cback = buttons_callback 102 | self._enc_btn_cback = encoder_button_callback 103 | self._enc_cback = encoder_callback 104 | self._faders_cback = faders_callback 105 | self._pot_cback= pot_callback 106 | self._register_osc_callbacks() 107 | 108 | self.reset_display() 109 | self._display_dev = get_display_device(DISPLAY_CONFIG) 110 | self._display_dirty = False 111 | 112 | self.set_rot_enc_initial_val() 113 | 114 | def set_rot_enc_initial_val(self): 115 | """ 116 | Needed so that the rotary encoder is properly initialized and it can be rutned counter-clockwise from a start 117 | https://forum.elk.audio/t/blackboard-turning-rotary-encoder-has-no-effect-if-i-dont-turn-it-right-first/565/9 118 | """ 119 | osc_msg = liblo.Message('/set_output') 120 | osc_msg.add(('i', ROT_ENC_ID)) 121 | osc_msg.add(('f', 0.5)) 122 | liblo.send(self._sensei_address, osc_msg) 123 | 124 | def set_led(self, idx, val): 125 | """ Immediately set one of the LEDs on the board. 126 | Inputs: 127 | idx : LED idx from 0 to 8 128 | val : 1 = LED on, 0 = LED off 129 | """ 130 | osc_msg = liblo.Message('/set_output') 131 | osc_msg.add(('i', LED_BASE_IDX+idx)) 132 | osc_msg.add(('f', val)) 133 | liblo.send(self._sensei_address, osc_msg) 134 | 135 | def set_fader_led(self, idx, val): 136 | """ Immediately set one of the LEDs on the faders. 137 | Inputs: 138 | idx : fader idx from 0 to 3 139 | val : 1 = LED on, 0 = LED off 140 | """ 141 | led_idx = LED_FADER_IDXS[idx] 142 | if led_idx is not None: 143 | osc_msg = liblo.Message('/set_output') 144 | osc_msg.add(('i', led_idx)) 145 | osc_msg.add(('f', val)) 146 | liblo.send(self._sensei_address, osc_msg) 147 | 148 | def set_display_frame(self, im): 149 | """ Sets the frame contents to display. 150 | 'im' is a 1-bit PIL.Image object of size 128x64. 151 | """ 152 | self._display_frame = im 153 | self._display_dirty = True 154 | 155 | def run(self): 156 | """ Starts the Sensei OSC server. 157 | Needs to be called once the registered callbacks are ready to receive data. 158 | """ 159 | # Reset LED status 160 | for n in range(N_LEDS): 161 | self.set_led(n, 0) 162 | 163 | for n in range(N_FADERS): 164 | self.set_fader_led(n, 0) 165 | 166 | self._fader_values = [0.0] * N_FADERS 167 | self._pot_value = 0.7 # TODO: Get current pot value here 168 | self._enc_value = None 169 | self._osc_server.start() 170 | 171 | def refresh(self): 172 | """ Needs to be called periodically from the event loop to refresh the OLED display. 173 | """ 174 | if not self._display_dirty: 175 | return 176 | 177 | with render.canvas(self._display_dev) as draw: 178 | 179 | if self._display_frame is not None: 180 | # If _display_frame is set, display that frame 181 | draw.bitmap((0, 0), self._display_frame, fill="white") 182 | 183 | self._display_dirty = False 184 | 185 | 186 | def _register_osc_callbacks(self): 187 | for n in range(N_FADERS): 188 | self._osc_server.add_method(FADER_PATH_PREFIX + str(n), 'f', self._handle_faders) 189 | 190 | for n in range(N_BUTTONS): 191 | self._osc_server.add_method(BUTTON_PATH_PREFIX + str(n), 'f', self._handle_buttons) 192 | 193 | self._osc_server.add_method(ROT_ENC_PATH, 'f', self._handle_encoder) 194 | self._osc_server.add_method(ROT_ENC_BUTTON_PATH, 'f', self._handle_encoder_button) 195 | 196 | self._osc_server.add_method(POTENTIOMETER_PATH, 'f', self._handle_potentiometer) 197 | 198 | self._osc_server.add_method(None, None, self._unhandled_msg_callback) 199 | 200 | def _unhandled_msg_callback(self, path, args, types, src): 201 | print('Unknown OSC message %s from %s' % (path, src.url)) 202 | 203 | def _handle_faders(self, path, args): 204 | if self._faders_cback is None: 205 | return 206 | 207 | idx = int(path.split('_')[-1]) 208 | val = args[0] 209 | # Extra filtering for noise in faders 210 | if (abs(self._fader_values[idx] - val) > ANALOG_SENSORS_MIN_ABS_DIFF): 211 | self._faders_cback(idx, val) 212 | self._fader_values[idx] = val 213 | 214 | def _handle_buttons(self, path, args): 215 | if self._btn_cback is None: 216 | return 217 | 218 | idx = int(path.split('_')[-1]) 219 | val = args[0] 220 | self._btn_cback(idx, int(val)) 221 | 222 | def _handle_encoder_button(self, path, args): 223 | if self._enc_btn_cback is None: 224 | return 225 | val = args[0] 226 | self._enc_btn_cback(int(val)) 227 | 228 | def _handle_encoder(self, path, args): 229 | if self._enc_cback is None: 230 | return 231 | 232 | val = args[0] 233 | if self._enc_value is None: 234 | self._enc_value = val 235 | else: 236 | val_diff = val - self._enc_value 237 | if (abs(val_diff) > 0): 238 | direction = int(math.copysign(1, val_diff)) 239 | self._enc_cback(direction) 240 | self._enc_value = val 241 | 242 | def _handle_potentiometer(self, path, args): 243 | if self._pot_cback is None: 244 | return 245 | 246 | val = args[0] 247 | # Extra filtering for noise in faders 248 | if (abs(self._pot_value - val) > ANALOG_SENSORS_MIN_ABS_DIFF): 249 | self._pot_cback(val) 250 | self._pot_value = val 251 | 252 | def reset_display(self): 253 | osc_msg = liblo.Message('/set_output') 254 | osc_msg.add(('i', RESET_PIN_INDEX)) 255 | osc_msg.add(('i', 0)) 256 | 257 | liblo.send(self._sensei_address, osc_msg) 258 | time.sleep(0.05) 259 | osc_msg = liblo.Message('/set_output') 260 | osc_msg.add(('i', RESET_PIN_INDEX)) 261 | osc_msg.add(('i', 1)) 262 | 263 | liblo.send(self._sensei_address, osc_msg) 264 | 265 | time.sleep(0.5) 266 | 267 | -------------------------------------------------------------------------------- /elk_platform/ui_app/html/simulator.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SOURCE HW simulator 6 | 7 | 58 | 59 | 173 | 174 | 175 | 176 |

SOURCE HW simulator

177 |
178 | 179 |
180 | 181 | 182 | 183 | 184 |
185 |
186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 |
196 |
197 | 198 | 199 | 200 |
201 | 202 |
203 | 204 |

State monitor

205 | 206 | 207 | 208 | 209 | 210 | 211 | -------------------------------------------------------------------------------- /elk_platform/ui_app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | requests 3 | oscpy 4 | lxml 5 | bs4 6 | numpy==1.19.5 7 | Pillow 8 | scipy 9 | websocket-client 10 | -------------------------------------------------------------------------------- /elk_platform/ui_app/resources/FuturaHeavyfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/elk_platform/ui_app/resources/FuturaHeavyfont.ttf -------------------------------------------------------------------------------- /elk_platform/ui_app/resources/LiberationMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/elk_platform/ui_app/resources/LiberationMono-Regular.ttf -------------------------------------------------------------------------------- /elk_platform/ui_app/resources/logo_oled_fs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/elk_platform/ui_app/resources/logo_oled_fs.png -------------------------------------------------------------------------------- /elk_platform/ui_app/resources/logo_oled_ra.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/elk_platform/ui_app/resources/logo_oled_ra.png -------------------------------------------------------------------------------- /elk_platform/ui_app/resources/logo_oled_ra_b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/elk_platform/ui_app/resources/logo_oled_ra_b.png -------------------------------------------------------------------------------- /elk_platform/ui_app/resources/logo_oled_upf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/elk_platform/ui_app/resources/logo_oled_upf.png -------------------------------------------------------------------------------- /elk_platform/ui_app/sound_downloader.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | import urllib 4 | 5 | from freesound_interface import get_stored_access_token 6 | from helpers import sizeof_fmt 7 | 8 | 9 | class SoundDownloaderProgress: 10 | def __init__(self, url, outfile, sound_uuid, source_plugin_interface): 11 | self.time_started = time.time() 12 | self.old_percent = 0 13 | self.url = url 14 | self.outfile = outfile 15 | self.sound_uuid = sound_uuid 16 | self.source_plugin_interface = source_plugin_interface 17 | 18 | def download_progress_hook(self, count, blockSize, totalSize): 19 | percent = count * blockSize * 100 / totalSize 20 | if percent > 100.0: 21 | percent = 100.0 22 | if percent > self.old_percent: 23 | self.old_percent = percent 24 | self.source_plugin_interface.send_msg_to_plugin( 25 | '/downloading_sound_progress', [self.sound_uuid, self.outfile, percent]) 26 | if percent >= 100.0: 27 | os.rename(self.outfile + '.tmp', self.outfile) 28 | self.source_plugin_interface.send_msg_to_plugin( 29 | '/finished_downloading_sound', [self.sound_uuid, self.outfile, 1]) 30 | n_seconds = time.time() - self.time_started 31 | kbytes_per_second = count * blockSize / n_seconds / 1000 32 | print('- Finished downloading {} ({} at {:.0f}kbps)'.format( 33 | self.url, sizeof_fmt(totalSize), kbytes_per_second)) 34 | 35 | 36 | def download_sound(url, outfile, sound_uuid, use_header, source_plugin_interface): 37 | print('- Downloading ' + url) 38 | progress = SoundDownloaderProgress(url, outfile, sound_uuid, source_plugin_interface) 39 | if ':' in use_header: 40 | opener = urllib.request.build_opener() 41 | if len(use_header) > len('Authorization: Bearer ') + 10: 42 | # If the plugin has sent a header long enough so that it contains the actual access token, use it 43 | opener.addheaders = [(use_header.split(':')[0], use_header.split(':')[1])] 44 | else: 45 | # If the plugin did not send an access token, use the one storen in python ui code 46 | opener.addheaders = [('Authorization', 'Bearer {}'.format(get_stored_access_token()))] 47 | urllib.request.install_opener(opener) 48 | try: 49 | urllib.request.urlretrieve(url, outfile + '.tmp', reporthook=progress.download_progress_hook) 50 | except Exception as e: 51 | print('ERROR DOWNLOADING AFTER {:.2f} seconds: {}'.format(time.time()-progress.time_started, progress.url)) 52 | print(e) 53 | -------------------------------------------------------------------------------- /elk_platform/ui_app/system_stats.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | import time 4 | 5 | from helpers import get_platform, get_command_output 6 | 7 | system_stats = {} 8 | last_time_restarting_connman = 0 9 | network_currently_connected = False 10 | 11 | last_time_disk_space_checked = 0 12 | last_disk_space_percentage = -1.0 13 | last_disk_usage_bytes = -1.0 14 | last_disk_capacity_bytes = -1.0 15 | 16 | 17 | def get_disk_stats(): 18 | global last_time_disk_space_checked 19 | global last_disk_space_percentage 20 | global last_disk_usage_bytes 21 | global last_disk_capacity_bytes 22 | 23 | now = time.time() 24 | if now - last_time_disk_space_checked > 10.0: 25 | if get_platform() == "ELK": 26 | path_to_check = '/udata/' 27 | else: 28 | path_to_check = os.path.dirname(os.path.realpath(__file__)) 29 | total, used, free = shutil.disk_usage(__file__) 30 | last_disk_space_percentage = free/total 31 | last_disk_usage_bytes = free 32 | last_disk_capacity_bytes = total 33 | last_time_disk_space_checked = now 34 | 35 | return { 36 | 'disk_free_percentage': last_disk_space_percentage, 37 | 'disk_used_bytes': last_disk_usage_bytes, 38 | 'disk_capacity_bytes': last_disk_capacity_bytes 39 | } 40 | 41 | 42 | def collect_system_stats(): 43 | global system_stats 44 | global last_time_restarting_connman 45 | global network_currently_connected 46 | 47 | if get_platform() == "ELK": 48 | 49 | # Get system stats like cpu usage, temperature, etc. 50 | try: 51 | system_stats.update(get_disk_stats()) 52 | system_stats['temp'] = get_command_output("sudo vcgencmd measure_temp").replace('temp=', '').replace("'C", '') 53 | system_stats['cpu'] = get_command_output("/bin/grep 'cpu ' /proc/stat | awk '{usage=($2+$4)*100/($2+$4+$5)} END {print usage \"%\"}'")[0:4] 54 | system_stats['mem'] = get_command_output("free | /bin/grep Mem | awk '{print $3/$2 * 100.0}'")[0:4] 55 | proc_xenomai_output = get_command_output("/bin/more /proc/xenomai/sched/stat | /bin/grep sushi_b64") 56 | total_cpu = 0 57 | for line in proc_xenomai_output.split('\n'): 58 | total_cpu += float(line.split('sushi_b64')[0].strip().split(' ')[-1]) 59 | system_stats['xenomai_cpu'] = total_cpu 60 | system_stats['n_sushi_proc'] = get_command_output("/bin/ps -e | /bin/grep sushi | wc -l") 61 | 62 | # Check network status and reconnect if disconnected 63 | connmanctl_services_output = get_command_output("sudo connmanctl services") 64 | network_is_connected = '*AO' in connmanctl_services_output 65 | if network_is_connected: 66 | if not network_currently_connected: 67 | # Network has changed state from not connected to connected 68 | # Do some "initialization" stuff that requires a connection 69 | # NOTE: nothing to be done so far 70 | network_currently_connected = True # Set this to true so we don't do the initialization again 71 | 72 | system_stats['network_ssid'] = connmanctl_services_output.split('*AO ')[1].split(' ')[0] 73 | last_time_restarting_connman = 0 74 | else: 75 | system_stats['network_ssid'] = '-' + ' (R)' if last_time_restarting_connman != 0 else '' 76 | if time.time() - last_time_restarting_connman > 10: # Don't try to reconnect more often than every 10 seconds 77 | print('* Restarting connman') 78 | last_time_restarting_connman = time.time() 79 | get_command_output("sudo connmanctl enable wifi") 80 | get_command_output("sudo systemctl restart connman") 81 | 82 | # Check aconnect status and reconnect if disconnected 83 | aconnect_l_output = get_command_output("aconnect -l") 84 | aconnect_is_connected = 'Connected' in aconnect_l_output 85 | if not aconnect_is_connected: 86 | print('* Running aconnect') 87 | out = get_command_output("aconnect 16 128") 88 | print(out) 89 | 90 | except: 91 | system_stats = {} 92 | else: 93 | system_stats.update(get_disk_stats()) 94 | -------------------------------------------------------------------------------- /elk_platform/ui_app/ui_state_manager/__init__.py: -------------------------------------------------------------------------------- 1 | from .manager import state_manager, source_plugin_interface 2 | from .states_home import HomeState 3 | 4 | state_manager.move_to(HomeState()) 5 | -------------------------------------------------------------------------------- /elk_platform/ui_app/ui_state_manager/constants.py: -------------------------------------------------------------------------------- 1 | EXTRA_PAGE_1_NAME = "extra1" 2 | EXTRA_PAGE_2_NAME = "extra2" 3 | sound_parameter_pages = [ 4 | [ 5 | "gain", 6 | "pitch", 7 | "reverse", 8 | "launchMode", 9 | ], [ 10 | "noteMappingMode", 11 | "numSlices", 12 | "playheadPosition", 13 | "freezePlayheadSpeed", 14 | ], [ 15 | "startPosition", 16 | "endPosition", 17 | "loopStartPosition", 18 | "loopEndPosition", 19 | ], [ 20 | "attack", 21 | "decay", 22 | "sustain", 23 | "release", 24 | ], [ 25 | "filterCutoff", 26 | "filterRessonance", 27 | "filterKeyboardTracking", 28 | "filterADSR2CutoffAmt", 29 | ], [ 30 | "filterAttack", 31 | "filterDecay", 32 | "filterSustain", 33 | "filterRelease", 34 | ], [ 35 | "vel2CutoffAmt", 36 | "vel2GainAmt", 37 | "velSensitivity", 38 | "pan", 39 | ], [ 40 | "mod2CutoffAmt", 41 | "mod2GainAmt", 42 | "mod2PitchAmt", 43 | "mod2PlayheadPos", 44 | ], [ 45 | "pitchBendRangeUp", 46 | "pitchBendRangeDown", 47 | "loopXFadeNSamples", 48 | "midiChannel", 49 | ] 50 | ] 51 | 52 | # parameter position in OSC message, parameter label 53 | reverb_parameters_info_dict = { 54 | "roomSize": (0, "Room size"), 55 | "damping": (1, "Damping"), 56 | "wetLevel": (2, "Wet level"), 57 | "dryLevel": (3, "Dry level"), 58 | "width": (4, "Width"), 59 | "freezeMode": (5, "Freeze"), 60 | } 61 | 62 | note_layout_types = ['Contiguous', 'Interleaved'] 63 | license_types = ['All', 'CC0', 'Exclude NC'] 64 | num_sounds_options = [1, 2, 3, 4, 5, 6, 8, 12, 16, 24, 32, 64] 65 | ac_descriptors_options = ['off', 'low', 'mid', 'high'] 66 | ac_descriptors_names = ['brightness', 'hardness', 'depth', 'roughness','boominess', 'warmth', 'sharpness'] 67 | 68 | query_settings_info_dict = { 69 | 'num_sounds': (lambda x:num_sounds_options[int(round(x * (len(num_sounds_options) - 1)))], 'Num sounds', '{}', 8), 70 | 'min_length': (lambda x:float(pow(x, 4) * 300), 'Min length', '{0:.1f}s', 0.0), 71 | 'max_length': (lambda x:float(pow(x, 4) * 300), 'Max length', '{0:.1f}s', 10.0), 72 | 'layout': (lambda x:note_layout_types[int(round(x * (len(note_layout_types) - 1)))], 'Layout', '{}', note_layout_types[1]), 73 | 'brightness': (lambda x:ac_descriptors_options[int(round(x * (len(ac_descriptors_options) - 1)))], 'Brightness', '{}', ac_descriptors_options[0]), 74 | 'hardness': (lambda x:ac_descriptors_options[int(round(x * (len(ac_descriptors_options) - 1)))], 'Hardness', '{}', ac_descriptors_options[0]), 75 | 'depth': (lambda x:ac_descriptors_options[int(round(x * (len(ac_descriptors_options) - 1)))], 'Depth', '{}', ac_descriptors_options[0]), 76 | 'roughness': (lambda x:ac_descriptors_options[int(round(x * (len(ac_descriptors_options) - 1)))], 'Roughness', '{}', ac_descriptors_options[0]), 77 | 'boominess': (lambda x:ac_descriptors_options[int(round(x * (len(ac_descriptors_options) - 1)))], 'Boominess', '{}', ac_descriptors_options[0]), 78 | 'warmth': (lambda x:ac_descriptors_options[int(round(x * (len(ac_descriptors_options) - 1)))], 'Warmth', '{}', ac_descriptors_options[0]), 79 | 'sharpness': (lambda x:ac_descriptors_options[int(round(x * (len(ac_descriptors_options) - 1)))], 'Sharpness', '{}', ac_descriptors_options[0]), 80 | 'license': (lambda x:license_types[int(round(x * (len(license_types) - 1)))], 'License', '{}', license_types[0]), 81 | } 82 | 83 | query_settings_pages = [ 84 | [ 85 | 'num_sounds', 86 | 'min_length', 87 | 'max_length', 88 | 'layout' 89 | ], [ 90 | 'brightness', 91 | 'hardness', 92 | 'depth', 93 | 'roughness' 94 | ], [ 95 | 'boominess', 96 | 'warmth', 97 | 'sharpness', 98 | 'license' 99 | ] 100 | ] 101 | 102 | midi_cc_available_parameters_list = ["startPosition", "endPosition", "loopStartPosition", "loopEndPosition", "playheadPosition", "freezePlayheadSpeed", "filterCutoff", "filterRessonance", "gain", "pan", "pitch"] 103 | 104 | predefined_queries = ['wind', 'rain', 'piano', 'explosion', 'music', 'whoosh', 'woosh', 'intro', 'birds', 'footsteps', 'fire', '808', 'scream', 'water', 'bell', 'click', 'thunder', 'guitar', 'bass', 'beep', 'swoosh', 'pop', 'cartoon', 'magic', 'car', 'horror', 'vocal', 'game', 'trap', 'lofi', 'clap', 'happy', 'forest', 'ding', 'drum', 'kick', 'glitch', 'drop', 'transition', 'animal', 'gun', 'door', 'hit', 'punch', 'nature', 'jump', 'flute', 'sad', 'beat', 'christmas'] 105 | predefined_queries = sorted(predefined_queries) 106 | 107 | reverb_parameters_pages = [ 108 | [ 109 | "roomSize", 110 | "damping", 111 | "width", 112 | "freezeMode" 113 | ], [ 114 | "wetLevel", 115 | "dryLevel", 116 | None, 117 | None 118 | ] 119 | ] -------------------------------------------------------------------------------- /elk_platform/ui_app/ui_state_manager/manager.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import time 4 | 5 | from helpers import add_global_message_to_frame, clear_moving_text_cache, log_sound_used, configure_recent_queries_sound_usage_log_tmp_base_path_from_source_state 6 | from elk_bridge import N_LEDS, N_FADERS 7 | from freesound_interface import get_stored_access_token 8 | from .states_base import EnterDataViaWebInterfaceState, EnterTextViaHWOrWebInterfaceState 9 | from .states_sound_selected import SoundSelectedState 10 | 11 | # Add parent directory to python path and import pysource 12 | sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))) 13 | from pysource.pysource import SourcePluginInterface 14 | 15 | 16 | def state_class_import(name): 17 | components = name.split('.') 18 | mod = __import__(components[0]) 19 | for comp in components[1:]: 20 | mod = getattr(mod, comp) 21 | return mod 22 | 23 | 24 | class UIStateManager(object): 25 | state_stack = [] 26 | global_message = ('', 0, 0) # (text, starttime, duration) 27 | ui_client = None 28 | frame_counter = 0 29 | open_url_in_browser = None 30 | should_show_start_animation = True 31 | block_ui_input = False 32 | waiting_to_go_to_last_loaded_sound = False 33 | 34 | def set_ui_client(self, ui_client): 35 | self.ui_client = ui_client 36 | 37 | def set_waiting_to_go_to_last_loaded_sound(self): 38 | self.waiting_to_go_to_last_loaded_sound = True 39 | 40 | def set_led(self, led_idx, unset_others=False): 41 | if self.ui_client is not None: 42 | if unset_others: 43 | for led_idx2 in range(0, N_LEDS): 44 | if led_idx2 != led_idx: 45 | self.ui_client.set_led(led_idx2, 0) 46 | self.ui_client.set_led(led_idx, 1) 47 | 48 | def unset_led(self, led_idx): 49 | if self.ui_client is not None: 50 | self.ui_client.set_led(led_idx, 0) 51 | 52 | def unset_all_leds(self): 53 | if self.ui_client is not None: 54 | for led_idx in range(0, N_LEDS): 55 | self.ui_client.set_led(led_idx, 0) 56 | 57 | def set_fader_led(self, fader_idx, unset_others=False): 58 | if self.ui_client is not None: 59 | if unset_others: 60 | for fader_idx2 in range(0, N_FADERS): 61 | if fader_idx2 != fader_idx: 62 | self.ui_client.set_fader_led(fader_idx2, 0) 63 | self.ui_client.set_fader_led(fader_idx, 1) 64 | 65 | def unset_all_fader_leds(self): 66 | if self.ui_client is not None: 67 | for fader_idx in range(0, N_FADERS): 68 | self.ui_client.set_fader_led(fader_idx, 0) 69 | 70 | def set_all_fader_leds(self): 71 | if self.ui_client is not None: 72 | for fader_idx in range(0, N_FADERS): 73 | self.ui_client.set_fader_led(fader_idx, 1) 74 | 75 | def draw_display_frame(self): 76 | self.frame_counter += 1 77 | 78 | # Compute display frame of the current ui state and plugin state variables 79 | if not self.current_state.should_show_help(): 80 | frame = self.current_state.draw_display_frame() 81 | else: 82 | frame = self.current_state.get_help_page_frame() 83 | 84 | # If a global message should be added, do it here 85 | if self.global_message[0] != '': 86 | if time.time() - self.global_message[1] < self.global_message[2]: 87 | add_global_message_to_frame(frame, self.global_message[0]) 88 | else: 89 | self.global_message = ('', 0, 0) 90 | 91 | return frame 92 | 93 | def show_global_message(self, text, duration=1, only_if_current_message_matches=None): 94 | if only_if_current_message_matches is None: 95 | show_message = True 96 | else: 97 | if self.global_message is None: 98 | show_message = True 99 | else: 100 | show_message = only_if_current_message_matches in self.global_message[0] 101 | if show_message: 102 | self.global_message = (text, time.time(), duration) 103 | 104 | 105 | def move_to(self, new_state, replace_current=False): 106 | new_state.spi = spi 107 | new_state.sm = self 108 | clear_moving_text_cache() 109 | if self.state_stack: 110 | self.current_state.exit_help() 111 | if replace_current: 112 | self.current_state.on_deactivating_state() 113 | self.state_stack.pop() 114 | self.state_stack.append(new_state) 115 | self.current_state.on_activating_state() 116 | 117 | def move_to_selected_sound_state(self, sound_idx): 118 | # Special case of "move to" used to move to a "selected sound state" and which is needed to avoid some 119 | # circular dependency imports 120 | self.move_to(SoundSelectedState(sound_idx)) 121 | 122 | def go_back(self, n_times=1): 123 | for i in range(0, n_times): 124 | if len(self.state_stack) > 1: 125 | self.current_state.on_deactivating_state() 126 | self.state_stack.pop() 127 | self.current_state.on_activating_state() 128 | 129 | def is_waiting_for_data_from_web(self): 130 | return type(self.current_state) == EnterDataViaWebInterfaceState or type( 131 | self.current_state) == EnterTextViaHWOrWebInterfaceState 132 | 133 | def process_data_from_web(self, data): 134 | if self.is_waiting_for_data_from_web(): 135 | self.current_state.on_data_received(data) 136 | 137 | def log_sound_used(self, sound_sample_element): 138 | log_sound_used(sound_sample_element) 139 | 140 | def configure_recent_queries_sound_usage_log_tmp_base_path_from_source_state(self, data_location, tmp_files_location): 141 | configure_recent_queries_sound_usage_log_tmp_base_path_from_source_state(data_location, tmp_files_location) 142 | 143 | def get_stored_access_token(self): 144 | return get_stored_access_token() 145 | 146 | @property 147 | def current_state(self): 148 | return self.state_stack[-1] 149 | 150 | 151 | state_manager = UIStateManager() 152 | sm = state_manager 153 | 154 | source_plugin_interface = SourcePluginInterface(sm) 155 | spi = source_plugin_interface 156 | -------------------------------------------------------------------------------- /pysource/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ffont/source/7822fd784fdb264c226335ef7e44fca65c241b50/pysource/__init__.py -------------------------------------------------------------------------------- /requirements_fabfile.txt: -------------------------------------------------------------------------------- 1 | fabric==2.6.0 --------------------------------------------------------------------------------