+ p = node.property (X_("address-only"));
+ if (p) {
+ address_only = OSCDebugMode (PBD::atoi(p->value ()));
+ }
+ p = node.property (X_("remote-port"));
+ if (p) {
+ remote_port = p->value ();
+ }
+ p = node.property (X_("banksize"));
+ if (p) {
+ default_banksize = OSCDebugMode (PBD::atoi(p->value ()));
+ }
+ p = node.property (X_("striptypes"));
+ if (p) {
+ default_strip = OSCDebugMode (PBD::atoi(p->value ()));
+ }
+ p = node.property (X_("feedback"));
+ if (p) {
+ default_feedback = OSCDebugMode (PBD::atoi(p->value ()));
+ }
+ p = node.property (X_("gainmode"));
+ if (p) {
+ default_gainmode = OSCDebugMode (PBD::atoi(p->value ()));
+ }
+ XMLNode* cnode = node.child (X_("Configurations"));
+
+ if (cnode) {
+ XMLNodeList const& devices = cnode->children();
+ for (XMLNodeList::const_iterator d = devices.begin(); d != devices.end(); ++d) {
+ XMLProperty const * prop = (*d)->property (X_("url"));
+ if (prop) {
+ OSCSurface s;
+ bank_dirty = true;
+ s.remote_url = prop->value();
+ prop = (*d)->property (X_("bank-size"));
+ if (prop) {
+ s.bank_size = atoi (prop->value().c_str());
+ }
+ prop = (*d)->property (X_("strip-types"));
+ if (prop) {
+ s.strip_types = atoi (prop->value().c_str());
+ }
+ prop = (*d)->property (X_("feedback"));
+ if (prop) {
+ s.feedback = atoi (prop->value().c_str());
+ }
+ prop = (*d)->property (X_("gainmode"));
+ if (prop) {
+ s.gainmode = atoi (prop->value().c_str());
+ }
+ s.bank = 1;
+ s.sel_obs = 0;
+ s.expand = 0;
+ s.expand_enable = false;
+ s.strips = get_sorted_stripables(s.strip_types);
+ s.nstrips = s.strips.size();
+ _surface.push_back (s);
+ }
+ }
+ }
+ global_init = true;
+ tick = false;
+
+ return 0;
+}
+
+// predicate for sort call in get_sorted_stripables
+struct StripableByPresentationOrder
+{
+ bool operator () (const boost::shared_ptr<Stripable> & a, const boost::shared_ptr<Stripable> & b) const
+ {
+ return a->presentation_info().order() < b->presentation_info().order();
+ }
+
+ bool operator () (const Stripable & a, const Stripable & b) const
+ {
+ return a.presentation_info().order() < b.presentation_info().order();
+ }
+
+ bool operator () (const Stripable * a, const Stripable * b) const
+ {
+ return a->presentation_info().order() < b->presentation_info().order();
+ }
+};
+
+OSC::Sorted
+OSC::get_sorted_stripables(std::bitset<32> types)
+{
+ Sorted sorted;
+
+ // fetch all stripables
+ StripableList stripables;
+
+ session->get_stripables (stripables);
+
+ // Look for stripables that match bit in sur->strip_types
+ for (StripableList::iterator it = stripables.begin(); it != stripables.end(); ++it) {
+
+ boost::shared_ptr<Stripable> s = *it;
+ if ((!types[9]) && (s->presentation_info().flags() & PresentationInfo::Hidden)) {
+ // do nothing... skip it
+ } else {
+
+ if (types[0] && (s->presentation_info().flags() & PresentationInfo::AudioTrack)) {
+ sorted.push_back (s);
+ } else
+ if (types[1] && (s->presentation_info().flags() & PresentationInfo::MidiTrack)) {
+ sorted.push_back (s);
+ } else
+ if ((s->presentation_info().flags() & PresentationInfo::AudioBus)) {
+ boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
+ // r->feeds (session->master_out()) may make more sense
+ 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);
+ }
+ }
+ } else
+ if (types[3] && (s->presentation_info().flags() & PresentationInfo::MidiBus)) {
+ sorted.push_back (s);
+ } else
+ if (types[4] && (s->presentation_info().flags() & PresentationInfo::VCA)) {
+ sorted.push_back (s);
+ } else
+ if (types[8] && (s->presentation_info().flags() & PresentationInfo::Selected)) {
+ sorted.push_back (s);
+ } else
+ if (types[9] && (s->presentation_info().flags() & PresentationInfo::Hidden)) {
+ sorted.push_back (s);
+ }
+ }
+ }
+ sort (sorted.begin(), sorted.end(), StripableByPresentationOrder());
+ // Master/Monitor might be anywhere... we put them at the end - Sorry ;)
+ if (types[5]) {
+ sorted.push_back (session->master_out());
+ }
+ if (types[6]) {
+ sorted.push_back (session->monitor_out());
+ }
+ return sorted;
+}
+
+int
+OSC::cue_parse (const char *path, const char* types, lo_arg **argv, int argc, lo_message msg)
+{
+ int ret = 1; /* unhandled */
+
+ if (!strncmp (path, "/cue/aux", 8)) {
+ // set our Aux bus
+ cue_set (argv[0]->i, msg);
+ ret = 0;
+ }
+ else if (!strncmp (path, "/cue/connect", 12)) {
+ // switch to next Aux bus
+ cue_set (0, msg);
+ ret = 0;
+ }
+ else if (!strncmp (path, "/cue/next_aux", 13)) {
+ // switch to next Aux bus
+ cue_next (msg);
+ ret = 0;
+ }
+ else if (!strncmp (path, "/cue/previous_aux", 17)) {
+ // switch to previous Aux bus
+ cue_previous (msg);
+ ret = 0;
+ }
+ else if (!strncmp (path, "/cue/send/fader/", 16) && strlen (path) > 16) {
+ int id = atoi (&path[16]);
+ cue_send_fader (id, argv[0]->f, msg);
+ ret = 0;
+ }
+ else if (!strncmp (path, "/cue/send/enable/", 17) && strlen (path) > 17) {
+ int id = atoi (&path[17]);
+ cue_send_enable (id, argv[0]->f, msg);
+ ret = 0;
+ }
+ else if (!strncmp (path, "/cue/fader", 10)) {
+ cue_aux_fader (argv[0]->f, msg);
+ ret = 0;
+ }
+ else if (!strncmp (path, "/cue/mute", 9)) {
+ cue_aux_mute (argv[0]->f, msg);
+ ret = 0;
+ }
+
+ if ((ret && _debugmode == Unhandled)) {
+ debugmsg (_("Unhandled OSC cue message"), path, types, argv, argc);
+ } else if ((!ret && _debugmode == All)) {
+ debugmsg (_("OSC cue"), path, types, argv, argc);
+ }
+
+ return ret;
+}
+
+int
+OSC::cue_set (uint32_t aux, lo_message msg)
+{
+ return _cue_set (aux, get_address (msg));
+}
+
+int
+OSC::_cue_set (uint32_t aux, lo_address addr)
+{
+ OSCSurface *s = get_surface(addr);
+ s->bank_size = 0;
+ s->strip_types = 128;
+ s->feedback = 0;
+ s->gainmode = 1;
+ s->cue = true;
+ s->aux = aux;
+ s->strips = get_sorted_stripables(s->strip_types);
+
+ s->nstrips = s->strips.size();
+ // get rid of any old CueObsevers for this address
+ cueobserver_connections.drop_connections ();
+ CueObservers::iterator x;
+ for (x = cue_observers.begin(); x != cue_observers.end();) {
+
+ OSCCueObserver* co;
+
+ if ((co = dynamic_cast<OSCCueObserver*>(*x)) != 0) {
+
+ int res = strcmp(lo_address_get_url(co->address()), lo_address_get_url(addr));
+
+ if (res == 0) {
+ delete *x;
+ x = cue_observers.erase (x);
+ } else {
+ ++x;
+ }
+ } else {
+ ++x;
+ }
+ }
+
+ // get a list of Auxes
+ for (uint32_t n = 0; n < s->nstrips; ++n) {
+ boost::shared_ptr<Stripable> stp = s->strips[n];
+ if (stp) {
+ text_message (string_compose ("/cue/name/%1", n+1), stp->name(), addr);
+ if (aux == n+1) {
+ // aux must be at least one
+ // need a signal if aux vanishes
+ stp->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::_cue_set, this, aux, addr), this);
+
+ // make a list of stripables with sends that go to this bus
+ s->sends = cue_get_sorted_stripables(stp, aux, addr);
+ // start cue observer
+ OSCCueObserver* co = new OSCCueObserver (stp, s->sends, addr);
+ cue_observers.push_back (co);
+ }
+
+ }
+ }
+
+ return 0;
+}
+
+int
+OSC::cue_next (lo_message msg)
+{
+ OSCSurface *s = get_surface(get_address (msg));
+ if (s->aux < s->nstrips) {
+ cue_set (s->aux + 1, msg);
+ } else {
+ cue_set (s->nstrips, msg);
+ }
+ return 0;
+}
+
+int
+OSC::cue_previous (lo_message msg)
+{
+ OSCSurface *s = get_surface(get_address (msg));
+ if (s->aux > 1) {
+ cue_set (s->aux - 1, msg);
+ }
+ return 0;
+}
+
+boost::shared_ptr<Send>
+OSC::cue_get_send (uint32_t id, lo_address addr)
+{
+ OSCSurface *s = get_surface(addr);
+ if (id && s->aux > 0 && id <= s->sends.size()) {
+ boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s->sends[id - 1]);
+ boost::shared_ptr<Stripable> aux = get_strip (s->aux, addr);
+ if (r && aux) {
+ return r->internal_send_for (boost::dynamic_pointer_cast<Route> (aux));
+ }
+ }
+ return boost::shared_ptr<Send>();
+
+}
+
+int
+OSC::cue_aux_fader (float position, lo_message msg)
+{
+ if (!session) return -1;
+
+ OSCSurface *sur = get_surface(get_address (msg));
+ if (sur->cue) {
+ if (sur->aux) {
+ boost::shared_ptr<Stripable> s = get_strip (sur->aux, get_address (msg));
+
+ if (s) {
+ float abs;
+ abs = slider_position_to_gain_with_max (position, 2.0);
+ if (s->gain_control()) {
+ s->gain_control()->set_value (abs, PBD::Controllable::NoGroup);
+ return 0;
+ }
+ }
+ }
+ }
+ return cue_float_message ("/cue/fader", 0, get_address (msg));
+}
+
+int
+OSC::cue_aux_mute (float state, lo_message msg)
+{
+ if (!session) return -1;
+
+ OSCSurface *sur = get_surface(get_address (msg));
+ if (sur->cue) {
+ if (sur->aux) {
+ boost::shared_ptr<Stripable> s = get_strip (sur->aux, get_address (msg));
+
+ if (s->mute_control()) {
+ s->mute_control()->set_value (state ? 1.0 : 0.0, PBD::Controllable::NoGroup);
+ return 0;
+ }
+ }
+ }
+ return cue_float_message ("/cue/mute", 0, get_address (msg));
+}
+
+int
+OSC::cue_send_fader (uint32_t id, float val, lo_message msg)
+{
+ if (!session) {
+ return -1;
+ }
+ boost::shared_ptr<Send> s = cue_get_send (id, get_address (msg));
+ float abs;
+ if (s) {
+ if (s->gain_control()) {
+ abs = slider_position_to_gain_with_max (val, 2.0);
+ s->gain_control()->set_value (abs, PBD::Controllable::NoGroup);
+ return 0;
+ }
+ }
+ return cue_float_message (string_compose ("/cue/send/fader/%1", id), 0, get_address (msg));
+}
+
+int
+OSC::cue_send_enable (uint32_t id, float state, lo_message msg)
+{
+ if (!session)
+ return -1;
+ boost::shared_ptr<Send> s = cue_get_send (id, get_address (msg));
+ if (s) {
+ if (state) {
+ s->activate ();
+ } else {
+ s->deactivate ();
+ }
+ return 0;
+ }
+ return cue_float_message (string_compose ("/cue/send/enable/%1", id), 0, get_address (msg));
+}
+
+int
+OSC::cue_float_message (string path, float val, lo_address addr)
+{
+
+ lo_message reply;
+ reply = lo_message_new ();
+ lo_message_add_float (reply, (float) val);
+
+ lo_send_message (addr, path.c_str(), reply);
+ lo_message_free (reply);
+
+ return 0;
+}
+
+int
+OSC::text_message (string path, string val, lo_address addr)
+{
+
+ lo_message reply;
+ reply = lo_message_new ();
+ lo_message_add_string (reply, val.c_str());
+
+ lo_send_message (addr, path.c_str(), reply);
+ lo_message_free (reply);