allow user tweaking of everything that might have inherent latency; add GUI for track level adjustment and widget that can be (but is not yet) embedded in a plugin GUI
git-svn-id: svn://localhost/ardour2/trunk@2075 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
34be8c2119
commit
b5af3bb8e3
|
@ -152,6 +152,7 @@ gtk-custom-ruler.c
|
|||
io_selector.cc
|
||||
keyboard.cc
|
||||
ladspa_pluginui.cc
|
||||
latency_gui.cc
|
||||
location_ui.cc
|
||||
main.cc
|
||||
marker.cc
|
||||
|
|
|
@ -0,0 +1,167 @@
|
|||
#define __STDC_FORMAT_MACROS 1
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <ardour/latent.h>
|
||||
#include <gtkmm2ext/utils.h>
|
||||
|
||||
#include "latency_gui.h"
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
using namespace PBD;
|
||||
using namespace Gtk;
|
||||
using namespace Gtkmm2ext;
|
||||
using namespace sigc;
|
||||
using namespace ARDOUR;
|
||||
|
||||
|
||||
static const gchar *_unit_strings[] = {
|
||||
N_("sample"),
|
||||
N_("msec"),
|
||||
N_("period"),
|
||||
0
|
||||
};
|
||||
|
||||
std::vector<std::string> LatencyGUI::unit_strings;
|
||||
|
||||
void
|
||||
LatencyGUI::latency_printer (char *buf, unsigned int bufsize)
|
||||
{
|
||||
double nframes = adjustment.get_value();
|
||||
|
||||
if (nframes < (sample_rate / 1000.0)) {
|
||||
snprintf (buf, bufsize, "%" PRId64 " samples", (nframes64_t) rint (nframes));
|
||||
} else {
|
||||
snprintf (buf, bufsize, "%.2g msecs" , nframes / (sample_rate / 1000.0));
|
||||
}
|
||||
}
|
||||
|
||||
LatencyGUI::LatencyGUI (Latent& l, nframes64_t sr, nframes64_t psz)
|
||||
: _latent (l),
|
||||
initial_value (_latent.signal_latency()),
|
||||
sample_rate (sr),
|
||||
period_size (psz),
|
||||
/* max 1 second, step by frames, page by msecs */
|
||||
adjustment (initial_value, 0.0, sample_rate, 1.0, sample_rate / 1000.0f),
|
||||
bc (adjustment, ignored, sigc::mem_fun (*this, &LatencyGUI::latency_printer)),
|
||||
reset_button (_("Automatic"))
|
||||
{
|
||||
Widget* w;
|
||||
|
||||
if (unit_strings.empty()) {
|
||||
unit_strings = I18N (_unit_strings);
|
||||
}
|
||||
|
||||
set_popdown_strings (units_combo, unit_strings);
|
||||
units_combo.set_active_text (unit_strings.front());
|
||||
|
||||
w = manage (new Image (Stock::ADD, ICON_SIZE_BUTTON));
|
||||
w->show ();
|
||||
plus_button.add (*w);
|
||||
w = manage (new Image (Stock::REMOVE, ICON_SIZE_BUTTON));
|
||||
w->show ();
|
||||
minus_button.add (*w);
|
||||
|
||||
hbox1.pack_start (bc, true, true);
|
||||
|
||||
hbox2.set_homogeneous (false);
|
||||
hbox2.set_spacing (12);
|
||||
hbox2.pack_start (reset_button);
|
||||
hbox2.pack_start (minus_button);
|
||||
hbox2.pack_start (plus_button);
|
||||
hbox2.pack_start (units_combo, true, true);
|
||||
|
||||
minus_button.signal_clicked().connect (bind (mem_fun (*this, &LatencyGUI::change_latency_from_button), -1));
|
||||
plus_button.signal_clicked().connect (bind (mem_fun (*this, &LatencyGUI::change_latency_from_button), 1));
|
||||
reset_button.signal_clicked().connect (mem_fun (*this, &LatencyGUI::reset));
|
||||
|
||||
adjustment.signal_value_changed().connect (mem_fun (*this, &LatencyGUI::finish));
|
||||
|
||||
bc.set_size_request (-1, 25);
|
||||
bc.set_style (BarController::LeftToRight);
|
||||
bc.set_use_parent (true);
|
||||
bc.set_name (X_("PluginSlider"));
|
||||
|
||||
set_spacing (12);
|
||||
pack_start (hbox1, true, true);
|
||||
pack_start (hbox2, true, true);
|
||||
}
|
||||
|
||||
void
|
||||
LatencyGUI::finish ()
|
||||
{
|
||||
nframes64_t new_value = (nframes64_t) adjustment.get_value();
|
||||
if (new_value != initial_value) {
|
||||
_latent.set_user_latency (new_value);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LatencyGUI::reset ()
|
||||
{
|
||||
_latent.set_user_latency (0);
|
||||
adjustment.set_value (initial_value);
|
||||
}
|
||||
|
||||
void
|
||||
LatencyGUI::refresh ()
|
||||
{
|
||||
initial_value = _latent.signal_latency();
|
||||
adjustment.set_value (initial_value);
|
||||
}
|
||||
|
||||
void
|
||||
LatencyGUI::change_latency_from_button (int dir)
|
||||
{
|
||||
Glib::ustring unitstr = units_combo.get_active_text();
|
||||
double shift;
|
||||
|
||||
if (unitstr == unit_strings[0]) {
|
||||
shift = 1;
|
||||
} else if (unitstr == unit_strings[1]) {
|
||||
shift = (sample_rate / 1000.0);
|
||||
} else if (unitstr == unit_strings[2]) {
|
||||
shift = period_size;
|
||||
} else {
|
||||
fatal << string_compose (_("programming error: %1 (%2)"), X_("illegal string in latency GUI units combo"), unitstr)
|
||||
<< endmsg;
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
if (dir > 0) {
|
||||
adjustment.set_value (adjustment.get_value() + shift);
|
||||
} else {
|
||||
adjustment.set_value (adjustment.get_value() - shift);
|
||||
}
|
||||
}
|
||||
|
||||
LatencyDialog::LatencyDialog (const Glib::ustring& title, Latent& l, nframes64_t sr, nframes64_t psz)
|
||||
: ArdourDialog (title, false, true),
|
||||
lwidget (l, sr, psz)
|
||||
{
|
||||
|
||||
get_vbox()->pack_start (lwidget);
|
||||
add_button (Stock::CANCEL, RESPONSE_CANCEL);
|
||||
add_button (Stock::APPLY, RESPONSE_REJECT);
|
||||
add_button (Stock::OK, RESPONSE_ACCEPT);
|
||||
|
||||
show_all ();
|
||||
|
||||
while (true) {
|
||||
int ret = run ();
|
||||
|
||||
switch (ret) {
|
||||
case RESPONSE_ACCEPT:
|
||||
return;
|
||||
break;
|
||||
|
||||
case RESPONSE_REJECT:
|
||||
lwidget.finish ();
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <gtkmm/dialog.h>
|
||||
#include <gtkmm/box.h>
|
||||
#include <gtkmm/button.h>
|
||||
#include <gtkmm/adjustment.h>
|
||||
|
||||
#include <gtkmm2ext/barcontroller.h>
|
||||
#include <pbd/controllable.h>
|
||||
|
||||
#include <ardour/types.h>
|
||||
|
||||
#include "ardour_dialog.h"
|
||||
|
||||
namespace ARDOUR {
|
||||
class Latent;
|
||||
}
|
||||
|
||||
class LatencyGUI : public Gtk::VBox
|
||||
{
|
||||
public:
|
||||
LatencyGUI (ARDOUR::Latent&, nframes64_t sample_rate, nframes64_t period_size);
|
||||
~LatencyGUI() { }
|
||||
|
||||
void finish ();
|
||||
void reset ();
|
||||
void refresh ();
|
||||
|
||||
private:
|
||||
ARDOUR::Latent& _latent;
|
||||
nframes64_t initial_value;
|
||||
nframes64_t sample_rate;
|
||||
nframes64_t period_size;
|
||||
PBD::IgnorableControllable ignored;
|
||||
|
||||
Gtk::Adjustment adjustment;
|
||||
Gtkmm2ext::BarController bc;
|
||||
Gtk::HBox hbox1;
|
||||
Gtk::HBox hbox2;
|
||||
Gtk::HButtonBox hbbox;
|
||||
Gtk::Button minus_button;
|
||||
Gtk::Button plus_button;
|
||||
Gtk::Button reset_button;
|
||||
Gtk::ComboBoxText units_combo;
|
||||
|
||||
void change_latency_from_button (int dir);
|
||||
void latency_printer (char* buf, unsigned int bufsize);
|
||||
|
||||
static std::vector<std::string> unit_strings;
|
||||
};
|
||||
|
||||
class LatencyDialog : public ArdourDialog
|
||||
{
|
||||
public:
|
||||
LatencyDialog (const Glib::ustring& title, ARDOUR::Latent&, nframes64_t sample_rate, nframes64_t period_size);
|
||||
~LatencyDialog() {}
|
||||
|
||||
private:
|
||||
LatencyGUI lwidget;
|
||||
};
|
|
@ -984,6 +984,11 @@ MixerStrip::build_route_ops_menu ()
|
|||
items.push_back (CheckMenuElem (_("Active"), mem_fun (*this, &RouteUI::toggle_route_active)));
|
||||
route_active_menu_item = dynamic_cast<CheckMenuItem *> (&items.back());
|
||||
route_active_menu_item->set_active (_route->active());
|
||||
|
||||
items.push_back (SeparatorElem());
|
||||
|
||||
items.push_back (MenuElem (_("Adjust latency"), mem_fun (*this, &RouteUI::adjust_latency)));
|
||||
|
||||
items.push_back (SeparatorElem());
|
||||
items.push_back (CheckMenuElem (_("Invert Polarity"), mem_fun (*this, &RouteUI::toggle_polarity)));
|
||||
polarity_menu_item = dynamic_cast<CheckMenuItem *> (&items.back());
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <glibmm/thread.h>
|
||||
#include <gtkmm2ext/utils.h>
|
||||
|
@ -58,7 +60,9 @@ using namespace sigc;
|
|||
|
||||
RouteParams_UI::RouteParams_UI ()
|
||||
: ArdourDialog ("track/bus inspector"),
|
||||
latency_apply_button (Stock::APPLY),
|
||||
track_menu(0)
|
||||
|
||||
{
|
||||
pre_insert_box = 0;
|
||||
post_insert_box = 0;
|
||||
|
@ -66,12 +70,14 @@ RouteParams_UI::RouteParams_UI ()
|
|||
_output_iosel = 0;
|
||||
_active_pre_view = 0;
|
||||
_active_post_view = 0;
|
||||
|
||||
latency_widget = 0;
|
||||
|
||||
using namespace Notebook_Helpers;
|
||||
|
||||
input_frame.set_shadow_type(Gtk::SHADOW_NONE);
|
||||
output_frame.set_shadow_type(Gtk::SHADOW_NONE);
|
||||
|
||||
latency_frame.set_shadow_type (Gtk::SHADOW_NONE);
|
||||
|
||||
notebook.set_show_tabs (true);
|
||||
notebook.set_show_border (true);
|
||||
notebook.set_name ("RouteParamNotebook");
|
||||
|
@ -92,7 +98,6 @@ RouteParams_UI::RouteParams_UI ()
|
|||
route_select_scroller.add(route_display);
|
||||
route_select_scroller.set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
|
||||
|
||||
|
||||
route_select_frame.set_name("RouteSelectBaseFrame");
|
||||
route_select_frame.set_shadow_type (Gtk::SHADOW_IN);
|
||||
route_select_frame.add(route_select_scroller);
|
||||
|
@ -103,12 +108,17 @@ RouteParams_UI::RouteParams_UI ()
|
|||
notebook.pages().push_back (TabElem (output_frame, _("Outputs")));
|
||||
notebook.pages().push_back (TabElem (pre_redir_hpane, _("Pre-fader Redirects")));
|
||||
notebook.pages().push_back (TabElem (post_redir_hpane, _("Post-fader Redirects")));
|
||||
notebook.pages().push_back (TabElem (latency_frame, _("Latency")));
|
||||
|
||||
notebook.set_name ("InspectorNotebook");
|
||||
|
||||
title_label.set_name ("RouteParamsTitleLabel");
|
||||
update_title();
|
||||
|
||||
latency_packer.set_spacing (18);
|
||||
latency_button_box.pack_start (latency_apply_button);
|
||||
delay_label.set_alignment (0, 0.5);
|
||||
|
||||
// changeable area
|
||||
route_param_frame.set_name("RouteParamsBaseFrame");
|
||||
route_param_frame.set_shadow_type (Gtk::SHADOW_IN);
|
||||
|
@ -116,7 +126,6 @@ RouteParams_UI::RouteParams_UI ()
|
|||
|
||||
route_hpacker.pack_start (notebook, true, true);
|
||||
|
||||
|
||||
route_vpacker.pack_start (title_label, false, false);
|
||||
route_vpacker.pack_start (route_hpacker, true, true);
|
||||
|
||||
|
@ -142,6 +151,7 @@ RouteParams_UI::RouteParams_UI ()
|
|||
title += _("Track/Bus Inspector");
|
||||
set_title (title.get_string());
|
||||
|
||||
|
||||
// events
|
||||
route_display.get_selection()->signal_changed().connect(mem_fun(*this, &RouteParams_UI::route_selected));
|
||||
route_display.get_column(0)->signal_clicked().connect(mem_fun(*this, &RouteParams_UI::show_track_menu));
|
||||
|
@ -252,6 +262,55 @@ RouteParams_UI::cleanup_processor_boxes()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
RouteParams_UI::refresh_latency ()
|
||||
{
|
||||
if (latency_widget) {
|
||||
latency_widget->refresh();
|
||||
|
||||
char buf[128];
|
||||
snprintf (buf, sizeof (buf), _("Playback delay: %u samples"), _route->initial_delay());
|
||||
delay_label.set_text (buf);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RouteParams_UI::cleanup_latency_frame ()
|
||||
{
|
||||
if (latency_widget) {
|
||||
latency_frame.remove ();
|
||||
latency_packer.remove (*latency_widget);
|
||||
latency_packer.remove (latency_button_box);
|
||||
latency_packer.remove (delay_label);
|
||||
delete latency_widget;
|
||||
latency_widget = 0;
|
||||
latency_conn.disconnect ();
|
||||
delay_conn.disconnect ();
|
||||
latency_apply_conn.disconnect ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RouteParams_UI::setup_latency_frame ()
|
||||
{
|
||||
latency_widget = new LatencyGUI (*(_route.get()), session->frame_rate(), session->engine().frames_per_cycle());
|
||||
|
||||
char buf[128];
|
||||
snprintf (buf, sizeof (buf), _("Playback delay: %u samples"), _route->initial_delay());
|
||||
delay_label.set_text (buf);
|
||||
|
||||
latency_packer.pack_start (*latency_widget, false, false);
|
||||
latency_packer.pack_start (latency_button_box, false, false);
|
||||
latency_packer.pack_start (delay_label);
|
||||
|
||||
latency_apply_conn = latency_apply_button.signal_clicked().connect (mem_fun (*latency_widget, &LatencyGUI::finish));
|
||||
latency_conn = _route->signal_latency_changed.connect (mem_fun (*this, &RouteParams_UI::refresh_latency));
|
||||
delay_conn = _route->initial_delay_changed.connect (mem_fun (*this, &RouteParams_UI::refresh_latency));
|
||||
|
||||
latency_frame.add (latency_packer);
|
||||
latency_frame.show_all ();
|
||||
}
|
||||
|
||||
void
|
||||
RouteParams_UI::setup_io_frames()
|
||||
{
|
||||
|
@ -387,6 +446,7 @@ RouteParams_UI::session_gone ()
|
|||
cleanup_pre_view();
|
||||
cleanup_post_view();
|
||||
cleanup_processor_boxes();
|
||||
cleanup_latency_frame ();
|
||||
|
||||
_route.reset ((Route*) 0);
|
||||
_pre_processor.reset ((Processor*) 0);
|
||||
|
@ -402,6 +462,7 @@ RouteParams_UI::route_selected()
|
|||
{
|
||||
Glib::RefPtr<TreeSelection> selection = route_display.get_selection();
|
||||
TreeModel::iterator iter = selection->get_selected(); // only used with Gtk::SELECTION_SINGLE
|
||||
|
||||
if(iter) {
|
||||
//If anything is selected
|
||||
boost::shared_ptr<Route> route = (*iter)[route_display_columns.route] ;
|
||||
|
@ -419,6 +480,7 @@ RouteParams_UI::route_selected()
|
|||
cleanup_pre_view();
|
||||
cleanup_post_view();
|
||||
cleanup_io_frames();
|
||||
cleanup_latency_frame ();
|
||||
}
|
||||
|
||||
// update the other panes with the correct info
|
||||
|
@ -427,6 +489,7 @@ RouteParams_UI::route_selected()
|
|||
|
||||
setup_io_frames();
|
||||
setup_processor_boxes();
|
||||
setup_latency_frame ();
|
||||
|
||||
// bind to redirects changed event for this route
|
||||
_route_conn = route->processors_changed.connect (mem_fun(*this, &RouteParams_UI::processors_changed));
|
||||
|
@ -434,6 +497,7 @@ RouteParams_UI::route_selected()
|
|||
track_input_label.set_text (_route->name());
|
||||
|
||||
update_title();
|
||||
|
||||
} else {
|
||||
// no selection
|
||||
if (_route) {
|
||||
|
@ -444,6 +508,7 @@ RouteParams_UI::route_selected()
|
|||
cleanup_pre_view();
|
||||
cleanup_post_view();
|
||||
cleanup_processor_boxes();
|
||||
cleanup_latency_frame ();
|
||||
|
||||
_route.reset ((Route*) 0);
|
||||
_pre_processor.reset ((Processor*) 0);
|
||||
|
@ -454,52 +519,19 @@ RouteParams_UI::route_selected()
|
|||
}
|
||||
}
|
||||
|
||||
//void
|
||||
//RouteParams_UI::route_unselected (gint row, gint col, GdkEvent *ev)
|
||||
//{
|
||||
// if (_route) {
|
||||
// _route_conn.disconnect();
|
||||
|
||||
// remove from view
|
||||
// cleanup_io_frames();
|
||||
// cleanup_pre_view();
|
||||
// cleanup_post_view();
|
||||
// cleanup_processor_boxes();
|
||||
|
||||
// _route.reset ((Route*)0);
|
||||
// _pre_processor = 0;
|
||||
// _post_processor = 0;
|
||||
// track_input_label.set_text(_("NO TRACK"));
|
||||
// update_title();
|
||||
// }
|
||||
//}
|
||||
|
||||
void
|
||||
RouteParams_UI::processors_changed ()
|
||||
|
||||
{
|
||||
ENSURE_GUI_THREAD(mem_fun(*this, &RouteParams_UI::processors_changed));
|
||||
|
||||
// pre_insert_list.freeze ();
|
||||
// pre_insert_list.clear ();
|
||||
// post_insert_list.freeze ();
|
||||
// post_insert_list.clear ();
|
||||
// if (_route) {
|
||||
// _route->foreach_redirect (this, &RouteParams_UI::add_redirect_to_display);
|
||||
// }
|
||||
// pre_insert_list.thaw ();
|
||||
// post_insert_list.thaw ();
|
||||
|
||||
cleanup_pre_view();
|
||||
cleanup_post_view();
|
||||
|
||||
_pre_processor.reset ((Processor*) 0);
|
||||
_post_processor.reset ((Processor*) 0);
|
||||
|
||||
//update_title();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
RouteParams_UI::show_track_menu()
|
||||
{
|
||||
|
@ -515,8 +547,6 @@ RouteParams_UI::show_track_menu()
|
|||
track_menu->popup (1, gtk_get_current_event_time());
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
RouteParams_UI::redirect_selected (boost::shared_ptr<ARDOUR::Processor> insert, ARDOUR::Placement place)
|
||||
{
|
||||
|
@ -658,7 +688,7 @@ RouteParams_UI::update_title ()
|
|||
// }
|
||||
|
||||
title_label.set_text(_route->name());
|
||||
|
||||
|
||||
title += _route->name();
|
||||
|
||||
set_title(title.get_string());
|
||||
|
@ -670,7 +700,6 @@ RouteParams_UI::update_title ()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RouteParams_UI::start_updating ()
|
||||
{
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "ardour_dialog.h"
|
||||
#include "processor_box.h"
|
||||
#include "route_processor_selection.h"
|
||||
#include "latency_gui.h"
|
||||
|
||||
namespace ARDOUR {
|
||||
class Route;
|
||||
|
@ -83,7 +84,7 @@ class RouteParams_UI : public ArdourDialog
|
|||
Gtk::Frame output_frame;
|
||||
Gtk::HPaned pre_redir_hpane;
|
||||
Gtk::HPaned post_redir_hpane;
|
||||
|
||||
|
||||
Gtk::Frame route_select_frame;
|
||||
|
||||
Gtk::HBox route_hpacker;
|
||||
|
@ -102,7 +103,18 @@ class RouteParams_UI : public ArdourDialog
|
|||
|
||||
Gtk::VBox choice_vpacker;
|
||||
|
||||
Gtk::Frame latency_frame;
|
||||
Gtk::VBox latency_packer;
|
||||
Gtk::HButtonBox latency_button_box;
|
||||
Gtk::Button latency_apply_button;
|
||||
LatencyGUI* latency_widget;
|
||||
Gtk::Label delay_label;
|
||||
sigc::connection latency_conn;
|
||||
sigc::connection delay_conn;
|
||||
sigc::connection latency_apply_conn;
|
||||
|
||||
void refresh_latency ();
|
||||
|
||||
Gtk::ToggleButton input_button;
|
||||
Gtk::ToggleButton output_button;
|
||||
Gtk::Label track_input_label;
|
||||
|
@ -168,8 +180,8 @@ class RouteParams_UI : public ArdourDialog
|
|||
void cleanup_io_frames();
|
||||
void cleanup_pre_view(bool stopupdate = true);
|
||||
void cleanup_post_view(bool stopupdate = true);
|
||||
|
||||
|
||||
void cleanup_latency_frame ();
|
||||
void setup_latency_frame ();
|
||||
|
||||
void processors_changed ();
|
||||
|
||||
|
|
|
@ -22,17 +22,21 @@
|
|||
#include <gtkmm2ext/choice.h>
|
||||
#include <gtkmm2ext/doi.h>
|
||||
#include <gtkmm2ext/bindable_button.h>
|
||||
#include <gtkmm2ext/barcontroller.h>
|
||||
|
||||
#include <ardour/route_group.h>
|
||||
#include <pbd/memento_command.h>
|
||||
#include <pbd/stacktrace.h>
|
||||
#include <pbd/shiva.h>
|
||||
#include <pbd/controllable.h>
|
||||
|
||||
#include "route_ui.h"
|
||||
#include "keyboard.h"
|
||||
#include "utils.h"
|
||||
#include "prompter.h"
|
||||
#include "gui_thread.h"
|
||||
#include "ardour_dialog.h"
|
||||
#include "latency_gui.h"
|
||||
|
||||
#include <ardour/route.h>
|
||||
#include <ardour/session.h>
|
||||
|
@ -451,7 +455,7 @@ RouteUI::update_rec_display ()
|
|||
rec_enable_button->set_active (model);
|
||||
ignore_toggle = false;
|
||||
}
|
||||
|
||||
|
||||
/* now make sure its color state is correct */
|
||||
|
||||
if (model) {
|
||||
|
@ -1040,3 +1044,8 @@ RouteUI::map_frozen ()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
RouteUI::adjust_latency ()
|
||||
{
|
||||
LatencyDialog dialog (_route->name() + _("latency"), *(_route.get()), _session.frame_rate(), _session.engine().frames_per_cycle());
|
||||
}
|
||||
|
|
|
@ -163,6 +163,8 @@ class RouteUI : public virtual AxisView
|
|||
|
||||
void reversibly_apply_route_boolean (string name, void (ARDOUR::Route::*func)(bool, void*), bool, void *);
|
||||
void reversibly_apply_track_boolean (string name, void (ARDOUR::Track::*func)(bool, void*), bool, void *);
|
||||
|
||||
void adjust_latency ();
|
||||
};
|
||||
|
||||
#endif /* __ardour_route_ui__ */
|
||||
|
|
|
@ -199,6 +199,25 @@ def CheckJackVideoFrameOffset(context):
|
|||
context.Result(result)
|
||||
return result
|
||||
|
||||
|
||||
#
|
||||
# See if JACK supports jack_recompute_total_latency() (single port version)
|
||||
#
|
||||
|
||||
jack_port_latency_test = """
|
||||
#include <jack/jack.h>
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
jack_recompute_total_latency ((jack_client_t*) 0, (jack_port_t*) 0);
|
||||
return 0;
|
||||
}
|
||||
"""
|
||||
def CheckJackRecomputeLatency(context):
|
||||
context.Message('Checking for jack_recompute_total_latency()...')
|
||||
result = context.TryLink(jack_port_latency_test, '.c')
|
||||
context.Result(result)
|
||||
return result
|
||||
|
||||
#
|
||||
# See if JACK supports jack_port_ensure_monitor_input()
|
||||
#
|
||||
|
@ -223,6 +242,7 @@ def CheckJackEnsureMonitorInput(context):
|
|||
conf = Configure(ardour, custom_tests = {
|
||||
'CheckJackClientOpen' : CheckJackClientOpen,
|
||||
'CheckJackRecomputeLatencies' : CheckJackRecomputeLatencies,
|
||||
'CheckJackRecomputeLatency' : CheckJackRecomputeLatency,
|
||||
'CheckJackVideoFrameOffset' : CheckJackVideoFrameOffset,
|
||||
'CheckJackEnsureMonitorInput' : CheckJackEnsureMonitorInput
|
||||
})
|
||||
|
@ -233,6 +253,9 @@ if conf.CheckJackClientOpen():
|
|||
if conf.CheckJackRecomputeLatencies():
|
||||
ardour.Append(CXXFLAGS="-DHAVE_JACK_RECOMPUTE_LATENCIES")
|
||||
|
||||
if conf.CheckJackRecomputeLatency():
|
||||
ardour.Append(CXXFLAGS="-DHAVE_JACK_RECOMPUTE_LATENCY")
|
||||
|
||||
if conf.CheckJackVideoFrameOffset():
|
||||
ardour.Append(CXXFLAGS="-DHAVE_JACK_VIDEO_SUPPORT")
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ class AUPlugin : public ARDOUR::Plugin
|
|||
const char * maker () const;
|
||||
uint32_t parameter_count () const;
|
||||
float default_value (uint32_t port);
|
||||
nframes_t latency () const;
|
||||
nframes_t signal_latency () const;
|
||||
void set_parameter (uint32_t which, float val);
|
||||
float get_parameter (uint32_t which) const;
|
||||
|
||||
|
|
|
@ -139,6 +139,7 @@ class AudioEngine : public sigc::trackable
|
|||
|
||||
nframes_t get_port_total_latency (const Port&);
|
||||
void update_total_latencies ();
|
||||
void update_total_latency (const Port&);
|
||||
|
||||
/** Caller may not delete the object pointed to by the return value
|
||||
*/
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include <ardour/data_type.h>
|
||||
#include <ardour/port_set.h>
|
||||
#include <ardour/chan_count.h>
|
||||
#include <ardour/latent.h>
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
@ -64,7 +65,8 @@ class BufferSet;
|
|||
* An IO can contain ports of varying types, making routes/inserts/etc with
|
||||
* varied combinations of types (eg MIDI and audio) possible.
|
||||
*/
|
||||
class IO : public Automatable
|
||||
|
||||
class IO : public Automatable, public Latent
|
||||
{
|
||||
public:
|
||||
static const string state_node_name;
|
||||
|
@ -141,9 +143,12 @@ class IO : public Automatable
|
|||
int disconnect_inputs (void *src);
|
||||
int disconnect_outputs (void *src);
|
||||
|
||||
nframes_t signal_latency() const { return _own_latency; }
|
||||
nframes_t output_latency() const;
|
||||
nframes_t input_latency() const;
|
||||
void set_port_latency (nframes_t);
|
||||
void set_port_latency (nframes_t);
|
||||
|
||||
void update_port_total_latencies ();
|
||||
|
||||
const PortSet& inputs() const { return _inputs; }
|
||||
const PortSet& outputs() const { return _outputs; }
|
||||
|
|
|
@ -59,7 +59,7 @@ class LadspaPlugin : public ARDOUR::Plugin
|
|||
const char * maker() const { return descriptor->Maker; }
|
||||
uint32_t parameter_count() const { return descriptor->PortCount; }
|
||||
float default_value (uint32_t port);
|
||||
nframes_t latency() const;
|
||||
nframes_t signal_latency() const;
|
||||
void set_parameter (uint32_t port, float val);
|
||||
float get_parameter (uint32_t port) const;
|
||||
int get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const;
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
#ifndef __ardour_latent_h__
|
||||
#define __ardour_latent_h__
|
||||
|
||||
#include <ardour/types.h>
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
class Latent {
|
||||
public:
|
||||
Latent() : _own_latency (0), _user_latency (0) {}
|
||||
virtual ~Latent() {}
|
||||
|
||||
virtual nframes_t signal_latency() const = 0;
|
||||
nframes_t user_latency () const { return _user_latency; }
|
||||
|
||||
virtual void set_latency_delay (nframes_t val) { _own_latency = val; }
|
||||
virtual void set_user_latency (nframes_t val) { _user_latency = val; }
|
||||
|
||||
protected:
|
||||
nframes_t _own_latency;
|
||||
nframes_t _user_latency;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* __ardour_latent_h__*/
|
|
@ -31,6 +31,7 @@
|
|||
#include <ardour/chan_count.h>
|
||||
#include <ardour/plugin_state.h>
|
||||
#include <ardour/cycles.h>
|
||||
#include <ardour/latent.h>
|
||||
#include <ardour/param_id.h>
|
||||
|
||||
#include <vector>
|
||||
|
@ -79,7 +80,7 @@ class PluginInfo {
|
|||
typedef boost::shared_ptr<PluginInfo> PluginInfoPtr;
|
||||
typedef std::list<PluginInfoPtr> PluginInfoList;
|
||||
|
||||
class Plugin : public PBD::StatefulDestructible
|
||||
class Plugin : public PBD::StatefulDestructible, public Latent
|
||||
{
|
||||
public:
|
||||
Plugin (ARDOUR::AudioEngine&, ARDOUR::Session&);
|
||||
|
@ -110,7 +111,6 @@ class Plugin : public PBD::StatefulDestructible
|
|||
virtual const char * maker() const = 0;
|
||||
virtual uint32_t parameter_count () const = 0;
|
||||
virtual float default_value (uint32_t port) = 0;
|
||||
virtual nframes_t latency() const = 0;
|
||||
virtual void set_parameter (uint32_t which, float val) = 0;
|
||||
virtual float get_parameter(uint32_t which) const = 0;
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ class PluginInsert : public Processor
|
|||
|
||||
string describe_parameter (ParamID param);
|
||||
|
||||
nframes_t latency();
|
||||
nframes_t signal_latency() const;
|
||||
|
||||
void transport_stopped (nframes_t now);
|
||||
void automation_snapshot (nframes_t now);
|
||||
|
|
|
@ -54,7 +54,7 @@ class PortInsert : public IOProcessor
|
|||
|
||||
void run (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset);
|
||||
|
||||
nframes_t latency();
|
||||
nframes_t signal_latency() const;
|
||||
|
||||
ChanCount output_streams() const;
|
||||
ChanCount input_streams() const;
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#include <ardour/plugin_state.h>
|
||||
#include <ardour/buffer_set.h>
|
||||
#include <ardour/automatable.h>
|
||||
|
||||
#include <ardour/latent.h>
|
||||
|
||||
class XMLNode;
|
||||
|
||||
|
@ -43,7 +43,7 @@ class Session;
|
|||
|
||||
/* A mixer strip element - plugin, send, meter, etc.
|
||||
*/
|
||||
class Processor : public Automatable
|
||||
class Processor : public Automatable, public Latent
|
||||
{
|
||||
public:
|
||||
static const string state_node_name;
|
||||
|
@ -66,7 +66,7 @@ class Processor : public Automatable
|
|||
bool get_next_ab_is_active () const { return _next_ab_is_active; }
|
||||
void set_next_ab_is_active (bool yn) { _next_ab_is_active = yn; }
|
||||
|
||||
virtual nframes_t latency() { return 0; }
|
||||
virtual nframes_t signal_latency() const { return 0; }
|
||||
|
||||
virtual void transport_stopped (nframes_t frame) {}
|
||||
|
||||
|
|
|
@ -187,8 +187,9 @@ class Route : public IO
|
|||
void all_processors_active (Placement, bool state);
|
||||
|
||||
virtual nframes_t update_total_latency();
|
||||
nframes_t signal_latency() const { return _own_latency; }
|
||||
virtual void set_latency_delay (nframes_t);
|
||||
void set_latency_delay (nframes_t);
|
||||
void set_user_latency (nframes_t);
|
||||
nframes_t initial_delay() const { return _initial_delay; }
|
||||
|
||||
sigc::signal<void,void*> solo_changed;
|
||||
sigc::signal<void,void*> solo_safe_changed;
|
||||
|
@ -204,6 +205,8 @@ class Route : public IO
|
|||
sigc::signal<void,void*> mix_group_changed;
|
||||
sigc::signal<void> active_changed;
|
||||
sigc::signal<void,void*> meter_change;
|
||||
sigc::signal<void> signal_latency_changed;
|
||||
sigc::signal<void> initial_delay_changed;
|
||||
|
||||
/* gui's call this for their own purposes. */
|
||||
|
||||
|
@ -294,7 +297,6 @@ class Route : public IO
|
|||
|
||||
nframes_t _initial_delay;
|
||||
nframes_t _roll_delay;
|
||||
nframes_t _own_latency;
|
||||
ProcessorList _processors;
|
||||
Glib::RWLock _processor_lock;
|
||||
IO *_control_outs;
|
||||
|
|
|
@ -62,7 +62,7 @@ class VSTPlugin : public ARDOUR::Plugin
|
|||
const char * maker() const;
|
||||
uint32_t parameter_count() const;
|
||||
float default_value (uint32_t port);
|
||||
nframes_t latency() const;
|
||||
nframes_t signal_latency() const;
|
||||
void set_parameter (uint32_t port, float val);
|
||||
float get_parameter (uint32_t port) const;
|
||||
int get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const;
|
||||
|
|
|
@ -113,8 +113,12 @@ AUPlugin::default_value (uint32_t port)
|
|||
}
|
||||
|
||||
nframes_t
|
||||
AUPlugin::latency () const
|
||||
AUPlugin::signal_latency () const
|
||||
{
|
||||
if (_user_latency) {
|
||||
return _user_latency;
|
||||
}
|
||||
|
||||
return unit->Latency ();
|
||||
}
|
||||
|
||||
|
|
|
@ -931,6 +931,27 @@ AudioEngine::get_port_total_latency (const Port& port)
|
|||
return jack_port_get_total_latency (_jack, port._port);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioEngine::update_total_latency (const Port& port)
|
||||
{
|
||||
if (!_jack) {
|
||||
fatal << _("update_total_latency() called with no JACK client connection") << endmsg;
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
if (!_running) {
|
||||
if (!_has_run) {
|
||||
fatal << _("update_total_latency() called before engine was started") << endmsg;
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_JACK_RECOMPUTE_LATENCY
|
||||
jack_recompute_total_latency (_jack, port._port);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
AudioEngine::transport_stop ()
|
||||
{
|
||||
|
|
|
@ -1899,7 +1899,7 @@ IO::input_latency () const
|
|||
for (PortSet::const_iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
|
||||
if ((latency = _session.engine().get_port_total_latency (*i)) > max_latency) {
|
||||
max_latency = latency;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return max_latency;
|
||||
|
@ -2411,4 +2411,16 @@ IO::set_denormal_protection (bool yn, void *src)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
IO::update_port_total_latencies ()
|
||||
{
|
||||
/* io_lock, not taken: function must be called from Session::process() calltree */
|
||||
|
||||
for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
|
||||
_session.engine().update_total_latency (*i);
|
||||
}
|
||||
|
||||
for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
|
||||
_session.engine().update_total_latency (*i);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -491,7 +491,6 @@ LadspaPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor& des
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
string
|
||||
LadspaPlugin::describe_parameter (ParamID which)
|
||||
{
|
||||
|
@ -503,8 +502,12 @@ LadspaPlugin::describe_parameter (ParamID which)
|
|||
}
|
||||
|
||||
ARDOUR::nframes_t
|
||||
LadspaPlugin::latency () const
|
||||
LadspaPlugin::signal_latency () const
|
||||
{
|
||||
if (_user_latency) {
|
||||
return _user_latency;
|
||||
}
|
||||
|
||||
if (latency_control_port) {
|
||||
return (nframes_t) floor (*latency_control_port);
|
||||
} else {
|
||||
|
|
|
@ -836,11 +836,15 @@ PluginInsert::describe_parameter (ParamID param)
|
|||
}
|
||||
|
||||
ARDOUR::nframes_t
|
||||
PluginInsert::latency()
|
||||
PluginInsert::signal_latency() const
|
||||
{
|
||||
return _plugins[0]->latency ();
|
||||
if (_user_latency) {
|
||||
return _user_latency;
|
||||
}
|
||||
|
||||
return _plugins[0]->signal_latency ();
|
||||
}
|
||||
|
||||
|
||||
ARDOUR::PluginType
|
||||
PluginInsert::type ()
|
||||
{
|
||||
|
@ -870,4 +874,3 @@ PluginInsert::type ()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -160,7 +160,7 @@ PortInsert::set_state(const XMLNode& node)
|
|||
}
|
||||
|
||||
ARDOUR::nframes_t
|
||||
PortInsert::latency()
|
||||
PortInsert::signal_latency() const
|
||||
{
|
||||
/* because we deliver and collect within the same cycle,
|
||||
all I/O is necessarily delayed by at least frames_per_cycle().
|
||||
|
|
|
@ -89,6 +89,7 @@ Route::init ()
|
|||
_initial_delay = 0;
|
||||
_roll_delay = 0;
|
||||
_own_latency = 0;
|
||||
_user_latency = 0;
|
||||
_have_internal_generator = false;
|
||||
_declickable = false;
|
||||
_pending_declick = true;
|
||||
|
@ -812,6 +813,8 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams*
|
|||
|
||||
processor->activate ();
|
||||
processor->ActiveChanged.connect (bind (mem_fun (_session, &Session::update_latency_compensation), false, false));
|
||||
|
||||
_user_latency = 0;
|
||||
}
|
||||
|
||||
if (processor_max_outs != old_rmo || old_rmo == ChanCount::ZERO) {
|
||||
|
@ -867,6 +870,8 @@ Route::add_processors (const ProcessorList& others, ProcessorStreams* err)
|
|||
(*i)->activate ();
|
||||
(*i)->ActiveChanged.connect (bind (mem_fun (_session, &Session::update_latency_compensation), false, false));
|
||||
}
|
||||
|
||||
_user_latency = 0;
|
||||
}
|
||||
|
||||
if (processor_max_outs != old_rmo || old_rmo == ChanCount::ZERO) {
|
||||
|
@ -1098,6 +1103,8 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
|
|||
removed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
_user_latency = 0;
|
||||
}
|
||||
|
||||
if (!removed) {
|
||||
|
@ -1337,6 +1344,7 @@ Route::copy_processors (const Route& other, Placement placement, ProcessorStream
|
|||
|
||||
/* SUCCESSFUL COPY ATTEMPT: delete the processors we removed pre-copy */
|
||||
to_be_deleted.clear ();
|
||||
_user_latency = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2470,32 +2478,62 @@ Route::set_meter_point (MeterPoint p, void *src)
|
|||
nframes_t
|
||||
Route::update_total_latency ()
|
||||
{
|
||||
_own_latency = 0;
|
||||
nframes_t old = _own_latency;
|
||||
|
||||
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
|
||||
if ((*i)->active ()) {
|
||||
_own_latency += (*i)->latency ();
|
||||
if (_user_latency) {
|
||||
_own_latency = _user_latency;
|
||||
} else {
|
||||
_own_latency = 0;
|
||||
|
||||
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
|
||||
if ((*i)->active ()) {
|
||||
_own_latency += (*i)->signal_latency ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set_port_latency (_own_latency);
|
||||
|
||||
if (!_user_latency) {
|
||||
/* this (virtual) function is used for pure Routes,
|
||||
not derived classes like AudioTrack. this means
|
||||
that the data processed here comes from an input
|
||||
port, not prerecorded material, and therefore we
|
||||
have to take into account any input latency.
|
||||
*/
|
||||
|
||||
/* this (virtual) function is used for pure Routes,
|
||||
not derived classes like AudioTrack. this means
|
||||
that the data processed here comes from an input
|
||||
port, not prerecorded material, and therefore we
|
||||
have to take into account any input latency.
|
||||
*/
|
||||
|
||||
_own_latency += input_latency ();
|
||||
_own_latency += input_latency ();
|
||||
}
|
||||
|
||||
if (old != _own_latency) {
|
||||
signal_latency_changed (); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
return _own_latency;
|
||||
}
|
||||
|
||||
void
|
||||
Route::set_user_latency (nframes_t nframes)
|
||||
{
|
||||
Latent::set_user_latency (nframes);
|
||||
_session.update_latency_compensation (false, false);
|
||||
}
|
||||
|
||||
void
|
||||
Route::set_latency_delay (nframes_t longest_session_latency)
|
||||
{
|
||||
_initial_delay = longest_session_latency - _own_latency;
|
||||
nframes_t old = _initial_delay;
|
||||
|
||||
if (_own_latency < longest_session_latency) {
|
||||
_initial_delay = longest_session_latency - _own_latency;
|
||||
} else {
|
||||
_initial_delay = 0;
|
||||
}
|
||||
|
||||
if (_initial_delay != old) {
|
||||
initial_delay_changed (); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
if (_session.transport_stopped()) {
|
||||
_roll_delay = _initial_delay;
|
||||
|
|
|
@ -1248,33 +1248,33 @@ Session::update_latency_compensation (bool with_stop, bool abort)
|
|||
boost::shared_ptr<RouteList> r = routes.reader ();
|
||||
|
||||
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
||||
|
||||
if (with_stop) {
|
||||
(*i)->handle_transport_stopped (abort, (post_transport_work & PostTransportLocate),
|
||||
(!(post_transport_work & PostTransportLocate) || pending_locate_flush));
|
||||
}
|
||||
|
||||
|
||||
nframes_t old_latency = (*i)->signal_latency ();
|
||||
nframes_t track_latency = (*i)->update_total_latency ();
|
||||
|
||||
|
||||
if (old_latency != track_latency) {
|
||||
(*i)->update_port_total_latencies ();
|
||||
update_jack = true;
|
||||
}
|
||||
|
||||
if (!(*i)->hidden() && ((*i)->active())) {
|
||||
|
||||
if (!(*i)->hidden() && ((*i)->active())) {
|
||||
_worst_track_latency = max (_worst_track_latency, track_latency);
|
||||
}
|
||||
}
|
||||
|
||||
if (update_jack) {
|
||||
_engine.update_total_latencies ();
|
||||
}
|
||||
|
||||
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
||||
(*i)->set_latency_delay (_worst_track_latency);
|
||||
}
|
||||
|
||||
/* tell JACK to play catch up */
|
||||
|
||||
if (update_jack) {
|
||||
_engine.update_total_latencies ();
|
||||
}
|
||||
|
||||
set_worst_io_latencies ();
|
||||
|
||||
/* reflect any changes in latencies into capture offsets
|
||||
|
|
|
@ -90,20 +90,29 @@ Track::toggle_monitor_input ()
|
|||
ARDOUR::nframes_t
|
||||
Track::update_total_latency ()
|
||||
{
|
||||
_own_latency = 0;
|
||||
nframes_t old = _own_latency;
|
||||
|
||||
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
|
||||
if ((*i)->active ()) {
|
||||
_own_latency += (*i)->latency ();
|
||||
if (_user_latency) {
|
||||
_own_latency = _user_latency;
|
||||
} else {
|
||||
_own_latency = 0;
|
||||
|
||||
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
|
||||
if ((*i)->active ()) {
|
||||
_own_latency += (*i)->signal_latency ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set_port_latency (_own_latency);
|
||||
|
||||
if (old != _own_latency) {
|
||||
signal_latency_changed (); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
return _own_latency;
|
||||
}
|
||||
|
||||
|
||||
Track::FreezeRecord::~FreezeRecord ()
|
||||
{
|
||||
for (vector<FreezeRecordProcessorInfo*>::iterator i = processor_info.begin(); i != processor_info.end(); ++i) {
|
||||
|
|
|
@ -351,8 +351,12 @@ VSTPlugin::describe_parameter (uint32_t param)
|
|||
}
|
||||
|
||||
nframes_t
|
||||
VSTPlugin::latency () const
|
||||
VSTPlugin::signal_latency () const
|
||||
{
|
||||
if (_user_latency) {
|
||||
return _user_latency;
|
||||
}
|
||||
|
||||
return _plugin->initialDelay;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ get_files_in_directory (const sys::path& directory_path, vector<string>& result)
|
|||
}
|
||||
catch (Glib::FileError& err)
|
||||
{
|
||||
warning << err.what();
|
||||
warning << err.what() << endmsg;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,6 +113,7 @@ find_file_in_search_path(const SearchPath& search_path,
|
|||
return false;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (tmp.size() != 1)
|
||||
{
|
||||
info << string_compose
|
||||
|
@ -123,6 +124,7 @@ find_file_in_search_path(const SearchPath& search_path,
|
|||
)
|
||||
<< endmsg;
|
||||
}
|
||||
#endif
|
||||
|
||||
result = tmp.front();
|
||||
|
||||
|
|
|
@ -70,6 +70,21 @@ class Controllable : public PBD::StatefulDestructible {
|
|||
static Controllables registry;
|
||||
};
|
||||
|
||||
/* a utility class for the occasions when you need but do not have
|
||||
a Controllable
|
||||
*/
|
||||
|
||||
class IgnorableControllable : public Controllable
|
||||
{
|
||||
public:
|
||||
IgnorableControllable () : PBD::Controllable ("ignoreMe") {}
|
||||
~IgnorableControllable () {}
|
||||
|
||||
void set_value (float v){}
|
||||
float get_value () const { return 0.0; }
|
||||
bool can_send_feedback () const { return false; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* __pbd_controllable_h__ */
|
||||
|
|
Loading…
Reference in New Issue