summaryrefslogtreecommitdiff
path: root/libs/surfaces/control_protocol
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2006-05-23 19:54:52 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2006-05-23 19:54:52 +0000
commit2fba6d0925307abd11be9d8f7a8d2722a2b6ccbd (patch)
tree485eed909963636b010d5f1e24527a6a4b377a42 /libs/surfaces/control_protocol
parenta222c19737fa2d3fce3971350c1a18906635e29a (diff)
breakout control protocol code into LGPL library; fix panner buttons even more than nick did, plus some other bits and pieces
git-svn-id: svn://localhost/trunk/ardour2@522 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/surfaces/control_protocol')
-rw-r--r--libs/surfaces/control_protocol/SConscript54
-rw-r--r--libs/surfaces/control_protocol/basic_ui.cc273
-rw-r--r--libs/surfaces/control_protocol/basic_ui.h98
-rw-r--r--libs/surfaces/control_protocol/control_protocol.cc333
-rw-r--r--libs/surfaces/control_protocol/control_protocol.h121
5 files changed, 879 insertions, 0 deletions
diff --git a/libs/surfaces/control_protocol/SConscript b/libs/surfaces/control_protocol/SConscript
new file mode 100644
index 0000000000..e3927fa7ac
--- /dev/null
+++ b/libs/surfaces/control_protocol/SConscript
@@ -0,0 +1,54 @@
+# -*- python -*-
+
+import os
+import os.path
+import glob
+
+Import('env final_prefix install_prefix final_config_prefix libraries i18n')
+
+cp = env.Copy()
+
+#
+# this defines the version number of libardour_cp
+#
+
+domain = 'ardour_cp'
+
+cp.Append(DOMAIN = domain, MAJOR = 1, MINOR = 0, MICRO = 0)
+cp.Append(CXXFLAGS = "-DPACKAGE=\\\"" + domain + "\\\"")
+cp.Append(CXXFLAGS="-DLIBSIGC_DISABLE_DEPRECATED")
+cp.Append(PACKAGE = domain)
+cp.Append(POTFILE = domain + '.pot')
+
+cp_files=Split("""
+basic_ui.cc
+control_protocol.cc
+""")
+
+cp.Append(CCFLAGS="-D_REENTRANT -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE")
+cp.Append(CXXFLAGS="-DDATA_DIR=\\\""+final_prefix+"/share\\\"")
+cp.Append(CXXFLAGS="-DCONFIG_DIR=\\\""+final_config_prefix+"\\\"")
+cp.Append(CXXFLAGS="-DLOCALEDIR=\\\""+final_prefix+"/share/locale\\\"")
+
+cp.Merge ([
+ libraries['ardour'],
+ libraries['sigc2'],
+ libraries['pbd3'],
+ libraries['midi++2'],
+ libraries['xml'],
+ libraries['usb']
+ ])
+
+libardour_cp = cp.SharedLibrary('ardour_cp', cp_files)
+
+Default(libardour_cp)
+
+if env['NLS']:
+ i18n (cp, cp_files, env)
+
+env.Alias('install', env.Install(os.path.join(install_prefix, 'lib/ardour2/surfaces'), libardour_cp))
+
+env.Alias('tarball', env.Distribute (env['DISTTREE'],
+ [ 'SConscript', 'i18n.h', 'gettext.h' ] +
+ cp_files +
+ glob.glob('po/*.po') + glob.glob('*.h')))
diff --git a/libs/surfaces/control_protocol/basic_ui.cc b/libs/surfaces/control_protocol/basic_ui.cc
new file mode 100644
index 0000000000..4519eb2781
--- /dev/null
+++ b/libs/surfaces/control_protocol/basic_ui.cc
@@ -0,0 +1,273 @@
+/*
+ Copyright (C) 2006 Paul Davis
+
+ This program is free software; you can redistribute it
+ and/or modify it under the terms of the GNU Lesser
+ General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <ardour/session.h>
+#include <ardour/location.h>
+
+#include "basic_ui.h"
+#include "i18n.h"
+
+using namespace ARDOUR;
+
+BasicUI::BasicUI (Session& s)
+ : session (&s)
+{
+}
+
+BasicUI::BasicUI ()
+ : session (0)
+{
+}
+
+BasicUI::~BasicUI ()
+{
+
+}
+
+void
+BasicUI::loop_toggle ()
+{
+ if (session->get_auto_loop()) {
+ session->request_auto_loop (false);
+ } else {
+ session->request_auto_loop (true);
+ if (!session->transport_rolling()) {
+ session->request_transport_speed (1.0);
+ }
+ }
+}
+
+void
+BasicUI::goto_start ()
+{
+ session->goto_start ();
+}
+
+void
+BasicUI::goto_end ()
+{
+ session->goto_end ();
+}
+
+void
+BasicUI::add_marker ()
+{
+ jack_nframes_t when = session->audible_frame();
+ session->locations()->add (new Location (when, when, _("unnamed"), Location::IsMark));
+}
+
+void
+BasicUI::rewind ()
+{
+ session->request_transport_speed (-2.0f);
+}
+
+void
+BasicUI::ffwd ()
+{
+ session->request_transport_speed (2.0f);
+}
+
+void
+BasicUI::transport_stop ()
+{
+ session->request_transport_speed (0.0);
+}
+
+void
+BasicUI::transport_play (bool from_last_start)
+{
+ bool rolling = session->transport_rolling ();
+
+ if (session->get_auto_loop()) {
+ session->request_auto_loop (false);
+ }
+
+ if (session->get_play_range ()) {
+ session->request_play_range (false);
+ }
+
+ if (from_last_start && rolling) {
+ session->request_locate (session->last_transport_start(), true);
+
+ }
+
+ session->request_transport_speed (1.0f);
+}
+
+void
+BasicUI::rec_enable_toggle ()
+{
+ switch (session->record_status()) {
+ case Session::Disabled:
+ if (session->ntracks() == 0) {
+ // string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
+ // MessageDialog msg (*editor, txt);
+ // msg.run ();
+ return;
+ }
+ session->maybe_enable_record ();
+ break;
+ case Session::Recording:
+ case Session::Enabled:
+ session->disable_record (true);
+ }
+}
+
+void
+BasicUI::save_state ()
+{
+ session->save_state ("");
+}
+
+void
+BasicUI::prev_marker ()
+{
+ Location *location = session->locations()->first_location_before (session->transport_frame());
+
+ if (location) {
+ session->request_locate (location->start(), session->transport_rolling());
+ } else {
+ session->goto_start ();
+ }
+}
+
+void
+BasicUI::next_marker ()
+{
+ Location *location = session->locations()->first_location_after (session->transport_frame());
+
+ if (location) {
+ session->request_locate (location->start(), session->transport_rolling());
+ } else {
+ session->request_locate (session->current_end_frame());
+ }
+}
+
+void
+BasicUI::set_transport_speed (float speed)
+{
+ session->request_transport_speed (speed);
+}
+
+float
+BasicUI::get_transport_speed ()
+{
+ return session->transport_speed ();
+}
+
+void
+BasicUI::undo ()
+{
+ session->undo (1);
+}
+
+void
+BasicUI::redo ()
+{
+ session->redo (1);
+}
+
+void
+BasicUI::toggle_all_rec_enables ()
+{
+ if (session->get_record_enabled()) {
+ session->record_disenable_all ();
+ } else {
+ session->record_enable_all ();
+ }
+}
+
+void
+BasicUI::toggle_punch_in ()
+{
+ session->set_punch_in (!session->get_punch_in());
+}
+
+void
+BasicUI::toggle_punch_out ()
+{
+ session->set_punch_out (!session->get_punch_out());
+}
+
+bool
+BasicUI::get_record_enabled ()
+{
+ return session->get_record_enabled();
+}
+
+void
+BasicUI::set_record_enable (bool yn)
+{
+ if (yn) {
+ session->maybe_enable_record ();
+ } else {
+ session->disable_record (false, true);
+ }
+}
+
+jack_nframes_t
+BasicUI::transport_frame ()
+{
+ return session->transport_frame();
+}
+
+void
+BasicUI::locate (jack_nframes_t where, bool roll_after_locate)
+{
+ session->request_locate (where, roll_after_locate);
+}
+
+bool
+BasicUI::locating ()
+{
+ return session->locate_pending();
+}
+
+bool
+BasicUI::locked ()
+{
+ return session->transport_locked ();
+}
+
+jack_nframes_t
+BasicUI::smpte_frames_per_hour ()
+{
+ return session->smpte_frames_per_hour ();
+}
+
+void
+BasicUI::smpte_time (jack_nframes_t where, SMPTE_t& smpte)
+{
+ session->smpte_time (where, *((SMPTE_Time *) &smpte));
+}
+
+void
+BasicUI::smpte_to_sample (SMPTE_t& smpte, jack_nframes_t& sample, bool use_offset, bool use_subframes) const
+{
+ session->smpte_to_sample (*((SMPTE_Time*)&smpte), sample, use_offset, use_subframes);
+}
+
+void
+BasicUI::sample_to_smpte (jack_nframes_t sample, SMPTE_t& smpte, bool use_offset, bool use_subframes) const
+{
+ session->sample_to_smpte (sample, *((SMPTE_Time*)&smpte), use_offset, use_subframes);
+}
diff --git a/libs/surfaces/control_protocol/basic_ui.h b/libs/surfaces/control_protocol/basic_ui.h
new file mode 100644
index 0000000000..2db19685b1
--- /dev/null
+++ b/libs/surfaces/control_protocol/basic_ui.h
@@ -0,0 +1,98 @@
+/*
+ Copyright (C) 2006 Paul Davis
+
+ This program is free software; you can redistribute it
+ and/or modify it under the terms of the GNU Lesser
+ General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_basic_ui_h__
+#define __ardour_basic_ui_h__
+
+#include <jack/types.h>
+
+namespace ARDOUR {
+ class Session;
+}
+
+class BasicUI {
+ public:
+ BasicUI (ARDOUR::Session&);
+ virtual ~BasicUI ();
+
+ void add_marker ();
+
+ /* transport control */
+
+ void loop_toggle ();
+ void goto_start ();
+ void goto_end ();
+ void rewind ();
+ void ffwd ();
+ void transport_stop ();
+ void transport_play (bool jump_back = true);
+ void set_transport_speed (float speed);
+ float get_transport_speed ();
+
+ jack_nframes_t transport_frame ();
+ void locate (jack_nframes_t frame, bool play = false);
+ bool locating ();
+ bool locked ();
+
+ void save_state ();
+ void prev_marker ();
+ void next_marker ();
+ void undo ();
+ void redo ();
+ void toggle_punch_in ();
+ void toggle_punch_out ();
+
+ void set_record_enable (bool yn);
+ bool get_record_enabled ();
+
+ void rec_enable_toggle ();
+ void toggle_all_rec_enables ();
+
+ jack_nframes_t smpte_frames_per_hour ();
+
+ struct SMPTE_t {
+ bool negative;
+ uint32_t hours;
+ uint32_t minutes;
+ uint32_t seconds;
+ uint32_t frames;
+ uint32_t subframes; // mostly not used
+
+ SMPTE_t () {
+ negative = false;
+ hours = 0;
+ minutes = 0;
+ seconds = 0;
+ frames = 0;
+ subframes = 0;
+ }
+ };
+
+ void smpte_time (jack_nframes_t where, SMPTE_t&);
+ void smpte_to_sample (SMPTE_t& smpte, jack_nframes_t& sample, bool use_offset, bool use_subframes) const;
+ void sample_to_smpte (jack_nframes_t sample, SMPTE_t& smpte, bool use_offset, bool use_subframes) const;
+
+ protected:
+ BasicUI ();
+ ARDOUR::Session* session;
+};
+
+#endif /* __ardour_basic_ui_h__ */
diff --git a/libs/surfaces/control_protocol/control_protocol.cc b/libs/surfaces/control_protocol/control_protocol.cc
new file mode 100644
index 0000000000..6407c64385
--- /dev/null
+++ b/libs/surfaces/control_protocol/control_protocol.cc
@@ -0,0 +1,333 @@
+/*
+ Copyright (C) 2006 Paul Davis
+
+ This program is free software; you can redistribute it
+ and/or modify it under the terms of the GNU Lesser
+ General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <ardour/session.h>
+#include <ardour/route.h>
+#include <ardour/audio_track.h>
+
+#include "control_protocol.h"
+
+using namespace ARDOUR;
+using namespace std;
+
+sigc::signal<void> ControlProtocol::ZoomToSession;
+sigc::signal<void> ControlProtocol::ZoomOut;
+sigc::signal<void> ControlProtocol::ZoomIn;
+sigc::signal<void> ControlProtocol::Enter;
+sigc::signal<void,float> ControlProtocol::ScrollTimeline;
+
+ControlProtocol::ControlProtocol (Session& s, string str)
+ : BasicUI (s),
+ _name (str)
+{
+ _active = false;
+}
+
+ControlProtocol::~ControlProtocol ()
+{
+}
+
+void
+ControlProtocol::next_track (uint32_t initial_id)
+{
+ uint32_t limit = session->nroutes();
+ Route* cr = route_table[0];
+ uint32_t id;
+
+ if (cr) {
+ id = cr->remote_control_id ();
+ } else {
+ id = 0;
+ }
+
+ if (id == limit) {
+ id = 0;
+ } else {
+ id++;
+ }
+
+ while (id < limit) {
+ if ((cr = session->route_by_remote_id (id)) != 0) {
+ break;
+ }
+ id++;
+ }
+
+ if (id == limit) {
+ id = 0;
+ while (id != initial_id) {
+ if ((cr = session->route_by_remote_id (id)) != 0) {
+ break;
+ }
+ id++;
+ }
+ }
+
+ route_table[0] = cr;
+}
+
+void
+ControlProtocol::prev_track (uint32_t initial_id)
+{
+ uint32_t limit = session->nroutes() - 1;
+ Route* cr = route_table[0];
+ uint32_t id;
+
+ if (cr) {
+ id = cr->remote_control_id ();
+ } else {
+ id = 0;
+ }
+
+ if (id == 0) {
+ id = session->nroutes() - 1;
+ } else {
+ id--;
+ }
+
+ while (id >= 0) {
+ if ((cr = session->route_by_remote_id (id)) != 0) {
+ break;
+ }
+ id--;
+ }
+
+ if (id < 0) {
+ id = limit;
+ while (id > initial_id) {
+ if ((cr = session->route_by_remote_id (id)) != 0) {
+ break;
+ }
+ id--;
+ }
+ }
+
+ route_table[0] = cr;
+}
+
+
+void
+ControlProtocol::set_route_table_size (uint32_t size)
+{
+ while (route_table.size() < size) {
+ route_table.push_back (0);
+ }
+}
+
+void
+ControlProtocol::set_route_table (uint32_t table_index, ARDOUR::Route*)
+{
+}
+
+bool
+ControlProtocol::set_route_table (uint32_t table_index, uint32_t remote_control_id)
+{
+ if (table_index >= route_table.size()) {
+ return false;
+ }
+
+ Route* r = session->route_by_remote_id (remote_control_id);
+
+ if (!r) {
+ return false;
+ }
+
+ route_table[table_index] = r;
+
+ return true;
+}
+
+void
+ControlProtocol::route_set_rec_enable (uint32_t table_index, bool yn)
+{
+ if (table_index > route_table.size()) {
+ return;
+ }
+
+ Route* r = route_table[table_index];
+
+ AudioTrack* at = dynamic_cast<AudioTrack*>(r);
+
+ if (at) {
+ at->set_record_enable (yn, this);
+ }
+}
+
+bool
+ControlProtocol::route_get_rec_enable (uint32_t table_index)
+{
+ if (table_index > route_table.size()) {
+ return false;
+ }
+
+ Route* r = route_table[table_index];
+
+ AudioTrack* at = dynamic_cast<AudioTrack*>(r);
+
+ if (at) {
+ return at->record_enabled ();
+ }
+
+ return false;
+}
+
+
+float
+ControlProtocol::route_get_gain (uint32_t table_index)
+{
+ if (table_index > route_table.size()) {
+ return 0.0f;
+ }
+
+ Route* r = route_table[table_index];
+
+ if (r == 0) {
+ return 0.0f;
+ }
+
+ return r->gain ();
+}
+
+void
+ControlProtocol::route_set_gain (uint32_t table_index, float gain)
+{
+ if (table_index > route_table.size()) {
+ return;
+ }
+
+ Route* r = route_table[table_index];
+
+ if (r != 0) {
+ r->set_gain (gain, this);
+ }
+}
+
+float
+ControlProtocol::route_get_effective_gain (uint32_t table_index)
+{
+ if (table_index > route_table.size()) {
+ return 0.0f;
+ }
+
+ Route* r = route_table[table_index];
+
+ if (r == 0) {
+ return 0.0f;
+ }
+
+ return r->effective_gain ();
+}
+
+
+float
+ControlProtocol::route_get_peak_input_power (uint32_t table_index, uint32_t which_input)
+{
+ if (table_index > route_table.size()) {
+ return 0.0f;
+ }
+
+ Route* r = route_table[table_index];
+
+ if (r == 0) {
+ return 0.0f;
+ }
+
+ return r->peak_input_power (which_input);
+}
+
+
+bool
+ControlProtocol::route_get_muted (uint32_t table_index)
+{
+ if (table_index > route_table.size()) {
+ return false;
+ }
+
+ Route* r = route_table[table_index];
+
+ if (r == 0) {
+ return false;
+ }
+
+ return r->muted ();
+}
+
+void
+ControlProtocol::route_set_muted (uint32_t table_index, bool yn)
+{
+ if (table_index > route_table.size()) {
+ return;
+ }
+
+ Route* r = route_table[table_index];
+
+ if (r != 0) {
+ r->set_mute (yn, this);
+ }
+}
+
+
+bool
+ControlProtocol::route_get_soloed (uint32_t table_index)
+{
+ if (table_index > route_table.size()) {
+ return false;
+ }
+
+ Route* r = route_table[table_index];
+
+ if (r == 0) {
+ return false;
+ }
+
+ return r->soloed ();
+}
+
+void
+ControlProtocol::route_set_soloed (uint32_t table_index, bool yn)
+{
+ if (table_index > route_table.size()) {
+ return;
+ }
+
+ Route* r = route_table[table_index];
+
+ if (r != 0) {
+ r->set_solo (yn, this);
+ }
+}
+
+string
+ControlProtocol:: route_get_name (uint32_t table_index)
+{
+ if (table_index > route_table.size()) {
+ return "";
+ }
+
+ Route* r = route_table[table_index];
+
+ if (r == 0) {
+ return "";
+ }
+
+ return r->name();
+}
+
diff --git a/libs/surfaces/control_protocol/control_protocol.h b/libs/surfaces/control_protocol/control_protocol.h
new file mode 100644
index 0000000000..720188c666
--- /dev/null
+++ b/libs/surfaces/control_protocol/control_protocol.h
@@ -0,0 +1,121 @@
+/*
+ Copyright (C) 2006 Paul Davis
+
+ This program is free software; you can redistribute it
+ and/or modify it under the terms of the GNU Lesser
+ General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef ardour_control_protocols_h
+#define ardour_control_protocols_h
+
+#include <string>
+#include <vector>
+#include <list>
+#include <sigc++/sigc++.h>
+
+#include "basic_ui.h"
+
+namespace ARDOUR {
+
+class Route;
+class Session;
+
+class ControlProtocol : public sigc::trackable, public BasicUI {
+ public:
+ ControlProtocol (Session&, std::string name);
+ virtual ~ControlProtocol();
+
+ std::string name() const { return _name; }
+
+ virtual int set_active (bool yn) = 0;
+ bool get_active() const { return _active; }
+
+ sigc::signal<void> ActiveChanged;
+
+ /* signals that a control protocol can emit and other (presumably graphical)
+ user interfaces can respond to
+ */
+
+ static sigc::signal<void> ZoomToSession;
+ static sigc::signal<void> ZoomIn;
+ static sigc::signal<void> ZoomOut;
+ static sigc::signal<void> Enter;
+ static sigc::signal<void,float> ScrollTimeline;
+
+ /* the model here is as follows:
+
+ we imagine most control surfaces being able to control
+ from 1 to N tracks at a time, with a session that may
+ contain 1 to M tracks, where M may be smaller, larger or
+ equal to N.
+
+ the control surface has a fixed set of physical controllers
+ which can potentially be mapped onto different tracks/busses
+ via some mechanism.
+
+ therefore, the control protocol object maintains
+ a table that reflects the current mapping between
+ the controls and route object.
+ */
+
+ void set_route_table_size (uint32_t size);
+ void set_route_table (uint32_t table_index, ARDOUR::Route*);
+ bool set_route_table (uint32_t table_index, uint32_t remote_control_id);
+
+ void route_set_rec_enable (uint32_t table_index, bool yn);
+ bool route_get_rec_enable (uint32_t table_index);
+
+ float route_get_gain (uint32_t table_index);
+ void route_set_gain (uint32_t table_index, float);
+ float route_get_effective_gain (uint32_t table_index);
+
+ float route_get_peak_input_power (uint32_t table_index, uint32_t which_input);
+
+ bool route_get_muted (uint32_t table_index);
+ void route_set_muted (uint32_t table_index, bool);
+
+ bool route_get_soloed (uint32_t table_index);
+ void route_set_soloed (uint32_t table_index, bool);
+
+ std::string route_get_name (uint32_t table_index);
+
+ protected:
+ std::vector<ARDOUR::Route*> route_table;
+ std::string _name;
+ bool _active;
+
+ void next_track (uint32_t initial_id);
+ void prev_track (uint32_t initial_id);
+};
+
+extern "C" {
+ struct ControlProtocolDescriptor {
+ const char* name; /* descriptive */
+ const char* id; /* unique and version-specific */
+ void* ptr; /* protocol can store a value here */
+ void* module; /* not for public access */
+ int mandatory; /* if non-zero, always load and do not make optional */
+ bool (*probe)(ControlProtocolDescriptor*);
+ ControlProtocol* (*initialize)(ControlProtocolDescriptor*,Session*);
+ void (*destroy)(ControlProtocolDescriptor*,ControlProtocol*);
+
+ };
+}
+
+}
+
+#endif // ardour_control_protocols_h