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
This commit is contained in:
parent
7e8a982245
commit
a157537898
|
@ -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'>
|
||||
|
|
|
@ -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 ()
|
||||
{
|
||||
|
|
|
@ -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*);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -193,7 +193,6 @@ ARDOUR_UI::unload_session ()
|
|||
session = 0;
|
||||
|
||||
update_buffer_load ();
|
||||
// update_disk_rate ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
@ -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<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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 ()
|
||||
{
|
||||
|
|
|
@ -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<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()
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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<MixerStrip *>::iterator i = strips.begin(); i != strips.end(); ++i) {
|
||||
(*i)->update ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Mixer_UI::fast_update_strips ()
|
||||
{
|
||||
|
|
|
@ -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 ();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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*);
|
||||
|
||||
|
|
|
@ -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 (Session&, std::string protocol_name);
|
||||
int teardown (std::string protocol_name);
|
||||
ControlProtocol* instantiate (ControlProtocolInfo&);
|
||||
int teardown (ControlProtocolInfo&);
|
||||
|
||||
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);
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
|
|
@ -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 (cpi.path);
|
||||
|
||||
cpi->descriptor = get_descriptor ((*i)->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;
|
||||
}
|
||||
|
||||
return -1;
|
||||
if (!cpi.descriptor) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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']
|
||||
])
|
||||
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 ();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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) {
|
||||
if (requested_display_mode != display_mode) {
|
||||
switch (requested_display_mode) {
|
||||
case DisplayNormal:
|
||||
enter_normal_display_mode ();
|
||||
break;
|
||||
case DisplayBigMeter:
|
||||
enter_big_meter_mode ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
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;
|
||||
}
|
||||
|
||||
show_transport_time ();
|
||||
float level = current_route->peak_input_power (0);
|
||||
float fraction = log_meter (level);
|
||||
int fill = (int) floor (fraction * 20);
|
||||
char buf[21];
|
||||
int i;
|
||||
|
||||
if (session.soloing()) {
|
||||
light_on (LightAnysolo);
|
||||
} else {
|
||||
light_off (LightAnysolo);
|
||||
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);
|
||||
LockMonitor lm (print_lock, __LINE__, __FILE__);
|
||||
|
||||
/* overwrite with new text */
|
||||
/* 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);
|
||||
|
||||
uint32_t tocopy = min ((4U - offset), left);
|
||||
memcpy (tmp+offset, text, tocopy);
|
||||
|
||||
memcpy (tmp+offset, text, tocopy);
|
||||
|
||||
cell += (row * 5);
|
||||
uint8_t cmd[8];
|
||||
|
||||
lcd_write (row, base_col, cell, tmp);
|
||||
|
||||
text += tocopy;
|
||||
left -= tocopy;
|
||||
col += tocopy;
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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*);
|
||||
|
|
Loading…
Reference in New Issue