OSC: in custom strip list check all strips exist
[ardour.git] / libs / surfaces / osc / osc.cc
index a7af9c1b10c3d97f7edd2a343639531ec87b2916..80d45b0bc71fd96a49b8390fbe7a2fd15b771f41 100644 (file)
@@ -415,6 +415,9 @@ OSC::register_callbacks()
                REGISTER_CALLBACK (serv, "/refresh", "f", refresh_surface);
                REGISTER_CALLBACK (serv, "/strip/list", "", routes_list);
                REGISTER_CALLBACK (serv, "/strip/list", "f", routes_list);
+               REGISTER_CALLBACK (serv, "/strip/custom/enable", "f", custom_enable);
+               REGISTER_CALLBACK (serv, "/strip/custom/clear", "f", custom_clear);
+               REGISTER_CALLBACK (serv, "/strip/custom/clear", "", custom_clear);
                REGISTER_CALLBACK (serv, "/surface/list", "", surface_list);
                REGISTER_CALLBACK (serv, "/surface/list", "f", surface_list);
                REGISTER_CALLBACK (serv, "/add_marker", "", add_marker);
@@ -582,6 +585,7 @@ OSC::register_callbacks()
                REGISTER_CALLBACK (serv, "/select/send_page", "f", sel_send_page);
                REGISTER_CALLBACK (serv, "/select/plug_page", "f", sel_plug_page);
                REGISTER_CALLBACK (serv, "/select/plugin", "f", sel_plugin);
+               REGISTER_CALLBACK (serv, "/select/plugin/activate", "f", sel_plugin_activate);
                REGISTER_CALLBACK (serv, "/select/expand", "i", sel_expand);
                REGISTER_CALLBACK (serv, "/select/pan_elevation_position", "f", sel_pan_elevation);
                REGISTER_CALLBACK (serv, "/select/pan_frontback_position", "f", sel_pan_frontback);
@@ -793,10 +797,7 @@ OSC::catchall (const char *path, const char* types, lo_arg **argv, int argc, lo_
        /* 15 for /#current_value plus 2 for /<path> */
 
        len = strlen (path);
-       /*
-        * not needed until /strip/listen/ignore fixed
-       OSCSurface *sur = get_surface(get_address (msg));
-       */
+       OSCSurface *sur = get_surface(get_address (msg), true);
 
        if (strstr (path, "/automation")) {
                ret = set_automation (path, types, argv, argc, msg);
@@ -831,56 +832,38 @@ OSC::catchall (const char *path, const char* types, lo_arg **argv, int argc, lo_
 
                ret = 0;
        } else
-/*     if (strcmp (path, "/strip/listen") == 0) {
-               check_surface (msg);
-
-               cerr << "set up listener\n";
-
-               lo_message reply = lo_message_new ();
-
+       if (strcmp (path, "/strip/listen") == 0) {
                if (argc <= 0) {
-                       lo_message_add_string (reply, "syntax error");
+                       PBD::warning << "OSC: Wrong number of parameters." << endmsg;
+               } else if (sur->custom_enable) {
+                       PBD::warning << "OSC: Can't add strips with custom enabled." << endmsg;
                } else {
                        for (int n = 0; n < argc; ++n) {
 
-                               boost::shared_ptr<Route> r = session->get_remote_nth_route (argv[n]->i);
-
-                               if (!r) {
-                                       lo_message_add_string (reply, "not found");
-                                       cerr << "no such route\n";
-                                       break;
-                               } else {
-                                       cerr << "add listener\n";
-                                       listen_to_route (r, get_address (msg));
-                                       lo_message_add_int32 (reply, argv[n]->i);
+                               boost::shared_ptr<Stripable> s = get_strip (argv[n]->i, get_address (msg));
+                               if (s) {
+                                       sur->custom_strips.push_back (s);
                                }
                        }
                }
-
-               if (sur->feedback[14]) {
-                       lo_send_message (get_address (msg), "/reply", reply);
-               } else {
-                       lo_send_message (get_address (msg), "#reply", reply);
-               }
-               lo_message_free (reply);
-
                ret = 0;
-
        } else
        if (strcmp (path, "/strip/ignore") == 0) {
-               check_surface (msg);
-
-               for (int n = 0; n < argc; ++n) {
-
-                       boost::shared_ptr<Route> r = session->get_remote_nth_route (argv[n]->i);
-
-                       if (r) {
-                               end_listen (r, get_address (msg));
+               if (argc <= 0) {
+                       PBD::warning << "OSC: Wrong number of parameters." << endmsg;
+               } else if (!sur->custom_enable) {
+                       PBD::warning << "OSC: Can't remove strips without custom enabled." << endmsg;
+               } else {
+                       for (int n = 0; n < argc; ++n) {
+                               if ((uint32_t) argv[n]->i <= sur->custom_strips.size ()) {
+                                       sur->custom_strips[argv[n]->i - 1] = boost::shared_ptr<Stripable>();
+                               }
                        }
+                       ret = set_bank (sur->bank, msg);
                }
 
                ret = 0;
-       } else */
+       } else
        if (strstr (path, "/strip") && (argc != 1)) {
                // All of the strip commands below require 1 parameter
                PBD::warning << "OSC: Wrong number of parameters." << endmsg;
@@ -1268,6 +1251,7 @@ OSC::surface_list (lo_message msg)
                OSCSurface* sur = &_surface[it];
                cerr << string_compose ("  Surface: %1 URL: %2\n", it, sur->remote_url);
                cerr << string_compose ("       Number of strips: %1 Bank size: %2 Current Bank %3\n", sur->nstrips, sur->bank_size, sur->bank);
+               cerr << string_compose ("       Use Custom: %1 Custom Strips: %2\n", sur->custom_enable, sur->custom_strips.size ());
                bool ug = false;
                if (sur->usegroup == PBD::Controllable::UseGroup) {
                        ug = true;
@@ -1299,6 +1283,47 @@ OSC::surface_list (lo_message msg)
        cerr << "\n";
 }
 
+int
+OSC::custom_clear (lo_message msg)
+{
+       if (!session) {
+               return 0;
+       }
+       OSCSurface *sur = get_surface(get_address (msg), true);
+       sur->custom_enable = false;
+       sur->custom_strips.clear ();
+       sur->strips = get_sorted_stripables(sur->strip_types, sur->cue, false, sur->custom_strips);
+       sur->nstrips = sur->strips.size();
+       return set_bank (1, msg);
+}
+
+int
+OSC::custom_enable (float state, lo_message msg)
+{
+       if (!session) {
+               return 0;
+       }
+       OSCSurface *sur = get_surface(get_address (msg), true);
+       if (state > 0){
+               if (sur->custom_strips.size () == 0) {
+                       PBD::warning << "No custom strips set to enable" << endmsg;
+                       sur->custom_enable = false;
+                       return -1;
+               } else {
+                       sur->custom_enable = true;
+                       sur->strips = get_sorted_stripables(sur->strip_types, sur->cue, true, sur->custom_strips);
+                       sur->nstrips = sur->custom_strips.size();
+                       return set_bank (1, msg);
+               }
+       } else {
+               sur->custom_enable = false;
+               sur->strips = get_sorted_stripables(sur->strip_types, sur->cue, false, sur->custom_strips);
+               sur->nstrips = sur->strips.size();
+               return set_bank (1, msg);
+       }
+       return -1;
+}
+
 int
 OSC::cancel_all_solos ()
 {
@@ -1929,13 +1954,15 @@ OSC::get_surface (lo_address addr , bool quiet)
        s.feedback = default_feedback;
        s.gainmode = default_gainmode;
        s.usegroup = PBD::Controllable::NoGroup;
+       s.custom_strips.clear ();
+       s.custom_enable = false;
        s.sel_obs = 0;
        s.expand = 0;
        s.expand_enable = false;
        s.cue = false;
        s.aux = 0;
        s.cue_obs = 0;
-       s.strips = get_sorted_stripables(s.strip_types, s.cue);
+       s.strips = get_sorted_stripables(s.strip_types, s.cue, false, s.custom_strips);
        s.send_page = 1;
        s.send_page_size = default_send_size;
        s.plug_page = 1;
@@ -1973,7 +2000,10 @@ OSC::global_feedback (OSCSurface* sur)
 void
 OSC::strip_feedback (OSCSurface* sur, bool new_bank_size)
 {
-       sur->strips = get_sorted_stripables(sur->strip_types, sur->cue);
+       if (sur->custom_strips.size () == 0) {
+               sur->custom_enable = false;
+       }
+       sur->strips = get_sorted_stripables(sur->strip_types, sur->cue, sur->custom_enable, sur->custom_strips);
        sur->nstrips = sur->strips.size();
        if (new_bank_size || (!sur->feedback[0] && !sur->feedback[1])) {
                // delete old observers
@@ -2050,8 +2080,6 @@ OSC::_recalcbanks ()
        // refresh each surface we know about.
        for (uint32_t it = 0; it < _surface.size(); ++it) {
                OSCSurface* sur = &_surface[it];
-               sur->strips = get_sorted_stripables(sur->strip_types, sur->cue);
-               sur->nstrips = sur->strips.size();
                // find lo_address
                lo_address addr = lo_address_new_from_url (sur->remote_url.c_str());
                if (sur->cue) {
@@ -2328,7 +2356,7 @@ OSC::sel_send_pagesize (uint32_t size, lo_message msg)
        OSCSurface *s = get_surface(get_address (msg));
        if  (size != s->send_page_size) {
                s->send_page_size = size;
-               s->sel_obs->renew_sends();
+               s->sel_obs->set_send_size(size);
        }
        return 0;
 }
@@ -2337,8 +2365,18 @@ int
 OSC::sel_send_page (int page, lo_message msg)
 {
        OSCSurface *s = get_surface(get_address (msg));
+       uint32_t send_size = s->send_page_size;
+       if (!send_size) {
+               send_size = s->nsends;
+       }
+       uint32_t max_page = (uint32_t)(s->nsends / send_size) + 1;
        s->send_page = s->send_page + page;
-       s->sel_obs->renew_sends();
+       if (s->send_page < 1) {
+               s->send_page = 1;
+       } else if ((uint32_t)s->send_page > max_page) {
+               s->send_page = max_page;
+       }
+       s->sel_obs->set_send_page (s->send_page);
        return 0;
 }
 
@@ -2348,7 +2386,7 @@ OSC::sel_plug_pagesize (uint32_t size, lo_message msg)
        OSCSurface *s = get_surface(get_address (msg));
        if (size != s->plug_page_size) {
                s->plug_page_size = size;
-               s->sel_obs->renew_plugin();
+               s->sel_obs->set_plugin_size(size);
        }
        return 0;
 }
@@ -2356,15 +2394,35 @@ OSC::sel_plug_pagesize (uint32_t size, lo_message msg)
 int
 OSC::sel_plug_page (int page, lo_message msg)
 {
+       if (!page) {
+               return 0;
+       }
+       int new_page = 0;
        OSCSurface *s = get_surface(get_address (msg));
-       s->plug_page = s->plug_page + page;
-       s->sel_obs->renew_plugin();
+       if (page > 0) {
+               new_page = s->plug_page + s->plug_page_size;
+               if ((uint32_t) new_page > s->plug_params.size ()) {
+                       new_page = s->plug_page;
+               }
+       } else {
+               new_page = s->plug_page - s->plug_page_size;
+               if (new_page < 1) {
+                       new_page = 1;
+               }
+       }
+       if (new_page != s->plug_page) {
+               s->plug_page = new_page;
+               s->sel_obs->set_plugin_page(s->plug_page);
+       }
        return 0;
 }
 
 int
 OSC::sel_plugin (int delta, lo_message msg)
 {
+       if (!delta) {
+               return 0;
+       }
        OSCSurface *sur = get_surface(get_address (msg));
        return _sel_plugin (sur->plugin_id + delta, get_address (msg));
 }
@@ -2373,12 +2431,7 @@ int
 OSC::_sel_plugin (int id, lo_address addr)
 {
        OSCSurface *sur = get_surface(addr);
-       boost::shared_ptr<Stripable> s;
-       if (sur->expand_enable) {
-               s = get_strip (sur->expand, addr);
-       } else {
-               s = _select;
-       }
+       boost::shared_ptr<Stripable> s = sur->select;
        if (s) {
                boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route>(s);
                if (!r) {
@@ -2402,24 +2455,28 @@ OSC::_sel_plugin (int id, lo_address addr)
                                                if (!pi->is_channelstrip()) {
 #endif
                                                        sur->plugins.push_back (nplugs);
+                                                       nplugs++;
 #ifdef MIXBUS
                                                }
                                        }
 #endif
                                }
                                plugs = true;
-                               nplugs++;
                        }
                } while (plugs);
 
                // limit plugin_id to actual plugins
-               if (!sur->plugins.size()) {
+               if (sur->plugins.size() < 1) {
                        sur->plugin_id = 0;
+                       sur->plug_page = 1;
+                       if (sur->sel_obs) {
+                               sur->sel_obs->set_plugin_id(-1, 1);
+                       }
                        return 0;
+               } else if (id < 1) {
+                       sur->plugin_id = 1;
                } else if (sur->plugins.size() < (uint32_t) id) {
                        sur->plugin_id = sur->plugins.size();
-               } else  if (sur->plugins.size() && !id) {
-                       sur->plugin_id = 1;
                } else {
                        sur->plugin_id = id;
                }
@@ -2449,7 +2506,7 @@ OSC::_sel_plugin (int id, lo_address addr)
                sur->plug_page = 1;
 
                if (sur->sel_obs) {
-                       sur->sel_obs->renew_plugin();
+                       sur->sel_obs->set_plugin_id(sur->plugins[sur->plugin_id - 1], sur->plug_page);
                }
                return 0;
        }
@@ -3601,15 +3658,28 @@ OSC::_strip_select (boost::shared_ptr<Stripable> s, lo_address addr)
                        _select = s;
        }
        sur->select = s;
+       bool sends;
+       uint32_t nsends  = 0;
+       do {
+               sends = false;
+               if (s->send_level_controllable (nsends)) {
+                       sends = true;
+                       nsends++;
+               }
+       } while (sends);
+       sur->nsends = nsends;
+
        s->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::recalcbanks, this), this);
 
        OSCSelectObserver* so = dynamic_cast<OSCSelectObserver*>(sur->sel_obs);
        if (sur->feedback[13]) {
                if (so != 0) {
-                       delete so;
+                       so->refresh_strip (s, nsends, true);
+               } else {
+                       OSCSelectObserver* sel_fb = new OSCSelectObserver (*this, sur);
+                       sur->sel_obs = sel_fb;
                }
-               OSCSelectObserver* sel_fb = new OSCSelectObserver (*this, sur);
-               sur->sel_obs = sel_fb;
+               sur->sel_obs->set_expand (sur->expand_enable);
                uint32_t obs_expand = 0;
                if (sur->expand_enable) {
                        obs_expand = sur->expand;
@@ -3630,7 +3700,7 @@ OSC::_strip_select (boost::shared_ptr<Stripable> s, lo_address addr)
        boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route>(s);
        if (r) {
                r->processors_changed.connect  (sur->proc_connection, MISSING_INVALIDATOR, boost::bind (&OSC::processor_changed, this, addr), this);
-               processor_changed (addr);
+               _sel_plugin (sur->plugin_id, addr);
        }
 
        return 0;
@@ -3640,7 +3710,6 @@ void
 OSC::processor_changed (lo_address addr)
 {
        OSCSurface *sur = get_surface (addr);
-       sur->proc_connection.disconnect ();
        _sel_plugin (sur->plugin_id, addr);
        if (sur->sel_obs) {
                sur->sel_obs->renew_sends ();
@@ -4265,12 +4334,7 @@ OSC::select_plugin_parameter (const char *path, const char* types, lo_arg **argv
        if (sur->plug_page_size && (paid > (int)sur->plug_page_size)) {
                return float_message_with_id ("/select/plugin/parameter", paid, 0, sur->feedback[2], get_address (msg));
        }
-       boost::shared_ptr<Stripable> s;
-       if (sur->expand_enable) {
-               s = get_strip (sur->expand, get_address (msg));
-       } else {
-               s = _select;
-       }
+       boost::shared_ptr<Stripable> s = sur->select;
        boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route>(s);
        if (!r) {
                return 1;
@@ -4283,7 +4347,7 @@ OSC::select_plugin_parameter (const char *path, const char* types, lo_arg **argv
        }
        boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
        // paid is paged parameter convert to absolute
-       int parid = paid + (int)(sur->plug_page_size * (sur->plug_page - 1));
+       int parid = paid + (int)sur->plug_page - 1;
        if (parid > (int) sur->plug_params.size ()) {
                if (sur->feedback[13]) {
                        float_message_with_id ("/select/plugin/parameter", paid, 0, sur->feedback[2], get_address (msg));
@@ -4316,6 +4380,36 @@ OSC::select_plugin_parameter (const char *path, const char* types, lo_arg **argv
        return 1;
 }
 
+int
+OSC::sel_plugin_activate (float state, lo_message msg)
+{
+       if (!session) {
+               return -1;
+       }
+       OSCSurface *sur = get_surface(get_address (msg));
+       boost::shared_ptr<Stripable> s = sur->select;
+
+       boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
+
+       if (r) {
+               boost::shared_ptr<Processor> redi=r->nth_plugin (sur->plugins[sur->plugin_id -1]);
+               if (redi) {
+                       boost::shared_ptr<PluginInsert> pi;
+                       if ((pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
+                               if(state > 0) {
+                                       pi->activate();
+                               } else {
+                                       pi->deactivate();
+                               }
+                               return 0;
+                       }
+               }
+       }
+       float_message ("/select/plugin/activate", 0, get_address (msg));
+       PBD::warning << "OSC: Select has no Plugin." << endmsg;
+       return 0;
+}
+
 int
 OSC::route_plugin_list (int ssid, lo_message msg) {
        if (!session) {
@@ -5213,7 +5307,7 @@ struct StripableByPresentationOrder
 };
 
 OSC::Sorted
-OSC::get_sorted_stripables(std::bitset<32> types, bool cue)
+OSC::get_sorted_stripables(std::bitset<32> types, bool cue, bool custom, Sorted my_list)
 {
        Sorted sorted;
        StripableList stripables;
@@ -5221,6 +5315,25 @@ OSC::get_sorted_stripables(std::bitset<32> types, bool cue)
        // fetch all stripables
        session->get_stripables (stripables);
 
+       if (custom) {
+               uint32_t nstps = my_list.size ();
+               boost::shared_ptr<Stripable> s;
+               for (uint32_t i = 0; i < nstps; i++) {
+                       bool exists = false;
+                       s = my_list[i];
+                       for (StripableList::iterator it = stripables.begin(); it != stripables.end(); ++it) {
+                               boost::shared_ptr<Stripable> sl = *it;
+                               if (s == sl) {
+                                       exists = true;
+                                       break;
+                               }
+                       }
+                       if(!exists) {
+                               my_list[i] = boost::shared_ptr<Stripable>();
+                       }
+               }
+               return my_list;
+       }
        // Look for stripables that match bit in sur->strip_types
        for (StripableList::iterator it = stripables.begin(); it != stripables.end(); ++it) {
 
@@ -5291,17 +5404,19 @@ OSC::cue_parse (const char *path, const char* types, lo_arg **argv, int argc, lo
        OSCSurface *s = get_surface(get_address (msg), true);
        s->bank_size = 0;
        float value = 0;
+       if (argc == 1) {
+               if (types[0] == 'f') {
+                       value = argv[0]->f;
+               } else if (types[0] == 'i') {
+                       value = (float) argv[0]->i;
+               }
+       }
        int ret = 1; /* unhandled */
        if (!strncmp (path, "/cue/aux", 8)) {
                // set our Aux bus
                if (argc) {
-                       if (types[0] == 'f') {
-                               value = argv[0]->f;
-                       } else if (types[0] == 'i') {
-                               value = (float) argv[0]->i;
-                       }
                        if (value) {
-                               ret = cue_set ((uint32_t) argv[0]->f, msg);
+                               ret = cue_set ((uint32_t) value, msg);
                        } else {
                                ret = 0;
                        }
@@ -5334,23 +5449,23 @@ OSC::cue_parse (const char *path, const char* types, lo_arg **argv, int argc, lo
        else if (!strncmp (path, "/cue/send/fader/", 16) && strlen (path) > 16) {
                if (argc == 1) {
                        int id = atoi (&path[16]);
-                       ret = cue_send_fader (id, argv[0]->f, msg);
+                       ret = cue_send_fader (id, value, msg);
                }
        }
        else if (!strncmp (path, "/cue/send/enable/", 17) && strlen (path) > 17) {
                if (argc == 1) {
                        int id = atoi (&path[17]);
-                       ret = cue_send_enable (id, argv[0]->f, msg);
+                       ret = cue_send_enable (id, value, msg);
                }
        }
        else if (!strncmp (path, "/cue/fader", 10)) {
                if (argc == 1) {
-                       ret = cue_aux_fader (argv[0]->f, msg);
+                       ret = cue_aux_fader (value, msg);
                }
        }
        else if (!strncmp (path, "/cue/mute", 9)) {
                if (argc == 1) {
-                       ret = cue_aux_mute (argv[0]->f, msg);
+                       ret = cue_aux_mute (value, msg);
                }
        }
 
@@ -5374,7 +5489,7 @@ OSC::_cue_set (uint32_t aux, lo_address addr)
        s->feedback = 0;
        s->gainmode = 1;
        s->cue = true;
-       s->strips = get_sorted_stripables(s->strip_types, s->cue);
+       s->strips = get_sorted_stripables(s->strip_types, s->cue, false, s->custom_strips);
 
        s->nstrips = s->strips.size();
 
@@ -5396,7 +5511,7 @@ OSC::_cue_set (uint32_t aux, lo_address addr)
                                // make a list of stripables with sends that go to this bus
                                s->sends = cue_get_sorted_stripables(stp, aux, addr);
                                if (s->cue_obs) {
-                                       s->cue_obs->refresh_strip (stp, s->sends, false);
+                                       s->cue_obs->refresh_strip (stp, s->sends, true);
                                } else {
                                        // start cue observer
                                        OSCCueObserver* co = new OSCCueObserver (*this, s);
@@ -5438,6 +5553,8 @@ OSC::cue_previous (lo_message msg)
        }
        if (s->aux > 1) {
                ret = cue_set (s->aux - 1, msg);
+       } else {
+               ret = cue_set (1, msg);
        }
        return ret;
 }