diff --git a/firmware/vcv_plugin/export/src/plugin/Plugin.cpp b/firmware/vcv_plugin/export/src/plugin/Plugin.cpp index 4460af126..2c1174d00 100644 --- a/firmware/vcv_plugin/export/src/plugin/Plugin.cpp +++ b/firmware/vcv_plugin/export/src/plugin/Plugin.cpp @@ -83,7 +83,7 @@ Plugin::~Plugin() { // In VCV Rack: don't delete model because it's allocated once and referenced by a global. // In MetaModule: we need to delete the models when the Plugin is removed - pr_dbg("Deleting Model %s\n", model->slug.c_str()); + pr_trace("Deleting Model %s\n", model->slug.c_str()); delete model; MetaModule::ModuleFactory::unregisterBrand(slug); diff --git a/firmware/vcv_ports/CMakeLists.txt b/firmware/vcv_ports/CMakeLists.txt index 2db48f98e..62a99537c 100644 --- a/firmware/vcv_ports/CMakeLists.txt +++ b/firmware/vcv_ports/CMakeLists.txt @@ -38,6 +38,10 @@ target_include_directories(vcv_ports INTERFACE ${CMAKE_CURRENT_LIST_DIR}/glue ) +if (NOT TARGET simulator) + target_include_directories(vcv_ports INTERFACE ${CMAKE_CURRENT_LIST_DIR}/glue/ext_plugin) +endif() + # Get list of brands include(${CMAKE_CURRENT_LIST_DIR}/brands.cmake) @@ -72,7 +76,7 @@ foreach(brand ${brands}) target_link_libraries(_vcv_ports_internal PUBLIC ${brand}Library) - endif() +endif() endforeach() diff --git a/firmware/vcv_ports/glue/ext_plugin/ext_plugin_builtin.hh b/firmware/vcv_ports/glue/ext_plugin/ext_plugin_builtin.hh new file mode 100644 index 000000000..f8eea5604 --- /dev/null +++ b/firmware/vcv_ports/glue/ext_plugin/ext_plugin_builtin.hh @@ -0,0 +1,3 @@ +// do nothing in firmware: +inline void load_ext_builtin_plugins(auto &internal_plugins) { +} diff --git a/firmware/vcv_ports/internal_plugin_manager.hh b/firmware/vcv_ports/internal_plugin_manager.hh index 2eb05068a..947477865 100644 --- a/firmware/vcv_ports/internal_plugin_manager.hh +++ b/firmware/vcv_ports/internal_plugin_manager.hh @@ -1,5 +1,6 @@ #pragma once #include "convert_plugins.hh" +#include "ext_plugin_builtin.hh" #include "fat_file_io.hh" #include "fs/asset_drive/asset_fs.hh" #include "fs/asset_drive/untar.hh" @@ -27,6 +28,7 @@ struct InternalPluginManager { prepare_ramdisk(); load_internal_assets(); load_internal_plugins(); + load_ext_builtin_plugins(internal_plugins); } void prepare_ramdisk() { diff --git a/simulator/CMakeLists.txt b/simulator/CMakeLists.txt index 47b22adee..45f7f89e2 100644 --- a/simulator/CMakeLists.txt +++ b/simulator/CMakeLists.txt @@ -165,7 +165,7 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "Ap set(DEBUG_COMMAND ${CMAKE_DEBUGGER_BINARY} $ -- --sdcarddir ${CMAKE_CURRENT_LIST_DIR}/patches --flashdir ${CMAKE_CURRENT_LIST_DIR}/../patches/default - --assets ${CMAKE_CURRENT_LIST_DIR}/../firmware/build/assets.uimg + --assets ${CMAKE_CURRENT_LIST_DIR}/build/assets.uimg ) @@ -178,7 +178,7 @@ elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") --args $ --sdcarddir ${CMAKE_CURRENT_LIST_DIR}/patches --flashdir ${CMAKE_CURRENT_LIST_DIR}/../shared/patch/default - --assets ${CMAKE_CURRENT_LIST_DIR}/../firmware/build/assets.uimg + --assets ${CMAKE_CURRENT_LIST_DIR}/build/assets.uimg ) else () set(DEBUG_COMMAND echo "Compiler is ${CMAKE_CXX_COMPILER_ID}, but must be Clang, AppleClang, or GNU to debug") @@ -191,3 +191,4 @@ add_custom_target( USES_TERMINAL ) +include(ext-plugins.cmake) diff --git a/simulator/ext-plugins.cmake b/simulator/ext-plugins.cmake new file mode 100644 index 000000000..601ab7d70 --- /dev/null +++ b/simulator/ext-plugins.cmake @@ -0,0 +1,65 @@ +# Two steps to build an external plugin into the simulator: +# +# 1. Copy/paste the two `list APPEND commands` below, puttting in the path to the +# plugin (where the CMakeLists.txt lives), and the plugin cmake library name +# +# 2. In the plugin, find the file where init(rack::Plugin*) is defined, and rename it to init_Brand +# You can use #if defined(METAMODULE_BUILTIN) so that it's still called init() when building as a plugin for Rack or MM. +# `Brand` in init_Brand must match the plugin cmake library name you used in step 1. + +# Example with Venom: +# list(APPEND ext_builtin_brand_paths "${CMAKE_CURRENT_LIST_DIR}/../../metamodule-plugin-examples/Venom") +# list(APPEND ext_builtin_brand_libname "Venom") + + +# +# Asset dir +# + +cmake_path(SET ASSET_DIR "${CMAKE_CURRENT_BINARY_DIR}/assets") +set(ASSET_IMG_FILENAME assets.uimg) +cmake_path(APPEND ASSET_IMG_PATH "${CMAKE_CURRENT_BINARY_DIR}" "${ASSET_IMG_FILENAME}") + +message("set ASSET_DIR to ${ASSET_DIR}") +message("set ASSET_IMG_PATH to ${ASSET_IMG_PATH}") + +add_custom_command( + OUTPUT ${ASSET_DIR} + COMMAND ${CMAKE_COMMAND} -E echo Copying "${FWDIR}/assets" to "${ASSET_DIR}" + COMMAND ${CMAKE_COMMAND} -E copy_directory "${FWDIR}/assets" "${ASSET_DIR}" + COMMENT "Copying assets/ dir from ${FWDIR}/assets to ${ASSET_DIR}" + VERBATIM USES_TERMINAL +) + +add_custom_command( + OUTPUT ${ASSET_IMG_PATH} + COMMAND cd ${ASSET_DIR} && ${CMAKE_COMMAND} -E tar -cf ${ASSET_IMG_PATH}.tar . + COMMAND cd ${FWDIR} && flashing/uimg_header.py --name Assets ${ASSET_IMG_PATH}.tar ${ASSET_IMG_PATH} + COMMENT "Creating assets uimg file at ${ASSET_IMG_PATH}" + DEPENDS ${ASSET_DIR} + VERBATIM USES_TERMINAL +) + + add_custom_target(asset-image ALL + DEPENDS ${ASSET_IMG_PATH} + ) + + set(EXT_PLUGIN_INIT_CALLS "") + +foreach(branddir brand IN ZIP_LISTS ext_builtin_brand_paths ext_builtin_brand_libname) + set(METAMODULE_SDK_DIR ${CMAKE_CURRENT_LIST_DIR}) + add_subdirectory(${branddir} ${CMAKE_CURRENT_BINARY_DIR}/builtins/${brand}) + + target_link_libraries(${brand} PRIVATE metamodule::vcv-plugin-interface) + target_link_libraries(${brand} PRIVATE cpputil::cpputil) + target_compile_definitions(${brand} PRIVATE METAMODULE METAMODULE_BUILTIN) + + target_link_libraries(_vcv_ports_internal PUBLIC ${brand}) + add_dependencies(asset-image ${brand}-assets) + + string(APPEND EXT_PLUGIN_INIT_CALLS "\textern void init_${brand}(rack::plugin::Plugin *);\n\tinit_${brand}(&internal_plugins.emplace_back(\"${brand}\"));") +endforeach() + +configure_file(src/ext_plugin_builtin.hh.in ${CMAKE_CURRENT_BINARY_DIR}/ext_plugin/ext_plugin_builtin.hh) +target_include_directories(simulator PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/ext_plugin) + diff --git a/simulator/plugin.cmake b/simulator/plugin.cmake new file mode 100644 index 000000000..647250c36 --- /dev/null +++ b/simulator/plugin.cmake @@ -0,0 +1,41 @@ +# TODO: Get cmake to copy the source file that contains init() and rename that function to init_BRAND() +# Also see if Cmake can generate the calls to init (currently manually written into simulator/src/ext_plugin_builtin.hh) + +# file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/replace.cmake" +# [=[ +# file(READ "${SOURCE}" TEXT) +# string(REPLACE "foo" "bar" TEXT "${TEXT}") +# file(WRITE "${TARGET}" "${TEXT}") +# ]=]) + +# add_custom_command( +# OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/plugin.cpp" +# COMMAND "${CMAKE_COMMAND}" +# "-DSOURCE=${CMAKE_CURRENT_SOURCE_DIR}/plugin.cpp" +# "-DTARGET=${CMAKE_CURRENT_BINARY_DIR}/plugin.cpp" +# -P "${CMAKE_CURRENT_BINARY_DIR}/replace.cmake" +# DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/plugin.cpp" "${CMAKE_CURRENT_BINARY_DIR}/replace.cmake" +# ) + + +function(create_plugin) + message("Building ${brand} as built-in plugin (create_plugin)") + + # target_sources(${PLUGIN_OPTIONS_SOURCE_LIB} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/plugin.cpp) + + set(oneValueArgs SOURCE_LIB SOURCE_ASSETS DESTINATION PLUGIN_NAME PLUGIN_JSON) + cmake_parse_arguments(PLUGIN_OPTIONS "" "${oneValueArgs}" "" ${ARGN} ) + + add_custom_command( + OUTPUT "${ASSET_DIR}/${PLUGIN_OPTIONS_PLUGIN_NAME}" + COMMAND ${CMAKE_COMMAND} -E copy_directory "${PLUGIN_OPTIONS_SOURCE_ASSETS}" "${ASSET_DIR}/${PLUGIN_OPTIONS_PLUGIN_NAME}" + COMMENT "Copying ${PLUGIN_OPTIONS_SOURCE_ASSETS} to ${ASSET_DIR}/${PLUGIN_OPTIONS_PLUGIN_NAME}" + VERBATIM + ) + + add_custom_target(${PLUGIN_OPTIONS_SOURCE_LIB}-assets + DEPENDS "${ASSET_DIR}/${PLUGIN_OPTIONS_PLUGIN_NAME}" + ) + + +endfunction() diff --git a/simulator/src/ext_plugin_builtin.hh.in b/simulator/src/ext_plugin_builtin.hh.in new file mode 100644 index 000000000..abb830732 --- /dev/null +++ b/simulator/src/ext_plugin_builtin.hh.in @@ -0,0 +1,3 @@ +inline void load_ext_builtin_plugins(auto &internal_plugins) { +${EXT_PLUGIN_INIT_CALLS} +} diff --git a/simulator/src/settings.hh b/simulator/src/settings.hh index 1b38697ba..bdfee0972 100644 --- a/simulator/src/settings.hh +++ b/simulator/src/settings.hh @@ -10,7 +10,7 @@ struct Settings { unsigned zoom = 100; std::string sdcard_path = "patches/"; std::string flash_path = "../patches/default/"; - std::string asset_file = "../firmware/build/assets.uimg"; + std::string asset_file = "build/assets.uimg"; int audioout_dev = 0; void parse(int argc, char *argv[]) {