mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-06 14:54:56 +01:00
Insert/Redirect refactoring, towards better MIDI support in mixer strip, and
http://ardour.org/node/1043 style things. git-svn-id: svn://localhost/ardour2/trunk@2027 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
05184ed52f
commit
49ee64ada7
77 changed files with 2052 additions and 1948 deletions
|
|
@ -106,8 +106,8 @@ AudioTimeAxisView::AudioTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
|
|||
|
||||
/* map current state of the route */
|
||||
|
||||
redirects_changed (0);
|
||||
reset_redirect_automation_curves ();
|
||||
inserts_changed ();
|
||||
reset_insert_automation_curves ();
|
||||
|
||||
ensure_xml_node ();
|
||||
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ IOSelector::IOSelector (Session& sess, boost::shared_ptr<IO> ior, bool input)
|
|||
io->output_changed.connect (mem_fun(*this, &IOSelector::ports_changed));
|
||||
}
|
||||
|
||||
io->name_changed.connect (mem_fun(*this, &IOSelector::name_changed));
|
||||
io->NameChanged.connect (mem_fun(*this, &IOSelector::name_changed));
|
||||
}
|
||||
|
||||
IOSelector::~IOSelector ()
|
||||
|
|
@ -298,9 +298,9 @@ IOSelector::set_button_sensitivity ()
|
|||
|
||||
|
||||
void
|
||||
IOSelector::name_changed (void* src)
|
||||
IOSelector::name_changed ()
|
||||
{
|
||||
ENSURE_GUI_THREAD(bind (mem_fun(*this, &IOSelector::name_changed), src));
|
||||
ENSURE_GUI_THREAD(mem_fun(*this, &IOSelector::name_changed));
|
||||
|
||||
display_ports ();
|
||||
}
|
||||
|
|
@ -765,8 +765,8 @@ IOSelector::redisplay ()
|
|||
}
|
||||
|
||||
PortInsertUI::PortInsertUI (Session& sess, boost::shared_ptr<PortInsert> pi)
|
||||
: input_selector (sess, pi, true),
|
||||
output_selector (sess, pi, false)
|
||||
: input_selector (sess, pi->io(), true),
|
||||
output_selector (sess, pi->io(), false)
|
||||
{
|
||||
hbox.pack_start (output_selector, true, true);
|
||||
hbox.pack_start (input_selector, true, true);
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ class IOSelector : public Gtk::VBox {
|
|||
bool port_selection_changed(GdkEventButton *, Gtk::TreeView*);
|
||||
|
||||
void ports_changed (ARDOUR::IOChange, void *);
|
||||
void name_changed (void*);
|
||||
void name_changed ();
|
||||
|
||||
void add_port ();
|
||||
void remove_port ();
|
||||
|
|
|
|||
|
|
@ -103,7 +103,8 @@ LadspaPluginUI::LadspaPluginUI (boost::shared_ptr<PluginInsert> pi, bool scrolla
|
|||
pack_start (hpacker, false, false);
|
||||
}
|
||||
|
||||
insert->active_changed.connect (mem_fun(*this, &LadspaPluginUI::redirect_active_changed));
|
||||
insert->ActiveChanged.connect (bind(mem_fun(*this, &LadspaPluginUI::insert_active_changed),
|
||||
boost::weak_ptr<Insert>(insert)));
|
||||
bypass_button.set_active (!insert->active());
|
||||
|
||||
build ();
|
||||
|
|
@ -671,11 +672,13 @@ LadspaPluginUI::control_combo_changed (ControlUI* cui)
|
|||
}
|
||||
|
||||
void
|
||||
LadspaPluginUI::redirect_active_changed (Redirect* r, void* src)
|
||||
LadspaPluginUI::insert_active_changed (boost::weak_ptr<Insert> weak_insert)
|
||||
{
|
||||
ENSURE_GUI_THREAD(bind (mem_fun(*this, &LadspaPluginUI::redirect_active_changed), r, src));
|
||||
ENSURE_GUI_THREAD(bind (mem_fun(*this, &LadspaPluginUI::insert_active_changed), weak_insert));
|
||||
|
||||
bypass_button.set_active (!r->active());
|
||||
boost::shared_ptr<Insert> insert = weak_insert.lock();
|
||||
|
||||
bypass_button.set_active (!insert || !insert->active());
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -98,13 +98,13 @@ MidiTimeAxisView::MidiTimeAxisView (PublicEditor& ed, Session& sess, boost::shar
|
|||
|
||||
/* map current state of the route */
|
||||
|
||||
redirects_changed (0);
|
||||
inserts_changed ();
|
||||
|
||||
ensure_xml_node ();
|
||||
|
||||
set_state (*xml_node);
|
||||
|
||||
_route->redirects_changed.connect (mem_fun(*this, &MidiTimeAxisView::redirects_changed));
|
||||
_route->inserts_changed.connect (mem_fun(*this, &MidiTimeAxisView::inserts_changed));
|
||||
|
||||
if (is_track()) {
|
||||
|
||||
|
|
@ -174,25 +174,6 @@ MidiTimeAxisView::set_state (const XMLNode& node)
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME: duplicated in audio_time_axis.cc
|
||||
/*static string
|
||||
legalize_for_xml_node (string str)
|
||||
{
|
||||
string::size_type pos;
|
||||
string legal_chars = "abcdefghijklmnopqrtsuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_+=:";
|
||||
string legal;
|
||||
|
||||
legal = str;
|
||||
pos = 0;
|
||||
|
||||
while ((pos = legal.find_first_not_of (legal_chars, pos)) != string::npos) {
|
||||
legal.replace (pos, 1, "_");
|
||||
pos += 1;
|
||||
}
|
||||
|
||||
return legal;
|
||||
}*/
|
||||
|
||||
void
|
||||
MidiTimeAxisView::route_active_changed ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -44,21 +44,13 @@ namespace ARDOUR {
|
|||
class Session;
|
||||
class MidiDiskstream;
|
||||
class RouteGroup;
|
||||
class Redirect;
|
||||
class Insert;
|
||||
class Insert;
|
||||
class Location;
|
||||
class MidiPlaylist;
|
||||
}
|
||||
|
||||
class PublicEditor;
|
||||
class Selection;
|
||||
class Selectable;
|
||||
class AutomationLine;
|
||||
class AutomationGainLine;
|
||||
class AutomationPanLine;
|
||||
class RedirectAutomationLine;
|
||||
class TimeSelection;
|
||||
class AutomationTimeAxisView;
|
||||
|
||||
class MidiTimeAxisView : public RouteTimeAxisView
|
||||
{
|
||||
|
|
@ -76,9 +68,7 @@ class MidiTimeAxisView : public RouteTimeAxisView
|
|||
private:
|
||||
void route_active_changed ();
|
||||
|
||||
//void redirects_changed (void *); FIXME?
|
||||
|
||||
void add_redirect_to_subplugin_menu (ARDOUR::Redirect *);
|
||||
void add_insert_to_subplugin_menu (ARDOUR::Insert *);
|
||||
|
||||
Gtk::Menu subplugin_menu;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -303,7 +303,7 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr<Route> rt
|
|||
get_diskstream()->SpeedChanged.connect (mem_fun(*this, &MixerStrip::speed_changed));
|
||||
}
|
||||
|
||||
_route->name_changed.connect (mem_fun(*this, &RouteUI::name_changed));
|
||||
_route->NameChanged.connect (mem_fun(*this, &RouteUI::name_changed));
|
||||
_route->comment_changed.connect (mem_fun(*this, &MixerStrip::comment_changed));
|
||||
_route->gui_changed.connect (mem_fun(*this, &MixerStrip::route_gui_changed));
|
||||
|
||||
|
|
@ -336,7 +336,7 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr<Route> rt
|
|||
post_redirect_box.update();
|
||||
mute_changed (0);
|
||||
solo_changed (0);
|
||||
name_changed (0);
|
||||
name_changed ();
|
||||
comment_changed (0);
|
||||
mix_group_changed (0);
|
||||
|
||||
|
|
@ -469,7 +469,7 @@ MixerStrip::set_width (Width w, void* owner)
|
|||
update_input_display ();
|
||||
update_output_display ();
|
||||
mix_group_changed (0);
|
||||
name_changed (0);
|
||||
name_changed ();
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1078,11 +1078,11 @@ MixerStrip::set_selected (bool yn)
|
|||
}
|
||||
|
||||
void
|
||||
MixerStrip::name_changed (void *src)
|
||||
MixerStrip::name_changed ()
|
||||
{
|
||||
switch (_width) {
|
||||
case Wide:
|
||||
RouteUI::name_changed (src);
|
||||
RouteUI::name_changed ();
|
||||
break;
|
||||
case Narrow:
|
||||
name_label.set_text (PBD::short_version (_route->name(), 5));
|
||||
|
|
@ -1149,13 +1149,13 @@ MixerStrip::map_frozen ()
|
|||
break;
|
||||
}
|
||||
}
|
||||
_route->foreach_redirect (this, &MixerStrip::hide_redirect_editor);
|
||||
_route->foreach_insert (this, &MixerStrip::hide_insert_editor);
|
||||
}
|
||||
|
||||
void
|
||||
MixerStrip::hide_redirect_editor (boost::shared_ptr<Redirect> redirect)
|
||||
MixerStrip::hide_insert_editor (boost::shared_ptr<Insert> insert)
|
||||
{
|
||||
void* gui = redirect->get_gui ();
|
||||
void* gui = insert->get_gui ();
|
||||
|
||||
if (gui) {
|
||||
static_cast<Gtk::Widget*>(gui)->hide ();
|
||||
|
|
|
|||
|
|
@ -236,10 +236,10 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
|
|||
|
||||
void speed_adjustment_changed ();
|
||||
void speed_changed ();
|
||||
void name_changed (void *src);
|
||||
void name_changed ();
|
||||
void update_speed_display ();
|
||||
void map_frozen ();
|
||||
void hide_redirect_editor (boost::shared_ptr<ARDOUR::Redirect> redirect);
|
||||
void hide_insert_editor (boost::shared_ptr<ARDOUR::Insert> insert);
|
||||
|
||||
bool ignore_speed_adjustment;
|
||||
|
||||
|
|
|
|||
|
|
@ -292,7 +292,7 @@ Mixer_UI::add_strip (Session::RouteList& routes)
|
|||
no_track_list_redisplay = false;
|
||||
redisplay_track_list ();
|
||||
|
||||
route->name_changed.connect (bind (mem_fun(*this, &Mixer_UI::strip_name_changed), strip));
|
||||
route->NameChanged.connect (bind (mem_fun(*this, &Mixer_UI::strip_name_changed), strip));
|
||||
strip->GoingAway.connect (bind (mem_fun(*this, &Mixer_UI::remove_strip), strip));
|
||||
|
||||
strip->signal_button_release_event().connect (bind (mem_fun(*this, &Mixer_UI::strip_button_release_event), strip));
|
||||
|
|
@ -738,9 +738,9 @@ Mixer_UI::build_track_menu ()
|
|||
}
|
||||
|
||||
void
|
||||
Mixer_UI::strip_name_changed (void* src, MixerStrip* mx)
|
||||
Mixer_UI::strip_name_changed (MixerStrip* mx)
|
||||
{
|
||||
ENSURE_GUI_THREAD(bind (mem_fun(*this, &Mixer_UI::strip_name_changed), src, mx));
|
||||
ENSURE_GUI_THREAD(bind (mem_fun(*this, &Mixer_UI::strip_name_changed), mx));
|
||||
|
||||
TreeModel::Children rows = track_model->children();
|
||||
TreeModel::Children::iterator i;
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ class Mixer_UI : public Gtk::Window
|
|||
|
||||
PluginSelector *_plugin_selector;
|
||||
|
||||
void strip_name_changed (void *src, MixerStrip *);
|
||||
void strip_name_changed (MixerStrip *);
|
||||
|
||||
void group_flags_changed (void *src, ARDOUR::RouteGroup *);
|
||||
|
||||
|
|
|
|||
|
|
@ -208,6 +208,6 @@ PlugUIBase::bypass_toggled ()
|
|||
bool x;
|
||||
|
||||
if ((x = bypass_button.get_active()) == insert->active()) {
|
||||
insert->set_active (!x, this);
|
||||
insert->set_active (!x);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ class LadspaPluginUI : public PlugUIBase, public Gtk::VBox
|
|||
void control_port_toggled (ControlUI* cui);
|
||||
void control_combo_changed (ControlUI* cui);
|
||||
|
||||
void redirect_active_changed (ARDOUR::Redirect*, void*);
|
||||
void insert_active_changed (boost::weak_ptr<ARDOUR::Insert>);
|
||||
|
||||
void astate_clicked (ControlUI*, uint32_t parameter);
|
||||
void automation_state_changed (ControlUI*);
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ using namespace std;
|
|||
using namespace ARDOUR;
|
||||
using namespace PBD;
|
||||
|
||||
RedirectAutomationLine::RedirectAutomationLine (const string & name, Redirect& rd, uint32_t port, Session& s,
|
||||
RedirectAutomationLine::RedirectAutomationLine (const string & name, Insert& i, uint32_t port, Session& s,
|
||||
|
||||
TimeAxisView& tv, ArdourCanvas::Group& parent,
|
||||
|
||||
|
|
@ -41,16 +41,16 @@ RedirectAutomationLine::RedirectAutomationLine (const string & name, Redirect& r
|
|||
|
||||
: AutomationLine (name, tv, parent, l),
|
||||
session (s),
|
||||
_redirect (rd),
|
||||
_insert (i),
|
||||
_port (port)
|
||||
{
|
||||
set_verbose_cursor_uses_gain_mapping (false);
|
||||
set_verbose_cursor_uses_gain_mapping (false);
|
||||
|
||||
PluginInsert *pi;
|
||||
Plugin::ParameterDescriptor desc;
|
||||
|
||||
if ((pi = dynamic_cast<PluginInsert*>(&_redirect)) == 0) {
|
||||
fatal << _("redirect automation created for non-plugin") << endmsg;
|
||||
if ((pi = dynamic_cast<PluginInsert*>(&_insert)) == 0) {
|
||||
fatal << _("insert automation created for non-plugin") << endmsg;
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
namespace ARDOUR {
|
||||
class Session;
|
||||
class Redirect;
|
||||
class Insert;
|
||||
}
|
||||
|
||||
class TimeAxisView;
|
||||
|
|
@ -34,17 +34,17 @@ class TimeAxisView;
|
|||
class RedirectAutomationLine : public AutomationLine
|
||||
{
|
||||
public:
|
||||
RedirectAutomationLine (const string & name, ARDOUR::Redirect&, uint32_t port, ARDOUR::Session&, TimeAxisView&,
|
||||
RedirectAutomationLine (const string & name, ARDOUR::Insert&, uint32_t port, ARDOUR::Session&, TimeAxisView&,
|
||||
ArdourCanvas::Group& parent, ARDOUR::AutomationList&);
|
||||
|
||||
uint32_t port() const { return _port; }
|
||||
ARDOUR::Redirect& redirect() const { return _redirect; }
|
||||
ARDOUR::Insert& insert() const { return _insert; }
|
||||
|
||||
string get_verbose_cursor_string (float);
|
||||
|
||||
private:
|
||||
ARDOUR::Session& session;
|
||||
ARDOUR::Redirect& _redirect;
|
||||
ARDOUR::Insert& _insert;
|
||||
uint32_t _port;
|
||||
float upper;
|
||||
float lower;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
*/
|
||||
|
||||
#include <ardour/redirect.h>
|
||||
#include <ardour/insert.h>
|
||||
#include <ardour/session.h>
|
||||
#include <cstdlib>
|
||||
#include <pbd/memento_command.h>
|
||||
|
|
@ -34,11 +34,11 @@ using namespace Gtk;
|
|||
|
||||
RedirectAutomationTimeAxisView::RedirectAutomationTimeAxisView (Session& s, boost::shared_ptr<Route> r,
|
||||
PublicEditor& e, TimeAxisView& parent, Canvas& canvas, std::string n,
|
||||
uint32_t prt, Redirect& rd, string state_name)
|
||||
uint32_t prt, Insert& i, string state_name)
|
||||
|
||||
: AxisView (s),
|
||||
AutomationTimeAxisView (s, r, e, parent, canvas, n, state_name, rd.name()),
|
||||
redirect (rd),
|
||||
AutomationTimeAxisView (s, r, e, parent, canvas, n, state_name, i.name()),
|
||||
insert (i),
|
||||
port (prt)
|
||||
|
||||
{
|
||||
|
|
@ -91,9 +91,9 @@ RedirectAutomationTimeAxisView::add_automation_event (ArdourCanvas::Item* item,
|
|||
/* map to model space */
|
||||
|
||||
if (!lines.empty()) {
|
||||
AutomationList& alist (redirect.automation_list(port));
|
||||
AutomationList& alist (insert.automation_list(port));
|
||||
string description = _("add automation event to ");
|
||||
description += redirect.describe_parameter (port);
|
||||
description += insert.describe_parameter (port);
|
||||
|
||||
lines.front()->view_to_model_y (y);
|
||||
|
||||
|
|
@ -111,9 +111,9 @@ void
|
|||
RedirectAutomationTimeAxisView::ensure_xml_node ()
|
||||
{
|
||||
if (xml_node == 0) {
|
||||
if ((xml_node = redirect.extra_xml ("GUI")) == 0) {
|
||||
if ((xml_node = insert.extra_xml ("GUI")) == 0) {
|
||||
xml_node = new XMLNode ("GUI");
|
||||
redirect.add_extra_xml (*xml_node);
|
||||
insert.add_extra_xml (*xml_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -168,6 +168,6 @@ void
|
|||
RedirectAutomationTimeAxisView::set_automation_state (AutoState state)
|
||||
{
|
||||
if (!ignore_state_request) {
|
||||
redirect.automation_list (port).set_automation_state (state);
|
||||
insert.automation_list (port).set_automation_state (state);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ class RedirectAutomationTimeAxisView : public AutomationTimeAxisView
|
|||
ArdourCanvas::Canvas& canvas,
|
||||
std::string name,
|
||||
uint32_t port,
|
||||
ARDOUR::Redirect& rd,
|
||||
ARDOUR::Insert& i,
|
||||
std::string state_name);
|
||||
|
||||
~RedirectAutomationTimeAxisView();
|
||||
|
|
@ -51,7 +51,7 @@ class RedirectAutomationTimeAxisView : public AutomationTimeAxisView
|
|||
|
||||
|
||||
private:
|
||||
ARDOUR::Redirect& redirect;
|
||||
ARDOUR::Insert& insert;
|
||||
uint32_t port;
|
||||
|
||||
XMLNode *xml_node;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -62,6 +62,8 @@ namespace ARDOUR {
|
|||
class Session;
|
||||
}
|
||||
|
||||
|
||||
// FIXME: change name to InsertBox
|
||||
class RedirectBox : public Gtk::HBox
|
||||
{
|
||||
public:
|
||||
|
|
@ -73,14 +75,13 @@ class RedirectBox : public Gtk::HBox
|
|||
|
||||
void update();
|
||||
|
||||
void select_all_redirects ();
|
||||
void deselect_all_redirects ();
|
||||
void select_all_plugins ();
|
||||
void select_all_inserts ();
|
||||
void deselect_all_inserts ();
|
||||
void select_all_plugins ();
|
||||
void select_all_sends ();
|
||||
|
||||
sigc::signal<void,boost::shared_ptr<ARDOUR::Redirect> > RedirectSelected;
|
||||
sigc::signal<void,boost::shared_ptr<ARDOUR::Redirect> > RedirectUnselected;
|
||||
sigc::signal<void,boost::shared_ptr<ARDOUR::Insert> > InsertSelected;
|
||||
sigc::signal<void,boost::shared_ptr<ARDOUR::Insert> > InsertUnselected;
|
||||
|
||||
static void register_actions();
|
||||
|
||||
|
|
@ -103,11 +104,11 @@ class RedirectBox : public Gtk::HBox
|
|||
struct ModelColumns : public Gtk::TreeModel::ColumnRecord {
|
||||
ModelColumns () {
|
||||
add (text);
|
||||
add (redirect);
|
||||
add (insert);
|
||||
add (color);
|
||||
}
|
||||
Gtk::TreeModelColumn<std::string> text;
|
||||
Gtk::TreeModelColumn<boost::shared_ptr<ARDOUR::Redirect> > redirect;
|
||||
Gtk::TreeModelColumn<boost::shared_ptr<ARDOUR::Insert> > insert;
|
||||
Gtk::TreeModelColumn<Gdk::Color> color;
|
||||
};
|
||||
|
||||
|
|
@ -117,15 +118,15 @@ class RedirectBox : public Gtk::HBox
|
|||
void selection_changed ();
|
||||
|
||||
static bool get_colors;
|
||||
static Gdk::Color* active_redirect_color;
|
||||
static Gdk::Color* inactive_redirect_color;
|
||||
static Gdk::Color* active_insert_color;
|
||||
static Gdk::Color* inactive_insert_color;
|
||||
|
||||
Gtk::EventBox redirect_eventbox;
|
||||
Gtk::HBox redirect_hpacker;
|
||||
Gtkmm2ext::DnDTreeView<boost::shared_ptr<ARDOUR::Redirect> > redirect_display;
|
||||
Gtk::ScrolledWindow redirect_scroller;
|
||||
Gtk::EventBox insert_eventbox;
|
||||
Gtk::HBox insert_hpacker;
|
||||
Gtkmm2ext::DnDTreeView<boost::shared_ptr<ARDOUR::Insert> > insert_display;
|
||||
Gtk::ScrolledWindow insert_scroller;
|
||||
|
||||
void object_drop (std::string type, uint32_t cnt, const boost::shared_ptr<ARDOUR::Redirect>*);
|
||||
void object_drop (std::string type, uint32_t cnt, const boost::shared_ptr<ARDOUR::Insert>*);
|
||||
|
||||
Width _width;
|
||||
|
||||
|
|
@ -135,72 +136,71 @@ class RedirectBox : public Gtk::HBox
|
|||
void new_send ();
|
||||
void show_send_controls ();
|
||||
|
||||
Gtk::Menu *redirect_menu;
|
||||
gint redirect_menu_map_handler (GdkEventAny *ev);
|
||||
Gtk::Menu * build_redirect_menu ();
|
||||
void build_redirect_tooltip (Gtk::EventBox&, string);
|
||||
void show_redirect_menu (gint arg);
|
||||
Gtk::Menu *insert_menu;
|
||||
gint insert_menu_map_handler (GdkEventAny *ev);
|
||||
Gtk::Menu * build_insert_menu ();
|
||||
void build_insert_tooltip (Gtk::EventBox&, string);
|
||||
void show_insert_menu (gint arg);
|
||||
|
||||
void choose_send ();
|
||||
void send_io_finished (IOSelector::Result, boost::weak_ptr<ARDOUR::Redirect>, IOSelectorWindow*);
|
||||
void send_io_finished (IOSelector::Result, boost::shared_ptr<ARDOUR::Send>, IOSelectorWindow*);
|
||||
void choose_insert ();
|
||||
void choose_plugin ();
|
||||
void insert_plugin_chosen (boost::shared_ptr<ARDOUR::Plugin>);
|
||||
|
||||
bool no_redirect_redisplay;
|
||||
bool no_insert_redisplay;
|
||||
bool ignore_delete;
|
||||
|
||||
bool redirect_button_press_event (GdkEventButton *);
|
||||
bool redirect_button_release_event (GdkEventButton *);
|
||||
void redisplay_redirects (void* src);
|
||||
void add_redirect_to_display (boost::shared_ptr<ARDOUR::Redirect>);
|
||||
bool insert_button_press_event (GdkEventButton *);
|
||||
bool insert_button_release_event (GdkEventButton *);
|
||||
void redisplay_inserts ();
|
||||
void add_insert_to_display (boost::shared_ptr<ARDOUR::Insert>);
|
||||
void row_deleted (const Gtk::TreeModel::Path& path);
|
||||
void show_redirect_active_r (ARDOUR::Redirect*, void *, boost::weak_ptr<ARDOUR::Redirect>);
|
||||
void show_redirect_active (boost::weak_ptr<ARDOUR::Redirect>);
|
||||
void show_redirect_name (void* src, boost::weak_ptr<ARDOUR::Redirect>);
|
||||
string redirect_name (boost::weak_ptr<ARDOUR::Redirect>);
|
||||
void show_insert_active (boost::weak_ptr<ARDOUR::Insert>);
|
||||
void show_insert_name (boost::weak_ptr<ARDOUR::Insert>);
|
||||
string insert_name (boost::weak_ptr<ARDOUR::Insert>);
|
||||
|
||||
void remove_redirect_gui (boost::shared_ptr<ARDOUR::Redirect>);
|
||||
void remove_insert_gui (boost::shared_ptr<ARDOUR::Insert>);
|
||||
|
||||
void redirects_reordered (const Gtk::TreeModel::Path&, const Gtk::TreeModel::iterator&, int*);
|
||||
void compute_redirect_sort_keys ();
|
||||
vector<sigc::connection> redirect_active_connections;
|
||||
vector<sigc::connection> redirect_name_connections;
|
||||
void inserts_reordered (const Gtk::TreeModel::Path&, const Gtk::TreeModel::iterator&, int*);
|
||||
void compute_insert_sort_keys ();
|
||||
vector<sigc::connection> insert_active_connections;
|
||||
vector<sigc::connection> insert_name_connections;
|
||||
|
||||
bool redirect_drag_in_progress;
|
||||
void redirect_drag_begin (GdkDragContext*);
|
||||
void redirect_drag_end (GdkDragContext*);
|
||||
void all_redirects_active(bool state);
|
||||
bool insert_drag_in_progress;
|
||||
void insert_drag_begin (GdkDragContext*);
|
||||
void insert_drag_end (GdkDragContext*);
|
||||
void all_inserts_active(bool state);
|
||||
void all_plugins_active(bool state);
|
||||
void ab_plugins ();
|
||||
|
||||
void cut_redirects ();
|
||||
void copy_redirects ();
|
||||
void paste_redirects ();
|
||||
void delete_redirects ();
|
||||
void clear_redirects ();
|
||||
void clone_redirects ();
|
||||
void rename_redirects ();
|
||||
void cut_inserts ();
|
||||
void copy_inserts ();
|
||||
void paste_inserts ();
|
||||
void delete_inserts ();
|
||||
void clear_inserts ();
|
||||
void clone_inserts ();
|
||||
void rename_inserts ();
|
||||
|
||||
void for_selected_redirects (void (RedirectBox::*pmf)(boost::shared_ptr<ARDOUR::Redirect>));
|
||||
void get_selected_redirects (vector<boost::shared_ptr<ARDOUR::Redirect> >&);
|
||||
void for_selected_inserts (void (RedirectBox::*pmf)(boost::shared_ptr<ARDOUR::Insert>));
|
||||
void get_selected_inserts (vector<boost::shared_ptr<ARDOUR::Insert> >&);
|
||||
|
||||
static Glib::RefPtr<Gtk::Action> paste_action;
|
||||
void paste_redirect_list (std::list<boost::shared_ptr<ARDOUR::Redirect> >& redirects);
|
||||
void paste_insert_list (std::list<boost::shared_ptr<ARDOUR::Insert> >& inserts);
|
||||
|
||||
void activate_redirect (boost::shared_ptr<ARDOUR::Redirect>);
|
||||
void deactivate_redirect (boost::shared_ptr<ARDOUR::Redirect>);
|
||||
void cut_redirect (boost::shared_ptr<ARDOUR::Redirect>);
|
||||
void copy_redirect (boost::shared_ptr<ARDOUR::Redirect>);
|
||||
void edit_redirect (boost::shared_ptr<ARDOUR::Redirect>);
|
||||
void hide_redirect_editor (boost::shared_ptr<ARDOUR::Redirect>);
|
||||
void rename_redirect (boost::shared_ptr<ARDOUR::Redirect>);
|
||||
void activate_insert (boost::shared_ptr<ARDOUR::Insert>);
|
||||
void deactivate_insert (boost::shared_ptr<ARDOUR::Insert>);
|
||||
void cut_insert (boost::shared_ptr<ARDOUR::Insert>);
|
||||
void copy_insert (boost::shared_ptr<ARDOUR::Insert>);
|
||||
void edit_insert (boost::shared_ptr<ARDOUR::Insert>);
|
||||
void hide_insert_editor (boost::shared_ptr<ARDOUR::Insert>);
|
||||
void rename_insert (boost::shared_ptr<ARDOUR::Insert>);
|
||||
|
||||
gint idle_delete_redirect (boost::weak_ptr<ARDOUR::Redirect>);
|
||||
gint idle_delete_insert (boost::weak_ptr<ARDOUR::Insert>);
|
||||
|
||||
void weird_plugin_dialog (ARDOUR::Plugin& p, ARDOUR::Route::InsertStreams streams, boost::shared_ptr<ARDOUR::IO> io);
|
||||
|
||||
static RedirectBox* _current_redirect_box;
|
||||
static RedirectBox* _current_insert_box;
|
||||
static bool enter_box (GdkEventCrossing*, RedirectBox*);
|
||||
static bool leave_box (GdkEventCrossing*, RedirectBox*);
|
||||
|
||||
|
|
@ -223,8 +223,8 @@ class RedirectBox : public Gtk::HBox
|
|||
static void rb_ab_plugins ();
|
||||
static void rb_deactivate_plugins ();
|
||||
|
||||
void route_name_changed (void* src, PluginUIWindow* plugin_ui, boost::weak_ptr<ARDOUR::PluginInsert> pi);
|
||||
std::string generate_redirect_title (boost::shared_ptr<ARDOUR::PluginInsert> pi);
|
||||
void route_name_changed (PluginUIWindow* plugin_ui, boost::weak_ptr<ARDOUR::PluginInsert> pi);
|
||||
std::string generate_insert_title (boost::shared_ptr<ARDOUR::PluginInsert> pi);
|
||||
};
|
||||
|
||||
#endif /* __ardour_gtk_redirect_box__ */
|
||||
|
|
|
|||
|
|
@ -24,9 +24,9 @@
|
|||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace ARDOUR {
|
||||
class Redirect;
|
||||
class Insert;
|
||||
}
|
||||
|
||||
struct RedirectSelection : list<boost::shared_ptr<ARDOUR::Redirect> > {};
|
||||
struct InsertSelection : list<boost::shared_ptr<ARDOUR::Insert> > {};
|
||||
|
||||
#endif /* __ardour_gtk_redirect_selection_h__ */
|
||||
|
|
|
|||
|
|
@ -60,8 +60,8 @@ RouteParams_UI::RouteParams_UI ()
|
|||
: ArdourDialog ("track/bus inspector"),
|
||||
track_menu(0)
|
||||
{
|
||||
pre_redirect_box = 0;
|
||||
post_redirect_box = 0;
|
||||
pre_insert_box = 0;
|
||||
post_insert_box = 0;
|
||||
_input_iosel = 0;
|
||||
_output_iosel = 0;
|
||||
_active_pre_view = 0;
|
||||
|
|
@ -178,16 +178,16 @@ RouteParams_UI::add_routes (Session::RouteList& routes)
|
|||
|
||||
//route_select_list.rows().back().select ();
|
||||
|
||||
route->name_changed.connect (bind (mem_fun(*this, &RouteParams_UI::route_name_changed), route));
|
||||
route->NameChanged.connect (bind (mem_fun(*this, &RouteParams_UI::route_name_changed), route));
|
||||
route->GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::route_removed), route));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RouteParams_UI::route_name_changed (void *src, boost::shared_ptr<Route> route)
|
||||
RouteParams_UI::route_name_changed (boost::shared_ptr<Route> route)
|
||||
{
|
||||
ENSURE_GUI_THREAD(bind (mem_fun(*this, &RouteParams_UI::route_name_changed), src, route));
|
||||
ENSURE_GUI_THREAD(bind (mem_fun(*this, &RouteParams_UI::route_name_changed), route));
|
||||
|
||||
bool found = false ;
|
||||
TreeModel::Children rows = route_display_model->children();
|
||||
|
|
@ -219,16 +219,16 @@ RouteParams_UI::setup_redirect_boxes()
|
|||
cleanup_redirect_boxes();
|
||||
|
||||
// construct new redirect boxes
|
||||
pre_redirect_box = new RedirectBox(PreFader, *session, _route, *_plugin_selector, _rr_selection);
|
||||
post_redirect_box = new RedirectBox(PostFader, *session, _route, *_plugin_selector, _rr_selection);
|
||||
pre_insert_box = new RedirectBox(PreFader, *session, _route, *_plugin_selector, _rr_selection);
|
||||
post_insert_box = new RedirectBox(PostFader, *session, _route, *_plugin_selector, _rr_selection);
|
||||
|
||||
pre_redir_hpane.pack1 (*pre_redirect_box);
|
||||
post_redir_hpane.pack1 (*post_redirect_box);
|
||||
pre_redir_hpane.pack1 (*pre_insert_box);
|
||||
post_redir_hpane.pack1 (*post_insert_box);
|
||||
|
||||
pre_redirect_box->RedirectSelected.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_selected), PreFader));
|
||||
pre_redirect_box->RedirectUnselected.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_selected), PreFader));
|
||||
post_redirect_box->RedirectSelected.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_selected), PostFader));
|
||||
post_redirect_box->RedirectUnselected.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_selected), PostFader));
|
||||
pre_insert_box->InsertSelected.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_selected), PreFader));
|
||||
pre_insert_box->InsertUnselected.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_selected), PreFader));
|
||||
post_insert_box->InsertSelected.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_selected), PostFader));
|
||||
post_insert_box->InsertUnselected.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_selected), PostFader));
|
||||
|
||||
pre_redir_hpane.show_all();
|
||||
post_redir_hpane.show_all();
|
||||
|
|
@ -239,16 +239,16 @@ RouteParams_UI::setup_redirect_boxes()
|
|||
void
|
||||
RouteParams_UI::cleanup_redirect_boxes()
|
||||
{
|
||||
if (pre_redirect_box) {
|
||||
pre_redir_hpane.remove(*pre_redirect_box);
|
||||
delete pre_redirect_box;
|
||||
pre_redirect_box = 0;
|
||||
if (pre_insert_box) {
|
||||
pre_redir_hpane.remove(*pre_insert_box);
|
||||
delete pre_insert_box;
|
||||
pre_insert_box = 0;
|
||||
}
|
||||
|
||||
if (post_redirect_box) {
|
||||
post_redir_hpane.remove(*post_redirect_box);
|
||||
delete post_redirect_box;
|
||||
post_redirect_box = 0;
|
||||
if (post_insert_box) {
|
||||
post_redir_hpane.remove(*post_insert_box);
|
||||
delete post_insert_box;
|
||||
post_insert_box = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -347,8 +347,8 @@ RouteParams_UI::route_removed (boost::shared_ptr<Route> route)
|
|||
cleanup_redirect_boxes();
|
||||
|
||||
_route.reset ((Route*) 0);
|
||||
_pre_redirect.reset ((Redirect*) 0);
|
||||
_post_redirect.reset ((Redirect*) 0);
|
||||
_pre_insert.reset ((Redirect*) 0);
|
||||
_post_insert.reset ((Redirect*) 0);
|
||||
update_title();
|
||||
}
|
||||
}
|
||||
|
|
@ -389,8 +389,8 @@ RouteParams_UI::session_gone ()
|
|||
cleanup_redirect_boxes();
|
||||
|
||||
_route.reset ((Route*) 0);
|
||||
_pre_redirect.reset ((Redirect*) 0);
|
||||
_post_redirect.reset ((Redirect*) 0);
|
||||
_pre_insert.reset ((Redirect*) 0);
|
||||
_post_insert.reset ((Redirect*) 0);
|
||||
update_title();
|
||||
|
||||
ArdourDialog::session_gone();
|
||||
|
|
@ -429,7 +429,7 @@ RouteParams_UI::route_selected()
|
|||
setup_redirect_boxes();
|
||||
|
||||
// bind to redirects changed event for this route
|
||||
_route_conn = route->redirects_changed.connect (mem_fun(*this, &RouteParams_UI::redirects_changed));
|
||||
_route_conn = route->inserts_changed.connect (mem_fun(*this, &RouteParams_UI::inserts_changed));
|
||||
|
||||
track_input_label.set_text (_route->name());
|
||||
|
||||
|
|
@ -446,8 +446,8 @@ RouteParams_UI::route_selected()
|
|||
cleanup_redirect_boxes();
|
||||
|
||||
_route.reset ((Route*) 0);
|
||||
_pre_redirect.reset ((Redirect*) 0);
|
||||
_post_redirect.reset ((Redirect *) 0);
|
||||
_pre_insert.reset ((Redirect*) 0);
|
||||
_post_insert.reset ((Redirect *) 0);
|
||||
track_input_label.set_text(_("NO TRACK"));
|
||||
update_title();
|
||||
}
|
||||
|
|
@ -467,34 +467,34 @@ RouteParams_UI::route_selected()
|
|||
// cleanup_redirect_boxes();
|
||||
|
||||
// _route.reset ((Route*)0);
|
||||
// _pre_redirect = 0;
|
||||
// _post_redirect = 0;
|
||||
// _pre_insert = 0;
|
||||
// _post_insert = 0;
|
||||
// track_input_label.set_text(_("NO TRACK"));
|
||||
// update_title();
|
||||
// }
|
||||
//}
|
||||
|
||||
void
|
||||
RouteParams_UI::redirects_changed (void *src)
|
||||
RouteParams_UI::inserts_changed ()
|
||||
|
||||
{
|
||||
ENSURE_GUI_THREAD(bind (mem_fun(*this, &RouteParams_UI::redirects_changed), src));
|
||||
ENSURE_GUI_THREAD(mem_fun(*this, &RouteParams_UI::inserts_changed));
|
||||
|
||||
// pre_redirect_list.freeze ();
|
||||
// pre_redirect_list.clear ();
|
||||
// post_redirect_list.freeze ();
|
||||
// post_redirect_list.clear ();
|
||||
// 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_redirect_list.thaw ();
|
||||
// post_redirect_list.thaw ();
|
||||
// pre_insert_list.thaw ();
|
||||
// post_insert_list.thaw ();
|
||||
|
||||
cleanup_pre_view();
|
||||
cleanup_post_view();
|
||||
|
||||
_pre_redirect.reset ((Redirect*) 0);
|
||||
_post_redirect.reset ((Redirect*) 0);
|
||||
_pre_insert.reset ((Redirect*) 0);
|
||||
_post_insert.reset ((Redirect*) 0);
|
||||
//update_title();
|
||||
}
|
||||
|
||||
|
|
@ -518,98 +518,84 @@ RouteParams_UI::show_track_menu()
|
|||
|
||||
|
||||
void
|
||||
RouteParams_UI::redirect_selected (boost::shared_ptr<ARDOUR::Redirect> redirect, ARDOUR::Placement place)
|
||||
RouteParams_UI::redirect_selected (boost::shared_ptr<ARDOUR::Insert> insert, ARDOUR::Placement place)
|
||||
{
|
||||
boost::shared_ptr<Insert> insert;
|
||||
|
||||
if ((place == PreFader && _pre_redirect == redirect)
|
||||
|| (place == PostFader && _post_redirect == redirect)){
|
||||
if ((place == PreFader && _pre_insert == insert)
|
||||
|| (place == PostFader && _post_insert == insert)){
|
||||
return;
|
||||
}
|
||||
|
||||
if ((insert = boost::dynamic_pointer_cast<Insert> (redirect)) == 0) {
|
||||
boost::shared_ptr<Send> send;
|
||||
boost::shared_ptr<PluginInsert> plugin_insert;
|
||||
boost::shared_ptr<PortInsert> port_insert;
|
||||
|
||||
if ((send = boost::dynamic_pointer_cast<Send> (insert)) != 0) {
|
||||
|
||||
boost::shared_ptr<Send> send;
|
||||
|
||||
if ((send = boost::dynamic_pointer_cast<Send> (redirect)) != 0) {
|
||||
SendUI *send_ui = new SendUI (send, *session);
|
||||
|
||||
/* its a send */
|
||||
if (place == PreFader) {
|
||||
cleanup_pre_view();
|
||||
_pre_plugin_conn = send->GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_going_away), insert));
|
||||
_active_pre_view = send_ui;
|
||||
|
||||
pre_redir_hpane.add2 (*_active_pre_view);
|
||||
pre_redir_hpane.show_all();
|
||||
}
|
||||
else {
|
||||
cleanup_post_view();
|
||||
_post_plugin_conn = send->GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_going_away), insert));
|
||||
_active_post_view = send_ui;
|
||||
|
||||
post_redir_hpane.add2 (*_active_post_view);
|
||||
post_redir_hpane.show_all();
|
||||
}
|
||||
} else if ((plugin_insert = boost::dynamic_pointer_cast<PluginInsert> (insert)) != 0) {
|
||||
|
||||
SendUI *send_ui = new SendUI (send, *session);
|
||||
LadspaPluginUI *plugin_ui = new LadspaPluginUI (plugin_insert, true);
|
||||
|
||||
if (place == PreFader) {
|
||||
cleanup_pre_view();
|
||||
_pre_plugin_conn = send->GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_going_away), redirect));
|
||||
_active_pre_view = send_ui;
|
||||
|
||||
pre_redir_hpane.add2 (*_active_pre_view);
|
||||
pre_redir_hpane.show_all();
|
||||
}
|
||||
else {
|
||||
cleanup_post_view();
|
||||
_post_plugin_conn = send->GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_going_away), redirect));
|
||||
_active_post_view = send_ui;
|
||||
|
||||
post_redir_hpane.add2 (*_active_post_view);
|
||||
post_redir_hpane.show_all();
|
||||
}
|
||||
if (place == PreFader) {
|
||||
cleanup_pre_view();
|
||||
_pre_plugin_conn = plugin_insert->plugin()->GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::plugin_going_away), PreFader));
|
||||
plugin_ui->start_updating (0);
|
||||
_active_pre_view = plugin_ui;
|
||||
pre_redir_hpane.pack2 (*_active_pre_view);
|
||||
pre_redir_hpane.show_all();
|
||||
}
|
||||
else {
|
||||
cleanup_post_view();
|
||||
_post_plugin_conn = plugin_insert->plugin()->GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::plugin_going_away), PostFader));
|
||||
plugin_ui->start_updating (0);
|
||||
_active_post_view = plugin_ui;
|
||||
post_redir_hpane.pack2 (*_active_post_view);
|
||||
post_redir_hpane.show_all();
|
||||
}
|
||||
|
||||
} else {
|
||||
/* its an insert, though we don't know what kind yet. */
|
||||
} else if ((port_insert = boost::dynamic_pointer_cast<PortInsert> (insert)) != 0) {
|
||||
|
||||
boost::shared_ptr<PluginInsert> plugin_insert;
|
||||
boost::shared_ptr<PortInsert> port_insert;
|
||||
PortInsertUI *portinsert_ui = new PortInsertUI (*session, port_insert);
|
||||
|
||||
if ((plugin_insert = boost::dynamic_pointer_cast<PluginInsert> (insert)) != 0) {
|
||||
|
||||
LadspaPluginUI *plugin_ui = new LadspaPluginUI (plugin_insert, true);
|
||||
|
||||
if (place == PreFader) {
|
||||
cleanup_pre_view();
|
||||
_pre_plugin_conn = plugin_insert->plugin()->GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::plugin_going_away), PreFader));
|
||||
plugin_ui->start_updating (0);
|
||||
_active_pre_view = plugin_ui;
|
||||
pre_redir_hpane.pack2 (*_active_pre_view);
|
||||
pre_redir_hpane.show_all();
|
||||
}
|
||||
else {
|
||||
cleanup_post_view();
|
||||
_post_plugin_conn = plugin_insert->plugin()->GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::plugin_going_away), PostFader));
|
||||
plugin_ui->start_updating (0);
|
||||
_active_post_view = plugin_ui;
|
||||
post_redir_hpane.pack2 (*_active_post_view);
|
||||
post_redir_hpane.show_all();
|
||||
}
|
||||
|
||||
} else if ((port_insert = boost::dynamic_pointer_cast<PortInsert> (insert)) != 0) {
|
||||
|
||||
PortInsertUI *portinsert_ui = new PortInsertUI (*session, port_insert);
|
||||
|
||||
if (place == PreFader) {
|
||||
cleanup_pre_view();
|
||||
_pre_plugin_conn = port_insert->GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_going_away), redirect));
|
||||
_active_pre_view = portinsert_ui;
|
||||
pre_redir_hpane.pack2 (*_active_pre_view);
|
||||
portinsert_ui->redisplay();
|
||||
pre_redir_hpane.show_all();
|
||||
}
|
||||
else {
|
||||
cleanup_post_view();
|
||||
_post_plugin_conn = port_insert->GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_going_away), redirect));
|
||||
_active_post_view = portinsert_ui;
|
||||
post_redir_hpane.pack2 (*_active_post_view);
|
||||
portinsert_ui->redisplay();
|
||||
post_redir_hpane.show_all();
|
||||
}
|
||||
if (place == PreFader) {
|
||||
cleanup_pre_view();
|
||||
_pre_plugin_conn = port_insert->GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_going_away), insert));
|
||||
_active_pre_view = portinsert_ui;
|
||||
pre_redir_hpane.pack2 (*_active_pre_view);
|
||||
portinsert_ui->redisplay();
|
||||
pre_redir_hpane.show_all();
|
||||
}
|
||||
else {
|
||||
cleanup_post_view();
|
||||
_post_plugin_conn = port_insert->GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_going_away), insert));
|
||||
_active_post_view = portinsert_ui;
|
||||
post_redir_hpane.pack2 (*_active_post_view);
|
||||
portinsert_ui->redisplay();
|
||||
post_redir_hpane.show_all();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (place == PreFader) {
|
||||
_pre_redirect = redirect;
|
||||
_pre_insert = insert;
|
||||
} else {
|
||||
_post_redirect = redirect;
|
||||
_post_insert = insert;
|
||||
}
|
||||
|
||||
update_title();
|
||||
|
|
@ -625,28 +611,28 @@ RouteParams_UI::plugin_going_away (Placement place)
|
|||
|
||||
if (place == PreFader) {
|
||||
cleanup_pre_view (false);
|
||||
_pre_redirect.reset ((Redirect*) 0);
|
||||
_pre_insert.reset ((Redirect*) 0);
|
||||
}
|
||||
else {
|
||||
cleanup_post_view (false);
|
||||
_post_redirect.reset ((Redirect*) 0);
|
||||
_post_insert.reset ((Redirect*) 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RouteParams_UI::redirect_going_away (boost::shared_ptr<ARDOUR::Redirect> redirect)
|
||||
RouteParams_UI::redirect_going_away (boost::shared_ptr<ARDOUR::Insert> insert)
|
||||
|
||||
{
|
||||
ENSURE_GUI_THREAD(bind (mem_fun(*this, &RouteParams_UI::redirect_going_away), redirect));
|
||||
ENSURE_GUI_THREAD(bind (mem_fun(*this, &RouteParams_UI::redirect_going_away), insert));
|
||||
|
||||
printf ("redirect going away\n");
|
||||
// delete the current view without calling finish
|
||||
if (redirect == _pre_redirect) {
|
||||
if (insert == _pre_insert) {
|
||||
cleanup_pre_view (false);
|
||||
_pre_redirect.reset ((Redirect*) 0);
|
||||
} else if (redirect == _post_redirect) {
|
||||
_pre_insert.reset ((Redirect*) 0);
|
||||
} else if (insert == _post_insert) {
|
||||
cleanup_post_view (false);
|
||||
_post_redirect.reset ((Redirect*) 0);
|
||||
_post_insert.reset ((Redirect*) 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -89,8 +89,8 @@ class RouteParams_UI : public ArdourDialog
|
|||
Gtk::HBox route_hpacker;
|
||||
Gtk::VBox route_vpacker;
|
||||
|
||||
RedirectBox * pre_redirect_box;
|
||||
RedirectBox * post_redirect_box;
|
||||
RedirectBox * pre_insert_box;
|
||||
RedirectBox * post_insert_box;
|
||||
|
||||
Gtk::HPaned list_hpane;
|
||||
|
||||
|
|
@ -121,11 +121,11 @@ class RouteParams_UI : public ArdourDialog
|
|||
sigc::connection _route_conn;
|
||||
sigc::connection _route_ds_conn;
|
||||
|
||||
boost::shared_ptr<ARDOUR::Redirect> _pre_redirect;
|
||||
sigc::connection _pre_plugin_conn;
|
||||
boost::shared_ptr<ARDOUR::Insert> _pre_insert;
|
||||
sigc::connection _pre_plugin_conn;
|
||||
|
||||
boost::shared_ptr<ARDOUR::Redirect> _post_redirect;
|
||||
sigc::connection _post_plugin_conn;
|
||||
boost::shared_ptr<ARDOUR::Insert> _post_insert;
|
||||
sigc::connection _post_plugin_conn;
|
||||
|
||||
|
||||
enum ConfigView {
|
||||
|
|
@ -157,7 +157,7 @@ class RouteParams_UI : public ArdourDialog
|
|||
|
||||
void add_routes (ARDOUR::Session::RouteList&);
|
||||
|
||||
void route_name_changed (void *src, boost::shared_ptr<ARDOUR::Route> route);
|
||||
void route_name_changed (boost::shared_ptr<ARDOUR::Route> route);
|
||||
void route_removed (boost::shared_ptr<ARDOUR::Route> route);
|
||||
|
||||
|
||||
|
|
@ -171,15 +171,15 @@ class RouteParams_UI : public ArdourDialog
|
|||
|
||||
|
||||
|
||||
void redirects_changed (void *src);
|
||||
void inserts_changed ();
|
||||
|
||||
void setup_redirect_boxes();
|
||||
void cleanup_redirect_boxes();
|
||||
|
||||
void redirect_selected (boost::shared_ptr<ARDOUR::Redirect>, ARDOUR::Placement);
|
||||
void redirect_selected (boost::shared_ptr<ARDOUR::Insert>, ARDOUR::Placement);
|
||||
|
||||
void plugin_going_away (ARDOUR::Placement);
|
||||
void redirect_going_away (boost::shared_ptr<ARDOUR::Redirect>);
|
||||
void redirect_going_away (boost::shared_ptr<ARDOUR::Insert>);
|
||||
|
||||
gint edit_input_configuration (GdkEventButton *ev);
|
||||
gint edit_output_configuration (GdkEventButton *ev);
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
#include <pbd/error.h>
|
||||
|
||||
#include <ardour/playlist.h>
|
||||
#include <ardour/redirect.h>
|
||||
#include <ardour/insert.h>
|
||||
#include <ardour/route.h>
|
||||
|
||||
#include "route_redirect_selection.h"
|
||||
|
|
@ -37,7 +37,7 @@ RouteRedirectSelection&
|
|||
RouteRedirectSelection::operator= (const RouteRedirectSelection& other)
|
||||
{
|
||||
if (&other != this) {
|
||||
redirects = other.redirects;
|
||||
inserts = other.inserts;
|
||||
routes = other.routes;
|
||||
}
|
||||
return *this;
|
||||
|
|
@ -46,22 +46,22 @@ RouteRedirectSelection::operator= (const RouteRedirectSelection& other)
|
|||
bool
|
||||
operator== (const RouteRedirectSelection& a, const RouteRedirectSelection& b)
|
||||
{
|
||||
return a.redirects == b.redirects &&
|
||||
return a.inserts == b.inserts &&
|
||||
a.routes == b.routes;
|
||||
}
|
||||
|
||||
void
|
||||
RouteRedirectSelection::clear ()
|
||||
{
|
||||
clear_redirects ();
|
||||
clear_inserts ();
|
||||
clear_routes ();
|
||||
}
|
||||
|
||||
void
|
||||
RouteRedirectSelection::clear_redirects ()
|
||||
RouteRedirectSelection::clear_inserts ()
|
||||
{
|
||||
redirects.clear ();
|
||||
RedirectsChanged ();
|
||||
inserts.clear ();
|
||||
InsertsChanged ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -72,27 +72,27 @@ RouteRedirectSelection::clear_routes ()
|
|||
}
|
||||
|
||||
void
|
||||
RouteRedirectSelection::add (boost::shared_ptr<Redirect> r)
|
||||
RouteRedirectSelection::add (boost::shared_ptr<Insert> r)
|
||||
{
|
||||
if (find (redirects.begin(), redirects.end(), r) == redirects.end()) {
|
||||
redirects.push_back (r);
|
||||
if (find (inserts.begin(), inserts.end(), r) == inserts.end()) {
|
||||
inserts.push_back (r);
|
||||
|
||||
// XXX SHAREDPTR FIXME
|
||||
// void (RouteRedirectSelection::*pmf)(Redirect*) = &RouteRedirectSelection::remove;
|
||||
// r->GoingAway.connect (mem_fun(*this, pmf));
|
||||
|
||||
RedirectsChanged();
|
||||
InsertsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RouteRedirectSelection::add (const vector<boost::shared_ptr<Redirect> >& rlist)
|
||||
RouteRedirectSelection::add (const vector<boost::shared_ptr<Insert> >& rlist)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
for (vector<boost::shared_ptr<Redirect> >::const_iterator i = rlist.begin(); i != rlist.end(); ++i) {
|
||||
if (find (redirects.begin(), redirects.end(), *i) == redirects.end()) {
|
||||
redirects.push_back (*i);
|
||||
for (vector<boost::shared_ptr<Insert> >::const_iterator i = rlist.begin(); i != rlist.end(); ++i) {
|
||||
if (find (inserts.begin(), inserts.end(), *i) == inserts.end()) {
|
||||
inserts.push_back (*i);
|
||||
|
||||
// XXX SHAREDPTR FIXME
|
||||
|
||||
|
|
@ -103,31 +103,31 @@ RouteRedirectSelection::add (const vector<boost::shared_ptr<Redirect> >& rlist)
|
|||
}
|
||||
|
||||
if (changed) {
|
||||
RedirectsChanged();
|
||||
InsertsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RouteRedirectSelection::remove (boost::shared_ptr<Redirect> r)
|
||||
RouteRedirectSelection::remove (boost::shared_ptr<Insert> r)
|
||||
{
|
||||
list<boost::shared_ptr<Redirect> >::iterator i;
|
||||
if ((i = find (redirects.begin(), redirects.end(), r)) != redirects.end()) {
|
||||
redirects.erase (i);
|
||||
RedirectsChanged ();
|
||||
list<boost::shared_ptr<Insert> >::iterator i;
|
||||
if ((i = find (inserts.begin(), inserts.end(), r)) != inserts.end()) {
|
||||
inserts.erase (i);
|
||||
InsertsChanged ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RouteRedirectSelection::set (boost::shared_ptr<Redirect> r)
|
||||
RouteRedirectSelection::set (boost::shared_ptr<Insert> r)
|
||||
{
|
||||
clear_redirects ();
|
||||
clear_inserts ();
|
||||
add (r);
|
||||
}
|
||||
|
||||
void
|
||||
RouteRedirectSelection::set (const vector<boost::shared_ptr<Redirect> >& rlist)
|
||||
RouteRedirectSelection::set (const vector<boost::shared_ptr<Insert> >& rlist)
|
||||
{
|
||||
clear_redirects ();
|
||||
clear_inserts ();
|
||||
add (rlist);
|
||||
}
|
||||
|
||||
|
|
@ -171,6 +171,6 @@ RouteRedirectSelection::selected (boost::shared_ptr<Route> r)
|
|||
bool
|
||||
RouteRedirectSelection::empty ()
|
||||
{
|
||||
return redirects.empty () && routes.empty ();
|
||||
return inserts.empty () && routes.empty ();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,30 +29,30 @@
|
|||
class RouteRedirectSelection : public sigc::trackable
|
||||
{
|
||||
public:
|
||||
RedirectSelection redirects;
|
||||
InsertSelection inserts;
|
||||
RouteSelection routes;
|
||||
|
||||
RouteRedirectSelection() {}
|
||||
|
||||
RouteRedirectSelection& operator= (const RouteRedirectSelection& other);
|
||||
|
||||
sigc::signal<void> RedirectsChanged;
|
||||
sigc::signal<void> InsertsChanged;
|
||||
sigc::signal<void> RoutesChanged;
|
||||
|
||||
void clear ();
|
||||
bool empty();
|
||||
|
||||
void set (boost::shared_ptr<ARDOUR::Redirect>);
|
||||
void set (const std::vector<boost::shared_ptr<ARDOUR::Redirect> >&);
|
||||
void add (boost::shared_ptr<ARDOUR::Redirect>);
|
||||
void add (const std::vector<boost::shared_ptr<ARDOUR::Redirect> >&);
|
||||
void remove (boost::shared_ptr<ARDOUR::Redirect>);
|
||||
void set (boost::shared_ptr<ARDOUR::Insert>);
|
||||
void set (const std::vector<boost::shared_ptr<ARDOUR::Insert> >&);
|
||||
void add (boost::shared_ptr<ARDOUR::Insert>);
|
||||
void add (const std::vector<boost::shared_ptr<ARDOUR::Insert> >&);
|
||||
void remove (boost::shared_ptr<ARDOUR::Insert>);
|
||||
|
||||
void set (boost::shared_ptr<ARDOUR::Route>);
|
||||
void add (boost::shared_ptr<ARDOUR::Route>);
|
||||
void remove (boost::shared_ptr<ARDOUR::Route>);
|
||||
|
||||
void clear_redirects ();
|
||||
void clear_inserts ();
|
||||
void clear_routes ();
|
||||
|
||||
bool selected (boost::shared_ptr<ARDOUR::Route>);
|
||||
|
|
|
|||
|
|
@ -179,8 +179,8 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
|
|||
|
||||
_route->mute_changed.connect (mem_fun(*this, &RouteUI::mute_changed));
|
||||
_route->solo_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
|
||||
_route->redirects_changed.connect (mem_fun(*this, &RouteTimeAxisView::redirects_changed));
|
||||
_route->name_changed.connect (mem_fun(*this, &RouteTimeAxisView::route_name_changed));
|
||||
_route->inserts_changed.connect (mem_fun(*this, &RouteTimeAxisView::inserts_changed));
|
||||
_route->NameChanged.connect (mem_fun(*this, &RouteTimeAxisView::route_name_changed));
|
||||
_route->solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
|
||||
|
||||
|
||||
|
|
@ -204,9 +204,9 @@ RouteTimeAxisView::~RouteTimeAxisView ()
|
|||
{
|
||||
GoingAway (); /* EMIT_SIGNAL */
|
||||
|
||||
vector_delete (&redirect_automation_curves);
|
||||
vector_delete (&insert_automation_curves);
|
||||
|
||||
for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
|
||||
for (list<InsertAutomationInfo*>::iterator i = insert_automation.begin(); i != insert_automation.end(); ++i) {
|
||||
delete *i;
|
||||
}
|
||||
|
||||
|
|
@ -232,9 +232,9 @@ RouteTimeAxisView::post_construct ()
|
|||
/* map current state of the route */
|
||||
|
||||
update_diskstream_display ();
|
||||
_route->foreach_redirect (this, &RouteTimeAxisView::add_redirect_to_subplugin_menu);
|
||||
_route->foreach_redirect (this, &RouteTimeAxisView::add_existing_redirect_automation_curves);
|
||||
reset_redirect_automation_curves ();
|
||||
_route->foreach_insert (this, &RouteTimeAxisView::add_insert_to_subplugin_menu);
|
||||
_route->foreach_insert (this, &RouteTimeAxisView::add_existing_insert_automation_curves);
|
||||
reset_insert_automation_curves ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -322,7 +322,7 @@ RouteTimeAxisView::label_view ()
|
|||
}
|
||||
|
||||
void
|
||||
RouteTimeAxisView::route_name_changed (void *src)
|
||||
RouteTimeAxisView::route_name_changed ()
|
||||
{
|
||||
editor.route_name_changed (this);
|
||||
label_view ();
|
||||
|
|
@ -1135,7 +1135,7 @@ RouteTimeAxisView::name_entry_changed ()
|
|||
}
|
||||
|
||||
if (_session.route_name_unique (x)) {
|
||||
_route->set_name (x, this);
|
||||
_route->set_name (x);
|
||||
} else {
|
||||
ARDOUR_UI::instance()->popup_error (_("A track already exists with that name"));
|
||||
name_entry.set_text (_route->name());
|
||||
|
|
@ -1253,8 +1253,7 @@ RouteTimeAxisView::paste (nframes_t pos, float times, Selection& selection, size
|
|||
list<TimeAxisView*>
|
||||
RouteTimeAxisView::get_child_list()
|
||||
{
|
||||
|
||||
list<TimeAxisView*>redirect_children;
|
||||
list<TimeAxisView*> redirect_children;
|
||||
|
||||
for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
|
||||
if (!(*i)->hidden()) {
|
||||
|
|
@ -1385,10 +1384,10 @@ RouteTimeAxisView::show_all_automation ()
|
|||
{
|
||||
no_redraw = true;
|
||||
|
||||
for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
|
||||
for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
|
||||
for (list<InsertAutomationInfo*>::iterator i = insert_automation.begin(); i != insert_automation.end(); ++i) {
|
||||
for (vector<InsertAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
|
||||
if ((*ii)->view == 0) {
|
||||
add_redirect_automation_curve ((*i)->redirect, (*ii)->what);
|
||||
add_insert_automation_curve ((*i)->insert, (*ii)->what);
|
||||
}
|
||||
|
||||
(*ii)->menu_item->set_active (true);
|
||||
|
|
@ -1405,8 +1404,8 @@ RouteTimeAxisView::show_existing_automation ()
|
|||
{
|
||||
no_redraw = true;
|
||||
|
||||
for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
|
||||
for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
|
||||
for (list<InsertAutomationInfo*>::iterator i = insert_automation.begin(); i != insert_automation.end(); ++i) {
|
||||
for (vector<InsertAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
|
||||
if ((*ii)->view != 0) {
|
||||
(*ii)->menu_item->set_active (true);
|
||||
}
|
||||
|
|
@ -1423,8 +1422,8 @@ RouteTimeAxisView::hide_all_automation ()
|
|||
{
|
||||
no_redraw = true;
|
||||
|
||||
for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
|
||||
for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
|
||||
for (list<InsertAutomationInfo*>::iterator i = insert_automation.begin(); i != insert_automation.end(); ++i) {
|
||||
for (vector<InsertAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
|
||||
(*ii)->menu_item->set_active (false);
|
||||
}
|
||||
}
|
||||
|
|
@ -1447,20 +1446,20 @@ RouteTimeAxisView::region_view_added (RegionView* rv)
|
|||
}
|
||||
|
||||
void
|
||||
RouteTimeAxisView::add_ghost_to_redirect (RegionView* rv, AutomationTimeAxisView* atv)
|
||||
RouteTimeAxisView::add_ghost_to_insert (RegionView* rv, AutomationTimeAxisView* atv)
|
||||
{
|
||||
rv->add_ghost (*atv);
|
||||
}
|
||||
|
||||
RouteTimeAxisView::RedirectAutomationInfo::~RedirectAutomationInfo ()
|
||||
RouteTimeAxisView::InsertAutomationInfo::~InsertAutomationInfo ()
|
||||
{
|
||||
for (vector<RedirectAutomationNode*>::iterator i = lines.begin(); i != lines.end(); ++i) {
|
||||
for (vector<InsertAutomationNode*>::iterator i = lines.begin(); i != lines.end(); ++i) {
|
||||
delete *i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RouteTimeAxisView::RedirectAutomationNode::~RedirectAutomationNode ()
|
||||
RouteTimeAxisView::InsertAutomationNode::~InsertAutomationNode ()
|
||||
{
|
||||
parent.remove_ran (this);
|
||||
|
||||
|
|
@ -1470,21 +1469,21 @@ RouteTimeAxisView::RedirectAutomationNode::~RedirectAutomationNode ()
|
|||
}
|
||||
|
||||
void
|
||||
RouteTimeAxisView::remove_ran (RedirectAutomationNode* ran)
|
||||
RouteTimeAxisView::remove_ran (InsertAutomationNode* ran)
|
||||
{
|
||||
if (ran->view) {
|
||||
remove_child (ran->view);
|
||||
}
|
||||
}
|
||||
|
||||
RouteTimeAxisView::RedirectAutomationNode*
|
||||
RouteTimeAxisView::find_redirect_automation_node (boost::shared_ptr<Redirect> redirect, uint32_t what)
|
||||
RouteTimeAxisView::InsertAutomationNode*
|
||||
RouteTimeAxisView::find_insert_automation_node (boost::shared_ptr<Insert> insert, uint32_t what)
|
||||
{
|
||||
for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
|
||||
for (list<InsertAutomationInfo*>::iterator i = insert_automation.begin(); i != insert_automation.end(); ++i) {
|
||||
|
||||
if ((*i)->redirect == redirect) {
|
||||
if ((*i)->insert == insert) {
|
||||
|
||||
for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
|
||||
for (vector<InsertAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
|
||||
if ((*ii)->what == what) {
|
||||
return *ii;
|
||||
}
|
||||
|
|
@ -1495,7 +1494,6 @@ RouteTimeAxisView::find_redirect_automation_node (boost::shared_ptr<Redirect> re
|
|||
return 0;
|
||||
}
|
||||
|
||||
// FIXME: duplicated in midi_time_axis.cc
|
||||
static string
|
||||
legalize_for_xml_node (string str)
|
||||
{
|
||||
|
|
@ -1516,16 +1514,16 @@ legalize_for_xml_node (string str)
|
|||
|
||||
|
||||
void
|
||||
RouteTimeAxisView::add_redirect_automation_curve (boost::shared_ptr<Redirect> redirect, uint32_t what)
|
||||
RouteTimeAxisView::add_insert_automation_curve (boost::shared_ptr<Insert> insert, uint32_t what)
|
||||
{
|
||||
RedirectAutomationLine* ral;
|
||||
string name;
|
||||
RedirectAutomationNode* ran;
|
||||
InsertAutomationNode* ran;
|
||||
|
||||
if ((ran = find_redirect_automation_node (redirect, what)) == 0) {
|
||||
if ((ran = find_insert_automation_node (insert, what)) == 0) {
|
||||
fatal << _("programming error: ")
|
||||
<< string_compose (X_("redirect automation curve for %1:%2 not registered with audio track!"),
|
||||
redirect->name(), what)
|
||||
<< string_compose (X_("insert automation curve for %1:%2 not registered with audio track!"),
|
||||
insert->name(), what)
|
||||
<< endmsg;
|
||||
/*NOTREACHED*/
|
||||
return;
|
||||
|
|
@ -1535,25 +1533,25 @@ RouteTimeAxisView::add_redirect_automation_curve (boost::shared_ptr<Redirect> re
|
|||
return;
|
||||
}
|
||||
|
||||
name = redirect->describe_parameter (what);
|
||||
name = insert->describe_parameter (what);
|
||||
|
||||
/* create a string that is a legal XML node name that can be used to refer to this redirect+port combination */
|
||||
|
||||
char state_name[256];
|
||||
snprintf (state_name, sizeof (state_name), "Redirect-%s-%" PRIu32, legalize_for_xml_node (redirect->name()).c_str(), what);
|
||||
snprintf (state_name, sizeof (state_name), "Redirect-%s-%" PRIu32, legalize_for_xml_node (insert->name()).c_str(), what);
|
||||
|
||||
ran->view = new RedirectAutomationTimeAxisView (_session, _route, editor, *this, parent_canvas, name, what, *redirect, state_name);
|
||||
ran->view = new RedirectAutomationTimeAxisView (_session, _route, editor, *this, parent_canvas, name, what, *insert, state_name);
|
||||
|
||||
ral = new RedirectAutomationLine (name,
|
||||
*redirect, what, _session, *ran->view,
|
||||
*ran->view->canvas_display, redirect->automation_list (what));
|
||||
*insert, what, _session, *ran->view,
|
||||
*ran->view->canvas_display, insert->automation_list (what));
|
||||
|
||||
ral->set_line_color (Config->canvasvar_RedirectAutomationLine.get());
|
||||
ral->queue_reset ();
|
||||
|
||||
ran->view->add_line (*ral);
|
||||
|
||||
ran->view->Hiding.connect (bind (mem_fun(*this, &RouteTimeAxisView::redirect_automation_track_hidden), ran, redirect));
|
||||
ran->view->Hiding.connect (bind (mem_fun(*this, &RouteTimeAxisView::insert_automation_track_hidden), ran, insert));
|
||||
|
||||
if (!ran->view->marked_for_display()) {
|
||||
ran->view->hide ();
|
||||
|
|
@ -1564,68 +1562,68 @@ RouteTimeAxisView::add_redirect_automation_curve (boost::shared_ptr<Redirect> re
|
|||
add_child (ran->view);
|
||||
|
||||
if (_view) {
|
||||
_view->foreach_regionview (bind (mem_fun(*this, &RouteTimeAxisView::add_ghost_to_redirect), ran->view));
|
||||
_view->foreach_regionview (bind (mem_fun(*this, &RouteTimeAxisView::add_ghost_to_insert), ran->view));
|
||||
}
|
||||
|
||||
redirect->mark_automation_visible (what, true);
|
||||
insert->mark_automation_visible (what, true);
|
||||
}
|
||||
|
||||
void
|
||||
RouteTimeAxisView::redirect_automation_track_hidden (RouteTimeAxisView::RedirectAutomationNode* ran, boost::shared_ptr<Redirect> r)
|
||||
RouteTimeAxisView::insert_automation_track_hidden (RouteTimeAxisView::InsertAutomationNode* ran, boost::shared_ptr<Insert> i)
|
||||
{
|
||||
if (!_hidden) {
|
||||
ran->menu_item->set_active (false);
|
||||
}
|
||||
|
||||
r->mark_automation_visible (ran->what, false);
|
||||
i->mark_automation_visible (ran->what, false);
|
||||
|
||||
_route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
|
||||
}
|
||||
|
||||
void
|
||||
RouteTimeAxisView::add_existing_redirect_automation_curves (boost::shared_ptr<Redirect> redirect)
|
||||
RouteTimeAxisView::add_existing_insert_automation_curves (boost::shared_ptr<Insert> insert)
|
||||
{
|
||||
set<uint32_t> s;
|
||||
RedirectAutomationLine *ral;
|
||||
|
||||
redirect->what_has_visible_automation (s);
|
||||
insert->what_has_visible_automation (s);
|
||||
|
||||
for (set<uint32_t>::iterator i = s.begin(); i != s.end(); ++i) {
|
||||
|
||||
if ((ral = find_redirect_automation_curve (redirect, *i)) != 0) {
|
||||
if ((ral = find_insert_automation_curve (insert, *i)) != 0) {
|
||||
ral->queue_reset ();
|
||||
} else {
|
||||
add_redirect_automation_curve (redirect, (*i));
|
||||
add_insert_automation_curve (insert, (*i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RouteTimeAxisView::add_redirect_to_subplugin_menu (boost::shared_ptr<Redirect> r)
|
||||
RouteTimeAxisView::add_insert_to_subplugin_menu (boost::shared_ptr<Insert> insert)
|
||||
{
|
||||
using namespace Menu_Helpers;
|
||||
RedirectAutomationInfo *rai;
|
||||
list<RedirectAutomationInfo*>::iterator x;
|
||||
InsertAutomationInfo *rai;
|
||||
list<InsertAutomationInfo*>::iterator x;
|
||||
|
||||
const std::set<uint32_t>& automatable = r->what_can_be_automated ();
|
||||
const std::set<uint32_t>& automatable = insert->what_can_be_automated ();
|
||||
std::set<uint32_t> has_visible_automation;
|
||||
|
||||
r->what_has_visible_automation(has_visible_automation);
|
||||
insert->what_has_visible_automation(has_visible_automation);
|
||||
|
||||
if (automatable.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (x = redirect_automation.begin(); x != redirect_automation.end(); ++x) {
|
||||
if ((*x)->redirect == r) {
|
||||
for (x = insert_automation.begin(); x != insert_automation.end(); ++x) {
|
||||
if ((*x)->insert == insert) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (x == redirect_automation.end()) {
|
||||
if (x == insert_automation.end()) {
|
||||
|
||||
rai = new RedirectAutomationInfo (r);
|
||||
redirect_automation.push_back (rai);
|
||||
rai = new InsertAutomationInfo (insert);
|
||||
insert_automation.push_back (rai);
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -1633,7 +1631,7 @@ RouteTimeAxisView::add_redirect_to_subplugin_menu (boost::shared_ptr<Redirect> r
|
|||
|
||||
}
|
||||
|
||||
/* any older menu was deleted at the top of redirects_changed()
|
||||
/* any older menu was deleted at the top of inserts_changed()
|
||||
when we cleared the subplugin menu.
|
||||
*/
|
||||
|
||||
|
|
@ -1645,10 +1643,10 @@ RouteTimeAxisView::add_redirect_to_subplugin_menu (boost::shared_ptr<Redirect> r
|
|||
|
||||
for (std::set<uint32_t>::const_iterator i = automatable.begin(); i != automatable.end(); ++i) {
|
||||
|
||||
RedirectAutomationNode* ran;
|
||||
InsertAutomationNode* ran;
|
||||
CheckMenuItem* mitem;
|
||||
|
||||
string name = r->describe_parameter (*i);
|
||||
string name = insert->describe_parameter (*i);
|
||||
|
||||
items.push_back (CheckMenuElem (name));
|
||||
mitem = dynamic_cast<CheckMenuItem*> (&items.back());
|
||||
|
|
@ -1657,11 +1655,11 @@ RouteTimeAxisView::add_redirect_to_subplugin_menu (boost::shared_ptr<Redirect> r
|
|||
mitem->set_active(true);
|
||||
}
|
||||
|
||||
if ((ran = find_redirect_automation_node (r, *i)) == 0) {
|
||||
if ((ran = find_insert_automation_node (insert, *i)) == 0) {
|
||||
|
||||
/* new item */
|
||||
|
||||
ran = new RedirectAutomationNode (*i, mitem, *this);
|
||||
ran = new InsertAutomationNode (*i, mitem, *this);
|
||||
|
||||
rai->lines.push_back (ran);
|
||||
|
||||
|
|
@ -1671,28 +1669,28 @@ RouteTimeAxisView::add_redirect_to_subplugin_menu (boost::shared_ptr<Redirect> r
|
|||
|
||||
}
|
||||
|
||||
mitem->signal_toggled().connect (bind (mem_fun(*this, &RouteTimeAxisView::redirect_menu_item_toggled), rai, ran));
|
||||
mitem->signal_toggled().connect (bind (mem_fun(*this, &RouteTimeAxisView::insert_menu_item_toggled), rai, ran));
|
||||
}
|
||||
|
||||
/* add the menu for this redirect, because the subplugin
|
||||
menu is always cleared at the top of redirects_changed().
|
||||
/* add the menu for this insert, because the subplugin
|
||||
menu is always cleared at the top of inserts_changed().
|
||||
this is the result of some poor design in gtkmm and/or
|
||||
GTK+.
|
||||
*/
|
||||
|
||||
subplugin_menu.items().push_back (MenuElem (r->name(), *rai->menu));
|
||||
subplugin_menu.items().push_back (MenuElem (insert->name(), *rai->menu));
|
||||
rai->valid = true;
|
||||
}
|
||||
|
||||
void
|
||||
RouteTimeAxisView::redirect_menu_item_toggled (RouteTimeAxisView::RedirectAutomationInfo* rai,
|
||||
RouteTimeAxisView::RedirectAutomationNode* ran)
|
||||
RouteTimeAxisView::insert_menu_item_toggled (RouteTimeAxisView::InsertAutomationInfo* rai,
|
||||
RouteTimeAxisView::InsertAutomationNode* ran)
|
||||
{
|
||||
bool showit = ran->menu_item->get_active();
|
||||
bool redraw = false;
|
||||
|
||||
if (ran->view == 0 && showit) {
|
||||
add_redirect_automation_curve (rai->redirect, ran->what);
|
||||
add_insert_automation_curve (rai->insert, ran->what);
|
||||
redraw = true;
|
||||
}
|
||||
|
||||
|
|
@ -1702,7 +1700,7 @@ RouteTimeAxisView::redirect_menu_item_toggled (RouteTimeAxisView::RedirectAutoma
|
|||
ran->view->set_marked_for_display (true);
|
||||
ran->view->canvas_display->show();
|
||||
} else {
|
||||
rai->redirect->mark_automation_visible (ran->what, true);
|
||||
rai->insert->mark_automation_visible (ran->what, true);
|
||||
ran->view->set_marked_for_display (false);
|
||||
ran->view->hide ();
|
||||
}
|
||||
|
|
@ -1721,22 +1719,22 @@ RouteTimeAxisView::redirect_menu_item_toggled (RouteTimeAxisView::RedirectAutoma
|
|||
}
|
||||
|
||||
void
|
||||
RouteTimeAxisView::redirects_changed (void *src)
|
||||
RouteTimeAxisView::inserts_changed ()
|
||||
{
|
||||
using namespace Menu_Helpers;
|
||||
|
||||
for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
|
||||
for (list<InsertAutomationInfo*>::iterator i = insert_automation.begin(); i != insert_automation.end(); ++i) {
|
||||
(*i)->valid = false;
|
||||
}
|
||||
|
||||
subplugin_menu.items().clear ();
|
||||
|
||||
_route->foreach_redirect (this, &RouteTimeAxisView::add_redirect_to_subplugin_menu);
|
||||
_route->foreach_redirect (this, &RouteTimeAxisView::add_existing_redirect_automation_curves);
|
||||
_route->foreach_insert (this, &RouteTimeAxisView::add_insert_to_subplugin_menu);
|
||||
_route->foreach_insert (this, &RouteTimeAxisView::add_existing_insert_automation_curves);
|
||||
|
||||
for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ) {
|
||||
for (list<InsertAutomationInfo*>::iterator i = insert_automation.begin(); i != insert_automation.end(); ) {
|
||||
|
||||
list<RedirectAutomationInfo*>::iterator tmp;
|
||||
list<InsertAutomationInfo*>::iterator tmp;
|
||||
|
||||
tmp = i;
|
||||
++tmp;
|
||||
|
|
@ -1744,7 +1742,7 @@ RouteTimeAxisView::redirects_changed (void *src)
|
|||
if (!(*i)->valid) {
|
||||
|
||||
delete *i;
|
||||
redirect_automation.erase (i);
|
||||
insert_automation.erase (i);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1757,11 +1755,11 @@ RouteTimeAxisView::redirects_changed (void *src)
|
|||
}
|
||||
|
||||
RedirectAutomationLine *
|
||||
RouteTimeAxisView::find_redirect_automation_curve (boost::shared_ptr<Redirect> redirect, uint32_t what)
|
||||
RouteTimeAxisView::find_insert_automation_curve (boost::shared_ptr<Insert> insert, uint32_t what)
|
||||
{
|
||||
RedirectAutomationNode* ran;
|
||||
InsertAutomationNode* ran;
|
||||
|
||||
if ((ran = find_redirect_automation_node (redirect, what)) != 0) {
|
||||
if ((ran = find_insert_automation_node (insert, what)) != 0) {
|
||||
if (ran->view) {
|
||||
return dynamic_cast<RedirectAutomationLine*> (ran->view->lines.front());
|
||||
}
|
||||
|
|
@ -1771,9 +1769,9 @@ RouteTimeAxisView::find_redirect_automation_curve (boost::shared_ptr<Redirect> r
|
|||
}
|
||||
|
||||
void
|
||||
RouteTimeAxisView::reset_redirect_automation_curves ()
|
||||
RouteTimeAxisView::reset_insert_automation_curves ()
|
||||
{
|
||||
for (vector<RedirectAutomationLine*>::iterator i = redirect_automation_curves.begin(); i != redirect_automation_curves.end(); ++i) {
|
||||
for (vector<RedirectAutomationLine*>::iterator i = insert_automation_curves.begin(); i != insert_automation_curves.end(); ++i) {
|
||||
(*i)->reset();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,28 +103,28 @@ public:
|
|||
protected:
|
||||
friend class StreamView;
|
||||
|
||||
struct RedirectAutomationNode {
|
||||
struct InsertAutomationNode {
|
||||
uint32_t what;
|
||||
Gtk::CheckMenuItem* menu_item;
|
||||
AutomationTimeAxisView* view;
|
||||
RouteTimeAxisView& parent;
|
||||
|
||||
RedirectAutomationNode (uint32_t w, Gtk::CheckMenuItem* mitem, RouteTimeAxisView& p)
|
||||
InsertAutomationNode (uint32_t w, Gtk::CheckMenuItem* mitem, RouteTimeAxisView& p)
|
||||
: what (w), menu_item (mitem), view (0), parent (p) {}
|
||||
|
||||
~RedirectAutomationNode ();
|
||||
~InsertAutomationNode ();
|
||||
};
|
||||
|
||||
struct RedirectAutomationInfo {
|
||||
boost::shared_ptr<ARDOUR::Redirect> redirect;
|
||||
bool valid;
|
||||
Gtk::Menu* menu;
|
||||
vector<RedirectAutomationNode*> lines;
|
||||
struct InsertAutomationInfo {
|
||||
boost::shared_ptr<ARDOUR::Insert> insert;
|
||||
bool valid;
|
||||
Gtk::Menu* menu;
|
||||
vector<InsertAutomationNode*> lines;
|
||||
|
||||
RedirectAutomationInfo (boost::shared_ptr<ARDOUR::Redirect> r)
|
||||
: redirect (r), valid (true), menu (0) {}
|
||||
InsertAutomationInfo (boost::shared_ptr<ARDOUR::Insert> i)
|
||||
: insert (i), valid (true), menu (0) {}
|
||||
|
||||
~RedirectAutomationInfo ();
|
||||
~InsertAutomationInfo ();
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -133,30 +133,30 @@ protected:
|
|||
|
||||
gint edit_click (GdkEventButton *);
|
||||
|
||||
void redirects_changed (void *);
|
||||
void inserts_changed ();
|
||||
|
||||
void add_redirect_to_subplugin_menu (boost::shared_ptr<ARDOUR::Redirect>);
|
||||
void remove_ran (RedirectAutomationNode* ran);
|
||||
void add_insert_to_subplugin_menu (boost::shared_ptr<ARDOUR::Insert>);
|
||||
void remove_ran (InsertAutomationNode* ran);
|
||||
|
||||
void redirect_menu_item_toggled (RouteTimeAxisView::RedirectAutomationInfo*,
|
||||
RouteTimeAxisView::RedirectAutomationNode*);
|
||||
void insert_menu_item_toggled (RouteTimeAxisView::InsertAutomationInfo*,
|
||||
RouteTimeAxisView::InsertAutomationNode*);
|
||||
|
||||
void redirect_automation_track_hidden (RedirectAutomationNode*,
|
||||
boost::shared_ptr<ARDOUR::Redirect>);
|
||||
void insert_automation_track_hidden (InsertAutomationNode*,
|
||||
boost::shared_ptr<ARDOUR::Insert>);
|
||||
|
||||
RedirectAutomationNode*
|
||||
find_redirect_automation_node (boost::shared_ptr<ARDOUR::Redirect> r, uint32_t);
|
||||
InsertAutomationNode*
|
||||
find_insert_automation_node (boost::shared_ptr<ARDOUR::Insert> i, uint32_t);
|
||||
|
||||
RedirectAutomationLine*
|
||||
find_redirect_automation_curve (boost::shared_ptr<ARDOUR::Redirect> r, uint32_t);
|
||||
find_insert_automation_curve (boost::shared_ptr<ARDOUR::Insert> i, uint32_t);
|
||||
|
||||
void add_redirect_automation_curve (boost::shared_ptr<ARDOUR::Redirect> r, uint32_t);
|
||||
void add_existing_redirect_automation_curves (boost::shared_ptr<ARDOUR::Redirect>);
|
||||
void add_insert_automation_curve (boost::shared_ptr<ARDOUR::Insert> r, uint32_t);
|
||||
void add_existing_insert_automation_curves (boost::shared_ptr<ARDOUR::Insert>);
|
||||
|
||||
void reset_redirect_automation_curves ();
|
||||
void reset_insert_automation_curves ();
|
||||
|
||||
void take_name_changed (void *);
|
||||
void route_name_changed (void *);
|
||||
void take_name_changed (void *src);
|
||||
void route_name_changed ();
|
||||
void name_entry_changed ();
|
||||
|
||||
void update_rec_display ();
|
||||
|
|
@ -202,7 +202,7 @@ protected:
|
|||
void color_handler ();
|
||||
|
||||
void region_view_added (RegionView*);
|
||||
void add_ghost_to_redirect (RegionView*, AutomationTimeAxisView*);
|
||||
void add_ghost_to_insert (RegionView*, AutomationTimeAxisView*);
|
||||
|
||||
|
||||
StreamView* _view;
|
||||
|
|
@ -211,7 +211,7 @@ protected:
|
|||
|
||||
Gtk::HBox other_button_hbox;
|
||||
Gtk::Table button_table;
|
||||
Gtk::Button redirect_button;
|
||||
Gtk::Button insert_button;
|
||||
Gtk::Button edit_group_button;
|
||||
Gtk::Button playlist_button;
|
||||
Gtk::Button size_button;
|
||||
|
|
@ -238,8 +238,8 @@ protected:
|
|||
void _set_track_mode (ARDOUR::Track* track, ARDOUR::TrackMode mode, Gtk::RadioMenuItem* reset_item);
|
||||
void track_mode_changed ();
|
||||
|
||||
list<RedirectAutomationInfo*> redirect_automation;
|
||||
vector<RedirectAutomationLine*> redirect_automation_curves;
|
||||
list<InsertAutomationInfo*> insert_automation;
|
||||
vector<RedirectAutomationLine*> insert_automation_curves;
|
||||
|
||||
sigc::connection modified_connection;
|
||||
|
||||
|
|
|
|||
|
|
@ -817,7 +817,7 @@ RouteUI::route_rename ()
|
|||
case Gtk::RESPONSE_ACCEPT:
|
||||
name_prompter.get_result (result);
|
||||
if (result.length()) {
|
||||
_route->set_name (result, this);
|
||||
_route->set_name (result);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -827,9 +827,9 @@ RouteUI::route_rename ()
|
|||
}
|
||||
|
||||
void
|
||||
RouteUI::name_changed (void *src)
|
||||
RouteUI::name_changed ()
|
||||
{
|
||||
ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::name_changed), src));
|
||||
ENSURE_GUI_THREAD(sigc::mem_fun(*this, &RouteUI::name_changed));
|
||||
|
||||
name_label.set_text (_route->name());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ class RouteUI : public virtual AxisView
|
|||
void solo_changed(void*);
|
||||
void solo_changed_so_update_mute ();
|
||||
void mute_changed(void*);
|
||||
virtual void redirects_changed (void *) {}
|
||||
virtual void inserts_changed () {}
|
||||
void route_rec_enable_changed();
|
||||
void session_rec_enable_changed();
|
||||
|
||||
|
|
@ -133,7 +133,7 @@ class RouteUI : public virtual AxisView
|
|||
|
||||
void route_rename();
|
||||
|
||||
virtual void name_changed (void *src);
|
||||
virtual void name_changed ();
|
||||
void route_removed ();
|
||||
|
||||
Gtk::CheckMenuItem *route_active_menu_item;
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ operator== (const Selection& a, const Selection& b)
|
|||
a.time == b.time &&
|
||||
a.lines == b.lines &&
|
||||
a.playlists == b.playlists &&
|
||||
a.redirects == b.redirects;
|
||||
a.inserts == b.inserts;
|
||||
}
|
||||
|
||||
/** Clear everything from the Selection */
|
||||
|
|
@ -77,7 +77,7 @@ Selection::clear ()
|
|||
clear_lines();
|
||||
clear_time ();
|
||||
clear_playlists ();
|
||||
clear_redirects ();
|
||||
clear_inserts ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -91,11 +91,11 @@ Selection::dump_region_layers()
|
|||
|
||||
|
||||
void
|
||||
Selection::clear_redirects ()
|
||||
Selection::clear_inserts ()
|
||||
{
|
||||
if (!redirects.empty()) {
|
||||
redirects.clear ();
|
||||
RedirectsChanged ();
|
||||
if (!inserts.empty()) {
|
||||
inserts.clear ();
|
||||
InsertsChanged ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -154,16 +154,16 @@ Selection::clear_lines ()
|
|||
}
|
||||
|
||||
void
|
||||
Selection::toggle (boost::shared_ptr<Redirect> r)
|
||||
Selection::toggle (boost::shared_ptr<Insert> r)
|
||||
{
|
||||
RedirectSelection::iterator i;
|
||||
InsertSelection::iterator i;
|
||||
|
||||
if ((i = find (redirects.begin(), redirects.end(), r)) == redirects.end()) {
|
||||
redirects.push_back (r);
|
||||
if ((i = find (inserts.begin(), inserts.end(), r)) == inserts.end()) {
|
||||
inserts.push_back (r);
|
||||
} else {
|
||||
redirects.erase (i);
|
||||
inserts.erase (i);
|
||||
}
|
||||
RedirectsChanged();
|
||||
InsertsChanged();
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -254,11 +254,11 @@ Selection::toggle (nframes_t start, nframes_t end)
|
|||
|
||||
|
||||
void
|
||||
Selection::add (boost::shared_ptr<Redirect> r)
|
||||
Selection::add (boost::shared_ptr<Insert> i)
|
||||
{
|
||||
if (find (redirects.begin(), redirects.end(), r) == redirects.end()) {
|
||||
redirects.push_back (r);
|
||||
RedirectsChanged();
|
||||
if (find (inserts.begin(), inserts.end(), i) == inserts.end()) {
|
||||
inserts.push_back (i);
|
||||
InsertsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -395,12 +395,12 @@ Selection::add (AutomationList* ac)
|
|||
}
|
||||
|
||||
void
|
||||
Selection::remove (boost::shared_ptr<Redirect> r)
|
||||
Selection::remove (boost::shared_ptr<Insert> r)
|
||||
{
|
||||
RedirectSelection::iterator i;
|
||||
if ((i = find (redirects.begin(), redirects.end(), r)) != redirects.end()) {
|
||||
redirects.erase (i);
|
||||
RedirectsChanged ();
|
||||
InsertSelection::iterator i;
|
||||
if ((i = find (inserts.begin(), inserts.end(), r)) != inserts.end()) {
|
||||
inserts.erase (i);
|
||||
InsertsChanged ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -510,10 +510,10 @@ Selection::remove (AutomationList *ac)
|
|||
}
|
||||
|
||||
void
|
||||
Selection::set (boost::shared_ptr<Redirect> r)
|
||||
Selection::set (boost::shared_ptr<Insert> i)
|
||||
{
|
||||
clear_redirects ();
|
||||
add (r);
|
||||
clear_inserts ();
|
||||
add (i);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -625,7 +625,7 @@ Selection::empty ()
|
|||
lines.empty () &&
|
||||
time.empty () &&
|
||||
playlists.empty () &&
|
||||
redirects.empty ()
|
||||
inserts.empty ()
|
||||
;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ namespace ARDOUR {
|
|||
class Region;
|
||||
class AudioRegion;
|
||||
class Playlist;
|
||||
class Redirect;
|
||||
class Insert;
|
||||
class AutomationList;
|
||||
}
|
||||
|
||||
|
|
@ -69,7 +69,7 @@ class Selection : public sigc::trackable
|
|||
TimeSelection time;
|
||||
AutomationSelection lines;
|
||||
PlaylistSelection playlists;
|
||||
RedirectSelection redirects;
|
||||
InsertSelection inserts;
|
||||
PointSelection points;
|
||||
|
||||
Selection() {
|
||||
|
|
@ -84,7 +84,7 @@ class Selection : public sigc::trackable
|
|||
sigc::signal<void> TimeChanged;
|
||||
sigc::signal<void> LinesChanged;
|
||||
sigc::signal<void> PlaylistsChanged;
|
||||
sigc::signal<void> RedirectsChanged;
|
||||
sigc::signal<void> InsertsChanged;
|
||||
sigc::signal<void> PointsChanged;
|
||||
|
||||
void clear ();
|
||||
|
|
@ -107,7 +107,7 @@ class Selection : public sigc::trackable
|
|||
void set (ARDOUR::AutomationList*);
|
||||
void set (boost::shared_ptr<ARDOUR::Playlist>);
|
||||
void set (const std::list<boost::shared_ptr<ARDOUR::Playlist> >&);
|
||||
void set (boost::shared_ptr<ARDOUR::Redirect>);
|
||||
void set (boost::shared_ptr<ARDOUR::Insert>);
|
||||
void set (AutomationSelectable*);
|
||||
|
||||
void toggle (TimeAxisView*);
|
||||
|
|
@ -118,7 +118,7 @@ class Selection : public sigc::trackable
|
|||
void toggle (ARDOUR::AutomationList*);
|
||||
void toggle (boost::shared_ptr<ARDOUR::Playlist>);
|
||||
void toggle (const std::list<boost::shared_ptr<ARDOUR::Playlist> >&);
|
||||
void toggle (boost::shared_ptr<ARDOUR::Redirect>);
|
||||
void toggle (boost::shared_ptr<ARDOUR::Insert>);
|
||||
void toggle (const std::vector<AutomationSelectable*>&);
|
||||
|
||||
void add (TimeAxisView*);
|
||||
|
|
@ -129,7 +129,7 @@ class Selection : public sigc::trackable
|
|||
void add (ARDOUR::AutomationList*);
|
||||
void add (boost::shared_ptr<ARDOUR::Playlist>);
|
||||
void add (const std::list<boost::shared_ptr<ARDOUR::Playlist> >&);
|
||||
void add (boost::shared_ptr<ARDOUR::Redirect>);
|
||||
void add (boost::shared_ptr<ARDOUR::Insert>);
|
||||
|
||||
void remove (TimeAxisView*);
|
||||
void remove (const std::list<TimeAxisView*>&);
|
||||
|
|
@ -139,7 +139,7 @@ class Selection : public sigc::trackable
|
|||
void remove (ARDOUR::AutomationList*);
|
||||
void remove (boost::shared_ptr<ARDOUR::Playlist>);
|
||||
void remove (const std::list<boost::shared_ptr<ARDOUR::Playlist> >&);
|
||||
void remove (boost::shared_ptr<ARDOUR::Redirect>);
|
||||
void remove (boost::shared_ptr<ARDOUR::Insert>);
|
||||
void remove (const list<Selectable*>&);
|
||||
|
||||
void replace (uint32_t time_index, nframes_t start, nframes_t end);
|
||||
|
|
@ -149,7 +149,7 @@ class Selection : public sigc::trackable
|
|||
void clear_time();
|
||||
void clear_lines ();
|
||||
void clear_playlists ();
|
||||
void clear_redirects ();
|
||||
void clear_inserts ();
|
||||
void clear_points ();
|
||||
|
||||
void foreach_region (void (ARDOUR::Region::*method)(void));
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@ using namespace PBD;
|
|||
SendUI::SendUI (boost::shared_ptr<Send> s, Session& se)
|
||||
: _send (s),
|
||||
_session (se),
|
||||
gpm (s, se),
|
||||
panners (s, se)
|
||||
gpm (s->io(), se),
|
||||
panners (s->io(), se)
|
||||
{
|
||||
hbox.pack_start (gpm, true, true);
|
||||
set_name ("SendUIFrame");
|
||||
|
|
@ -44,7 +44,7 @@ SendUI::SendUI (boost::shared_ptr<Send> s, Session& se)
|
|||
vbox.pack_start (hbox, false, false, false);
|
||||
vbox.pack_start (panners, false,false);
|
||||
|
||||
io = new IOSelector (se, s, false);
|
||||
io = new IOSelector (se, s->io(), false);
|
||||
|
||||
pack_start (vbox, false, false);
|
||||
|
||||
|
|
@ -54,8 +54,8 @@ SendUI::SendUI (boost::shared_ptr<Send> s, Session& se)
|
|||
|
||||
_send->set_metering (true);
|
||||
|
||||
_send->output_changed.connect (mem_fun (*this, &SendUI::ins_changed));
|
||||
_send->output_changed.connect (mem_fun (*this, &SendUI::outs_changed));
|
||||
_send->io()->output_changed.connect (mem_fun (*this, &SendUI::ins_changed));
|
||||
_send->io()->output_changed.connect (mem_fun (*this, &SendUI::outs_changed));
|
||||
|
||||
panners.set_width (Wide);
|
||||
panners.setup_pan ();
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ gain.cc
|
|||
gdither.cc
|
||||
globals.cc
|
||||
import.cc
|
||||
automatable.cc
|
||||
insert.cc
|
||||
plugin_insert.cc
|
||||
port_insert.cc
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ class BufferSet;
|
|||
|
||||
/** Applies a declick operation to all audio inputs, passing the same number of
|
||||
* audio outputs, and passing through any other types unchanged.
|
||||
*
|
||||
* FIXME: make this an insert.
|
||||
*/
|
||||
class Amp {
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -56,7 +56,8 @@ class AudioFileSource : public AudioSource {
|
|||
|
||||
virtual ~AudioFileSource ();
|
||||
|
||||
int set_name (Glib::ustring newname, bool destructive);
|
||||
bool set_name (const std::string& newname) { return (set_source_name(newname, destructive()) == 0); }
|
||||
int set_source_name (Glib::ustring newname, bool destructive);
|
||||
|
||||
Glib::ustring path() const { return _path; }
|
||||
Glib::ustring peak_path (Glib::ustring audio_path);
|
||||
|
|
|
|||
78
libs/ardour/ardour/automatable.h
Normal file
78
libs/ardour/ardour/automatable.h
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
Copyright (C) 2000,2007 Paul Davis
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __ardour_automatable_h__
|
||||
#define __ardour_automatable_h__
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <ardour/session_object.h>
|
||||
#include <ardour/automation_event.h>
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
class Session;
|
||||
|
||||
class Automatable : public SessionObject
|
||||
{
|
||||
public:
|
||||
Automatable(Session&, const std::string& name);
|
||||
|
||||
virtual ~Automatable() {}
|
||||
|
||||
virtual AutomationList& automation_list(uint32_t n);
|
||||
|
||||
virtual void automation_snapshot (nframes_t now) {};
|
||||
|
||||
virtual bool find_next_event(nframes_t start, nframes_t end, ControlEvent& ev) const;
|
||||
|
||||
virtual string describe_parameter(uint32_t which);
|
||||
virtual float default_parameter_value(uint32_t which) { return 1.0f; }
|
||||
|
||||
void what_has_automation(std::set<uint32_t>&) const;
|
||||
void what_has_visible_automation(std::set<uint32_t>&) const;
|
||||
const std::set<uint32_t>& what_can_be_automated() const { return _can_automate_list; }
|
||||
|
||||
void mark_automation_visible(uint32_t, bool);
|
||||
|
||||
protected:
|
||||
|
||||
void can_automate(uint32_t);
|
||||
|
||||
virtual void automation_list_creation_callback(uint32_t, AutomationList&) {}
|
||||
|
||||
int set_automation_state(const XMLNode&);
|
||||
XMLNode& get_automation_state();
|
||||
|
||||
int load_automation (const std::string& path);
|
||||
int old_set_automation_state(const XMLNode&);
|
||||
|
||||
mutable Glib::Mutex _automation_lock;
|
||||
|
||||
// FIXME: map with int keys is a bit silly. this could be O(1)
|
||||
std::map<uint32_t,AutomationList*> _parameter_automation;
|
||||
std::set<uint32_t> _visible_parameter_automation;
|
||||
std::set<uint32_t> _can_automate_list;
|
||||
|
||||
nframes_t _last_automation_snapshot;
|
||||
};
|
||||
|
||||
} // namespace ARDOUR
|
||||
|
||||
#endif /* __ardour_automatable_h__ */
|
||||
|
|
@ -114,10 +114,10 @@ class AutomationList : public PBD::StatefulDestructible
|
|||
AutoStyle automation_style() const { return _style; }
|
||||
sigc::signal<void> automation_state_changed;
|
||||
|
||||
bool automation_playback() {
|
||||
bool automation_playback() const {
|
||||
return (_state & Play) || ((_state & Touch) && !_touching);
|
||||
}
|
||||
bool automation_write () {
|
||||
bool automation_write () const {
|
||||
return (_state & Write) || ((_state & Touch) && _touching);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ class Curve : public AutomationList
|
|||
|
||||
void solve ();
|
||||
|
||||
static sigc::signal<void, Curve*> CurveCreated;
|
||||
static sigc::signal<void, Curve*> CurveCreated;
|
||||
|
||||
protected:
|
||||
ControlEvent* point_factory (double,double) const;
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ class Session;
|
|||
class Playlist;
|
||||
class IO;
|
||||
|
||||
class Diskstream : public PBD::StatefulDestructible
|
||||
class Diskstream : public SessionObject
|
||||
{
|
||||
public:
|
||||
enum Flag {
|
||||
|
|
@ -65,9 +65,8 @@ class Diskstream : public PBD::StatefulDestructible
|
|||
Diskstream (Session &, const string& name, Flag f = Recordable);
|
||||
Diskstream (Session &, const XMLNode&);
|
||||
virtual ~Diskstream();
|
||||
|
||||
string name () const { return _name; }
|
||||
virtual int set_name (string str);
|
||||
|
||||
bool set_name (const string& str);
|
||||
|
||||
ARDOUR::IO* io() const { return _io; }
|
||||
void set_io (ARDOUR::IO& io);
|
||||
|
|
@ -238,8 +237,6 @@ class Diskstream : public PBD::StatefulDestructible
|
|||
|
||||
uint32_t i_am_the_modifier;
|
||||
|
||||
string _name;
|
||||
ARDOUR::Session& _session;
|
||||
ARDOUR::IO* _io;
|
||||
ChanCount _n_channels;
|
||||
|
||||
|
|
|
|||
|
|
@ -24,11 +24,16 @@
|
|||
#include <string>
|
||||
#include <exception>
|
||||
|
||||
#include <pbd/statefuldestructible.h>
|
||||
|
||||
#include <sigc++/signal.h>
|
||||
#include <ardour/ardour.h>
|
||||
#include <ardour/redirect.h>
|
||||
#include <ardour/plugin_state.h>
|
||||
|
||||
#include <ardour/types.h>
|
||||
#include <ardour/ardour.h>
|
||||
#include <ardour/plugin_state.h>
|
||||
#include <ardour/buffer_set.h>
|
||||
#include <ardour/automatable.h>
|
||||
|
||||
|
||||
class XMLNode;
|
||||
|
||||
|
|
@ -36,26 +41,71 @@ namespace ARDOUR {
|
|||
|
||||
class Session;
|
||||
|
||||
class Insert : public Redirect
|
||||
/* A mixer strip element - plugin, send, meter, etc.
|
||||
*/
|
||||
class Insert : public Automatable
|
||||
{
|
||||
public:
|
||||
Insert(Session& s, std::string name, Placement p);
|
||||
Insert(Session& s, std::string name, Placement p, int imin, int imax, int omin, int omax);
|
||||
static const string state_node_name;
|
||||
|
||||
Insert(Session&, const string& name, Placement p); // TODO: remove placement in favour of sort key
|
||||
|
||||
virtual ~Insert() { }
|
||||
|
||||
static boost::shared_ptr<Insert> clone (boost::shared_ptr<const Insert>);
|
||||
|
||||
uint32_t sort_key() const { return _sort_key; }
|
||||
void set_sort_key (uint32_t key);
|
||||
|
||||
Placement placement() const { return _placement; }
|
||||
void set_placement (Placement);
|
||||
|
||||
bool active () const { return _active; }
|
||||
void set_active (bool yn);
|
||||
|
||||
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 void transport_stopped (nframes_t frame) {}
|
||||
|
||||
virtual void set_block_size (nframes_t nframes) {}
|
||||
|
||||
virtual void run (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset) = 0;
|
||||
virtual void silence (nframes_t nframes, nframes_t offset) {}
|
||||
|
||||
virtual void activate () {}
|
||||
virtual void deactivate () {}
|
||||
virtual void activate () { _active = true; ActiveChanged.emit(); }
|
||||
virtual void deactivate () { _active = false; ActiveChanged.emit(); }
|
||||
|
||||
virtual bool configure_io (ChanCount in, ChanCount out) { _configured_input = in; return (_configured = true); }
|
||||
|
||||
virtual bool can_support_input_configuration (ChanCount in) const = 0;
|
||||
virtual ChanCount output_for_input_configuration (ChanCount in) const = 0;
|
||||
virtual bool configure_io (ChanCount in, ChanCount out) = 0;
|
||||
/* Act as a pass through, if not overridden */
|
||||
virtual bool can_support_input_configuration (ChanCount in) const { return true; }
|
||||
virtual ChanCount output_for_input_configuration (ChanCount in) const { return in; }
|
||||
virtual ChanCount output_streams() const { return _configured_input; }
|
||||
virtual ChanCount input_streams () const { return _configured_input; }
|
||||
|
||||
virtual XMLNode& state (bool full);
|
||||
virtual XMLNode& get_state (void);
|
||||
virtual int set_state (const XMLNode&);
|
||||
|
||||
void *get_gui () const { return _gui; }
|
||||
void set_gui (void *p) { _gui = p; }
|
||||
|
||||
static sigc::signal<void,Insert*> InsertCreated;
|
||||
|
||||
sigc::signal<void> ActiveChanged;
|
||||
sigc::signal<void> PlacementChanged;
|
||||
|
||||
protected:
|
||||
bool _active;
|
||||
bool _next_ab_is_active;
|
||||
bool _configured;
|
||||
ChanCount _configured_input;
|
||||
Placement _placement;
|
||||
uint32_t _sort_key;
|
||||
void* _gui; /* generic, we don't know or care what this is */
|
||||
};
|
||||
|
||||
} // namespace ARDOUR
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include <pbd/controllable.h>
|
||||
|
||||
#include <ardour/ardour.h>
|
||||
#include <ardour/session_object.h>
|
||||
#include <ardour/utils.h>
|
||||
#include <ardour/curve.h>
|
||||
#include <ardour/types.h>
|
||||
|
|
@ -63,13 +64,13 @@ 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 PBD::StatefulDestructible
|
||||
class IO : public SessionObject
|
||||
{
|
||||
|
||||
public:
|
||||
static const string state_node_name;
|
||||
|
||||
IO (Session&, string name,
|
||||
IO (Session&, const string& name,
|
||||
int input_min = -1, int input_max = -1,
|
||||
int output_min = -1, int output_max = -1,
|
||||
DataType default_type = DataType::AUDIO);
|
||||
|
|
@ -90,10 +91,9 @@ class IO : public PBD::StatefulDestructible
|
|||
|
||||
DataType default_type() const { return _default_type; }
|
||||
void set_default_type(DataType t) { _default_type = t; }
|
||||
|
||||
const string& name() const { return _name; }
|
||||
virtual int set_name (string str, void *src);
|
||||
|
||||
bool set_name (const string& str);
|
||||
|
||||
virtual void silence (nframes_t, nframes_t offset);
|
||||
|
||||
void collect_input (BufferSet& bufs, nframes_t nframes, nframes_t offset);
|
||||
|
|
@ -179,7 +179,6 @@ class IO : public PBD::StatefulDestructible
|
|||
sigc::signal<void,IOChange,void*> output_changed;
|
||||
|
||||
sigc::signal<void,void*> gain_changed;
|
||||
sigc::signal<void,void*> name_changed;
|
||||
|
||||
virtual XMLNode& state (bool full);
|
||||
XMLNode& get_state (void);
|
||||
|
|
@ -229,26 +228,16 @@ class IO : public PBD::StatefulDestructible
|
|||
|
||||
void clear_automation ();
|
||||
|
||||
bool gain_automation_recording() const {
|
||||
return (_gain_automation_curve.automation_state() & (Write|Touch));
|
||||
}
|
||||
|
||||
bool gain_automation_playback() const {
|
||||
return (_gain_automation_curve.automation_state() & Play) ||
|
||||
((_gain_automation_curve.automation_state() & Touch) &&
|
||||
!_gain_automation_curve.touching());
|
||||
}
|
||||
|
||||
virtual void set_gain_automation_state (AutoState);
|
||||
AutoState gain_automation_state() const { return _gain_automation_curve.automation_state(); }
|
||||
sigc::signal<void> gain_automation_state_changed;
|
||||
//sigc::signal<void> gain_automation_state_changed;
|
||||
|
||||
virtual void set_gain_automation_style (AutoStyle);
|
||||
AutoStyle gain_automation_style () const { return _gain_automation_curve.automation_style(); }
|
||||
sigc::signal<void> gain_automation_style_changed;
|
||||
//sigc::signal<void> gain_automation_style_changed;
|
||||
|
||||
virtual void transport_stopped (nframes_t now);
|
||||
void automation_snapshot (nframes_t now);
|
||||
virtual void transport_stopped (nframes_t now); // interface: matches Insert
|
||||
void automation_snapshot (nframes_t now); // interface: matches Automatable
|
||||
|
||||
ARDOUR::Curve& gain_automation_curve () { return _gain_automation_curve; }
|
||||
|
||||
|
|
@ -272,7 +261,6 @@ class IO : public PBD::StatefulDestructible
|
|||
mutable Glib::Mutex io_lock;
|
||||
|
||||
protected:
|
||||
Session& _session;
|
||||
Panner* _panner;
|
||||
BufferSet* _output_buffers; //< Set directly to output port buffers
|
||||
gain_t _gain;
|
||||
|
|
@ -282,7 +270,6 @@ class IO : public PBD::StatefulDestructible
|
|||
PortSet _outputs;
|
||||
PortSet _inputs;
|
||||
PeakMeter* _meter;
|
||||
string _name;
|
||||
Bundle* _input_bundle;
|
||||
Bundle* _output_bundle;
|
||||
bool no_panner_reset;
|
||||
|
|
@ -336,6 +323,8 @@ class IO : public PBD::StatefulDestructible
|
|||
|
||||
private:
|
||||
|
||||
friend class Send;
|
||||
|
||||
/* are these the best variable names ever, or what? */
|
||||
|
||||
sigc::connection input_bundle_configuration_connection;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include <vector>
|
||||
#include <ardour/types.h>
|
||||
#include <ardour/insert.h>
|
||||
#include <pbd/fastlog.h>
|
||||
|
||||
namespace ARDOUR {
|
||||
|
|
@ -32,16 +33,17 @@ class Session;
|
|||
|
||||
/** Meters peaks on the input and stores them for access.
|
||||
*/
|
||||
class PeakMeter {
|
||||
class PeakMeter : public Insert {
|
||||
public:
|
||||
PeakMeter(Session& s) : _session(s) {}
|
||||
PeakMeter(Session& s) : Insert(s, "meter", PreFader) {}
|
||||
|
||||
void setup (const ChanCount& in);
|
||||
void reset ();
|
||||
void reset_max ();
|
||||
|
||||
|
||||
bool configure_io (ChanCount in, ChanCount out);
|
||||
|
||||
/** Compute peaks */
|
||||
void run (BufferSet& bufs, nframes_t nframes, nframes_t offset=0);
|
||||
void run (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset);
|
||||
|
||||
float peak_power (uint32_t n) {
|
||||
if (n < _visible_peak_power.size()) {
|
||||
|
|
@ -64,7 +66,6 @@ private:
|
|||
friend class IO;
|
||||
void meter();
|
||||
|
||||
Session& _session;
|
||||
std::vector<float> _peak_power;
|
||||
std::vector<float> _visible_peak_power;
|
||||
std::vector<float> _max_peak_power;
|
||||
|
|
|
|||
|
|
@ -37,8 +37,6 @@ public:
|
|||
MidiTrack (Session&, const XMLNode&);
|
||||
~MidiTrack ();
|
||||
|
||||
int set_name (string str, void *src);
|
||||
|
||||
int roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
|
||||
nframes_t offset, int declick, bool can_record, bool rec_monitors_input);
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include <pbd/statefuldestructible.h>
|
||||
|
||||
#include <ardour/ardour.h>
|
||||
#include <ardour/session_object.h>
|
||||
#include <ardour/crossfade_compare.h>
|
||||
#include <ardour/location.h>
|
||||
#include <ardour/data_type.h>
|
||||
|
|
@ -47,7 +48,7 @@ namespace ARDOUR {
|
|||
class Session;
|
||||
class Region;
|
||||
|
||||
class Playlist : public PBD::StatefulDestructible, public boost::enable_shared_from_this<Playlist> {
|
||||
class Playlist : public SessionObject, public boost::enable_shared_from_this<Playlist> {
|
||||
public:
|
||||
typedef list<boost::shared_ptr<Region> > RegionList;
|
||||
|
||||
|
|
@ -67,8 +68,7 @@ class Playlist : public PBD::StatefulDestructible, public boost::enable_shared_f
|
|||
void release();
|
||||
bool used () const { return _refcnt != 0; }
|
||||
|
||||
std::string name() const { return _name; }
|
||||
void set_name (std::string str);
|
||||
bool set_name (const string& str);
|
||||
|
||||
const DataType& data_type() const { return _type; }
|
||||
|
||||
|
|
@ -130,8 +130,6 @@ class Playlist : public PBD::StatefulDestructible, public boost::enable_shared_f
|
|||
|
||||
uint32_t read_data_count() const { return _read_data_count; }
|
||||
|
||||
Session& session() { return _session; }
|
||||
|
||||
const PBD::ID& get_orig_diskstream_id () const { return _orig_diskstream_id; }
|
||||
void set_orig_diskstream_id (const PBD::ID& did) { _orig_diskstream_id = did; }
|
||||
|
||||
|
|
@ -170,8 +168,6 @@ class Playlist : public PBD::StatefulDestructible, public boost::enable_shared_f
|
|||
|
||||
RegionList regions; /* the current list of regions in the playlist */
|
||||
std::set<boost::shared_ptr<Region> > all_regions; /* all regions ever added to this playlist */
|
||||
string _name;
|
||||
Session& _session;
|
||||
DataType _type;
|
||||
mutable gint block_notifications;
|
||||
mutable gint ignore_state_changes;
|
||||
|
|
|
|||
|
|
@ -22,13 +22,13 @@
|
|||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <exception>
|
||||
|
||||
#include <sigc++/signal.h>
|
||||
#include <ardour/ardour.h>
|
||||
#include <ardour/plugin_state.h>
|
||||
#include <ardour/types.h>
|
||||
#include <ardour/insert.h>
|
||||
#include <ardour/automation_event.h>
|
||||
|
||||
class XMLNode;
|
||||
|
||||
|
|
@ -105,7 +105,7 @@ class PluginInsert : public Insert
|
|||
|
||||
void parameter_changed (uint32_t, float);
|
||||
|
||||
vector<boost::shared_ptr<Plugin> > _plugins;
|
||||
std::vector<boost::shared_ptr<Plugin> > _plugins;
|
||||
|
||||
void automation_run (BufferSet& bufs, nframes_t nframes, nframes_t offset);
|
||||
void connect_and_run (BufferSet& bufs, nframes_t nframes, nframes_t offset, bool with_auto, nframes_t now = 0);
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
#include <sigc++/signal.h>
|
||||
#include <ardour/ardour.h>
|
||||
#include <ardour/insert.h>
|
||||
#include <ardour/redirect.h>
|
||||
#include <ardour/plugin_state.h>
|
||||
#include <ardour/types.h>
|
||||
|
||||
|
|
@ -37,8 +37,10 @@ namespace ARDOUR {
|
|||
class Session;
|
||||
|
||||
/** Port inserts: send output to a Jack port, pick up input at a Jack port
|
||||
*
|
||||
* PortInsert IS-A Redirect IS-A Insert, IO
|
||||
*/
|
||||
class PortInsert : public Insert
|
||||
class PortInsert : public Redirect
|
||||
{
|
||||
public:
|
||||
PortInsert (Session&, Placement);
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include <pbd/undo.h>
|
||||
|
||||
#include <ardour/ardour.h>
|
||||
#include <ardour/insert.h>
|
||||
#include <ardour/io.h>
|
||||
#include <ardour/automation_event.h>
|
||||
|
||||
|
|
@ -46,97 +47,37 @@ namespace ARDOUR {
|
|||
|
||||
class Session;
|
||||
|
||||
class Redirect : public IO
|
||||
/** A mixer strip element (Insert) with Jack ports (IO).
|
||||
*/
|
||||
class Redirect : public Insert
|
||||
{
|
||||
public:
|
||||
static const string state_node_name;
|
||||
|
||||
Redirect (Session&, const string& name, Placement,
|
||||
int input_min = -1, int input_max = -1, int output_min = -1, int output_max = -1);
|
||||
Redirect (const Redirect&);
|
||||
virtual ~Redirect ();
|
||||
|
||||
virtual ChanCount output_streams() const { return _io->n_outputs(); }
|
||||
virtual ChanCount input_streams () const { return _io->n_inputs(); }
|
||||
virtual ChanCount natural_output_streams() const { return _io->n_outputs(); }
|
||||
virtual ChanCount natural_input_streams () const { return _io->n_inputs(); }
|
||||
|
||||
static boost::shared_ptr<Redirect> clone (boost::shared_ptr<const Redirect>);
|
||||
|
||||
bool active () const { return _active; }
|
||||
void set_active (bool yn, void *src);
|
||||
|
||||
virtual ChanCount output_streams() const { return n_outputs(); }
|
||||
virtual ChanCount input_streams () const { return n_inputs(); }
|
||||
virtual ChanCount natural_output_streams() const { return n_outputs(); }
|
||||
virtual ChanCount natural_input_streams () const { return n_inputs(); }
|
||||
|
||||
uint32_t sort_key() const { return _sort_key; }
|
||||
void set_sort_key (uint32_t key);
|
||||
|
||||
Placement placement() const { return _placement; }
|
||||
void set_placement (Placement, void *src);
|
||||
boost::shared_ptr<IO> io() { return _io; }
|
||||
boost::shared_ptr<const IO> io() const { return _io; }
|
||||
|
||||
virtual void automation_snapshot (nframes_t now) { _io->automation_snapshot(now); }
|
||||
|
||||
virtual void run (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset) = 0;
|
||||
virtual void activate () = 0;
|
||||
virtual void deactivate () = 0;
|
||||
virtual nframes_t latency() { return 0; }
|
||||
void silence (nframes_t nframes, nframes_t offset);
|
||||
|
||||
virtual void set_block_size (nframes_t nframes) {}
|
||||
|
||||
sigc::signal<void,Redirect*,void*> active_changed;
|
||||
sigc::signal<void,Redirect*,void*> placement_changed;
|
||||
sigc::signal<void,Redirect*,bool> AutomationPlaybackChanged;
|
||||
sigc::signal<void,Redirect*,bool> AutomationPlaybackChanged;
|
||||
sigc::signal<void,Redirect*,uint32_t> AutomationChanged;
|
||||
|
||||
static sigc::signal<void,Redirect*> RedirectCreated;
|
||||
|
||||
XMLNode& state (bool full);
|
||||
XMLNode& get_state (void);
|
||||
XMLNode& state (bool full_state);
|
||||
int set_state (const XMLNode&);
|
||||
|
||||
void *get_gui () const { return _gui; }
|
||||
void set_gui (void *p) { _gui = p; }
|
||||
|
||||
virtual string describe_parameter (uint32_t which);
|
||||
virtual float default_parameter_value (uint32_t which) {
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
void what_has_automation (set<uint32_t>&) const;
|
||||
void what_has_visible_automation (set<uint32_t>&) const;
|
||||
const set<uint32_t>& what_can_be_automated () const { return can_automate_list; }
|
||||
|
||||
void mark_automation_visible (uint32_t, bool);
|
||||
|
||||
AutomationList& automation_list (uint32_t);
|
||||
bool find_next_event (nframes_t, nframes_t, ControlEvent&) const;
|
||||
|
||||
virtual void transport_stopped (nframes_t frame) {};
|
||||
|
||||
bool get_next_ab_is_active () const { return _next_ab_is_active; }
|
||||
void set_next_ab_is_active (bool yn);
|
||||
|
||||
protected:
|
||||
/* children may use this stuff as they see fit */
|
||||
|
||||
map<uint32_t,AutomationList*> parameter_automation;
|
||||
set<uint32_t> visible_parameter_automation;
|
||||
|
||||
mutable Glib::Mutex _automation_lock;
|
||||
|
||||
void can_automate (uint32_t);
|
||||
set<uint32_t> can_automate_list;
|
||||
|
||||
virtual void automation_list_creation_callback (uint32_t, AutomationList&) {}
|
||||
|
||||
int set_automation_state (const XMLNode&);
|
||||
XMLNode& get_automation_state ();
|
||||
|
||||
private:
|
||||
bool _active;
|
||||
bool _next_ab_is_active;
|
||||
Placement _placement;
|
||||
uint32_t _sort_key;
|
||||
void* _gui; /* generic, we don't know or care what this is */
|
||||
|
||||
int old_set_automation_state (const XMLNode&);
|
||||
int load_automation (std::string path);
|
||||
boost::shared_ptr<IO> _io;
|
||||
};
|
||||
|
||||
} // namespace ARDOUR
|
||||
|
|
|
|||
|
|
@ -59,7 +59,8 @@ class Route : public IO
|
|||
{
|
||||
protected:
|
||||
|
||||
typedef list<boost::shared_ptr<Redirect> > RedirectList;
|
||||
typedef list<boost::shared_ptr<Insert> > InsertList;
|
||||
|
||||
public:
|
||||
|
||||
enum Flag {
|
||||
|
|
@ -99,7 +100,7 @@ class Route : public IO
|
|||
virtual bool can_record() { return false; }
|
||||
virtual void set_record_enable (bool yn, void *src) {}
|
||||
virtual bool record_enabled() const { return false; }
|
||||
virtual void handle_transport_stopped (bool abort, bool did_locate, bool flush_redirects);
|
||||
virtual void handle_transport_stopped (bool abort, bool did_locate, bool flush_inserts);
|
||||
virtual void set_pending_declick (int);
|
||||
|
||||
/* end of vfunc-based API */
|
||||
|
|
@ -136,54 +137,54 @@ class Route : public IO
|
|||
virtual void set_meter_point (MeterPoint, void *src);
|
||||
MeterPoint meter_point() const { return _meter_point; }
|
||||
|
||||
/* Redirects */
|
||||
/* Inserts */
|
||||
|
||||
void flush_redirects ();
|
||||
void flush_inserts ();
|
||||
|
||||
template<class T> void foreach_redirect (T *obj, void (T::*func)(boost::shared_ptr<Redirect>)) {
|
||||
Glib::RWLock::ReaderLock lm (redirect_lock);
|
||||
for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
|
||||
template<class T> void foreach_insert (T *obj, void (T::*func)(boost::shared_ptr<Insert>)) {
|
||||
Glib::RWLock::ReaderLock lm (insert_lock);
|
||||
for (InsertList::iterator i = _inserts.begin(); i != _inserts.end(); ++i) {
|
||||
(obj->*func) (*i);
|
||||
}
|
||||
}
|
||||
|
||||
boost::shared_ptr<Redirect> nth_redirect (uint32_t n) {
|
||||
Glib::RWLock::ReaderLock lm (redirect_lock);
|
||||
RedirectList::iterator i;
|
||||
for (i = _redirects.begin(); i != _redirects.end() && n; ++i, --n);
|
||||
if (i == _redirects.end()) {
|
||||
boost::shared_ptr<Insert> nth_insert (uint32_t n) {
|
||||
Glib::RWLock::ReaderLock lm (insert_lock);
|
||||
InsertList::iterator i;
|
||||
for (i = _inserts.begin(); i != _inserts.end() && n; ++i, --n);
|
||||
if (i == _inserts.end()) {
|
||||
return boost::shared_ptr<Redirect> ();
|
||||
} else {
|
||||
return *i;
|
||||
}
|
||||
}
|
||||
|
||||
ChanCount max_redirect_outs () const { return redirect_max_outs; }
|
||||
ChanCount max_insert_outs () const { return insert_max_outs; }
|
||||
ChanCount pre_fader_streams() const;
|
||||
|
||||
/** A record of the stream configuration at some point in the redirect list.
|
||||
* Used to return where and why a redirect list configuration request failed.
|
||||
/** A record of the stream configuration at some point in the insert list.
|
||||
* Used to return where and why an insert list configuration request failed.
|
||||
*/
|
||||
struct InsertStreams {
|
||||
InsertStreams(size_t i=0, ChanCount c=ChanCount()) : index(i), count(c) {}
|
||||
|
||||
size_t index; ///< Index of redirect where configuration failed
|
||||
ChanCount count; ///< Input requested of redirect
|
||||
size_t index; ///< Index of insert where configuration failed
|
||||
ChanCount count; ///< Input requested of insert
|
||||
};
|
||||
|
||||
int add_redirect (boost::shared_ptr<Redirect>, void *src, InsertStreams* err = 0);
|
||||
int add_redirects (const RedirectList&, void *src, InsertStreams* err = 0);
|
||||
int remove_redirect (boost::shared_ptr<Redirect>, void *src, InsertStreams* err = 0);
|
||||
int copy_redirects (const Route&, Placement, InsertStreams* err = 0);
|
||||
int sort_redirects (InsertStreams* err = 0);
|
||||
void disable_redirects (Placement);
|
||||
void disable_redirects ();
|
||||
int add_insert (boost::shared_ptr<Insert>, InsertStreams* err = 0);
|
||||
int add_inserts (const InsertList&, InsertStreams* err = 0);
|
||||
int remove_insert (boost::shared_ptr<Insert>, InsertStreams* err = 0);
|
||||
int copy_inserts (const Route&, Placement, InsertStreams* err = 0);
|
||||
int sort_inserts (InsertStreams* err = 0);
|
||||
void disable_inserts (Placement);
|
||||
void disable_inserts ();
|
||||
void disable_plugins (Placement);
|
||||
void disable_plugins ();
|
||||
void ab_plugins (bool forward);
|
||||
void clear_redirects (Placement, void *src);
|
||||
void all_redirects_flip();
|
||||
void all_redirects_active (Placement, bool state);
|
||||
void clear_inserts (Placement);
|
||||
void all_inserts_flip();
|
||||
void all_inserts_active (Placement, bool state);
|
||||
|
||||
virtual nframes_t update_total_latency();
|
||||
nframes_t signal_latency() const { return _own_latency; }
|
||||
|
|
@ -197,7 +198,7 @@ class Route : public IO
|
|||
sigc::signal<void,void*> post_fader_changed;
|
||||
sigc::signal<void,void*> control_outs_changed;
|
||||
sigc::signal<void,void*> main_outs_changed;
|
||||
sigc::signal<void,void*> redirects_changed;
|
||||
sigc::signal<void> inserts_changed;
|
||||
sigc::signal<void,void*> record_enable_changed;
|
||||
sigc::signal<void,void*> edit_group_changed;
|
||||
sigc::signal<void,void*> mix_group_changed;
|
||||
|
|
@ -214,8 +215,8 @@ class Route : public IO
|
|||
int set_state(const XMLNode& node);
|
||||
virtual XMLNode& get_template();
|
||||
|
||||
XMLNode& get_redirect_state ();
|
||||
int set_redirect_state (const XMLNode&);
|
||||
XMLNode& get_insert_state ();
|
||||
int set_insert_state (const XMLNode&);
|
||||
|
||||
sigc::signal<void,void*> SelectedChanged;
|
||||
|
||||
|
|
@ -294,8 +295,8 @@ class Route : public IO
|
|||
nframes_t _initial_delay;
|
||||
nframes_t _roll_delay;
|
||||
nframes_t _own_latency;
|
||||
RedirectList _redirects;
|
||||
Glib::RWLock redirect_lock;
|
||||
InsertList _inserts;
|
||||
Glib::RWLock insert_lock;
|
||||
IO *_control_outs;
|
||||
Glib::Mutex control_outs_lock;
|
||||
RouteGroup *_edit_group;
|
||||
|
|
@ -311,7 +312,7 @@ class Route : public IO
|
|||
|
||||
virtual void process_output_buffers (BufferSet& bufs,
|
||||
nframes_t start_frame, nframes_t end_frame,
|
||||
nframes_t nframes, nframes_t offset, bool with_redirects, int declick,
|
||||
nframes_t nframes, nframes_t offset, bool with_inserts, int declick,
|
||||
bool meter);
|
||||
|
||||
protected:
|
||||
|
|
@ -326,14 +327,14 @@ class Route : public IO
|
|||
|
||||
sigc::connection input_signal_connection;
|
||||
|
||||
ChanCount redirect_max_outs;
|
||||
ChanCount insert_max_outs;
|
||||
uint32_t _remote_control_id;
|
||||
|
||||
uint32_t pans_required() const;
|
||||
ChanCount n_process_buffers ();
|
||||
|
||||
virtual int _set_state (const XMLNode&, bool call_base);
|
||||
virtual void _set_redirect_states (const XMLNodeList&);
|
||||
virtual void _set_insert_states (const XMLNodeList&);
|
||||
|
||||
private:
|
||||
void init ();
|
||||
|
|
@ -354,7 +355,6 @@ class Route : public IO
|
|||
void input_change_handler (IOChange, void *src);
|
||||
void output_change_handler (IOChange, void *src);
|
||||
|
||||
bool legal_redirect (Redirect&);
|
||||
int reset_plugin_counts (InsertStreams*); /* locked */
|
||||
int _reset_plugin_counts (InsertStreams*); /* unlocked */
|
||||
|
||||
|
|
@ -372,8 +372,7 @@ class Route : public IO
|
|||
bool check_some_plugin_counts (std::list<InsertCount>& iclist, ChanCount required_inputs, InsertStreams* err_streams);
|
||||
|
||||
void set_deferred_state ();
|
||||
void add_redirect_from_xml (const XMLNode&);
|
||||
void redirect_active_proxy (Redirect*, void*);
|
||||
void add_insert_from_xml (const XMLNode&);
|
||||
};
|
||||
|
||||
} // namespace ARDOUR
|
||||
|
|
|
|||
|
|
@ -42,6 +42,9 @@ class Send : public Redirect
|
|||
|
||||
uint32_t bit_slot() const { return bitslot; }
|
||||
|
||||
ChanCount output_streams() const;
|
||||
ChanCount input_streams () const;
|
||||
|
||||
void run (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset);
|
||||
|
||||
void activate() {}
|
||||
|
|
@ -54,7 +57,10 @@ class Send : public Redirect
|
|||
int set_state(const XMLNode& node);
|
||||
|
||||
uint32_t pans_required() const { return _expected_inputs.n_audio(); }
|
||||
void expect_inputs (const ChanCount&);
|
||||
|
||||
virtual bool can_support_input_configuration (ChanCount in) const;
|
||||
virtual ChanCount output_for_input_configuration (ChanCount in) const;
|
||||
virtual bool configure_io (ChanCount in, ChanCount out);
|
||||
|
||||
static uint32_t how_many_sends();
|
||||
|
||||
|
|
|
|||
|
|
@ -1374,7 +1374,7 @@ class Session : public PBD::StatefulDestructible
|
|||
|
||||
void set_play_loop (bool yn);
|
||||
void overwrite_some_buffers (Diskstream*);
|
||||
void flush_all_redirects ();
|
||||
void flush_all_inserts ();
|
||||
void locate (nframes_t, bool with_roll, bool with_flush, bool with_loop=false);
|
||||
void start_locate (nframes_t, bool with_roll, bool with_flush, bool with_loop=false);
|
||||
void force_locate (nframes_t frame, bool with_roll = false);
|
||||
|
|
@ -1521,8 +1521,8 @@ class Session : public PBD::StatefulDestructible
|
|||
uint32_t insert_cnt;
|
||||
|
||||
|
||||
void add_redirect (Redirect *);
|
||||
void remove_redirect (Redirect *);
|
||||
void add_insert (Insert *);
|
||||
void remove_insert (Insert *);
|
||||
|
||||
/* S/W RAID */
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,8 @@ class SMFSource : public MidiSource {
|
|||
virtual void mark_capture_end () {}
|
||||
virtual void clear_capture_marks() {}
|
||||
|
||||
int set_name (string newname, bool destructive);
|
||||
bool set_name (const std::string& newname) { return (set_source_name(newname, false) == 0); }
|
||||
int set_source_name (string newname, bool destructive);
|
||||
|
||||
string path() const { return _path; }
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include <pbd/statefuldestructible.h>
|
||||
|
||||
#include <ardour/ardour.h>
|
||||
#include <ardour/session_object.h>
|
||||
#include <ardour/data_type.h>
|
||||
|
||||
namespace ARDOUR {
|
||||
|
|
@ -35,17 +36,14 @@ namespace ARDOUR {
|
|||
class Session;
|
||||
class Playlist;
|
||||
|
||||
class Source : public PBD::StatefulDestructible
|
||||
class Source : public SessionObject
|
||||
{
|
||||
public:
|
||||
Source (Session&, std::string name, DataType type);
|
||||
Source (Session&, const std::string& name, DataType type);
|
||||
Source (Session&, const XMLNode&);
|
||||
|
||||
virtual ~Source ();
|
||||
|
||||
std::string name() const { return _name; }
|
||||
int set_name (std::string str, bool destructive);
|
||||
|
||||
|
||||
DataType type() { return _type; }
|
||||
|
||||
time_t timestamp() const { return _timestamp; }
|
||||
|
|
@ -76,8 +74,6 @@ class Source : public PBD::StatefulDestructible
|
|||
protected:
|
||||
void update_length (nframes_t pos, nframes_t cnt);
|
||||
|
||||
Session& _session;
|
||||
string _name;
|
||||
DataType _type;
|
||||
time_t _timestamp;
|
||||
nframes_t _length;
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ class Track : public Route
|
|||
|
||||
virtual ~Track ();
|
||||
|
||||
int set_name (string str, void *src);
|
||||
bool set_name (const std::string& str);
|
||||
|
||||
TrackMode mode () const { return _mode; }
|
||||
virtual int set_mode (TrackMode m) { return false; }
|
||||
|
|
|
|||
|
|
@ -2024,7 +2024,7 @@ AudioDiskstream::rename_write_sources ()
|
|||
|
||||
for (chan = c->begin(), n = 0; chan != c->end(); ++chan, ++n) {
|
||||
if ((*chan)->write_source != 0) {
|
||||
(*chan)->write_source->set_name (_name, destructive());
|
||||
(*chan)->write_source->set_source_name (_name, destructive());
|
||||
/* XXX what to do if one of them fails ? */
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -515,7 +515,7 @@ AudioTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
|
|||
boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
|
||||
|
||||
{
|
||||
Glib::RWLock::ReaderLock lm (redirect_lock, Glib::TRY_LOCK);
|
||||
Glib::RWLock::ReaderLock lm (insert_lock, Glib::TRY_LOCK);
|
||||
if (lm.locked()) {
|
||||
// automation snapshot can also be called from the non-rt context
|
||||
// and it uses the redirect list, so we take the lock out here
|
||||
|
|
@ -524,7 +524,7 @@ AudioTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
|
|||
}
|
||||
|
||||
|
||||
if (n_outputs().n_total() == 0 && _redirects.empty()) {
|
||||
if (n_outputs().n_total() == 0 && _inserts.empty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -601,7 +601,7 @@ AudioTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
|
|||
if (!diskstream->record_enabled() && _session.transport_rolling()) {
|
||||
Glib::Mutex::Lock am (automation_lock, Glib::TRY_LOCK);
|
||||
|
||||
if (am.locked() && gain_automation_playback()) {
|
||||
if (am.locked() && _gain_automation_curve.automation_playback()) {
|
||||
apply_gain_automation = _gain_automation_curve.rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes);
|
||||
}
|
||||
}
|
||||
|
|
@ -620,7 +620,7 @@ int
|
|||
AudioTrack::silent_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset,
|
||||
bool can_record, bool rec_monitors_input)
|
||||
{
|
||||
if (n_outputs().n_total() == 0 && _redirects.empty()) {
|
||||
if (n_outputs().n_total() == 0 && _inserts.empty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -643,12 +643,12 @@ AudioTrack::export_stuff (BufferSet& buffers, nframes_t start, nframes_t nframes
|
|||
gain_t gain_automation[nframes];
|
||||
gain_t gain_buffer[nframes];
|
||||
float mix_buffer[nframes];
|
||||
RedirectList::iterator i;
|
||||
InsertList::iterator i;
|
||||
bool post_fader_work = false;
|
||||
gain_t this_gain = _gain;
|
||||
boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
|
||||
|
||||
Glib::RWLock::ReaderLock rlock (redirect_lock);
|
||||
Glib::RWLock::ReaderLock rlock (insert_lock);
|
||||
|
||||
boost::shared_ptr<AudioPlaylist> apl = boost::dynamic_pointer_cast<AudioPlaylist>(diskstream->playlist());
|
||||
assert(apl);
|
||||
|
|
@ -681,7 +681,7 @@ AudioTrack::export_stuff (BufferSet& buffers, nframes_t start, nframes_t nframes
|
|||
will already have checked that there are no external port inserts.
|
||||
*/
|
||||
|
||||
for (i = _redirects.begin(); i != _redirects.end(); ++i) {
|
||||
for (i = _inserts.begin(); i != _inserts.end(); ++i) {
|
||||
boost::shared_ptr<Insert> insert;
|
||||
|
||||
if ((insert = boost::dynamic_pointer_cast<Insert>(*i)) != 0) {
|
||||
|
|
@ -719,7 +719,7 @@ AudioTrack::export_stuff (BufferSet& buffers, nframes_t start, nframes_t nframes
|
|||
|
||||
if (post_fader_work) {
|
||||
|
||||
for (i = _redirects.begin(); i != _redirects.end(); ++i) {
|
||||
for (i = _inserts.begin(); i != _inserts.end(); ++i) {
|
||||
boost::shared_ptr<PluginInsert> insert;
|
||||
|
||||
if ((insert = boost::dynamic_pointer_cast<PluginInsert>(*i)) != 0) {
|
||||
|
|
@ -800,9 +800,9 @@ AudioTrack::freeze (InterThreadInfo& itt)
|
|||
_freeze_record.have_mementos = true;
|
||||
|
||||
{
|
||||
Glib::RWLock::ReaderLock lm (redirect_lock);
|
||||
Glib::RWLock::ReaderLock lm (insert_lock);
|
||||
|
||||
for (RedirectList::iterator r = _redirects.begin(); r != _redirects.end(); ++r) {
|
||||
for (InsertList::iterator r = _inserts.begin(); r != _inserts.end(); ++r) {
|
||||
|
||||
boost::shared_ptr<Insert> insert;
|
||||
|
||||
|
|
@ -816,7 +816,8 @@ AudioTrack::freeze (InterThreadInfo& itt)
|
|||
|
||||
/* now deactivate the insert */
|
||||
|
||||
insert->set_active (false, this);
|
||||
insert->set_active (false);
|
||||
_session.set_dirty ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -857,8 +858,8 @@ AudioTrack::unfreeze ()
|
|||
|
||||
} else {
|
||||
|
||||
Glib::RWLock::ReaderLock lm (redirect_lock); // should this be a write lock? jlc
|
||||
for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
|
||||
Glib::RWLock::ReaderLock lm (insert_lock); // should this be a write lock? jlc
|
||||
for (InsertList::iterator i = _inserts.begin(); i != _inserts.end(); ++i) {
|
||||
for (vector<FreezeRecordInsertInfo*>::iterator ii = _freeze_record.insert_info.begin(); ii != _freeze_record.insert_info.end(); ++ii) {
|
||||
if ((*ii)->id == (*i)->id()) {
|
||||
(*i)->set_state (((*ii)->state));
|
||||
|
|
|
|||
|
|
@ -573,7 +573,7 @@ AudioFileSource::set_allow_remove_if_empty (bool yn)
|
|||
}
|
||||
|
||||
int
|
||||
AudioFileSource::set_name (ustring newname, bool destructive)
|
||||
AudioFileSource::set_source_name (ustring newname, bool destructive)
|
||||
{
|
||||
Glib::Mutex::Lock lm (_lock);
|
||||
ustring oldpath = _path;
|
||||
|
|
|
|||
267
libs/ardour/automatable.cc
Normal file
267
libs/ardour/automatable.cc
Normal file
|
|
@ -0,0 +1,267 @@
|
|||
/*
|
||||
Copyright (C) 2001,2007 Paul Davis
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
#include <ardour/ardour.h>
|
||||
#include <fstream>
|
||||
#include <inttypes.h>
|
||||
#include <cstdio>
|
||||
#include <errno.h>
|
||||
#include <pbd/error.h>
|
||||
#include <pbd/enumwriter.h>
|
||||
#include <ardour/session.h>
|
||||
#include <ardour/automatable.h>
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace ARDOUR;
|
||||
using namespace PBD;
|
||||
|
||||
|
||||
Automatable::Automatable(Session& _session, const string& name)
|
||||
: SessionObject(_session, name)
|
||||
, _last_automation_snapshot(0)
|
||||
{}
|
||||
|
||||
int
|
||||
Automatable::old_set_automation_state (const XMLNode& node)
|
||||
{
|
||||
const XMLProperty *prop;
|
||||
|
||||
if ((prop = node.property ("path")) != 0) {
|
||||
load_automation (prop->value());
|
||||
} else {
|
||||
warning << string_compose(_("%1: Automation node has no path property"), _name) << endmsg;
|
||||
}
|
||||
|
||||
if ((prop = node.property ("visible")) != 0) {
|
||||
uint32_t what;
|
||||
stringstream sstr;
|
||||
|
||||
_visible_parameter_automation.clear ();
|
||||
|
||||
sstr << prop->value();
|
||||
while (1) {
|
||||
sstr >> what;
|
||||
if (sstr.fail()) {
|
||||
break;
|
||||
}
|
||||
mark_automation_visible (what, true);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
Automatable::load_automation (const string& path)
|
||||
{
|
||||
string fullpath;
|
||||
|
||||
if (path[0] == '/') { // legacy
|
||||
fullpath = path;
|
||||
} else {
|
||||
fullpath = _session.automation_dir();
|
||||
fullpath += path;
|
||||
}
|
||||
ifstream in (fullpath.c_str());
|
||||
|
||||
if (!in) {
|
||||
warning << string_compose(_("%1: cannot open %2 to load automation data (%3)"), _name, fullpath, strerror (errno)) << endmsg;
|
||||
return 1;
|
||||
}
|
||||
|
||||
Glib::Mutex::Lock lm (_automation_lock);
|
||||
set<uint32_t> tosave;
|
||||
_parameter_automation.clear ();
|
||||
|
||||
while (in) {
|
||||
double when;
|
||||
double value;
|
||||
uint32_t port;
|
||||
|
||||
in >> port; if (!in) break;
|
||||
in >> when; if (!in) goto bad;
|
||||
in >> value; if (!in) goto bad;
|
||||
|
||||
AutomationList& al = automation_list (port);
|
||||
al.add (when, value);
|
||||
tosave.insert (port);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
bad:
|
||||
error << string_compose(_("%1: cannot load automation data from %2"), _name, fullpath) << endmsg;
|
||||
_parameter_automation.clear ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Automatable::what_has_automation (set<uint32_t>& s) const
|
||||
{
|
||||
Glib::Mutex::Lock lm (_automation_lock);
|
||||
map<uint32_t,AutomationList*>::const_iterator li;
|
||||
|
||||
for (li = _parameter_automation.begin(); li != _parameter_automation.end(); ++li) {
|
||||
s.insert ((*li).first);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Automatable::what_has_visible_automation (set<uint32_t>& s) const
|
||||
{
|
||||
Glib::Mutex::Lock lm (_automation_lock);
|
||||
set<uint32_t>::const_iterator li;
|
||||
|
||||
for (li = _visible_parameter_automation.begin(); li != _visible_parameter_automation.end(); ++li) {
|
||||
s.insert (*li);
|
||||
}
|
||||
}
|
||||
AutomationList&
|
||||
Automatable::automation_list (uint32_t parameter)
|
||||
{
|
||||
AutomationList* al = _parameter_automation[parameter];
|
||||
|
||||
if (al == 0) {
|
||||
al = _parameter_automation[parameter] = new AutomationList (default_parameter_value (parameter));
|
||||
/* let derived classes do whatever they need with this */
|
||||
automation_list_creation_callback (parameter, *al);
|
||||
}
|
||||
|
||||
return *al;
|
||||
}
|
||||
|
||||
string
|
||||
Automatable::describe_parameter (uint32_t which)
|
||||
{
|
||||
/* derived classes will override this */
|
||||
return "";
|
||||
}
|
||||
|
||||
void
|
||||
Automatable::can_automate (uint32_t what)
|
||||
{
|
||||
_can_automate_list.insert (what);
|
||||
}
|
||||
|
||||
void
|
||||
Automatable::mark_automation_visible (uint32_t what, bool yn)
|
||||
{
|
||||
if (yn) {
|
||||
_visible_parameter_automation.insert (what);
|
||||
} else {
|
||||
set<uint32_t>::iterator i;
|
||||
|
||||
if ((i = _visible_parameter_automation.find (what)) != _visible_parameter_automation.end()) {
|
||||
_visible_parameter_automation.erase (i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Automatable::find_next_event (nframes_t now, nframes_t end, ControlEvent& next_event) const
|
||||
{
|
||||
map<uint32_t,AutomationList*>::const_iterator li;
|
||||
AutomationList::TimeComparator cmp;
|
||||
|
||||
next_event.when = max_frames;
|
||||
|
||||
for (li = _parameter_automation.begin(); li != _parameter_automation.end(); ++li) {
|
||||
|
||||
AutomationList::const_iterator i;
|
||||
const AutomationList& alist (*((*li).second));
|
||||
ControlEvent cp (now, 0.0f);
|
||||
|
||||
for (i = lower_bound (alist.const_begin(), alist.const_end(), &cp, cmp); i != alist.const_end() && (*i)->when < end; ++i) {
|
||||
if ((*i)->when > now) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i != alist.const_end() && (*i)->when < end) {
|
||||
|
||||
if ((*i)->when < next_event.when) {
|
||||
next_event.when = (*i)->when;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return next_event.when != max_frames;
|
||||
}
|
||||
|
||||
int
|
||||
Automatable::set_automation_state (const XMLNode& node)
|
||||
{
|
||||
Glib::Mutex::Lock lm (_automation_lock);
|
||||
|
||||
_parameter_automation.clear ();
|
||||
|
||||
XMLNodeList nlist = node.children();
|
||||
XMLNodeIterator niter;
|
||||
|
||||
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
||||
uint32_t param;
|
||||
|
||||
if (sscanf ((*niter)->name().c_str(), "parameter-%" PRIu32, ¶m) != 1) {
|
||||
error << string_compose (_("%2: badly formatted node name in XML automation state, ignored"), _name) << endmsg;
|
||||
continue;
|
||||
}
|
||||
|
||||
AutomationList& al = automation_list (param);
|
||||
if (al.set_state (*(*niter)->children().front())) {
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
bad:
|
||||
error << string_compose(_("%1: cannot load automation data from XML"), _name) << endmsg;
|
||||
_parameter_automation.clear ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
XMLNode&
|
||||
Automatable::get_automation_state ()
|
||||
{
|
||||
Glib::Mutex::Lock lm (_automation_lock);
|
||||
XMLNode* node = new XMLNode (X_("Automation"));
|
||||
string fullpath;
|
||||
|
||||
if (_parameter_automation.empty()) {
|
||||
return *node;
|
||||
}
|
||||
|
||||
map<uint32_t,AutomationList*>::iterator li;
|
||||
|
||||
for (li = _parameter_automation.begin(); li != _parameter_automation.end(); ++li) {
|
||||
|
||||
XMLNode* child;
|
||||
|
||||
char buf[64];
|
||||
stringstream str;
|
||||
snprintf (buf, sizeof (buf), "parameter-%" PRIu32, li->first);
|
||||
child = new XMLNode (buf);
|
||||
child->add_child_nocopy (li->second->get_state ());
|
||||
}
|
||||
|
||||
return *node;
|
||||
}
|
||||
|
|
@ -67,14 +67,13 @@ sigc::signal<void> Diskstream::DiskOverrun;
|
|||
sigc::signal<void> Diskstream::DiskUnderrun;
|
||||
|
||||
Diskstream::Diskstream (Session &sess, const string &name, Flag flag)
|
||||
: _name (name)
|
||||
, _session (sess)
|
||||
: SessionObject(sess, name)
|
||||
{
|
||||
init (flag);
|
||||
}
|
||||
|
||||
Diskstream::Diskstream (Session& sess, const XMLNode& node)
|
||||
: _session (sess)
|
||||
: SessionObject(sess, "unnamed diskstream")
|
||||
{
|
||||
init (Recordable);
|
||||
}
|
||||
|
|
@ -377,23 +376,24 @@ Diskstream::playlist_deleted (boost::weak_ptr<Playlist> wpl)
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
Diskstream::set_name (string str)
|
||||
bool
|
||||
Diskstream::set_name (const string& str)
|
||||
{
|
||||
if (str != _name) {
|
||||
assert(playlist());
|
||||
playlist()->set_name (str);
|
||||
_name = str;
|
||||
|
||||
SessionObject::set_name(str);
|
||||
|
||||
if (!in_set_state && recordable()) {
|
||||
/* rename existing capture files so that they have the correct name */
|
||||
return rename_write_sources ();
|
||||
} else {
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include <sigc++/bind.h>
|
||||
|
||||
#include <pbd/failed_constructor.h>
|
||||
#include <pbd/enumwriter.h>
|
||||
#include <pbd/xml++.h>
|
||||
|
||||
#include <ardour/insert.h>
|
||||
|
|
@ -30,6 +31,9 @@
|
|||
#include <ardour/route.h>
|
||||
#include <ardour/ladspa_plugin.h>
|
||||
#include <ardour/buffer_set.h>
|
||||
#include <ardour/send.h>
|
||||
#include <ardour/port_insert.h>
|
||||
#include <ardour/plugin_insert.h>
|
||||
|
||||
#ifdef VST_SUPPORT
|
||||
#include <ardour/vst_plugin.h>
|
||||
|
|
@ -49,17 +53,214 @@ using namespace std;
|
|||
using namespace ARDOUR;
|
||||
using namespace PBD;
|
||||
|
||||
Insert::Insert(Session& s, string name, Placement p)
|
||||
: Redirect (s, name, p)
|
||||
sigc::signal<void,Insert*> Insert::InsertCreated;
|
||||
|
||||
// Always saved as Insert, but may be Redirect in legacy sessions
|
||||
const string Insert::state_node_name = "Insert";
|
||||
|
||||
Insert::Insert(Session& session, const string& name, Placement p)
|
||||
: Automatable(session, name)
|
||||
, _active(false)
|
||||
, _next_ab_is_active(false)
|
||||
, _configured(false)
|
||||
, _placement(p)
|
||||
, _gui(0)
|
||||
{
|
||||
// FIXME: default type?
|
||||
}
|
||||
|
||||
Insert::Insert(Session& s, string name, Placement p, int imin, int imax, int omin, int omax)
|
||||
: Redirect (s, name, p, imin, imax, omin, omax)
|
||||
, _configured(false)
|
||||
boost::shared_ptr<Insert>
|
||||
Insert::clone (boost::shared_ptr<const Insert> other)
|
||||
{
|
||||
// FIXME: default type?
|
||||
boost::shared_ptr<const Send> send;
|
||||
boost::shared_ptr<const PortInsert> port_insert;
|
||||
boost::shared_ptr<const PluginInsert> plugin_insert;
|
||||
|
||||
if ((send = boost::dynamic_pointer_cast<const Send>(other)) != 0) {
|
||||
return boost::shared_ptr<Insert> (new Send (*send));
|
||||
} else if ((port_insert = boost::dynamic_pointer_cast<const PortInsert>(other)) != 0) {
|
||||
return boost::shared_ptr<Insert> (new PortInsert (*port_insert));
|
||||
} else if ((plugin_insert = boost::dynamic_pointer_cast<const PluginInsert>(other)) != 0) {
|
||||
return boost::shared_ptr<Insert> (new PluginInsert (*plugin_insert));
|
||||
} else {
|
||||
fatal << _("programming error: unknown Insert type in Insert::Clone!\n")
|
||||
<< endmsg;
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
return boost::shared_ptr<Insert>();
|
||||
}
|
||||
|
||||
void
|
||||
Insert::set_sort_key (uint32_t key)
|
||||
{
|
||||
_sort_key = key;
|
||||
}
|
||||
|
||||
void
|
||||
Insert::set_placement (Placement p)
|
||||
{
|
||||
if (_placement != p) {
|
||||
_placement = p;
|
||||
PlacementChanged (); /* EMIT SIGNAL */
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Insert::set_active (bool yn)
|
||||
{
|
||||
_active = yn;
|
||||
ActiveChanged ();
|
||||
}
|
||||
|
||||
XMLNode&
|
||||
Insert::get_state (void)
|
||||
{
|
||||
return state (true);
|
||||
}
|
||||
|
||||
/* NODE STRUCTURE
|
||||
|
||||
<Automation [optionally with visible="...." ]>
|
||||
<parameter-N>
|
||||
<AutomationList id=N>
|
||||
<events>
|
||||
X1 Y1
|
||||
X2 Y2
|
||||
....
|
||||
</events>
|
||||
</parameter-N>
|
||||
<Automation>
|
||||
*/
|
||||
|
||||
XMLNode&
|
||||
Insert::state (bool full_state)
|
||||
{
|
||||
XMLNode* node = new XMLNode (state_node_name);
|
||||
stringstream sstr;
|
||||
|
||||
// FIXME: This conflicts with "id" used by plugin for name in legacy sessions (ugh).
|
||||
// Do we need to serialize this?
|
||||
/*
|
||||
char buf[64];
|
||||
id().print (buf, sizeof (buf));
|
||||
node->add_property("id", buf);
|
||||
*/
|
||||
|
||||
node->add_property("name", _name);
|
||||
node->add_property("active", active() ? "yes" : "no");
|
||||
node->add_property("placement", enum_2_string (_placement));
|
||||
|
||||
if (_extra_xml){
|
||||
node->add_child_copy (*_extra_xml);
|
||||
}
|
||||
|
||||
if (full_state) {
|
||||
|
||||
XMLNode& automation = Automatable::get_automation_state();
|
||||
|
||||
for (set<uint32_t>::iterator x = _visible_parameter_automation.begin(); x != _visible_parameter_automation.end(); ++x) {
|
||||
if (x != _visible_parameter_automation.begin()) {
|
||||
sstr << ' ';
|
||||
}
|
||||
sstr << *x;
|
||||
}
|
||||
|
||||
automation.add_property ("visible", sstr.str());
|
||||
|
||||
node->add_child_nocopy (automation);
|
||||
}
|
||||
|
||||
return *node;
|
||||
}
|
||||
|
||||
int
|
||||
Insert::set_state (const XMLNode& node)
|
||||
{
|
||||
const XMLProperty *prop;
|
||||
|
||||
if (node.name() != state_node_name) {
|
||||
error << string_compose(_("incorrect XML node \"%1\" passed to Redirect object"), node.name()) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((prop = node.property ("name")) == 0) {
|
||||
warning << _("XML node describing an insert is missing the `name' field") << endmsg;
|
||||
} else {
|
||||
set_name(prop->value());
|
||||
}
|
||||
|
||||
XMLNodeList nlist = node.children();
|
||||
XMLNodeIterator niter;
|
||||
bool have_io = false;
|
||||
|
||||
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
||||
|
||||
if ((*niter)->name() == X_("Automation")) {
|
||||
|
||||
|
||||
XMLProperty *prop;
|
||||
|
||||
if ((prop = (*niter)->property ("path")) != 0) {
|
||||
old_set_automation_state (*(*niter));
|
||||
} else {
|
||||
Automatable::set_automation_state (*(*niter));
|
||||
}
|
||||
|
||||
if ((prop = (*niter)->property ("visible")) != 0) {
|
||||
uint32_t what;
|
||||
stringstream sstr;
|
||||
|
||||
_visible_parameter_automation.clear ();
|
||||
|
||||
sstr << prop->value();
|
||||
while (1) {
|
||||
sstr >> what;
|
||||
if (sstr.fail()) {
|
||||
break;
|
||||
}
|
||||
mark_automation_visible (what, true);
|
||||
}
|
||||
}
|
||||
|
||||
} else if ((*niter)->name() == "extra") {
|
||||
_extra_xml = new XMLNode (*(*niter));
|
||||
}
|
||||
}
|
||||
|
||||
if (!have_io && dynamic_cast<IO*>(this)) {
|
||||
error << _("XML node describing a redirect is missing an IO node") << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((prop = node.property ("active")) == 0) {
|
||||
error << _("XML node describing an insert is missing the `active' field") << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_active != (prop->value() == "yes")) {
|
||||
_active = !_active;
|
||||
ActiveChanged (); /* EMIT_SIGNAL */
|
||||
}
|
||||
|
||||
if ((prop = node.property ("placement")) == 0) {
|
||||
error << _("XML node describing an insert is missing the `placement' field") << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* hack to handle older sessions before we only used EnumWriter */
|
||||
|
||||
string pstr;
|
||||
|
||||
if (prop->value() == "pre") {
|
||||
pstr = "PreFader";
|
||||
} else if (prop->value() == "post") {
|
||||
pstr = "PostFader";
|
||||
} else {
|
||||
pstr = prop->value();
|
||||
}
|
||||
|
||||
Placement p = Placement (string_2_enum (pstr, p));
|
||||
set_placement (p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -98,12 +98,11 @@ static double direct_gain_to_control (gain_t gain) {
|
|||
/** @param default_type The type of port that will be created by ensure_io
|
||||
* and friends if no type is explicitly requested (to avoid breakage).
|
||||
*/
|
||||
IO::IO (Session& s, string name,
|
||||
IO::IO (Session& s, const string& name,
|
||||
int input_min, int input_max, int output_min, int output_max,
|
||||
DataType default_type)
|
||||
: _session (s),
|
||||
: SessionObject(s, name),
|
||||
_output_buffers(new BufferSet()),
|
||||
_name (name),
|
||||
_default_type(default_type),
|
||||
_gain_control (X_("gaincontrol"), *this),
|
||||
_gain_automation_curve (0.0, 2.0, 1.0),
|
||||
|
|
@ -158,7 +157,7 @@ IO::IO (Session& s, string name,
|
|||
}
|
||||
|
||||
IO::IO (Session& s, const XMLNode& node, DataType dt)
|
||||
: _session (s),
|
||||
: SessionObject(s, "unnamed io"),
|
||||
_output_buffers(new BufferSet()),
|
||||
_default_type (dt),
|
||||
_gain_control (X_("gaincontrol"), *this),
|
||||
|
|
@ -324,7 +323,7 @@ IO::just_meter_input (nframes_t start_frame, nframes_t end_frame,
|
|||
|
||||
collect_input (bufs, nframes, offset);
|
||||
|
||||
_meter->run(bufs, nframes);
|
||||
_meter->run(bufs, start_frame, end_frame, nframes, offset);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1130,7 +1129,7 @@ IO::ensure_outputs (ChanCount count, bool clear, bool lockit, void* src)
|
|||
gain_t
|
||||
IO::effective_gain () const
|
||||
{
|
||||
if (gain_automation_playback()) {
|
||||
if (_gain_automation_curve.automation_playback()) {
|
||||
return _effective_gain;
|
||||
} else {
|
||||
return _desired_gain;
|
||||
|
|
@ -1826,14 +1825,15 @@ IO::parse_gain_string (const string& str, vector<string>& ports)
|
|||
return ports.size();
|
||||
}
|
||||
|
||||
int
|
||||
IO::set_name (string name, void* src)
|
||||
bool
|
||||
IO::set_name (const string& str)
|
||||
{
|
||||
if (name == _name) {
|
||||
return 0;
|
||||
if (str == _name) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* replace all colons in the name. i wish we didn't have to do this */
|
||||
string name = str;
|
||||
|
||||
if (replace_all (name, ":", "-")) {
|
||||
warning << _("you cannot use colons to name objects with I/O connections") << endmsg;
|
||||
|
|
@ -1851,10 +1851,7 @@ IO::set_name (string name, void* src)
|
|||
i->set_name (current_name);
|
||||
}
|
||||
|
||||
_name = name;
|
||||
name_changed (src); /* EMIT SIGNAL */
|
||||
|
||||
return 0;
|
||||
return SessionObject::set_name(name);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -2169,7 +2166,8 @@ IO::GainControllable::get_value (void) const
|
|||
void
|
||||
IO::setup_peak_meters()
|
||||
{
|
||||
_meter->setup(std::max(_inputs.count(), _outputs.count()));
|
||||
ChanCount max_streams = std::max(_inputs.count(), _outputs.count());
|
||||
_meter->configure_io(max_streams, max_streams);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2226,28 +2224,17 @@ IO::set_gain_automation_state (AutoState state)
|
|||
|
||||
if (changed) {
|
||||
_session.set_dirty ();
|
||||
gain_automation_state_changed (); /* EMIT SIGNAL */
|
||||
//gain_automation_state_changed (); /* EMIT SIGNAL */
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
IO::set_gain_automation_style (AutoStyle style)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
{
|
||||
Glib::Mutex::Lock lm (automation_lock);
|
||||
|
||||
if (style != _gain_automation_curve.automation_style()) {
|
||||
changed = true;
|
||||
_gain_automation_curve.set_automation_style (style);
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
gain_automation_style_changed (); /* EMIT SIGNAL */
|
||||
}
|
||||
Glib::Mutex::Lock lm (automation_lock);
|
||||
_gain_automation_curve.set_automation_style (style);
|
||||
}
|
||||
|
||||
void
|
||||
IO::inc_gain (gain_t factor, void *src)
|
||||
{
|
||||
|
|
@ -2276,7 +2263,7 @@ IO::set_gain (gain_t val, void *src)
|
|||
gain_changed (src);
|
||||
_gain_control.Changed (); /* EMIT SIGNAL */
|
||||
|
||||
if (_session.transport_stopped() && src != 0 && src != this && gain_automation_recording()) {
|
||||
if (_session.transport_stopped() && src != 0 && src != this && _gain_automation_curve.automation_write()) {
|
||||
_gain_automation_curve.add (_session.transport_frame(), val);
|
||||
|
||||
}
|
||||
|
|
@ -2318,7 +2305,7 @@ IO::automation_snapshot (nframes_t now)
|
|||
{
|
||||
if (last_automation_snapshot > now || (now - last_automation_snapshot) > _automation_interval) {
|
||||
|
||||
if (gain_automation_recording()) {
|
||||
if (_gain_automation_curve.automation_write()) {
|
||||
_gain_automation_curve.rt_add (now, gain());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ namespace ARDOUR {
|
|||
* be set to 0.
|
||||
*/
|
||||
void
|
||||
PeakMeter::run (BufferSet& bufs, nframes_t nframes, nframes_t offset)
|
||||
PeakMeter::run (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset)
|
||||
{
|
||||
size_t meterable = std::min(bufs.count().n_total(), _peak_power.size());
|
||||
|
||||
|
|
@ -93,9 +93,13 @@ PeakMeter::reset_max ()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
PeakMeter::setup (const ChanCount& in)
|
||||
bool
|
||||
PeakMeter::configure_io (ChanCount in, ChanCount out)
|
||||
{
|
||||
/* we're transparent no matter what. fight the power. */
|
||||
if (out != in)
|
||||
return false;
|
||||
|
||||
uint32_t limit = in.n_total();
|
||||
|
||||
while (_peak_power.size() > limit) {
|
||||
|
|
@ -113,6 +117,10 @@ PeakMeter::setup (const ChanCount& in)
|
|||
assert(_peak_power.size() == limit);
|
||||
assert(_visible_peak_power.size() == limit);
|
||||
assert(_max_peak_power.size() == limit);
|
||||
|
||||
Insert::configure_io(in, out);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** To be driven by the Meter signal from IO.
|
||||
|
|
|
|||
|
|
@ -1391,7 +1391,7 @@ int
|
|||
MidiDiskstream::rename_write_sources ()
|
||||
{
|
||||
if (_write_source != 0) {
|
||||
_write_source->set_name (_name, destructive());
|
||||
_write_source->set_source_name (_name, destructive());
|
||||
/* XXX what to do if this fails ? */
|
||||
}
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -427,7 +427,7 @@ MidiTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
|
|||
int dret;
|
||||
boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
|
||||
|
||||
if (n_outputs().n_total() == 0 && _redirects.empty()) {
|
||||
if (n_outputs().n_total() == 0 && _inserts.empty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -498,7 +498,7 @@ int
|
|||
MidiTrack::silent_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset,
|
||||
bool can_record, bool rec_monitors_input)
|
||||
{
|
||||
if (n_outputs().n_midi() == 0 && _redirects.empty()) {
|
||||
if (n_outputs().n_midi() == 0 && _inserts.empty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -518,29 +518,29 @@ MidiTrack::silent_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_
|
|||
void
|
||||
MidiTrack::process_output_buffers (BufferSet& bufs,
|
||||
nframes_t start_frame, nframes_t end_frame,
|
||||
nframes_t nframes, nframes_t offset, bool with_redirects, int declick,
|
||||
nframes_t nframes, nframes_t offset, bool with_inserts, int declick,
|
||||
bool meter)
|
||||
{
|
||||
/* There's no such thing as a MIDI bus for the time being, to avoid diverging from trunk
|
||||
* too much until the SoC settles down. We'll do all the MIDI route work here for now,
|
||||
* but the long-term goal is to have Route::process_output_buffers handle everything */
|
||||
/* There's no such thing as a MIDI bus for the time being.
|
||||
* We'll do all the MIDI route work here for now, but the long-term goal is to have
|
||||
* Route::process_output_buffers handle everything */
|
||||
|
||||
if (meter && (_meter_point == MeterInput || _meter_point == MeterPreFader)) {
|
||||
_meter->run(bufs, nframes);
|
||||
_meter->run(bufs, start_frame, end_frame, nframes, offset);
|
||||
}
|
||||
|
||||
// Run all redirects
|
||||
if (with_redirects) {
|
||||
Glib::RWLock::ReaderLock rm (redirect_lock, Glib::TRY_LOCK);
|
||||
// Run all inserts
|
||||
if (with_inserts) {
|
||||
Glib::RWLock::ReaderLock rm (insert_lock, Glib::TRY_LOCK);
|
||||
if (rm.locked()) {
|
||||
for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
|
||||
for (InsertList::iterator i = _inserts.begin(); i != _inserts.end(); ++i) {
|
||||
(*i)->run (bufs, start_frame, end_frame, nframes, offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (meter && (_meter_point == MeterPostFader)) {
|
||||
_meter->run(bufs, nframes);
|
||||
_meter->run(bufs, start_frame, end_frame, nframes, offset);
|
||||
}
|
||||
|
||||
// Main output stage
|
||||
|
|
@ -551,28 +551,6 @@ MidiTrack::process_output_buffers (BufferSet& bufs,
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
MidiTrack::set_name (string str, void *src)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (record_enabled() && _session.actively_recording()) {
|
||||
/* this messes things up if done while recording */
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_diskstream->set_name (str)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* save state so that the statefile fully reflects any filename changes */
|
||||
|
||||
if ((ret = IO::set_name (str, src)) == 0) {
|
||||
_session.save_state ("");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
MidiTrack::export_stuff (BufferSet& bufs, nframes_t nframes, nframes_t end_frame)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ struct RegionSortByLastLayerOp {
|
|||
};
|
||||
|
||||
Playlist::Playlist (Session& sess, string nom, DataType type, bool hide)
|
||||
: _session (sess)
|
||||
: SessionObject(sess, nom)
|
||||
, _type(type)
|
||||
{
|
||||
init (hide);
|
||||
|
|
@ -81,7 +81,7 @@ Playlist::Playlist (Session& sess, string nom, DataType type, bool hide)
|
|||
}
|
||||
|
||||
Playlist::Playlist (Session& sess, const XMLNode& node, DataType type, bool hide)
|
||||
: _session (sess)
|
||||
: SessionObject(sess, "unnamed playlist")
|
||||
, _type(type)
|
||||
{
|
||||
const XMLProperty* prop = node.property("type");
|
||||
|
|
@ -94,7 +94,7 @@ Playlist::Playlist (Session& sess, const XMLNode& node, DataType type, bool hide
|
|||
}
|
||||
|
||||
Playlist::Playlist (boost::shared_ptr<const Playlist> other, string namestr, bool hide)
|
||||
: _name (namestr), _session (other->_session), _type(other->_type), _orig_diskstream_id(other->_orig_diskstream_id)
|
||||
: SessionObject(other->_session, namestr), _type(other->_type), _orig_diskstream_id(other->_orig_diskstream_id)
|
||||
{
|
||||
init (hide);
|
||||
|
||||
|
|
@ -126,7 +126,7 @@ Playlist::Playlist (boost::shared_ptr<const Playlist> other, string namestr, boo
|
|||
}
|
||||
|
||||
Playlist::Playlist (boost::shared_ptr<const Playlist> other, nframes_t start, nframes_t cnt, string str, bool hide)
|
||||
: _name (str), _session (other->_session), _type(other->_type), _orig_diskstream_id(other->_orig_diskstream_id)
|
||||
: SessionObject(other->_session, str), _type(other->_type), _orig_diskstream_id(other->_orig_diskstream_id)
|
||||
{
|
||||
RegionLock rlock2 (const_cast<Playlist*> (other.get()));
|
||||
|
||||
|
|
@ -247,14 +247,14 @@ Playlist::init (bool hide)
|
|||
}
|
||||
|
||||
Playlist::Playlist (const Playlist& pl)
|
||||
: _session (pl._session)
|
||||
: SessionObject(pl._session, pl._name)
|
||||
, _type(pl.data_type())
|
||||
{
|
||||
fatal << _("playlist const copy constructor called") << endmsg;
|
||||
}
|
||||
|
||||
Playlist::Playlist (Playlist& pl)
|
||||
: _session (pl._session)
|
||||
: SessionObject(pl._session, pl._name)
|
||||
, _type(pl.data_type())
|
||||
{
|
||||
fatal << _("playlist non-const copy constructor called") << endmsg;
|
||||
|
|
@ -273,8 +273,8 @@ Playlist::~Playlist ()
|
|||
/* GoingAway must be emitted by derived classes */
|
||||
}
|
||||
|
||||
void
|
||||
Playlist::set_name (string str)
|
||||
bool
|
||||
Playlist::set_name (const string& str)
|
||||
{
|
||||
/* in a typical situation, a playlist is being used
|
||||
by one diskstream and also is referenced by the
|
||||
|
|
@ -283,11 +283,10 @@ Playlist::set_name (string str)
|
|||
*/
|
||||
|
||||
if (_refcnt > 2) {
|
||||
return;
|
||||
return false;
|
||||
} else {
|
||||
return SessionObject::set_name(str);
|
||||
}
|
||||
|
||||
_name = str;
|
||||
NameChanged(); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include <ardour/route.h>
|
||||
#include <ardour/ladspa_plugin.h>
|
||||
#include <ardour/buffer_set.h>
|
||||
#include <ardour/automation_event.h>
|
||||
|
||||
#ifdef VST_SUPPORT
|
||||
#include <ardour/vst_plugin.h>
|
||||
|
|
@ -67,11 +68,11 @@ PluginInsert::PluginInsert (Session& s, boost::shared_ptr<Plugin> plug, Placemen
|
|||
IO::MoreChannels (max(input_streams(), output_streams()));
|
||||
}
|
||||
|
||||
RedirectCreated (this); /* EMIT SIGNAL */
|
||||
InsertCreated (this); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
PluginInsert::PluginInsert (Session& s, const XMLNode& node)
|
||||
: Insert (s, "will change", PreFader)
|
||||
: Insert (s, "unnamed plugin insert", PreFader)
|
||||
{
|
||||
if (set_state (node)) {
|
||||
throw failed_constructor();
|
||||
|
|
@ -88,7 +89,7 @@ PluginInsert::PluginInsert (Session& s, const XMLNode& node)
|
|||
}
|
||||
|
||||
PluginInsert::PluginInsert (const PluginInsert& other)
|
||||
: Insert (other._session, other.plugin()->name(), other.placement())
|
||||
: Insert (other._session, other._name, other.placement())
|
||||
{
|
||||
uint32_t count = other._plugins.size();
|
||||
|
||||
|
|
@ -102,7 +103,7 @@ PluginInsert::PluginInsert (const PluginInsert& other)
|
|||
|
||||
init ();
|
||||
|
||||
RedirectCreated (this); /* EMIT SIGNAL */
|
||||
InsertCreated (this); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -272,7 +273,7 @@ PluginInsert::connect_and_run (BufferSet& bufs, nframes_t nframes, nframes_t off
|
|||
map<uint32_t,AutomationList*>::iterator li;
|
||||
uint32_t n;
|
||||
|
||||
for (n = 0, li = parameter_automation.begin(); li != parameter_automation.end(); ++li, ++n) {
|
||||
for (n = 0, li = _parameter_automation.begin(); li != _parameter_automation.end(); ++li, ++n) {
|
||||
|
||||
AutomationList& alist (*((*li).second));
|
||||
|
||||
|
|
@ -302,14 +303,14 @@ PluginInsert::automation_snapshot (nframes_t now)
|
|||
{
|
||||
map<uint32_t,AutomationList*>::iterator li;
|
||||
|
||||
for (li = parameter_automation.begin(); li != parameter_automation.end(); ++li) {
|
||||
for (li =_parameter_automation.begin(); li !=_parameter_automation.end(); ++li) {
|
||||
|
||||
AutomationList *alist = ((*li).second);
|
||||
if (alist != 0 && alist->automation_write ()) {
|
||||
|
||||
float val = _plugins[0]->get_parameter ((*li).first);
|
||||
alist->rt_add (now, val);
|
||||
last_automation_snapshot = now;
|
||||
_last_automation_snapshot = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -319,7 +320,7 @@ PluginInsert::transport_stopped (nframes_t now)
|
|||
{
|
||||
map<uint32_t,AutomationList*>::iterator li;
|
||||
|
||||
for (li = parameter_automation.begin(); li != parameter_automation.end(); ++li) {
|
||||
for (li =_parameter_automation.begin(); li !=_parameter_automation.end(); ++li) {
|
||||
AutomationList& alist (*(li->second));
|
||||
alist.reposition_for_rt_add (now);
|
||||
|
||||
|
|
@ -353,6 +354,9 @@ PluginInsert::run (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame,
|
|||
connect_and_run (bufs, nframes, offset, false);
|
||||
}
|
||||
} else {
|
||||
|
||||
/* FIXME: type, audio only */
|
||||
|
||||
uint32_t in = _plugins[0]->get_info()->n_inputs.n_audio();
|
||||
uint32_t out = _plugins[0]->get_info()->n_outputs.n_audio();
|
||||
|
||||
|
|
@ -365,7 +369,7 @@ PluginInsert::run (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame,
|
|||
}
|
||||
}
|
||||
|
||||
bufs.count().set(_default_type, out);
|
||||
bufs.count().set_audio(out);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -526,26 +530,41 @@ PluginInsert::configure_io (ChanCount in, ChanCount out)
|
|||
return false;
|
||||
} else {
|
||||
bool success = set_count (count_for_configuration(in, out));
|
||||
if (success) {
|
||||
_configured = true;
|
||||
_configured_input = in;
|
||||
}
|
||||
if (success)
|
||||
Insert::configure_io(in, out);
|
||||
return success;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
PluginInsert::can_support_input_configuration (ChanCount in_count) const
|
||||
PluginInsert::can_support_input_configuration (ChanCount in) const
|
||||
{
|
||||
int32_t outputs = _plugins[0]->get_info()->n_outputs.get(_default_type);
|
||||
int32_t inputs = _plugins[0]->get_info()->n_inputs.get(_default_type);
|
||||
int32_t in = in_count.get(_default_type);
|
||||
ChanCount outputs = _plugins[0]->get_info()->n_outputs;
|
||||
ChanCount inputs = _plugins[0]->get_info()->n_inputs;
|
||||
|
||||
/* see output_for_input_configuration below */
|
||||
if ((inputs == 0)
|
||||
|| (outputs == 1 && inputs == 1)
|
||||
|| (inputs == in)
|
||||
|| ((inputs < in) && (inputs % in == 0))) {
|
||||
if ((inputs.n_total() == 0)
|
||||
|| (inputs.n_total() == 1 && outputs == inputs)
|
||||
|| (inputs.n_total() == 1 && outputs == inputs
|
||||
&& ((inputs.n_audio() == 0 && in.n_audio() == 0)
|
||||
|| (inputs.n_midi() == 0 && in.n_midi() == 0)))
|
||||
|| (inputs == in)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool can_replicate = true;
|
||||
|
||||
/* if number of inputs is a factor of the requested input
|
||||
configuration for every type, we can replicate.
|
||||
*/
|
||||
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
|
||||
if (inputs.get(*t) >= in.get(*t) || (inputs.get(*t) % in.get(*t) != 0)) {
|
||||
can_replicate = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (can_replicate && (in.n_total() % inputs.n_total() == 0)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
|
@ -563,7 +582,9 @@ PluginInsert::output_for_input_configuration (ChanCount in) const
|
|||
return outputs;
|
||||
}
|
||||
|
||||
if (inputs.n_total() == 1 && outputs == inputs) {
|
||||
if (inputs.n_total() == 1 && outputs == inputs
|
||||
&& ((inputs.n_audio() == 0 && in.n_audio() == 0)
|
||||
|| (inputs.n_midi() == 0 && in.n_midi() == 0))) {
|
||||
/* mono plugin, replicate as needed to match in */
|
||||
return in;
|
||||
}
|
||||
|
|
@ -573,17 +594,26 @@ PluginInsert::output_for_input_configuration (ChanCount in) const
|
|||
return outputs;
|
||||
}
|
||||
|
||||
// FIXME: single type plugins only. can we do this for instruments?
|
||||
if ((inputs.n_total() == inputs.get(_default_type))
|
||||
&& ((in.n_total() == in.get(_default_type))
|
||||
&& (inputs.n_total() < in.n_total())
|
||||
&& (inputs.n_total() % in.n_total() == 0))) {
|
||||
bool can_replicate = true;
|
||||
|
||||
/* number of inputs is a factor of the requested input
|
||||
configuration, so we can replicate.
|
||||
*/
|
||||
/* if number of inputs is a factor of the requested input
|
||||
configuration for every type, we can replicate.
|
||||
*/
|
||||
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
|
||||
if (inputs.get(*t) >= in.get(*t) || (in.get(*t) % inputs.get(*t) != 0)) {
|
||||
can_replicate = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ChanCount(_default_type, in.n_total() / inputs.n_total());
|
||||
if (can_replicate && (inputs.n_total() % in.n_total() == 0)) {
|
||||
ChanCount output;
|
||||
|
||||
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
|
||||
output.set(*t, outputs.get(*t) * (in.get(*t) / inputs.get(*t)));
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/* sorry */
|
||||
|
|
@ -606,7 +636,9 @@ PluginInsert::count_for_configuration (ChanCount in, ChanCount out) const
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (inputs.n_total() == 1 && outputs == inputs) {
|
||||
if (inputs.n_total() == 1 && outputs == inputs
|
||||
&& ((inputs.n_audio() == 0 && in.n_audio() == 0)
|
||||
|| (inputs.n_midi() == 0 && in.n_midi() == 0))) {
|
||||
/* mono plugin, replicate as needed to match in */
|
||||
return in.n_total();
|
||||
}
|
||||
|
|
@ -616,20 +648,14 @@ PluginInsert::count_for_configuration (ChanCount in, ChanCount out) const
|
|||
return 1;
|
||||
}
|
||||
|
||||
// FIXME: single type plugins only. can we do this for instruments?
|
||||
if ((inputs.n_total() == inputs.get(_default_type))
|
||||
&& ((in.n_total() == in.get(_default_type))
|
||||
&& (inputs.n_total() < in.n_total())
|
||||
&& (inputs.n_total() % in.n_total() == 0))) {
|
||||
|
||||
/* number of inputs is a factor of the requested input
|
||||
configuration, so we can replicate.
|
||||
*/
|
||||
// assumes in is valid, so we must be replicating
|
||||
if (inputs.n_total() < in.n_total()
|
||||
&& (in.n_total() % inputs.n_total() == 0)) {
|
||||
|
||||
return in.n_total() / inputs.n_total();
|
||||
}
|
||||
|
||||
/* sorry */
|
||||
/* err... */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -643,20 +669,18 @@ XMLNode&
|
|||
PluginInsert::state (bool full)
|
||||
{
|
||||
char buf[256];
|
||||
XMLNode *node = new XMLNode("Insert");
|
||||
XMLNode& node = Insert::state (full);
|
||||
|
||||
node->add_child_nocopy (Redirect::state (full));
|
||||
|
||||
node->add_property ("type", _plugins[0]->state_node_name());
|
||||
node.add_property ("type", _plugins[0]->state_node_name());
|
||||
snprintf(buf, sizeof(buf), "%s", _plugins[0]->name());
|
||||
node->add_property("id", string(buf));
|
||||
node.add_property("id", string(buf));
|
||||
if (_plugins[0]->state_node_name() == "ladspa") {
|
||||
char buf[32];
|
||||
snprintf (buf, sizeof (buf), "%ld", _plugins[0]->get_info()->unique_id);
|
||||
node->add_property("unique-id", string(buf));
|
||||
node.add_property("unique-id", string(buf));
|
||||
}
|
||||
node->add_property("count", string_compose("%1", _plugins.size()));
|
||||
node->add_child_nocopy (_plugins[0]->get_state());
|
||||
node.add_property("count", string_compose("%1", _plugins.size()));
|
||||
node.add_child_nocopy (_plugins[0]->get_state());
|
||||
|
||||
/* add port automation state */
|
||||
XMLNode *autonode = new XMLNode(port_automation_node_name);
|
||||
|
|
@ -672,9 +696,9 @@ PluginInsert::state (bool full)
|
|||
autonode->add_child_nocopy (*child);
|
||||
}
|
||||
|
||||
node->add_child_nocopy (*autonode);
|
||||
node.add_child_nocopy (*autonode);
|
||||
|
||||
return *node;
|
||||
return node;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -752,23 +776,18 @@ PluginInsert::set_state(const XMLNode& node)
|
|||
}
|
||||
}
|
||||
|
||||
const XMLNode* insert_node = &node;
|
||||
|
||||
// legacy sessions: search for child Redirect node
|
||||
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
||||
if ((*niter)->name() == Redirect::state_node_name) {
|
||||
Redirect::set_state (**niter);
|
||||
if ((*niter)->name() == "Redirect") {
|
||||
insert_node = *niter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (niter == nlist.end()) {
|
||||
error << _("XML node describing insert is missing a Redirect node") << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (niter == nlist.end()) {
|
||||
error << string_compose(_("XML node describing a plugin insert is missing the `%1' information"), plugin->state_node_name()) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
Insert::set_state (*insert_node);
|
||||
|
||||
/* look for port automation node */
|
||||
|
||||
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
||||
|
|
@ -835,7 +854,7 @@ PluginInsert::set_state(const XMLNode& node)
|
|||
}
|
||||
|
||||
// The name of the PluginInsert comes from the plugin, nothing else
|
||||
set_name(plugin->get_info()->name,this);
|
||||
_name = plugin->get_info()->name;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,41 +41,41 @@ using namespace ARDOUR;
|
|||
using namespace PBD;
|
||||
|
||||
PortInsert::PortInsert (Session& s, Placement p)
|
||||
: Insert (s, string_compose (_("insert %1"), (bitslot = s.next_insert_id()) + 1), p, 1, -1, 1, -1)
|
||||
: Redirect (s, string_compose (_("insert %1"), (bitslot = s.next_insert_id()) + 1), p, 1, -1, 1, -1)
|
||||
{
|
||||
init ();
|
||||
RedirectCreated (this); /* EMIT SIGNAL */
|
||||
InsertCreated (this); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
PortInsert::PortInsert (const PortInsert& other)
|
||||
: Insert (other._session, string_compose (_("insert %1"), (bitslot = other._session.next_insert_id()) + 1), other.placement(), 1, -1, 1, -1)
|
||||
: Redirect (other._session, string_compose (_("insert %1"), (bitslot = other._session.next_insert_id()) + 1), other.placement(), 1, -1, 1, -1)
|
||||
{
|
||||
init ();
|
||||
RedirectCreated (this); /* EMIT SIGNAL */
|
||||
InsertCreated (this); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
void
|
||||
PortInsert::init ()
|
||||
{
|
||||
if (add_input_port ("", this)) {
|
||||
if (_io->add_input_port ("", this)) {
|
||||
error << _("PortInsert: cannot add input port") << endmsg;
|
||||
throw failed_constructor();
|
||||
}
|
||||
|
||||
if (add_output_port ("", this)) {
|
||||
if (_io->add_output_port ("", this)) {
|
||||
error << _("PortInsert: cannot add output port") << endmsg;
|
||||
throw failed_constructor();
|
||||
}
|
||||
}
|
||||
|
||||
PortInsert::PortInsert (Session& s, const XMLNode& node)
|
||||
: Insert (s, "will change", PreFader)
|
||||
: Redirect (s, "unnamed port insert", PreFader)
|
||||
{
|
||||
if (set_state (node)) {
|
||||
throw failed_constructor();
|
||||
}
|
||||
|
||||
RedirectCreated (this); /* EMIT SIGNAL */
|
||||
InsertCreated (this); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
PortInsert::~PortInsert ()
|
||||
|
|
@ -86,19 +86,19 @@ PortInsert::~PortInsert ()
|
|||
void
|
||||
PortInsert::run (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset)
|
||||
{
|
||||
if (n_outputs().get(_default_type) == 0) {
|
||||
if (_io->n_outputs().n_total() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!active()) {
|
||||
/* deliver silence */
|
||||
silence (nframes, offset);
|
||||
_io->silence (nframes, offset);
|
||||
return;
|
||||
}
|
||||
|
||||
deliver_output(bufs, start_frame, end_frame, nframes, offset);
|
||||
_io->deliver_output(bufs, start_frame, end_frame, nframes, offset);
|
||||
|
||||
collect_input(bufs, nframes, offset);
|
||||
_io->collect_input(bufs, nframes, offset);
|
||||
}
|
||||
|
||||
XMLNode&
|
||||
|
|
@ -110,14 +110,13 @@ PortInsert::get_state(void)
|
|||
XMLNode&
|
||||
PortInsert::state (bool full)
|
||||
{
|
||||
XMLNode *node = new XMLNode("Insert");
|
||||
XMLNode& node = Redirect::state(full);
|
||||
char buf[32];
|
||||
node->add_child_nocopy (Redirect::state(full));
|
||||
node->add_property ("type", "port");
|
||||
node.add_property ("type", "port");
|
||||
snprintf (buf, sizeof (buf), "%" PRIu32, bitslot);
|
||||
node->add_property ("bitslot", buf);
|
||||
node.add_property ("bitslot", buf);
|
||||
|
||||
return *node;
|
||||
return node;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -145,17 +144,17 @@ PortInsert::set_state(const XMLNode& node)
|
|||
_session.mark_insert_id (bitslot);
|
||||
}
|
||||
|
||||
const XMLNode* insert_node = &node;
|
||||
|
||||
// legacy sessions: search for child Redirect node
|
||||
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
||||
if ((*niter)->name() == Redirect::state_node_name) {
|
||||
Redirect::set_state (**niter);
|
||||
if ((*niter)->name() == "Redirect") {
|
||||
insert_node = *niter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (niter == nlist.end()) {
|
||||
error << _("XML node describing insert is missing a Redirect node") << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
Redirect::set_state (*insert_node);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -170,13 +169,13 @@ PortInsert::latency()
|
|||
need to take that into account too.
|
||||
*/
|
||||
|
||||
return _session.engine().frames_per_cycle() + input_latency();
|
||||
return _session.engine().frames_per_cycle() + _io->input_latency();
|
||||
}
|
||||
|
||||
bool
|
||||
PortInsert::can_support_input_configuration (ChanCount in) const
|
||||
{
|
||||
if (input_maximum() == ChanCount::INFINITE && output_maximum() == ChanCount::INFINITE) {
|
||||
if (_io->input_maximum() == ChanCount::INFINITE && _io->output_maximum() == ChanCount::INFINITE) {
|
||||
|
||||
/* not configured yet */
|
||||
|
||||
|
|
@ -188,7 +187,7 @@ PortInsert::can_support_input_configuration (ChanCount in) const
|
|||
many output ports it will have.
|
||||
*/
|
||||
|
||||
if (output_maximum() == in) {
|
||||
if (_io->output_maximum() == in) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -220,23 +219,28 @@ PortInsert::configure_io (ChanCount in, ChanCount out)
|
|||
to the number of input ports we need.
|
||||
*/
|
||||
|
||||
set_output_maximum (in);
|
||||
set_output_minimum (in);
|
||||
set_input_maximum (out);
|
||||
set_input_minimum (out);
|
||||
_io->set_output_maximum (in);
|
||||
_io->set_output_minimum (in);
|
||||
_io->set_input_maximum (out);
|
||||
_io->set_input_minimum (out);
|
||||
|
||||
return (ensure_io (out, in, false, this) == 0);
|
||||
bool success = (_io->ensure_io (out, in, false, this) == 0);
|
||||
|
||||
if (success)
|
||||
return Insert::configure_io(in, out);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
ChanCount
|
||||
PortInsert::output_streams() const
|
||||
{
|
||||
return n_inputs ();
|
||||
return _io->n_inputs ();
|
||||
}
|
||||
|
||||
ChanCount
|
||||
PortInsert::input_streams() const
|
||||
{
|
||||
return n_outputs ();
|
||||
return _io->n_outputs ();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,17 +42,13 @@ using namespace std;
|
|||
using namespace ARDOUR;
|
||||
using namespace PBD;
|
||||
|
||||
const string Redirect::state_node_name = "Redirect";
|
||||
sigc::signal<void,Redirect*> Redirect::RedirectCreated;
|
||||
|
||||
Redirect::Redirect (Session& s, const string& name, Placement p,
|
||||
int input_min, int input_max,
|
||||
int output_min, int output_max)
|
||||
: IO (s, name, input_min, input_max, output_min, output_max)
|
||||
: Insert(s, name, p)
|
||||
, _io(new IO(s, name, input_min, input_max, output_min, output_max))
|
||||
{
|
||||
_placement = p;
|
||||
_active = false;
|
||||
_next_ab_is_active = false;
|
||||
_sort_key = 0;
|
||||
_gui = 0;
|
||||
_extra_xml = 0;
|
||||
|
|
@ -63,161 +59,22 @@ Redirect::~Redirect ()
|
|||
notify_callbacks ();
|
||||
}
|
||||
|
||||
boost::shared_ptr<Redirect>
|
||||
Redirect::clone (boost::shared_ptr<const Redirect> other)
|
||||
{
|
||||
boost::shared_ptr<const Send> send;
|
||||
boost::shared_ptr<const PortInsert> port_insert;
|
||||
boost::shared_ptr<const PluginInsert> plugin_insert;
|
||||
|
||||
if ((send = boost::dynamic_pointer_cast<const Send>(other)) != 0) {
|
||||
return boost::shared_ptr<Redirect> (new Send (*send));
|
||||
} else if ((port_insert = boost::dynamic_pointer_cast<const PortInsert>(other)) != 0) {
|
||||
return boost::shared_ptr<Redirect> (new PortInsert (*port_insert));
|
||||
} else if ((plugin_insert = boost::dynamic_pointer_cast<const PluginInsert>(other)) != 0) {
|
||||
return boost::shared_ptr<Redirect> (new PluginInsert (*plugin_insert));
|
||||
} else {
|
||||
fatal << _("programming error: unknown Redirect type in Redirect::Clone!\n")
|
||||
<< endmsg;
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
return boost::shared_ptr<Redirect>();
|
||||
}
|
||||
|
||||
void
|
||||
Redirect::set_sort_key (uint32_t key)
|
||||
{
|
||||
_sort_key = key;
|
||||
}
|
||||
|
||||
void
|
||||
Redirect::set_placement (Placement p, void *src)
|
||||
{
|
||||
if (_placement != p) {
|
||||
_placement = p;
|
||||
placement_changed (this, src); /* EMIT SIGNAL */
|
||||
}
|
||||
}
|
||||
|
||||
/* NODE STRUCTURE
|
||||
|
||||
<Automation [optionally with visible="...." ]>
|
||||
<parameter-N>
|
||||
<AutomationList id=N>
|
||||
<events>
|
||||
X1 Y1
|
||||
X2 Y2
|
||||
....
|
||||
</events>
|
||||
</parameter-N>
|
||||
<Automation>
|
||||
*/
|
||||
|
||||
int
|
||||
Redirect::set_automation_state (const XMLNode& node)
|
||||
{
|
||||
Glib::Mutex::Lock lm (_automation_lock);
|
||||
|
||||
parameter_automation.clear ();
|
||||
|
||||
XMLNodeList nlist = node.children();
|
||||
XMLNodeIterator niter;
|
||||
|
||||
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
||||
uint32_t param;
|
||||
|
||||
if (sscanf ((*niter)->name().c_str(), "parameter-%" PRIu32, ¶m) != 1) {
|
||||
error << string_compose (_("%2: badly formatted node name in XML automation state, ignored"), _name) << endmsg;
|
||||
continue;
|
||||
}
|
||||
|
||||
AutomationList& al = automation_list (param);
|
||||
if (al.set_state (*(*niter)->children().front())) {
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
bad:
|
||||
error << string_compose(_("%1: cannot load automation data from XML"), _name) << endmsg;
|
||||
parameter_automation.clear ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
XMLNode&
|
||||
Redirect::get_automation_state ()
|
||||
{
|
||||
Glib::Mutex::Lock lm (_automation_lock);
|
||||
XMLNode* node = new XMLNode (X_("Automation"));
|
||||
string fullpath;
|
||||
|
||||
if (parameter_automation.empty()) {
|
||||
return *node;
|
||||
}
|
||||
|
||||
map<uint32_t,AutomationList*>::iterator li;
|
||||
|
||||
for (li = parameter_automation.begin(); li != parameter_automation.end(); ++li) {
|
||||
|
||||
XMLNode* child;
|
||||
|
||||
char buf[64];
|
||||
stringstream str;
|
||||
snprintf (buf, sizeof (buf), "parameter-%" PRIu32, li->first);
|
||||
child = new XMLNode (buf);
|
||||
child->add_child_nocopy (li->second->get_state ());
|
||||
}
|
||||
|
||||
return *node;
|
||||
}
|
||||
|
||||
XMLNode&
|
||||
Redirect::get_state (void)
|
||||
{
|
||||
return state (true);
|
||||
}
|
||||
|
||||
XMLNode&
|
||||
Redirect::state (bool full_state)
|
||||
{
|
||||
XMLNode* node = new XMLNode (state_node_name);
|
||||
stringstream sstr;
|
||||
|
||||
node->add_property("active", active() ? "yes" : "no");
|
||||
node->add_property("placement", enum_2_string (_placement));
|
||||
node->add_child_nocopy (IO::state (full_state));
|
||||
|
||||
if (_extra_xml){
|
||||
node->add_child_copy (*_extra_xml);
|
||||
}
|
||||
XMLNode& node = Insert::state(full_state);
|
||||
|
||||
if (full_state) {
|
||||
node.add_child_nocopy (_io->state (full_state));
|
||||
|
||||
XMLNode& automation = get_automation_state();
|
||||
|
||||
for (set<uint32_t>::iterator x = visible_parameter_automation.begin(); x != visible_parameter_automation.end(); ++x) {
|
||||
if (x != visible_parameter_automation.begin()) {
|
||||
sstr << ' ';
|
||||
}
|
||||
sstr << *x;
|
||||
}
|
||||
|
||||
automation.add_property ("visible", sstr.str());
|
||||
|
||||
node->add_child_nocopy (automation);
|
||||
}
|
||||
|
||||
return *node;
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Redirect::set_state (const XMLNode& node)
|
||||
{
|
||||
const XMLProperty *prop;
|
||||
Insert::set_state(node);
|
||||
|
||||
if (node.name() != state_node_name) {
|
||||
if (node.name() != "Insert" && node.name() != "Redirect") {
|
||||
error << string_compose(_("incorrect XML node \"%1\" passed to Redirect object"), node.name()) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -227,260 +84,22 @@ Redirect::set_state (const XMLNode& node)
|
|||
bool have_io = false;
|
||||
|
||||
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
||||
|
||||
if ((*niter)->name() == IO::state_node_name) {
|
||||
|
||||
IO::set_state (**niter);
|
||||
have_io = true;
|
||||
|
||||
} else if ((*niter)->name() == X_("Automation")) {
|
||||
|
||||
|
||||
XMLProperty *prop;
|
||||
|
||||
if ((prop = (*niter)->property ("path")) != 0) {
|
||||
old_set_automation_state (*(*niter));
|
||||
} else {
|
||||
set_automation_state (*(*niter));
|
||||
}
|
||||
|
||||
if ((prop = (*niter)->property ("visible")) != 0) {
|
||||
uint32_t what;
|
||||
stringstream sstr;
|
||||
|
||||
visible_parameter_automation.clear ();
|
||||
|
||||
sstr << prop->value();
|
||||
while (1) {
|
||||
sstr >> what;
|
||||
if (sstr.fail()) {
|
||||
break;
|
||||
}
|
||||
mark_automation_visible (what, true);
|
||||
}
|
||||
}
|
||||
|
||||
} else if ((*niter)->name() == "extra") {
|
||||
_extra_xml = new XMLNode (*(*niter));
|
||||
_io->set_state(**niter);
|
||||
}
|
||||
}
|
||||
|
||||
if (!have_io) {
|
||||
error << _("XML node describing an IO is missing an IO node") << endmsg;
|
||||
error << _("XML node describing a redirect is missing an IO node") << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((prop = node.property ("active")) == 0) {
|
||||
error << _("XML node describing a redirect is missing the `active' field") << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_active != (prop->value() == "yes")) {
|
||||
_active = !_active;
|
||||
active_changed (this, this); /* EMIT_SIGNAL */
|
||||
}
|
||||
|
||||
if ((prop = node.property ("placement")) == 0) {
|
||||
error << _("XML node describing a redirect is missing the `placement' field") << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* hack to handle older sessions before we only used EnumWriter */
|
||||
|
||||
string pstr;
|
||||
|
||||
if (prop->value() == "pre") {
|
||||
pstr = "PreFader";
|
||||
} else if (prop->value() == "post") {
|
||||
pstr = "PostFader";
|
||||
} else {
|
||||
pstr = prop->value();
|
||||
}
|
||||
|
||||
Placement p = Placement (string_2_enum (pstr, p));
|
||||
set_placement (p, this);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
Redirect::old_set_automation_state (const XMLNode& node)
|
||||
{
|
||||
const XMLProperty *prop;
|
||||
|
||||
if ((prop = node.property ("path")) != 0) {
|
||||
load_automation (prop->value());
|
||||
} else {
|
||||
warning << string_compose(_("%1: Automation node has no path property"), _name) << endmsg;
|
||||
}
|
||||
|
||||
if ((prop = node.property ("visible")) != 0) {
|
||||
uint32_t what;
|
||||
stringstream sstr;
|
||||
|
||||
visible_parameter_automation.clear ();
|
||||
|
||||
sstr << prop->value();
|
||||
while (1) {
|
||||
sstr >> what;
|
||||
if (sstr.fail()) {
|
||||
break;
|
||||
}
|
||||
mark_automation_visible (what, true);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
Redirect::load_automation (string path)
|
||||
{
|
||||
string fullpath;
|
||||
|
||||
if (path[0] == '/') { // legacy
|
||||
fullpath = path;
|
||||
} else {
|
||||
fullpath = _session.automation_dir();
|
||||
fullpath += path;
|
||||
}
|
||||
ifstream in (fullpath.c_str());
|
||||
|
||||
if (!in) {
|
||||
warning << string_compose(_("%1: cannot open %2 to load automation data (%3)"), _name, fullpath, strerror (errno)) << endmsg;
|
||||
return 1;
|
||||
}
|
||||
|
||||
Glib::Mutex::Lock lm (_automation_lock);
|
||||
set<uint32_t> tosave;
|
||||
parameter_automation.clear ();
|
||||
|
||||
while (in) {
|
||||
double when;
|
||||
double value;
|
||||
uint32_t port;
|
||||
|
||||
in >> port; if (!in) break;
|
||||
in >> when; if (!in) goto bad;
|
||||
in >> value; if (!in) goto bad;
|
||||
|
||||
AutomationList& al = automation_list (port);
|
||||
al.add (when, value);
|
||||
tosave.insert (port);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
bad:
|
||||
error << string_compose(_("%1: cannot load automation data from %2"), _name, fullpath) << endmsg;
|
||||
parameter_automation.clear ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Redirect::what_has_automation (set<uint32_t>& s) const
|
||||
Redirect::silence (nframes_t nframes, nframes_t offset)
|
||||
{
|
||||
Glib::Mutex::Lock lm (_automation_lock);
|
||||
map<uint32_t,AutomationList*>::const_iterator li;
|
||||
|
||||
for (li = parameter_automation.begin(); li != parameter_automation.end(); ++li) {
|
||||
s.insert ((*li).first);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Redirect::what_has_visible_automation (set<uint32_t>& s) const
|
||||
{
|
||||
Glib::Mutex::Lock lm (_automation_lock);
|
||||
set<uint32_t>::const_iterator li;
|
||||
|
||||
for (li = visible_parameter_automation.begin(); li != visible_parameter_automation.end(); ++li) {
|
||||
s.insert (*li);
|
||||
}
|
||||
}
|
||||
AutomationList&
|
||||
Redirect::automation_list (uint32_t parameter)
|
||||
{
|
||||
AutomationList* al = parameter_automation[parameter];
|
||||
|
||||
if (al == 0) {
|
||||
al = parameter_automation[parameter] = new AutomationList (default_parameter_value (parameter));
|
||||
/* let derived classes do whatever they need with this */
|
||||
automation_list_creation_callback (parameter, *al);
|
||||
}
|
||||
|
||||
return *al;
|
||||
}
|
||||
|
||||
string
|
||||
Redirect::describe_parameter (uint32_t which)
|
||||
{
|
||||
/* derived classes will override this */
|
||||
return "";
|
||||
}
|
||||
|
||||
void
|
||||
Redirect::can_automate (uint32_t what)
|
||||
{
|
||||
can_automate_list.insert (what);
|
||||
}
|
||||
|
||||
void
|
||||
Redirect::mark_automation_visible (uint32_t what, bool yn)
|
||||
{
|
||||
if (yn) {
|
||||
visible_parameter_automation.insert (what);
|
||||
} else {
|
||||
set<uint32_t>::iterator i;
|
||||
|
||||
if ((i = visible_parameter_automation.find (what)) != visible_parameter_automation.end()) {
|
||||
visible_parameter_automation.erase (i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Redirect::find_next_event (nframes_t now, nframes_t end, ControlEvent& next_event) const
|
||||
{
|
||||
map<uint32_t,AutomationList*>::const_iterator li;
|
||||
AutomationList::TimeComparator cmp;
|
||||
|
||||
next_event.when = max_frames;
|
||||
|
||||
for (li = parameter_automation.begin(); li != parameter_automation.end(); ++li) {
|
||||
|
||||
AutomationList::const_iterator i;
|
||||
const AutomationList& alist (*((*li).second));
|
||||
ControlEvent cp (now, 0.0f);
|
||||
|
||||
for (i = lower_bound (alist.const_begin(), alist.const_end(), &cp, cmp); i != alist.const_end() && (*i)->when < end; ++i) {
|
||||
if ((*i)->when > now) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i != alist.const_end() && (*i)->when < end) {
|
||||
|
||||
if ((*i)->when < next_event.when) {
|
||||
next_event.when = (*i)->when;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return next_event.when != max_frames;
|
||||
}
|
||||
|
||||
void
|
||||
Redirect::set_active (bool yn, void* src)
|
||||
{
|
||||
_active = yn;
|
||||
active_changed (this, src);
|
||||
_session.set_dirty ();
|
||||
}
|
||||
|
||||
void
|
||||
Redirect::set_next_ab_is_active (bool yn)
|
||||
{
|
||||
_next_ab_is_active = yn;
|
||||
_io->silence(nframes, offset);
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -149,7 +149,6 @@ RouteGroup::set_state (const XMLNode& node)
|
|||
|
||||
void
|
||||
RouteGroup::set_active (bool yn, void *src)
|
||||
|
||||
{
|
||||
if (is_active() == yn) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ Send::Send (Session& s, Placement p)
|
|||
: Redirect (s, string_compose (_("send %1"), (bitslot = s.next_send_id()) + 1), p)
|
||||
{
|
||||
_metering = false;
|
||||
RedirectCreated (this); /* EMIT SIGNAL */
|
||||
InsertCreated (this); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
Send::Send (Session& s, const XMLNode& node)
|
||||
|
|
@ -48,14 +48,14 @@ Send::Send (Session& s, const XMLNode& node)
|
|||
throw failed_constructor();
|
||||
}
|
||||
|
||||
RedirectCreated (this); /* EMIT SIGNAL */
|
||||
InsertCreated (this); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
Send::Send (const Send& other)
|
||||
: Redirect (other._session, string_compose (_("send %1"), (bitslot = other._session.next_send_id()) + 1), other.placement())
|
||||
{
|
||||
_metering = false;
|
||||
RedirectCreated (this); /* EMIT SIGNAL */
|
||||
InsertCreated (this); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
Send::~Send ()
|
||||
|
|
@ -72,12 +72,13 @@ Send::get_state(void)
|
|||
XMLNode&
|
||||
Send::state(bool full)
|
||||
{
|
||||
XMLNode *node = new XMLNode("Send");
|
||||
XMLNode& node = Redirect::state(full);
|
||||
char buf[32];
|
||||
node->add_child_nocopy (Redirect::state (full));
|
||||
node.add_property ("type", "send");
|
||||
snprintf (buf, sizeof (buf), "%" PRIu32, bitslot);
|
||||
node->add_property ("bitslot", buf);
|
||||
return *node;
|
||||
node.add_property ("bitslot", buf);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -94,16 +95,19 @@ Send::set_state(const XMLNode& node)
|
|||
_session.mark_send_id (bitslot);
|
||||
}
|
||||
|
||||
const XMLNode* insert_node = &node;
|
||||
|
||||
/* Send has regular IO automation (gain, pan) */
|
||||
|
||||
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
||||
if ((*niter)->name() == Redirect::state_node_name) {
|
||||
Redirect::set_state (**niter);
|
||||
break;
|
||||
if ((*niter)->name() == "Redirect") {
|
||||
insert_node = *niter;
|
||||
} else if ((*niter)->name() == X_("Automation")) {
|
||||
IO::set_automation_state (*(*niter));
|
||||
_io->set_automation_state (*(*niter));
|
||||
}
|
||||
}
|
||||
|
||||
Redirect::set_state (*insert_node);
|
||||
|
||||
if (niter == nlist.end()) {
|
||||
error << _("XML node describing a send is missing a Redirect node") << endmsg;
|
||||
|
|
@ -126,21 +130,21 @@ Send::run (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_
|
|||
sendbufs.read_from(bufs, nframes);
|
||||
assert(sendbufs.count() == bufs.count());
|
||||
|
||||
IO::deliver_output (sendbufs, start_frame, end_frame, nframes, offset);
|
||||
_io->deliver_output (sendbufs, start_frame, end_frame, nframes, offset);
|
||||
|
||||
if (_metering) {
|
||||
if (_gain == 0) {
|
||||
_meter->reset();
|
||||
if (_io->_gain == 0) {
|
||||
_io->_meter->reset();
|
||||
} else {
|
||||
_meter->run(output_buffers(), nframes, offset);
|
||||
_io->_meter->run(_io->output_buffers(), start_frame, end_frame, nframes, offset);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
silence (nframes, offset);
|
||||
_io->silence (nframes, offset);
|
||||
|
||||
if (_metering) {
|
||||
_meter->reset();
|
||||
_io->_meter->reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -152,15 +156,72 @@ Send::set_metering (bool yn)
|
|||
|
||||
if (!_metering) {
|
||||
/* XXX possible thread hazard here */
|
||||
peak_meter().reset();
|
||||
_io->peak_meter().reset();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Send::expect_inputs (const ChanCount& expected)
|
||||
bool
|
||||
Send::can_support_input_configuration (ChanCount in) const
|
||||
{
|
||||
if (expected != _expected_inputs) {
|
||||
_expected_inputs = expected;
|
||||
reset_panner ();
|
||||
if (_io->input_maximum() == ChanCount::INFINITE && _io->output_maximum() == ChanCount::INFINITE) {
|
||||
|
||||
/* not configured yet */
|
||||
|
||||
return true; /* we can support anything the first time we're asked */
|
||||
|
||||
} else {
|
||||
|
||||
/* the "input" config for a port insert corresponds to how
|
||||
many output ports it will have.
|
||||
*/
|
||||
|
||||
if (_io->output_maximum() == in) {
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ChanCount
|
||||
Send::output_for_input_configuration (ChanCount in) const
|
||||
{
|
||||
// from the internal (Insert) perspective a Send does not modify its input whatsoever
|
||||
return in;
|
||||
}
|
||||
|
||||
bool
|
||||
Send::configure_io (ChanCount in, ChanCount out)
|
||||
{
|
||||
/* we're transparent no matter what. fight the power. */
|
||||
if (out != in)
|
||||
return false;
|
||||
|
||||
_io->set_output_maximum (in);
|
||||
_io->set_output_minimum (in);
|
||||
_io->set_input_maximum (ChanCount::ZERO);
|
||||
_io->set_input_minimum (ChanCount::ZERO);
|
||||
|
||||
bool success = _io->ensure_io (ChanCount::ZERO, in, false, this) == 0;
|
||||
|
||||
if (success) {
|
||||
Insert::configure_io(in, out);
|
||||
_io->reset_panner();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ChanCount
|
||||
Send::output_streams() const
|
||||
{
|
||||
return _io->n_outputs ();
|
||||
}
|
||||
|
||||
ChanCount
|
||||
Send::input_streams() const
|
||||
{
|
||||
return _io->n_outputs (); // (sic)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1887,7 +1887,7 @@ Session::add_routes (RouteList& new_routes, bool save)
|
|||
(*x)->solo_changed.connect (sigc::bind (mem_fun (*this, &Session::route_solo_changed), wpr));
|
||||
(*x)->mute_changed.connect (mem_fun (*this, &Session::route_mute_changed));
|
||||
(*x)->output_changed.connect (mem_fun (*this, &Session::set_worst_io_latencies_x));
|
||||
(*x)->redirects_changed.connect (mem_fun (*this, &Session::update_latency_compensation_proxy));
|
||||
(*x)->inserts_changed.connect (bind (mem_fun (*this, &Session::update_latency_compensation), false, false));
|
||||
|
||||
if ((*x)->master()) {
|
||||
_master_out = (*x);
|
||||
|
|
@ -3529,65 +3529,51 @@ Session::record_enable_change_all (bool yn)
|
|||
}
|
||||
|
||||
void
|
||||
Session::add_redirect (Redirect* redirect)
|
||||
Session::add_insert (Insert* insert)
|
||||
{
|
||||
Send* send;
|
||||
Insert* insert;
|
||||
PortInsert* port_insert;
|
||||
PluginInsert* plugin_insert;
|
||||
|
||||
if ((insert = dynamic_cast<Insert *> (redirect)) != 0) {
|
||||
if ((port_insert = dynamic_cast<PortInsert *> (insert)) != 0) {
|
||||
_port_inserts.insert (_port_inserts.begin(), port_insert);
|
||||
} else if ((plugin_insert = dynamic_cast<PluginInsert *> (insert)) != 0) {
|
||||
_plugin_inserts.insert (_plugin_inserts.begin(), plugin_insert);
|
||||
} else {
|
||||
fatal << _("programming error: unknown type of Insert created!") << endmsg;
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
} else if ((send = dynamic_cast<Send *> (redirect)) != 0) {
|
||||
if ((port_insert = dynamic_cast<PortInsert *> (insert)) != 0) {
|
||||
_port_inserts.insert (_port_inserts.begin(), port_insert);
|
||||
} else if ((plugin_insert = dynamic_cast<PluginInsert *> (insert)) != 0) {
|
||||
_plugin_inserts.insert (_plugin_inserts.begin(), plugin_insert);
|
||||
} else if ((send = dynamic_cast<Send *> (insert)) != 0) {
|
||||
_sends.insert (_sends.begin(), send);
|
||||
} else {
|
||||
fatal << _("programming error: unknown type of Redirect created!") << endmsg;
|
||||
fatal << _("programming error: unknown type of Insert created!") << endmsg;
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
redirect->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_redirect), redirect));
|
||||
insert->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_insert), insert));
|
||||
|
||||
set_dirty();
|
||||
}
|
||||
|
||||
void
|
||||
Session::remove_redirect (Redirect* redirect)
|
||||
Session::remove_insert (Insert* insert)
|
||||
{
|
||||
Send* send;
|
||||
Insert* insert;
|
||||
PortInsert* port_insert;
|
||||
PluginInsert* plugin_insert;
|
||||
|
||||
if ((insert = dynamic_cast<Insert *> (redirect)) != 0) {
|
||||
if ((port_insert = dynamic_cast<PortInsert *> (insert)) != 0) {
|
||||
list<PortInsert*>::iterator x = find (_port_inserts.begin(), _port_inserts.end(), port_insert);
|
||||
if (x != _port_inserts.end()) {
|
||||
insert_bitset[port_insert->bit_slot()] = false;
|
||||
_port_inserts.erase (x);
|
||||
}
|
||||
} else if ((plugin_insert = dynamic_cast<PluginInsert *> (insert)) != 0) {
|
||||
_plugin_inserts.remove (plugin_insert);
|
||||
} else {
|
||||
fatal << string_compose (_("programming error: %1"),
|
||||
X_("unknown type of Insert deleted!"))
|
||||
<< endmsg;
|
||||
/*NOTREACHED*/
|
||||
if ((port_insert = dynamic_cast<PortInsert *> (insert)) != 0) {
|
||||
list<PortInsert*>::iterator x = find (_port_inserts.begin(), _port_inserts.end(), port_insert);
|
||||
if (x != _port_inserts.end()) {
|
||||
insert_bitset[port_insert->bit_slot()] = false;
|
||||
_port_inserts.erase (x);
|
||||
}
|
||||
} else if ((send = dynamic_cast<Send *> (redirect)) != 0) {
|
||||
} else if ((plugin_insert = dynamic_cast<PluginInsert *> (insert)) != 0) {
|
||||
_plugin_inserts.remove (plugin_insert);
|
||||
} else if ((send = dynamic_cast<Send *> (insert)) != 0) {
|
||||
list<Send*>::iterator x = find (_sends.begin(), _sends.end(), send);
|
||||
if (x != _sends.end()) {
|
||||
send_bitset[send->bit_slot()] = false;
|
||||
_sends.erase (x);
|
||||
}
|
||||
} else {
|
||||
fatal << _("programming error: unknown type of Redirect deleted!") << endmsg;
|
||||
fatal << _("programming error: unknown type of Insert deleted!") << endmsg;
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -261,7 +261,7 @@ Session::first_stage_init (string fullpath, string snapshot_name)
|
|||
RegionFactory::CheckNewRegion.connect (mem_fun (*this, &Session::add_region));
|
||||
SourceFactory::SourceCreated.connect (mem_fun (*this, &Session::add_source));
|
||||
PlaylistFactory::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist));
|
||||
Redirect::RedirectCreated.connect (mem_fun (*this, &Session::add_redirect));
|
||||
Insert::InsertCreated.connect (mem_fun (*this, &Session::add_insert));
|
||||
NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection));
|
||||
AutomationList::AutomationListCreated.connect (mem_fun (*this, &Session::add_automation_list));
|
||||
|
||||
|
|
|
|||
|
|
@ -379,7 +379,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
|
|||
if ((Config->get_slave_source() == None && Config->get_auto_return()) || (post_transport_work & PostTransportLocate) || synced_to_jack()) {
|
||||
|
||||
if (pending_locate_flush) {
|
||||
flush_all_redirects ();
|
||||
flush_all_inserts ();
|
||||
}
|
||||
|
||||
if (((Config->get_slave_source() == None && Config->get_auto_return()) || synced_to_jack()) && !(post_transport_work & PostTransportLocate)) {
|
||||
|
|
@ -573,12 +573,12 @@ Session::set_play_loop (bool yn)
|
|||
}
|
||||
|
||||
void
|
||||
Session::flush_all_redirects ()
|
||||
Session::flush_all_inserts ()
|
||||
{
|
||||
boost::shared_ptr<RouteList> r = routes.reader ();
|
||||
|
||||
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
||||
(*i)->flush_redirects ();
|
||||
(*i)->flush_inserts ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1266,12 +1266,6 @@ Session::update_latency_compensation (bool with_stop, bool abort)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Session::update_latency_compensation_proxy (void* ignored)
|
||||
{
|
||||
update_latency_compensation (false, false);
|
||||
}
|
||||
|
||||
void
|
||||
Session::allow_auto_play (bool yn)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -679,7 +679,7 @@ SMFSource::set_allow_remove_if_empty (bool yn)
|
|||
}
|
||||
|
||||
int
|
||||
SMFSource::set_name (string newname, bool destructive)
|
||||
SMFSource::set_source_name (string newname, bool destructive)
|
||||
{
|
||||
//Glib::Mutex::Lock lm (_lock); FIXME
|
||||
string oldpath = _path;
|
||||
|
|
|
|||
|
|
@ -42,20 +42,20 @@ using std::max;
|
|||
|
||||
using namespace ARDOUR;
|
||||
|
||||
Source::Source (Session& s, string name, DataType type)
|
||||
: _session (s)
|
||||
Source::Source (Session& s, const string& name, DataType type)
|
||||
: SessionObject(s, name)
|
||||
, _type(type)
|
||||
{
|
||||
assert(_name.find("/") == string::npos);
|
||||
// not true.. is this supposed to be an assertion?
|
||||
//assert(_name.find("/") == string::npos);
|
||||
|
||||
_name = name;
|
||||
_timestamp = 0;
|
||||
_length = 0;
|
||||
_in_use = 0;
|
||||
}
|
||||
|
||||
Source::Source (Session& s, const XMLNode& node)
|
||||
: _session (s)
|
||||
: SessionObject(s, "unnamed source")
|
||||
, _type(DataType::AUDIO)
|
||||
{
|
||||
_timestamp = 0;
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ using namespace PBD;
|
|||
|
||||
Track::Track (Session& sess, string name, Route::Flag flag, TrackMode mode, DataType default_type)
|
||||
: Route (sess, name, 1, -1, -1, -1, flag, default_type)
|
||||
, _rec_enable_control (*this)
|
||||
, _rec_enable_control (*this)
|
||||
{
|
||||
_declickable = true;
|
||||
_freeze_record.state = NoFreeze;
|
||||
|
|
@ -49,8 +49,8 @@ Track::Track (Session& sess, string name, Route::Flag flag, TrackMode mode, Data
|
|||
}
|
||||
|
||||
Track::Track (Session& sess, const XMLNode& node, DataType default_type)
|
||||
: Route (sess, node),
|
||||
_rec_enable_control (*this)
|
||||
: Route (sess, node)
|
||||
, _rec_enable_control (*this)
|
||||
{
|
||||
_freeze_record.state = NoFreeze;
|
||||
_declickable = true;
|
||||
|
|
@ -92,7 +92,7 @@ Track::update_total_latency ()
|
|||
{
|
||||
_own_latency = 0;
|
||||
|
||||
for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
|
||||
for (InsertList::iterator i = _inserts.begin(); i != _inserts.end(); ++i) {
|
||||
if ((*i)->active ()) {
|
||||
_own_latency += (*i)->latency ();
|
||||
}
|
||||
|
|
@ -182,25 +182,27 @@ Track::set_record_enable (bool yn, void *src)
|
|||
_rec_enable_control.Changed ();
|
||||
}
|
||||
|
||||
int
|
||||
Track::set_name (string str, void *src)
|
||||
|
||||
bool
|
||||
Track::set_name (const string& str)
|
||||
{
|
||||
int ret;
|
||||
bool ret;
|
||||
|
||||
if (record_enabled() && _session.actively_recording()) {
|
||||
/* this messes things up if done while recording */
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_diskstream->set_name (str)) {
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* save state so that the statefile fully reflects any filename changes */
|
||||
|
||||
if ((ret = IO::set_name (str, src)) == 0) {
|
||||
if ((ret = IO::set_name (str)) == 0) {
|
||||
_session.save_state ("");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -980,7 +980,7 @@ void MackieControlProtocol::notify_gain_changed( RouteSignal * route_signal )
|
|||
}
|
||||
}
|
||||
|
||||
void MackieControlProtocol::notify_name_changed( void *, RouteSignal * route_signal )
|
||||
void MackieControlProtocol::notify_name_changed( RouteSignal * route_signal )
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ class MackieControlProtocol
|
|||
/// Signal handler for Route::gain_changed ( from IO )
|
||||
void notify_gain_changed( Mackie::RouteSignal * );
|
||||
/// Signal handler for Route::name_change
|
||||
void notify_name_changed( void *, Mackie::RouteSignal * );
|
||||
void notify_name_changed( Mackie::RouteSignal * );
|
||||
/// Signal handler from Panner::Change
|
||||
void notify_panner_changed( Mackie::RouteSignal * );
|
||||
/// Signal handler for new routes added
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ void RouteSignal::connect()
|
|||
if ( _strip.has_gain() )
|
||||
_gain_changed_connection = _route.gain_control().Changed.connect( sigc::bind ( mem_fun ( _mcp, &MackieControlProtocol::notify_gain_changed ), this ) );
|
||||
|
||||
_name_changed_connection = _route.name_changed.connect( sigc::bind ( mem_fun ( _mcp, &MackieControlProtocol::notify_name_changed ), this ) );
|
||||
_name_changed_connection = _route.NameChanged.connect( sigc::bind ( mem_fun ( _mcp, &MackieControlProtocol::notify_name_changed ), this ) );
|
||||
|
||||
if ( _route.panner().size() == 1 )
|
||||
{
|
||||
|
|
@ -85,7 +85,7 @@ void RouteSignal::notify_all()
|
|||
if ( _strip.has_gain() )
|
||||
_mcp.notify_gain_changed( this );
|
||||
|
||||
_mcp.notify_name_changed( &_route, this );
|
||||
_mcp.notify_name_changed( this );
|
||||
|
||||
if ( _strip.has_vpot() )
|
||||
_mcp.notify_panner_changed( this );
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue