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