summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2006-04-10 03:54:00 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2006-04-10 03:54:00 +0000
commita157537898eccf08009281633b19970515366a78 (patch)
treecd6f7bb1e7f9bddba1b5cc4ce6e10c60cb2b2a46 /libs
parent7e8a98224578e03e17fbf5e656241ff5ef1a0bc1 (diff)
a) moved metering and meter falloff code into libardour
b) added initial "big meter" mode for tranzport c) fixed some lock issues in ARDOUR::IO objects d) generic_midi control surface module now compiles and loads git-svn-id: svn://localhost/trunk/ardour2@450 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
-rw-r--r--libs/ardour/ardour/audioengine.h8
-rw-r--r--libs/ardour/ardour/control_protocol.h8
-rw-r--r--libs/ardour/ardour/control_protocol_manager.h18
-rw-r--r--libs/ardour/ardour/io.h15
-rw-r--r--libs/ardour/audioengine.cc122
-rw-r--r--libs/ardour/control_protocol.cc9
-rw-r--r--libs/ardour/control_protocol_manager.cc129
-rw-r--r--libs/ardour/globals.cc2
-rw-r--r--libs/ardour/io.cc47
-rw-r--r--libs/ardour/route.cc8
-rw-r--r--libs/ardour/session_butler.cc1
-rw-r--r--libs/ardour/session_state.cc2
-rw-r--r--libs/gtkmm2ext/utils.cc4
-rw-r--r--libs/surfaces/generic_midi/SConscript9
-rw-r--r--libs/surfaces/generic_midi/generic_midi_control_protocol.cc26
-rw-r--r--libs/surfaces/generic_midi/generic_midi_control_protocol.h4
-rw-r--r--libs/surfaces/generic_midi/interface.cc10
-rw-r--r--libs/surfaces/tranzport/interface.cc12
-rw-r--r--libs/surfaces/tranzport/tranzport_control_protocol.cc275
-rw-r--r--libs/surfaces/tranzport/tranzport_control_protocol.h15
20 files changed, 452 insertions, 272 deletions
diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h
index 9fe3ce5424..36dbbd1dbe 100644
--- a/libs/ardour/ardour/audioengine.h
+++ b/libs/ardour/ardour/audioengine.h
@@ -202,6 +202,8 @@ class AudioEngine : public sigc::trackable
sigc::slot<int,jack_nframes_t> freewheel_action;
bool reconnect_on_halt;
int _usecs_per_cycle;
+ jack_nframes_t last_meter_point;
+ jack_nframes_t meter_interval;
typedef std::set<Port*> Ports;
Ports ports;
@@ -232,9 +234,13 @@ class AudioEngine : public sigc::trackable
int jack_sample_rate_callback (jack_nframes_t);
static void halted (void *);
- static void meter (Port *port, jack_nframes_t nframes);
int connect_to_jack (std::string client_name);
+
+ static void* _meter_thread (void* arg);
+ void* meter_thread ();
+ pthread_t meter_thread_id;
+ void maybe_start_metering_thread ();
};
}; /* namespace ARDOUR */
diff --git a/libs/ardour/ardour/control_protocol.h b/libs/ardour/ardour/control_protocol.h
index c2ab8736b7..64658fc199 100644
--- a/libs/ardour/ardour/control_protocol.h
+++ b/libs/ardour/ardour/control_protocol.h
@@ -30,7 +30,6 @@ class ControlProtocol : public sigc::trackable {
void set_active (bool yn);
bool get_active() const { return active_thread > 0; }
-
bool send() const { return _send != 0; }
bool send_route_feedback () const { return _send & SendRoute; }
bool send_global_feedback () const { return _send & SendGlobal; }
@@ -77,9 +76,10 @@ class ControlProtocol : public sigc::trackable {
extern "C" {
struct ControlProtocolDescriptor {
- const char* name;
- void* ptr;
- void* module;
+ 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 */
ControlProtocol* (*initialize)(ControlProtocolDescriptor*,Session*);
void (*destroy)(ControlProtocolDescriptor*,ControlProtocol*);
diff --git a/libs/ardour/ardour/control_protocol_manager.h b/libs/ardour/ardour/control_protocol_manager.h
index f0b7846978..b06c3024b6 100644
--- a/libs/ardour/ardour/control_protocol_manager.h
+++ b/libs/ardour/ardour/control_protocol_manager.h
@@ -4,12 +4,15 @@
#include <string>
#include <list>
+#include <sigc++/sigc++.h>
+
#include <pbd/lockmonitor.h>
namespace ARDOUR {
class ControlProtocol;
class ControlProtocolDescriptor;
+class Session;
struct ControlProtocolInfo {
ControlProtocolDescriptor* descriptor;
@@ -18,7 +21,7 @@ struct ControlProtocolInfo {
std::string path;
};
-class ControlProtocolManager
+ class ControlProtocolManager : public sigc::trackable
{
public:
ControlProtocolManager ();
@@ -26,19 +29,24 @@ class ControlProtocolManager
static ControlProtocolManager& instance() { return *_instance; }
+ void set_session (Session&);
void discover_control_protocols (std::string search_path);
- void startup (Session&);
+ void foreach_known_protocol (sigc::slot<void,const ControlProtocolInfo*>);
+
+ ControlProtocol* instantiate (ControlProtocolInfo&);
+ int teardown (ControlProtocolInfo&);
- ControlProtocol* instantiate (Session&, std::string protocol_name);
- int teardown (std::string protocol_name);
+ std::list<ControlProtocolInfo*> control_protocol_info;
private:
static ControlProtocolManager* _instance;
+ Session* _session;
PBD::Lock protocols_lock;
- std::list<ControlProtocolInfo*> control_protocol_info;
std::list<ControlProtocol*> control_protocols;
+ void drop_session ();
+
int control_protocol_discover (std::string path);
ControlProtocolDescriptor* get_descriptor (std::string path);
};
diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h
index c67473dcc0..8321e9afda 100644
--- a/libs/ardour/ardour/io.h
+++ b/libs/ardour/ardour/io.h
@@ -198,19 +198,14 @@ class IO : public Stateful, public ARDOUR::StateManager
/* Peak metering */
float peak_input_power (uint32_t n) {
- if (n < std::max(_ninputs, _noutputs)) {
- float x = _stored_peak_power[n];
- if(x > 0.0) {
- return 20 * fast_log10(x);
- } else {
- return minus_infinity();
- }
+ if (n < std::max (_ninputs, _noutputs)) {
+ return _visible_peak_power[n];
} else {
return minus_infinity();
}
}
- static sigc::signal<void> GrabPeakPower;
+ static sigc::signal<void> Meter;
/* automation */
@@ -278,7 +273,7 @@ class IO : public Stateful, public ARDOUR::StateManager
vector<Port*> _outputs;
vector<Port*> _inputs;
vector<float> _peak_power;
- vector<float> _stored_peak_power;
+ vector<float> _visible_peak_power;
string _name;
Connection* _input_connection;
Connection* _output_connection;
@@ -394,7 +389,7 @@ class IO : public Stateful, public ARDOUR::StateManager
int make_connections (const XMLNode&);
void setup_peak_meters ();
- void grab_peak_power ();
+ void meter ();
bool ensure_inputs_locked (uint32_t, bool clear, void *src);
bool ensure_outputs_locked (uint32_t, bool clear, void *src);
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index c64b4d6429..9d736f765e 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -21,6 +21,7 @@
#include <unistd.h>
#include <cerrno>
#include <vector>
+
#include <pbd/pthread_utils.h>
#include <ardour/audioengine.h>
@@ -59,6 +60,9 @@ AudioEngine::AudioEngine (string client_name)
_buffer_size = 0;
_freewheeling = false;
_freewheel_thread_registered = false;
+ last_meter_point = 0;
+ meter_interval = 0;
+ meter_thread_id = (pthread_t) 0;
if (connect_to_jack (client_name)) {
throw NoBackendAvailable ();
@@ -71,6 +75,10 @@ AudioEngine::~AudioEngine ()
if (_running) {
jack_client_close (_jack);
}
+
+ if (meter_thread_id != (pthread_t) 0) {
+ pthread_cancel (meter_thread_id);
+ }
}
void
@@ -216,59 +224,6 @@ AudioEngine::_freewheel_callback (int onoff, void *arg)
static_cast<AudioEngine*>(arg)->_freewheeling = onoff;
}
-void
-AudioEngine::meter (Port *port, jack_nframes_t nframes)
-{
- double peak;
- uint32_t overlen;
- jack_default_audio_sample_t *buf;
-
- buf = port->get_buffer (nframes);
- peak = port->_peak;
- overlen = port->overlen;
-
- {
- for (jack_nframes_t n = 0; n < nframes; ++n) {
-
- /* 1) peak metering */
-
- peak = f_max (peak, buf[n]);
-
- /* 2) clip/over metering */
-
- if (buf[n] >= 1.0) {
- overlen++;
- } else if (overlen) {
- if (overlen > Port::short_over_length) {
- port->_short_overs++;
- }
- if (overlen > Port::long_over_length) {
- port->_long_overs++;
- }
- overlen = 0;
- }
- }
- }
-
- /* post-loop check on the final status of overlen */
-
- if (overlen > Port::short_over_length) {
- port->_short_overs++;
- }
- if (overlen > Port::long_over_length) {
- port->_short_overs++;
- }
-
- if (peak > 0.0) {
- port->_peak_db= 20 * fast_log10 (peak);
- } else {
- port->_peak_db = minus_infinity();
- }
-
- port->_peak = peak;
- port->overlen = overlen;
-}
-
int
AudioEngine::process_callback (jack_nframes_t nframes)
{
@@ -304,14 +259,6 @@ AudioEngine::process_callback (jack_nframes_t nframes)
return 0;
}
- /* do input peak metering */
-
- for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) {
- if ((*i)->metering) {
- meter ((*i), nframes);
- }
- }
-
session->process (nframes);
if (!_running) {
@@ -323,6 +270,13 @@ AudioEngine::process_callback (jack_nframes_t nframes)
return 0;
}
+ /* manage meters */
+
+ if ((meter_interval > _buffer_size) && (last_meter_point + meter_interval < next_processed_frames)) {
+ IO::Meter ();
+ last_meter_point = next_processed_frames;
+ }
+
if (last_monitor_check + monitor_check_interval < next_processed_frames) {
for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) {
@@ -360,6 +314,11 @@ AudioEngine::jack_sample_rate_callback (jack_nframes_t nframes)
monitor_check_interval = nframes / 10;
last_monitor_check = 0;
+
+ meter_interval = nframes / 100;
+ last_meter_point = 0;
+
+ maybe_start_metering_thread ();
if (session) {
session->set_frame_rate (nframes);
@@ -391,6 +350,47 @@ AudioEngine::jack_bufsize_callback (jack_nframes_t nframes)
session->set_block_size (_buffer_size);
}
+ maybe_start_metering_thread ();
+
+ return 0;
+}
+
+void
+AudioEngine::maybe_start_metering_thread ()
+{
+ if (meter_interval == 0) {
+ return;
+ }
+
+ if (_buffer_size == 0) {
+ return;
+ }
+
+ if (meter_interval < _buffer_size) {
+ if (meter_thread_id != (pthread_t) 0) {
+ pthread_cancel (meter_thread_id);
+ }
+ pthread_create (&meter_thread_id, 0, _meter_thread, this);
+ }
+}
+
+void*
+AudioEngine::_meter_thread (void *arg)
+{
+ return static_cast<AudioEngine*>(arg)->meter_thread ();
+}
+
+void*
+AudioEngine::meter_thread ()
+{
+ PBD::ThreadCreated (pthread_self(), "Metering");
+
+ while (true) {
+ usleep (10000); /* 1/100th sec interval */
+ pthread_testcancel();
+ IO::Meter ();
+ }
+
return 0;
}
diff --git a/libs/ardour/control_protocol.cc b/libs/ardour/control_protocol.cc
index d2a84967d2..2a28921d53 100644
--- a/libs/ardour/control_protocol.cc
+++ b/libs/ardour/control_protocol.cc
@@ -240,11 +240,10 @@ ControlProtocol::thread_work ()
if (send()) {
- // list<Route*> routes = session.get_routes(); /* copies the routes */
-
- // if (send_route_feedback ()) {
- //send_route_feedback (routes);
- // }
+ if (send_route_feedback ()) {
+ list<Route*> routes = session.get_routes(); /* copies the routes */
+ send_route_feedback (routes);
+ }
send_global_feedback ();
}
diff --git a/libs/ardour/control_protocol_manager.cc b/libs/ardour/control_protocol_manager.cc
index b89b83a29f..893124f0f5 100644
--- a/libs/ardour/control_protocol_manager.cc
+++ b/libs/ardour/control_protocol_manager.cc
@@ -4,6 +4,7 @@
#include <pbd/error.h>
#include <pbd/pathscanner.h>
+#include <ardour/session.h>
#include <ardour/control_protocol.h>
#include <ardour/control_protocol_manager.h>
@@ -20,6 +21,8 @@ ControlProtocolManager::ControlProtocolManager ()
if (_instance == 0) {
_instance = this;
}
+
+ _session = 0;
}
ControlProtocolManager::~ControlProtocolManager()
@@ -35,97 +38,75 @@ ControlProtocolManager::~ControlProtocolManager()
}
void
-ControlProtocolManager::startup (Session& s)
+ControlProtocolManager::set_session (Session& s)
{
- list<ControlProtocolInfo *>::iterator i;
-
- for (i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
+ _session = &s;
+ _session->going_away.connect (mem_fun (*this, &ControlProtocolManager::drop_session));
+}
- ControlProtocolInfo* cpi = (*i);
+void
+ControlProtocolManager::drop_session ()
+{
+ _session = 0;
- if (cpi->name == "Tranzport") {
-
- cpi->descriptor = get_descriptor ((*i)->path);
-
- if (cpi->descriptor == 0) {
- error << string_compose (_("control protocol name \"%1\" has no descriptor"), cpi->name) << endmsg;
- continue;
- }
-
- if ((cpi->protocol = cpi->descriptor->initialize (cpi->descriptor, &s)) == 0) {
- error << string_compose (_("control protocol name \"%1\" could not be initialized"), cpi->name) << endmsg;
- continue;
- }
-
- {
- LockMonitor lm (protocols_lock, __LINE__, __FILE__);
- control_protocols.push_back (cpi->protocol);
- }
-
- cpi->protocol->init ();
- cpi->protocol->set_active (true);
+ {
+ LockMonitor lm (protocols_lock, __LINE__, __FILE__);
+ for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
+ delete *p;
}
+ control_protocols.clear ();
}
}
ControlProtocol*
-ControlProtocolManager::instantiate (Session& session, string name)
+ControlProtocolManager::instantiate (ControlProtocolInfo& cpi)
{
- list<ControlProtocolInfo *>::iterator i;
-
- for (i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
- if ((*i)->name == name) {
- break;
- }
- }
-
- if (i == control_protocol_info.end()) {
- error << string_compose (_("control protocol name \"%1\" is unknown"), name) << endmsg;
+ if (_session == 0) {
return 0;
}
- ControlProtocolInfo* cpi = (*i);
-
- cpi->descriptor = get_descriptor ((*i)->path);
+ cpi.descriptor = get_descriptor (cpi.path);
- if (cpi->descriptor == 0) {
- error << string_compose (_("control protocol name \"%1\" has no descriptor"), name) << endmsg;
+ if (cpi.descriptor == 0) {
+ error << string_compose (_("control protocol name \"%1\" has no descriptor"), cpi.name) << endmsg;
return 0;
}
- if ((cpi->protocol = cpi->descriptor->initialize (cpi->descriptor, &session)) == 0) {
- error << string_compose (_("control protocol name \"%1\" could not be initialized"), name) << endmsg;
+ if ((cpi.protocol = cpi.descriptor->initialize (cpi.descriptor, _session)) == 0) {
+ error << string_compose (_("control protocol name \"%1\" could not be initialized"), cpi.name) << endmsg;
return 0;
}
LockMonitor lm (protocols_lock, __LINE__, __FILE__);
- control_protocols.push_back (cpi->protocol);
- return cpi->protocol;
+ control_protocols.push_back (cpi.protocol);
+
+ return cpi.protocol;
}
int
-ControlProtocolManager::teardown (string name)
+ControlProtocolManager::teardown (ControlProtocolInfo& cpi)
{
- for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
- ControlProtocolInfo* cpi = *i;
-
- if (cpi->name == name && cpi->descriptor && cpi->protocol) {
- cpi->descriptor->destroy (cpi->descriptor, cpi->protocol);
-
- {
- LockMonitor lm (protocols_lock, __LINE__, __FILE__);
- list<ControlProtocol*>::iterator p = find (control_protocols.begin(), control_protocols.end(), cpi->protocol);
- if (p != control_protocols.end()) {
- control_protocols.erase (p);
- }
- }
-
- cpi->protocol = 0;
- return 0;
- }
+ if (!cpi.protocol) {
+ return 0;
+ }
+
+ if (!cpi.descriptor) {
+ return 0;
}
- return -1;
+ cpi.descriptor->destroy (cpi.descriptor, cpi.protocol);
+
+ {
+ LockMonitor lm (protocols_lock, __LINE__, __FILE__);
+ list<ControlProtocol*>::iterator p = find (control_protocols.begin(), control_protocols.end(), cpi.protocol);
+ if (p != control_protocols.end()) {
+ control_protocols.erase (p);
+ }
+ }
+
+ cpi.protocol = 0;
+ dlclose (cpi.descriptor->module);
+ return 0;
}
static bool protocol_filter (const string& str, void *arg)
@@ -141,12 +122,9 @@ ControlProtocolManager::discover_control_protocols (string path)
vector<string *> *found;
PathScanner scanner;
- cerr << "CP Manager looking for surfaces\n";
-
found = scanner (path, protocol_filter, 0, false, true);
for (vector<string*>::iterator i = found->begin(); i != found->end(); ++i) {
- cerr << "CP Manager looking at " << **i << endl;
control_protocol_discover (**i);
delete *i;
}
@@ -166,15 +144,12 @@ ControlProtocolManager::control_protocol_discover (string path)
info->descriptor = descriptor;
info->name = descriptor->name;
info->path = path;
-
- control_protocol_info.push_back (info);
+ info->protocol = 0;
- cerr << "Found \"" << info->name << "\"\n";
+ control_protocol_info.push_back (info);
dlclose (descriptor->module);
- } else {
- cerr << "no descriptor\n";
}
return 0;
@@ -212,3 +187,11 @@ ControlProtocolManager::get_descriptor (string path)
return descriptor;
}
+
+void
+ControlProtocolManager::foreach_known_protocol (sigc::slot<void,const ControlProtocolInfo*> method)
+{
+ for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
+ method (*i);
+ }
+}
diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc
index 6aa53f5219..5fca7f07eb 100644
--- a/libs/ardour/globals.cc
+++ b/libs/ardour/globals.cc
@@ -353,7 +353,7 @@ find_file (string name, string dir, string subdir = "")
path = *i;
path += "/" + name;
if (access (path.c_str(), R_OK) == 0) {
- cerr << "Using file " << path << " found in ARDOUR_PATH." << endl;
+ // cerr << "Using file " << path << " found in ARDOUR_PATH." << endl;
return path;
}
}
diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc
index 916e77b492..b6ea1eee6e 100644
--- a/libs/ardour/io.cc
+++ b/libs/ardour/io.cc
@@ -63,7 +63,7 @@ const string IO::state_node_name = "IO";
bool IO::connecting_legal = false;
bool IO::ports_legal = false;
bool IO::panners_legal = false;
-sigc::signal<void> IO::GrabPeakPower;
+sigc::signal<void> IO::Meter;
sigc::signal<int> IO::ConnectingLegal;
sigc::signal<int> IO::PortsLegal;
sigc::signal<int> IO::PannersLegal;
@@ -127,7 +127,7 @@ IO::IO (Session& s, string name,
_gain_automation_state = Off;
_gain_automation_style = Absolute;
- GrabPeakPower.connect (mem_fun (*this, &IO::grab_peak_power));
+ Meter.connect (mem_fun (*this, &IO::meter));
}
IO::~IO ()
@@ -1171,11 +1171,11 @@ IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src)
_session.engine().disconnect (*i);
}
}
- }
-
- if (in_changed || out_changed) {
- setup_peak_meters ();
- reset_panner ();
+
+ if (in_changed || out_changed) {
+ setup_peak_meters ();
+ reset_panner ();
+ }
}
if (out_changed) {
@@ -1213,6 +1213,7 @@ IO::ensure_inputs (uint32_t n, bool clear, bool lockit, void* src)
if (lockit) {
LockMonitor em (_session.engine().process_lock(), __LINE__, __FILE__);
+ LockMonitor im (io_lock, __LINE__, __FILE__);
changed = ensure_inputs_locked (n, clear, src);
} else {
changed = ensure_inputs_locked (n, clear, src);
@@ -1314,6 +1315,7 @@ IO::ensure_outputs (uint32_t n, bool clear, bool lockit, void* src)
if (lockit) {
LockMonitor em (_session.engine().process_lock(), __LINE__, __FILE__);
+ LockMonitor im (io_lock, __LINE__, __FILE__);
changed = ensure_outputs_locked (n, clear, src);
} else {
changed = ensure_outputs_locked (n, clear, src);
@@ -2406,7 +2408,7 @@ IO::setup_peak_meters ()
while (_peak_power.size() < limit) {
_peak_power.push_back (0);
- _stored_peak_power.push_back (0);
+ _visible_peak_power.push_back (0);
}
}
@@ -2436,16 +2438,35 @@ IO::send_state_changed ()
}
void
-IO::grab_peak_power ()
+IO::meter ()
{
LockMonitor lm (io_lock, __LINE__, __FILE__);
-
uint32_t limit = max (_ninputs, _noutputs);
-
+
for (uint32_t n = 0; n < limit; ++n) {
- /* XXX should we use atomic exchange here ? */
- _stored_peak_power[n] = _peak_power[n];
+
+ /* XXX we should use atomic exchange here */
+
+ /* grab peak since last read */
+
+ float new_peak = _peak_power[n];
_peak_power[n] = 0;
+
+ /* compute new visible value using falloff */
+
+ if (new_peak > 0.0) {
+ new_peak = coefficient_to_dB (new_peak);
+ } else {
+ new_peak = minus_infinity();
+ }
+
+ if (_session.meter_falloff() == 0.0f || new_peak > _visible_peak_power[n]) {
+ _visible_peak_power[n] = new_peak;
+ } else {
+ // do falloff
+ new_peak = _visible_peak_power[n] - _session.meter_falloff();
+ _visible_peak_power[n] = max (new_peak, -200.0f);
+ }
}
}
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index d338cee277..2ce7f939b4 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -813,8 +813,8 @@ Route::add_redirect (Redirect *redirect, void *src, uint32_t* err_streams)
while (_peak_power.size() < potential_max_streams) {
_peak_power.push_back(0);
}
- while (_stored_peak_power.size() < potential_max_streams) {
- _stored_peak_power.push_back(0);
+ while (_visible_peak_power.size() < potential_max_streams) {
+ _visible_peak_power.push_back(0);
}
_redirects.push_back (redirect);
@@ -871,8 +871,8 @@ Route::add_redirects (const RedirectList& others, void *src, uint32_t* err_strea
while (_peak_power.size() < potential_max_streams) {
_peak_power.push_back(0);
}
- while (_stored_peak_power.size() < potential_max_streams) {
- _stored_peak_power.push_back(0);
+ while (_visible_peak_power.size() < potential_max_streams) {
+ _visible_peak_power.push_back(0);
}
_redirects.push_back (*i);
diff --git a/libs/ardour/session_butler.cc b/libs/ardour/session_butler.cc
index ec543f8fa1..dafc28385b 100644
--- a/libs/ardour/session_butler.cc
+++ b/libs/ardour/session_butler.cc
@@ -154,7 +154,6 @@ void *
Session::_butler_thread_work (void* arg)
{
PBD::ThreadCreated (pthread_self(), X_("Butler"));
-
return ((Session *) arg)->butler_thread_work ();
return 0;
}
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index a78a2bdfa7..6f1d20d17f 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -341,7 +341,7 @@ Session::second_stage_init (bool new_session)
deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0);
deliver_mmc (MIDI::MachineControl::cmdLocate, 0);
- ControlProtocolManager::instance().startup (*this);
+ ControlProtocolManager::instance().set_session (*this);
if (new_session) {
_end_location_is_free = true;
diff --git a/libs/gtkmm2ext/utils.cc b/libs/gtkmm2ext/utils.cc
index 401ed3e8ad..0a0737becd 100644
--- a/libs/gtkmm2ext/utils.cc
+++ b/libs/gtkmm2ext/utils.cc
@@ -18,6 +18,8 @@
$Id$
*/
+#include <map>
+
#include <gtk/gtkpaned.h>
#include <gtk/gtk.h>
@@ -41,7 +43,7 @@ Gtkmm2ext::set_size_request_to_display_given_text (Gtk::Widget &w, const gchar *
int width = 0;
w.ensure_style ();
- w.create_pango_layout(text)->get_pixel_size (width, height);
+ w.create_pango_layout (text)->get_pixel_size (width, height);
height += vpadding;
width += hpadding;
diff --git a/libs/surfaces/generic_midi/SConscript b/libs/surfaces/generic_midi/SConscript
index abede3f4d7..51e0ff88c8 100644
--- a/libs/surfaces/generic_midi/SConscript
+++ b/libs/surfaces/generic_midi/SConscript
@@ -29,12 +29,13 @@ genericmidi.Append(CXXFLAGS="-DDATA_DIR=\\\""+final_prefix+"/share\\\"")
genericmidi.Append(CXXFLAGS="-DCONFIG_DIR=\\\""+final_config_prefix+"\\\"")
genericmidi.Append(CXXFLAGS="-DLOCALEDIR=\\\""+final_prefix+"/share/locale\\\"")
+genericmidi.Append(CPPPATH=libraries['ardour'].get ('CPPPATH', []))
+genericmidi.Append(CPPPATH=libraries['sigc2'].get ('CPPPATH', []))
+genericmidi.Append(CPPPATH=libraries['pbd3'].get ('CPPPATH', []))
+genericmidi.Append(CPPPATH=libraries['midi++2'].get ('CPPPATH', []))
+
genericmidi.Merge ([
libraries['usb'],
- libraries['ardour'],
- libraries['sigc2'],
- libraries['pbd3'],
- libraries['midi++2'],
libraries['xml']
])
diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
index 4d64c6ce23..61a8b7974e 100644
--- a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
+++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
@@ -1,3 +1,5 @@
+#include <midi++/port.h>
+
#include <ardour/route.h>
#include <ardour/session.h>
@@ -10,13 +12,28 @@ using namespace ARDOUR;
GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
: ControlProtocol (s, _("GenericMIDI"))
{
- _port = 0;
+ _port = s.midi_port();
+ s.MIDI_PortChanged.connect (mem_fun (*this, &GenericMidiControlProtocol::port_change));
+
}
GenericMidiControlProtocol::~GenericMidiControlProtocol ()
{
}
+int
+GenericMidiControlProtocol::init ()
+{
+ /* start delivery/outbound thread */
+ return init_thread ();
+}
+
+void
+GenericMidiControlProtocol::port_change ()
+{
+ _port = session.midi_port ();
+}
+
void
GenericMidiControlProtocol::set_port (MIDI::Port* p)
{
@@ -29,20 +46,19 @@ GenericMidiControlProtocol::send_route_feedback (list<Route*>& routes)
if (_port != 0) {
const int32_t bufsize = 16 * 1024;
+ MIDI::byte buf[bufsize];
int32_t bsize = bufsize;
- MIDI::byte* buf = new MIDI::byte[bufsize];
MIDI::byte* end = buf;
for (list<Route*>::iterator r = routes.begin(); r != routes.end(); ++r) {
- end = (*r)->write_midi_feedback (end, bsize);
+ end = (*r)->write_midi_feedback (end, bsize);
}
if (end == buf) {
- delete [] buf;
return;
}
- session.deliver_midi (_port, buf, (int32_t) (end - buf));
+ _port->write (buf, (int32_t) (end - buf));
//cerr << "MIDI feedback: wrote " << (int32_t) (end - buf) << " to midi port\n";
}
}
diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.h b/libs/surfaces/generic_midi/generic_midi_control_protocol.h
index 75b514f016..54831b2982 100644
--- a/libs/surfaces/generic_midi/generic_midi_control_protocol.h
+++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.h
@@ -14,6 +14,8 @@ class GenericMidiControlProtocol : public ControlProtocol {
GenericMidiControlProtocol (Session&);
virtual ~GenericMidiControlProtocol();
+ int init ();
+
bool active() const;
void set_port (MIDI::Port*);
@@ -24,6 +26,8 @@ class GenericMidiControlProtocol : public ControlProtocol {
private:
void route_feedback (ARDOUR::Route&, bool);
MIDI::Port* _port;
+
+ void port_change ();
};
}
diff --git a/libs/surfaces/generic_midi/interface.cc b/libs/surfaces/generic_midi/interface.cc
index 8283b92e6f..500d745deb 100644
--- a/libs/surfaces/generic_midi/interface.cc
+++ b/libs/surfaces/generic_midi/interface.cc
@@ -7,7 +7,14 @@ using namespace ARDOUR;
ControlProtocol*
new_generic_midi_protocol (ControlProtocolDescriptor* descriptor, Session* s)
{
- return new GenericMidiControlProtocol (*s);
+ GenericMidiControlProtocol* gmcp = new GenericMidiControlProtocol (*s);
+
+ if (gmcp->init ()) {
+ delete gmcp;
+ return 0;
+ }
+
+ return gmcp;
}
void
@@ -18,6 +25,7 @@ delete_generic_midi_protocol (ControlProtocolDescriptor* descriptor, ControlProt
static ControlProtocolDescriptor generic_midi_descriptor = {
name : "Generic MIDI",
+ id : "uri://ardour.org/surfaces/generic_midi:0",
ptr : 0,
module : 0,
initialize : new_generic_midi_protocol,
diff --git a/libs/surfaces/tranzport/interface.cc b/libs/surfaces/tranzport/interface.cc
index a731be2ddf..f2160c3144 100644
--- a/libs/surfaces/tranzport/interface.cc
+++ b/libs/surfaces/tranzport/interface.cc
@@ -7,7 +7,15 @@ using namespace ARDOUR;
ControlProtocol*
new_tranzport_protocol (ControlProtocolDescriptor* descriptor, Session* s)
{
- return new TranzportControlProtocol (*s);
+ TranzportControlProtocol* tcp = new TranzportControlProtocol (*s);
+
+ if (tcp->init ()) {
+ delete tcp;
+ return 0;
+ }
+
+ return tcp;
+
}
void
@@ -18,10 +26,12 @@ delete_tranzport_protocol (ControlProtocolDescriptor* descriptor, ControlProtoco
static ControlProtocolDescriptor tranzport_descriptor = {
name : "Tranzport",
+ id : "uri://ardour.org/surfaces/tranzport:0",
ptr : 0,
module : 0,
initialize : new_tranzport_protocol,
destroy : delete_tranzport_protocol
+
};
diff --git a/libs/surfaces/tranzport/tranzport_control_protocol.cc b/libs/surfaces/tranzport/tranzport_control_protocol.cc
index eee60c43eb..34ba54c8b6 100644
--- a/libs/surfaces/tranzport/tranzport_control_protocol.cc
+++ b/libs/surfaces/tranzport/tranzport_control_protocol.cc
@@ -34,6 +34,8 @@ TranzportControlProtocol::TranzportControlProtocol (Session& s)
wheel_shift_mode = WheelShiftGain;
timerclear (&last_wheel_motion);
last_wheel_dir = 1;
+ display_mode = DisplayNormal;
+ requested_display_mode = display_mode;
memset (current_screen, 0, sizeof (current_screen));
@@ -60,6 +62,15 @@ TranzportControlProtocol::init ()
return -1;
}
+ lcd_clear ();
+
+ print (0, 0, "Welcome to");
+ print (1, 0, "Ardour");
+
+ show_wheel_mode();
+ next_track ();
+ show_transport_time ();
+
/* outbound thread */
init_thread ();
@@ -85,17 +96,124 @@ TranzportControlProtocol::send_route_feedback (list<Route*>& routes)
void
TranzportControlProtocol::send_global_feedback ()
{
- if (_device_status == STATUS_OFFLINE) {
- return;
+ if (requested_display_mode != display_mode) {
+ switch (requested_display_mode) {
+ case DisplayNormal:
+ enter_normal_display_mode ();
+ break;
+ case DisplayBigMeter:
+ enter_big_meter_mode ();
+ break;
+ }
}
- show_transport_time ();
+ switch (display_mode) {
+ case DisplayBigMeter:
+ show_meter ();
+ break;
+
+ case DisplayNormal:
+ show_transport_time ();
+ if (session.soloing()) {
+ light_on (LightAnysolo);
+ } else {
+ light_off (LightAnysolo);
+ }
+ break;
+ }
+}
+
+void
+TranzportControlProtocol::next_display_mode ()
+{
+ cerr << "Next display mode\n";
+
+ switch (display_mode) {
+ case DisplayNormal:
+ requested_display_mode = DisplayBigMeter;
+ break;
+
+ case DisplayBigMeter:
+ requested_display_mode = DisplayNormal;
+ break;
+ }
+}
- if (session.soloing()) {
- light_on (LightAnysolo);
+void
+TranzportControlProtocol::enter_big_meter_mode ()
+{
+ lcd_clear ();
+ lights_off ();
+ display_mode = DisplayBigMeter;
+}
+
+void
+TranzportControlProtocol::enter_normal_display_mode ()
+{
+ lcd_clear ();
+ lights_off ();
+ show_current_track ();
+ show_wheel_mode ();
+ show_transport_time ();
+ display_mode = DisplayNormal;
+}
+
+
+float
+log_meter (float db)
+{
+ float def = 0.0f; /* Meter deflection %age */
+
+ if (db < -70.0f) {
+ def = 0.0f;
+ } else if (db < -60.0f) {
+ def = (db + 70.0f) * 0.25f;
+ } else if (db < -50.0f) {
+ def = (db + 60.0f) * 0.5f + 2.5f;
+ } else if (db < -40.0f) {
+ def = (db + 50.0f) * 0.75f + 7.5f;
+ } else if (db < -30.0f) {
+ def = (db + 40.0f) * 1.5f + 15.0f;
+ } else if (db < -20.0f) {
+ def = (db + 30.0f) * 2.0f + 30.0f;
+ } else if (db < 6.0f) {
+ def = (db + 20.0f) * 2.5f + 50.0f;
} else {
- light_off (LightAnysolo);
+ def = 115.0f;
}
+
+ /* 115 is the deflection %age that would be
+ when db=6.0. this is an arbitrary
+ endpoint for our scaling.
+ */
+
+ return def/115.0f;
+}
+
+void
+TranzportControlProtocol::show_meter ()
+{
+ if (current_route == 0) {
+ return;
+ }
+
+ float level = current_route->peak_input_power (0);
+ float fraction = log_meter (level);
+ int fill = (int) floor (fraction * 20);
+ char buf[21];
+ int i;
+
+ for (i = 0; i < fill; ++i) {
+ buf[i] = 0x70; /* tranzport special code for 4 quadrant LCD block */
+ }
+ for (; i < 20; ++i) {
+ buf[i] = ' ';
+ }
+
+ buf[21] = '\0';
+
+ print (0, 0, buf);
+ print (1, 0, buf);
}
void
@@ -141,33 +259,6 @@ TranzportControlProtocol::thread_work ()
{
PBD::ThreadCreated (pthread_self(), X_("tranzport monitor"));
- /* wait for the device to go online */
-
- while (true) {
- if (read()) {
- return 0;
- }
- switch (_device_status) {
- case STATUS_OFFLINE:
- cerr << "tranzport offline\n";
- break;
- case STATUS_ONLINE:
- case 0:
- cerr << "tranzport online\n";
- break;
- default:
- cerr << "tranzport: unknown status\n";
- break;
- }
-
- if (_device_status == STATUS_ONLINE || _device_status == 0) {
- break;
- }
- }
-
- lcd_clear ();
- show_wheel_mode();
-
while (true) {
if (read ()) {
break;
@@ -217,6 +308,13 @@ TranzportControlProtocol::open_core (struct usb_device* dev)
return -1;
}
+ if (usb_set_configuration (udev, 1) < 0) {
+ error << _("Tranzport: cannot configure USB interface") << endmsg;
+ usb_close (udev);
+ udev = 0;
+ return -1;
+ }
+
return 0;
}
@@ -276,7 +374,8 @@ TranzportControlProtocol::lcd_clear ()
cmd[7] = 0x00;
{
- LockMonitor lm (write_lock, __LINE__, __FILE__);
+ LockMonitor lp (print_lock, __LINE__, __FILE__);
+ LockMonitor lw (write_lock, __LINE__, __FILE__);
for (uint8_t i = 0; i < 10; ++i) {
cmd[2] = i;
@@ -287,35 +386,16 @@ TranzportControlProtocol::lcd_clear ()
}
}
-int
-TranzportControlProtocol::lcd_write (int row, int col, uint8_t cell, const char* text)
+void
+TranzportControlProtocol::lights_off ()
{
- uint8_t cmd[8];
-
- if (cell > 9) {
- return -1;
- }
-
- if (memcmp (text, &current_screen[row][col], 4)) {
-
- current_screen[row][col] = text[0];
- current_screen[row][col+1] = text[1];
- current_screen[row][col+2] = text[2];
- current_screen[row][col+3] = text[3];
-
- cmd[0] = 0x00;
- cmd[1] = 0x01;
- cmd[2] = cell;
- cmd[3] = text[0];
- cmd[4] = text[1];
- cmd[5] = text[2];
- cmd[6] = text[3];
- cmd[7] = 0x00;
-
- return write (cmd, 500);
- }
-
- return 0;
+ light_off (LightRecord);
+ light_off (LightTrackrec);
+ light_off (LightTrackmute);
+ light_off (LightTracksolo);
+ light_off (LightAnysolo);
+ light_off (LightLoop);
+ light_off (LightPunch);
}
int
@@ -865,7 +945,11 @@ TranzportControlProtocol::button_event_fastforward_release (bool shifted)
void
TranzportControlProtocol::button_event_stop_press (bool shifted)
{
- session.request_transport_speed (0.0);
+ if (shifted) {
+ next_display_mode ();
+ } else {
+ session.request_transport_speed (0.0);
+ }
}
void
@@ -1039,9 +1123,17 @@ void
TranzportControlProtocol::shuttle ()
{
if (_datawheel < WheelDirectionThreshold) {
- session.request_transport_speed (session.transport_speed() + 0.1);
+ if (session.transport_speed() < 0) {
+ session.request_transport_speed (1.0);
+ } else {
+ session.request_transport_speed (session.transport_speed() + 0.1);
+ }
} else {
- session.request_transport_speed (session.transport_speed() - 0.1);
+ if (session.transport_speed() > 0) {
+ session.request_transport_speed (-1.0);
+ } else {
+ session.request_transport_speed (session.transport_speed() - 0.1);
+ }
}
}
@@ -1254,23 +1346,46 @@ TranzportControlProtocol::print (int row, int col, const char *text)
int offset = col % 4;
- /* copy current cell contents into tmp */
-
- memcpy (tmp, &current_screen[row][base_col], 4);
-
- /* overwrite with new text */
+ {
- uint32_t tocopy = min ((4U - offset), left);
+ LockMonitor lm (print_lock, __LINE__, __FILE__);
- memcpy (tmp+offset, text, tocopy);
-
- cell += (row * 5);
-
- lcd_write (row, base_col, cell, tmp);
-
- text += tocopy;
- left -= tocopy;
- col += tocopy;
+ /* copy current cell contents into tmp */
+
+ memcpy (tmp, &current_screen[row][base_col], 4);
+
+ /* overwrite with new text */
+
+ uint32_t tocopy = min ((4U - offset), left);
+
+ memcpy (tmp+offset, text, tocopy);
+
+ uint8_t cmd[8];
+
+ /* compare with current screen */
+
+ if (memcmp (tmp, &current_screen[row][base_col], 4)) {
+
+ /* different, so update */
+
+ memcpy (&current_screen[row][base_col], tmp, 4);
+
+ cmd[0] = 0x00;
+ cmd[1] = 0x01;
+ cmd[2] = cell + (row * 5);
+ cmd[3] = tmp[0];
+ cmd[4] = tmp[1];
+ cmd[5] = tmp[2];
+ cmd[6] = tmp[3];
+ cmd[7] = 0x00;
+
+ write (cmd, 500);
+ }
+
+ text += tocopy;
+ left -= tocopy;
+ col += tocopy;
+ }
}
}
diff --git a/libs/surfaces/tranzport/tranzport_control_protocol.h b/libs/surfaces/tranzport/tranzport_control_protocol.h
index c5aa5f90e0..d460a6c74a 100644
--- a/libs/surfaces/tranzport/tranzport_control_protocol.h
+++ b/libs/surfaces/tranzport/tranzport_control_protocol.h
@@ -77,6 +77,11 @@ class TranzportControlProtocol : public ControlProtocol {
WheelScrub,
WheelShuttle
};
+
+ enum DisplayMode {
+ DisplayNormal,
+ DisplayBigMeter
+ };
pthread_t thread;
uint32_t buttonmask;
@@ -92,6 +97,8 @@ class TranzportControlProtocol : public ControlProtocol {
WheelShiftMode wheel_shift_mode;
struct timeval last_wheel_motion;
int last_wheel_dir;
+ DisplayMode display_mode;
+ DisplayMode requested_display_mode;
std::vector<sigc::connection> track_connections;
@@ -103,6 +110,7 @@ class TranzportControlProtocol : public ControlProtocol {
jack_nframes_t last_where;
PBD::Lock write_lock;
+ PBD::Lock print_lock;
int open ();
int read (uint32_t timeout_override = 0);
@@ -112,16 +120,21 @@ class TranzportControlProtocol : public ControlProtocol {
int open_core (struct usb_device*);
void lcd_clear ();
- int lcd_write (int row, int col, uint8_t cell, const char *text);
void print (int row, int col, const char* text);
int light_on (LightID);
int light_off (LightID);
+ void lights_off ();
+
+ void enter_big_meter_mode ();
+ void enter_normal_display_mode ();
+ void next_display_mode ();
void show_current_track ();
void show_transport_time ();
void show_wheel_mode ();
void show_gain ();
void show_pan ();
+ void show_meter ();
void track_solo_changed (void*);
void track_rec_changed (void*);