diff --git a/server/supernova/sc/sc_osc_handler.cpp b/server/supernova/sc/sc_osc_handler.cpp index 171ca3da279..13f26d8b136 100644 --- a/server/supernova/sc/sc_osc_handler.cpp +++ b/server/supernova/sc/sc_osc_handler.cpp @@ -2909,7 +2909,24 @@ void handle_p_new(received_message const & msg) } } +void handle_u_cmd(received_message const & msg, int size) +{ + sc_msg_iter args(size, msg.AddressPattern()); + + int node_id = args.geti(); + server_node * target_synth = find_node(node_id); + + if (target_synth == NULL || target_synth->is_group()) + return; + + sc_synth * synth = static_cast(target_synth); + + int ugen_index = args.geti(); + const char * cmd_name = args.gets(); + + synth->apply_unit_cmd(cmd_name, ugen_index, &args); +} } /* namespace */ @@ -3053,6 +3070,10 @@ void sc_osc_handler::handle_message_int_address(received_message const & message handle_b_alloc(message, endpoint); break; + case cmd_u_cmd: + handle_u_cmd(message, msg_size); + break; + case cmd_b_free: handle_b_free(message, endpoint); break; @@ -3494,6 +3515,11 @@ void sc_osc_handler::handle_message_sym_address(received_message const & message return; } + if (strcmp(address+1, "u_cmd") == 0) { + handle_u_cmd(message, msg_size); + return; + } + if (strcmp(address+1, "status") == 0) { handle_status(endpoint); return; diff --git a/server/supernova/sc/sc_plugin_interface.cpp b/server/supernova/sc/sc_plugin_interface.cpp index 57b82332ea7..3996bdfad7e 100644 --- a/server/supernova/sc/sc_plugin_interface.cpp +++ b/server/supernova/sc/sc_plugin_interface.cpp @@ -294,6 +294,12 @@ bool define_bufgen(const char * name, BufGenFunc func) } } +bool define_unitcmd(const char * unitClassName, const char * cmdName, UnitCmdFunc inFunc) +{ + return nova::sc_factory->register_ugen_command_function(unitClassName, cmdName, inFunc); +} + + bool define_plugincmd(const char * name, PlugInCmdFunc func, void * user_data) { std::cerr << "plugin commands not implemented: " << name << std::endl; @@ -520,6 +526,7 @@ void sc_plugin_interface::initialize(void) sc_interface.fDefineUnit = &define_unit; sc_interface.fDefineBufGen = &define_bufgen; sc_interface.fDefinePlugInCmd = &define_plugincmd; + sc_interface.fDefineUnitCmd = &define_unitcmd; /* interface functions */ sc_interface.fNodeEnd = &node_end; diff --git a/server/supernova/sc/sc_synth.cpp b/server/supernova/sc/sc_synth.cpp index 4e2df6c238d..9e74e408693 100644 --- a/server/supernova/sc/sc_synth.cpp +++ b/server/supernova/sc/sc_synth.cpp @@ -231,6 +231,16 @@ void sc_synth::map_control_buses_audio (const char * slot_name, int audio_bus_in map_control_buses_audio(index, audio_bus_index, count); } +void sc_synth::apply_unit_cmd(const char * unit_cmd, unsigned int unit_index, struct sc_msg_iter *args) +{ + Unit * unit = units[unit_index]; + sc_ugen_def * def = reinterpret_cast(unit->mUnitDef); + + UnitCmdFunc func = def->find_command(unit_cmd); + (func)(unit, args); +} + + void sc_synth::run(void) { perform(); diff --git a/server/supernova/sc/sc_synth.hpp b/server/supernova/sc/sc_synth.hpp index 7c79f749ebf..857d64adcc0 100644 --- a/server/supernova/sc/sc_synth.hpp +++ b/server/supernova/sc/sc_synth.hpp @@ -128,6 +128,8 @@ class sc_synth: trace = 1; } + void apply_unit_cmd(const char * unit_cmd, unsigned int unit_index, struct sc_msg_iter *args); + private: void run_traced(void); diff --git a/server/supernova/sc/sc_ugen_factory.cpp b/server/supernova/sc/sc_ugen_factory.cpp index d8659a9a6df..b6a2ca65328 100644 --- a/server/supernova/sc/sc_ugen_factory.cpp +++ b/server/supernova/sc/sc_ugen_factory.cpp @@ -33,6 +33,63 @@ namespace nova { +namespace +{ + +template +struct compare_def +{ + bool operator()(def const & lhs, + std::string const & rhs) const + { + return lhs.name() < rhs; + } + + bool operator()(std::string const & lhs, + def const & rhs) const + { + return lhs < rhs.name(); + } + + bool operator()(def const & lhs, + const char * rhs) const + { + return (strcmp(lhs.name().c_str(), rhs) < 0); + } + + bool operator()(const char * lhs, + def const & rhs) const + { + return (strcmp(lhs, rhs.name().c_str()) < 0); + } +}; + +template +struct equal_def +{ + bool operator()(def const & lhs, + std::string const & rhs) const + { + return lhs.name() == rhs; + } + + bool operator()(std::string const & lhs, + def const & rhs) const + { + return lhs == rhs.name(); + } +}; + +template +struct hash_def +{ + std::size_t operator()(std::string const & value) + { + return def::hash(value); + } +}; + +} sc_ugen_factory * sc_factory; @@ -119,6 +176,23 @@ Unit * sc_ugen_def::construct(sc_synthdef::unit_spec_t const & unit_spec, sc_syn return unit; } +bool sc_ugen_def::add_command(const char* cmd_name, UnitCmdFunc func) +{ + sc_unitcmd_def * def = new sc_unitcmd_def(cmd_name, func); + commands.insert(*def); + return true; +} + +UnitCmdFunc sc_ugen_def::find_command(const char * cmd_name) +{ + unit_commands_set::iterator it = commands.find(cmd_name, compare_def()); + + if (it == commands.end()) + return NULL; + else + return it->func; +} + void sc_ugen_factory::load_plugin_folder (boost::filesystem::path const & path) { using namespace boost::filesystem; @@ -174,6 +248,7 @@ void sc_ugen_factory::close_handles(void) {} #endif + void sc_ugen_factory::register_ugen(const char *inUnitClassName, size_t inAllocSize, UnitCtorFunc inCtor, UnitDtorFunc inDtor, uint32 inFlags) { @@ -209,4 +284,14 @@ sc_ugen_def * sc_ugen_factory::find_ugen(std::string const & name) return &*it; } +bool sc_ugen_factory::register_ugen_command_function(const char * ugen_name, const char * cmd_name, + UnitCmdFunc func) +{ + sc_ugen_def * def = find_ugen(ugen_name); + if (!def) + return false; + return def->add_command(cmd_name, func); +} + + } /* namespace nova */ diff --git a/server/supernova/sc/sc_ugen_factory.hpp b/server/supernova/sc/sc_ugen_factory.hpp index 81624fb3d33..52f49d56776 100644 --- a/server/supernova/sc/sc_ugen_factory.hpp +++ b/server/supernova/sc/sc_ugen_factory.hpp @@ -34,6 +34,34 @@ namespace nova { namespace bi = boost::intrusive; + +struct sc_unitcmd_def: + public bi::set_base_hook<> +{ + const std::string name_; + +public: + const UnitCmdFunc func; + + sc_unitcmd_def(const char * cmd_name, UnitCmdFunc func): + name_(cmd_name), func(func) + {} + + std::string const & name(void) const + { + return name_; + } + +public: + /* sort by name */ + friend bool operator< (sc_unitcmd_def const & a, + sc_unitcmd_def const & b) + { + return a.name_ < b.name_; + } +}; + + class sc_ugen_def: public bi::unordered_set_base_hook<> { @@ -44,6 +72,9 @@ class sc_ugen_def: const UnitDtorFunc dtor; const uint32_t flags; + typedef bi::set unit_commands_set; + unit_commands_set commands; + public: sc_ugen_def(const char *inUnitClassName, size_t inAllocSize, UnitCtorFunc inCtor, UnitDtorFunc inDtor, uint32 inFlags); @@ -86,13 +117,8 @@ class sc_ugen_def: return alloc_size; } -public: - /* sort by name */ - friend bool operator< (sc_ugen_def const & a, - sc_ugen_def const & b) - { - return a.name_ < b.name_; - } + bool add_command(const char * cmd_name, UnitCmdFunc func); + UnitCmdFunc find_command(const char * cmd_name); friend bool operator== (sc_ugen_def const & a, sc_ugen_def const & b) @@ -142,59 +168,6 @@ class sc_ugen_factory: typedef bi::set bufgen_set_t; - template - struct compare_def - { - bool operator()(def const & lhs, - std::string const & rhs) const - { - return lhs.name() < rhs; - } - - bool operator()(std::string const & lhs, - def const & rhs) const - { - return lhs < rhs.name(); - } - - bool operator()(def const & lhs, - const char * rhs) const - { - return (strcmp(lhs.name().c_str(), rhs) < 0); - } - - bool operator()(const char * lhs, - def const & rhs) const - { - return (strcmp(lhs, rhs.name().c_str()) < 0); - } - }; - - template - struct equal_def - { - bool operator()(def const & lhs, - std::string const & rhs) const - { - return lhs.name() == rhs; - } - - bool operator()(std::string const & lhs, - def const & rhs) const - { - return lhs == rhs.name(); - } - }; - - template - struct hash_def - { - std::size_t operator()(std::string const & value) - { - return def::hash(value); - } - }; - ugen_set_type::bucket_type node_buckets[ugen_set_bucket_count]; ugen_set_type ugen_set; @@ -244,6 +217,8 @@ class sc_ugen_factory: sc_ugen_def * find_ugen(std::string const & name); + bool register_ugen_command_function(const char * ugen_name, const char * cmd_name, UnitCmdFunc); + private: void close_handles(void); uint32_t ugen_count_;