summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2009-05-16 02:51:17 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2009-05-16 02:51:17 +0000
commitace07c80a81a631eb8ff95155e5ace2751838809 (patch)
tree4e440b7878535f04561dbddbe3ae4848a3207840
parent86dda29be798073d3d8b08aa833b52773b41daad (diff)
a gadzillion changes all over the place. nothing is finished, but all is better than it was. more to come on all almost everything touched by this commit, this is purely a sync-to-repository. compiles and runs, but now incompatible with all previous 3.0 session files (probably)
git-svn-id: svn://localhost/ardour2/branches/3.0@5084 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--gtk2_ardour/editor_canvas.cc3
-rw-r--r--gtk2_ardour/io_selector.cc41
-rw-r--r--gtk2_ardour/io_selector.h2
-rw-r--r--gtk2_ardour/processor_box.cc91
-rw-r--r--gtk2_ardour/processor_box.h5
-rw-r--r--libs/ardour/ardour/io.h26
-rw-r--r--libs/ardour/ardour/processor.h4
-rw-r--r--libs/ardour/ardour/route.h26
-rw-r--r--libs/ardour/audio_track.cc5
-rw-r--r--libs/ardour/audioengine.cc1
-rw-r--r--libs/ardour/io.cc200
-rw-r--r--libs/ardour/midi_track.cc6
-rw-r--r--libs/ardour/plugin_insert.cc4
-rw-r--r--libs/ardour/processor.cc11
-rw-r--r--libs/ardour/route.cc504
-rw-r--r--libs/ardour/send.cc14
-rw-r--r--libs/ardour/session.cc15
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/dndtreeview.h15
18 files changed, 435 insertions, 538 deletions
diff --git a/gtk2_ardour/editor_canvas.cc b/gtk2_ardour/editor_canvas.cc
index bdb051173d..428334dfc6 100644
--- a/gtk2_ardour/editor_canvas.cc
+++ b/gtk2_ardour/editor_canvas.cc
@@ -543,7 +543,8 @@ Editor::drop_regions (const RefPtr<Gdk::DragContext>& context,
guint info, guint time)
{
std::list<boost::shared_ptr<Region> > regions;
- region_list_display.get_object_drag_data (regions);
+ Gtk::TreeView* source;
+ region_list_display.get_object_drag_data (regions, &source);
for (list<boost::shared_ptr<Region> >::iterator r = regions.begin(); r != regions.end(); ++r) {
diff --git a/gtk2_ardour/io_selector.cc b/gtk2_ardour/io_selector.cc
index 93ade90dca..3bc4836920 100644
--- a/gtk2_ardour/io_selector.cc
+++ b/gtk2_ardour/io_selector.cc
@@ -153,27 +153,6 @@ IOSelector::n_io_ports () const
}
}
-uint32_t
-IOSelector::maximum_io_ports () const
-{
- if (!_find_inputs_for_io_outputs) {
- return _io->input_maximum ().get (_io->default_type());
- } else {
- return _io->output_maximum ().get (_io->default_type());
- }
-}
-
-
-uint32_t
-IOSelector::minimum_io_ports () const
-{
- if (!_find_inputs_for_io_outputs) {
- return _io->input_minimum ().get (_io->default_type());
- } else {
- return _io->output_minimum ().get (_io->default_type());
- }
-}
-
void
IOSelector::add_channel (boost::shared_ptr<ARDOUR::Bundle> b)
{
@@ -249,12 +228,10 @@ IOSelectorWindow::IOSelectorWindow (ARDOUR::Session& session, boost::shared_ptr<
get_action_area()->pack_start (disconnect_button, false, false);
/* Add Port button */
- if (_selector.maximum_io_ports() > _selector.n_io_ports()) {
- add_button.set_name ("IOSelectorButton");
- add_button.set_image (*Gtk::manage (new Gtk::Image (Gtk::Stock::ADD, Gtk::ICON_SIZE_BUTTON)));
- get_action_area()->pack_start (add_button, false, false);
- add_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (_selector, &IOSelector::add_channel), boost::shared_ptr<Bundle> ()));
- }
+ add_button.set_name ("IOSelectorButton");
+ add_button.set_image (*Gtk::manage (new Gtk::Image (Gtk::Stock::ADD, Gtk::ICON_SIZE_BUTTON)));
+ get_action_area()->pack_start (add_button, false, false);
+ add_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (_selector, &IOSelector::add_channel), boost::shared_ptr<Bundle> ()));
/* Rescan button */
rescan_button.set_name ("IOSelectorButton");
@@ -299,11 +276,11 @@ IOSelectorWindow::IOSelectorWindow (ARDOUR::Session& session, boost::shared_ptr<
void
IOSelectorWindow::ports_changed ()
{
- if (_selector.maximum_io_ports() > _selector.n_io_ports()) {
- add_button.set_sensitive (true);
- } else {
- add_button.set_sensitive (false);
- }
+ /* XXX make this insensitive based on port connectivity, not
+ port counts.
+ */
+
+ add_button.set_sensitive (true);
}
void
diff --git a/gtk2_ardour/io_selector.h b/gtk2_ardour/io_selector.h
index ccd3bc929f..872fd5d7d6 100644
--- a/gtk2_ardour/io_selector.h
+++ b/gtk2_ardour/io_selector.h
@@ -45,8 +45,6 @@ class IOSelector : public PortMatrix
}
uint32_t n_io_ports () const;
- uint32_t maximum_io_ports () const;
- uint32_t minimum_io_ports () const;
boost::shared_ptr<ARDOUR::IO> const io () { return _io; }
void setup_ports (int);
bool list_is_global (int) const;
diff --git a/gtk2_ardour/processor_box.cc b/gtk2_ardour/processor_box.cc
index a259a25695..027d9df51e 100644
--- a/gtk2_ardour/processor_box.cc
+++ b/gtk2_ardour/processor_box.cc
@@ -118,7 +118,8 @@ ProcessorBox::ProcessorBox (Placement pcmnt, Session& sess, PluginSelector &plug
RefPtr<TreeSelection> selection = processor_display.get_selection();
selection->set_mode (Gtk::SELECTION_MULTIPLE);
selection->signal_changed().connect (mem_fun (*this, &ProcessorBox::selection_changed));
-
+
+ processor_display.set_data ("processorbox", this);
processor_display.set_model (model);
processor_display.append_column (X_("notshown"), columns.text);
processor_display.set_name ("ProcessorSelector");
@@ -186,16 +187,31 @@ ProcessorBox::route_going_away ()
void
-ProcessorBox::object_drop (const list<boost::shared_ptr<Processor> >& procs)
+ProcessorBox::object_drop (const list<boost::shared_ptr<Processor> >& procs, Gtk::TreeView* source, Glib::RefPtr<Gdk::DragContext>& context)
{
- for (std::list<boost::shared_ptr<Processor> >::const_iterator i = procs.begin();
- i != procs.end(); ++i) {
+ cerr << "Drop from " << source << " (mine is " << &processor_display << ") action = " << hex << context->get_suggested_action() << dec << endl;
+
+ for (list<boost::shared_ptr<Processor> >::const_iterator i = procs.begin(); i != procs.end(); ++i) {
XMLNode& state = (*i)->get_state ();
XMLNodeList nlist;
nlist.push_back (&state);
paste_processor_state (nlist);
delete &state;
}
+
+ /* since the treeview doesn't take care of this properly, we have to delete the originals
+ ourselves.
+ */
+
+ if ((context->get_suggested_action() == Gdk::ACTION_MOVE) && source) {
+ ProcessorBox* other = reinterpret_cast<ProcessorBox*> (source->get_data ("processorbox"));
+ if (other) {
+ cerr << "source was another processor box, delete the selected items\n";
+ other->delete_dragged_processors (procs);
+ }
+ }
+
+ context->drag_finish (true, (context->get_suggested_action() == Gdk::ACTION_MOVE), 0);
}
void
@@ -433,9 +449,7 @@ ProcessorBox::use_plugins (const SelectedPlugins& plugins)
processor->activate ();
}
- assign_default_sort_key (processor);
-
- if (_route->add_processor (processor, &err_streams)) {
+ if (_route->add_processor (processor, _placement, &err_streams)) {
weird_plugin_dialog (**p, err_streams, _route);
// XXX SHAREDPTR delete plugin here .. do we even need to care?
} else {
@@ -500,8 +514,7 @@ ProcessorBox::choose_insert ()
mem_fun(*this, &ProcessorBox::show_processor_active),
boost::weak_ptr<Processor>(processor)));
- assign_default_sort_key (processor);
- _route->add_processor (processor);
+ _route->add_processor (processor, _placement);
}
void
@@ -553,8 +566,7 @@ ProcessorBox::send_io_finished (IOSelector::Result r, boost::weak_ptr<Processor>
break;
case IOSelector::Accepted:
- assign_default_sort_key (processor);
- _route->add_processor (processor);
+ _route->add_processor (processor, _placement);
if (Profile->get_sae()) {
processor->activate ();
}
@@ -611,8 +623,7 @@ ProcessorBox::return_io_finished (IOSelector::Result r, boost::weak_ptr<Processo
break;
case IOSelector::Accepted:
- assign_default_sort_key (processor);
- _route->add_processor (processor);
+ _route->add_processor (processor, _placement);
if (Profile->get_sae()) {
processor->activate ();
}
@@ -658,7 +669,7 @@ ProcessorBox::add_processor_to_display (boost::weak_ptr<Processor> p)
return;
}
- if (processor == _route->amp()) {
+ if (processor == _route->amp() || !processor->visible()) {
return;
}
@@ -796,22 +807,16 @@ ProcessorBox::row_deleted (const Gtk::TreeModel::Path& path)
void
ProcessorBox::compute_processor_sort_keys ()
{
- uint32_t sort_key;
Gtk::TreeModel::Children children = model->children();
-
- if (_placement == PreFader) {
- sort_key = 0;
- } else {
- sort_key = _route->fader_sort_key() + 1;
- }
+ Route::ProcessorList our_processors;
for (Gtk::TreeModel::Children::iterator iter = children.begin(); iter != children.end(); ++iter) {
- boost::shared_ptr<Processor> r = (*iter)[columns.processor];
- r->set_sort_key (sort_key);
- sort_key++;
+ our_processors.push_back ((*iter)[columns.processor]);
}
- if (_route->sort_processors ()) {
+ if (_route->reorder_processors (our_processors, _placement)) {
+
+ /* reorder failed, so redisplay */
redisplay_processors ();
@@ -928,6 +933,8 @@ ProcessorBox::delete_processors ()
return;
}
+ no_processor_redisplay = true;
+
for (ProcSelection::iterator i = to_be_deleted.begin(); i != to_be_deleted.end(); ++i) {
void* gui = (*i)->get_gui ();
@@ -943,6 +950,27 @@ ProcessorBox::delete_processors ()
redisplay_processors ();
}
+void
+ProcessorBox::delete_dragged_processors (const list<boost::shared_ptr<Processor> >& procs)
+{
+ list<boost::shared_ptr<Processor> >::const_iterator x;
+
+ no_processor_redisplay = true;
+ for (x = procs.begin(); x != procs.end(); ++x) {
+
+ void* gui = (*x)->get_gui ();
+
+ if (gui) {
+ static_cast<Gtk::Widget*>(gui)->hide ();
+ }
+
+ _route->remove_processor(*x);
+ }
+
+ no_processor_redisplay = false;
+ redisplay_processors ();
+}
+
gint
ProcessorBox::idle_delete_processor (boost::weak_ptr<Processor> weak_processor)
{
@@ -1051,9 +1079,7 @@ ProcessorBox::paste_processor_state (const XMLNodeList& nlist)
return;
}
- assign_default_sort_key (copies.front());
-
- if (_route->add_processors (copies, 0, copies.front()->sort_key())) {
+ if (_route->add_processors (copies, _placement)) {
string msg = _(
"Copying the set of processors on the clipboard failed,\n\
@@ -1568,12 +1594,3 @@ ProcessorBox::generate_processor_title (boost::shared_ptr<PluginInsert> pi)
return string_compose(_("%1: %2 (by %3)"), _route->name(), pi->name(), maker);
}
-void
-ProcessorBox::assign_default_sort_key (boost::shared_ptr<Processor> p)
-{
- p->set_sort_key (_placement == PreFader ? 0 : 9999);
- cerr << "default sort key for "
- << _placement << " = " << p->sort_key()
- << endl;
-}
-
diff --git a/gtk2_ardour/processor_box.h b/gtk2_ardour/processor_box.h
index f5af4c49dc..a003ed8c5d 100644
--- a/gtk2_ardour/processor_box.h
+++ b/gtk2_ardour/processor_box.h
@@ -128,7 +128,8 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject
Gtkmm2ext::DnDTreeView<boost::shared_ptr<ARDOUR::Processor> > processor_display;
Gtk::ScrolledWindow processor_scroller;
- void object_drop (const std::list<boost::shared_ptr<ARDOUR::Processor> >&);
+ void object_drop (const std::list<boost::shared_ptr<ARDOUR::Processor> >&, Gtk::TreeView*,
+ Glib::RefPtr<Gdk::DragContext>& context);
Width _width;
@@ -168,7 +169,6 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject
void processors_reordered (const Gtk::TreeModel::Path&, const Gtk::TreeModel::iterator&, int*);
void compute_processor_sort_keys ();
- void assign_default_sort_key (boost::shared_ptr<ARDOUR::Processor>);
std::vector<sigc::connection> processor_active_connections;
std::vector<sigc::connection> processor_name_connections;
@@ -183,6 +183,7 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject
void copy_processors ();
void paste_processors ();
void delete_processors ();
+ void delete_dragged_processors (const std::list<boost::shared_ptr<ARDOUR::Processor> >&);
void clear_processors ();
void rename_processors ();
diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h
index 297a4ee82c..5c7d8d0f0f 100644
--- a/libs/ardour/ardour/io.h
+++ b/libs/ardour/ardour/io.h
@@ -71,24 +71,11 @@ class IO : public SessionObject, public AutomatableControls, public Latent
public:
static const std::string state_node_name;
- IO (Session&, const std::string& name, DataType default_type = DataType::AUDIO,
- ChanCount in_min=ChanCount::ZERO, ChanCount in_max=ChanCount::INFINITE,
- ChanCount out_min=ChanCount::ZERO, ChanCount out_max=ChanCount::INFINITE);
-
+ IO (Session&, const std::string& name, DataType default_type = DataType::AUDIO);
IO (Session&, const XMLNode&, DataType default_type = DataType::AUDIO);
virtual ~IO();
- ChanCount input_minimum() const { return _input_minimum; }
- ChanCount input_maximum() const { return _input_maximum; }
- ChanCount output_minimum() const { return _output_minimum; }
- ChanCount output_maximum() const { return _output_maximum; }
-
- void set_input_minimum (ChanCount n);
- void set_input_maximum (ChanCount n);
- void set_output_minimum (ChanCount n);
- void set_output_maximum (ChanCount n);
-
bool active() const { return _active; }
void set_active (bool yn);
@@ -283,8 +270,6 @@ class IO : public SessionObject, public AutomatableControls, public Latent
XMLNode* deferred_state;
DataType _default_type;
nframes_t _output_offset;
- ChanCount _configured_inputs;
- ChanCount _configured_outputs;
boost::shared_ptr<Amp> _amp;
boost::shared_ptr<PeakMeter> _meter;
@@ -327,11 +312,6 @@ class IO : public SessionObject, public AutomatableControls, public Latent
sigc::connection port_legal_c;
sigc::connection panner_legal_c;
- ChanCount _input_minimum; ///< minimum number of input channels (0 for no minimum)
- ChanCount _input_maximum; ///< maximum number of input channels (ChanCount::INFINITE for no maximum)
- ChanCount _output_minimum; ///< minimum number of output channels (0 for no minimum)
- ChanCount _output_maximum; ///< maximum number of output channels (ChanCount::INFINITE for no maximum)
-
boost::shared_ptr<Bundle> _bundle_for_inputs; ///< a bundle representing our inputs
boost::shared_ptr<Bundle> _bundle_for_outputs; ///< a bundle representing our outputs
@@ -361,7 +341,9 @@ class IO : public SessionObject, public AutomatableControls, public Latent
void bundle_changed (Bundle::Change);
- int get_port_counts (const XMLNode& node);
+
+ int get_port_counts (const XMLNode& node, ChanCount& in, ChanCount& out,
+ boost::shared_ptr<Bundle>& ic, boost::shared_ptr<Bundle>& oc);
int create_ports (const XMLNode&);
int make_connections (const XMLNode&);
boost::shared_ptr<Bundle> find_possible_bundle (const std::string &desired_name, const std::string &default_name, const std::string &connection_type_name);
diff --git a/libs/ardour/ardour/processor.h b/libs/ardour/ardour/processor.h
index 68fdb5c6a6..73a93b31d9 100644
--- a/libs/ardour/ardour/processor.h
+++ b/libs/ardour/ardour/processor.h
@@ -63,9 +63,6 @@ class Processor : public SessionObject, public AutomatableControls, public Laten
virtual bool visible() const { return true; }
- uint32_t sort_key() const { return _sort_key; }
- void set_sort_key (uint32_t key);
-
bool active () const { return _active; }
bool get_next_ab_is_active () const { return _next_ab_is_active; }
@@ -129,7 +126,6 @@ protected:
bool _configured;
ChanCount _configured_input;
ChanCount _configured_output;
- uint32_t _sort_key;
void* _gui; /* generic, we don't know or care what this is */
Mapping _mapping;
};
diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h
index aee361d3a5..c498b1f04e 100644
--- a/libs/ardour/ardour/route.h
+++ b/libs/ardour/ardour/route.h
@@ -60,12 +60,10 @@ enum mute_type {
class Route : public IO
{
- protected:
+ public:
typedef std::list<boost::shared_ptr<Processor> > ProcessorList;
- public:
-
enum Flag {
Hidden = 0x1,
MasterOut = 0x2,
@@ -73,9 +71,7 @@ class Route : public IO
};
Route (Session&, std::string name, Flag flags = Flag(0),
- DataType default_type = DataType::AUDIO,
- ChanCount in=ChanCount::ZERO, ChanCount out=ChanCount::ZERO);
-
+ DataType default_type = DataType::AUDIO);
Route (Session&, const XMLNode&, DataType default_type = DataType::AUDIO);
virtual ~Route();
@@ -176,7 +172,7 @@ class Route : public IO
}
}
- uint32_t fader_sort_key() const;
+ ProcessorList::iterator prefader_iterator();
ChanCount max_processor_streams () const { return processor_max_streams; }
ChanCount pre_fader_streams() const;
@@ -196,10 +192,12 @@ class Route : public IO
ChanCount count; ///< Input requested of processor
};
- int add_processor (boost::shared_ptr<Processor>, ProcessorStreams* err = 0, ProcessorList::iterator* iter=0);
- int add_processors (const ProcessorList&, ProcessorStreams* err = 0, uint32_t first_sort_key = 0);
+ int add_processor (boost::shared_ptr<Processor>, Placement placement, ProcessorStreams* err = 0);
+ int add_processor (boost::shared_ptr<Processor>, ProcessorList::iterator iter, ProcessorStreams* err = 0);
+ int add_processors (const ProcessorList&, Placement placement, ProcessorStreams* err = 0);
+ int add_processors (const ProcessorList&, ProcessorList::iterator iter, ProcessorStreams* err = 0);
int remove_processor (boost::shared_ptr<Processor>, ProcessorStreams* err = 0);
- int sort_processors (ProcessorStreams* err = 0);
+ int reorder_processors (const ProcessorList& new_order, Placement placement, ProcessorStreams* err = 0);
void disable_processors (Placement);
void disable_processors ();
void disable_plugins (Placement);
@@ -389,12 +387,10 @@ class Route : public IO
int configure_processors_unlocked (ProcessorStreams*);
void set_deferred_state ();
- bool add_processor_from_xml (const XMLNode&, ProcessorList::iterator* iter=0);
+ bool add_processor_from_xml (const XMLNode&, Placement);
+ bool add_processor_from_xml (const XMLNode&, ProcessorList::iterator iter);
- void placement_range(
- Placement p,
- ProcessorList::iterator& start,
- ProcessorList::iterator& end);
+ void placement_range (Placement p, ProcessorList::iterator& start, ProcessorList::iterator& end);
};
} // namespace ARDOUR
diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc
index 878ad1118f..70e317c880 100644
--- a/libs/ardour/audio_track.cc
+++ b/libs/ardour/audio_track.cc
@@ -139,11 +139,6 @@ AudioTrack::deprecated_use_diskstream_connections ()
diskstream->deprecated_io_node = 0;
- set_input_minimum (ChanCount::ZERO);
- set_input_maximum (ChanCount::INFINITE);
- set_output_minimum (ChanCount::ZERO);
- set_output_maximum (ChanCount::INFINITE);
-
if ((prop = node.property ("gain")) != 0) {
set_gain (atof (prop->value().c_str()), this);
_gain = _gain_control->user_float();
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index 1dc646b610..fe9c064efa 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -329,6 +329,7 @@ int
AudioEngine::process_callback (nframes_t nframes)
{
// CycleTimer ct ("AudioEngine::process");
+
Glib::Mutex::Lock tm (_process_lock, Glib::TRY_LOCK);
/// The number of frames that will have been processed when we've finished
diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc
index cdd80b747d..0cacdb160e 100644
--- a/libs/ardour/io.cc
+++ b/libs/ardour/io.cc
@@ -100,9 +100,7 @@ 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, const string& name,
- DataType default_type,
- ChanCount in_min, ChanCount in_max, ChanCount out_min, ChanCount out_max)
+IO::IO (Session& s, const string& name, DataType default_type)
: SessionObject (s, name)
, AutomatableControls (s)
, _output_buffers (new BufferSet())
@@ -111,16 +109,7 @@ IO::IO (Session& s, const string& name,
, _amp (new Amp(s, *this))
, _meter (new PeakMeter(s))
, _panner (new Panner(name, s))
- , _input_minimum (ChanCount::ZERO)
- , _input_maximum (ChanCount::INFINITE)
- , _output_minimum (ChanCount::ZERO)
- , _output_maximum (ChanCount::INFINITE)
{
- _input_minimum = in_min;
- _output_minimum = out_min;
- _input_maximum = in_max;
- _output_maximum = out_max;
-
_gain = 1.0;
pending_state_node = 0;
no_panner_reset = false;
@@ -521,19 +510,10 @@ IO::set_input (Port* other_port, void* src)
to the specified source.
*/
- if (_input_minimum.n_total() > 1) {
- /* sorry, you can't do this */
+ if (!other_port) {
return -1;
}
- if (other_port == 0) {
- if (_input_minimum == ChanCount::ZERO) {
- return ensure_inputs (ChanCount::ZERO, false, true, src);
- } else {
- return -1;
- }
- }
-
if (ensure_inputs (ChanCount(other_port->type(), 1), true, true, src)) {
return -1;
}
@@ -553,11 +533,6 @@ IO::remove_output_port (Port* port, void* src)
{
Glib::Mutex::Lock lm (io_lock);
- if (n_outputs() <= _output_minimum) {
- /* sorry, you can't do this */
- return -1;
- }
-
if (_outputs.remove(port)) {
change = IOChange (change|ConfigurationChanged);
@@ -610,10 +585,6 @@ IO::add_output_port (string destination, void* src, DataType type)
{
Glib::Mutex::Lock lm (io_lock);
- if (n_outputs() >= _output_maximum) {
- return -1;
- }
-
/* Create a new output port */
string portname = build_legal_port_name (type, false);
@@ -657,11 +628,6 @@ IO::remove_input_port (Port* port, void* src)
{
Glib::Mutex::Lock lm (io_lock);
- if (n_inputs() <= _input_minimum) {
- /* sorry, you can't do this */
- return -1;
- }
-
if (_inputs.remove(port)) {
change = IOChange (change|ConfigurationChanged);
@@ -714,10 +680,6 @@ IO::add_input_port (string source, void* src, DataType type)
{
Glib::Mutex::Lock lm (io_lock);
- if (n_inputs().get (type) >= _input_maximum.get (type)) {
- return -1;
- }
-
/* Create a new input port */
string portname = build_legal_port_name (type, true);
@@ -801,8 +763,6 @@ IO::ensure_inputs_locked (ChanCount count, bool clear, void* src)
Port* input_port = 0;
bool changed = false;
- _configured_inputs = count;
-
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
const size_t n = count.get(*t);
@@ -870,12 +830,6 @@ IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
assert(in != ChanCount::INFINITE);
assert(out != ChanCount::INFINITE);
- in = ChanCount::min (_input_maximum, in);
- out = ChanCount::min (_output_maximum, out);
-
- _configured_inputs = in;
- _configured_outputs = out;
-
if (in == n_inputs() && out == n_outputs() && !clear) {
return 0;
}
@@ -1007,8 +961,6 @@ IO::ensure_inputs (ChanCount count, bool clear, bool lockit, void* src)
{
bool changed = false;
- count = min (_input_maximum, count);
-
if (count == n_inputs() && !clear) {
return 0;
}
@@ -1036,8 +988,6 @@ IO::ensure_outputs_locked (ChanCount count, bool clear, void* src)
bool changed = false;
bool need_pan_reset = false;
- _configured_outputs = count;
-
if (n_outputs() != count) {
need_pan_reset = true;
}
@@ -1098,13 +1048,6 @@ IO::ensure_outputs (ChanCount count, bool clear, bool lockit, void* src)
{
bool changed = false;
- if (_output_maximum != ChanCount::INFINITE) {
- count = min (_output_maximum, count);
- if (count == n_outputs() && !clear) {
- return 0;
- }
- }
-
/* XXX caller should hold io_lock, but generally doesn't */
if (lockit) {
@@ -1276,7 +1219,7 @@ IO::state (bool full_state)
node->add_property ("gain", buf);
/* port counts */
-
+
node->add_child_nocopy(*n_inputs().state("Inputs"));
node->add_child_nocopy(*n_outputs().state("Outputs"));
@@ -1313,44 +1256,6 @@ IO::set_state (const XMLNode& node)
_id = prop->value ();
}
- int in_min = -1;
- int in_max = -1;
- int out_min = -1;
- int out_max = -1;
-
- if ((prop = node.property ("iolimits")) != 0) {
- sscanf (prop->value().c_str(), "%d,%d,%d,%d",
- &in_min, &in_max, &out_min, &out_max);
-
- // Legacy numbers:
- // minimum == -1 => minimum == 0
- // maximum == -1 => maximum == infinity
-
- if (in_min < 0) {
- _input_minimum = ChanCount::ZERO;
- } else {
- _input_minimum = ChanCount (_default_type, in_min);
- }
-
- if (in_max < 0) {
- _input_maximum = ChanCount::INFINITE;
- } else {
- _input_maximum = ChanCount (_default_type, in_max);
- }
-
- if (out_min < 0) {
- _output_minimum = ChanCount::ZERO;
- } else {
- _output_minimum = ChanCount (_default_type, out_min);
- }
-
- if (out_max < 0) {
- _output_maximum = ChanCount::INFINITE;
- } else {
- _output_maximum = ChanCount (_default_type, out_max);
- }
- }
-
if ((prop = node.property ("gain")) != 0) {
set_gain (atof (prop->value().c_str()), this);
_gain = _gain_control->user_float();
@@ -1391,8 +1296,6 @@ IO::set_state (const XMLNode& node)
}
}
- get_port_counts (node);
-
if (ports_legal) {
if (create_ports (node)) {
@@ -1541,7 +1444,6 @@ IO::ports_became_legal ()
port_legal_c.disconnect ();
- get_port_counts (*pending_state_node);
ret = create_ports (*pending_state_node);
if (connecting_legal) {
@@ -1645,69 +1547,74 @@ IO::find_possible_bundle (const string &desired_name, const string &default_name
}
int
-IO::get_port_counts (const XMLNode& node)
+IO::get_port_counts (const XMLNode& node, ChanCount& in, ChanCount& out,
+ boost::shared_ptr<Bundle>& ic, boost::shared_ptr<Bundle>& oc)
{
XMLProperty const * prop;
XMLNodeConstIterator iter;
- ChanCount num_inputs = n_inputs();
- ChanCount num_outputs = n_outputs();
+
+ in = n_inputs();
+ out = n_outputs();
for (iter = node.children().begin(); iter != node.children().end(); ++iter) {
if ((*iter)->name() == X_("Inputs")) {
- num_inputs = ChanCount::max(num_inputs, ChanCount(**iter));
+ in = ChanCount::max(in, ChanCount(**iter));
} else if ((*iter)->name() == X_("Outputs")) {
- num_outputs = ChanCount::max(num_inputs, ChanCount(**iter));
+ out = ChanCount::max(out, ChanCount(**iter));
}
}
if ((prop = node.property ("input-connection")) != 0) {
- boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("in"), _("input"));
- if (c) {
- num_inputs = ChanCount::max(num_inputs, ChanCount(c->type(), c->nchannels()));
+ ic = find_possible_bundle (prop->value(), _("in"), _("input"));
+ if (ic) {
+ in = ChanCount::max(in, ChanCount(ic->type(), ic->nchannels()));
}
} else if ((prop = node.property ("inputs")) != 0) {
- num_inputs = ChanCount::max(num_inputs, ChanCount(_default_type,
- count (prop->value().begin(), prop->value().end(), '{')));
+ in = ChanCount::max(in, ChanCount(_default_type,
+ count (prop->value().begin(), prop->value().end(), '{')));
}
if ((prop = node.property ("output-connection")) != 0) {
-
- boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("out"), _("output"));
- if (c) {
- num_outputs = ChanCount::max(num_outputs, ChanCount(c->type(), c->nchannels()));
+
+ oc = find_possible_bundle (prop->value(), _("out"), _("output"));
+ if (oc) {
+ out = ChanCount::max(out, ChanCount(oc->type(), oc->nchannels()));
}
} else if ((prop = node.property ("outputs")) != 0) {
-
- num_outputs = ChanCount::max(num_outputs, ChanCount(_default_type,
- count (prop->value().begin(), prop->value().end(), '{')));
+
+ out = ChanCount::max(out, ChanCount(_default_type,
+ count (prop->value().begin(), prop->value().end(), '{')));
}
- _configured_inputs = num_inputs;
- _configured_outputs = num_outputs;
-
- _input_minimum = ChanCount::min(_input_minimum, num_inputs);
- _input_maximum = ChanCount::max(_input_maximum, num_inputs);
- _output_minimum = ChanCount::min(_output_minimum, num_outputs);
- _output_maximum = ChanCount::max(_output_maximum, num_outputs);
-
return 0;
}
int
IO::create_ports (const XMLNode& node)
{
+ ChanCount in;
+ ChanCount out;
+ boost::shared_ptr<Bundle> ic;
+ boost::shared_ptr<Bundle> oc;
+
no_panner_reset = true;
- if (ensure_io (_input_minimum, _output_minimum, true, this)) {
+ get_port_counts (*pending_state_node, in, out, ic, oc);
+
+ if (ensure_io (in, out, true, this)) {
error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
return -1;
}
+ /* XXX use ic and oc if relevant */
+
no_panner_reset = false;
+
+ cerr << "IO " << name() << " created ports, ci = " << n_inputs() << endl;
set_deferred_state ();
@@ -1843,7 +1750,7 @@ IO::set_outputs (const string& str)
return 0;
}
- // FIXME: audio-only
+ // FIXME: audio-only - need a way to identify port types from XML/string
if (ensure_outputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
return -1;
}
@@ -1971,30 +1878,6 @@ IO::set_name (const string& requested_name)
}
void
-IO::set_input_minimum (ChanCount n)
-{
- _input_minimum = n;
-}
-
-void
-IO::set_input_maximum (ChanCount n)
-{
- _input_maximum = n;
-}
-
-void
-IO::set_output_minimum (ChanCount n)
-{
- _output_minimum = n;
-}
-
-void
-IO::set_output_maximum (ChanCount n)
-{
- _output_maximum = n;
-}
-
-void
IO::set_port_latency (nframes_t nframes)
{
Glib::Mutex::Lock lm (io_lock);
@@ -2411,7 +2294,6 @@ IO::build_legal_port_name (DataType type, bool in)
const int name_size = jack_port_name_size();
int limit;
string suffix;
- int maxports;
if (type == DataType::AUDIO) {
suffix = _("audio");
@@ -2423,20 +2305,10 @@ IO::build_legal_port_name (DataType type, bool in)
if (in) {
suffix += _("_in");
- maxports = _input_maximum.get(type);
} else {
suffix += _("_out");
- maxports = _output_maximum.get(type);
}
-
- if (maxports == 1) {
- // allow space for the slash + the suffix
- limit = name_size - _session.engine().client_name().length() - (suffix.length() + 1);
- char buf[name_size+1];
- snprintf (buf, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str());
- return string (buf);
- }
-
+
// allow up to 4 digits for the output port number, plus the slash, suffix and extra space
limit = name_size - _session.engine().client_name().length() - (suffix.length() + 5);
diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc
index 6feb3253ce..c993b17ced 100644
--- a/libs/ardour/midi_track.cc
+++ b/libs/ardour/midi_track.cc
@@ -57,9 +57,6 @@ MidiTrack::MidiTrack (Session& sess, string name, Route::Flag flag, TrackMode mo
_freeze_record.state = NoFreeze;
_saved_meter_point = _meter_point;
_mode = mode;
-
- set_input_minimum(ChanCount(DataType::MIDI, 1));
- set_input_maximum(ChanCount(DataType::MIDI, 1));
}
MidiTrack::MidiTrack (Session& sess, const XMLNode& node)
@@ -68,9 +65,6 @@ MidiTrack::MidiTrack (Session& sess, const XMLNode& node)
, _note_mode(Sustained)
{
_set_state(node, false);
-
- set_input_minimum(ChanCount(DataType::MIDI, 1));
- set_input_maximum(ChanCount(DataType::MIDI, 1));
}
MidiTrack::~MidiTrack ()
diff --git a/libs/ardour/plugin_insert.cc b/libs/ardour/plugin_insert.cc
index 6a6e9cf100..f7a348f33f 100644
--- a/libs/ardour/plugin_insert.cc
+++ b/libs/ardour/plugin_insert.cc
@@ -848,10 +848,6 @@ PluginInsert::set_state(const XMLNode& node)
break;
}
- if (niter == nlist.end()) {
- warning << string_compose(_("XML node describing a port automation is missing the `%1' information"), port_automation_node_name) << endmsg;
- }
-
// The name of the PluginInsert comes from the plugin, nothing else
_name = plugin->get_info()->name;
diff --git a/libs/ardour/processor.cc b/libs/ardour/processor.cc
index 84fb43d68c..3fc9fcaee2 100644
--- a/libs/ardour/processor.cc
+++ b/libs/ardour/processor.cc
@@ -64,17 +64,10 @@ Processor::Processor(Session& session, const string& name)
, _active(false)
, _next_ab_is_active(false)
, _configured(false)
- , _sort_key (0)
, _gui(0)
{
}
-void
-Processor::set_sort_key (uint32_t key)
-{
- _sort_key = key;
-}
-
XMLNode&
Processor::get_state (void)
{
@@ -102,14 +95,10 @@ Processor::state (bool full_state)
stringstream sstr;
char buf[64];
- // NOTE: This conflicts with "id" used by plugin for name in legacy sessions
-
id().print (buf, sizeof (buf));
node->add_property("id", buf);
node->add_property("name", _name);
node->add_property("active", active() ? "yes" : "no");
- snprintf (buf, sizeof (buf), "%u", _sort_key);
- node->add_property("sort-key", buf);
if (_extra_xml){
node->add_child_copy (*_extra_xml);
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index 06b9308d35..67ff44a709 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -63,15 +63,12 @@ using namespace PBD;
uint32_t Route::order_key_cnt = 0;
sigc::signal<void,const char*> Route::SyncOrderKeys;
-Route::Route (Session& sess, string name, Flag flg,
- DataType default_type, ChanCount in, ChanCount out)
- : IO (sess, name, default_type, in, ChanCount::INFINITE, out, ChanCount::INFINITE)
+Route::Route (Session& sess, string name, Flag flg, DataType default_type)
+ : IO (sess, name, default_type)
, _flags (flg)
, _solo_control (new ToggleControllable (X_("solo"), *this, ToggleControllable::SoloControl))
, _mute_control (new ToggleControllable (X_("mute"), *this, ToggleControllable::MuteControl))
{
- _configured_inputs = in;
- _configured_outputs = out;
init ();
}
@@ -129,14 +126,11 @@ Route::init ()
/* amp & meter belong to IO but need to be added to our processor list */
- _amp->set_sort_key (0);
- _meter->set_sort_key (1);
- add_processor (_amp);
- add_processor (_meter);
+ add_processor (_amp, PostFader);
+ add_processor (_meter, PreFader);
_main_outs.reset (new Delivery (_session, this, _name, Delivery::Main));
- ProcessorList::iterator i = _processors.end();
- add_processor (_main_outs, 0, &i);
+ add_processor (_main_outs, PostFader);
}
Route::~Route ()
@@ -598,31 +592,59 @@ dump_processors(const string& name, const list<boost::shared_ptr<Processor> >& p
cerr << name << " {" << endl;
for (list<boost::shared_ptr<Processor> >::const_iterator p = procs.begin();
p != procs.end(); ++p) {
- cerr << "\t" << (*p)->sort_key() << ": " << (*p)->name() << endl;
+ cerr << "\t" << (*p)->name() << endl;
}
cerr << "}" << endl;
}
+Route::ProcessorList::iterator
+Route::prefader_iterator()
+{
+ Glib::RWLock::ReaderLock lm (_processor_lock);
+ return find (_processors.begin(), _processors.end(), _amp);
+}
-struct ProcessorSortByKey {
- bool operator() (boost::shared_ptr<Processor> a, boost::shared_ptr<Processor> b) {
- return a->sort_key() < b->sort_key();
- }
-};
-
-uint32_t
-Route::fader_sort_key() const
+int
+Route::add_processor (boost::shared_ptr<Processor> processor, Placement placement, ProcessorStreams* err)
{
- return _amp->sort_key();
+ ProcessorList::iterator loc;
+
+ /* XXX this is not thread safe - we don't hold the lock across determining the iter
+ to add before and actually doing the insertion. dammit.
+ */
+
+ if (placement == PreFader) {
+ /* generic pre-fader: insert immediately before the amp */
+ loc = find(_processors.begin(), _processors.end(), _amp);
+ } else {
+ /* generic post-fader: insert at end */
+ loc = _processors.end();
+
+ if (processor->visible() && !_processors.empty()) {
+ /* check for invisible processors stacked at the end and leave them there */
+ ProcessorList::iterator p;
+ p = _processors.end();
+ --p;
+ cerr << "Let's check " << (*p)->name() << " vis ? " << (*p)->visible() << endl;
+ while (!(*p)->visible() && p != _processors.begin()) {
+ --p;
+ }
+ ++p;
+ loc = p;
+ }
+ }
+
+ return add_processor (processor, loc, err);
}
+
/** Add a processor to the route.
* If @a iter is not NULL, it must point to an iterator in _processors and the new
* processor will be inserted immediately before this location. Otherwise,
* @a position is used.
*/
int
-Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams* err, ProcessorList::iterator* iter)
+Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorList::iterator iter, ProcessorStreams* err)
{
ChanCount old_pms = processor_max_streams;
@@ -630,9 +652,7 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams*
return 1;
}
- cerr << "Adding a processor called " << processor->name() << " sk = " << processor->sort_key()
- << ((iter == 0) ? " NO given position " : " with given position")
- << endl;
+ cerr << "Adding a processor called " << processor->name() << endl;
{
Glib::RWLock::WriterLock lm (_processor_lock);
@@ -645,15 +665,10 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams*
if (processor == _amp || processor == _meter || processor == _main_outs) {
// Ensure only one of these are in the list at any time
if (loc != _processors.end()) {
- if (iter) {
- if (*iter == loc) { // Already in place, do nothing
- return 0;
- } else { // New position given, relocate
- _processors.erase(loc);
- }
- } else { // Insert at end
- _processors.erase(loc);
- loc = _processors.end();
+ if (iter == loc) { // Already in place, do nothing
+ return 0;
+ } else { // New position given, relocate
+ _processors.erase (loc);
}
}
@@ -662,41 +677,26 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams*
cerr << "ERROR: Processor added to route twice!" << endl;
return 1;
}
- }
- if (iter) {
- // Use position given by user
- loc = *iter;
- } else {
- if (processor->sort_key() == 0) {
- /* generic pre-fader: insert immediately before the amp */
- loc = find(_processors.begin(), _processors.end(), _amp);
- } else if (processor->sort_key() > _processors.size()) {
- /* generic post-fader: insert at end */
- loc = _processors.end();
- } else {
- /* find insert point */
- ProcessorSortByKey cmp;
- loc = upper_bound (_processors.begin(), _processors.end(), processor, cmp);
- }
- }
-
- // Update sort keys
- if (loc == _processors.end()) {
- processor->set_sort_key(_processors.size());
- } else {
- processor->set_sort_key((*loc)->sort_key());
- for (ProcessorList::iterator p = loc; p != _processors.end(); ++p) {
- (*p)->set_sort_key((*p)->sort_key() + 1);
- }
+ loc = iter;
}
- _processors.insert(loc, processor);
+ cerr << "Adding " << processor->name() << endl;
+
+ _processors.insert (loc, processor);
// Set up processor list channels. This will set processor->[input|output]_streams(),
// configure redirect ports properly, etc.
- if (configure_processors_unlocked (err)) {
+
+ ProcessorStreams rerr;
+
+ if (configure_processors_unlocked (&rerr)) {
+
dump_processors(_name + "bad config", _processors);
+ if (err) {
+ *err = rerr;
+ }
+ cerr << "Error at proc " << rerr.index << " with input of " << rerr.count << endl;
ProcessorList::iterator ploc = loc;
--ploc;
_processors.erase(ploc);
@@ -736,8 +736,146 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams*
return 0;
}
+bool
+Route::add_processor_from_xml (const XMLNode& node, Placement placement)
+{
+ ProcessorList::iterator loc;
+ if (placement == PreFader) {
+ /* generic pre-fader: insert immediately before the amp */
+ loc = find(_processors.begin(), _processors.end(), _amp);
+ } else {
+ /* generic post-fader: insert at end */
+ loc = _processors.end();
+ }
+
+ return add_processor_from_xml (node, loc);
+}
+
+bool
+Route::add_processor_from_xml (const XMLNode& node, ProcessorList::iterator iter)
+{
+ const XMLProperty *prop;
+
+ // legacy sessions use a different node name for sends
+ if (node.name() == "Send") {
+
+ try {
+ boost::shared_ptr<Send> send (new Send (_session, node));
+ add_processor (send, iter);
+ return true;
+ }
+
+ catch (failed_constructor &err) {
+ error << _("Send construction failed") << endmsg;
+ return false;
+ }
+
+ } else if (node.name() == "Processor") {
+
+ try {
+ if ((prop = node.property ("type")) != 0) {
+
+ boost::shared_ptr<Processor> processor;
+ bool have_insert = false;
+
+ if (prop->value() == "ladspa" || prop->value() == "Ladspa" ||
+ prop->value() == "lv2" ||
+ prop->value() == "vst" ||
+ prop->value() == "audiounit") {
+
+ processor.reset (new PluginInsert(_session, node));
+ have_insert = true;
+
+ } else if (prop->value() == "port") {
+
+ processor.reset (new PortInsert (_session, node));
+
+ } else if (prop->value() == "send") {
+
+ processor.reset (new Send (_session, node));
+ have_insert = true;
+
+ } else if (prop->value() == "meter") {
+
+ processor = _meter;
+
+ } else if (prop->value() == "amp") {
+
+ processor = _amp;
+
+ } else if (prop->value() == "listen" || prop->value() == "deliver") {
+
+ /* XXX need to generalize */
+
+ processor = _control_outs;
+
+ } else if (prop->value() == "main-outs") {
+
+ processor = _main_outs;
+
+ } else {
+
+ error << string_compose(_("unknown Processor type \"%1\"; ignored"), prop->value()) << endmsg;
+ }
+
+ if (iter == _processors.end() && processor->visible() && !_processors.empty()) {
+ /* check for invisible processors stacked at the end and leave them there */
+ ProcessorList::iterator p;
+ p = _processors.end();
+ --p;
+ cerr << "Let's check " << (*p)->name() << " vis ? " << (*p)->visible() << endl;
+ while (!(*p)->visible() && p != _processors.begin()) {
+ --p;
+ }
+ ++p;
+ iter = p;
+ }
+
+ return (add_processor (processor, iter) == 0);
+
+ } else {
+ error << _("Processor XML node has no type property") << endmsg;
+ }
+ }
+
+ catch (failed_constructor &err) {
+ warning << _("processor could not be created. Ignored.") << endmsg;
+ return false;
+ }
+ }
+ return false;
+}
+
int
-Route::add_processors (const ProcessorList& others, ProcessorStreams* err, uint32_t first_sort_key)
+Route::add_processors (const ProcessorList& others, Placement placement, ProcessorStreams* err)
+{
+ ProcessorList::iterator loc;
+ if (placement == PreFader) {
+ /* generic pre-fader: insert immediately before the amp */
+ loc = find(_processors.begin(), _processors.end(), _amp);
+ } else {
+ /* generic post-fader: insert at end */
+ loc = _processors.end();
+
+ if (!_processors.empty()) {
+ /* check for invisible processors stacked at the end and leave them there */
+ ProcessorList::iterator p;
+ p = _processors.end();
+ --p;
+ cerr << "Let's check " << (*p)->name() << " vis ? " << (*p)->visible() << endl;
+ while (!(*p)->visible() && p != _processors.begin()) {
+ --p;
+ }
+ ++p;
+ loc = p;
+ }
+ }
+
+ return add_processors (others, loc, err);
+}
+
+int
+Route::add_processors (const ProcessorList& others, ProcessorList::iterator iter, ProcessorStreams* err)
{
/* NOTE: this is intended to be used ONLY when copying
processors from another Route. Hence the subtle
@@ -750,29 +888,16 @@ Route::add_processors (const ProcessorList& others, ProcessorStreams* err, uint3
return 1;
}
+ if (others.empty()) {
+ return 0;
+ }
+
{
Glib::RWLock::WriterLock lm (_processor_lock);
-
- ProcessorList::iterator loc;
ProcessorList::iterator existing_end = _processors.end();
--existing_end;
- ChanCount potential_max_streams = ChanCount::max(input_minimum(), output_minimum());
-
- if (first_sort_key == 0) {
- /* generic pre-fader: insert immediately before the amp */
- cerr << "Add new procs at amp, sk = " << first_sort_key << endl;
- loc = find(_processors.begin(), _processors.end(), _amp);
- } else if (first_sort_key > _processors.size()) {
- /* generic post-fader: insert at end */
- cerr << "Add new procs at end, sk = " << first_sort_key << endl;
- loc = _processors.end();
- } else {
- /* find insert point */
- ProcessorSortByKey cmp;
- cerr << "Add new procs at sk = " << first_sort_key << endl;
- loc = upper_bound (_processors.begin(), _processors.end(), others.front(), cmp);
- }
+ ChanCount potential_max_streams = ChanCount::max (n_inputs(), n_outputs());
for (ProcessorList::const_iterator i = others.begin(); i != others.end(); ++i) {
@@ -797,7 +922,7 @@ Route::add_processors (const ProcessorList& others, ProcessorStreams* err, uint3
// Ensure peak vector sizes before the plugin is activated
_meter->configure_io (potential_max_streams, potential_max_streams);
- _processors.insert (loc, *i);
+ _processors.insert (iter, *i);
if (configure_processors_unlocked (err)) {
++existing_end;
@@ -1150,16 +1275,18 @@ Route::configure_processors_unlocked (ProcessorStreams* err)
_in_configure_processors = true;
// Check each processor in order to see if we can configure as requested
- ChanCount in = _configured_inputs;
+ ChanCount in = n_inputs();
ChanCount out;
list< pair<ChanCount,ChanCount> > configuration;
uint32_t index = 0;
for (ProcessorList::iterator p = _processors.begin(); p != _processors.end(); ++p, ++index) {
- (*p)->set_sort_key(index);
+ cerr << "Can " << (*p)->name() << " support in= " << in << " out= " << out;
if ((*p)->can_support_io_configuration(in, out)) {
+ cerr << " yes\n";
configuration.push_back(make_pair(in, out));
in = out;
} else {
+ cerr << " no\n";
if (err) {
err->index = index;
err->count = in;
@@ -1181,7 +1308,7 @@ Route::configure_processors_unlocked (ProcessorStreams* err)
// Ensure route outputs match last processor's outputs
if (out != n_outputs()) {
- ensure_io(_configured_inputs, out, false, this);
+ ensure_io (n_inputs(), out, false, this);
}
_in_configure_processors = false;
@@ -1244,21 +1371,68 @@ Route::all_processors_active (Placement p, bool state)
}
int
-Route::sort_processors (ProcessorStreams* err)
+Route::reorder_processors (const ProcessorList& new_order, Placement placement, ProcessorStreams* err)
{
{
- ProcessorSortByKey comparator;
Glib::RWLock::WriterLock lm (_processor_lock);
ChanCount old_pms = processor_max_streams;
+ ProcessorList::iterator oiter;
+ ProcessorList::const_iterator niter;
+ ProcessorList as_it_was_before = _processors;
+ ProcessorList as_it_will_be;
+ ProcessorList::iterator start, end;
- /* the sweet power of C++ ... */
+ dump_processors (_name + " PreReorder", _processors);
+ placement_range (placement, start, end);
- ProcessorList as_it_was_before = _processors;
+ oiter = start;
+ niter = new_order.begin();
- dump_processors (_name + " PRESORT", _processors);
+ while (oiter != end && niter != new_order.end()) {
+
+ /* if the next processor in the old list is invisible (i.e. should not be in the new order)
+ then append it to the temp list.
+
+ Otherwise, see if the next processor in the old list is in the new list. if not,
+ its been deleted. If its there, append it to the temp list.
+ */
+
+ if (oiter == end) {
+
+ /* no more elements in the old list, so just stick the rest of
+ the new order onto the temp list.
+ */
+
+ as_it_will_be.insert (as_it_will_be.end(), niter, new_order.end());
+
+ } else {
+
+ if (!(*oiter)->visible()) {
+
+ as_it_will_be.push_back (*oiter);
+
+ } else {
+
+ /* visible processor: check that its in the new order */
+
+ if (find (new_order.begin(), new_order.end(), (*oiter)) == new_order.end()) {
+ /* deleted: do nothing */
+ } else {
+ /* ignore this one, and add the next item from the new order instead */
+ as_it_will_be.push_back (*niter);
+ ++niter;
+ }
+ }
+
+ /* now remove from old order - its taken care of no matter what */
+ oiter = _processors.erase (oiter);
+ }
+ }
+
+ _processors.insert (end, as_it_will_be.begin(), as_it_will_be.end());
+
+ dump_processors (_name + " PostReorder", _processors);
- _processors.sort (comparator);
-
if (configure_processors_unlocked (err)) {
_processors = as_it_was_before;
processor_max_streams = old_pms;
@@ -1267,6 +1441,7 @@ Route::sort_processors (ProcessorStreams* err)
}
dump_processors (_name + " sorted", _processors);
+ /* do we really need to do this every time? */
reset_panner ();
processors_changed (); /* EMIT SIGNAL */
@@ -1440,96 +1615,12 @@ Route::set_deferred_state ()
nlist = deferred_state->children();
- for (niter = nlist.begin(); niter != nlist.end(); ++niter){
- add_processor_from_xml (**niter);
- }
+ _set_processor_states (nlist);
delete deferred_state;
deferred_state = 0;
}
-bool
-Route::add_processor_from_xml (const XMLNode& node, ProcessorList::iterator* iter)
-{
- const XMLProperty *prop;
-
- // legacy sessions use a different node name for sends
- if (node.name() == "Send") {
-
- try {
- boost::shared_ptr<Send> send (new Send (_session, node));
- add_processor (send, 0, iter);
- return true;
- }
-
- catch (failed_constructor &err) {
- error << _("Send construction failed") << endmsg;
- return false;
- }
-
- } else if (node.name() == "Processor") {
-
- try {
- if ((prop = node.property ("type")) != 0) {
-
- boost::shared_ptr<Processor> processor;
- bool have_insert = false;
-
- if (prop->value() == "ladspa" || prop->value() == "Ladspa" ||
- prop->value() == "lv2" ||
- prop->value() == "vst" ||
- prop->value() == "audiounit") {
-
- processor.reset (new PluginInsert(_session, node));
- have_insert = true;
-
- } else if (prop->value() == "port") {
-
- processor.reset (new PortInsert (_session, node));
-
- } else if (prop->value() == "send") {
-
- processor.reset (new Send (_session, node));
- have_insert = true;
-
- } else if (prop->value() == "meter") {
-
- processor = _meter;
-
- } else if (prop->value() == "amp") {
-
- processor = _amp;
-
- } else if (prop->value() == "listen" || prop->value() == "deliver") {
-
- /* XXX need to generalize */
-
- processor = _control_outs;
-
- } else if (prop->value() == "main-outs") {
-
- processor = _main_outs;
-
- } else {
-
- error << string_compose(_("unknown Processor type \"%1\"; ignored"), prop->value()) << endmsg;
- }
-
- return (add_processor (processor, 0, iter) == 0);
-
- } else {
- error << _("Processor XML node has no type property") << endmsg;
- }
- }
-
- catch (failed_constructor &err) {
- warning << _("processor could not be created. Ignored.") << endmsg;
- return false;
- }
- }
- return false;
-}
-
int
Route::set_state (const XMLNode& node)
{
@@ -1671,31 +1762,23 @@ Route::_set_state (const XMLNode& node, bool call_base)
}
}
- XMLNodeList processor_nodes;
- bool has_meter_processor = false; // legacy sessions don't
-
for (niter = nlist.begin(); niter != nlist.end(); ++niter){
-
+
child = *niter;
if (child->name() == X_("Send") || child->name() == X_("Processor")) {
- processor_nodes.push_back(child);
- if ((prop = child->property (X_("type"))) != 0 && prop->value() == "meter") {
- has_meter_processor = true;
- }
+ deferred_state->add_child_copy (*child);
}
-
}
- _set_processor_states(processor_nodes);
- if (!has_meter_processor) {
- set_meter_point(_meter_point, NULL);
+ if (ports_legal) {
+ _set_processor_states (deferred_state->children());
+ delete deferred_state;
+ deferred_state = 0;
}
- processors_changed ();
for (niter = nlist.begin(); niter != nlist.end(); ++niter){
child = *niter;
- // All processors have been applied already
if (child->name() == X_("Automation")) {
@@ -1752,9 +1835,11 @@ void
Route::_set_processor_states(const XMLNodeList &nlist)
{
XMLNodeConstIterator niter;
-
+ bool has_meter_processor = false; // legacy sessions don't
ProcessorList::iterator i, o;
+ cerr << "Setting processor states with in = " << n_inputs() << endl;
+
// Iterate through existing processors, remove those which are not in the state list
for (i = _processors.begin(); i != _processors.end(); ) {
ProcessorList::iterator tmp = i;
@@ -1785,7 +1870,11 @@ Route::_set_processor_states(const XMLNodeList &nlist)
for (niter = nlist.begin(); niter != nlist.end(); ++niter, ++i) {
XMLProperty* prop = (*niter)->property ("type");
-
+
+ if (prop && prop->value() == "meter") {
+ has_meter_processor = true;
+ }
+
o = i;
if (prop->value() != "meter" && prop->value() != "amp" && prop->value() != "main-outs") {
@@ -1806,7 +1895,7 @@ Route::_set_processor_states(const XMLNodeList &nlist)
// create it and move it to the correct location
if (o == _processors.end()) {
- if (add_processor_from_xml (**niter, &i)) {
+ if (add_processor_from_xml (**niter, i)) {
--i; // move iterator to the newly inserted processor
} else {
cerr << "Error restoring route: unable to restore processor" << endl;
@@ -1818,7 +1907,6 @@ Route::_set_processor_states(const XMLNodeList &nlist)
if (i != o) {
boost::shared_ptr<Processor> tmp = (*o);
- cerr << "move proc from state\n";
_processors.erase (o); // remove the old copy
_processors.insert (i, tmp); // insert the processor at the correct location
--i; // move iterator to the correct processor
@@ -1827,6 +1915,19 @@ Route::_set_processor_states(const XMLNodeList &nlist)
(*i)->set_state (**niter);
}
}
+
+ /* note: there is no configure_processors() call because we figure that
+ the XML state represents a working signal route.
+ */
+
+ if (!has_meter_processor) {
+ set_meter_point (_meter_point, NULL);
+ }
+
+ processors_changed ();
+
+
+
}
void
@@ -1887,8 +1988,7 @@ Route::add_listener (boost::shared_ptr<IO> io, const string& listen_name)
return boost::shared_ptr<Delivery>();
}
- listener->set_sort_key (_meter->sort_key() + 1);
- add_processor (listener, NULL);
+ add_processor (listener, PostFader);
return listener;
}
@@ -2360,16 +2460,6 @@ Route::set_meter_point (MeterPoint p, void *src)
}
_processors.insert(loc, _meter);
- // Update sort key
- if (loc == _processors.end()) {
- _meter->set_sort_key(_processors.size());
- } else {
- _meter->set_sort_key((*loc)->sort_key());
- for (ProcessorList::iterator p = loc; p != _processors.end(); ++p) {
- (*p)->set_sort_key((*p)->sort_key() + 1);
- }
- }
-
meter_change (src); /* EMIT SIGNAL */
processors_changed (); /* EMIT SIGNAL */
_session.set_dirty ();
diff --git a/libs/ardour/send.cc b/libs/ardour/send.cc
index e4de26e864..852f27d38f 100644
--- a/libs/ardour/send.cc
+++ b/libs/ardour/send.cc
@@ -108,8 +108,7 @@ Send::set_state(const XMLNode& node)
bool
Send::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
{
- if (_io->input_maximum() == ChanCount::INFINITE
- && _io->output_maximum() == ChanCount::INFINITE) {
+ if (_io->n_inputs() == ChanCount::ZERO && _io->n_outputs() == ChanCount::ZERO) {
/* not configured yet, we can support anything */
@@ -120,10 +119,8 @@ Send::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
/* for a send, processor input corresponds to IO output */
- if (_io->output_maximum() == in) {
- out = in;
- return true;
- }
+ out = in;
+ return true;
}
return false;
@@ -138,11 +135,6 @@ Send::configure_io (ChanCount in, ChanCount out)
return false;
}
- /*_io->set_output_maximum (in);
- _io->set_output_minimum (in);
- _io->set_input_maximum (ChanCount::ZERO);
- _io->set_input_minimum (ChanCount::ZERO);*/
-
if (_io->ensure_io (ChanCount::ZERO, in, false, this) != 0) {
return false;
}
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index eebde5ffa7..db6063e7f4 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -271,8 +271,8 @@ Session::Session (AudioEngine &eng,
if (control_out_channels) {
ChanCount count(DataType::AUDIO, control_out_channels);
- shared_ptr<Route> r (new Route (*this, _("monitor"), Route::ControlOut,
- DataType::AUDIO, count, count));
+ shared_ptr<Route> r (new Route (*this, _("monitor"), Route::ControlOut, DataType::AUDIO));
+ r->ensure_io (count, count, false, this);
r->set_remote_control_id (control_id++);
rl.push_back (r);
@@ -281,8 +281,8 @@ Session::Session (AudioEngine &eng,
if (master_out_channels) {
ChanCount count(DataType::AUDIO, master_out_channels);
cerr << "new MO with " << count << endl;
- shared_ptr<Route> r (new Route (*this, _("master"), Route::MasterOut,
- DataType::AUDIO, count, count));
+ shared_ptr<Route> r (new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO));
+ r->ensure_io (count, count, false, this);
r->set_remote_control_id (control_id);
rl.push_back (r);
@@ -671,12 +671,9 @@ Session::when_engine_running ()
_master_out->ports_became_legal();
}
- /* create ports, without any connections
- */
- _master_out->ensure_io (_master_out->input_minimum (), _master_out->output_minimum (), true, this);
-
/* if requested auto-connect the outputs to the first N physical ports.
*/
+
if (Config->get_auto_connect_master()) {
uint32_t limit = _master_out->n_outputs().n_total();
@@ -771,7 +768,7 @@ Session::hookup_io ()
if (_control_out) {
- _control_out->ensure_io (_control_out->input_minimum(), _control_out->output_minimum(), false, this);
+ // _control_out->ensure_io (_control_out->input_minimum(), _control_out->output_minimum(), false, this);
boost::shared_ptr<RouteList> r = routes.reader ();
diff --git a/libs/gtkmm2ext/gtkmm2ext/dndtreeview.h b/libs/gtkmm2ext/gtkmm2ext/dndtreeview.h
index 085e500f21..cc9d1c1463 100644
--- a/libs/gtkmm2ext/gtkmm2ext/dndtreeview.h
+++ b/libs/gtkmm2ext/gtkmm2ext/dndtreeview.h
@@ -86,7 +86,7 @@ class DnDTreeView : public DnDTreeViewBase
DnDTreeView() {}
~DnDTreeView() {}
- sigc::signal<void,const std::list<DataType>& > signal_drop;
+ sigc::signal<void,const std::list<DataType>&,Gtk::TreeView*,Glib::RefPtr<Gdk::DragContext>&> signal_drop;
void on_drag_data_get(const Glib::RefPtr<Gdk::DragContext>& context, Gtk::SelectionData& selection_data, guint info, guint time) {
if (selection_data.get_target() == "GTK_TREE_MODEL_ROW") {
@@ -123,7 +123,7 @@ class DnDTreeView : public DnDTreeViewBase
} else if (selection_data.get_target() == object_type) {
- end_object_drag ();
+ end_object_drag (const_cast<Glib::RefPtr<Gdk::DragContext>& > (context));
} else {
/* some kind of target type added by the app, which will be handled by a signal handler */
@@ -135,7 +135,7 @@ class DnDTreeView : public DnDTreeViewBase
* object that wants to get the list of dragged items.
*/
- void get_object_drag_data (std::list<DataType>& l) {
+ void get_object_drag_data (std::list<DataType>& l, Gtk::TreeView** source) {
Glib::RefPtr<Gtk::TreeModel> model = drag_data.source->get_model();
DataType v;
Gtk::TreeSelection::ListHandle_Path selection = drag_data.source->get_selection()->get_selected_rows ();
@@ -144,13 +144,16 @@ class DnDTreeView : public DnDTreeViewBase
model->get_iter (*x)->get_value (drag_data.data_column, v);
l.push_back (v);
}
+
+ *source = drag_data.source;
}
private:
- void end_object_drag () {
+ void end_object_drag (Glib::RefPtr<Gdk::DragContext>& context) {
std::list<DataType> l;
- get_object_drag_data (l);
- signal_drop (l);
+ Gtk::TreeView* source;
+ get_object_drag_data (l, &source);
+ signal_drop (l, source, context);
}
};