summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2009-05-13 21:34:09 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2009-05-13 21:34:09 +0000
commit0569107ddc0d2a8df6ca0a2c8cc16ebe8f3dee99 (patch)
tree81b0a6ffb5cd967d3b205a11ad6d4f8726aa03d2
parent7188ec39903e4cef049468c5a0583d9ec67a290d (diff)
more work on the new all-Processor-all-The-Time redesign of Route - LOTS OF BREAKAGE STILL EXPECTED ; change all(?) methods that pass a start/end frame in to use sframes_t not nframes_t
git-svn-id: svn://localhost/ardour2/branches/3.0@5074 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--gtk2_ardour/audio_region_view.h1
-rw-r--r--gtk2_ardour/audio_streamview.cc39
-rw-r--r--gtk2_ardour/canvas-waveview.c1
-rw-r--r--gtk2_ardour/editor_ops.cc183
-rw-r--r--gtk2_ardour/port_matrix_grid.cc8
-rw-r--r--gtk2_ardour/processor_box.cc54
-rw-r--r--gtk2_ardour/processor_box.h1
-rw-r--r--gtk2_ardour/streamview.cc24
-rw-r--r--gtk2_ardour/streamview.h5
-rw-r--r--libs/ardour/amp.cc14
-rw-r--r--libs/ardour/ardour/amp.h3
-rw-r--r--libs/ardour/ardour/audio_track.h4
-rw-r--r--libs/ardour/ardour/configuration_vars.h1
-rw-r--r--libs/ardour/ardour/control_outputs.h27
-rw-r--r--libs/ardour/ardour/delivery.h79
-rw-r--r--libs/ardour/ardour/io.h4
-rw-r--r--libs/ardour/ardour/io_processor.h6
-rw-r--r--libs/ardour/ardour/meter.h3
-rw-r--r--libs/ardour/ardour/midi_diskstream.h1
-rw-r--r--libs/ardour/ardour/midi_state_tracker.h3
-rw-r--r--libs/ardour/ardour/midi_track.h7
-rw-r--r--libs/ardour/ardour/panner.h2
-rw-r--r--libs/ardour/ardour/playlist.h2
-rw-r--r--libs/ardour/ardour/plugin_insert.h2
-rw-r--r--libs/ardour/ardour/port_insert.h2
-rw-r--r--libs/ardour/ardour/processor.h19
-rw-r--r--libs/ardour/ardour/return.h2
-rw-r--r--libs/ardour/ardour/route.h40
-rw-r--r--libs/ardour/ardour/send.h9
-rw-r--r--libs/ardour/ardour/session.h10
-rw-r--r--libs/ardour/ardour/track.h8
-rw-r--r--libs/ardour/audio_track.cc4
-rw-r--r--libs/ardour/audioengine.cc5
-rw-r--r--libs/ardour/control_outputs.cc55
-rw-r--r--libs/ardour/delivery.cc203
-rw-r--r--libs/ardour/enums.cc8
-rw-r--r--libs/ardour/io.cc9
-rw-r--r--libs/ardour/io_processor.cc86
-rw-r--r--libs/ardour/meter.cc14
-rw-r--r--libs/ardour/midi_diskstream.cc169
-rw-r--r--libs/ardour/midi_state_tracker.cc19
-rw-r--r--libs/ardour/midi_track.cc6
-rw-r--r--libs/ardour/panner.cc2
-rw-r--r--libs/ardour/playlist.cc29
-rw-r--r--libs/ardour/plugin_insert.cc2
-rw-r--r--libs/ardour/plugin_manager.cc1
-rw-r--r--libs/ardour/port_insert.cc2
-rw-r--r--libs/ardour/processor.cc19
-rw-r--r--libs/ardour/return.cc2
-rw-r--r--libs/ardour/route.cc533
-rw-r--r--libs/ardour/send.cc44
-rw-r--r--libs/ardour/session.cc92
-rw-r--r--libs/ardour/session_transport.cc4
-rw-r--r--libs/ardour/track.cc12
-rw-r--r--libs/ardour/wscript2
-rw-r--r--libs/pbd/id.cc6
-rw-r--r--libs/pbd/pbd/id.h2
57 files changed, 1250 insertions, 644 deletions
diff --git a/gtk2_ardour/audio_region_view.h b/gtk2_ardour/audio_region_view.h
index 33d7c2ac1e..35e93b985f 100644
--- a/gtk2_ardour/audio_region_view.h
+++ b/gtk2_ardour/audio_region_view.h
@@ -28,6 +28,7 @@
#include "region_view.h"
#include "route_time_axis.h"
+
#include "time_axis_view_item.h"
#include "automation_line.h"
#include "enums.h"
diff --git a/gtk2_ardour/audio_streamview.cc b/gtk2_ardour/audio_streamview.cc
index 8dcee5aaab..772b455f97 100644
--- a/gtk2_ardour/audio_streamview.cc
+++ b/gtk2_ardour/audio_streamview.cc
@@ -108,30 +108,32 @@ RegionView*
AudioStreamView::add_region_view_internal (boost::shared_ptr<Region> r, bool wait_for_waves, bool recording)
{
AudioRegionView *region_view = 0;
-
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (r);
if (region == 0) {
return NULL;
}
- for (list<RegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
- if ((*i)->region() == r) {
-
- /* great. we already have a AudioRegionView for this Region. use it again. */
-
- (*i)->set_valid (true);
-
- // this might not be necessary
- AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
- if (arv) {
- arv->set_waveform_scale (_waveform_scale);
- arv->set_waveform_shape (_waveform_shape);
- }
+// if(!recording){
+// for (list<RegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+// if ((*i)->region() == r) {
+// cerr << "audio_streamview in add_region_view_internal region found" << endl;
+ /* great. we already have a AudioRegionView for this Region. use it again. */
- return NULL;
- }
- }
+// (*i)->set_valid (true);
+
+ // this might not be necessary
+// AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
+
+// if (arv) {
+// arv->set_waveform_scale (_waveform_scale);
+// arv->set_waveform_shape (_waveform_shape);
+// }
+
+// return NULL;
+// }
+// }
+// }
switch (_trackview.audio_track()->mode()) {
@@ -173,6 +175,7 @@ AudioStreamView::add_region_view_internal (boost::shared_ptr<Region> r, bool wai
otherwise, we set it to the current value */
if (region_views.size() == 1) {
+
if (region_view->waveform_logscaled()) {
_waveform_scale = LogWaveform;
} else {
@@ -191,7 +194,6 @@ AudioStreamView::add_region_view_internal (boost::shared_ptr<Region> r, bool wai
}
/* follow global waveform setting */
-
region_view->set_waveform_visible(_trackview.editor().show_waveforms());
/* catch regionview going away */
@@ -396,6 +398,7 @@ AudioStreamView::redisplay_diskstream ()
}
// Add and display region and crossfade views, and flag them as valid
+
if (_trackview.is_audio_track()) {
_trackview.get_diskstream()->playlist()->foreach_region(
static_cast<StreamView*>(this),
diff --git a/gtk2_ardour/canvas-waveview.c b/gtk2_ardour/canvas-waveview.c
index 5563fe5a78..8b2a7c8af7 100644
--- a/gtk2_ardour/canvas-waveview.c
+++ b/gtk2_ardour/canvas-waveview.c
@@ -764,6 +764,7 @@ gnome_canvas_waveview_set_property (GObject *object,
waveview->length_function = g_value_get_pointer(value);
redraw = TRUE;
break;
+
case PROP_SOURCEFILE_LENGTH_FUNCTION:
waveview->sourcefile_length_function = g_value_get_pointer(value);
redraw = TRUE;
diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc
index b1ad57f9cd..7e1a303e73 100644
--- a/gtk2_ardour/editor_ops.cc
+++ b/gtk2_ardour/editor_ops.cc
@@ -199,74 +199,6 @@ Editor::split_regions_at (nframes64_t where, RegionSelection& regions)
_new_regionviews_show_envelope = false;
}
-
-/** Remove `clicked_regionview' */
-void
-Editor::remove_clicked_region ()
-{
- if (clicked_routeview == 0 || clicked_regionview == 0) {
- return;
- }
-
- boost::shared_ptr<Playlist> playlist = clicked_routeview->playlist();
-
- begin_reversible_command (_("remove region"));
- XMLNode &before = playlist->get_state();
- playlist->remove_region (clicked_regionview->region());
- XMLNode &after = playlist->get_state();
- session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
- commit_reversible_command ();
-}
-
-
-/** Remove the selected regions */
-void
-Editor::remove_selected_regions ()
-{
- RegionSelection rs;
- get_regions_for_action (rs);
-
- if (!session) {
- return;
- }
-
- if (rs.empty()) {
- return;
- }
-
- begin_reversible_command (_("remove region"));
-
- list<boost::shared_ptr<Region> > regions_to_remove;
-
- for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
- // we can't just remove the region(s) in this loop because
- // this removes them from the RegionSelection, and they thus
- // disappear from underneath the iterator, and the ++i above
- // SEGVs in a puzzling fashion.
-
- // so, first iterate over the regions to be removed from rs and
- // add them to the regions_to_remove list, and then
- // iterate over the list to actually remove them.
-
- regions_to_remove.push_back ((*i)->region());
- }
-
- for (list<boost::shared_ptr<Region> >::iterator rl = regions_to_remove.begin(); rl != regions_to_remove.end(); ++rl) {
- boost::shared_ptr<Playlist> playlist = (*rl)->playlist();
- if (!playlist) {
- // is this check necessary?
- continue;
- }
-
- XMLNode &before = playlist->get_state();
- playlist->remove_region (*rl);
- XMLNode &after = playlist->get_state();
- session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
- }
-
- commit_reversible_command ();
-}
-
boost::shared_ptr<Region>
Editor::select_region_for_operation (int dir, TimeAxisView **tv)
{
@@ -4076,13 +4008,106 @@ struct PlaylistMapping {
PlaylistMapping (TimeAxisView* tvp) : tv (tvp) {}
};
+/** Remove `clicked_regionview' */
+void
+Editor::remove_clicked_region ()
+{
+ if (clicked_routeview == 0 || clicked_regionview == 0) {
+ return;
+ }
+
+ boost::shared_ptr<Playlist> playlist = clicked_routeview->playlist();
+
+ begin_reversible_command (_("remove region"));
+ XMLNode &before = playlist->get_state();
+ playlist->remove_region (clicked_regionview->region());
+ XMLNode &after = playlist->get_state();
+ session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
+ commit_reversible_command ();
+}
+
+
+/** Remove the selected regions */
+void
+Editor::remove_selected_regions ()
+{
+ RegionSelection rs;
+ get_regions_for_action (rs);
+
+ if (!session) {
+ return;
+ }
+
+ if (rs.empty()) {
+ return;
+ }
+
+ begin_reversible_command (_("remove region"));
+
+ list<boost::shared_ptr<Region> > regions_to_remove;
+
+ for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
+ // we can't just remove the region(s) in this loop because
+ // this removes them from the RegionSelection, and they thus
+ // disappear from underneath the iterator, and the ++i above
+ // SEGVs in a puzzling fashion.
+
+ // so, first iterate over the regions to be removed from rs and
+ // add them to the regions_to_remove list, and then
+ // iterate over the list to actually remove them.
+
+ regions_to_remove.push_back ((*i)->region());
+ }
+
+ vector<PlaylistState> playlists;
+
+ for (list<boost::shared_ptr<Region> >::iterator rl = regions_to_remove.begin(); rl != regions_to_remove.end(); ++rl) {
+
+ boost::shared_ptr<Playlist> playlist = (*rl)->playlist();
+
+ if (!playlist) {
+ // is this check necessary?
+ continue;
+ }
+
+ vector<PlaylistState>::iterator i;
+
+ //only take state if this is a new playlist.
+ for (i = playlists.begin(); i != playlists.end(); ++i) {
+ if ((*i).playlist == playlist) {
+ break;
+ }
+ }
+
+ if (i == playlists.end()) {
+
+ PlaylistState before;
+ before.playlist = playlist;
+ before.before = &playlist->get_state();
+
+ playlist->freeze ();
+ playlists.push_back(before);
+ }
+
+ playlist->remove_region (*rl);
+ }
+
+ vector<PlaylistState>::iterator pl;
+
+ for (pl = playlists.begin(); pl != playlists.end(); ++pl) {
+ (*pl).playlist->thaw ();
+ session->add_command(new MementoCommand<Playlist>(*(*pl).playlist, (*pl).before, &(*pl).playlist->get_state()));
+ }
+
+ commit_reversible_command ();
+}
/** Cut, copy or clear selected regions.
* @param op Operation (Cut, Copy or Clear)
*/
void
Editor::cut_copy_regions (CutCopyOp op, RegionSelection& rs)
-{
+{
/* we can't use a std::map here because the ordering is important, and we can't trivially sort
a map when we want ordered access to both elements. i think.
*/
@@ -4106,15 +4131,21 @@ Editor::cut_copy_regions (CutCopyOp op, RegionSelection& rs)
boost::shared_ptr<Playlist> pl = (*x)->region()->playlist();
if (pl) {
+ set<PlaylistState, lt_playlist>::iterator fl;
- PlaylistState before;
- before.playlist = pl;
- before.before = &pl->get_state();
-
- insert_result = freezelist.insert (before);
-
- if (insert_result.second) {
+ //only take state if this is a new playlist.
+ for (fl = freezelist.begin(); fl != freezelist.end(); ++fl) {
+ if ((*fl).playlist == pl) {
+ break;
+ }
+ }
+
+ if (fl == freezelist.end()) {
+ PlaylistState before;
+ before.playlist = pl;
+ before.before = &pl->get_state();
pl->freeze ();
+ insert_result = freezelist.insert (before);
}
}
}
diff --git a/gtk2_ardour/port_matrix_grid.cc b/gtk2_ardour/port_matrix_grid.cc
index bbf5447160..7c94beaeac 100644
--- a/gtk2_ardour/port_matrix_grid.cc
+++ b/gtk2_ardour/port_matrix_grid.cc
@@ -141,6 +141,8 @@ PortMatrixGrid::render (cairo_t* cr)
case PortMatrixNode::PARTIAL:
draw_association_indicator (cr, bx, by, 0.5);
break;
+ default:
+ break;
}
by += row_height();
@@ -179,6 +181,9 @@ PortMatrixGrid::render (cairo_t* cr)
case PortMatrixNode::NOT_ASSOCIATED:
break;
+
+ default:
+ break;
}
y += row_height();
@@ -483,6 +488,9 @@ PortMatrixGrid::bundle_to_bundle_state (boost::shared_ptr<ARDOUR::Bundle> a, boo
have_diagonal_not_association = true;
}
break;
+
+ default:
+ break;
}
}
}
diff --git a/gtk2_ardour/processor_box.cc b/gtk2_ardour/processor_box.cc
index f9b4cc0e6e..a259a25695 100644
--- a/gtk2_ardour/processor_box.cc
+++ b/gtk2_ardour/processor_box.cc
@@ -433,7 +433,9 @@ ProcessorBox::use_plugins (const SelectedPlugins& plugins)
processor->activate ();
}
- if (_route->add_processor (processor, &err_streams, 0, _placement)) {
+ assign_default_sort_key (processor);
+
+ if (_route->add_processor (processor, &err_streams)) {
weird_plugin_dialog (**p, err_streams, _route);
// XXX SHAREDPTR delete plugin here .. do we even need to care?
} else {
@@ -497,7 +499,9 @@ ProcessorBox::choose_insert ()
processor->ActiveChanged.connect (bind (
mem_fun(*this, &ProcessorBox::show_processor_active),
boost::weak_ptr<Processor>(processor)));
- _route->add_processor (processor, 0, 0, _placement);
+
+ assign_default_sort_key (processor);
+ _route->add_processor (processor);
}
void
@@ -549,7 +553,8 @@ ProcessorBox::send_io_finished (IOSelector::Result r, boost::weak_ptr<Processor>
break;
case IOSelector::Accepted:
- _route->add_processor (processor, 0, 0, _placement);
+ assign_default_sort_key (processor);
+ _route->add_processor (processor);
if (Profile->get_sae()) {
processor->activate ();
}
@@ -606,7 +611,8 @@ ProcessorBox::return_io_finished (IOSelector::Result r, boost::weak_ptr<Processo
break;
case IOSelector::Accepted:
- _route->add_processor (processor, 0, 0, _placement);
+ assign_default_sort_key (processor);
+ _route->add_processor (processor);
if (Profile->get_sae()) {
processor->activate ();
}
@@ -636,10 +642,10 @@ ProcessorBox::redisplay_processors ()
switch (_placement) {
case PreFader:
- build_processor_tooltip(processor_eventbox, _("Pre-fader inserts, sends & plugins:"));
+ build_processor_tooltip (processor_eventbox, _("Pre-fader inserts, sends & plugins:"));
break;
case PostFader:
- build_processor_tooltip(processor_eventbox, _("Post-fader inserts, sends & plugins:"));
+ build_processor_tooltip (processor_eventbox, _("Post-fader inserts, sends & plugins:"));
break;
}
}
@@ -790,9 +796,15 @@ ProcessorBox::row_deleted (const Gtk::TreeModel::Path& path)
void
ProcessorBox::compute_processor_sort_keys ()
{
- uint32_t sort_key = 0;
+ uint32_t sort_key;
Gtk::TreeModel::Children children = model->children();
+ if (_placement == PreFader) {
+ sort_key = 0;
+ } else {
+ sort_key = _route->fader_sort_key() + 1;
+ }
+
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);
@@ -1013,6 +1025,17 @@ ProcessorBox::paste_processor_state (const XMLNodeList& nlist)
} else if (type->value() == "meter") {
p = _route->shared_peak_meter();
+ } else if (type->value() == "main-outs") {
+ /* do not copy-n-paste main outs */
+ continue;
+
+ } else if (type->value() == "amp") {
+ /* do not copy-n-paste amp */
+ continue;
+
+ } else if (type->value() == "listen") {
+ p.reset (new Delivery (_session, **niter));
+
} else {
p.reset (new PluginInsert (_session, **niter));
}
@@ -1024,7 +1047,13 @@ ProcessorBox::paste_processor_state (const XMLNodeList& nlist)
}
}
- if (_route->add_processors (copies, 0, _placement)) {
+ if (copies.empty()) {
+ return;
+ }
+
+ assign_default_sort_key (copies.front());
+
+ if (_route->add_processors (copies, 0, copies.front()->sort_key())) {
string msg = _(
"Copying the set of processors on the clipboard failed,\n\
@@ -1539,3 +1568,12 @@ 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 3286c14e6c..f5af4c49dc 100644
--- a/gtk2_ardour/processor_box.h
+++ b/gtk2_ardour/processor_box.h
@@ -168,6 +168,7 @@ 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;
diff --git a/gtk2_ardour/streamview.cc b/gtk2_ardour/streamview.cc
index 6425b84c27..2127d1354c 100644
--- a/gtk2_ardour/streamview.cc
+++ b/gtk2_ardour/streamview.cc
@@ -169,9 +169,19 @@ StreamView::set_samples_per_unit (gdouble spp)
}
void
+StreamView::add_region_view_weak (boost::weak_ptr<Region> r)
+{
+ boost::shared_ptr<Region> sp (r.lock());
+
+ if (sp) {
+ add_region_view (sp);
+ }
+}
+
+void
StreamView::add_region_view (boost::shared_ptr<Region> r)
{
- // ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::add_region_view), r));
+ ENSURE_GUI_THREAD (bind (mem_fun (*this, &StreamView::add_region_view), r));
add_region_view_internal (r, true);
if (_layer_display == Stacked) {
@@ -284,6 +294,7 @@ void
StreamView::playlist_modified_weak (boost::weak_ptr<Diskstream> ds)
{
boost::shared_ptr<Diskstream> sp (ds.lock());
+
if (sp) {
playlist_modified (sp);
}
@@ -300,7 +311,7 @@ StreamView::playlist_modified (boost::shared_ptr<Diskstream> ds)
_layers = ds->playlist()->top_layer() + 1;
update_contents_height ();
update_coverage_frames ();
- redisplay_diskstream ();
+ //redisplay_diskstream ();
}
}
@@ -342,8 +353,13 @@ StreamView::playlist_changed (boost::shared_ptr<Diskstream> ds)
/* catch changes */
playlist_connections.push_back (ds->playlist()->Modified.connect (bind (
- mem_fun (*this, &StreamView::playlist_modified_weak),
- ds)));
+ mem_fun (*this, &StreamView::playlist_modified_weak), ds)));
+
+ playlist_connections.push_back (ds->playlist()->RegionAdded.connect (
+ mem_fun (*this, &StreamView::add_region_view_weak)));
+
+ playlist_connections.push_back (ds->playlist()->RegionRemoved.connect (
+ mem_fun (*this, &StreamView::remove_region_view)));
}
void
diff --git a/gtk2_ardour/streamview.h b/gtk2_ardour/streamview.h
index 546d51dee2..bb6047df23 100644
--- a/gtk2_ardour/streamview.h
+++ b/gtk2_ardour/streamview.h
@@ -93,7 +93,10 @@ public:
void get_inverted_selectables (Selection&, std::list<Selectable* >& results);
virtual void update_contents_metrics(boost::shared_ptr<ARDOUR::Region> r) {}
+
+ void add_region_view_weak (boost::weak_ptr<ARDOUR::Region> r);
void add_region_view (boost::shared_ptr<ARDOUR::Region>);
+
void region_layered (RegionView*);
virtual void update_contents_height ();
@@ -114,7 +117,7 @@ protected:
void update_rec_box ();
virtual RegionView* add_region_view_internal (boost::shared_ptr<ARDOUR::Region>,
- bool wait_for_waves, bool recording = false) = 0;
+ bool wait_for_waves, bool recording = false) = 0;
virtual void remove_region_view (boost::weak_ptr<ARDOUR::Region> );
void display_diskstream (boost::shared_ptr<ARDOUR::Diskstream>);
diff --git a/libs/ardour/amp.cc b/libs/ardour/amp.cc
index aa20f3e389..591fcd8569 100644
--- a/libs/ardour/amp.cc
+++ b/libs/ardour/amp.cc
@@ -57,7 +57,7 @@ Amp::configure_io (ChanCount in, ChanCount out)
}
void
-Amp::run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes)
+Amp::run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
{
gain_t* gab = _session.gain_automation_buffer();
@@ -201,15 +201,9 @@ Amp::apply_simple_gain (BufferSet& bufs, nframes_t nframes, gain_t target)
XMLNode&
Amp::state (bool full_state)
{
- return get_state();
-}
-
-XMLNode&
-Amp::get_state()
-{
- XMLNode* node = new XMLNode(state_node_name);
- node->add_property("type", "amp");
- return *node;
+ XMLNode& node (Processor::state (full_state));
+ node.add_property("type", "amp");
+ return node;
}
} // namespace ARDOUR
diff --git a/libs/ardour/ardour/amp.h b/libs/ardour/ardour/amp.h
index fa9de724ad..152b89a431 100644
--- a/libs/ardour/ardour/amp.h
+++ b/libs/ardour/ardour/amp.h
@@ -39,7 +39,7 @@ public:
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
bool configure_io (ChanCount in, ChanCount out);
- void run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes);
+ void run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
bool apply_gain() const { return _apply_gain; }
void apply_gain(bool yn) { _apply_gain = yn; }
@@ -61,7 +61,6 @@ public:
}
XMLNode& state (bool full);
- XMLNode& get_state();
static void apply_gain (BufferSet& bufs, nframes_t nframes,
gain_t initial, gain_t target, bool invert_polarity);
diff --git a/libs/ardour/ardour/audio_track.h b/libs/ardour/ardour/audio_track.h
index 145272b331..5813c2d697 100644
--- a/libs/ardour/ardour/audio_track.h
+++ b/libs/ardour/ardour/audio_track.h
@@ -39,7 +39,7 @@ class AudioTrack : public Track
int set_mode (TrackMode m);
bool can_use_mode (TrackMode m, bool& bounce_required);
- int roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
+ int roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
int declick, bool can_record, bool rec_monitors_input);
boost::shared_ptr<AudioDiskstream> audio_diskstream() const;
@@ -47,7 +47,7 @@ class AudioTrack : public Track
int use_diskstream (std::string name);
int use_diskstream (const PBD::ID& id);
- int export_stuff (BufferSet& bufs, nframes_t nframes, nframes_t end_frame, bool enable_processing = true);
+ int export_stuff (BufferSet& bufs, sframes_t start_frame, nframes_t nframes, bool enable_processing = true);
void freeze (InterThreadInfo&);
void unfreeze ();
diff --git a/libs/ardour/ardour/configuration_vars.h b/libs/ardour/ardour/configuration_vars.h
index 3091538e38..f49663b55b 100644
--- a/libs/ardour/ardour/configuration_vars.h
+++ b/libs/ardour/ardour/configuration_vars.h
@@ -19,6 +19,7 @@
/* IO connection */
+CONFIG_VARIABLE (bool, auto_connect_master, "auto-connect-master", true)
CONFIG_VARIABLE (AutoConnectOption, output_auto_connect, "output-auto-connect", AutoConnectOption (0))
CONFIG_VARIABLE (AutoConnectOption, input_auto_connect, "input-auto-connect", AutoConnectOption (0))
diff --git a/libs/ardour/ardour/control_outputs.h b/libs/ardour/ardour/control_outputs.h
index 72d9534ddf..0a09ab10f4 100644
--- a/libs/ardour/ardour/control_outputs.h
+++ b/libs/ardour/ardour/control_outputs.h
@@ -26,26 +26,19 @@
namespace ARDOUR {
-class BufferSet;
-class IO;
+/* this exists for one reason only: so that it can override the "type"
+ property in the state of the Delivery processor. we need this
+ because ControlOutputs are "unique" because they deliver to
+ an IO object that is private to a Route and so cannot be looked
+ up in the Session etc.
+*/
-class ControlOutputs : public IOProcessor {
+class ControlOutputs : public Delivery {
public:
- ControlOutputs(Session& s, IO* io);
-
- bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
- bool configure_io (ChanCount in, ChanCount out);
-
- void run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes);
-
- bool deliver() const { return _deliver; }
- void deliver(bool yn) { _deliver = yn; }
-
- XMLNode& state (bool full);
- XMLNode& get_state();
+ ControlOutputs(Session& s);
+ XMLNode& get_state ();
-private:
- bool _deliver;
+ static const std::string processor_type_name;
};
diff --git a/libs/ardour/ardour/delivery.h b/libs/ardour/ardour/delivery.h
new file mode 100644
index 0000000000..8d083695b1
--- /dev/null
+++ b/libs/ardour/ardour/delivery.h
@@ -0,0 +1,79 @@
+/*
+ Copyright (C) 2006 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_delivery_h__
+#define __ardour_delivery_h__
+
+#include <string>
+#include "ardour/types.h"
+#include "ardour/chan_count.h"
+#include "ardour/io_processor.h"
+
+namespace ARDOUR {
+
+class BufferSet;
+class IO;
+
+class Delivery : public IOProcessor {
+public:
+ enum Role {
+ Send = 0x1,
+ Solo = 0x2,
+ Listen = 0x4,
+ Main = 0x8
+ };
+
+ Delivery (Session& s, IO* io, const std::string& name, Role);
+ Delivery (Session& s, const std::string& name, Role);
+ Delivery (Session&, const XMLNode&);
+
+ bool visible() const;
+
+ Role role() const { return _role; }
+
+ bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
+ bool configure_io (ChanCount in, ChanCount out);
+
+ void run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
+
+ void set_metering (bool yn);
+
+ bool muted_by_self() const { return _muted_by_self; }
+ bool muted_by_others() const { return _muted_by_others; }
+
+ void set_self_mute (bool);
+ void set_nonself_mute (bool);
+
+ sigc::signal<void> SelfMuteChange;
+ sigc::signal<void> OtherMuteChange;
+
+ XMLNode& state (bool full);
+ int set_state (const XMLNode&);
+
+private:
+ Role _role;
+ bool _metering;
+ bool _muted_by_self;
+ bool _muted_by_others;
+};
+
+
+} // namespace ARDOUR
+
+#endif // __ardour__h__
+
diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h
index 8b236eadff..297a4ee82c 100644
--- a/libs/ardour/ardour/io.h
+++ b/libs/ardour/ardour/io.h
@@ -100,8 +100,8 @@ class IO : public SessionObject, public AutomatableControls, public Latent
virtual void silence (nframes_t);
void collect_input (BufferSet& bufs, nframes_t nframes, ChanCount offset=ChanCount::ZERO);
- void deliver_output (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes);
- void just_meter_input (nframes_t start_frame, nframes_t end_frame, nframes_t nframes);
+ void deliver_output (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
+ void just_meter_input (sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
BufferSet& output_buffers() { return *_output_buffers; }
diff --git a/libs/ardour/ardour/io_processor.h b/libs/ardour/ardour/io_processor.h
index 7f847c9221..896de52a3b 100644
--- a/libs/ardour/ardour/io_processor.h
+++ b/libs/ardour/ardour/io_processor.h
@@ -49,6 +49,8 @@ class IOProcessor : public Processor
ARDOUR::DataType default_type = DataType::AUDIO);
virtual ~IOProcessor ();
+ bool set_name (const std::string& str);
+
virtual ChanCount output_streams() const;
virtual ChanCount input_streams () const;
virtual ChanCount natural_output_streams() const;
@@ -56,10 +58,11 @@ class IOProcessor : public Processor
boost::shared_ptr<IO> io() { return _io; }
boost::shared_ptr<const IO> io() const { return _io; }
+ void set_io (boost::shared_ptr<IO>);
virtual void automation_snapshot (nframes_t now, bool force);
- virtual void run_in_place (BufferSet& in, nframes_t start, nframes_t end, nframes_t nframes) = 0;
+ virtual void run_in_place (BufferSet& in, sframes_t start, sframes_t end, nframes_t nframes) = 0;
void silence (nframes_t nframes);
sigc::signal<void,IOProcessor*,bool> AutomationPlaybackChanged;
@@ -74,6 +77,7 @@ class IOProcessor : public Processor
private:
/* disallow copy construction */
IOProcessor (const IOProcessor&);
+ bool _own_io;
};
diff --git a/libs/ardour/ardour/meter.h b/libs/ardour/ardour/meter.h
index 0a49ddf99f..250fb3111e 100644
--- a/libs/ardour/ardour/meter.h
+++ b/libs/ardour/ardour/meter.h
@@ -44,7 +44,7 @@ public:
bool configure_io (ChanCount in, ChanCount out);
/** Compute peaks */
- void run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes);
+ void run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
float peak_power (uint32_t n) {
if (n < _visible_peak_power.size()) {
@@ -63,7 +63,6 @@ public:
}
XMLNode& state (bool full);
- XMLNode& get_state();
private:
friend class IO;
diff --git a/libs/ardour/ardour/midi_diskstream.h b/libs/ardour/ardour/midi_diskstream.h
index a7b4f5e120..d5c2d0cdb3 100644
--- a/libs/ardour/ardour/midi_diskstream.h
+++ b/libs/ardour/ardour/midi_diskstream.h
@@ -180,6 +180,7 @@ class MidiDiskstream : public Diskstream
nframes_t _last_flush_frame;
NoteMode _note_mode;
MidiStateTracker _midi_state_tracker;
+ MidiStateTracker _incoming_midi_state_tracker;
volatile gint _frames_written_to_ringbuffer;
volatile gint _frames_read_from_ringbuffer;
};
diff --git a/libs/ardour/ardour/midi_state_tracker.h b/libs/ardour/ardour/midi_state_tracker.h
index 3f74d67b17..4c15ab1e0f 100644
--- a/libs/ardour/ardour/midi_state_tracker.h
+++ b/libs/ardour/ardour/midi_state_tracker.h
@@ -24,7 +24,6 @@
#include "ardour/midi_buffer.h"
-
namespace ARDOUR {
@@ -38,6 +37,8 @@ public:
bool track (const MidiBuffer::iterator& from, const MidiBuffer::iterator& to);
void resolve_notes (MidiBuffer& buffer, nframes_t time);
+ void dump (std::ostream&);
+ void reset ();
private:
void track_note_onoffs(const Evoral::MIDIEvent<MidiBuffer::TimeType>& event);
diff --git a/libs/ardour/ardour/midi_track.h b/libs/ardour/ardour/midi_track.h
index fe8290d5d9..e7ffd40d67 100644
--- a/libs/ardour/ardour/midi_track.h
+++ b/libs/ardour/ardour/midi_track.h
@@ -38,7 +38,7 @@ public:
MidiTrack (Session&, const XMLNode&);
~MidiTrack ();
- int roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
+ int roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
int declick, bool can_record, bool rec_monitors_input);
boost::shared_ptr<MidiDiskstream> midi_diskstream() const;
@@ -48,8 +48,7 @@ public:
void set_latency_delay (nframes_t);
- int export_stuff (BufferSet& bufs,
- nframes_t nframes, nframes_t end_frame);
+ int export_stuff (BufferSet& bufs, nframes_t nframes, sframes_t end_frame);
void freeze (InterThreadInfo&);
void unfreeze ();
@@ -85,7 +84,7 @@ protected:
int _set_state (const XMLNode&, bool call_base);
private:
- void write_controller_messages(MidiBuffer& buf, nframes_t start_frame, nframes_t end_frame, nframes_t nframes);
+ void write_controller_messages(MidiBuffer& buf, sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
int set_diskstream (boost::shared_ptr<MidiDiskstream> ds);
void use_new_diskstream ();
diff --git a/libs/ardour/ardour/panner.h b/libs/ardour/ardour/panner.h
index be3de9a5a3..9bc1817af0 100644
--- a/libs/ardour/ardour/panner.h
+++ b/libs/ardour/ardour/panner.h
@@ -215,7 +215,7 @@ class Panner : public Processor
bool is_out_of_place () const { return true; }
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const { return true; };
- void run_out_of_place(BufferSet& src, BufferSet& dest, nframes_t start_frame, nframes_t end_frames, nframes_t nframes);
+ void run_out_of_place(BufferSet& src, BufferSet& dest, sframes_t start_frame, sframes_t end_frames, nframes_t nframes);
//void* get_inline_gui() const = 0;
//void* get_full_gui() const = 0;
diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h
index 15aa041ed6..8be95ca74b 100644
--- a/libs/ardour/ardour/playlist.h
+++ b/libs/ardour/ardour/playlist.h
@@ -129,6 +129,8 @@ class Playlist : public SessionObject,
sigc::signal<void,bool> InUse;
sigc::signal<void> Modified;
+ sigc::signal<void, boost::weak_ptr<Region> > RegionAdded;
+ sigc::signal<void, boost::weak_ptr<Region> > RegionRemoved;
sigc::signal<void> NameChanged;
sigc::signal<void> LengthChanged;
sigc::signal<void, std::list< Evoral::RangeMove<nframes_t> > const &> RangesMoved;
diff --git a/libs/ardour/ardour/plugin_insert.h b/libs/ardour/ardour/plugin_insert.h
index 59ab6de2d8..01cf9bedfd 100644
--- a/libs/ardour/ardour/plugin_insert.h
+++ b/libs/ardour/ardour/plugin_insert.h
@@ -54,7 +54,7 @@ class PluginInsert : public Processor
XMLNode& get_state(void);
int set_state(const XMLNode&);
- void run_in_place (BufferSet& in, nframes_t start_frame, nframes_t end_frame, nframes_t nframes);
+ void run_in_place (BufferSet& in, sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
void silence (nframes_t nframes);
void activate ();
diff --git a/libs/ardour/ardour/port_insert.h b/libs/ardour/ardour/port_insert.h
index ce21d9f223..56aa43c6c5 100644
--- a/libs/ardour/ardour/port_insert.h
+++ b/libs/ardour/ardour/port_insert.h
@@ -50,7 +50,7 @@ class PortInsert : public IOProcessor
void init ();
- void run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes);
+ void run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
nframes_t signal_latency() const;
diff --git a/libs/ardour/ardour/processor.h b/libs/ardour/ardour/processor.h
index 757af64c87..68fdb5c6a6 100644
--- a/libs/ardour/ardour/processor.h
+++ b/libs/ardour/ardour/processor.h
@@ -60,6 +60,8 @@ class Processor : public SessionObject, public AutomatableControls, public Laten
ChanCount in;
ChanCount out;
};
+
+ virtual bool visible() const { return true; }
uint32_t sort_key() const { return _sort_key; }
void set_sort_key (uint32_t key);
@@ -76,12 +78,12 @@ class Processor : public SessionObject, public AutomatableControls, public Laten
virtual void set_block_size (nframes_t nframes) {}
virtual void run_in_place (BufferSet& bufs,
- nframes_t start_frame, nframes_t end_frame,
- nframes_t nframes) { assert(is_in_place()); }
+ sframes_t start_frame, sframes_t end_frame,
+ nframes_t nframes) { assert(is_in_place()); }
virtual void run_out_of_place (BufferSet& input, BufferSet& output,
- nframes_t start_frame, nframes_t end_frame,
- nframes_t nframes) { assert(is_out_of_place()); }
+ sframes_t start_frame, sframes_t end_frame,
+ nframes_t nframes) { assert(is_out_of_place()); }
virtual void silence (nframes_t nframes) {}
@@ -103,9 +105,14 @@ class Processor : public SessionObject, public AutomatableControls, public Laten
virtual ChanCount input_streams () const { return _configured_input; }
virtual ChanCount output_streams() const { return _configured_output; }
+ /* note: derived classes should implement state(), NOT get_state(), to allow
+ us to merge C++ inheritance and XML lack-of-inheritance reasonably
+ smoothly.
+ */
+
virtual XMLNode& state (bool full);
- virtual XMLNode& get_state (void);
- virtual int set_state (const XMLNode&);
+ XMLNode& get_state (void);
+ int set_state (const XMLNode&);
void *get_gui () const { return _gui; }
void set_gui (void *p) { _gui = p; }
diff --git a/libs/ardour/ardour/return.h b/libs/ardour/ardour/return.h
index af55df59ed..2b6cd0b69e 100644
--- a/libs/ardour/ardour/return.h
+++ b/libs/ardour/ardour/return.h
@@ -41,7 +41,7 @@ public:
uint32_t bit_slot() const { return _bitslot; }
- void run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes);
+ void run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
void activate() {}
void deactivate () {}
diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h
index 9537097f74..aee361d3a5 100644
--- a/libs/ardour/ardour/route.h
+++ b/libs/ardour/ardour/route.h
@@ -45,7 +45,7 @@
namespace ARDOUR {
class Amp;
-class ControlOutputs;
+class Delivery;
class IOProcessor;
class Processor;
class RouteGroup;
@@ -84,6 +84,8 @@ class Route : public IO
std::string comment() { return _comment; }
void set_comment (std::string str, void *src);
+ bool set_name (const std::string& str);
+
long order_key (const char* name) const;
void set_order_key (const char* name, long n);
@@ -94,13 +96,13 @@ class Route : public IO
/* these are the core of the API of a Route. see the protected sections as well */
- virtual int roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
+ virtual int roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
int declick, bool can_record, bool rec_monitors_input);
- virtual int no_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
+ virtual int no_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
bool state_changing, bool can_record, bool rec_monitors_input);
- virtual int silent_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
+ virtual int silent_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
bool can_record, bool rec_monitors_input);
virtual void toggle_monitor_input ();
@@ -173,9 +175,16 @@ class Route : public IO
return *i;
}
}
+
+ uint32_t fader_sort_key() const;
ChanCount max_processor_streams () const { return processor_max_streams; }
ChanCount pre_fader_streams() const;
+
+ /* special processors */
+
+ boost::shared_ptr<Delivery> control_outs() const { return _control_outs; }
+ boost::shared_ptr<Delivery> main_outs() const { return _main_outs; }
/** A record of the stream configuration at some point in the processor list.
* Used to return where and why an processor list configuration request failed.
@@ -187,8 +196,8 @@ class Route : public IO
ChanCount count; ///< Input requested of processor
};
- int add_processor (boost::shared_ptr<Processor>, ProcessorStreams* err = 0, ProcessorList::iterator* iter=0, Placement=PreFader);
- int add_processors (const ProcessorList&, ProcessorStreams* err = 0, Placement placement=PreFader);
+ 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 remove_processor (boost::shared_ptr<Processor>, ProcessorStreams* err = 0);
int sort_processors (ProcessorStreams* err = 0);
void disable_processors (Placement);
@@ -237,9 +246,9 @@ class Route : public IO
int save_as_template (const std::string& path, const std::string& name);
sigc::signal<void,void*> SelectedChanged;
-
- int set_control_outs (const std::vector<std::string>& ports);
- boost::shared_ptr<ControlOutputs> control_outs() { return _control_outs; }
+
+ int listen_via (boost::shared_ptr<IO>, const std::string& name);
+ void drop_listen (boost::shared_ptr<IO>);
bool feeds (boost::shared_ptr<Route>);
std::set<boost::shared_ptr<Route> > fed_by;
@@ -288,11 +297,11 @@ class Route : public IO
protected:
nframes_t check_initial_delay (nframes_t, nframes_t&);
- void passthru (nframes_t start_frame, nframes_t end_frame,
- nframes_t nframes, int declick);
+ void passthru (sframes_t start_frame, sframes_t end_frame,
+ nframes_t nframes, int declick);
virtual void process_output_buffers (BufferSet& bufs,
- nframes_t start_frame, nframes_t end_frame,
+ sframes_t start_frame, sframes_t end_frame,
nframes_t nframes, bool with_processors, int declick);
Flag _flags;
@@ -308,7 +317,8 @@ class Route : public IO
nframes_t _roll_delay;
ProcessorList _processors;
Glib::RWLock _processor_lock;
- boost::shared_ptr<ControlOutputs> _control_outs;
+ boost::shared_ptr<Delivery> _main_outs;
+ boost::shared_ptr<Delivery> _control_outs; // XXX to be removed/generalized by listen points
RouteGroup *_edit_group;
RouteGroup *_mix_group;
std::string _comment;
@@ -336,7 +346,7 @@ class Route : public IO
virtual XMLNode& state(bool);
- void passthru_silence (nframes_t start_frame, nframes_t end_frame,
+ void passthru_silence (sframes_t start_frame, sframes_t end_frame,
nframes_t nframes, int declick);
void silence (nframes_t nframes);
@@ -354,6 +364,8 @@ class Route : public IO
virtual int _set_state (const XMLNode&, bool call_base);
virtual void _set_processor_states (const XMLNodeList&);
+ boost::shared_ptr<Delivery> add_listener (boost::shared_ptr<IO>, const std::string&);
+
private:
void init ();
diff --git a/libs/ardour/ardour/send.h b/libs/ardour/ardour/send.h
index 825506f0e2..7bdc7ed02f 100644
--- a/libs/ardour/ardour/send.h
+++ b/libs/ardour/ardour/send.h
@@ -27,11 +27,11 @@
#include "pbd/stateful.h"
#include "ardour/ardour.h"
#include "ardour/audioengine.h"
-#include "ardour/io_processor.h"
+#include "ardour/delivery.h"
namespace ARDOUR {
-class Send : public IOProcessor
+class Send : public Delivery
{
public:
Send (Session&);
@@ -40,13 +40,9 @@ class Send : public IOProcessor
uint32_t bit_slot() const { return _bitslot; }
- void run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes);
-
void activate() {}
void deactivate () {}
- void set_metering (bool yn);
-
XMLNode& state(bool full);
XMLNode& get_state(void);
int set_state(const XMLNode& node);
@@ -63,7 +59,6 @@ class Send : public IOProcessor
/* disallow copy construction */
Send (const Send&);
- bool _metering;
uint32_t _bitslot;
};
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index 31bbded03b..344b79bcd1 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -1020,12 +1020,10 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
bool _silent;
volatile double _transport_speed;
double _last_transport_speed;
- // fixed point transport speed for varispeed playback
- uint64_t phi;
- // fixed point target transport speed for varispeed playback when tempo changes
- uint64_t target_phi;
- // fixed point phase for varispeed playback
- uint64_t phase;
+ // varispeed playback
+ uint64_t phi; // fixed point transport speed
+ uint64_t target_phi; // fixed point target transport speed
+ uint64_t phase; // fixed point phase
bool auto_play_legal;
nframes_t _last_slave_transport_frame;
nframes_t maximum_output_latency;
diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h
index 700380417b..aca7c6f968 100644
--- a/libs/ardour/ardour/track.h
+++ b/libs/ardour/ardour/track.h
@@ -45,13 +45,13 @@ class Track : public Route
virtual bool can_use_mode (TrackMode m, bool& bounce_required) { return false; }
sigc::signal<void> TrackModeChanged;
- int no_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
- bool state_changing, bool can_record, bool rec_monitors_input);
+ int no_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
+ bool state_changing, bool can_record, bool rec_monitors_input);
- int silent_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
+ int silent_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
bool can_record, bool rec_monitors_input);
- virtual int roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
+ virtual int roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
int declick, bool can_record, bool rec_monitors_input) = 0;
void toggle_monitor_input ();
diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc
index 79b1240ab0..4a3fa04d1c 100644
--- a/libs/ardour/audio_track.cc
+++ b/libs/ardour/audio_track.cc
@@ -454,7 +454,7 @@ AudioTrack::set_state_part_two ()
}
int
-AudioTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, int declick,
+AudioTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame, int declick,
bool can_record, bool rec_monitors_input)
{
int dret;
@@ -624,7 +624,7 @@ AudioTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
}
int
-AudioTrack::export_stuff (BufferSet& buffers, nframes_t start, nframes_t nframes, bool enable_processing)
+AudioTrack::export_stuff (BufferSet& buffers, sframes_t start, nframes_t nframes, bool enable_processing)
{
gain_t gain_buffer[nframes];
float mix_buffer[nframes];
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index 91cea6ba71..3e1ba8b2d9 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -41,6 +41,9 @@
#include "ardour/utils.h"
#include "ardour/event_type_map.h"
#include "ardour/io.h"
+#include "ardour/amp.h"
+#include "ardour/port_set.h"
+#include "ardour/buffer_set.h"
#include "ardour/timestamps.h"
@@ -420,7 +423,7 @@ AudioEngine::process_callback (nframes_t nframes)
port->get_buffer(nframes).silence(nframes);
}
}
- }
+ }
// Finalize ports
diff --git a/libs/ardour/control_outputs.cc b/libs/ardour/control_outputs.cc
index 2acd3c6d9e..8efb75145c 100644
--- a/libs/ardour/control_outputs.cc
+++ b/libs/ardour/control_outputs.cc
@@ -16,64 +16,23 @@
675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <cmath>
-#include <algorithm>
#include "ardour/control_outputs.h"
-#include "ardour/audio_buffer.h"
-#include "ardour/buffer_set.h"
-#include "ardour/configuration.h"
-#include "ardour/io.h"
-#include "ardour/session.h"
using namespace std;
+using namespace ARDOUR;
-namespace ARDOUR {
+const std::string ControlOutputs::processor_type_name = "control-outputs";
-ControlOutputs::ControlOutputs(Session& s, IO* io)
- : IOProcessor(s, io, "Control Outs")
- , _deliver(true)
+ControlOutputs::ControlOutputs(Session& s, IO* io, const std::string& name)
+ : Delivery (s, io, name)
{
}
-bool
-ControlOutputs::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
-{
- out = in;
- return true;
-}
-
-bool
-ControlOutputs::configure_io (ChanCount in, ChanCount out)
-{
- if (out != in) { // always 1:1
- return false;
- }
-
- return Processor::configure_io (in, out);
-}
-
-void
-ControlOutputs::run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes)
-{
- if (_deliver) {
- _io->deliver_output (bufs, start_frame, end_frame, nframes);
- } else {
- _io->silence (nframes);
- }
-}
-
-XMLNode&
-ControlOutputs::state (bool full_state)
-{
- return get_state();
-}
-
XMLNode&
ControlOutputs::get_state()
{
- XMLNode* node = new XMLNode(state_node_name);
- node->add_property("type", "control-outputs");
- return *node;
+ XMLNode& node (Delivery::get_state());
+ node.add_property ("type", processor_type_name);
+ return node;
}
-} // namespace ARDOUR
diff --git a/libs/ardour/delivery.cc b/libs/ardour/delivery.cc
new file mode 100644
index 0000000000..bf15242094
--- /dev/null
+++ b/libs/ardour/delivery.cc
@@ -0,0 +1,203 @@
+/*
+ Copyright (C) 2009 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 <cmath>
+#include <algorithm>
+
+#include "pbd/enumwriter.h"
+#include "ardour/delivery.h"
+#include "ardour/audio_buffer.h"
+#include "ardour/buffer_set.h"
+#include "ardour/configuration.h"
+#include "ardour/io.h"
+#include "ardour/meter.h"
+#include "ardour/session.h"
+
+using namespace std;
+using namespace ARDOUR;
+
+/* deliver to an existing IO object */
+
+Delivery::Delivery (Session& s, IO* io, const string& name, Role r)
+ : IOProcessor(s, io, name)
+ , _role (r)
+ , _metering (false)
+ , _muted_by_self (false)
+ , _muted_by_others (false)
+{
+}
+
+/* deliver to a new IO object */
+
+Delivery::Delivery (Session& s, const string& name, Role r)
+ : IOProcessor(s, name)
+ , _role (r)
+ , _metering (false)
+ , _muted_by_self (false)
+ , _muted_by_others (false)
+{
+}
+
+/* reconstruct from XML */
+
+Delivery::Delivery (Session& s, const XMLNode& node)
+ : IOProcessor (s, "reset")
+ , _role (Role (0))
+ , _metering (false)
+ , _muted_by_self (false)
+ , _muted_by_others (false)
+{
+ if (set_state (node)) {
+ throw failed_constructor ();
+ }
+}
+
+
+bool
+Delivery::visible () const
+{
+ if (_role & (Main|Solo)) {
+ return false;
+ }
+
+ return true;
+}
+
+bool
+Delivery::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
+{
+ out = in;
+ return true;
+}
+
+bool
+Delivery::configure_io (ChanCount in, ChanCount out)
+{
+ if (out != in) { // always 1:1
+ return false;
+ }
+
+ return Processor::configure_io (in, out);
+}
+
+void
+Delivery::run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
+{
+ if (_io->n_outputs().get (_io->default_type()) == 0) {
+ return;
+ }
+
+ if (!active() || _muted_by_self || _muted_by_others) {
+ silence (nframes);
+ if (_metering) {
+ _io->peak_meter().reset();
+ }
+ } else {
+
+ // we have to copy the input, because IO::deliver_output may alter the buffers
+ // in-place, which a send must never do.
+
+ BufferSet& sendbufs = _session.get_mix_buffers (bufs.count());
+
+ sendbufs.read_from(bufs, nframes);
+ assert(sendbufs.count() == bufs.count());
+
+ _io->deliver_output (sendbufs, start_frame, end_frame, nframes);
+
+ if (_metering) {
+ if (_io->effective_gain() == 0) {
+ _io->peak_meter().reset();
+ } else {
+ _io->peak_meter().run_in_place(_io->output_buffers(), start_frame, end_frame, nframes);
+ }
+ }
+ }
+}
+
+void
+Delivery::set_metering (bool yn)
+{
+ _metering = yn;
+
+ if (!_metering) {
+ /* XXX possible thread hazard here */
+ _io->peak_meter().reset();
+ }
+}
+void
+Delivery::set_self_mute (bool yn)
+{
+ if (yn != _muted_by_self) {
+ _muted_by_self = yn;
+ SelfMuteChange (); // emit signal
+ }
+}
+
+void
+Delivery::set_nonself_mute (bool yn)
+{
+ if (yn != _muted_by_others) {
+ _muted_by_others = yn;
+ OtherMuteChange (); // emit signal
+ }
+}
+
+XMLNode&
+Delivery::state (bool full_state)
+{
+ XMLNode& node (IOProcessor::state (full_state));
+
+ if (_role & Main) {
+ node.add_property("type", "main-outs");
+ } else if (_role & Listen) {
+ node.add_property("type", "listen");
+ } else {
+ node.add_property("type", "delivery");
+ }
+
+ node.add_property("metering", (_metering ? "yes" : "no"));
+ node.add_property("self-muted", (_muted_by_self ? "yes" : "no"));
+ node.add_property("other-muted", (_muted_by_others ? "yes" : "no"));
+ node.add_property("role", enum_2_string(_role));
+
+ return node;
+}
+
+int
+Delivery::set_state (const XMLNode& node)
+{
+ const XMLProperty* prop;
+
+ if ((prop = node.property ("role")) != 0) {
+ _role = Role (string_2_enum (prop->value(), _role));
+ }
+
+ if ((prop = node.property ("metering")) != 0) {
+ set_metering (prop->value() == "yes");
+ }
+
+ if ((prop = node.property ("self-muted")) != 0) {
+ set_self_mute (prop->value() == "yes");
+ }
+
+ if ((prop = node.property ("other-muted")) != 0) {
+ set_nonself_mute (prop->value() == "yes");
+ }
+
+ return 0;
+}
diff --git a/libs/ardour/enums.cc b/libs/ardour/enums.cc
index 841b2ad185..7767381499 100644
--- a/libs/ardour/enums.cc
+++ b/libs/ardour/enums.cc
@@ -20,6 +20,7 @@
#include "pbd/enumwriter.h"
#include "ardour/types.h"
+#include "ardour/delivery.h"
#include "ardour/session.h"
#include "ardour/location.h"
#include "ardour/audiofilesource.h"
@@ -103,6 +104,7 @@ setup_enum_writer ()
ExportFormatBase::SampleRate _ExportFormatBase_SampleRate;
ExportFormatBase::SRCQuality _ExportFormatBase_SRCQuality;
ExportProfileManager::TimeFormat _ExportProfileManager_TimeFormat;
+ Delivery::Role _Delivery_Role;
#define REGISTER(e) enum_writer->register_distinct (typeid(e).name(), i, s); i.clear(); s.clear()
#define REGISTER_BITS(e) enum_writer->register_bits (typeid(e).name(), i, s); i.clear(); s.clear()
@@ -499,4 +501,10 @@ setup_enum_writer ()
REGISTER_CLASS_ENUM (ExportProfileManager, Frames);
REGISTER_CLASS_ENUM (ExportProfileManager, Off);
REGISTER (_ExportProfileManager_TimeFormat);
+
+ REGISTER_CLASS_ENUM (Delivery, Solo);
+ REGISTER_CLASS_ENUM (Delivery, Send);
+ REGISTER_CLASS_ENUM (Delivery, Listen);
+ REGISTER_CLASS_ENUM (Delivery, Main);
+ REGISTER_BITS (_Delivery_Role);
}
diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc
index 88b8aceb3f..cdd80b747d 100644
--- a/libs/ardour/io.cc
+++ b/libs/ardour/io.cc
@@ -221,7 +221,7 @@ IO::silence (nframes_t nframes)
* to the outputs, eg applying gain or pan or whatever else needs to be done.
*/
void
-IO::deliver_output (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes)
+IO::deliver_output (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
{
// Attach output buffers to port buffers
output_buffers().attach_buffers (_outputs, nframes, _output_offset);
@@ -317,7 +317,7 @@ IO::collect_input (BufferSet& outs, nframes_t nframes, ChanCount offset)
}
void
-IO::just_meter_input (nframes_t start_frame, nframes_t end_frame, nframes_t nframes)
+IO::just_meter_input (sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
{
BufferSet& bufs = _session.get_scratch_buffers (n_inputs());
collect_input (bufs, nframes);
@@ -866,7 +866,6 @@ IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
{
bool in_changed = false;
bool out_changed = false;
- bool need_pan_reset = false;
assert(in != ChanCount::INFINITE);
assert(out != ChanCount::INFINITE);
@@ -887,10 +886,6 @@ IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
Port* port;
- if (n_outputs() != out) {
- need_pan_reset = true;
- }
-
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
const size_t nin = in.get(*t);
diff --git a/libs/ardour/io_processor.cc b/libs/ardour/io_processor.cc
index 53fbda24c7..2eac9dc88b 100644
--- a/libs/ardour/io_processor.cc
+++ b/libs/ardour/io_processor.cc
@@ -36,6 +36,7 @@
#include "ardour/port_insert.h"
#include "ardour/plugin_insert.h"
#include "ardour/io.h"
+#include "ardour/route.h"
#include "i18n.h"
@@ -43,24 +44,22 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
+/* create an IOProcessor that proxies to a new IO object */
+
IOProcessor::IOProcessor (Session& s, const string& proc_name, const string io_name, DataType dtype)
: Processor(s, proc_name)
- , _io (new IO(s, io_name != "" ? io_name : proc_name, dtype))
+ , _io (new IO(s, io_name.empty() ? proc_name : io_name, dtype))
{
- _active = false;
- _sort_key = 0;
- _gui = 0;
- _extra_xml = 0;
+ _own_io = true;
}
+/* create an IOProcessor that proxies to an existing IO object */
+
IOProcessor::IOProcessor (Session& s, IO* io, const string& proc_name, DataType dtype)
: Processor(s, proc_name)
, _io (io)
{
- _active = false;
- _sort_key = 0;
- _gui = 0;
- _extra_xml = 0;
+ _own_io = false;
}
IOProcessor::~IOProcessor ()
@@ -68,12 +67,27 @@ IOProcessor::~IOProcessor ()
notify_callbacks ();
}
+void
+IOProcessor::set_io (boost::shared_ptr<IO> io)
+{
+ /* CALLER MUST HOLD PROCESS LOCK */
+
+ _io = io;
+ _own_io = false;
+}
+
XMLNode&
IOProcessor::state (bool full_state)
{
- XMLNode& node = Processor::state(full_state);
+ XMLNode& node (Processor::state (full_state));
- node.add_child_nocopy (_io->state (full_state));
+ if (_own_io) {
+ node.add_child_nocopy (_io->state (full_state));
+ node.add_property ("own-io", "yes");
+ } else {
+ node.add_property ("own-io", "no");
+ node.add_property ("io", _io->name());
+ }
return node;
}
@@ -86,6 +100,35 @@ IOProcessor::set_state (const XMLNode& node)
Processor::set_state(node);
+ if ((prop = node.property ("own-io")) != 0) {
+ _own_io = prop->value() == "yes";
+ }
+
+ /* don't attempt to set state for a proxied IO that we don't own */
+
+ if (!_own_io) {
+
+ /* look up the IO object we're supposed to proxy to */
+
+ if ((prop = node.property ("io")) == 0) {
+ fatal << "IOProcessor has no named IO object" << endmsg;
+ /*NOTREACHED*/
+ }
+
+ boost::shared_ptr<Route> r = _session.route_by_name (prop->value());
+
+ if (!r) {
+ fatal << string_compose ("IOProcessor uses an unknown IO object called %1", prop->value()) << endmsg;
+ /*NOTREACHED*/
+ }
+
+ /* gotcha */
+
+ _io = boost::static_pointer_cast<IO> (r);
+
+ return 0;
+ }
+
XMLNodeList nlist = node.children();
XMLNodeIterator niter;
@@ -112,7 +155,7 @@ IOProcessor::set_state (const XMLNode& node)
// legacy sessions: use IO name
if ((prop = node.property ("name")) == 0) {
- set_name(_io->name());
+ set_name (_io->name());
}
} else {
@@ -126,7 +169,9 @@ IOProcessor::set_state (const XMLNode& node)
void
IOProcessor::silence (nframes_t nframes)
{
- _io->silence (nframes);
+ if (_own_io) {
+ _io->silence (nframes);
+ }
}
ChanCount
@@ -156,6 +201,19 @@ IOProcessor::natural_input_streams () const
void
IOProcessor::automation_snapshot (nframes_t now, bool force)
{
- _io->automation_snapshot(now, force);
+ if (_own_io) {
+ _io->automation_snapshot(now, force);
+ }
}
+bool
+IOProcessor::set_name (const std::string& name)
+{
+ bool ret = SessionObject::set_name (name);
+
+ if (ret && _own_io) {
+ ret = _io->set_name (name);
+ }
+
+ return ret;
+}
diff --git a/libs/ardour/meter.cc b/libs/ardour/meter.cc
index d8fee1ac47..371e0c5a90 100644
--- a/libs/ardour/meter.cc
+++ b/libs/ardour/meter.cc
@@ -38,7 +38,7 @@ namespace ARDOUR {
* be set to 0.
*/
void
-PeakMeter::run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes)
+PeakMeter::run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
{
const uint32_t n_audio = min(_configured_input.n_audio(), bufs.count().n_audio());
const uint32_t n_midi = min(_configured_input.n_midi(), bufs.count().n_midi());
@@ -171,15 +171,9 @@ PeakMeter::meter ()
XMLNode&
PeakMeter::state (bool full_state)
{
- return get_state();
-}
-
-XMLNode&
-PeakMeter::get_state()
-{
- XMLNode* node = new XMLNode(state_node_name);
- node->add_property("type", "meter");
- return *node;
+ XMLNode& node (Processor::state (full_state));
+ node.add_property("type", "meter");
+ return node;
}
} // namespace ARDOUR
diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc
index f8d9f1eb58..6eaf01c819 100644
--- a/libs/ardour/midi_diskstream.cc
+++ b/libs/ardour/midi_diskstream.cc
@@ -52,6 +52,8 @@
#include "ardour/smf_source.h"
#include "ardour/utils.h"
+#include "midi++/types.h"
+
#include "i18n.h"
#include <locale.h>
@@ -419,6 +421,173 @@ MidiDiskstream::check_record_status (nframes_t transport_frame, nframes_t nframe
last_possibly_recording = possibly_recording;
}
+static void
+trace_midi (ostream& o, MIDI::byte *msg, size_t len)
+{
+ using namespace MIDI;
+ eventType type;
+ const char trace_prefix = ':';
+
+ type = (eventType) (msg[0]&0xF0);
+
+ switch (type) {
+ case off:
+ o << trace_prefix
+ << "Channel "
+ << (msg[0]&0xF)+1
+ << " NoteOff NoteNum "
+ << (int) msg[1]
+ << " Vel "
+ << (int) msg[2]
+ << endl;
+ break;
+
+ case on:
+ o << trace_prefix
+ << "Channel "
+ << (msg[0]&0xF)+1
+ << " NoteOn NoteNum "
+ << (int) msg[1]
+ << " Vel "
+ << (int) msg[2]
+ << endl;
+ break;
+
+ case polypress:
+ o << trace_prefix
+ << "Channel "
+ << (msg[0]&0xF)+1
+ << " PolyPressure"
+ << (int) msg[1]
+ << endl;
+ break;
+
+ case MIDI::controller:
+ o << trace_prefix
+ << "Channel "
+ << (msg[0]&0xF)+1
+ << " Controller "
+ << (int) msg[1]
+ << " Value "
+ << (int) msg[2]
+ << endl;
+ break;
+
+ case program:
+ o << trace_prefix
+ << "Channel "
+ << (msg[0]&0xF)+1
+ << " Program Change ProgNum "
+ << (int) msg[1]
+ << endl;
+ break;
+
+ case chanpress:
+ o << trace_prefix
+ << "Channel "
+ << (msg[0]&0xF)+1
+ << " Channel Pressure "
+ << (int) msg[1]
+ << endl;
+ break;
+
+ case MIDI::pitchbend:
+ o << trace_prefix
+ << "Channel "
+ << (msg[0]&0xF)+1
+ << " Pitch Bend "
+ << ((msg[2]<<7)|msg[1])
+ << endl;
+ break;
+
+ case MIDI::sysex:
+ if (len == 1) {
+ switch (msg[0]) {
+ case 0xf8:
+ o << trace_prefix
+ << "Clock"
+ << endl;
+ break;
+ case 0xfa:
+ o << trace_prefix
+ << "Start"
+ << endl;
+ break;
+ case 0xfb:
+ o << trace_prefix
+ << "Continue"
+ << endl;
+ break;
+ case 0xfc:
+ o << trace_prefix
+ << "Stop"
+ << endl;
+ break;
+ case 0xfe:
+ o << trace_prefix
+ << "Active Sense"
+ << endl;
+ break;
+ case 0xff:
+ o << trace_prefix
+ << "System Reset"
+ << endl;
+ break;
+ default:
+ o << trace_prefix
+ << "System Exclusive (1 byte : " << hex << (int) *msg << dec << ')'
+ << endl;
+ break;
+ }
+ } else {
+ o << trace_prefix
+ << "System Exclusive (" << len << ") = [ " << hex;
+ for (unsigned int i = 0; i < len; ++i) {
+ o << (int) msg[i] << ' ';
+ }
+ o << dec << ']' << endl;
+
+ }
+ break;
+
+ case MIDI::song:
+ o << trace_prefix << "Song" << endl;
+ break;
+
+ case MIDI::tune:
+ o << trace_prefix << "Tune" << endl;
+ break;
+
+ case MIDI::eox:
+ o << trace_prefix << "End-of-System Exclusive" << endl;
+ break;
+
+ case MIDI::timing:
+ o << trace_prefix << "Timing" << endl;
+ break;
+
+ case MIDI::start:
+ o << trace_prefix << "Start" << endl;
+ break;
+
+ case MIDI::stop:
+ o << trace_prefix << "Stop" << endl;
+ break;
+
+ case MIDI::contineu:
+ o << trace_prefix << "Continue" << endl;
+ break;
+
+ case active:
+ o << trace_prefix << "Active Sense" << endl;
+ break;
+
+ default:
+ o << trace_prefix << "Unrecognized MIDI message" << endl;
+ break;
+ }
+}
+
int
MidiDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can_record, bool rec_monitors_input)
{
diff --git a/libs/ardour/midi_state_tracker.cc b/libs/ardour/midi_state_tracker.cc
index 2cb602db6f..66d356f9a6 100644
--- a/libs/ardour/midi_state_tracker.cc
+++ b/libs/ardour/midi_state_tracker.cc
@@ -31,6 +31,12 @@ MidiStateTracker::MidiStateTracker ()
}
void
+MidiStateTracker::reset ()
+{
+ _active_notes.reset ();
+}
+
+void
MidiStateTracker::track_note_onoffs (const Evoral::MIDIEvent<MidiBuffer::TimeType>& event)
{
if (event.is_note_on()) {
@@ -79,3 +85,16 @@ MidiStateTracker::resolve_notes (MidiBuffer &dst, nframes_t time)
}
}
+void
+MidiStateTracker::dump (ostream& o)
+{
+ o << "******\n";
+ for (int c = 0; c < 16; ++c) {
+ for (int x = 0; x < 128; ++x) {
+ if (_active_notes[c * 128 + x]) {
+ o << "Channel " << c+1 << " Note " << x << " is on\n";
+ }
+ }
+ }
+ o << "+++++\n";
+}
diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc
index 030e8ff905..6697e3b704 100644
--- a/libs/ardour/midi_track.cc
+++ b/libs/ardour/midi_track.cc
@@ -363,7 +363,7 @@ MidiTrack::set_state_part_two ()
}
int
-MidiTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, int declick,
+MidiTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame, int declick,
bool can_record, bool rec_monitors_input)
{
int dret;
@@ -450,7 +450,7 @@ MidiTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
}
void
-MidiTrack::write_controller_messages(MidiBuffer& output_buf, nframes_t start, nframes_t end, nframes_t nframes)
+MidiTrack::write_controller_messages(MidiBuffer& output_buf, sframes_t start, sframes_t end, nframes_t nframes)
{
// Append immediate events (UI controls)
@@ -460,7 +460,7 @@ MidiTrack::write_controller_messages(MidiBuffer& output_buf, nframes_t start, nf
}
int
-MidiTrack::export_stuff (BufferSet& bufs, nframes_t nframes, nframes_t end_frame)
+MidiTrack::export_stuff (BufferSet& bufs, nframes_t nframes, sframes_t end_frame)
{
return -1;
}
diff --git a/libs/ardour/panner.cc b/libs/ardour/panner.cc
index 83923a44d6..73326e12a4 100644
--- a/libs/ardour/panner.cc
+++ b/libs/ardour/panner.cc
@@ -1419,7 +1419,7 @@ Panner::distribute_no_automation (BufferSet& inbufs, BufferSet& outbufs, nframes
}
void
-Panner::run_out_of_place (BufferSet& inbufs, BufferSet& outbufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes)
+Panner::run_out_of_place (BufferSet& inbufs, BufferSet& outbufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
{
if (outbufs.count().n_audio() == 0) {
// Failing to deliver audio we were asked to deliver is a bug
diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc
index a4a0a62e98..a78addf481 100644
--- a/libs/ardour/playlist.cc
+++ b/libs/ardour/playlist.cc
@@ -342,6 +342,7 @@ Playlist::notify_region_removed (boost::shared_ptr<Region> r)
pending_length = false;
LengthChanged (); /* EMIT SIGNAL */
pending_modified = false;
+ RegionRemoved (boost::weak_ptr<Region> (r)); /* EMIT SIGNAL */
Modified (); /* EMIT SIGNAL */
}
}
@@ -360,7 +361,6 @@ Playlist::notify_region_moved (boost::shared_ptr<Region> r)
list< Evoral::RangeMove<nframes_t> > m;
m.push_back (move);
RangesMoved (m);
-
}
}
@@ -380,6 +380,7 @@ Playlist::notify_region_added (boost::shared_ptr<Region> r)
pending_length = false;
LengthChanged (); /* EMIT SIGNAL */
pending_modified = false;
+ RegionAdded (boost::weak_ptr<Region> (r)); /* EMIT SIGNAL */
Modified (); /* EMIT SIGNAL */
}
}
@@ -420,21 +421,26 @@ Playlist::flush_notifications ()
// pending_bounds.sort (cmp);
for (RegionList::iterator r = pending_bounds.begin(); r != pending_bounds.end(); ++r) {
+
if (Config->get_layer_model() == MoveAddHigher) {
timestamp_layer_op (*r);
}
+
pending_length = true;
dependent_checks_needed.insert (*r);
- n++;
- }
- for (s = pending_adds.begin(); s != pending_adds.end(); ++s) {
- dependent_checks_needed.insert (*s);
n++;
}
for (s = pending_removes.begin(); s != pending_removes.end(); ++s) {
remove_dependents (*s);
+ RegionRemoved (boost::weak_ptr<Region> (*s)); /* EMIT SIGNAL */
+ n++;
+ }
+
+ for (s = pending_adds.begin(); s != pending_adds.end(); ++s) {
+ RegionAdded (boost::weak_ptr<Region> (*s)); /* EMIT SIGNAL */
+ dependent_checks_needed.insert (*s);
n++;
}
@@ -449,8 +455,7 @@ Playlist::flush_notifications ()
relayer ();
}
pending_modified = false;
- Modified (); /* EMIT SIGNAL */
-
+ Modified (); /* EMIT SIGNAL */
}
for (s = dependent_checks_needed.begin(); s != dependent_checks_needed.end(); ++s) {
@@ -537,6 +542,7 @@ Playlist::add_region_internal (boost::shared_ptr<Region> region, nframes_t posit
}
RegionSortByPosition cmp;
+
nframes_t old_length = 0;
if (!holding_state()) {
@@ -567,7 +573,9 @@ Playlist::add_region_internal (boost::shared_ptr<Region> region, nframes_t posit
notify_region_added (region);
if (!holding_state ()) {
+
check_dependents (region, false);
+
if (old_length != _get_maximum_extent()) {
notify_length_changed ();
}
@@ -1345,15 +1353,14 @@ Playlist::clear (bool with_signals)
std::list<sigc::connection>::iterator i = region_state_changed_connections.begin ();
i != region_state_changed_connections.end ();
++i
- ) {
-
- i->disconnect ();
-
+ ) {
+ i->disconnect ();
}
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
pending_removes.insert (*i);
}
+
regions.clear ();
}
diff --git a/libs/ardour/plugin_insert.cc b/libs/ardour/plugin_insert.cc
index b6e3671ff2..6a6e9cf100 100644
--- a/libs/ardour/plugin_insert.cc
+++ b/libs/ardour/plugin_insert.cc
@@ -371,7 +371,7 @@ PluginInsert::silence (nframes_t nframes)
}
void
-PluginInsert::run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes)
+PluginInsert::run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
{
if (active()) {
diff --git a/libs/ardour/plugin_manager.cc b/libs/ardour/plugin_manager.cc
index 0b5b9276f1..c0c854180f 100644
--- a/libs/ardour/plugin_manager.cc
+++ b/libs/ardour/plugin_manager.cc
@@ -127,7 +127,6 @@ PluginManager::PluginManager ()
}
#ifdef HAVE_SLV2
- cerr << "LV2: Creating world" << endl;
_lv2_world = new LV2World();
#endif
diff --git a/libs/ardour/port_insert.cc b/libs/ardour/port_insert.cc
index 73a70861ea..9d0d65ccd5 100644
--- a/libs/ardour/port_insert.cc
+++ b/libs/ardour/port_insert.cc
@@ -72,7 +72,7 @@ PortInsert::init ()
}
void
-PortInsert::run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes)
+PortInsert::run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
{
if (_io->n_outputs().n_total() == 0) {
return;
diff --git a/libs/ardour/processor.cc b/libs/ardour/processor.cc
index b48b0aebb0..84fb43d68c 100644
--- a/libs/ardour/processor.cc
+++ b/libs/ardour/processor.cc
@@ -64,6 +64,7 @@ Processor::Processor(Session& session, const string& name)
, _active(false)
, _next_ab_is_active(false)
, _configured(false)
+ , _sort_key (0)
, _gui(0)
{
}
@@ -99,17 +100,16 @@ Processor::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];
+
+ // 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);
@@ -144,11 +144,16 @@ Processor::set_state (const XMLNode& node)
const XMLProperty *legacy_active = 0;
const XMLProperty *legacy_placement = 0;
- // may not exist for legacy sessions
+ // may not exist for legacy 3.0 sessions
if ((prop = node.property ("name")) != 0) {
set_name(prop->value());
}
+ // may not exist for legacy 3.0 sessions
+ if ((prop = node.property ("id")) != 0) {
+ _id = prop->value();
+ }
+
XMLNodeList nlist = node.children();
XMLNodeIterator niter;
diff --git a/libs/ardour/return.cc b/libs/ardour/return.cc
index fdc2b259e1..1f228d01ca 100644
--- a/libs/ardour/return.cc
+++ b/libs/ardour/return.cc
@@ -106,7 +106,7 @@ Return::set_state(const XMLNode& node)
}
void
-Return::run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes)
+Return::run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
{
if (active()) {
_io->collect_input (bufs, nframes, _configured_input);
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index 931ae9a996..db06368371 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -20,6 +20,7 @@
#include <cmath>
#include <fstream>
#include <cassert>
+#include <algorithm>
#include <sigc++/bind.h>
#include "pbd/xml++.h"
@@ -35,7 +36,6 @@
#include "ardour/buffer.h"
#include "ardour/buffer_set.h"
#include "ardour/configuration.h"
-#include "ardour/control_outputs.h"
#include "ardour/cycle_timer.h"
#include "ardour/dB.h"
#include "ardour/ladspa_plugin.h"
@@ -64,7 +64,7 @@ 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)
+ DataType default_type, ChanCount in, ChanCount out)
: IO (sess, name, default_type, in, ChanCount::INFINITE, out, ChanCount::INFINITE)
, _flags (flg)
, _solo_control (new ToggleControllable (X_("solo"), *this, ToggleControllable::SoloControl))
@@ -73,6 +73,7 @@ Route::Route (Session& sess, string name, Flag flg,
_configured_inputs = in;
_configured_outputs = out;
init ();
+
}
Route::Route (Session& sess, const XMLNode& node, DataType default_type)
@@ -123,11 +124,19 @@ Route::init ()
input_changed.connect (mem_fun (this, &Route::input_change_handler));
output_changed.connect (mem_fun (this, &Route::output_change_handler));
+
+ /* add standard processors: amp, meter, main outs */
+
+ /* 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, NULL);
- add_processor (_meter, NULL);
+ add_processor (_amp);
+ add_processor (_meter);
+
+ _main_outs.reset (new Delivery (_session, this, _name, Delivery::Main));
+ ProcessorList::iterator i = _processors.end();
+ add_processor (_main_outs, 0, &i);
}
Route::~Route ()
@@ -294,8 +303,8 @@ Route::set_gain (gain_t val, void *src)
*/
void
Route::process_output_buffers (BufferSet& bufs,
- nframes_t start_frame, nframes_t end_frame, nframes_t nframes,
- bool with_processors, int declick)
+ sframes_t start_frame, sframes_t end_frame, nframes_t nframes,
+ bool with_processors, int declick)
{
ProcessorList::iterator i;
bool mute_declick_applied = false;
@@ -345,9 +354,8 @@ Route::process_output_buffers (BufferSet& bufs,
|| Config->get_monitoring_model() == SoftwareMonitoring);
// mute at the amp if...
- _amp->apply_mute(
- !_soloed && (mute_gain != dmg) && !mute_declick_applied && _mute_affects_post_fader,
- mute_gain, dmg);
+ _amp->apply_mute (!_soloed && (mute_gain != dmg) && !mute_declick_applied && _mute_affects_post_fader,
+ mute_gain, dmg);
_amp->set_gain (_gain, dg);
@@ -356,17 +364,32 @@ Route::process_output_buffers (BufferSet& bufs,
SET UP CONTROL OUTPUTS
----------------------------------------------------------------------------------------- */
- boost::shared_ptr<ControlOutputs> co = _control_outs;
+ boost::shared_ptr<Delivery> co = _control_outs;
if (co) {
// deliver control outputs unless we're ...
- co->deliver (!(
- dsg == 0 || // muted by solo of another track
- (dmg == 0 && _mute_affects_control_outs) || // or muted by mute of this track
- !recording_without_monitoring )); // or rec-enabled w/o s/w monitoring
+ bool self_mute = ((dmg == 0 && _mute_affects_control_outs) || // or muted by mute of this track
+ !recording_without_monitoring); // or rec-enabled w/o s/w monitoring
+ bool other_mute = (dsg == 0); // muted by solo of another track
+
+ co->set_self_mute (self_mute);
+ co->set_nonself_mute (other_mute);
}
-
/* -------------------------------------------------------------------------------------------
+ SET UP MAIN OUTPUT STAGE
+ ----------------------------------------------------------------------------------------- */
+
+ bool solo_audible = dsg > 0;
+ bool mute_audible = dmg > 0 || !_mute_affects_main_outs;
+
+ bool silent_anyway = (_gain == 0 && !_amp->apply_gain_automation());
+ bool muted_by_other_solo = (!solo_audible && (Config->get_solo_model() != SoloBus));
+ bool muted_by_self = !mute_audible;
+
+ _main_outs->set_nonself_mute (recording_without_monitoring || muted_by_other_solo || silent_anyway);
+ _main_outs->set_self_mute (muted_by_self);
+
+ /* -------------------------------------------------------------------------------------------
GLOBAL DECLICK (for transport changes etc.)
----------------------------------------------------------------------------------------- */
@@ -413,33 +436,23 @@ Route::process_output_buffers (BufferSet& bufs,
}
}
-
/* -------------------------------------------------------------------------------------------
- PROCESSORS (including Amp (fader) and Meter)
+ and go ....
----------------------------------------------------------------------------------------- */
- if (with_processors) {
- Glib::RWLock::ReaderLock rm (_processor_lock, Glib::TRY_LOCK);
- if (rm.locked()) {
- //if (!bufs.is_silent()) {
- for (i = _processors.begin(); i != _processors.end(); ++i) {
- bufs.set_count(ChanCount::max(bufs.count(), (*i)->input_streams()));
- (*i)->run_in_place (bufs, start_frame, end_frame, nframes);
- bufs.set_count(ChanCount::max(bufs.count(), (*i)->output_streams()));
- }
- /*} else {
- for (i = _processors.begin(); i != _processors.end(); ++i) {
- (*i)->silence (nframes);
- bufs.set_count(ChanCount::max(bufs.count(), (*i)->output_streams()));
- }
- }*/
- }
+ Glib::RWLock::ReaderLock rm (_processor_lock, Glib::TRY_LOCK);
+
+ if (rm.locked()) {
+ for (i = _processors.begin(); i != _processors.end(); ++i) {
+ bufs.set_count(ChanCount::max(bufs.count(), (*i)->input_streams()));
+ (*i)->run_in_place (bufs, start_frame, end_frame, nframes);
+ bufs.set_count(ChanCount::max(bufs.count(), (*i)->output_streams()));
+ }
if (!_processors.empty()) {
bufs.set_count(ChanCount::max(bufs.count(), _processors.back()->output_streams()));
}
}
-
/* -------------------------------------------------------------------------------------------
POST-FADER MUTING
@@ -450,64 +463,11 @@ Route::process_output_buffers (BufferSet& bufs,
mute_gain = dmg;
mute_declick_applied = true;
}
+
if (mute_gain == 0.0f && dmg == 0.0f) {
bufs.is_silent(true);
}
-
- /* -------------------------------------------------------------------------------------------
- MAIN OUTPUT STAGE
- ----------------------------------------------------------------------------------------- */
-
- bool solo_audible = dsg > 0;
- bool mute_audible = dmg > 0 || !_mute_affects_main_outs;
-
- if (n_outputs().get(_default_type) == 0) {
-
- /* relax */
-
- } else if (recording_without_monitoring) {
-
- IO::silence (nframes);
-
- } else {
-
- if ( // we're silent anyway
- (_gain == 0 && !_amp->apply_gain_automation()) ||
-
- // or muted by solo of another track, but not using control outs for solo
- (!solo_audible && (Config->get_solo_model() != SoloBus)) ||
-
- // or muted by mute of this track
- !mute_audible
- ) {
-
- /* don't use Route::silence() here, because that causes
- all outputs (sends, port processors, etc. to be silent).
- */
- IO::silence (nframes);
-
- } else {
-
- deliver_output(bufs, start_frame, end_frame, nframes);
-
- }
-
- }
-
- /* -------------------------------------------------------------------------------------------
- POST-FADER METERING
- ----------------------------------------------------------------------------------------- */
-
- /* TODO: Processor-list-ification needs to go further for this to be cleanly possible...
- if (meter && (_meter_point == MeterPostFader)) {
- if ((_gain == 0 && !apply_gain_automation) || dmg == 0) {
- _meter->reset();
- } else {
- _meter->run_in_place(output_buffers(), start_frame, end_frame, nframes);
- }
- }*/
-
// at this point we've reached the desired mute gain regardless
mute_gain = dmg;
}
@@ -527,7 +487,7 @@ Route::setup_peak_meters()
}
void
-Route::passthru (nframes_t start_frame, nframes_t end_frame, nframes_t nframes, int declick)
+Route::passthru (sframes_t start_frame, sframes_t end_frame, nframes_t nframes, int declick)
{
BufferSet& bufs = _session.get_scratch_buffers(n_process_buffers());
@@ -539,7 +499,7 @@ Route::passthru (nframes_t start_frame, nframes_t end_frame, nframes_t nframes,
}
void
-Route::passthru_silence (nframes_t start_frame, nframes_t end_frame, nframes_t nframes, int declick)
+Route::passthru_silence (sframes_t start_frame, sframes_t end_frame, nframes_t nframes, int declick)
{
process_output_buffers (_session.get_silent_buffers (n_process_buffers()), start_frame, end_frame, nframes, true, declick);
}
@@ -643,13 +603,26 @@ dump_processors(const string& name, const list<boost::shared_ptr<Processor> >& p
cerr << "}" << endl;
}
+
+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
+{
+ return _amp->sort_key();
+}
+
/** 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, Placement placement)
+Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams* err, ProcessorList::iterator* iter)
{
ChanCount old_pms = processor_max_streams;
@@ -657,6 +630,10 @@ 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;
+
{
Glib::RWLock::WriterLock lm (_processor_lock);
@@ -665,8 +642,8 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams*
ProcessorList::iterator loc = find(_processors.begin(), _processors.end(), processor);
- if (processor == _amp || processor == _meter) {
- // Ensure only one amp and one meter are in the list at any time
+ 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
@@ -687,17 +664,21 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams*
}
}
- // Use position given by user
if (iter) {
+ // Use position given by user
loc = *iter;
-
- // Insert immediately before the amp
- } else if (placement == PreFader) {
- loc = find(_processors.begin(), _processors.end(), _amp);
-
- // Insert at end
} else {
- loc = _processors.end();
+ 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
@@ -715,11 +696,12 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams*
// Set up processor list channels. This will set processor->[input|output]_streams(),
// configure redirect ports properly, etc.
if (configure_processors_unlocked (err)) {
- dump_processors(_name, _processors);
+ dump_processors(_name + "bad config", _processors);
ProcessorList::iterator ploc = loc;
--ploc;
_processors.erase(ploc);
configure_processors_unlocked (0); // it worked before we tried to add it ...
+ cerr << "Bad IO config\n";
return -1;
}
@@ -733,8 +715,7 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams*
}
// Ensure peak vector sizes before the plugin is activated
- ChanCount potential_max_streams = ChanCount::max(
- processor->input_streams(), processor->output_streams());
+ ChanCount potential_max_streams = ChanCount::max (processor->input_streams(), processor->output_streams());
_meter->configure_io (potential_max_streams, potential_max_streams);
@@ -749,15 +730,14 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams*
reset_panner ();
}
- dump_processors (_name, _processors);
+ dump_processors (_name + " added one", _processors);
processors_changed (); /* EMIT SIGNAL */
-
return 0;
}
int
-Route::add_processors (const ProcessorList& others, ProcessorStreams* err, Placement placement)
+Route::add_processors (const ProcessorList& others, ProcessorStreams* err, uint32_t first_sort_key)
{
/* NOTE: this is intended to be used ONLY when copying
processors from another Route. Hence the subtle
@@ -773,10 +753,26 @@ Route::add_processors (const ProcessorList& others, ProcessorStreams* err, Place
{
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);
+ }
for (ProcessorList::const_iterator i = others.begin(); i != others.end(); ++i) {
@@ -800,11 +796,7 @@ Route::add_processors (const ProcessorList& others, ProcessorStreams* err, Place
// Ensure peak vector sizes before the plugin is activated
_meter->configure_io (potential_max_streams, potential_max_streams);
-
- ProcessorList::iterator loc = (placement == PreFader)
- ? find(_processors.begin(), _processors.end(), _amp)
- : _processors.end();
-
+
_processors.insert (loc, *i);
if (configure_processors_unlocked (err)) {
@@ -824,7 +816,7 @@ Route::add_processors (const ProcessorList& others, ProcessorStreams* err, Place
reset_panner ();
}
- dump_processors (_name, _processors);
+ dump_processors (_name + " added several", _processors);
processors_changed (); /* EMIT SIGNAL */
return 0;
@@ -1003,7 +995,8 @@ Route::clear_processors (Placement p)
{
Glib::RWLock::WriterLock lm (_processor_lock);
ProcessorList new_list;
-
+ ProcessorStreams err;
+
ProcessorList::iterator amp_loc = find(_processors.begin(), _processors.end(), _amp);
if (p == PreFader) {
// Get rid of PreFader processors
@@ -1027,9 +1020,9 @@ Route::clear_processors (Placement p)
}
_processors = new_list;
+ configure_processors_unlocked (&err); // this can't fail
}
- /* FIXME: can't see how this test can ever fire */
if (processor_max_streams != old_pms) {
reset_panner ();
}
@@ -1046,7 +1039,9 @@ Route::clear_processors (Placement p)
int
Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStreams* err)
{
- if (processor == _amp || processor == _meter) {
+ /* these can never be removed */
+
+ if (processor == _amp || processor == _meter || processor == _main_outs) {
return 0;
}
@@ -1063,18 +1058,13 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
ProcessorList::iterator i;
bool removed = false;
- for (i = _processors.begin(); i != _processors.end(); ++i) {
+ for (i = _processors.begin(); i != _processors.end(); ) {
if (*i == processor) {
- ProcessorList::iterator tmp;
-
/* move along, see failure case for configure_processors()
where we may need to reprocessor the processor.
*/
- tmp = i;
- ++tmp;
-
/* stop redirects that send signals to JACK ports
from causing noise as a result of no longer being
run.
@@ -1086,12 +1076,13 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
redirect->io()->disconnect_inputs (this);
redirect->io()->disconnect_outputs (this);
}
-
- _processors.erase (i);
-
- i = tmp;
+
+ i = _processors.erase (i);
removed = true;
break;
+
+ } else {
+ ++i;
}
_user_latency = 0;
@@ -1130,7 +1121,7 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
processor->drop_references ();
- dump_processors (_name, _processors);
+ dump_processors (_name + " removed one", _processors);
processors_changed (); /* EMIT SIGNAL */
return 0;
@@ -1252,17 +1243,11 @@ Route::all_processors_active (Placement p, bool state)
_session.set_dirty ();
}
-struct ProcessorSorter {
- bool operator() (boost::shared_ptr<const Processor> a, boost::shared_ptr<const Processor> b) {
- return a->sort_key() < b->sort_key();
- }
-};
-
int
Route::sort_processors (ProcessorStreams* err)
{
{
- ProcessorSorter comparator;
+ ProcessorSortByKey comparator;
Glib::RWLock::WriterLock lm (_processor_lock);
ChanCount old_pms = processor_max_streams;
@@ -1270,6 +1255,8 @@ Route::sort_processors (ProcessorStreams* err)
ProcessorList as_it_was_before = _processors;
+ dump_processors (_name + " PRESORT", _processors);
+
_processors.sort (comparator);
if (configure_processors_unlocked (err)) {
@@ -1279,6 +1266,7 @@ Route::sort_processors (ProcessorStreams* err)
}
}
+ dump_processors (_name + " sorted", _processors);
reset_panner ();
processors_changed (); /* EMIT SIGNAL */
@@ -1356,12 +1344,6 @@ Route::state(bool full_state)
remote_control_node->add_property (X_("id"), buf);
node->add_child_nocopy (*remote_control_node);
- if (_control_outs) {
- XMLNode* cnode = new XMLNode (X_("ControlOuts"));
- cnode->add_child_nocopy (_control_outs->io()->state (full_state));
- node->add_child_nocopy (*cnode);
- }
-
if (_comment.length()) {
XMLNode *cmt = node->add_child ("Comment");
cmt->add_content (_comment);
@@ -1517,7 +1499,17 @@ Route::add_processor_from_xml (const XMLNode& node, ProcessorList::iterator* ite
} 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;
@@ -1712,27 +1704,8 @@ Route::_set_state (const XMLNode& node, bool call_base)
}
} else if (child->name() == X_("ControlOuts")) {
-
- string coutname = _name;
- coutname += _("[control]");
- _control_outs = boost::shared_ptr<ControlOutputs> (
- new ControlOutputs (_session, new IO (_session, coutname)));
-
- /* fix up the control out name in the XML before setting it.
- Otherwise track templates don't work because the control
- outs end up with the stored template name, rather than
- the new name of the track based on the template.
- */
-
- XMLProperty* prop = (*child->children().begin())->property ("name");
- if (prop) {
- prop->set_value (coutname);
- }
-
- _control_outs->io()->set_state (**(child->children().begin()));
- _control_outs->set_sort_key (_meter->sort_key() + 1);
- add_processor (_control_outs, 0);
+ /* ignore this - deprecated */
} else if (child->name() == X_("Comment")) {
@@ -1779,7 +1752,6 @@ void
Route::_set_processor_states(const XMLNodeList &nlist)
{
XMLNodeConstIterator niter;
- char buf[64];
ProcessorList::iterator i, o;
@@ -1790,21 +1762,12 @@ Route::_set_processor_states(const XMLNodeList &nlist)
bool processorInStateList = false;
- (*i)->id().print (buf, sizeof (buf));
-
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
- // legacy sessions (IOProcessor as a child of Processor, both is-a IO)
- XMLNode* ioproc_node = (*niter)->child(X_("IOProcessor"));
- if (ioproc_node && strncmp(buf, ioproc_node->child(X_("IO"))->property(X_("id"))->value().c_str(), sizeof(buf)) == 0) {
+ XMLProperty* id_prop = (*niter)->property(X_("id"));
+ if (id_prop && (*i)->id() == id_prop->value()) {
processorInStateList = true;
break;
- } else {
- XMLProperty* id_prop = (*niter)->property(X_("id"));
- if (id_prop && strncmp(buf, id_prop->value().c_str(), sizeof(buf)) == 0) {
- processorInStateList = true;
- }
- break;
}
}
@@ -1815,56 +1778,53 @@ Route::_set_processor_states(const XMLNodeList &nlist)
i = tmp;
}
- Placement placement = PreFader;
-
// Iterate through state list and make sure all processors are on the track and in the correct order,
// set the state of existing processors according to the new state on the same go
i = _processors.begin();
- for (niter = nlist.begin(); niter != nlist.end(); ++niter, ++i) {
- // Check whether the next processor in the list
+ for (niter = nlist.begin(); niter != nlist.end(); ++niter, ++i) {
+
+ XMLProperty* prop = (*niter)->property ("type");
+
o = i;
- while (o != _processors.end()) {
- (*o)->id().print (buf, sizeof (buf));
- XMLNode* ioproc_node = (*niter)->child(X_("IOProcessor"));
- if (ioproc_node && strncmp(buf, ioproc_node->child(X_("IO"))->property(X_("id"))->value().c_str(), sizeof(buf)) == 0) {
- break;
- } else {
+ if (prop->value() != "meter" && prop->value() != "amp" && prop->value() != "main-outs") {
+
+ // Check whether the next processor in the list
+
+ while (o != _processors.end()) {
XMLProperty* id_prop = (*niter)->property(X_("id"));
- if (id_prop && strncmp(buf, id_prop->value().c_str(), sizeof(buf)) == 0) {
+ if (id_prop && (*o)->id() == id_prop->value()) {
break;
}
+
+ ++o;
}
-
- ++o;
}
// If the processor (*niter) is not on the route,
// create it and move it to the correct location
if (o == _processors.end()) {
+
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;
}
- // Otherwise, we found the processor (*niter) on the route,
+ // Otherwise, the processor already exists; just
// ensure it is at the location provided in the XML state
} else {
if (i != o) {
boost::shared_ptr<Processor> tmp = (*o);
- _processors.erase(o); // remove the old copy
- _processors.insert(i, tmp); // insert the processor at the correct location
+ 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
}
- (*i)->set_state((**niter));
- }
-
- if (*i == _amp) {
- placement = PostFader;
+ (*i)->set_state (**niter);
}
}
}
@@ -1882,22 +1842,19 @@ Route::silence (nframes_t nframes)
if (!_silent) {
IO::silence (nframes);
-
- if (_control_outs) {
- _control_outs->io()->silence (nframes);
- }
-
+
{
Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
if (lm.locked()) {
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
boost::shared_ptr<PluginInsert> pi;
+
if (!_active && (pi = boost::dynamic_pointer_cast<PluginInsert> (*i)) != 0) {
// skip plugins, they don't need anything when we're not active
continue;
}
-
+
(*i)->silence (nframes);
}
@@ -1910,53 +1867,110 @@ Route::silence (nframes_t nframes)
}
}
-int
-Route::set_control_outs (const vector<string>& ports)
+boost::shared_ptr<Delivery>
+Route::add_listener (boost::shared_ptr<IO> io, const string& listen_name)
{
- vector<string>::const_iterator i;
-
- if (is_control() || is_master()) {
- /* no control outs for these two special busses */
- return 0;
- }
+ string name = _name;
+ name += '[';
+ name += listen_name;
+ name += ']';
- if (ports.empty()) {
- return 0;
- }
-
- string coutname = _name;
- coutname += _("[control]");
-
- IO* out_io = new IO (_session, coutname);
- boost::shared_ptr<ControlOutputs> out_proc(new ControlOutputs (_session, out_io));
+ boost::shared_ptr<Delivery> listener (new Delivery (_session, name, Delivery::Listen));
/* As an IO, our control outs need as many IO outputs as we have outputs
* (we track the changes in ::output_change_handler()).
- * As a processor, the control outs is an identity processor
+ * As a processor, the listener is an identity processor
* (i.e. it does not modify its input buffers whatsoever)
*/
- if (out_io->ensure_io (ChanCount::ZERO, n_outputs(), true, this)) {
- return -1;
+
+ if (listener->io()->ensure_io (ChanCount::ZERO, n_outputs(), true, this)) {
+ return boost::shared_ptr<Delivery>();
}
+
+ listener->set_sort_key (_meter->sort_key() + 1);
+ add_processor (listener, NULL);
+
+ return listener;
+}
+
+int
+Route::listen_via (boost::shared_ptr<IO> io, const string& listen_name)
+{
+ vector<string> ports;
+ vector<string>::const_iterator i;
+
+ {
+ Glib::RWLock::ReaderLock rm (_processor_lock);
+
+ for (ProcessorList::const_iterator x = _processors.begin(); x != _processors.end(); ++x) {
+ boost::shared_ptr<const Delivery> d = boost::dynamic_pointer_cast<const Delivery>(*x);
+
+ if (d && d->io() == io) {
+ /* already listening via the specified IO: do nothing */
+ return 0;
+ }
+ }
+ }
+
+ uint32_t ni = io->n_inputs().n_total();
+
+ for (uint32_t n = 0; n < ni; ++n) {
+ ports.push_back (io->input(n)->name());
+ }
+
+ if (ports.empty()) {
+ return 0;
+ }
+
+ boost::shared_ptr<Delivery> listen_point = add_listener (io, listen_name);
+
+ /* XXX hack for now .... until we can generalize listen points */
+
+ _control_outs = listen_point;
/* now connect to the named ports */
- for (size_t n = 0; n < n_outputs().n_total(); ++n) {
- if (out_io->connect_output (out_io->output (n), ports[n % ports.size()], this)) {
+ ni = listen_point->io()->n_outputs().n_total();
+ size_t psize = ports.size();
+
+ for (size_t n = 0; n < ni; ++n) {
+ if (listen_point->io()->connect_output (listen_point->io()->output (n), ports[n % psize], this)) {
error << string_compose (_("could not connect %1 to %2"),
- out_io->output(n)->name(), ports[n]) << endmsg;
+ listen_point->io()->output(n)->name(), ports[n % psize]) << endmsg;
return -1;
}
}
- _control_outs = out_proc;
- _control_outs->set_sort_key (_meter->sort_key() + 1);
- add_processor (_control_outs, NULL);
-
+
return 0;
}
void
+Route::drop_listen (boost::shared_ptr<IO> io)
+{
+ ProcessorStreams err;
+ ProcessorList::iterator tmp;
+
+ Glib::RWLock::ReaderLock rm (_processor_lock);
+
+ for (ProcessorList::iterator x = _processors.begin(); x != _processors.end(); ) {
+
+ tmp = x;
+ ++tmp;
+
+ boost::shared_ptr<Delivery> d = boost::dynamic_pointer_cast<Delivery>(*x);
+
+ if (d && d->io() == io) {
+ /* already listening via the specified IO: do nothing */
+ remove_processor (*x, &err);
+
+ }
+
+ x = tmp;
+ }
+}
+
+void
Route::set_edit_group (RouteGroup *eg, void *src)
{
@@ -2041,33 +2055,17 @@ Route::feeds (boost::shared_ptr<Route> other)
for (ProcessorList::iterator r = _processors.begin(); r != _processors.end(); r++) {
- boost::shared_ptr<IOProcessor> redirect = boost::dynamic_pointer_cast<IOProcessor>(*r);
-
- if ( ! redirect)
+ boost::shared_ptr<IOProcessor> proc = boost::dynamic_pointer_cast<IOProcessor>(*r);
+
+ if (!proc) {
continue;
-
- // TODO: support internal redirects here
-
- no = redirect->io()->n_outputs().n_total();
-
- for (i = 0; i < no; ++i) {
- for (j = 0; j < ni; ++j) {
- if (redirect->io()->output(i)->connected_to (other->input (j)->name())) {
- return true;
- }
- }
}
- }
-
- /* check for control room outputs which may also interconnect Routes */
-
- if (_control_outs) {
-
- no = _control_outs->io()->n_outputs().n_total();
+
+ no = proc->io()->n_outputs().n_total();
for (i = 0; i < no; ++i) {
for (j = 0; j < ni; ++j) {
- if (_control_outs->io()->output(i)->connected_to (other->input (j)->name())) {
+ if (proc->io()->output(i)->connected_to (other->input (j)->name())) {
return true;
}
}
@@ -2185,7 +2183,7 @@ Route::pans_required () const
}
int
-Route::no_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
+Route::no_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
bool session_state_changing, bool can_record, bool rec_monitors_input)
{
if (n_outputs().n_total() == 0) {
@@ -2236,7 +2234,7 @@ Route::check_initial_delay (nframes_t nframes, nframes_t& transport_frame)
}
int
-Route::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, int declick,
+Route::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame, int declick,
bool can_record, bool rec_monitors_input)
{
{
@@ -2282,7 +2280,7 @@ Route::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, int
}
int
-Route::silent_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
+Route::silent_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
bool can_record, bool rec_monitors_input)
{
silence (nframes);
@@ -2602,3 +2600,36 @@ Route::save_as_template (const string& path, const string& name)
tree.set_root (&node);
return tree.write (path.c_str());
}
+
+
+bool
+Route::set_name (const string& str)
+{
+ bool ret;
+ string ioproc_name;
+
+ if ((ret = IO::set_name (str)) == true) {
+ Glib::RWLock::ReaderLock lm (_processor_lock);
+
+ for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
+
+ /* rename all delivery objects to reflect our new name */
+
+ boost::shared_ptr<Delivery> dp = boost::dynamic_pointer_cast<Delivery> (*i);
+
+ if (dp) {
+ string dp_name = str;
+ dp_name += '[';
+ dp_name += "XXX FIX ME XXX";
+ dp_name += ']';
+
+ if (!dp->set_name (dp_name)) {
+ ret = false;
+ }
+ }
+ }
+
+ }
+
+ return ret;
+}
diff --git a/libs/ardour/send.cc b/libs/ardour/send.cc
index 2c28fb5dcd..e4de26e864 100644
--- a/libs/ardour/send.cc
+++ b/libs/ardour/send.cc
@@ -36,17 +36,14 @@ using namespace ARDOUR;
using namespace PBD;
Send::Send (Session& s)
- : IOProcessor (s, string_compose (_("send %1"), (_bitslot = s.next_send_id()) + 1))
+ : Delivery (s, string_compose (_("send %1"), (_bitslot = s.next_send_id()) + 1), Delivery::Send)
{
- _metering = false;
ProcessorCreated (this); /* EMIT SIGNAL */
}
Send::Send (Session& s, const XMLNode& node)
- : IOProcessor (s, "send")
+ : Delivery (s, "send", Delivery::Send)
{
- _metering = false;
-
if (set_state (node)) {
throw failed_constructor();
}
@@ -96,7 +93,7 @@ Send::set_state(const XMLNode& node)
/* Send has regular IO automation (gain, pan) */
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
- if ((*niter)->name() == "IOProcessor") {
+ if ((*niter)->name() == IOProcessor::state_node_name) {
insert_node = *niter;
} else if ((*niter)->name() == X_("Automation")) {
// _io->set_automation_state (*(*niter), Evoral::Parameter(GainAutomation));
@@ -108,41 +105,6 @@ Send::set_state(const XMLNode& node)
return 0;
}
-void
-Send::run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes)
-{
- if (active()) {
-
- _io->deliver_output (bufs, start_frame, end_frame, nframes);
-
- if (_metering) {
- if (_io->effective_gain() == 0) {
- _io->peak_meter().reset();
- } else {
- _io->peak_meter().run_in_place(_io->output_buffers(), start_frame, end_frame, nframes);
- }
- }
-
- } else {
- _io->silence (nframes);
-
- if (_metering) {
- _io->peak_meter().reset();
- }
- }
-}
-
-void
-Send::set_metering (bool yn)
-{
- _metering = yn;
-
- if (!_metering) {
- /* XXX possible thread hazard here */
- _io->peak_meter().reset();
- }
-}
-
bool
Send::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
{
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index 302bf87f64..3105b776dc 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -136,7 +136,6 @@ Session::Session (AudioEngine &eng,
midi_requests (128), // the size of this should match the midi request pool size
diskstreams (new DiskstreamList),
routes (new RouteList),
- auditioner ((Auditioner*) 0),
_total_free_4k_blocks (0),
_bundles (new BundleList),
_bundle_xml_node (0),
@@ -223,7 +222,6 @@ Session::Session (AudioEngine &eng,
midi_requests (16),
diskstreams (new DiskstreamList),
routes (new RouteList),
- auditioner ((Auditioner *) 0),
_total_free_4k_blocks (0),
_bundles (new BundleList),
_bundle_xml_node (0),
@@ -281,6 +279,7 @@ 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));
r->set_remote_control_id (control_id);
@@ -526,8 +525,6 @@ Session::when_engine_running ()
{
string first_physical_output;
- /* we don't want to run execute this again */
-
BootMessage (_("Set block size and sample rate"));
set_block_size (_engine.frames_per_cycle());
@@ -609,7 +606,8 @@ Session::when_engine_running ()
mono and stereo bundles, so that the common cases of mono
and stereo tracks get bundles to put in their mixer strip
in / out menus. There may be a nicer way of achieving that;
- it doesn't really scale that well to higher channel counts */
+ it doesn't really scale that well to higher channel counts
+ */
for (uint32_t np = 0; np < n_physical_outputs; ++np) {
char buf[32];
@@ -662,28 +660,37 @@ Session::when_engine_running ()
}
}
+ /* create master/control ports */
+
if (_master_out) {
- /* create master/control ports */
-
- if (_master_out) {
- /* force the master to ignore any later call to this */
- if (_master_out->pending_state_node) {
- _master_out->ports_became_legal();
- }
-
- /* no panner resets till we are through */
- _master_out->defer_pan_reset ();
+ /* force the master to ignore any later call to this
+ */
+ if (_master_out->pending_state_node) {
+ _master_out->ports_became_legal();
+ }
+
+ /* create ports, without any connections
+ */
+ _master_out->ensure_io (_master_out->input_minimum (), _master_out->output_minimum (), true, this);
- /* create ports */
- _master_out->set_input_minimum(ChanCount(DataType::AUDIO, n_physical_inputs));
- _master_out->set_output_minimum(ChanCount(DataType::AUDIO, n_physical_outputs));
- _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();
- _master_out->allow_pan_reset ();
+ for (uint32_t n = 0; n < limit; ++n) {
+ Port* p = _master_out->output (n);
+ string connect_to = _engine.get_nth_physical_output (DataType (p->type()), n);
+ if (!connect_to.empty()) {
+ if (_master_out->connect_output (p, connect_to, this)) {
+ error << string_compose (_("cannot connect master output %1 to %2"), n, connect_to)
+ << endmsg;
+ break;
+ }
+ }
+ }
}
}
@@ -739,7 +746,7 @@ Session::hookup_io ()
_state_of_the_state = StateOfTheState (_state_of_the_state | InitialConnecting);
- if (auditioner == 0) {
+ if (!auditioner) {
/* we delay creating the auditioner till now because
it makes its own connections to ports.
@@ -759,23 +766,21 @@ Session::hookup_io ()
IO::enable_ports ();
- if (_control_out) {
- vector<string> cports;
-
- _control_out->ensure_io(
- _control_out->input_minimum(), _control_out->output_minimum(),
- false, this);
+ /* Connect track to listen/solo etc. busses XXX generalize this beyond control_out */
- uint32_t ni = _control_out->n_inputs().get (DataType::AUDIO);
+ if (_control_out) {
- for (uint32_t n = 0; n < ni; ++n) {
- cports.push_back (_control_out->input(n)->name());
- }
+ _control_out->ensure_io (_control_out->input_minimum(), _control_out->output_minimum(), false, this);
boost::shared_ptr<RouteList> r = routes.reader ();
-
+
for (RouteList::iterator x = r->begin(); x != r->end(); ++x) {
- (*x)->set_control_outs (cports);
+
+ boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> (*x);
+
+ if (t) {
+ t->listen_via (_control_out, X_("listen"));
+ }
}
}
@@ -2081,15 +2086,8 @@ Session::add_routes (RouteList& new_routes, bool save)
if (_control_out && IO::connecting_legal) {
- vector<string> cports;
- uint32_t ni = _control_out->n_inputs().n_audio();
-
- for (uint32_t n = 0; n < ni; ++n) {
- cports.push_back (_control_out->input(n)->name());
- }
-
for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x) {
- (*x)->set_control_outs (cports);
+ (*x)->listen_via (_control_out, "control");
}
}
@@ -2146,15 +2144,13 @@ Session::remove_route (shared_ptr<Route> route)
}
if (route == _control_out) {
- _control_out = shared_ptr<Route> ();
-
/* cancel control outs for all routes */
- vector<string> empty;
-
for (RouteList::iterator r = rs->begin(); r != rs->end(); ++r) {
- (*r)->set_control_outs (empty);
+ (*r)->drop_listen (_control_out);
}
+
+ _control_out = shared_ptr<Route> ();
}
update_route_solo_state ();
diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc
index 55c09f7ed8..790d990bc2 100644
--- a/libs/ardour/session_transport.cc
+++ b/libs/ardour/session_transport.cc
@@ -805,6 +805,10 @@ Session::set_transport_speed (double speed, bool abort)
}
target_phi = (uint64_t) (0x1000000 * fabs(speed));
+
+ /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
+ and user needs. We really need CD-style "skip" playback for ffwd and rewind.
+ */
if (speed > 0) {
speed = min (8.0, speed);
diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc
index 1e344403b1..fd9267ede4 100644
--- a/libs/ardour/track.cc
+++ b/libs/ardour/track.cc
@@ -214,8 +214,8 @@ Track::set_name (const string& str)
}
/* save state so that the statefile fully reflects any filename changes */
-
- if ((ret = IO::set_name (str)) == 0) {
+
+ if ((ret = Route::set_name (str)) == 0) {
_session.save_state ("");
}
@@ -238,8 +238,8 @@ Track::zero_diskstream_id_in_xml (XMLNode& node)
}
int
-Track::no_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
- bool session_state_changing, bool can_record, bool rec_monitors_input)
+Track::no_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
+ bool session_state_changing, bool can_record, bool rec_monitors_input)
{
if (n_outputs().n_total() == 0) {
return 0;
@@ -324,8 +324,8 @@ Track::no_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
}
int
-Track::silent_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
- bool can_record, bool rec_monitors_input)
+Track::silent_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
+ bool can_record, bool rec_monitors_input)
{
if (n_outputs().n_total() == 0 && _processors.empty()) {
return 0;
diff --git a/libs/ardour/wscript b/libs/ardour/wscript
index fc0e8107f9..85187680d8 100644
--- a/libs/ardour/wscript
+++ b/libs/ardour/wscript
@@ -99,12 +99,12 @@ def build(bld):
chan_count.cc
chan_mapping.cc
configuration.cc
- control_outputs.cc
control_protocol_manager.cc
control_protocol_search_path.cc
crossfade.cc
cycle_timer.cc
default_click.cc
+ delivery.cc
directory_names.cc
diskstream.cc
element_import_handler.cc
diff --git a/libs/pbd/id.cc b/libs/pbd/id.cc
index d24d22a0f9..ab9c7e7392 100644
--- a/libs/pbd/id.cc
+++ b/libs/pbd/id.cc
@@ -71,6 +71,12 @@ string ID::to_s() const
return string(buf);
}
+bool
+ID::operator== (const string& str) const
+{
+ return to_s() == str;
+}
+
ID&
ID::operator= (string str)
{
diff --git a/libs/pbd/pbd/id.h b/libs/pbd/pbd/id.h
index 3f87a65e0d..d25ca81ef0 100644
--- a/libs/pbd/pbd/id.h
+++ b/libs/pbd/pbd/id.h
@@ -40,6 +40,8 @@ class ID {
return _id != other._id;
}
+ bool operator== (const std::string&) const;
+
ID& operator= (std::string);
bool operator< (const ID& other) const {