#include "ardour/plugin_insert.h"
#include "ardour/presentation_info.h"
#include "ardour/send.h"
+#include "ardour/phase_control.h"
+#include "ardour/solo_isolate_control.h"
+#include "ardour/solo_safe_control.h"
+#include "ardour/vca_manager.h"
#include "osc_select_observer.h"
#include "osc.h"
, _osc_unix_server (0)
, _send_route_changes (true)
, _debugmode (Off)
+ , tick (true)
+ , bank_dirty (false)
, gui (0)
{
_instance = this;
periodic_connection = periodic_timeout->connect (sigc::mem_fun (*this, &OSC::periodic));
periodic_timeout->attach (main_loop()->get_context());
+ // catch GUI select changes for GUI_select mode
StripableSelectionChanged.connect (session_connections, MISSING_INVALIDATOR, boost::bind (&OSC::gui_selection_changed, this, _1), this);
+ // catch track reordering
+ // receive routes added
+ session->RouteAdded.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&OSC::notify_routes_added, this, _1), this);
+ // receive VCAs added
+ session->vca_manager().VCAAdded.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&OSC::notify_vca_added, this, _1), this);
+ // order changed
+ PresentationInfo::Change.connect (session_connections, MISSING_INVALIDATOR, boost::bind (&OSC::recalcbanks, this), this);
+
+
return 0;
}
REGISTER_CALLBACK (serv, "/select/record_safe", "i", sel_recsafe);
REGISTER_CALLBACK (serv, "/select/mute", "i", sel_mute);
REGISTER_CALLBACK (serv, "/select/solo", "i", sel_solo);
+ REGISTER_CALLBACK (serv, "/select/solo_iso", "i", sel_solo_iso);
+ REGISTER_CALLBACK (serv, "/select/solo_safe", "i", sel_solo_safe);
REGISTER_CALLBACK (serv, "/select/monitor_input", "i", sel_monitor_input);
REGISTER_CALLBACK (serv, "/select/monitor_disk", "i", sel_monitor_disk);
+ REGISTER_CALLBACK (serv, "/select/polarity", "i", sel_phase);
REGISTER_CALLBACK (serv, "/select/gain", "f", sel_gain);
REGISTER_CALLBACK (serv, "/select/fader", "f", sel_fader);
REGISTER_CALLBACK (serv, "/select/trimdB", "f", sel_trim);
REGISTER_CALLBACK (serv, "/select/pan_stereo_position", "f", sel_pan_position);
+ REGISTER_CALLBACK (serv, "/select/pan_stereo_width", "f", sel_pan_width);
+ REGISTER_CALLBACK (serv, "/select/send_gain", "if", sel_sendgain);
+ REGISTER_CALLBACK (serv, "/select/send_fader", "if", sel_sendfader);
+ REGISTER_CALLBACK (serv, "/select/send_enable", "if", sel_sendenable);
/* These commands require the route index in addition to the arg; TouchOSC (et al) can't use these */
REGISTER_CALLBACK (serv, "/strip/mute", "ii", route_mute);
REGISTER_CALLBACK (serv, "/strip/solo", "ii", route_solo);
+ REGISTER_CALLBACK (serv, "/strip/solo_iso", "ii", route_solo_iso);
+ REGISTER_CALLBACK (serv, "/strip/solo_safe", "ii", route_solo_safe);
REGISTER_CALLBACK (serv, "/strip/recenable", "ii", route_recenable);
REGISTER_CALLBACK (serv, "/strip/record_safe", "ii", route_recsafe);
REGISTER_CALLBACK (serv, "/strip/monitor_input", "ii", route_monitor_input);
REGISTER_CALLBACK (serv, "/strip/monitor_disk", "ii", route_monitor_disk);
REGISTER_CALLBACK (serv, "/strip/select", "ii", strip_select);
REGISTER_CALLBACK (serv, "/strip/gui_select", "ii", strip_gui_select);
+ REGISTER_CALLBACK (serv, "/strip/polarity", "ii", strip_phase);
REGISTER_CALLBACK (serv, "/strip/gain", "if", route_set_gain_dB);
REGISTER_CALLBACK (serv, "/strip/fader", "if", route_set_gain_fader);
- REGISTER_CALLBACK (serv, "/strip/trimabs", "if", route_set_trim_abs);
REGISTER_CALLBACK (serv, "/strip/trimdB", "if", route_set_trim_dB);
REGISTER_CALLBACK (serv, "/strip/pan_stereo_position", "if", route_set_pan_stereo_position);
REGISTER_CALLBACK (serv, "/strip/pan_stereo_width", "if", route_set_pan_stereo_width);
REGISTER_CALLBACK (serv, "/strip/send/gainabs", "iif", route_set_send_gain_abs);
REGISTER_CALLBACK (serv, "/strip/send/gain", "iif", route_set_send_gain_dB);
REGISTER_CALLBACK (serv, "/strip/send/fader", "iif", route_set_send_fader);
+ REGISTER_CALLBACK (serv, "/strip/send/enable", "iif", route_set_send_enable);
/* still not-really-standardized query interface */
//REGISTER_CALLBACK (serv, "/ardour/*/#current_value", "", current_value);
OSCRouteObserver* o = new OSCRouteObserver (strip, addr, sid, s->gainmode, s->feedback);
route_observers.push_back (o);
- strip->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::drop_route, this, boost::weak_ptr<Stripable> (strip)), this);
+ strip->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::route_lost, this, boost::weak_ptr<Stripable> (strip)), this);
+}
+
+void
+OSC::route_lost (boost::weak_ptr<Stripable> wr)
+{
+ tick = false;
+ drop_route (wr);
+ bank_dirty = true;
}
void
strip_gui_select (ssid, argv[0]->f == 1.0, msg);
ret = 0;
}
+ else if (!strncmp (path, "/select/send_gain/", 18) && strlen (path) > 18) {
+ int ssid = atoi (&path[18]);
+ route_mute (ssid, argv[0]->f == 1.0, msg);
+ ret = 0;
+ }
+ else if (!strncmp (path, "/select/send_fader/", 19) && strlen (path) > 19) {
+ int ssid = atoi (&path[19]);
+ route_solo (ssid, argv[0]->f == 1.0, msg);
+ ret = 0;
+ }
}
if ((ret && _debugmode == Unhandled)) {
}
}
+void
+OSC::notify_routes_added (ARDOUR::RouteList &)
+{
+ recalcbanks();
+}
+
+void
+OSC::notify_vca_added (ARDOUR::VCAList &)
+{
+ recalcbanks();
+}
+
+void
+OSC::recalcbanks ()
+{
+ tick = false;
+ bank_dirty = true;
+}
+
+void
+OSC::_recalcbanks ()
+{
+ for (uint32_t it = 0; it < _surface.size(); ++it) {
+ OSCSurface* sur = &_surface[it];
+ // find lo_address
+ lo_address addr = lo_address_new_from_url (sur->remote_url.c_str());
+ _set_bank (sur->bank, addr);
+ }
+}
+
/*
* This gets called not only when bank changes but also:
* - bank size change
*/
int
OSC::set_bank (uint32_t bank_start, lo_message msg)
+{
+ return _set_bank (bank_start, lo_message_get_source (msg));
+}
+
+int
+OSC::_set_bank (uint32_t bank_start, lo_address addr)
{
if (!session) {
return -1;
nstrips = session->nroutes() - 1;
}
// reset local select
- _strip_select (0, lo_message_get_source (msg));
+ _strip_select (0, addr);
// undo all listeners for this url
for (int n = 0; n <= (int) nstrips; ++n) {
boost::shared_ptr<Stripable> stp = session->get_remote_nth_stripable (n, PresentationInfo::Route);
if (stp) {
- end_listen (stp, lo_message_get_source (msg));
+ end_listen (stp, addr);
}
}
- OSCSurface *s = get_surface (lo_message_get_source (msg));
+ OSCSurface *s = get_surface (addr);
uint32_t b_size;
if (!s->bank_size) {
boost::shared_ptr<Stripable> stp = session->get_remote_nth_stripable (n - 1, PresentationInfo::Route);
if (stp) {
- listen_to_route(stp, lo_message_get_source (msg));
+ listen_to_route(stp, addr);
if (!s->feedback[10]) {
if (stp->is_selected()) {
- _strip_select (n, lo_message_get_source (msg));
+ _strip_select (n, addr);
}
}
}
}
}
+ bank_dirty = false;
+ tick = true;
return 0;
}
}
int
-OSC::master_set_pan_stereo_position (float position)
+OSC::master_set_pan_stereo_position (float position, lo_message msg)
{
if (!session) return -1;
+ float endposition = .5;
boost::shared_ptr<Stripable> s = session->master_out();
if (s) {
if (s->pan_azimuth_control()) {
s->pan_azimuth_control()->set_value (position, PBD::Controllable::NoGroup);
+ endposition = s->pan_azimuth_control()->get_value ();
}
}
+ OSCSurface *sur = get_surface(lo_message_get_source (msg));
+
+ if (sur->feedback[4]) {
+ lo_message reply = lo_message_new ();
+ lo_message_add_float (reply, endposition);
+
+ lo_send_message (lo_message_get_source (msg), "/master/pan_stereo_position", reply);
+ lo_message_free (reply);
+ }
return 0;
}
boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
if (s) {
- s->mute_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
+ if (s->mute_control()) {
+ s->mute_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
+ return 0;
+ }
}
- return 0;
+ return route_send_fail ("mute", ssid, 0, lo_message_get_source (msg));
}
int
boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
if (s) {
- s->solo_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
+ if (s->solo_control()) {
+ s->solo_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
+ return 0;
+ }
}
- return 0;
+ return route_send_fail ("solo", ssid, 0, lo_message_get_source (msg));
+}
+
+int
+OSC::route_solo_iso (int ssid, int yn, lo_message msg)
+{
+ if (!session) return -1;
+ int rid = get_rid (ssid, lo_message_get_source (msg));
+
+ boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
+
+ if (s) {
+ if (s->solo_isolate_control()) {
+ s->solo_isolate_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
+ return 0;
+ }
+ }
+
+ return route_send_fail ("solo_iso", ssid, 0, lo_message_get_source (msg));
+}
+
+int
+OSC::route_solo_safe (int ssid, int yn, lo_message msg)
+{
+ if (!session) return -1;
+ int rid = get_rid (ssid, lo_message_get_source (msg));
+
+ boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
+
+ if (s) {
+ if (s->solo_safe_control()) {
+ s->solo_safe_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
+ return 0;
+ }
+ }
+
+ return route_send_fail ("solo_safe", ssid, 0, lo_message_get_source (msg));
}
int
}
}
+int
+OSC::sel_solo_iso (uint32_t yn, lo_message msg)
+{
+ OSCSurface *sur = get_surface(lo_message_get_source (msg));
+ if (sur->surface_sel) {
+ return route_solo_iso(sur->surface_sel, yn, msg);
+ } else {
+ return route_send_fail ("solo_iso", 0, 0, lo_message_get_source (msg));
+ }
+}
+
+int
+OSC::sel_solo_safe (uint32_t yn, lo_message msg)
+{
+ OSCSurface *sur = get_surface(lo_message_get_source (msg));
+ if (sur->surface_sel) {
+ return route_solo_safe(sur->surface_sel, yn, msg);
+ } else {
+ return route_send_fail ("solo_safe", 0, 0, lo_message_get_source (msg));
+ }
+}
+
int
OSC::sel_recenable (uint32_t yn, lo_message msg)
{
}
}
}
- // hmm, not set for whatever reason tell surface
return route_send_fail ("recenable", ssid, 0, lo_message_get_source (msg));
}
}
}
}
- // hmm, not set for whatever reason tell surface
return route_send_fail ("record_safe", ssid, 0,lo_message_get_source (msg));
}
if (s) {
boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (s);
if (track) {
- track->monitoring_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
- } else {
- route_send_fail ("monitor_input", ssid, 0, lo_message_get_source (msg));
+ if (track->monitoring_control()) {
+ track->monitoring_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
+ return 0;
+ }
}
}
- return 0;
+ return route_send_fail ("monitor_input", ssid, 0, lo_message_get_source (msg));
}
int
if (s) {
boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (s);
if (track) {
- track->monitoring_control()->set_value (yn ? 2.0 : 0.0, PBD::Controllable::NoGroup);
- } else {
- route_send_fail ("monitor_disk", ssid, 0, lo_message_get_source (msg));
+ if (track->monitoring_control()) {
+ track->monitoring_control()->set_value (yn ? 2.0 : 0.0, PBD::Controllable::NoGroup);
+ return 0;
+ }
}
}
- return 0;
+ return route_send_fail ("monitor_disk", ssid, 0, lo_message_get_source (msg));
}
int
}
}
+
+int
+OSC::strip_phase (int ssid, int yn, lo_message msg)
+{
+ if (!session) return -1;
+ int rid = get_rid (ssid, lo_message_get_source (msg));
+
+ boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
+
+ if (s) {
+ if (s->phase_control()) {
+ s->phase_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
+ return 0;
+ }
+ }
+
+ return route_send_fail ("polarity", ssid, 0, lo_message_get_source (msg));
+}
+
+int
+OSC::sel_phase (uint32_t yn, lo_message msg)
+{
+ OSCSurface *sur = get_surface(lo_message_get_source (msg));
+ if (sur->surface_sel) {
+ return strip_phase(sur->surface_sel, yn, msg);
+ } else {
+ return route_send_fail ("polarity", 0, 0, lo_message_get_source (msg));
+ }
+}
+
int
OSC::strip_select (int ssid, int yn, lo_message msg)
{
if (s) {
sur->surface_sel = ssid;
OSCSelectObserver* sel_fb = new OSCSelectObserver (s, addr, ssid, sur->gainmode, sur->feedback);
+ s->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::recalcbanks, this), this);
sur->sel_obs = sel_fb;
} else {
route_send_fail ("select", ssid, 0 , addr);
int rid = get_rid (ssid, lo_message_get_source (msg));
boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
if (s) {
- //SetStripableSelection ((*s)->presentation_info().order());
- SetStripableSelection (rid); //alt above may end up being better
+ SetStripableSelection (rid);
} else {
route_send_fail ("gui_select", ssid, 0, lo_message_get_source (msg));
}
boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
if (s) {
- s->gain_control()->set_value (level, PBD::Controllable::NoGroup);
+ if (s->gain_control()) {
+ s->gain_control()->set_value (level, PBD::Controllable::NoGroup);
+ } else {
+ return 1;
+ }
+ } else {
+ return 1;
}
return 0;
ret = route_set_gain_abs (rid, dB_to_coefficient (dB), msg);
}
if (ret != 0) {
- route_send_fail ("gain", ssid, -193, lo_message_get_source (msg));
+ return route_send_fail ("gain", ssid, -193, lo_message_get_source (msg));
}
- return ret;
+ return 0;
}
int
ret = route_set_gain_abs (rid, slider_position_to_gain_with_max ((pos/1023), 2.0), msg);
}
if (ret != 0) {
- route_send_fail ("fader", ssid, 0, lo_message_get_source (msg));
+ return route_send_fail ("fader", ssid, 0, lo_message_get_source (msg));
}
- return ret;
+ return 0;
}
int
if (s) {
if (s->trim_control()) {
s->trim_control()->set_value (level, PBD::Controllable::NoGroup);
+ return 0;
}
}
- return 0;
+ return -1;
}
int
OSC::route_set_trim_dB (int ssid, float dB, lo_message msg)
{
- return route_set_trim_abs(ssid, dB_to_coefficient (dB), msg);
+ int ret;
+ ret = route_set_trim_abs(ssid, dB_to_coefficient (dB), msg);
+ if (ret != 0) {
+ return route_send_fail ("trimdB", ssid, 0, lo_message_get_source (msg));
+ }
+
+return 0;
}
int
if (sur->surface_sel) {
return route_set_pan_stereo_position (sur->surface_sel, val, msg);
} else {
- return route_send_fail ("pan_stereo_position", 0, 0, lo_message_get_source (msg));
+ return route_send_fail ("pan_stereo_position", 0, 0.5, lo_message_get_source (msg));
+ }
+}
+
+int
+OSC::sel_pan_width (float val, lo_message msg)
+{
+ OSCSurface *sur = get_surface(lo_message_get_source (msg));
+ if (sur->surface_sel) {
+ return route_set_pan_stereo_width (sur->surface_sel, val, msg);
+ } else {
+ return route_send_fail ("pan_stereo_width", 0, 1, lo_message_get_source (msg));
}
}
if (s) {
if(s->pan_azimuth_control()) {
s->pan_azimuth_control()->set_value (pos, PBD::Controllable::NoGroup);
+ return route_send_fail ("pan_stereo_position", ssid, s->pan_azimuth_control()->get_value (), lo_message_get_source (msg));
}
}
- return 0;
-
+ return route_send_fail ("pan_stereo_position", ssid, 0.5, lo_message_get_source (msg));
}
int
if (s) {
if (s->pan_width_control()) {
s->pan_width_control()->set_value (pos, PBD::Controllable::NoGroup);
+ return 0;
}
}
- return 0;
-
+ return route_send_fail ("pan_stereo_width", ssid, 1, lo_message_get_source (msg));
}
int
if (s->send_level_controllable (sid)) {
s->send_level_controllable (sid)->set_value (val, PBD::Controllable::NoGroup);
+ return 0;
}
- return 0;
+ return -1;
}
int
if (!session) {
return -1;
}
- int ret;
if ((pos > 799.5) && (pos < 800.5)) {
- ret = route_set_send_gain_abs (ssid, sid, 1.0, msg);
+ return route_set_send_gain_abs (ssid, sid, 1.0, msg);
} else {
- ret = route_set_send_gain_abs (ssid, sid, slider_position_to_gain_with_max ((pos/1023), 2.0), msg);
+ return route_set_send_gain_abs (ssid, sid, slider_position_to_gain_with_max ((pos/1023), 2.0), msg);
}
- return ret;
+}
+
+int
+OSC::sel_sendgain (int id, float val, lo_message msg)
+{
+ OSCSurface *sur = get_surface(lo_message_get_source (msg));
+ int ret;
+ if (sur->surface_sel) {
+ ret = route_set_send_gain_dB(sur->surface_sel, id, val, msg);
+ }
+ if (!ret) {
+ return ret;
+ }
+ return sel_send_fail ("send_gain", id, -193, lo_message_get_source (msg));
+}
+
+int
+OSC::sel_sendfader (int id, float val, lo_message msg)
+{
+ OSCSurface *sur = get_surface(lo_message_get_source (msg));
+ int ret;
+ if (sur->surface_sel) {
+ ret = route_set_send_fader(sur->surface_sel, id, val, msg);
+ }
+ if (!ret) {
+ return ret;
+ }
+ return sel_send_fail ("send_gain", id, 0, lo_message_get_source (msg));
+
+}
+
+int
+OSC::route_set_send_enable (int ssid, int sid, float val, lo_message msg)
+{
+ if (!session) {
+ return -1;
+ }
+ int rid = get_rid (ssid, lo_message_get_source (msg));
+
+ boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
+
+ if (s) {
+
+ /* revert to zero-based counting */
+
+ if (sid > 0) {
+ --sid;
+ }
+
+ if (s->send_enable_controllable (sid)) {
+ s->send_enable_controllable (sid)->set_value (val, PBD::Controllable::NoGroup);
+ return 0;
+ }
+
+ if (s->send_level_controllable (sid)) {
+ return 1;
+ }
+
+ }
+
+ return -1;
+}
+
+int
+OSC::sel_sendenable (int id, float val, lo_message msg)
+{
+ OSCSurface *sur = get_surface(lo_message_get_source (msg));
+ int ret;
+ if (sur->surface_sel) {
+ ret = route_set_send_enable(sur->surface_sel, id, val, msg);
+ }
+ switch (ret) {
+ case 0:
+ return ret;
+ case 1:
+ return sel_send_fail ("send_enable", id, 1, lo_message_get_source (msg));
+ default:
+ sel_send_fail ("send_enable", id, 0, lo_message_get_source (msg));
+ return -1;
+ }
+ return -1;
+
+
}
int
bool
OSC::periodic (void)
{
+ if (!tick) {
+ usleep(100); // let flurry of signals subside
+ if (bank_dirty) {
+ _recalcbanks ();
+ bank_dirty = false;
+ tick = true;
+ }
+ }
+
for (GlobalObservers::iterator x = global_observers.begin(); x != global_observers.end(); x++) {
OSCGlobalObserver* go;
ro->tick();
}
}
- for (uint32_t it = 0; it < _surface.size(); ++it) {
+ for (uint32_t it = 0; it < _surface.size(); it++) {
OSCSurface* sur = &_surface[it];
OSCSelectObserver* so;
if ((so = dynamic_cast<OSCSelectObserver*>(sur->sel_obs)) != 0) {
return 0;
}
+int
+OSC::sel_send_fail (string path, uint32_t id, float val, lo_address addr)
+{
+ OSCSurface *sur = get_surface(addr);
+
+ ostringstream os;
+ lo_message reply;
+ reply = lo_message_new ();
+ if (sur->feedback[2]) {
+ os << "/select/" << path << "/" << id;
+ } else {
+ os << "/select/" << path;
+ lo_message_add_int32 (reply, id);
+ }
+ string str_pth = os.str();
+ lo_message_add_float (reply, (float) val);
+
+ lo_send_message (addr, str_pth.c_str(), reply);
+ lo_message_free (reply);
+
+ return 0;
+}
+
XMLNode&
OSC::get_state ()
{