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/ardour | |
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/ardour')
-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 |
12 files changed, 190 insertions, 179 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; |