Make foldback bus match foldback sends namewise
[ardour.git] / libs / surfaces / osc / osc.cc
index 95905df87b84f89cfb1cc4c672c07bf701d731b9..08b8fb9c185ea31a48282eed2c586f74565f1c95 100644 (file)
@@ -102,7 +102,7 @@ OSC::OSC (Session& s, uint32_t port)
        , address_only (true)
        , remote_port ("8000")
        , default_banksize (0)
-       , default_strip (159)
+       , default_strip (31)
        , default_feedback (0)
        , default_gainmode (0)
        , default_send_size (0)
@@ -620,6 +620,7 @@ OSC::register_callbacks()
                REGISTER_CALLBACK (serv, X_("/select/eq_freq"), "if", sel_eq_freq);
                REGISTER_CALLBACK (serv, X_("/select/eq_q"), "if", sel_eq_q);
                REGISTER_CALLBACK (serv, X_("/select/eq_shape"), "if", sel_eq_shape);
+               REGISTER_CALLBACK (serv, X_("/select/add_personal_send"), "s", sel_new_personal_send);
 
                /* These commands require the route index in addition to the arg; TouchOSC (et al) can't use these  */
                REGISTER_CALLBACK (serv, X_("/strip/mute"), "ii", route_mute);
@@ -2862,7 +2863,7 @@ OSC::set_temp_mode (lo_address addr)
                                        // this is a bus, but not master, monitor or audition
                                        sur->temp_strips.clear();
                                        StripableList stripables;
-                                       session->get_stripables (stripables);
+                                       session->get_stripables (stripables, PresentationInfo::AllStripables);
                                        for (StripableList::iterator it = stripables.begin(); it != stripables.end(); ++it) {
                                                boost::shared_ptr<Stripable> st = *it;
                                                boost::shared_ptr<Route> ri = boost::dynamic_pointer_cast<Route> (st);
@@ -4273,6 +4274,67 @@ OSC::sel_comment (char *newcomment, lo_message msg) {
        return 0;
 }
 
+int
+OSC::sel_new_personal_send (char *foldback, lo_message msg)
+{
+       OSCSurface *sur = get_surface(get_address (msg));
+       boost::shared_ptr<Stripable> s;
+       s = sur->select;
+       boost::shared_ptr<Route> rt = boost::shared_ptr<Route> ();
+       if (s) {
+               rt = boost::dynamic_pointer_cast<Route> (s);
+               if (!rt) {
+                       PBD::warning << "OSC: can not send from VCAs." << endmsg;
+                       return -1;
+               }
+       }
+       /* if a foldbackbus called foldback exists use it
+        * other wise create create it. Then create a foldback send from
+        * this route to that bus.
+        */
+       string foldbackbus = foldback;
+       string foldback_name = foldbackbus;
+       if (foldbackbus.find ("- monitor") == string::npos) {
+               foldback_name = string_compose ("%1 - monitor", foldbackbus);
+       }
+       boost::shared_ptr<Route> lsn_rt = session->route_by_name (foldback_name);
+       if (!lsn_rt) {
+               // doesn't exist but check if raw name does and is foldbackbus
+               boost::shared_ptr<Route> raw_rt = session->route_by_name (foldbackbus);
+               if (raw_rt && raw_rt->is_foldbackbus()) {
+                       lsn_rt = raw_rt;
+               } else {
+                       // create the foldbackbus
+                       RouteList list = session->new_audio_route (2, 2, 0, 1, foldback_name, PresentationInfo::FoldbackBus, (uint32_t) -1);
+                       lsn_rt = *(list.begin());
+                       lsn_rt->presentation_info().set_hidden (true);
+                       session->set_dirty();
+               }
+       }
+       if (lsn_rt) {
+               //boost::shared_ptr<Route> rt_send = ;
+               if (rt && (lsn_rt != rt)) {
+                       // make sure there isn't one already
+                       bool s_only = true;
+                       if (!rt->feeds (lsn_rt, &s_only)) {
+                               // create send
+                               rt->add_foldback_send (lsn_rt);
+                               //boost::shared_ptr<Send> snd = rt->internal_send_for (aux);
+                               session->dirty ();
+                               return 0;
+                       } else {
+                               PBD::warning << "OSC: new_send - duplicate send, ignored." << endmsg;
+                       }
+               } else {
+                       PBD::warning << "OSC: new_send - can't send to self." << endmsg;
+               }
+       } else {
+               PBD::warning << "OSC: new_send - no FoldbackBus to send to." << endmsg;
+       }
+
+       return -1;
+}
+
 int
 OSC::strip_group (int ssid, char *group, lo_message msg) {
        if (!session) {
@@ -6234,7 +6296,7 @@ OSC::get_sorted_stripables(std::bitset<32> types, bool cue, uint32_t custom, Sor
        StripableList custom_list;
 
        // fetch all stripables
-       session->get_stripables (stripables);
+       session->get_stripables (stripables, PresentationInfo::AllStripables);
        if (custom) {
                uint32_t nstps = my_list.size ();
                // check each custom strip to see if it still exists
@@ -6287,31 +6349,23 @@ OSC::get_sorted_stripables(std::bitset<32> types, bool cue, uint32_t custom, Sor
                                sorted.push_back (s);
                        } else if (types[4] && boost::dynamic_pointer_cast<VCA>(s)) {
                                sorted.push_back (s);
+                       } else  if (s->is_foldbackbus()) {
+                               if (types[7]) {
+                                       sorted.push_back (s);
+                               }
                        } else
 #ifdef MIXBUS
                        if (types[2] && Profile->get_mixbus() && s->mixbus()) {
                                sorted.push_back (s);
                        } else
-                       if (types[7] && boost::dynamic_pointer_cast<Route>(s) && !boost::dynamic_pointer_cast<Track>(s)) {
-                               if (Profile->get_mixbus() && !s->mixbus()) {
-                                       sorted.push_back (s);
-                               }
-                       } else
 #endif
-                       if ((types[2] || types[3] || types[7]) && boost::dynamic_pointer_cast<Route>(s) && !boost::dynamic_pointer_cast<Track>(s)) {
+                       if (boost::dynamic_pointer_cast<Route>(s) && !boost::dynamic_pointer_cast<Track>(s)) {
                                boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route>(s);
                                if (!(s->presentation_info().flags() & PresentationInfo::MidiBus)) {
                                        // note some older sessions will show midibuses as busses
-                                       if (r->direct_feeds_according_to_reality (session->master_out())) {
-                                               // this is a bus
-                                               if (types[2]) {
-                                                       sorted.push_back (s);
-                                               }
-                                       } else {
-                                               // this is an Aux out
-                                               if (types[7]) {
-                                                       sorted.push_back (s);
-                                               }
+                                       // this is a bus
+                                       if (types[2]) {
+                                               sorted.push_back (s);
                                        }
                                } else if (types[3]) {
                                                sorted.push_back (s);
@@ -6360,6 +6414,16 @@ OSC::cue_parse (const char *path, const char* types, lo_arg **argv, int argc, lo
                        }
                }
        }
+       else if (!strncmp (path, X_("/cue/connect_aux"), 16)) {
+               // Create new Aux bus
+               string dest = "";
+               if (argc == 1 && types[0] == 's') {
+                       dest = &argv[0]->s;
+                       ret = cue_connect_aux (dest, msg);
+               } else {
+                       PBD::warning << "OSC: connect_aux has wrong number or type of parameters." << endmsg;
+               }
+       }
        else if (!strncmp (path, X_("/cue/connect"), 12)) {
                // Connect to default Aux bus
                if ((!argc) || argv[0]->f || argv[0]->i) {
@@ -6368,6 +6432,38 @@ OSC::cue_parse (const char *path, const char* types, lo_arg **argv, int argc, lo
                        ret = 0;
                }
        }
+       else if (!strncmp (path, X_("/cue/new_aux"), 12)) {
+               // Create new Aux bus
+               string name = "";
+               string dest_1 = "";
+               string dest_2 = "";
+               if (argc == 3 && types[0] == 's' && types[1] == 's' && types[2] == 's') {
+                       name = &argv[0]->s;
+                       dest_1 = &argv[1]->s;
+                       dest_2 = &argv[2]->s;
+                       ret = cue_new_aux (name, dest_1, dest_2, msg);
+               } else if (argc == 2 && types[0] == 's' && types[1] == 's') {
+                       name = &argv[0]->s;
+                       dest_1 = &argv[1]->s;
+                       dest_2 = dest_1;
+                       ret = cue_new_aux (name, dest_1, dest_2, msg);
+               } else if (argc == 1 && types[0] == 's') {
+                       name = &argv[0]->s;
+                       ret = cue_new_aux (name, dest_1, dest_2, msg);
+               } else {
+                       PBD::warning << "OSC: new_aux has wrong number or type of parameters." << endmsg;
+               }
+       }
+       else if (!strncmp (path, X_("/cue/new_send"), 13)) {
+               // Create new send to aux
+               string rt_name = "";
+               if (argc == 1 && types[0] == 's') {
+                       rt_name = &argv[0]->s;
+                       ret = cue_new_send (rt_name, msg);
+               } else {
+                       PBD::warning << "OSC: new_send has wrong number or type of parameters." << endmsg;
+               }
+       }
        else if (!strncmp (path, X_("/cue/next_aux"), 13)) {
                // switch to next Aux bus
                if ((!argc) || argv[0]->f || argv[0]->i) {
@@ -6430,7 +6526,10 @@ OSC::_cue_set (uint32_t aux, lo_address addr)
        s->strips = get_sorted_stripables(s->strip_types, s->cue, false, s->custom_strips);
 
        s->nstrips = s->strips.size();
-
+       if (!s->nstrips) {
+               surface_destroy (s);
+               return 0;
+       }
        if (aux < 1) {
                aux = 1;
        } else if (aux > s->nstrips) {
@@ -6464,6 +6563,95 @@ OSC::_cue_set (uint32_t aux, lo_address addr)
        return ret;
 }
 
+int
+OSC::cue_new_aux (string name, string dest_1, string dest_2, lo_message msg)
+{
+       // create a new bus named name - monitor
+       RouteList list;
+       boost::shared_ptr<Stripable> aux;
+       name = string_compose ("%1 - monitor", name);
+       list = session->new_audio_route (2, 2, 0, 1, name, PresentationInfo::FoldbackBus, (uint32_t) -1);
+       aux = *(list.begin());
+       if (aux) {
+               boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route>(aux);
+               if (dest_1.size()) {
+                       if (atoi( dest_1.c_str())) {
+                               dest_1 = string_compose ("system:playback_%1", dest_1);
+                       }
+                       if (atoi( dest_2.c_str())) {
+                               dest_2 = string_compose ("system:playback_%1", dest_2);
+                       }
+                       PortSet& ports = r->output()->ports ();
+                       PortSet::iterator i = ports.begin();
+                       ++i;
+                       r->output ()->connect (*(ports.begin()), dest_1, this);
+                       r->output ()->connect (*(i), dest_2, this);
+               }
+               cue_set ((uint32_t) -1, msg);
+               session->set_dirty();
+               return 0;
+       }
+       return -1;
+}
+
+int
+OSC::cue_new_send (string rt_name, lo_message msg)
+{
+       OSCSurface *sur = get_surface(get_address (msg), true);
+       if (sur->cue) {
+               boost::shared_ptr<Route> aux = boost::dynamic_pointer_cast<Route> (get_strip (sur->aux, get_address(msg)));
+               if (aux) {
+                       boost::shared_ptr<Route> rt_send = session->route_by_name (rt_name);
+                       if (rt_send && (aux != rt_send)) {
+                               // make sure there isn't one already
+                               bool s_only = true;
+                               if (!rt_send->feeds (aux, &s_only)) {
+                                       // create send
+                                       rt_send->add_foldback_send (aux);
+                                       boost::shared_ptr<Send> snd = rt_send->internal_send_for (aux);
+                                       session->dirty ();
+                                       return 0;
+                               } else {
+                                       PBD::warning << "OSC: new_send - duplicate send, ignored." << endmsg;
+                               }
+                       } else {
+                               PBD::warning << "OSC: new_send - route doesn't exist or is aux." << endmsg;
+                       }
+               } else {
+                       PBD::warning << "OSC: new_send - No Aux to send to." << endmsg;
+               }
+       } else {
+               PBD::warning << "OSC: new_send - monitoring not set, select aux first." << endmsg;
+       }
+       return 1;
+}
+
+int
+OSC::cue_connect_aux (std::string dest, lo_message msg)
+{
+       OSCSurface *sur = get_surface(get_address (msg), true);
+       int ret = 1;
+       if (sur->cue) {
+               boost::shared_ptr<Route> rt = boost::dynamic_pointer_cast<Route> (get_strip (sur->aux, get_address(msg)));
+               if (rt) {
+                       if (dest.size()) {
+                               rt->output()->disconnect (this);
+                               if (atoi( dest.c_str())) {
+                                       dest = string_compose ("system:playback_%1", dest);
+                               }
+                               PortSet& ports = rt->output()->ports ();
+                               rt->output ()->connect (*(ports.begin()), dest, this);
+                               session->set_dirty();
+                               ret = 0;
+                       }
+               }
+       }
+       if (ret) {
+               PBD::warning << "OSC: cannot connect, no Aux bus chosen." << endmsg;
+       }
+       return ret;
+}
+
 int
 OSC::cue_next (lo_message msg)
 {
@@ -6709,24 +6897,15 @@ OSC::cue_get_sorted_stripables(boost::shared_ptr<Stripable> aux, uint32_t id, lo
        // fetch all stripables
        StripableList stripables;
 
-       session->get_stripables (stripables);
-
-       // Look for stripables that have a send to aux
-       for (StripableList::iterator it = stripables.begin(); it != stripables.end(); ++it) {
-
-               boost::shared_ptr<Stripable> s = *it;
-               // we only want routes
-               boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
-               if (r) {
-                       r->processors_changed.connect  (*this, MISSING_INVALIDATOR, boost::bind (&OSC::recalcbanks, this), this);
-                       boost::shared_ptr<Send> snd = r->internal_send_for (boost::dynamic_pointer_cast<Route> (aux));
-                       if (snd) { // test for send to aux
-                               sorted.push_back (s);
-                               s->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::cue_set, this, id, msg), this);
-                       }
+       session->get_stripables (stripables, PresentationInfo::MixerStripables);
+       boost::shared_ptr<Route> aux_rt = boost::dynamic_pointer_cast<Route> (aux);
+       Route::FedBy fed_by = aux_rt->fed_by();
+       for (Route::FedBy::iterator i = fed_by.begin(); i != fed_by.end(); ++i) {
+               if (i->sends_only) {
+                       boost::shared_ptr<Stripable> s (i->r.lock());
+                       sorted.push_back (s);
+                       s->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::cue_set, this, id, msg), this);
                }
-
-
        }
        sort (sorted.begin(), sorted.end(), StripableByPresentationOrder());