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
This commit is contained in:
parent
7188ec3990
commit
0569107ddc
|
@ -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"
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -168,10 +168,20 @@ StreamView::set_samples_per_unit (gdouble spp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -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>);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
|
@ -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);
|
||||
ControlOutputs(Session& s);
|
||||
XMLNode& get_state ();
|
||||
|
||||
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();
|
||||
|
||||
private:
|
||||
bool _deliver;
|
||||
static const std::string processor_type_name;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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__
|
||||
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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 () {}
|
||||
|
|
|
@ -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 ();
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -30,6 +30,12 @@ MidiStateTracker::MidiStateTracker ()
|
|||
_active_notes.reset();
|
||||
}
|
||||
|
||||
void
|
||||
MidiStateTracker::reset ()
|
||||
{
|
||||
_active_notes.reset ();
|
||||
}
|
||||
|
||||
void
|
||||
MidiStateTracker::track_note_onoffs (const Evoral::MIDIEvent<MidiBuffer::TimeType>& event)
|
||||
{
|
||||
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
||||
|
|
|
@ -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()) {
|
||||
|
||||
|
|
|
@ -127,7 +127,6 @@ PluginManager::PluginManager ()
|
|||
}
|
||||
|
||||
#ifdef HAVE_SLV2
|
||||
cerr << "LV2: Creating world" << endl;
|
||||
_lv2_world = new LV2World();
|
||||
#endif
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,16 +364,31 @@ 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,52 +1867,109 @@ 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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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 */
|
||||
/* 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);
|
||||
|
||||
if (_master_out) {
|
||||
/* force the master to ignore any later call to this */
|
||||
if (_master_out->pending_state_node) {
|
||||
_master_out->ports_became_legal();
|
||||
/* 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();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* no panner resets till we are through */
|
||||
_master_out->defer_pan_reset ();
|
||||
|
||||
/* 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);
|
||||
|
||||
_master_out->allow_pan_reset ();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 ();
|
||||
|
||||
/* Connect track to listen/solo etc. busses XXX generalize this beyond control_out */
|
||||
|
||||
if (_control_out) {
|
||||
vector<string> cports;
|
||||
|
||||
_control_out->ensure_io(
|
||||
_control_out->input_minimum(), _control_out->output_minimum(),
|
||||
false, this);
|
||||
|
||||
uint32_t ni = _control_out->n_inputs().get (DataType::AUDIO);
|
||||
|
||||
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 ();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue