From a157537898eccf08009281633b19970515366a78 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Mon, 10 Apr 2006 03:54:00 +0000 Subject: 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 --- gtk2_ardour/ardour.menus | 19 ++ gtk2_ardour/ardour_ui.cc | 29 --- gtk2_ardour/ardour_ui.h | 9 +- gtk2_ardour/ardour_ui_dialogs.cc | 1 - gtk2_ardour/ardour_ui_ed.cc | 49 +++- gtk2_ardour/editor.cc | 5 +- gtk2_ardour/editor_actions.cc | 6 +- gtk2_ardour/editor_mixer.cc | 8 - gtk2_ardour/gain_meter.cc | 30 +-- gtk2_ardour/mixer_strip.cc | 10 +- gtk2_ardour/mixer_strip.h | 1 - gtk2_ardour/mixer_ui.cc | 12 - gtk2_ardour/mixer_ui.h | 2 - gtk2_ardour/public_editor.h | 4 +- gtk2_ardour/send_ui.cc | 5 +- gtk2_ardour/time_axis_view.cc | 2 +- libs/ardour/ardour/audioengine.h | 8 +- libs/ardour/ardour/control_protocol.h | 8 +- libs/ardour/ardour/control_protocol_manager.h | 18 +- libs/ardour/ardour/io.h | 15 +- libs/ardour/audioengine.cc | 122 ++++----- libs/ardour/control_protocol.cc | 9 +- libs/ardour/control_protocol_manager.cc | 129 +++++----- libs/ardour/globals.cc | 2 +- libs/ardour/io.cc | 47 +++- libs/ardour/route.cc | 8 +- libs/ardour/session_butler.cc | 1 - libs/ardour/session_state.cc | 2 +- libs/gtkmm2ext/utils.cc | 4 +- libs/surfaces/generic_midi/SConscript | 9 +- .../generic_midi/generic_midi_control_protocol.cc | 26 +- .../generic_midi/generic_midi_control_protocol.h | 4 + libs/surfaces/generic_midi/interface.cc | 10 +- libs/surfaces/tranzport/interface.cc | 12 +- .../tranzport/tranzport_control_protocol.cc | 275 +++++++++++++++------ .../tranzport/tranzport_control_protocol.h | 15 +- 36 files changed, 533 insertions(+), 383 deletions(-) diff --git a/gtk2_ardour/ardour.menus b/gtk2_ardour/ardour.menus index 048e63667d..b8f6b10f78 100644 --- a/gtk2_ardour/ardour.menus +++ b/gtk2_ardour/ardour.menus @@ -211,11 +211,29 @@ + + + + + + + + + + + + + + + + + + @@ -250,6 +268,7 @@ + diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index 79c81992dc..846eca6096 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -497,27 +497,12 @@ ARDOUR_UI::every_second () update_cpu_load (); update_buffer_load (); update_disk_space (); - // update_disk_rate (); return TRUE; } gint ARDOUR_UI::every_point_one_seconds () { - struct timeval now; - struct timeval diff; - - /* do not attempt to grab peak power more than once per cycle. - */ - - gettimeofday (&now, 0); - timersub (&now, &last_peak_grab, &diff); - - if ((diff.tv_usec + (diff.tv_sec * 1000000)) >= engine->usecs_per_cycle()) { - IO::GrabPeakPower(); /* EMIT_SIGNAL */ - last_peak_grab = now; - } - update_speed_display (); RapidScreenUpdate(); /* EMIT_SIGNAL */ return TRUE; @@ -567,20 +552,6 @@ ARDOUR_UI::update_cpu_load () cpu_load_label.set_text (buf); } -void -ARDOUR_UI::update_disk_rate () -{ - char buf[64]; - - if (session) { - snprintf (buf, sizeof (buf), _("Disk r:%5.1f w:%5.1f MB/s"), - session->read_data_rate()/1048576.0f, session->write_data_rate()/1048576.0f); - disk_rate_label.set_text (buf); - } else { - disk_rate_label.set_text (""); - } -} - void ARDOUR_UI::update_buffer_load () { diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h index bca41f6ca7..cff822e2f3 100644 --- a/gtk2_ardour/ardour_ui.h +++ b/gtk2_ardour/ardour_ui.h @@ -87,6 +87,7 @@ namespace ARDOUR { class Route; class Port; class IO; + class ControlProtocolInfo; }; namespace ALSA { @@ -491,6 +492,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI Gtk::HBox menu_hbox; void build_menu_bar (); + void build_control_surface_menu (); void pack_toplevel_controls(); Gtk::Label wall_clock_label; @@ -505,10 +507,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI Gtk::EventBox cpu_load_box; void update_cpu_load (); - Gtk::Label disk_rate_label; - Gtk::EventBox disk_rate_box; - void update_disk_rate(); - Gtk::Label buffer_load_label; Gtk::EventBox buffer_load_box; void update_buffer_load (); @@ -718,7 +716,8 @@ class ARDOUR_UI : public Gtkmm2ext::UI void map_some_session_state (const char* group, const char* action, bool (ARDOUR::Session::*get)() const); void queue_session_control_changed (ARDOUR::Session::ControlType t); void session_control_changed (ARDOUR::Session::ControlType t); - + + void toggle_control_protocol (ARDOUR::ControlProtocolInfo*); }; diff --git a/gtk2_ardour/ardour_ui_dialogs.cc b/gtk2_ardour/ardour_ui_dialogs.cc index 29a5858603..e32d314036 100644 --- a/gtk2_ardour/ardour_ui_dialogs.cc +++ b/gtk2_ardour/ardour_ui_dialogs.cc @@ -193,7 +193,6 @@ ARDOUR_UI::unload_session () session = 0; update_buffer_load (); - // update_disk_rate (); return 0; } diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc index e658aa23e9..2a6bccf227 100644 --- a/gtk2_ardour/ardour_ui_ed.cc +++ b/gtk2_ardour/ardour_ui_ed.cc @@ -33,6 +33,7 @@ #include "actions.h" #include +#include #include "i18n.h" @@ -76,6 +77,7 @@ ARDOUR_UI::install_actions () ActionManager::register_action (main_actions, X_("AudioFileFormat"), _("Audio File Format")); ActionManager::register_action (main_actions, X_("AudioFileFormatHeader"), _("Header")); ActionManager::register_action (main_actions, X_("AudioFileFormatData"), _("Data")); + ActionManager::register_action (main_actions, X_("ControlSurfaces"), _("Control Surfaces")); /* the real actions */ @@ -441,9 +443,51 @@ ARDOUR_UI::install_actions () setup_config_options (); } +void +ARDOUR_UI::toggle_control_protocol (ControlProtocolInfo* cpi) +{ + if (cpi->protocol == 0) { + ControlProtocolManager::instance().instantiate (*cpi); + } else { + ControlProtocolManager::instance().teardown (*cpi); + } +} + +void +ARDOUR_UI::build_control_surface_menu () +{ + list::iterator i; + + /* !!! this has to match the top level entry from ardour.menus */ + + string ui = "\n\n\n"; + + for (i = ControlProtocolManager::instance().control_protocol_info.begin(); i != ControlProtocolManager::instance().control_protocol_info.end(); ++i) { + + string action_name = "Toggle"; + action_name += (*i)->name; + action_name += "Surface"; + + string action_label = (*i)->name; + + ActionManager::register_toggle_action (editor->editor_actions, action_name.c_str(), action_label.c_str(), + (bind (mem_fun (*this, &ARDOUR_UI::toggle_control_protocol), *i))); + + ui += "\n"; + } + + ui += "\n\n\n"; + + ActionManager::ui_manager->add_ui_from_string (ui); +} + void ARDOUR_UI::build_menu_bar () { + build_control_surface_menu (); + menu_bar = dynamic_cast (ActionManager::get_widget (X_("/Main"))); menu_bar->set_name ("MainMenuBar"); @@ -470,10 +514,6 @@ ARDOUR_UI::build_menu_bar () buffer_load_box.set_name ("BufferLoad"); buffer_load_label.set_name ("BufferLoad"); -// disk_rate_box.add (disk_rate_label); -// disk_rate_box.set_name ("DiskRate"); -// disk_rate_label.set_name ("DiskRate"); - sample_rate_box.add (sample_rate_label); sample_rate_box.set_name ("SampleRate"); sample_rate_label.set_name ("SampleRate"); @@ -482,7 +522,6 @@ ARDOUR_UI::build_menu_bar () menu_hbox.pack_end (wall_clock_box, false, false, 10); menu_hbox.pack_end (disk_space_box, false, false, 10); menu_hbox.pack_end (cpu_load_box, false, false, 10); -// menu_hbox.pack_end (disk_rate_box, false, false, 10); menu_hbox.pack_end (buffer_load_box, false, false, 10); menu_hbox.pack_end (sample_rate_box, false, false, 10); diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 2b0bbee1ae..b1f6a0d2cf 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -966,7 +966,7 @@ Editor::control_scroll (float fraction) } else if ((fraction > 0.0f) && (max_frames - session->transport_frame() < step)) { target = (max_frames - (current_page_frames()*2)); // allow room for slop in where the PH is on the screen } else { - target = (session->transport_frame() + (jack_nframes_t)(fraction * current_page_frames())); + target = (session->transport_frame() + (jack_nframes_t) floor ((fraction * current_page_frames()))); } /* move visuals, we'll catch up with it later */ @@ -1097,9 +1097,6 @@ Editor::start_scrolling () { scroll_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (mem_fun(*this, &Editor::update_current_screen)); - - slower_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect - (mem_fun(*this, &Editor::update_slower)); } void diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc index e7e3b186aa..161d015583 100644 --- a/gtk2_ardour/editor_actions.cc +++ b/gtk2_ardour/editor_actions.cc @@ -18,7 +18,8 @@ void Editor::register_actions () { RefPtr act; - RefPtr editor_actions = ActionGroup::create (X_("Editor")); + + editor_actions = ActionGroup::create (X_("Editor")); /* non-operative menu items for menu bar */ @@ -37,6 +38,9 @@ Editor::register_actions () ActionManager::register_action (editor_actions, X_("Monitoring"), _("Monitoring")); ActionManager::register_action (editor_actions, X_("Autoconnect"), _("Autoconnect")); ActionManager::register_action (editor_actions, X_("Layering"), _("Layering")); + ActionManager::register_action (editor_actions, X_("Metering"), _("Metering")); + ActionManager::register_action (editor_actions, X_("MeteringFallOffRate"), _("Fall off rate")); + ActionManager::register_action (editor_actions, X_("MeteringHoldTime"), _("Hold Time")); ActionManager::register_action (editor_actions, X_("addExistingAudioFiles"), _("Add Existing Audio")); /* add named actions for the editor */ diff --git a/gtk2_ardour/editor_mixer.cc b/gtk2_ardour/editor_mixer.cc index 512fe6a957..f6fe3b66c9 100644 --- a/gtk2_ardour/editor_mixer.cc +++ b/gtk2_ardour/editor_mixer.cc @@ -204,14 +204,6 @@ Editor::update_current_screen () } } -void -Editor::update_slower () -{ - if (current_mixer_strip) { - current_mixer_strip->update (); - } -} - void Editor::current_mixer_strip_removed () { diff --git a/gtk2_ardour/gain_meter.cc b/gtk2_ardour/gain_meter.cc index 8874b47cf3..55ffac2063 100644 --- a/gtk2_ardour/gain_meter.cc +++ b/gtk2_ardour/gain_meter.cc @@ -318,10 +318,8 @@ GainMeter::update_meters () if ((*i).packed) { peak = _io.peak_input_power (n); - if (_session.meter_falloff() == 0.0f || peak > (*i).meter->get_user_level()) { - (*i).meter->set (log_meter (peak), peak); - } - + (*i).meter->set (log_meter (peak), peak); + if (peak > max_peak) { max_peak = peak; /* set peak display */ @@ -334,32 +332,8 @@ GainMeter::update_meters () } } } - } -void -GainMeter::update_meters_falloff () -{ - vector::iterator i; - uint32_t n; - float dbpeak; - - for (n = 0, i = meters.begin(); i != meters.end(); ++i, ++n) { - if ((*i).packed) { - // just do falloff - //peak = (*i).meter->get_level() * _falloff_rate; - dbpeak = (*i).meter->get_user_level() - _session.meter_falloff(); - - dbpeak = std::max(dbpeak, -200.0f); - - // cerr << "tmplevel: " << tmplevel << endl; - (*i).meter->set (log_meter (dbpeak), dbpeak); - } - } - -} - - void GainMeter::meter_hold_changed() { diff --git a/gtk2_ardour/mixer_strip.cc b/gtk2_ardour/mixer_strip.cc index faf6bc43df..fe9d0b68bb 100644 --- a/gtk2_ardour/mixer_strip.cc +++ b/gtk2_ardour/mixer_strip.cc @@ -766,18 +766,10 @@ MixerStrip::update_output_display () panners.setup_pan (); } -void -MixerStrip::update () -{ - gpm.update_meters (); -} - void MixerStrip::fast_update () { - if (_session.meter_falloff() > 0.0f) { - gpm.update_meters_falloff (); - } + gpm.update_meters (); } gint diff --git a/gtk2_ardour/mixer_strip.h b/gtk2_ardour/mixer_strip.h index 79a58764da..e56c1ce4ec 100644 --- a/gtk2_ardour/mixer_strip.h +++ b/gtk2_ardour/mixer_strip.h @@ -89,7 +89,6 @@ class MixerStrip : public RouteUI, public Gtk::EventBox void set_width (Width); Width get_width() const { return _width; } - void update (); void fast_update (); void set_embedded (bool); diff --git a/gtk2_ardour/mixer_ui.cc b/gtk2_ardour/mixer_ui.cc index 0a0f7afe7f..195da09332 100644 --- a/gtk2_ardour/mixer_ui.cc +++ b/gtk2_ardour/mixer_ui.cc @@ -398,7 +398,6 @@ Mixer_UI::hide_strip (MixerStrip* ms) gint Mixer_UI::start_updating () { - screen_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect (mem_fun(*this, &Mixer_UI::update_strips)); fast_screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (mem_fun(*this, &Mixer_UI::fast_update_strips)); return 0; } @@ -406,21 +405,10 @@ Mixer_UI::hide_strip (MixerStrip* ms) gint Mixer_UI::stop_updating () { - screen_update_connection.disconnect(); fast_screen_update_connection.disconnect(); return 0; } - void - Mixer_UI::update_strips () - { - if (is_mapped () && session) { - for (list::iterator i = strips.begin(); i != strips.end(); ++i) { - (*i)->update (); - } - } - } - void Mixer_UI::fast_update_strips () { diff --git a/gtk2_ardour/mixer_ui.h b/gtk2_ardour/mixer_ui.h index 853304095f..6cf420d916 100644 --- a/gtk2_ardour/mixer_ui.h +++ b/gtk2_ardour/mixer_ui.h @@ -131,8 +131,6 @@ class Mixer_UI : public Gtk::Window void disconnect_from_session (); - sigc::connection screen_update_connection; - void update_strips (); sigc::connection fast_screen_update_connection; void fast_update_strips (); diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h index e45b9236ff..4c12b99d7c 100644 --- a/gtk2_ardour/public_editor.h +++ b/gtk2_ardour/public_editor.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -129,11 +130,10 @@ class PublicEditor : public Gtk::Window, public Stateful { sigc::signal DisplayControlChanged; sigc::signal ZoomFocusChanged; sigc::signal ZoomChanged; - sigc::signal XOriginChanged; sigc::signal Resized; sigc::signal Realized; - // FIXED FOR GTK2 + Glib::RefPtr editor_actions; virtual bool canvas_control_point_event (GdkEvent* event,ArdourCanvas::Item*, ControlPoint*) = 0; virtual bool canvas_line_event (GdkEvent* event,ArdourCanvas::Item*, AutomationLine*) = 0; diff --git a/gtk2_ardour/send_ui.cc b/gtk2_ardour/send_ui.cc index 0869490c0c..8ce3838176 100644 --- a/gtk2_ardour/send_ui.cc +++ b/gtk2_ardour/send_ui.cc @@ -63,7 +63,7 @@ SendUI::SendUI (Send& s, Session& se) gpm.setup_meters (); gpm.set_fader_name ("SendUIFrame"); - screen_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect (mem_fun (*this, &SendUI::update)); + // screen_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect (mem_fun (*this, &SendUI::update)); fast_screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (mem_fun (*this, &SendUI::fast_update)); } @@ -107,14 +107,13 @@ SendUI::send_going_away (Redirect *ignored) void SendUI::update () { - gpm.update_meters (); } void SendUI::fast_update () { if (_session.meter_falloff() > 0.0f) { - gpm.update_meters_falloff (); + gpm.update_meters (); } } diff --git a/gtk2_ardour/time_axis_view.cc b/gtk2_ardour/time_axis_view.cc index 1b6c1f390c..44b3541826 100644 --- a/gtk2_ardour/time_axis_view.cc +++ b/gtk2_ardour/time_axis_view.cc @@ -108,7 +108,7 @@ TimeAxisView::TimeAxisView (ARDOUR::Session& sess, PublicEditor& ed, TimeAxisVie name_entry.signal_activate().connect (mem_fun(*this, &TimeAxisView::name_entry_activated)); name_entry.signal_focus_in_event().connect (mem_fun (*this, &TimeAxisView::name_entry_focus_in)); name_entry.signal_focus_out_event().connect (mem_fun (*this, &TimeAxisView::name_entry_focus_out)); - Gtkmm2ext::set_size_request_to_display_given_text (name_entry, N_("gTortnam"), 10, 10); // just represents a short name + Gtkmm2ext::set_size_request_to_display_given_text (name_entry, N_("gTortnam"), 2, 2); // just represents a short name name_label.set_name ("TrackLabel"); name_label.set_alignment (0.0, 0.5); 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 freewheel_action; bool reconnect_on_halt; int _usecs_per_cycle; + jack_nframes_t last_meter_point; + jack_nframes_t meter_interval; typedef std::set 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 #include +#include + #include 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); + + ControlProtocol* instantiate (ControlProtocolInfo&); + int teardown (ControlProtocolInfo&); - ControlProtocol* instantiate (Session&, std::string protocol_name); - int teardown (std::string protocol_name); + std::list control_protocol_info; private: static ControlProtocolManager* _instance; + Session* _session; PBD::Lock protocols_lock; - std::list control_protocol_info; std::list 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 GrabPeakPower; + static sigc::signal Meter; /* automation */ @@ -278,7 +273,7 @@ class IO : public Stateful, public ARDOUR::StateManager vector _outputs; vector _inputs; vector _peak_power; - vector _stored_peak_power; + vector _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 #include #include + #include #include @@ -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(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(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 routes = session.get_routes(); /* copies the routes */ - - // if (send_route_feedback ()) { - //send_route_feedback (routes); - // } + if (send_route_feedback ()) { + list 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 #include +#include #include #include @@ -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::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::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::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::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::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::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 *found; PathScanner scanner; - cerr << "CP Manager looking for surfaces\n"; - found = scanner (path, protocol_filter, 0, false, true); for (vector::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 method) +{ + for (list::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 IO::GrabPeakPower; +sigc::signal IO::Meter; sigc::signal IO::ConnectingLegal; sigc::signal IO::PortsLegal; sigc::signal 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 + #include #include @@ -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 + #include #include @@ -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& 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::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& 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 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*); -- cgit v1.2.3