diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2006-04-10 03:54:00 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2006-04-10 03:54:00 +0000 |
commit | a157537898eccf08009281633b19970515366a78 (patch) | |
tree | cd6f7bb1e7f9bddba1b5cc4ce6e10c60cb2b2a46 /libs | |
parent | 7e8a98224578e03e17fbf5e656241ff5ef1a0bc1 (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.h | 8 | ||||
-rw-r--r-- | libs/ardour/ardour/control_protocol.h | 8 | ||||
-rw-r--r-- | libs/ardour/ardour/control_protocol_manager.h | 18 | ||||
-rw-r--r-- | libs/ardour/ardour/io.h | 15 | ||||
-rw-r--r-- | libs/ardour/audioengine.cc | 122 | ||||
-rw-r--r-- | libs/ardour/control_protocol.cc | 9 | ||||
-rw-r--r-- | libs/ardour/control_protocol_manager.cc | 129 | ||||
-rw-r--r-- | libs/ardour/globals.cc | 2 | ||||
-rw-r--r-- | libs/ardour/io.cc | 47 | ||||
-rw-r--r-- | libs/ardour/route.cc | 8 | ||||
-rw-r--r-- | libs/ardour/session_butler.cc | 1 | ||||
-rw-r--r-- | libs/ardour/session_state.cc | 2 | ||||
-rw-r--r-- | libs/gtkmm2ext/utils.cc | 4 | ||||
-rw-r--r-- | libs/surfaces/generic_midi/SConscript | 9 | ||||
-rw-r--r-- | libs/surfaces/generic_midi/generic_midi_control_protocol.cc | 26 | ||||
-rw-r--r-- | libs/surfaces/generic_midi/generic_midi_control_protocol.h | 4 | ||||
-rw-r--r-- | libs/surfaces/generic_midi/interface.cc | 10 | ||||
-rw-r--r-- | libs/surfaces/tranzport/interface.cc | 12 | ||||
-rw-r--r-- | libs/surfaces/tranzport/tranzport_control_protocol.cc | 275 | ||||
-rw-r--r-- | libs/surfaces/tranzport/tranzport_control_protocol.h | 15 |
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, ¤t_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, ¤t_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, ¤t_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, ¤t_screen[row][base_col], 4)) { + + /* different, so update */ + + memcpy (¤t_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*); |