From f375e819b9dd11dc159cfa12b324be2c4b27d3a1 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Sun, 30 Jun 2024 16:32:14 +0200 Subject: [PATCH 1/3] osc: Update sur->plugins whenever strip changes Previously, this happend in _sel_plugin when the selected plugin changed (which was called at the end of _strip_select2 too). By moving this code: 1. The list of plugins is only updated when the strip changes, and not when just the selected plugin changes (in which the case the selected strip and list of plugins remains the same, so this saves unneeded work). 2. The list of plugins is updated earlier, which allows it to be used by OSCSelectObserver (in the next commit). 3. The list of plugins is cleared when no strip is selected. --- libs/surfaces/osc/osc.cc | 46 ++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/libs/surfaces/osc/osc.cc b/libs/surfaces/osc/osc.cc index 9eb60147f43..1738b8da774 100644 --- a/libs/surfaces/osc/osc.cc +++ b/libs/surfaces/osc/osc.cc @@ -2883,26 +2883,6 @@ OSC::_sel_plugin (int id, lo_address addr) return 1; } - /* find out how many plugins we have */ - sur->plugins.clear(); - for (int nplugs = 0; true; ++nplugs) { - std::shared_ptr proc = r->nth_plugin (nplugs); - if (!proc) { - break; - } - if (!r->nth_plugin(nplugs)->display_to_user()) { - continue; - } -#ifdef MIXBUS - /* need to check for mixbus channel strips (and exclude them) */ - std::shared_ptr pi = std::dynamic_pointer_cast(proc); - if (pi && pi->is_channelstrip()) { - continue; - } -#endif - sur->plugins.push_back (nplugs); - } - // limit plugin_id to actual plugins if (sur->plugins.size() < 1) { sur->plugin_id = 0; @@ -4760,11 +4740,36 @@ OSC::_strip_select2 (std::shared_ptr s, OSCSurface *sur, lo_address a _select = s; } if (!s) { + sur->plugins.clear(); return 0; } if (s != old_sel) { sur->select = s; } + + /* Create list of user-visible plugins (into which piid indexes) */ + sur->plugins.clear(); + std::shared_ptr r = std::dynamic_pointer_cast(s); + if (r) { + for (int nplugs = 0; true; ++nplugs) { + std::shared_ptr proc = r->nth_plugin (nplugs); + if (!proc) { + break; + } + if (!r->nth_plugin(nplugs)->display_to_user()) { + continue; + } +#ifdef MIXBUS + /* need to check for mixbus channel strips (and exclude them) */ + std::shared_ptr pi = std::dynamic_pointer_cast(proc); + if (pi && pi->is_channelstrip()) { + continue; + } +#endif + sur->plugins.push_back (nplugs); + } + } + bool sends; uint32_t nsends = 0; do { @@ -4807,7 +4812,6 @@ OSC::_strip_select2 (std::shared_ptr s, OSCSurface *sur, lo_address a } // need to set monitor for processor changed signal (for paging) string address = lo_address_get_url (addr); - std::shared_ptr r = std::dynamic_pointer_cast(s); if (r) { r->processors_changed.connect (sur->proc_connection, MISSING_INVALIDATOR, boost::bind (&OSC::processor_changed, this, address), this); _sel_plugin (sur->plugin_id, addr); From 8a2a22d289bbc103f818ce1668f6177c561601b1 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Sun, 30 Jun 2024 19:51:18 +0200 Subject: [PATCH 2/3] osc: Pass user-visible piid to OSCSelectObserver There are two ways to identify a plugin: 1. The user-visible number, usually named "piid". This is a 1-based index into the list of visible, non-channelstrip plugins only. 2. The plugin id. This is a 1-based index into the list of all plugins as passed to nth_plugin The sur->plugins vector is used to translate the former into the latter. Previously, the latter, already translated, index was passed to OSCSelectObserver to indicate the currently selected plugin. To prepare for sending the piid of the selected plugin in a feedback message (in the next commit), this commit moves the translation of piid to plugin id into OSCSelectObserver. To emphasize the new meaning of the plug_id variable, it is renamed to selected_piid. Also, since the piid is 1-based, change it to a uint32_t and use 0 to mean "no plugin selected" instead of -1. This commit is expected to subtly change behaviour: When selecting a different strip, OSCSelectObserver would (via OSC::_strip_select2 and refresh_strip) send feedback for the plugin with the same plugin id as the previously selected plugin. Then OSC::_strip_select2 would do the piid to plugin id translation for the new strip and call set_plugin, causing a second round of feedback for the plugin with the same piid as the previously selected plugin. If the new strip has hidden plugins (i.e. piid and plugin id do not match), this could mean that you get feedback for two different plugins. With this commit applied, the translation happens in both cases and the feedback returned should be for the same plugin twice. --- libs/surfaces/osc/osc.cc | 4 ++-- libs/surfaces/osc/osc_select_observer.cc | 10 +++++----- libs/surfaces/osc/osc_select_observer.h | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libs/surfaces/osc/osc.cc b/libs/surfaces/osc/osc.cc index 1738b8da774..ac5ff8e6d6e 100644 --- a/libs/surfaces/osc/osc.cc +++ b/libs/surfaces/osc/osc.cc @@ -2888,7 +2888,7 @@ OSC::_sel_plugin (int id, lo_address addr) sur->plugin_id = 0; sur->plug_page = 1; if (sur->sel_obs) { - sur->sel_obs->set_plugin_id(-1, 1); + sur->sel_obs->set_plugin_id(0, 1); } return 0; } else if (id < 1) { @@ -2924,7 +2924,7 @@ OSC::_sel_plugin (int id, lo_address addr) sur->plug_page = 1; if (sur->sel_obs) { - sur->sel_obs->set_plugin_id(sur->plugins[sur->plugin_id - 1], sur->plug_page); + sur->sel_obs->set_plugin_id(sur->plugin_id, sur->plug_page); } return 0; } diff --git a/libs/surfaces/osc/osc_select_observer.cc b/libs/surfaces/osc/osc_select_observer.cc index a965b2f322c..5507ddbe70d 100644 --- a/libs/surfaces/osc/osc_select_observer.cc +++ b/libs/surfaces/osc/osc_select_observer.cc @@ -77,9 +77,9 @@ OSCSelectObserver::OSCSelectObserver (OSC& o, ARDOUR::Session& s, ArdourSurface: plug_size = plug_page_size; plug_page = sur->plug_page; if (sur->plugins.size () > 0) { - plug_id = sur->plugins[sur->plugin_id - 1]; + selected_piid = sur->plugin_id; } else { - plug_id = -1; + selected_piid = 0; } _group_sharing[15] = 1; refresh_strip (sur->select, sur->nsends, gainmode, true); @@ -441,7 +441,7 @@ OSCSelectObserver::send_end () void OSCSelectObserver::set_plugin_id (int id, uint32_t page) { - plug_id = id; + selected_piid = id; plug_page = page; renew_plugin (); } @@ -469,7 +469,7 @@ OSCSelectObserver::renew_plugin () { void OSCSelectObserver::plugin_init() { - if (plug_id < 0) { + if (!selected_piid) { plugin_end (); return; } @@ -480,7 +480,7 @@ OSCSelectObserver::plugin_init() } // we have a plugin number now get the processor - std::shared_ptr proc = r->nth_plugin (plug_id); + std::shared_ptr proc = r->nth_plugin (sur->plugins[selected_piid - 1]); std::shared_ptr pi; if (!(pi = std::dynamic_pointer_cast(proc))) { plugin_end (); diff --git a/libs/surfaces/osc/osc_select_observer.h b/libs/surfaces/osc/osc_select_observer.h index 171a985ddc6..30ff9978335 100644 --- a/libs/surfaces/osc/osc_select_observer.h +++ b/libs/surfaces/osc/osc_select_observer.h @@ -89,7 +89,7 @@ class OSCSelectObserver uint32_t nplug_params; uint32_t plug_page_size; uint32_t plug_page; - int plug_id; + uint32_t selected_piid; uint32_t plug_size; std::vector plug_params; int eq_bands; From b786aa783ef617b091990b3d813a1ee4b1bf9dab Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Fri, 28 Jun 2024 12:11:41 +0200 Subject: [PATCH 3/3] osc: Send /select/plugin plugin_id feedback Whenever the active plugin changes (because the plugin changes or the selected strip changes), the name, some other properties and parameter values for the newly selected plugin is sent as feedback. However, there was no clear indication of which plugin was selected exactly. Applications or surfaces that need to know the active plugin could track the currently selected plugin by remembering the most recently selected index, but unexpected plugin changes (e.g. when switching to a strip with fewer plugins) and the asynchronous nature of OSC messages make this more complicated than it should be. By sending the active plugin id as feedback, clients do not have to guess. When no plugin is selected (e.g. on startup or when no strip is selected) or the currently selected index is not a plugin (but a some other kind of processor), a value of 0 is sent. This uses the `/select/plugin` message, which is also used to change the selected plugin. There is a slight discrepancy: the control messages accepts a delta on the selected plugin, while the feedback sends an absolute value. --- libs/surfaces/osc/osc_select_observer.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/surfaces/osc/osc_select_observer.cc b/libs/surfaces/osc/osc_select_observer.cc index 5507ddbe70d..686175f2348 100644 --- a/libs/surfaces/osc/osc_select_observer.cc +++ b/libs/surfaces/osc/osc_select_observer.cc @@ -486,6 +486,8 @@ OSCSelectObserver::plugin_init() plugin_end (); return; } + _osc.float_message (X_("/select/plugin"), selected_piid, addr); + std::shared_ptr pip = pi->plugin(); // we have a plugin we can ask if it is activated proc->ActiveChanged.connect (plugin_connections, MISSING_INVALIDATOR, boost::bind (&OSCSelectObserver::plug_enable, this, X_("/select/plugin/activate"), proc), OSC::instance()); @@ -558,6 +560,7 @@ void OSCSelectObserver::plugin_end () { plugin_connections.drop_connections (); + _osc.float_message (X_("/select/plugin"), 0, addr); _osc.float_message (X_("/select/plugin/activate"), 0, addr); _osc.text_message (X_("/select/plugin/name"), " ", addr); for (uint32_t i = 1; i <= plug_size; i++) {