mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-06 14:54:56 +01:00
first pass at internal sends. this is a very tentative work in progress, and it is possible that major changes may follow in the near future. it is certainly not complete, but the fundamental changes to Port/Buffer operation merit a commit at this point
git-svn-id: svn://localhost/ardour2/branches/3.0@4464 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
ee62ee07d3
commit
70b939da4f
48 changed files with 679 additions and 404 deletions
|
|
@ -1273,7 +1273,7 @@ void
|
||||||
ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
|
ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
|
||||||
{
|
{
|
||||||
list<boost::shared_ptr<AudioTrack> > tracks;
|
list<boost::shared_ptr<AudioTrack> > tracks;
|
||||||
Session::RouteList routes;
|
RouteList routes;
|
||||||
|
|
||||||
if (session == 0) {
|
if (session == 0) {
|
||||||
warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
|
warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
|
||||||
|
|
|
||||||
|
|
@ -595,7 +595,7 @@ class Editor : public PublicEditor
|
||||||
|
|
||||||
void add_item_with_sensitivity (Gtk::Menu_Helpers::MenuList&, Gtk::Menu_Helpers::MenuElem, bool) const;
|
void add_item_with_sensitivity (Gtk::Menu_Helpers::MenuList&, Gtk::Menu_Helpers::MenuElem, bool) const;
|
||||||
|
|
||||||
void handle_new_route (ARDOUR::Session::RouteList&);
|
void handle_new_route (ARDOUR::RouteList&);
|
||||||
void remove_route (TimeAxisView *);
|
void remove_route (TimeAxisView *);
|
||||||
bool route_removal;
|
bool route_removal;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ using namespace Glib;
|
||||||
const char* _order_key = N_("editor");
|
const char* _order_key = N_("editor");
|
||||||
|
|
||||||
void
|
void
|
||||||
Editor::handle_new_route (Session::RouteList& routes)
|
Editor::handle_new_route (RouteList& routes)
|
||||||
{
|
{
|
||||||
ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::handle_new_route), routes));
|
ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::handle_new_route), routes));
|
||||||
|
|
||||||
|
|
@ -60,7 +60,7 @@ Editor::handle_new_route (Session::RouteList& routes)
|
||||||
route_redisplay_does_not_sync_order_keys = true;
|
route_redisplay_does_not_sync_order_keys = true;
|
||||||
no_route_list_redisplay = true;
|
no_route_list_redisplay = true;
|
||||||
|
|
||||||
for (Session::RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
|
for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
|
||||||
boost::shared_ptr<Route> route = (*x);
|
boost::shared_ptr<Route> route = (*x);
|
||||||
|
|
||||||
if (route->is_hidden()) {
|
if (route->is_hidden()) {
|
||||||
|
|
@ -592,8 +592,8 @@ struct EditorOrderRouteSorter {
|
||||||
void
|
void
|
||||||
Editor::initial_route_list_display ()
|
Editor::initial_route_list_display ()
|
||||||
{
|
{
|
||||||
boost::shared_ptr<Session::RouteList> routes = session->get_routes();
|
boost::shared_ptr<RouteList> routes = session->get_routes();
|
||||||
Session::RouteList r (*routes);
|
RouteList r (*routes);
|
||||||
EditorOrderRouteSorter sorter;
|
EditorOrderRouteSorter sorter;
|
||||||
|
|
||||||
r.sort (sorter);
|
r.sort (sorter);
|
||||||
|
|
|
||||||
|
|
@ -105,14 +105,14 @@ void
|
||||||
PortExportChannelSelector::fill_route_list ()
|
PortExportChannelSelector::fill_route_list ()
|
||||||
{
|
{
|
||||||
channel_view.clear_routes ();
|
channel_view.clear_routes ();
|
||||||
Session::RouteList routes = *session->get_routes();
|
RouteList routes = *session->get_routes();
|
||||||
|
|
||||||
/* Add master bus and then everything else */
|
/* Add master bus and then everything else */
|
||||||
|
|
||||||
ARDOUR::IO * master = session->master_out().get();
|
ARDOUR::IO * master = session->master_out().get();
|
||||||
channel_view.add_route (master);
|
channel_view.add_route (master);
|
||||||
|
|
||||||
for (Session::RouteList::iterator it = routes.begin(); it != routes.end(); ++it) {
|
for (RouteList::iterator it = routes.begin(); it != routes.end(); ++it) {
|
||||||
if (it->get() == master) {
|
if (it->get() == master) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@
|
||||||
#include <gtkmm2ext/gtk_ui.h>
|
#include <gtkmm2ext/gtk_ui.h>
|
||||||
#include <midi++/manager.h>
|
#include <midi++/manager.h>
|
||||||
#include <pbd/fastlog.h>
|
#include <pbd/fastlog.h>
|
||||||
|
#include <pbd/stacktrace.h>
|
||||||
|
|
||||||
#include "ardour_ui.h"
|
#include "ardour_ui.h"
|
||||||
#include "gain_meter.h"
|
#include "gain_meter.h"
|
||||||
|
|
@ -160,6 +161,8 @@ GainMeterBase::~GainMeterBase ()
|
||||||
void
|
void
|
||||||
GainMeterBase::set_io (boost::shared_ptr<IO> io)
|
GainMeterBase::set_io (boost::shared_ptr<IO> io)
|
||||||
{
|
{
|
||||||
|
cerr << this << " Clear all connections\n";
|
||||||
|
|
||||||
connections.clear ();
|
connections.clear ();
|
||||||
|
|
||||||
_io = io;
|
_io = io;
|
||||||
|
|
@ -200,6 +203,8 @@ GainMeterBase::set_io (boost::shared_ptr<IO> io)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cerr << "Connect " << this << " to gain change for " << _io->name() << endl;
|
||||||
|
|
||||||
connections.push_back (_io->gain_control()->Changed.connect (mem_fun(*this, &GainMeterBase::gain_changed)));
|
connections.push_back (_io->gain_control()->Changed.connect (mem_fun(*this, &GainMeterBase::gain_changed)));
|
||||||
|
|
||||||
gain_changed ();
|
gain_changed ();
|
||||||
|
|
@ -371,8 +376,11 @@ GainMeterBase::show_gain ()
|
||||||
void
|
void
|
||||||
GainMeterBase::gain_adjusted ()
|
GainMeterBase::gain_adjusted ()
|
||||||
{
|
{
|
||||||
|
cerr << this << " for " << _io->name() << " GAIN ADJUSTED\n";
|
||||||
if (!ignore_toggle) {
|
if (!ignore_toggle) {
|
||||||
|
cerr << "Set GC\n";
|
||||||
_io->gain_control()->set_value (slider_position_to_gain (gain_adjustment.get_value()));
|
_io->gain_control()->set_value (slider_position_to_gain (gain_adjustment.get_value()));
|
||||||
|
cerr << "Set GC OUT\n";
|
||||||
}
|
}
|
||||||
show_gain ();
|
show_gain ();
|
||||||
}
|
}
|
||||||
|
|
@ -382,6 +390,9 @@ GainMeterBase::effective_gain_display ()
|
||||||
{
|
{
|
||||||
gfloat value = gain_to_slider_position (_io->effective_gain());
|
gfloat value = gain_to_slider_position (_io->effective_gain());
|
||||||
|
|
||||||
|
cerr << this << " for " << _io->name() << " EGAIN = " << value << " AGAIN = " << gain_adjustment.get_value () << endl;
|
||||||
|
// stacktrace (cerr, 20);
|
||||||
|
|
||||||
if (gain_adjustment.get_value() != value) {
|
if (gain_adjustment.get_value() != value) {
|
||||||
ignore_toggle = true;
|
ignore_toggle = true;
|
||||||
gain_adjustment.set_value (value);
|
gain_adjustment.set_value (value);
|
||||||
|
|
|
||||||
|
|
@ -297,7 +297,7 @@ Mixer_UI::hide_window (GdkEventAny *ev)
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Mixer_UI::add_strip (Session::RouteList& routes)
|
Mixer_UI::add_strip (RouteList& routes)
|
||||||
{
|
{
|
||||||
ENSURE_GUI_THREAD(bind (mem_fun(*this, &Mixer_UI::add_strip), routes));
|
ENSURE_GUI_THREAD(bind (mem_fun(*this, &Mixer_UI::add_strip), routes));
|
||||||
|
|
||||||
|
|
@ -306,7 +306,7 @@ Mixer_UI::add_strip (Session::RouteList& routes)
|
||||||
no_track_list_redisplay = true;
|
no_track_list_redisplay = true;
|
||||||
strip_redisplay_does_not_sync_order_keys = true;
|
strip_redisplay_does_not_sync_order_keys = true;
|
||||||
|
|
||||||
for (Session::RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
|
for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
|
||||||
boost::shared_ptr<Route> route = (*x);
|
boost::shared_ptr<Route> route = (*x);
|
||||||
|
|
||||||
if (route->is_hidden()) {
|
if (route->is_hidden()) {
|
||||||
|
|
@ -885,8 +885,8 @@ struct SignalOrderRouteSorter {
|
||||||
void
|
void
|
||||||
Mixer_UI::initial_track_display ()
|
Mixer_UI::initial_track_display ()
|
||||||
{
|
{
|
||||||
boost::shared_ptr<Session::RouteList> routes = session->get_routes();
|
boost::shared_ptr<RouteList> routes = session->get_routes();
|
||||||
Session::RouteList copy (*routes);
|
RouteList copy (*routes);
|
||||||
SignalOrderRouteSorter sorter;
|
SignalOrderRouteSorter sorter;
|
||||||
|
|
||||||
copy.sort (sorter);
|
copy.sort (sorter);
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ class Mixer_UI : public Gtk::Window
|
||||||
|
|
||||||
bool strip_scroller_button_release (GdkEventButton*);
|
bool strip_scroller_button_release (GdkEventButton*);
|
||||||
|
|
||||||
void add_strip (ARDOUR::Session::RouteList&);
|
void add_strip (ARDOUR::RouteList&);
|
||||||
void remove_strip (MixerStrip *);
|
void remove_strip (MixerStrip *);
|
||||||
|
|
||||||
void hide_all_strips (bool with_select);
|
void hide_all_strips (bool with_select);
|
||||||
|
|
|
||||||
|
|
@ -429,7 +429,11 @@ PlugUIBase::bypass_toggled ()
|
||||||
bool x;
|
bool x;
|
||||||
|
|
||||||
if ((x = bypass_button.get_active()) == insert->active()) {
|
if ((x = bypass_button.get_active()) == insert->active()) {
|
||||||
insert->set_active (!x);
|
if (x) {
|
||||||
|
insert->deactivate ();
|
||||||
|
} else {
|
||||||
|
insert->activate ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -142,9 +142,9 @@ PortGroupList::gather (ARDOUR::Session& session)
|
||||||
/* Find the bundles for routes. We take their bundles, copy them,
|
/* Find the bundles for routes. We take their bundles, copy them,
|
||||||
and add ports from the route's processors */
|
and add ports from the route's processors */
|
||||||
|
|
||||||
boost::shared_ptr<ARDOUR::Session::RouteList> routes = session.get_routes ();
|
boost::shared_ptr<ARDOUR::RouteList> routes = session.get_routes ();
|
||||||
|
|
||||||
for (ARDOUR::Session::RouteList::const_iterator i = routes->begin(); i != routes->end(); ++i) {
|
for (ARDOUR::RouteList::const_iterator i = routes->begin(); i != routes->end(); ++i) {
|
||||||
/* Copy the appropriate bundle from the route */
|
/* Copy the appropriate bundle from the route */
|
||||||
boost::shared_ptr<ARDOUR::Bundle> bundle (
|
boost::shared_ptr<ARDOUR::Bundle> bundle (
|
||||||
new ARDOUR::Bundle (
|
new ARDOUR::Bundle (
|
||||||
|
|
|
||||||
|
|
@ -89,8 +89,8 @@ PortMatrix::routes_changed ()
|
||||||
i->disconnect ();
|
i->disconnect ();
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<ARDOUR::Session::RouteList> routes = _session.get_routes ();
|
boost::shared_ptr<ARDOUR::RouteList> routes = _session.get_routes ();
|
||||||
for (ARDOUR::Session::RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
|
for (ARDOUR::RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
|
||||||
_route_connections.push_back (
|
_route_connections.push_back (
|
||||||
(*i)->processors_changed.connect (sigc::mem_fun (*this, &PortMatrix::setup))
|
(*i)->processors_changed.connect (sigc::mem_fun (*this, &PortMatrix::setup))
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -342,7 +342,11 @@ ProcessorBox::processor_button_release_event (GdkEventButton *ev)
|
||||||
|
|
||||||
/* button2-click with no modifiers */
|
/* button2-click with no modifiers */
|
||||||
|
|
||||||
processor->set_active (!processor->active());
|
if (processor->active()) {
|
||||||
|
processor->deactivate ();
|
||||||
|
} else {
|
||||||
|
processor->activate ();
|
||||||
|
}
|
||||||
ret = true;
|
ret = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -396,7 +400,7 @@ ProcessorBox::use_plugins (const SelectedPlugins& plugins)
|
||||||
Route::ProcessorStreams err_streams;
|
Route::ProcessorStreams err_streams;
|
||||||
|
|
||||||
if (Config->get_new_plugins_active()) {
|
if (Config->get_new_plugins_active()) {
|
||||||
processor->set_active (true);
|
processor->activate ();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_route->add_processor (processor, &err_streams)) {
|
if (_route->add_processor (processor, &err_streams)) {
|
||||||
|
|
@ -405,7 +409,7 @@ ProcessorBox::use_plugins (const SelectedPlugins& plugins)
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (Profile->get_sae()) {
|
if (Profile->get_sae()) {
|
||||||
processor->set_active (true);
|
processor->activate ();
|
||||||
}
|
}
|
||||||
processor->ActiveChanged.connect (bind (mem_fun (*this, &ProcessorBox::show_processor_active), boost::weak_ptr<Processor>(processor)));
|
processor->ActiveChanged.connect (bind (mem_fun (*this, &ProcessorBox::show_processor_active), boost::weak_ptr<Processor>(processor)));
|
||||||
}
|
}
|
||||||
|
|
@ -545,7 +549,7 @@ ProcessorBox::send_io_finished (IOSelector::Result r, boost::weak_ptr<Processor>
|
||||||
case IOSelector::Accepted:
|
case IOSelector::Accepted:
|
||||||
_route->add_processor (processor);
|
_route->add_processor (processor);
|
||||||
if (Profile->get_sae()) {
|
if (Profile->get_sae()) {
|
||||||
processor->set_active (true);
|
processor->activate ();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -982,13 +986,13 @@ could not match the configuration of this track.");
|
||||||
void
|
void
|
||||||
ProcessorBox::activate_processor (boost::shared_ptr<Processor> r)
|
ProcessorBox::activate_processor (boost::shared_ptr<Processor> r)
|
||||||
{
|
{
|
||||||
r->set_active (true);
|
r->activate ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ProcessorBox::deactivate_processor (boost::shared_ptr<Processor> r)
|
ProcessorBox::deactivate_processor (boost::shared_ptr<Processor> r)
|
||||||
{
|
{
|
||||||
r->set_active (false);
|
r->deactivate ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -171,11 +171,11 @@ RouteParams_UI::~RouteParams_UI ()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RouteParams_UI::add_routes (Session::RouteList& routes)
|
RouteParams_UI::add_routes (RouteList& routes)
|
||||||
{
|
{
|
||||||
ENSURE_GUI_THREAD(bind (mem_fun(*this, &RouteParams_UI::add_routes), routes));
|
ENSURE_GUI_THREAD(bind (mem_fun(*this, &RouteParams_UI::add_routes), routes));
|
||||||
|
|
||||||
for (Session::RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
|
for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
|
||||||
boost::shared_ptr<Route> route = (*x);
|
boost::shared_ptr<Route> route = (*x);
|
||||||
|
|
||||||
if (route->is_hidden()) {
|
if (route->is_hidden()) {
|
||||||
|
|
@ -423,7 +423,7 @@ RouteParams_UI::set_session (Session *sess)
|
||||||
route_display_model->clear();
|
route_display_model->clear();
|
||||||
|
|
||||||
if (session) {
|
if (session) {
|
||||||
boost::shared_ptr<Session::RouteList> r = session->get_routes();
|
boost::shared_ptr<RouteList> r = session->get_routes();
|
||||||
add_routes (*r);
|
add_routes (*r);
|
||||||
session->GoingAway.connect (mem_fun(*this, &ArdourDialog::session_gone));
|
session->GoingAway.connect (mem_fun(*this, &ArdourDialog::session_gone));
|
||||||
session->RouteAdded.connect (mem_fun(*this, &RouteParams_UI::add_routes));
|
session->RouteAdded.connect (mem_fun(*this, &RouteParams_UI::add_routes));
|
||||||
|
|
|
||||||
|
|
@ -167,7 +167,7 @@ class RouteParams_UI : public ArdourDialog
|
||||||
Glib::RefPtr<Gtk::ListStore> route_display_model;
|
Glib::RefPtr<Gtk::ListStore> route_display_model;
|
||||||
|
|
||||||
|
|
||||||
void add_routes (ARDOUR::Session::RouteList&);
|
void add_routes (ARDOUR::RouteList&);
|
||||||
|
|
||||||
void route_name_changed (boost::shared_ptr<ARDOUR::Route> route);
|
void route_name_changed (boost::shared_ptr<ARDOUR::Route> route);
|
||||||
void route_removed (boost::shared_ptr<ARDOUR::Route> route);
|
void route_removed (boost::shared_ptr<ARDOUR::Route> route);
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,7 @@ gain.cc
|
||||||
gdither.cc
|
gdither.cc
|
||||||
globals.cc
|
globals.cc
|
||||||
import.cc
|
import.cc
|
||||||
|
internal_send.cc
|
||||||
io.cc
|
io.cc
|
||||||
io_processor.cc
|
io_processor.cc
|
||||||
jack_slave.cc
|
jack_slave.cc
|
||||||
|
|
|
||||||
|
|
@ -42,9 +42,6 @@ namespace MIDI {
|
||||||
namespace ARDOUR {
|
namespace ARDOUR {
|
||||||
|
|
||||||
class AudioEngine;
|
class AudioEngine;
|
||||||
class OSC;
|
|
||||||
|
|
||||||
extern OSC* osc;
|
|
||||||
|
|
||||||
static const nframes_t max_frames = JACK_MAX_FRAMES;
|
static const nframes_t max_frames = JACK_MAX_FRAMES;
|
||||||
extern sigc::signal<void,std::string> BootMessage;
|
extern sigc::signal<void,std::string> BootMessage;
|
||||||
|
|
|
||||||
|
|
@ -68,9 +68,14 @@ public:
|
||||||
/** Accumulate (add) @a len frames FROM THE START OF @a src into self at @a offset
|
/** Accumulate (add) @a len frames FROM THE START OF @a src into self at @a offset
|
||||||
* scaling by @a gain_coeff */
|
* scaling by @a gain_coeff */
|
||||||
void accumulate_with_gain_from(const AudioBuffer& src, nframes_t len, nframes_t offset, gain_t gain_coeff) {
|
void accumulate_with_gain_from(const AudioBuffer& src, nframes_t len, nframes_t offset, gain_t gain_coeff) {
|
||||||
|
|
||||||
assert(_capacity > 0);
|
assert(_capacity > 0);
|
||||||
assert(offset + len <= _capacity);
|
assert(offset + len <= _capacity);
|
||||||
|
|
||||||
|
if (src.silent()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Sample* const dst_raw = _data + offset;
|
Sample* const dst_raw = _data + offset;
|
||||||
const Sample* const src_raw = src.data();
|
const Sample* const src_raw = src.data();
|
||||||
|
|
||||||
|
|
@ -82,6 +87,7 @@ public:
|
||||||
/** Accumulate (add) @a len frames FROM THE START OF @a src into self at @a offset
|
/** Accumulate (add) @a len frames FROM THE START OF @a src into self at @a offset
|
||||||
* scaling by @a gain_coeff */
|
* scaling by @a gain_coeff */
|
||||||
void accumulate_with_gain_from(const Sample* src_raw, nframes_t len, nframes_t offset, gain_t gain_coeff) {
|
void accumulate_with_gain_from(const Sample* src_raw, nframes_t len, nframes_t offset, gain_t gain_coeff) {
|
||||||
|
|
||||||
assert(_capacity > 0);
|
assert(_capacity > 0);
|
||||||
assert(offset + len <= _capacity);
|
assert(offset + len <= _capacity);
|
||||||
|
|
||||||
|
|
@ -123,7 +129,22 @@ public:
|
||||||
Sample* data (nframes_t nframes, nframes_t offset)
|
Sample* data (nframes_t nframes, nframes_t offset)
|
||||||
{ assert(offset + nframes <= _capacity); return _data + offset; }
|
{ assert(offset + nframes <= _capacity); return _data + offset; }
|
||||||
|
|
||||||
private:
|
void replace_data (size_t nframes);
|
||||||
|
|
||||||
|
void drop_data () {
|
||||||
|
assert (_owns_data);
|
||||||
|
assert (_data);
|
||||||
|
|
||||||
|
free (_data);
|
||||||
|
_data = 0;
|
||||||
|
_size = 0;
|
||||||
|
_capacity = 0;
|
||||||
|
_silent = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void copy_to_internal (Sample* p, nframes_t cnt, nframes_t offset);
|
||||||
|
|
||||||
|
private:
|
||||||
bool _owns_data;
|
bool _owns_data;
|
||||||
Sample* _data; ///< Actual buffer contents
|
Sample* _data; ///< Actual buffer contents
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -51,12 +51,16 @@ class AudioPort : public Port
|
||||||
|
|
||||||
AudioPort (std::string const &, Flags, bool, nframes_t);
|
AudioPort (std::string const &, Flags, bool, nframes_t);
|
||||||
|
|
||||||
|
bool using_internal_data() const;
|
||||||
|
void use_internal_data ();
|
||||||
|
void use_external_data ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void mixdown (nframes_t, nframes_t, bool);
|
void mixdown (nframes_t, nframes_t, bool);
|
||||||
|
|
||||||
bool _has_been_mixed_down;
|
bool _has_been_mixed_down;
|
||||||
AudioBuffer* _buffer;
|
AudioBuffer* _buffer;
|
||||||
bool _own_buffer;
|
bool _internal_buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ARDOUR
|
} // namespace ARDOUR
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,10 @@ class AudioTrack : public Track
|
||||||
int deprecated_use_diskstream_connections ();
|
int deprecated_use_diskstream_connections ();
|
||||||
void set_state_part_two ();
|
void set_state_part_two ();
|
||||||
void set_state_part_three ();
|
void set_state_part_three ();
|
||||||
|
|
||||||
|
void catch_up_on_busses (ARDOUR::RouteList&);
|
||||||
|
void add_internal_send (boost::shared_ptr<ARDOUR::Route>);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ARDOUR
|
} // namespace ARDOUR
|
||||||
|
|
|
||||||
|
|
@ -94,15 +94,16 @@ public:
|
||||||
Evoral::ControlSet& data() { return *this; }
|
Evoral::ControlSet& data() { return *this; }
|
||||||
const Evoral::ControlSet& data() const { return *this; }
|
const Evoral::ControlSet& data() const { return *this; }
|
||||||
|
|
||||||
protected:
|
int set_automation_state (const XMLNode&, Evoral::Parameter default_param);
|
||||||
|
XMLNode& get_automation_state();
|
||||||
|
|
||||||
|
protected:
|
||||||
Session& _a_session;
|
Session& _a_session;
|
||||||
|
|
||||||
void can_automate(Evoral::Parameter);
|
void can_automate(Evoral::Parameter);
|
||||||
|
|
||||||
virtual void auto_state_changed (Evoral::Parameter which) {}
|
virtual void auto_state_changed (Evoral::Parameter which) {}
|
||||||
|
|
||||||
int set_automation_state(const XMLNode&, Evoral::Parameter default_param);
|
|
||||||
XMLNode& get_automation_state();
|
|
||||||
|
|
||||||
int load_automation (const std::string& path);
|
int load_automation (const std::string& path);
|
||||||
int old_set_automation_state(const XMLNode&);
|
int old_set_automation_state(const XMLNode&);
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ public:
|
||||||
* passed to the constructor must have been non-zero.
|
* passed to the constructor must have been non-zero.
|
||||||
*/
|
*/
|
||||||
virtual void resize(size_t) = 0;
|
virtual void resize(size_t) = 0;
|
||||||
|
|
||||||
/** Clear (eg zero, or empty) buffer starting at TIME @a offset */
|
/** Clear (eg zero, or empty) buffer starting at TIME @a offset */
|
||||||
virtual void silence(nframes_t len, nframes_t offset=0) = 0;
|
virtual void silence(nframes_t len, nframes_t offset=0) = 0;
|
||||||
|
|
||||||
|
|
@ -77,9 +77,9 @@ public:
|
||||||
|
|
||||||
virtual void read_from(const Buffer& src, nframes_t offset, nframes_t len) = 0;
|
virtual void read_from(const Buffer& src, nframes_t offset, nframes_t len) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Buffer(DataType type, size_t capacity)
|
Buffer(DataType type, size_t capacity)
|
||||||
: _type(type), _capacity(capacity), _size(0), _silent(true)
|
: _type(type), _capacity(capacity), _size(0), _silent(true)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
DataType _type;
|
DataType _type;
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <ardour/chan_count.h>
|
#include <ardour/chan_count.h>
|
||||||
#include <ardour/data_type.h>
|
#include <ardour/data_type.h>
|
||||||
|
#include <ardour/types.h>
|
||||||
|
|
||||||
namespace ARDOUR {
|
namespace ARDOUR {
|
||||||
|
|
||||||
|
|
@ -53,7 +54,7 @@ public:
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
void attach_buffers(PortSet& ports);
|
void attach_buffers(PortSet& ports, nframes_t nframes, nframes_t offset);
|
||||||
|
|
||||||
void ensure_buffers(const ChanCount& count, size_t buffer_capacity);
|
void ensure_buffers(const ChanCount& count, size_t buffer_capacity);
|
||||||
void ensure_buffers(DataType type, size_t num_buffers, size_t buffer_capacity);
|
void ensure_buffers(DataType type, size_t num_buffers, size_t buffer_capacity);
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,8 @@ class IO : public SessionObject, public AutomatableControls, public Latent
|
||||||
void just_meter_input (nframes_t start_frame, nframes_t end_frame,
|
void just_meter_input (nframes_t start_frame, nframes_t end_frame,
|
||||||
nframes_t nframes, nframes_t offset);
|
nframes_t nframes, nframes_t offset);
|
||||||
|
|
||||||
|
BufferSet& output_buffers() { return *_output_buffers; }
|
||||||
|
|
||||||
gain_t gain () const { return _desired_gain; }
|
gain_t gain () const { return _desired_gain; }
|
||||||
virtual gain_t effective_gain () const;
|
virtual gain_t effective_gain () const;
|
||||||
|
|
||||||
|
|
@ -121,6 +123,7 @@ class IO : public SessionObject, public AutomatableControls, public Latent
|
||||||
Panner& panner() { return *_panner; }
|
Panner& panner() { return *_panner; }
|
||||||
PeakMeter& peak_meter() { return *_meter; }
|
PeakMeter& peak_meter() { return *_meter; }
|
||||||
const Panner& panner() const { return *_panner; }
|
const Panner& panner() const { return *_panner; }
|
||||||
|
void reset_panner ();
|
||||||
|
|
||||||
int ensure_io (ChanCount in, ChanCount out, bool clear, void *src);
|
int ensure_io (ChanCount in, ChanCount out, bool clear, void *src);
|
||||||
|
|
||||||
|
|
@ -196,15 +199,10 @@ class IO : public SessionObject, public AutomatableControls, public Latent
|
||||||
int set_state (const XMLNode&);
|
int set_state (const XMLNode&);
|
||||||
|
|
||||||
static int disable_connecting (void);
|
static int disable_connecting (void);
|
||||||
|
|
||||||
static int enable_connecting (void);
|
static int enable_connecting (void);
|
||||||
|
|
||||||
static int disable_ports (void);
|
static int disable_ports (void);
|
||||||
|
|
||||||
static int enable_ports (void);
|
static int enable_ports (void);
|
||||||
|
|
||||||
static int disable_panners (void);
|
static int disable_panners (void);
|
||||||
|
|
||||||
static int reset_panners (void);
|
static int reset_panners (void);
|
||||||
|
|
||||||
static sigc::signal<int> PortsLegal;
|
static sigc::signal<int> PortsLegal;
|
||||||
|
|
@ -214,16 +212,16 @@ class IO : public SessionObject, public AutomatableControls, public Latent
|
||||||
static sigc::signal<void,ChanCount> PortCountChanged;
|
static sigc::signal<void,ChanCount> PortCountChanged;
|
||||||
static sigc::signal<int> PortsCreated;
|
static sigc::signal<int> PortsCreated;
|
||||||
|
|
||||||
static void update_meters();
|
static void update_meters();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static sigc::signal<void> Meter;
|
static sigc::signal<void> Meter;
|
||||||
static Glib::StaticMutex m_meter_signal_lock;
|
static Glib::StaticMutex m_meter_signal_lock;
|
||||||
sigc::connection m_meter_connection;
|
sigc::connection m_meter_connection;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/* automation */
|
/* automation */
|
||||||
|
|
||||||
struct GainControl : public AutomationControl {
|
struct GainControl : public AutomationControl {
|
||||||
|
|
@ -292,8 +290,6 @@ class IO : public SessionObject, public AutomatableControls, public Latent
|
||||||
|
|
||||||
virtual void set_deferred_state() {}
|
virtual void set_deferred_state() {}
|
||||||
|
|
||||||
void reset_panner ();
|
|
||||||
|
|
||||||
virtual uint32_t pans_required() const
|
virtual uint32_t pans_required() const
|
||||||
{ return _inputs.count().n_audio(); }
|
{ return _inputs.count().n_audio(); }
|
||||||
|
|
||||||
|
|
@ -314,14 +310,11 @@ class IO : public SessionObject, public AutomatableControls, public Latent
|
||||||
static bool connecting_legal;
|
static bool connecting_legal;
|
||||||
static bool ports_legal;
|
static bool ports_legal;
|
||||||
|
|
||||||
BufferSet& output_buffers() { return *_output_buffers; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
friend class Send;
|
|
||||||
|
|
||||||
static bool panners_legal;
|
static bool panners_legal;
|
||||||
|
|
||||||
|
void copy_to_outputs (BufferSet& bufs, DataType type, nframes_t nframes, nframes_t offset);
|
||||||
|
|
||||||
int connecting_became_legal ();
|
int connecting_became_legal ();
|
||||||
int panners_became_legal ();
|
int panners_became_legal ();
|
||||||
sigc::connection connection_legal_c;
|
sigc::connection connection_legal_c;
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,9 @@ class IOProcessor : public Processor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
IOProcessor (Session&, const string& name, Placement,
|
IOProcessor (Session&, const string& name, Placement,
|
||||||
int input_min = -1, int input_max = -1, int output_min = -1, int output_max = -1);
|
int input_min = -1, int input_max = -1, int output_min = -1, int output_max = -1,
|
||||||
|
ARDOUR::DataType default_type = DataType::AUDIO,
|
||||||
|
bool public_ports = true);
|
||||||
IOProcessor (const IOProcessor&);
|
IOProcessor (const IOProcessor&);
|
||||||
virtual ~IOProcessor ();
|
virtual ~IOProcessor ();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool connected () const;
|
bool connected () const;
|
||||||
|
bool externally_connected () const;
|
||||||
int disconnect_all ();
|
int disconnect_all ();
|
||||||
int get_connections (std::vector<std::string> &) const;
|
int get_connections (std::vector<std::string> &) const;
|
||||||
|
|
||||||
|
|
@ -81,7 +82,7 @@ public:
|
||||||
|
|
||||||
/* connection by Port* */
|
/* connection by Port* */
|
||||||
bool connected_to (Port *) const;
|
bool connected_to (Port *) const;
|
||||||
int connect (Port *);
|
virtual int connect (Port *);
|
||||||
int disconnect (Port *);
|
int disconnect (Port *);
|
||||||
|
|
||||||
void ensure_monitor_input (bool);
|
void ensure_monitor_input (bool);
|
||||||
|
|
@ -113,6 +114,12 @@ protected:
|
||||||
std::set<Port*> _connections; ///< internal Ports that we are connected to
|
std::set<Port*> _connections; ///< internal Ports that we are connected to
|
||||||
|
|
||||||
static AudioEngine* _engine; ///< the AudioEngine
|
static AudioEngine* _engine; ///< the AudioEngine
|
||||||
|
|
||||||
|
virtual bool using_internal_data() const { return false; }
|
||||||
|
virtual void use_internal_data () {}
|
||||||
|
virtual void use_external_data () {}
|
||||||
|
|
||||||
|
void check_buffer_status ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class AudioEngine;
|
friend class AudioEngine;
|
||||||
|
|
@ -130,6 +137,7 @@ private:
|
||||||
/// list of JACK ports that we are connected to; we only keep this around
|
/// list of JACK ports that we are connected to; we only keep this around
|
||||||
/// so that we can implement ::reconnect ()
|
/// so that we can implement ::reconnect ()
|
||||||
std::set<std::string> _named_connections;
|
std::set<std::string> _named_connections;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ class XMLNode;
|
||||||
namespace ARDOUR {
|
namespace ARDOUR {
|
||||||
|
|
||||||
class Session;
|
class Session;
|
||||||
|
class Route;
|
||||||
|
|
||||||
/* A mixer strip element - plugin, send, meter, etc.
|
/* A mixer strip element - plugin, send, meter, etc.
|
||||||
*/
|
*/
|
||||||
|
|
@ -60,7 +61,6 @@ class Processor : public SessionObject, public AutomatableControls, public Laten
|
||||||
void set_placement (Placement);
|
void set_placement (Placement);
|
||||||
|
|
||||||
bool active () const { return _active; }
|
bool active () const { return _active; }
|
||||||
void set_active (bool yn);
|
|
||||||
|
|
||||||
bool get_next_ab_is_active () const { return _next_ab_is_active; }
|
bool get_next_ab_is_active () const { return _next_ab_is_active; }
|
||||||
void set_next_ab_is_active (bool yn) { _next_ab_is_active = yn; }
|
void set_next_ab_is_active (bool yn) { _next_ab_is_active = yn; }
|
||||||
|
|
@ -77,8 +77,8 @@ class Processor : public SessionObject, public AutomatableControls, public Laten
|
||||||
|
|
||||||
virtual void silence (nframes_t nframes, nframes_t offset) {}
|
virtual void silence (nframes_t nframes, nframes_t offset) {}
|
||||||
|
|
||||||
virtual void activate () { _active = true; ActiveChanged.emit(); }
|
void activate () { _active = true; ActiveChanged(); }
|
||||||
virtual void deactivate () { _active = false; ActiveChanged.emit(); }
|
void deactivate () { _active = false; ActiveChanged(); }
|
||||||
|
|
||||||
virtual bool configure_io (ChanCount in, ChanCount out);
|
virtual bool configure_io (ChanCount in, ChanCount out);
|
||||||
|
|
||||||
|
|
@ -108,6 +108,7 @@ class Processor : public SessionObject, public AutomatableControls, public Laten
|
||||||
sigc::signal<void> PlacementChanged;
|
sigc::signal<void> PlacementChanged;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
int _pending_active;
|
||||||
bool _active;
|
bool _active;
|
||||||
bool _next_ab_is_active;
|
bool _next_ab_is_active;
|
||||||
bool _configured;
|
bool _configured;
|
||||||
|
|
|
||||||
|
|
@ -306,7 +306,6 @@ class Session : public PBD::StatefulDestructible
|
||||||
uint32_t n_diskstreams() const;
|
uint32_t n_diskstreams() const;
|
||||||
|
|
||||||
typedef std::list<boost::shared_ptr<Diskstream> > DiskstreamList;
|
typedef std::list<boost::shared_ptr<Diskstream> > DiskstreamList;
|
||||||
typedef std::list<boost::shared_ptr<Route> > RouteList;
|
|
||||||
|
|
||||||
int load_routes (const XMLNode&);
|
int load_routes (const XMLNode&);
|
||||||
boost::shared_ptr<RouteList> get_routes() const {
|
boost::shared_ptr<RouteList> get_routes() const {
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ namespace ARDOUR {
|
||||||
|
|
||||||
class Source;
|
class Source;
|
||||||
class AudioSource;
|
class AudioSource;
|
||||||
|
class Route;
|
||||||
|
|
||||||
typedef jack_default_audio_sample_t Sample;
|
typedef jack_default_audio_sample_t Sample;
|
||||||
typedef float pan_t;
|
typedef float pan_t;
|
||||||
|
|
@ -419,9 +420,11 @@ namespace ARDOUR {
|
||||||
|
|
||||||
typedef std::list<nframes64_t> AnalysisFeatureList;
|
typedef std::list<nframes64_t> AnalysisFeatureList;
|
||||||
|
|
||||||
|
typedef std::list<boost::shared_ptr<Route> > RouteList;
|
||||||
|
|
||||||
class Bundle;
|
class Bundle;
|
||||||
typedef std::vector<boost::shared_ptr<Bundle> > BundleList;
|
typedef std::vector<boost::shared_ptr<Bundle> > BundleList;
|
||||||
|
|
||||||
} // namespace ARDOUR
|
} // namespace ARDOUR
|
||||||
|
|
||||||
std::istream& operator>>(std::istream& o, ARDOUR::SampleFormat& sf);
|
std::istream& operator>>(std::istream& o, ARDOUR::SampleFormat& sf);
|
||||||
|
|
|
||||||
|
|
@ -29,9 +29,7 @@ static const int CPU_CACHE_ALIGN = 16; /* arguably 32 on most arches, but it mat
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace PBD;
|
using namespace PBD;
|
||||||
|
using namespace ARDOUR;
|
||||||
namespace ARDOUR {
|
|
||||||
|
|
||||||
|
|
||||||
AudioBuffer::AudioBuffer(size_t capacity)
|
AudioBuffer::AudioBuffer(size_t capacity)
|
||||||
: Buffer(DataType::AUDIO, capacity)
|
: Buffer(DataType::AUDIO, capacity)
|
||||||
|
|
@ -41,6 +39,7 @@ AudioBuffer::AudioBuffer(size_t capacity)
|
||||||
if (_capacity > 0) {
|
if (_capacity > 0) {
|
||||||
_owns_data = true; // prevent resize() from gagging
|
_owns_data = true; // prevent resize() from gagging
|
||||||
resize (_capacity);
|
resize (_capacity);
|
||||||
|
_silent = false; // force silence on the intial buffer state
|
||||||
silence (_capacity);
|
silence (_capacity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -51,10 +50,28 @@ AudioBuffer::~AudioBuffer()
|
||||||
free(_data);
|
free(_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* called to replace a pointer to an external buffer (e.g. JACK) with
|
||||||
|
buffer-owned memory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioBuffer::replace_data (size_t capacity)
|
||||||
|
{
|
||||||
|
_owns_data = true;
|
||||||
|
_data = 0;
|
||||||
|
_capacity = 0; // force reallocation
|
||||||
|
resize (capacity);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AudioBuffer::resize (size_t size)
|
AudioBuffer::resize (size_t size)
|
||||||
{
|
{
|
||||||
if (!_owns_data || (size < _capacity)) {
|
if (!_owns_data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size < _capacity) {
|
||||||
|
_size = size;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -74,9 +91,12 @@ AudioBuffer::resize (size_t size)
|
||||||
CPU_CACHE_ALIGN, sizeof (Sample) * _capacity, strerror (errno)) << endmsg;
|
CPU_CACHE_ALIGN, sizeof (Sample) * _capacity, strerror (errno)) << endmsg;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_owns_data = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ARDOUR
|
void
|
||||||
|
AudioBuffer::copy_to_internal (Sample* p, nframes_t cnt, nframes_t offset)
|
||||||
|
{
|
||||||
|
memcpy (_data + offset, p, sizeof(Sample*) * cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,9 +29,10 @@ AudioPort::AudioPort (const std::string& name, Flags flags, bool ext, nframes_t
|
||||||
: Port (name, DataType::AUDIO, flags, ext)
|
: Port (name, DataType::AUDIO, flags, ext)
|
||||||
, _has_been_mixed_down (false)
|
, _has_been_mixed_down (false)
|
||||||
, _buffer (0)
|
, _buffer (0)
|
||||||
|
, _internal_buffer (false)
|
||||||
{
|
{
|
||||||
assert (name.find_first_of (':') == string::npos);
|
assert (name.find_first_of (':') == string::npos);
|
||||||
|
|
||||||
if (external ()) {
|
if (external ()) {
|
||||||
|
|
||||||
/* external ports use the external port buffer */
|
/* external ports use the external port buffer */
|
||||||
|
|
@ -41,8 +42,9 @@ AudioPort::AudioPort (const std::string& name, Flags flags, bool ext, nframes_t
|
||||||
|
|
||||||
/* internal ports need their own buffers */
|
/* internal ports need their own buffers */
|
||||||
_buffer = new AudioBuffer (capacity);
|
_buffer = new AudioBuffer (capacity);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_buffer_status ();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -56,11 +58,22 @@ AudioPort::cycle_start (nframes_t nframes, nframes_t offset)
|
||||||
{
|
{
|
||||||
/* caller must hold process lock */
|
/* caller must hold process lock */
|
||||||
|
|
||||||
_has_been_mixed_down = false;
|
/* For external (JACK) ports, get_buffer() must only be run
|
||||||
|
on outputs here in cycle_start().
|
||||||
|
|
||||||
if (external ()) {
|
Inputs must be done in the correct processing order, which
|
||||||
/* external ports use JACK's memory */
|
requires interleaving with route processing. that will
|
||||||
_buffer->set_data ((Sample *) jack_port_get_buffer (_jack_port, nframes), nframes + offset);
|
happen when Port::get_buffer() is called.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!receives_input() && external ()) {
|
||||||
|
_buffer->set_data ((Sample *) jack_port_get_buffer (_jack_port, nframes) + offset, nframes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (receives_input()) {
|
||||||
|
_has_been_mixed_down = false;
|
||||||
|
} else {
|
||||||
|
_buffer->silence (nframes, offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -69,36 +82,21 @@ AudioPort::get_audio_buffer (nframes_t nframes, nframes_t offset)
|
||||||
{
|
{
|
||||||
/* caller must hold process lock */
|
/* caller must hold process lock */
|
||||||
|
|
||||||
if (_has_been_mixed_down) {
|
if (receives_input () && !_has_been_mixed_down) {
|
||||||
return *_buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (receives_input ()) {
|
/* external ports use JACK's memory unless otherwise noted */
|
||||||
|
|
||||||
/* INPUT */
|
|
||||||
|
|
||||||
/* If we're external (), we have some data in our buffer set up by JACK;
|
|
||||||
otherwise, we have an undefined buffer. In either case we mix down
|
|
||||||
our non-JACK inputs; either accumulating into the JACK data or
|
|
||||||
overwriting the undefined data */
|
|
||||||
|
|
||||||
mixdown (nframes, offset, !external ());
|
|
||||||
|
|
||||||
} else {
|
if (external()) {
|
||||||
|
if (!using_internal_data()) {
|
||||||
/* OUTPUT */
|
_buffer->set_data ((Sample *) jack_port_get_buffer (_jack_port, nframes) + offset, nframes);
|
||||||
|
} else {
|
||||||
if (!external ()) {
|
_buffer->silence (nframes, offset);
|
||||||
/* start internal output buffers with silence */
|
}
|
||||||
_buffer->silence (nframes, offset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nframes) {
|
|
||||||
_has_been_mixed_down = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
mixdown (nframes, offset, !external ());
|
||||||
|
}
|
||||||
|
|
||||||
return *_buffer;
|
return *_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -111,22 +109,46 @@ AudioPort::cycle_end (nframes_t nframes, nframes_t offset)
|
||||||
void
|
void
|
||||||
AudioPort::mixdown (nframes_t cnt, nframes_t offset, bool first_overwrite)
|
AudioPort::mixdown (nframes_t cnt, nframes_t offset, bool first_overwrite)
|
||||||
{
|
{
|
||||||
|
/* note: this is only called for input ports */
|
||||||
|
|
||||||
if (_connections.empty()) {
|
if (_connections.empty()) {
|
||||||
if (first_overwrite) {
|
|
||||||
|
/* no internal mixing to do, so for internal ports
|
||||||
|
just make sure the buffer is silent.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!external()) {
|
||||||
_buffer->silence (cnt, offset);
|
_buffer->silence (cnt, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
set<Port*>::const_iterator p = _connections.begin();
|
||||||
|
|
||||||
|
/* mix in internally-connected ports. if this is an external port
|
||||||
|
then it may already have data present from JACK. in that case, we
|
||||||
|
do not want to overwrite that data, so we skip the initial ::read_from()
|
||||||
|
call and do everything with accumulate_from()
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!external()) {
|
||||||
|
_buffer->read_from (dynamic_cast<AudioPort*>(*p)->get_audio_buffer (cnt, offset), cnt, offset);
|
||||||
|
++p;
|
||||||
|
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
set<Port*>::const_iterator p = _connections.begin();
|
|
||||||
|
|
||||||
if (first_overwrite) {
|
for (; p != _connections.end (); ++p) {
|
||||||
_buffer->read_from (dynamic_cast<AudioPort*>(*p)->get_audio_buffer (cnt, offset), cnt, offset);
|
_buffer->accumulate_from (dynamic_cast<AudioPort*>(*p)->get_audio_buffer (cnt, offset), cnt, offset);
|
||||||
++p;
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; p != _connections.end (); ++p) {
|
/* XXX horrible heuristic designed to check that we worked the whole buffer.
|
||||||
_buffer->accumulate_from (dynamic_cast<AudioPort*>(*p)->get_audio_buffer (cnt, offset), cnt, offset);
|
Needs fixing but its a hard problem.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (cnt && offset == 0) {
|
||||||
|
_has_been_mixed_down = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -140,3 +162,23 @@ AudioPort::reset ()
|
||||||
_buffer->clear ();
|
_buffer->clear ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
AudioPort::using_internal_data () const
|
||||||
|
{
|
||||||
|
return _internal_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioPort::use_internal_data ()
|
||||||
|
{
|
||||||
|
_buffer->replace_data (_buffer->capacity());
|
||||||
|
_internal_buffer = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioPort::use_external_data ()
|
||||||
|
{
|
||||||
|
_internal_buffer = false;
|
||||||
|
_buffer->drop_data ();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@
|
||||||
#include <ardour/utils.h>
|
#include <ardour/utils.h>
|
||||||
#include <ardour/buffer_set.h>
|
#include <ardour/buffer_set.h>
|
||||||
#include <ardour/audio_buffer.h>
|
#include <ardour/audio_buffer.h>
|
||||||
|
#include <ardour/internal_send.h>
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
@ -65,6 +66,8 @@ AudioTrack::AudioTrack (Session& sess, string name, Route::Flag flag, TrackMode
|
||||||
|
|
||||||
_session.add_diskstream (ds);
|
_session.add_diskstream (ds);
|
||||||
|
|
||||||
|
_session.RouteAdded.connect (mem_fun (*this, &AudioTrack::catch_up_on_busses));
|
||||||
|
|
||||||
set_diskstream (boost::dynamic_pointer_cast<AudioDiskstream> (ds), this);
|
set_diskstream (boost::dynamic_pointer_cast<AudioDiskstream> (ds), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -72,12 +75,47 @@ AudioTrack::AudioTrack (Session& sess, const XMLNode& node)
|
||||||
: Track (sess, node)
|
: Track (sess, node)
|
||||||
{
|
{
|
||||||
_set_state (node, false);
|
_set_state (node, false);
|
||||||
|
|
||||||
|
_session.RouteAdded.connect (mem_fun (*this, &AudioTrack::catch_up_on_busses));
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioTrack::~AudioTrack ()
|
AudioTrack::~AudioTrack ()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioTrack::catch_up_on_busses (RouteList& added)
|
||||||
|
{
|
||||||
|
if (is_hidden()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (RouteList::iterator x = added.begin(); x != added.end(); ++x) {
|
||||||
|
if (boost::dynamic_pointer_cast<Track>(*x) == 0 && (*x)->default_type() == DataType::AUDIO) {
|
||||||
|
/* Audio bus */
|
||||||
|
if (!(*x)->is_master() && !(*x)->is_control()) {
|
||||||
|
add_internal_send (*x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioTrack::add_internal_send (boost::shared_ptr<Route> r)
|
||||||
|
{
|
||||||
|
boost::shared_ptr<InternalSend> is (new InternalSend (_session, PreFader, r));
|
||||||
|
|
||||||
|
cerr << name() << " Adding processor\n";
|
||||||
|
|
||||||
|
add_processor (is, 0);
|
||||||
|
|
||||||
|
cerr << "After add, we have " << _processors.size() << endl;
|
||||||
|
|
||||||
|
/* note: if adding failed, the InternalSend will be cleaned up automatically when
|
||||||
|
the shared_ptr goes out of scope.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
AudioTrack::set_mode (TrackMode m)
|
AudioTrack::set_mode (TrackMode m)
|
||||||
{
|
{
|
||||||
|
|
@ -879,7 +917,7 @@ AudioTrack::freeze (InterThreadInfo& itt)
|
||||||
|
|
||||||
/* now deactivate the processor */
|
/* now deactivate the processor */
|
||||||
|
|
||||||
processor->set_active (false);
|
processor->deactivate ();
|
||||||
_session.set_dirty ();
|
_session.set_dirty ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -348,13 +348,6 @@ AudioEngine::process_callback (nframes_t nframes)
|
||||||
boost::shared_ptr<Ports> p = ports.reader();
|
boost::shared_ptr<Ports> p = ports.reader();
|
||||||
|
|
||||||
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
|
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
|
||||||
|
|
||||||
/* Only run cycle_start() on output ports, because
|
|
||||||
inputs must be done in the correct processing order,
|
|
||||||
which requires interleaving with route processing.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* XXX: we're running this on both inputs and outputs... */
|
|
||||||
(*i)->cycle_start (nframes, 0);
|
(*i)->cycle_start (nframes, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -416,10 +409,8 @@ AudioEngine::process_callback (nframes_t nframes)
|
||||||
// Finalize ports (ie write data if necessary)
|
// Finalize ports (ie write data if necessary)
|
||||||
|
|
||||||
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
|
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
|
||||||
|
|
||||||
(*i)->cycle_end (nframes, 0);
|
(*i)->cycle_end (nframes, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
_processed_frames = next_processed_frames;
|
_processed_frames = next_processed_frames;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
675 Mass Ave, Cambridge, MA 02139, USA.
|
675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <ardour/buffer_set.h>
|
#include <ardour/buffer_set.h>
|
||||||
#include <ardour/buffer.h>
|
#include <ardour/buffer.h>
|
||||||
|
|
@ -61,7 +62,7 @@ BufferSet::clear()
|
||||||
/** Make this BufferSet a direct mirror of a PortSet's buffers.
|
/** Make this BufferSet a direct mirror of a PortSet's buffers.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
BufferSet::attach_buffers(PortSet& ports)
|
BufferSet::attach_buffers(PortSet& ports, nframes_t nframes, nframes_t offset)
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
|
|
@ -71,9 +72,8 @@ BufferSet::attach_buffers(PortSet& ports)
|
||||||
|
|
||||||
for (PortSet::iterator p = ports.begin(*t); p != ports.end(*t); ++p) {
|
for (PortSet::iterator p = ports.begin(*t); p != ports.end(*t); ++p) {
|
||||||
assert(p->type() == *t);
|
assert(p->type() == *t);
|
||||||
v.push_back(&(p->get_buffer(0,0)));
|
v.push_back(&(p->get_buffer(nframes, offset)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_count = ports.count();
|
_count = ports.count();
|
||||||
|
|
|
||||||
|
|
@ -153,9 +153,6 @@ IO::IO (Session& s, const string& name,
|
||||||
m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
|
m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect to our own PortCountChanged signal to connect output buffers
|
|
||||||
IO::PortCountChanged.connect (mem_fun (*this, &IO::attach_buffers));
|
|
||||||
|
|
||||||
_session.add_controllable (_gain_control);
|
_session.add_controllable (_gain_control);
|
||||||
|
|
||||||
create_bundles_for_inputs_and_outputs ();
|
create_bundles_for_inputs_and_outputs ();
|
||||||
|
|
@ -195,9 +192,6 @@ IO::IO (Session& s, const XMLNode& node, DataType dt)
|
||||||
m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
|
m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect to our own PortCountChanged signal to connect output buffers
|
|
||||||
IO::PortCountChanged.connect (mem_fun (*this, &IO::attach_buffers));
|
|
||||||
|
|
||||||
_session.add_controllable (_gain_control);
|
_session.add_controllable (_gain_control);
|
||||||
|
|
||||||
create_bundles_for_inputs_and_outputs ();
|
create_bundles_for_inputs_and_outputs ();
|
||||||
|
|
@ -222,7 +216,6 @@ IO::~IO ()
|
||||||
|
|
||||||
delete _meter;
|
delete _meter;
|
||||||
delete _panner;
|
delete _panner;
|
||||||
delete _output_buffers;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -266,48 +259,61 @@ IO::deliver_output (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame,
|
||||||
_gain = dg;
|
_gain = dg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* do this so that any processing that comes after deliver_outputs()
|
||||||
|
can use the output buffers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
output_buffers().attach_buffers (_outputs, nframes, offset);
|
||||||
|
|
||||||
// Use the panner to distribute audio to output port buffers
|
// Use the panner to distribute audio to output port buffers
|
||||||
if( _panner && _panner->npanners() && !_panner->bypassed()) {
|
|
||||||
|
if (0 && _panner && _panner->npanners() && !_panner->bypassed()) {
|
||||||
|
|
||||||
|
/* blech .. we shouldn't be creating and tearing this down every process()
|
||||||
|
cycle. XXX fix me to not waste cycles and do memory allocation etc.
|
||||||
|
*/
|
||||||
|
|
||||||
_panner->run_out_of_place(bufs, output_buffers(), start_frame, end_frame, nframes, offset);
|
_panner->run_out_of_place(bufs, output_buffers(), start_frame, end_frame, nframes, offset);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
const DataType type = DataType::AUDIO;
|
|
||||||
|
/* do a 1:1 copy of data to output ports */
|
||||||
// Copy any audio 1:1 to outputs
|
|
||||||
|
if (bufs.count().n_audio() > 0 && _outputs.count().n_audio () > 0) {
|
||||||
BufferSet::iterator o = output_buffers().begin(type);
|
copy_to_outputs (bufs, DataType::AUDIO, nframes, offset);
|
||||||
BufferSet::iterator i = bufs.begin(type);
|
|
||||||
BufferSet::iterator prev = i;
|
|
||||||
|
|
||||||
while (i != bufs.end(type) && o != output_buffers().end (type)) {
|
|
||||||
o->read_from(*i, nframes, offset);
|
|
||||||
prev = i;
|
|
||||||
++i;
|
|
||||||
++o;
|
|
||||||
}
|
}
|
||||||
|
if (bufs.count().n_midi() > 0 && _outputs.count().n_midi () > 0) {
|
||||||
/* extra outputs get a copy of the last buffer */
|
copy_to_outputs (bufs, DataType::MIDI, nframes, offset);
|
||||||
|
|
||||||
while (o != output_buffers().end(type)) {
|
|
||||||
o->read_from(*prev, nframes, offset);
|
|
||||||
++o;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ********** MIDI ********** */
|
void
|
||||||
|
IO::copy_to_outputs (BufferSet& bufs, DataType type, nframes_t nframes, nframes_t offset)
|
||||||
|
{
|
||||||
|
// Copy any buffers 1:1 to outputs
|
||||||
|
|
||||||
|
PortSet::iterator o = _outputs.begin(type);
|
||||||
|
BufferSet::iterator i = bufs.begin(type);
|
||||||
|
BufferSet::iterator prev = i;
|
||||||
|
|
||||||
|
while (i != bufs.end(type) && o != _outputs.end (type)) {
|
||||||
|
|
||||||
|
Buffer& port_buffer (o->get_buffer (nframes, offset));
|
||||||
|
port_buffer.read_from (*i, nframes, offset);
|
||||||
|
|
||||||
// No MIDI, we're done here
|
prev = i;
|
||||||
if (bufs.count().n_midi() == 0 || output_buffers().count().n_midi () == 0) {
|
++i;
|
||||||
return;
|
++o;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DataType type = DataType::MIDI;
|
/* extra outputs get a copy of the last buffer */
|
||||||
|
|
||||||
// Copy any MIDI 1:1 to outputs
|
while (o != _outputs.end(type)) {
|
||||||
assert(bufs.count().n_midi() == output_buffers().count().n_midi());
|
Buffer& port_buffer (o->get_buffer (nframes, offset));
|
||||||
BufferSet::iterator o = output_buffers().begin(type);
|
port_buffer.read_from(*prev, nframes, offset);
|
||||||
for (BufferSet::iterator i = bufs.begin(type); i != bufs.end(type); ++i, ++o) {
|
++o;
|
||||||
o->read_from(*i, nframes, offset);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -324,8 +330,10 @@ IO::collect_input (BufferSet& outs, nframes_t nframes, nframes_t offset)
|
||||||
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
|
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
|
||||||
|
|
||||||
BufferSet::iterator o = outs.begin(*t);
|
BufferSet::iterator o = outs.begin(*t);
|
||||||
for (PortSet::iterator i = _inputs.begin(*t); i != _inputs.end(*t); ++i, ++o) {
|
PortSet::iterator e = _inputs.end (*t);
|
||||||
o->read_from(i->get_buffer(nframes,offset), nframes, offset);
|
for (PortSet::iterator i = _inputs.begin(*t); i != e; ++i, ++o) {
|
||||||
|
Buffer& b (i->get_buffer (nframes,offset));
|
||||||
|
o->read_from (b, nframes, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -879,16 +887,6 @@ IO::ensure_inputs_locked (ChanCount count, bool clear, void* src)
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Attach output_buffers to port buffers.
|
|
||||||
*
|
|
||||||
* Connected to IO's own PortCountChanged signal.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
IO::attach_buffers(ChanCount ignored)
|
|
||||||
{
|
|
||||||
_output_buffers->attach_buffers(_outputs);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
|
IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
|
||||||
{
|
{
|
||||||
|
|
@ -2321,6 +2319,8 @@ IO::set_gain (gain_t val, void *src)
|
||||||
val = 1.99526231f;
|
val = 1.99526231f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cerr << "set desired gain to " << val << " when curgain = " << _gain_control->get_value () << endl;
|
||||||
|
|
||||||
if (src != _gain_control.get()) {
|
if (src != _gain_control.get()) {
|
||||||
_gain_control->set_value(val);
|
_gain_control->set_value(val);
|
||||||
// bit twisty, this will come back and call us again
|
// bit twisty, this will come back and call us again
|
||||||
|
|
@ -2741,3 +2741,5 @@ IO::bundle_channel_name (uint32_t c, uint32_t n) const
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,10 +43,12 @@ using namespace ARDOUR;
|
||||||
using namespace PBD;
|
using namespace PBD;
|
||||||
|
|
||||||
IOProcessor::IOProcessor (Session& s, const string& name, Placement p,
|
IOProcessor::IOProcessor (Session& s, const string& name, Placement p,
|
||||||
int input_min, int input_max,
|
int input_min, int input_max,
|
||||||
int output_min, int output_max)
|
int output_min, int output_max,
|
||||||
|
DataType dtype,
|
||||||
|
bool public_ports)
|
||||||
: Processor(s, name, p)
|
: Processor(s, name, p)
|
||||||
, _io(new IO(s, name, input_min, input_max, output_min, output_max))
|
, _io (new IO(s, name, input_min, input_max, output_min, output_max, dtype, public_ports))
|
||||||
{
|
{
|
||||||
_active = false;
|
_active = false;
|
||||||
_sort_key = 0;
|
_sort_key = 0;
|
||||||
|
|
|
||||||
|
|
@ -25,19 +25,30 @@
|
||||||
#include "pbd/compose.h"
|
#include "pbd/compose.h"
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
ARDOUR::AudioEngine* ARDOUR::Port::_engine = 0;
|
using namespace std;
|
||||||
|
using namespace ARDOUR;
|
||||||
|
|
||||||
|
AudioEngine* Port::_engine = 0;
|
||||||
|
|
||||||
/** @param n Port short name */
|
/** @param n Port short name */
|
||||||
ARDOUR::Port::Port (std::string const & n, DataType t, Flags f, bool e) : _jack_port (0), _last_monitor (false), _latency (0), _name (n), _flags (f)
|
Port::Port (std::string const & n, DataType t, Flags f, bool e)
|
||||||
|
: _jack_port (0)
|
||||||
|
, _last_monitor (false)
|
||||||
|
, _latency (0)
|
||||||
|
, _name (n)
|
||||||
|
, _flags (f)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Unfortunately we have to pass the DataType into this constructor so that we can
|
/* Unfortunately we have to pass the DataType into this constructor so that we can
|
||||||
create the right kind of JACK port; aside from this we'll use the virtual function type ()
|
create the right kind of JACK port; aside from this we'll use the virtual function type ()
|
||||||
to establish type. */
|
to establish type.
|
||||||
|
*/
|
||||||
|
|
||||||
assert (_name.find_first_of (':') == std::string::npos);
|
assert (_name.find_first_of (':') == std::string::npos);
|
||||||
|
|
||||||
if (e) {
|
if (e) {
|
||||||
try {
|
try {
|
||||||
|
cerr << "NEW PORT " << _name << " ext = " << e << endl;
|
||||||
do_make_external (t);
|
do_make_external (t);
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
|
|
@ -47,7 +58,7 @@ ARDOUR::Port::Port (std::string const & n, DataType t, Flags f, bool e) : _jack_
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Port destructor */
|
/** Port destructor */
|
||||||
ARDOUR::Port::~Port ()
|
Port::~Port ()
|
||||||
{
|
{
|
||||||
if (_jack_port) {
|
if (_jack_port) {
|
||||||
jack_port_unregister (_engine->jack (), _jack_port);
|
jack_port_unregister (_engine->jack (), _jack_port);
|
||||||
|
|
@ -58,28 +69,27 @@ ARDOUR::Port::~Port ()
|
||||||
* @param t Data type, so that we can call this method from the constructor.
|
* @param t Data type, so that we can call this method from the constructor.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
ARDOUR::Port::do_make_external (DataType t)
|
Port::do_make_external (DataType t)
|
||||||
{
|
{
|
||||||
if (_jack_port) {
|
if (_jack_port) {
|
||||||
/* already external */
|
/* already external */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_jack_port = jack_port_register (_engine->jack (), _name.c_str (), t.to_jack_type (), _flags, 0);
|
if ((_jack_port = jack_port_register (_engine->jack (), _name.c_str (), t.to_jack_type (), _flags, 0)) == 0) {
|
||||||
if (_jack_port == 0) {
|
|
||||||
throw std::runtime_error ("Could not register JACK port");
|
throw std::runtime_error ("Could not register JACK port");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ARDOUR::Port::make_external ()
|
Port::make_external ()
|
||||||
{
|
{
|
||||||
do_make_external (type ());
|
do_make_external (type ());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return true if this port is connected to anything */
|
/** @return true if this port is connected to anything */
|
||||||
bool
|
bool
|
||||||
ARDOUR::Port::connected () const
|
Port::connected () const
|
||||||
{
|
{
|
||||||
if (!_connections.empty ()) {
|
if (!_connections.empty ()) {
|
||||||
/* connected to a Port* */
|
/* connected to a Port* */
|
||||||
|
|
@ -94,8 +104,20 @@ ARDOUR::Port::connected () const
|
||||||
return (jack_port_connected (_jack_port) != 0);
|
return (jack_port_connected (_jack_port) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return true if this port is connected to anything via an external port */
|
||||||
|
bool
|
||||||
|
Port::externally_connected () const
|
||||||
|
{
|
||||||
|
if (_jack_port == 0) {
|
||||||
|
/* not using a JACK port, so can't be connected to anything else */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (jack_port_connected (_jack_port) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ARDOUR::Port::disconnect_all ()
|
Port::disconnect_all ()
|
||||||
{
|
{
|
||||||
/* Disconnect from Port* connections */
|
/* Disconnect from Port* connections */
|
||||||
for (std::set<Port*>::iterator i = _connections.begin (); i != _connections.end (); ++i) {
|
for (std::set<Port*>::iterator i = _connections.begin (); i != _connections.end (); ++i) {
|
||||||
|
|
@ -108,6 +130,8 @@ ARDOUR::Port::disconnect_all ()
|
||||||
jack_port_disconnect (_engine->jack(), _jack_port);
|
jack_port_disconnect (_engine->jack(), _jack_port);
|
||||||
_named_connections.clear ();
|
_named_connections.clear ();
|
||||||
|
|
||||||
|
check_buffer_status ();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,7 +139,7 @@ ARDOUR::Port::disconnect_all ()
|
||||||
* @return true if this port is connected to o, otherwise false.
|
* @return true if this port is connected to o, otherwise false.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
ARDOUR::Port::connected_to (std::string const & o) const
|
Port::connected_to (std::string const & o) const
|
||||||
{
|
{
|
||||||
std::string const full = _engine->make_port_name_non_relative (o);
|
std::string const full = _engine->make_port_name_non_relative (o);
|
||||||
std::string const shrt = _engine->make_port_name_non_relative (o);
|
std::string const shrt = _engine->make_port_name_non_relative (o);
|
||||||
|
|
@ -137,7 +161,7 @@ ARDOUR::Port::connected_to (std::string const & o) const
|
||||||
|
|
||||||
/** @param o Filled in with port full names of ports that we are connected to */
|
/** @param o Filled in with port full names of ports that we are connected to */
|
||||||
int
|
int
|
||||||
ARDOUR::Port::get_connections (std::vector<std::string> & c) const
|
Port::get_connections (std::vector<std::string> & c) const
|
||||||
{
|
{
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
|
|
@ -163,7 +187,7 @@ ARDOUR::Port::get_connections (std::vector<std::string> & c) const
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ARDOUR::Port::connect (std::string const & other)
|
Port::connect (std::string const & other)
|
||||||
{
|
{
|
||||||
/* caller must hold process lock */
|
/* caller must hold process lock */
|
||||||
|
|
||||||
|
|
@ -197,11 +221,13 @@ ARDOUR::Port::connect (std::string const & other)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_buffer_status ();
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ARDOUR::Port::disconnect (std::string const & other)
|
Port::disconnect (std::string const & other)
|
||||||
{
|
{
|
||||||
/* caller must hold process lock */
|
/* caller must hold process lock */
|
||||||
|
|
||||||
|
|
@ -227,6 +253,8 @@ ARDOUR::Port::disconnect (std::string const & other)
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
_named_connections.erase (other);
|
_named_connections.erase (other);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_buffer_status ();
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
|
|
@ -234,13 +262,13 @@ ARDOUR::Port::disconnect (std::string const & other)
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ARDOUR::Port::connected_to (Port* o) const
|
Port::connected_to (Port* o) const
|
||||||
{
|
{
|
||||||
return connected_to (o->name ());
|
return connected_to (o->name ());
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ARDOUR::Port::connect (Port* o)
|
Port::connect (Port* o)
|
||||||
{
|
{
|
||||||
/* caller must hold process lock */
|
/* caller must hold process lock */
|
||||||
|
|
||||||
|
|
@ -253,11 +281,14 @@ ARDOUR::Port::connect (Port* o)
|
||||||
_connections.insert (o);
|
_connections.insert (o);
|
||||||
o->_connections.insert (this);
|
o->_connections.insert (this);
|
||||||
|
|
||||||
|
check_buffer_status ();
|
||||||
|
o->check_buffer_status ();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ARDOUR::Port::disconnect (Port* o)
|
Port::disconnect (Port* o)
|
||||||
{
|
{
|
||||||
if (external () && o->external ()) {
|
if (external () && o->external ()) {
|
||||||
/* we're both external; try disconnecting using name */
|
/* we're both external; try disconnecting using name */
|
||||||
|
|
@ -270,17 +301,20 @@ ARDOUR::Port::disconnect (Port* o)
|
||||||
_connections.erase (o);
|
_connections.erase (o);
|
||||||
o->_connections.erase (this);
|
o->_connections.erase (this);
|
||||||
|
|
||||||
|
check_buffer_status ();
|
||||||
|
o->check_buffer_status ();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ARDOUR::Port::set_engine (AudioEngine* e)
|
Port::set_engine (AudioEngine* e)
|
||||||
{
|
{
|
||||||
_engine = e;
|
_engine = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ARDOUR::Port::ensure_monitor_input (bool yn)
|
Port::ensure_monitor_input (bool yn)
|
||||||
{
|
{
|
||||||
if (_jack_port) {
|
if (_jack_port) {
|
||||||
jack_port_ensure_monitor (_jack_port, yn);
|
jack_port_ensure_monitor (_jack_port, yn);
|
||||||
|
|
@ -288,7 +322,7 @@ ARDOUR::Port::ensure_monitor_input (bool yn)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ARDOUR::Port::monitoring_input () const
|
Port::monitoring_input () const
|
||||||
{
|
{
|
||||||
if (_jack_port) {
|
if (_jack_port) {
|
||||||
return jack_port_monitoring_input (_jack_port);
|
return jack_port_monitoring_input (_jack_port);
|
||||||
|
|
@ -298,7 +332,7 @@ ARDOUR::Port::monitoring_input () const
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ARDOUR::Port::reset ()
|
Port::reset ()
|
||||||
{
|
{
|
||||||
_last_monitor = false;
|
_last_monitor = false;
|
||||||
|
|
||||||
|
|
@ -308,7 +342,7 @@ ARDOUR::Port::reset ()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ARDOUR::Port::recompute_total_latency () const
|
Port::recompute_total_latency () const
|
||||||
{
|
{
|
||||||
#ifdef HAVE_JACK_RECOMPUTE_LATENCY
|
#ifdef HAVE_JACK_RECOMPUTE_LATENCY
|
||||||
if (_jack_port) {
|
if (_jack_port) {
|
||||||
|
|
@ -318,7 +352,7 @@ ARDOUR::Port::recompute_total_latency () const
|
||||||
}
|
}
|
||||||
|
|
||||||
nframes_t
|
nframes_t
|
||||||
ARDOUR::Port::total_latency () const
|
Port::total_latency () const
|
||||||
{
|
{
|
||||||
if (_jack_port) {
|
if (_jack_port) {
|
||||||
return jack_port_get_total_latency (_engine->jack (), _jack_port);
|
return jack_port_get_total_latency (_engine->jack (), _jack_port);
|
||||||
|
|
@ -328,7 +362,7 @@ ARDOUR::Port::total_latency () const
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ARDOUR::Port::reestablish ()
|
Port::reestablish ()
|
||||||
{
|
{
|
||||||
if (!_jack_port) {
|
if (!_jack_port) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -348,7 +382,7 @@ ARDOUR::Port::reestablish ()
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
ARDOUR::Port::reconnect ()
|
Port::reconnect ()
|
||||||
{
|
{
|
||||||
/* caller must hold process lock; intended to be used only after reestablish() */
|
/* caller must hold process lock; intended to be used only after reestablish() */
|
||||||
|
|
||||||
|
|
@ -367,7 +401,7 @@ ARDOUR::Port::reconnect ()
|
||||||
|
|
||||||
/** @param n Short name */
|
/** @param n Short name */
|
||||||
int
|
int
|
||||||
ARDOUR::Port::set_name (std::string const & n)
|
Port::set_name (std::string const & n)
|
||||||
{
|
{
|
||||||
assert (_name.find_first_of (':') == std::string::npos);
|
assert (_name.find_first_of (':') == std::string::npos);
|
||||||
|
|
||||||
|
|
@ -386,15 +420,48 @@ ARDOUR::Port::set_name (std::string const & n)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ARDOUR::Port::set_latency (nframes_t n)
|
Port::set_latency (nframes_t n)
|
||||||
{
|
{
|
||||||
_latency = n;
|
_latency = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ARDOUR::Port::request_monitor_input (bool yn)
|
Port::request_monitor_input (bool yn)
|
||||||
{
|
{
|
||||||
if (_jack_port) {
|
if (_jack_port) {
|
||||||
jack_port_request_monitor (_jack_port, yn);
|
jack_port_request_monitor (_jack_port, yn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Port::check_buffer_status ()
|
||||||
|
{
|
||||||
|
if (external() && receives_input()) {
|
||||||
|
if (!externally_connected()) {
|
||||||
|
if (!_connections.empty()) {
|
||||||
|
|
||||||
|
/* There are no external connections, so the
|
||||||
|
external port buffer will be the silent buffer. We cannot write into it.
|
||||||
|
But we have to write somewhere because there is at least one internal
|
||||||
|
connection that is supplying us with data.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!using_internal_data()) {
|
||||||
|
use_internal_data ();
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* There are no external connections and no internal ones
|
||||||
|
either, so we can revert to use the externally supplied
|
||||||
|
buffer which will be silent (whatever the semantics of
|
||||||
|
that are for a particular data type.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (using_internal_data()) {
|
||||||
|
use_external_data ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -105,13 +105,6 @@ Processor::set_placement (Placement p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
Processor::set_active (bool yn)
|
|
||||||
{
|
|
||||||
_active = yn;
|
|
||||||
ActiveChanged ();
|
|
||||||
}
|
|
||||||
|
|
||||||
XMLNode&
|
XMLNode&
|
||||||
Processor::get_state (void)
|
Processor::get_state (void)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@
|
||||||
#include <ardour/plugin_insert.h>
|
#include <ardour/plugin_insert.h>
|
||||||
#include <ardour/port_insert.h>
|
#include <ardour/port_insert.h>
|
||||||
#include <ardour/send.h>
|
#include <ardour/send.h>
|
||||||
|
#include <ardour/internal_send.h>
|
||||||
#include <ardour/session.h>
|
#include <ardour/session.h>
|
||||||
#include <ardour/utils.h>
|
#include <ardour/utils.h>
|
||||||
#include <ardour/configuration.h>
|
#include <ardour/configuration.h>
|
||||||
|
|
@ -1229,6 +1230,11 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams*
|
||||||
int
|
int
|
||||||
Route::add_processors (const ProcessorList& others, ProcessorStreams* err)
|
Route::add_processors (const ProcessorList& others, ProcessorStreams* err)
|
||||||
{
|
{
|
||||||
|
/* NOTE: this is intended to be used ONLY when copying
|
||||||
|
processors from another Route. Hence the subtle
|
||||||
|
differences between this and ::add_processor()
|
||||||
|
*/
|
||||||
|
|
||||||
ChanCount old_pmo = processor_max_outs;
|
ChanCount old_pmo = processor_max_outs;
|
||||||
|
|
||||||
if (!_session.engine().connected()) {
|
if (!_session.engine().connected()) {
|
||||||
|
|
@ -1292,7 +1298,7 @@ Route::disable_processors (Placement p)
|
||||||
|
|
||||||
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
|
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
|
||||||
if ((*i)->placement() == p) {
|
if ((*i)->placement() == p) {
|
||||||
(*i)->set_active (false);
|
(*i)->deactivate ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1308,7 +1314,7 @@ Route::disable_processors ()
|
||||||
Glib::RWLock::ReaderLock lm (_processor_lock);
|
Glib::RWLock::ReaderLock lm (_processor_lock);
|
||||||
|
|
||||||
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
|
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
|
||||||
(*i)->set_active (false);
|
(*i)->deactivate ();
|
||||||
}
|
}
|
||||||
|
|
||||||
_session.set_dirty ();
|
_session.set_dirty ();
|
||||||
|
|
@ -1325,7 +1331,7 @@ Route::disable_plugins (Placement p)
|
||||||
|
|
||||||
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
|
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
|
||||||
if (boost::dynamic_pointer_cast<PluginInsert> (*i) && (*i)->placement() == p) {
|
if (boost::dynamic_pointer_cast<PluginInsert> (*i) && (*i)->placement() == p) {
|
||||||
(*i)->set_active (false);
|
(*i)->deactivate ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1342,7 +1348,7 @@ Route::disable_plugins ()
|
||||||
|
|
||||||
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
|
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
|
||||||
if (boost::dynamic_pointer_cast<PluginInsert> (*i)) {
|
if (boost::dynamic_pointer_cast<PluginInsert> (*i)) {
|
||||||
(*i)->set_active (false);
|
(*i)->deactivate ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1367,7 +1373,7 @@ Route::ab_plugins (bool forward)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((*i)->active()) {
|
if ((*i)->active()) {
|
||||||
(*i)->set_active (false);
|
(*i)->deactivate ();
|
||||||
(*i)->set_next_ab_is_active (true);
|
(*i)->set_next_ab_is_active (true);
|
||||||
} else {
|
} else {
|
||||||
(*i)->set_next_ab_is_active (false);
|
(*i)->set_next_ab_is_active (false);
|
||||||
|
|
@ -1385,9 +1391,9 @@ Route::ab_plugins (bool forward)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((*i)->get_next_ab_is_active()) {
|
if ((*i)->get_next_ab_is_active()) {
|
||||||
(*i)->set_active (true);
|
(*i)->activate ();
|
||||||
} else {
|
} else {
|
||||||
(*i)->set_active (false);
|
(*i)->deactivate ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1602,9 +1608,11 @@ Route::_reset_processor_counts (ProcessorStreams* err)
|
||||||
|
|
||||||
} else if (boost::dynamic_pointer_cast<Send> (*r) != 0) {
|
} else if (boost::dynamic_pointer_cast<Send> (*r) != 0) {
|
||||||
++send_cnt;
|
++send_cnt;
|
||||||
|
} else if (boost::dynamic_pointer_cast<InternalSend> (*r) != 0) {
|
||||||
|
++send_cnt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (insert_cnt == 0) {
|
if (insert_cnt == 0) {
|
||||||
if (send_cnt) {
|
if (send_cnt) {
|
||||||
goto recompute;
|
goto recompute;
|
||||||
|
|
@ -1665,20 +1673,32 @@ Route::_reset_processor_counts (ProcessorStreams* err)
|
||||||
|
|
||||||
for (r = _processors.begin(); r != _processors.end(); prev = r, ++r) {
|
for (r = _processors.begin(); r != _processors.end(); prev = r, ++r) {
|
||||||
boost::shared_ptr<Send> s;
|
boost::shared_ptr<Send> s;
|
||||||
|
boost::shared_ptr<InternalSend> is;
|
||||||
|
|
||||||
if ((s = boost::dynamic_pointer_cast<Send> (*r)) != 0) {
|
if ((s = boost::dynamic_pointer_cast<Send> (*r)) != 0) {
|
||||||
|
|
||||||
|
/* don't pay any attention to send output configuration, since it doesn't
|
||||||
|
affect the route.
|
||||||
|
*/
|
||||||
|
|
||||||
if (r == _processors.begin()) {
|
if (r == _processors.begin()) {
|
||||||
s->expect_inputs (n_inputs());
|
s->expect_inputs (n_inputs());
|
||||||
} else {
|
} else {
|
||||||
s->expect_inputs ((*prev)->output_streams());
|
s->expect_inputs ((*prev)->output_streams());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if ((is = boost::dynamic_pointer_cast<InternalSend> (*r)) != 0) {
|
||||||
|
|
||||||
|
/* XXX ditto, but clean this inheritance pattern up someday soon */
|
||||||
|
|
||||||
|
if (r == _processors.begin()) {
|
||||||
|
is->expect_inputs (n_inputs());
|
||||||
|
} else {
|
||||||
|
is->expect_inputs ((*prev)->output_streams());
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* don't pay any attention to send output configuration, since it doesn't
|
|
||||||
affect the route.
|
|
||||||
*/
|
|
||||||
|
|
||||||
max_audio = max ((*r)->output_streams ().n_audio(), max_audio);
|
max_audio = max ((*r)->output_streams ().n_audio(), max_audio);
|
||||||
max_midi = max ((*r)->output_streams ().n_midi(), max_midi);
|
max_midi = max ((*r)->output_streams ().n_midi(), max_midi);
|
||||||
}
|
}
|
||||||
|
|
@ -1711,8 +1731,6 @@ Route::apply_some_processor_counts (list<ProcessorCount>& iclist)
|
||||||
|
|
||||||
ProcessorCount& pc (*i);
|
ProcessorCount& pc (*i);
|
||||||
|
|
||||||
cerr << "now applying for " << (*i).processor->name() << " in = " << pc.in.n_audio() << " out = " << pc.out.n_audio() << endl;
|
|
||||||
|
|
||||||
if (pc.processor->configure_io (pc.in, pc.out)) {
|
if (pc.processor->configure_io (pc.in, pc.out)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -1743,8 +1761,6 @@ Route::check_some_processor_counts (list<ProcessorCount>& iclist, ChanCount requ
|
||||||
|
|
||||||
for (i = iclist.begin(); i != iclist.end(); ++i, ++index) {
|
for (i = iclist.begin(); i != iclist.end(); ++i, ++index) {
|
||||||
|
|
||||||
cerr << "Checking whether " << (*i).processor->name() << " can support " << required_inputs.n_audio() << " inputs\n";
|
|
||||||
|
|
||||||
if (!(*i).processor->can_support_io_configuration (required_inputs, (*i).out)) {
|
if (!(*i).processor->can_support_io_configuration (required_inputs, (*i).out)) {
|
||||||
if (err) {
|
if (err) {
|
||||||
err->index = index;
|
err->index = index;
|
||||||
|
|
@ -1853,7 +1869,11 @@ Route::all_processors_flip ()
|
||||||
bool first_is_on = _processors.front()->active();
|
bool first_is_on = _processors.front()->active();
|
||||||
|
|
||||||
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
|
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
|
||||||
(*i)->set_active (!first_is_on);
|
if (first_is_on) {
|
||||||
|
(*i)->deactivate ();
|
||||||
|
} else {
|
||||||
|
(*i)->activate ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_session.set_dirty ();
|
_session.set_dirty ();
|
||||||
|
|
@ -1874,7 +1894,11 @@ Route::all_processors_active (Placement p, bool state)
|
||||||
|
|
||||||
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
|
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
|
||||||
if ((*i)->placement() == p) {
|
if ((*i)->placement() == p) {
|
||||||
(*i)->set_active (state);
|
if (state) {
|
||||||
|
(*i)->activate ();
|
||||||
|
} else {
|
||||||
|
(*i)->deactivate ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,7 @@ Send::set_state(const XMLNode& node)
|
||||||
if ((*niter)->name() == "IOProcessor") {
|
if ((*niter)->name() == "IOProcessor") {
|
||||||
insert_node = *niter;
|
insert_node = *niter;
|
||||||
} else if ((*niter)->name() == X_("Automation")) {
|
} else if ((*niter)->name() == X_("Automation")) {
|
||||||
_io->set_automation_state (*(*niter), Evoral::Parameter(GainAutomation));
|
// _io->set_automation_state (*(*niter), Evoral::Parameter(GainAutomation));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -165,10 +165,10 @@ Send::run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame,
|
||||||
_io->deliver_output (sendbufs, start_frame, end_frame, nframes, offset);
|
_io->deliver_output (sendbufs, start_frame, end_frame, nframes, offset);
|
||||||
|
|
||||||
if (_metering) {
|
if (_metering) {
|
||||||
if (_io->_gain == 0) {
|
if (_io->effective_gain() == 0) {
|
||||||
_io->_meter->reset();
|
_io->peak_meter().reset();
|
||||||
} else {
|
} else {
|
||||||
_io->_meter->run_in_place(_io->output_buffers(), start_frame, end_frame, nframes, offset);
|
_io->peak_meter().run_in_place(_io->output_buffers(), start_frame, end_frame, nframes, offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -176,7 +176,7 @@ Send::run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame,
|
||||||
_io->silence (nframes, offset);
|
_io->silence (nframes, offset);
|
||||||
|
|
||||||
if (_metering) {
|
if (_metering) {
|
||||||
_io->_meter->reset();
|
_io->peak_meter().reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,7 @@
|
||||||
#include <ardour/named_selection.h>
|
#include <ardour/named_selection.h>
|
||||||
#include <ardour/crossfade.h>
|
#include <ardour/crossfade.h>
|
||||||
#include <ardour/playlist.h>
|
#include <ardour/playlist.h>
|
||||||
|
#include <ardour/internal_send.h>
|
||||||
#include <ardour/click.h>
|
#include <ardour/click.h>
|
||||||
#include <ardour/data_type.h>
|
#include <ardour/data_type.h>
|
||||||
#include <ardour/buffer_set.h>
|
#include <ardour/buffer_set.h>
|
||||||
|
|
@ -1822,7 +1823,7 @@ Session::set_remote_control_ids ()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Session::RouteList
|
RouteList
|
||||||
Session::new_audio_route (int input_channels, int output_channels, uint32_t how_many)
|
Session::new_audio_route (int input_channels, int output_channels, uint32_t how_many)
|
||||||
{
|
{
|
||||||
char bus_name[32];
|
char bus_name[32];
|
||||||
|
|
@ -3685,6 +3686,8 @@ Session::add_processor (Processor* processor)
|
||||||
_plugin_inserts.insert (_plugin_inserts.begin(), plugin_insert);
|
_plugin_inserts.insert (_plugin_inserts.begin(), plugin_insert);
|
||||||
} else if ((send = dynamic_cast<Send *> (processor)) != 0) {
|
} else if ((send = dynamic_cast<Send *> (processor)) != 0) {
|
||||||
_sends.insert (_sends.begin(), send);
|
_sends.insert (_sends.begin(), send);
|
||||||
|
} else if (dynamic_cast<InternalSend *> (processor) != 0) {
|
||||||
|
/* relax */
|
||||||
} else {
|
} else {
|
||||||
fatal << _("programming error: unknown type of Insert created!") << endmsg;
|
fatal << _("programming error: unknown type of Insert created!") << endmsg;
|
||||||
/*NOTREACHED*/
|
/*NOTREACHED*/
|
||||||
|
|
@ -3710,6 +3713,8 @@ Session::remove_processor (Processor* processor)
|
||||||
}
|
}
|
||||||
} else if ((plugin_insert = dynamic_cast<PluginInsert *> (processor)) != 0) {
|
} else if ((plugin_insert = dynamic_cast<PluginInsert *> (processor)) != 0) {
|
||||||
_plugin_inserts.remove (plugin_insert);
|
_plugin_inserts.remove (plugin_insert);
|
||||||
|
} else if (dynamic_cast<InternalSend *> (processor) != 0) {
|
||||||
|
/* relax */
|
||||||
} else if ((send = dynamic_cast<Send *> (processor)) != 0) {
|
} else if ((send = dynamic_cast<Send *> (processor)) != 0) {
|
||||||
list<Send*>::iterator x = find (_sends.begin(), _sends.end(), send);
|
list<Send*>::iterator x = find (_sends.begin(), _sends.end(), send);
|
||||||
if (x != _sends.end()) {
|
if (x != _sends.end()) {
|
||||||
|
|
|
||||||
|
|
@ -151,14 +151,22 @@ PixFader::on_button_release_event (GdkEventButton* ev)
|
||||||
/* no motion - just a click */
|
/* no motion - just a click */
|
||||||
|
|
||||||
if (ev->state & Gdk::SHIFT_MASK) {
|
if (ev->state & Gdk::SHIFT_MASK) {
|
||||||
|
cerr << "SV A\n";
|
||||||
adjustment.set_value (default_value);
|
adjustment.set_value (default_value);
|
||||||
|
cerr << "SV A OUT\n";
|
||||||
} else if (ev->state & fine_scale_modifier) {
|
} else if (ev->state & fine_scale_modifier) {
|
||||||
|
cerr << "SV B\n";
|
||||||
adjustment.set_value (adjustment.get_lower());
|
adjustment.set_value (adjustment.get_lower());
|
||||||
|
cerr << "SV B OUT\n";
|
||||||
} else if ((_orien == VERT && ev_pos < span - display_span()) || (_orien == HORIZ && ev_pos > span - display_span())) {
|
} else if ((_orien == VERT && ev_pos < span - display_span()) || (_orien == HORIZ && ev_pos > span - display_span())) {
|
||||||
/* above the current display height, remember X Window coords */
|
/* above the current display height, remember X Window coords */
|
||||||
|
cerr << "SV C\n";
|
||||||
adjustment.set_value (adjustment.get_value() + adjustment.get_step_increment());
|
adjustment.set_value (adjustment.get_value() + adjustment.get_step_increment());
|
||||||
|
cerr << "SV C OUT\n";
|
||||||
} else {
|
} else {
|
||||||
|
cerr << "SV D\n";
|
||||||
adjustment.set_value (adjustment.get_value() - adjustment.get_step_increment());
|
adjustment.set_value (adjustment.get_value() - adjustment.get_step_increment());
|
||||||
|
cerr << "SV D OUT\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,8 @@ xml++.cc
|
||||||
conf = Configure(pbd)
|
conf = Configure(pbd)
|
||||||
if conf.CheckFunc('getmntent'):
|
if conf.CheckFunc('getmntent'):
|
||||||
conf.env.Append(CCFLAGS="-DHAVE_GETMNTENT")
|
conf.env.Append(CCFLAGS="-DHAVE_GETMNTENT")
|
||||||
|
if conf.CheckCHeader('execinfo.h'):
|
||||||
|
conf.env.Append(CXXFLAGS="-DHAVE_EXECINFO")
|
||||||
pbd = conf.Finish()
|
pbd = conf.Finish()
|
||||||
|
|
||||||
pbd.Merge ([ libraries['sigc2'],
|
pbd.Merge ([ libraries['sigc2'],
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ PBD::trace_twb ()
|
||||||
#ifdef HAVE_EXECINFO
|
#ifdef HAVE_EXECINFO
|
||||||
|
|
||||||
#include <execinfo.h>
|
#include <execinfo.h>
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PBD::stacktrace (std::ostream& out, int levels)
|
PBD::stacktrace (std::ostream& out, int levels)
|
||||||
|
|
|
||||||
|
|
@ -218,7 +218,7 @@ MackieControlProtocol::Sorted MackieControlProtocol::get_sorted_routes()
|
||||||
Sorted sorted;
|
Sorted sorted;
|
||||||
|
|
||||||
// fetch all routes
|
// fetch all routes
|
||||||
boost::shared_ptr<Session::RouteList> routes = session->get_routes();
|
boost::shared_ptr<RouteList> routes = session->get_routes();
|
||||||
set<uint32_t> remote_ids;
|
set<uint32_t> remote_ids;
|
||||||
|
|
||||||
// routes with remote_id 0 should never be added
|
// routes with remote_id 0 should never be added
|
||||||
|
|
@ -227,7 +227,7 @@ MackieControlProtocol::Sorted MackieControlProtocol::get_sorted_routes()
|
||||||
|
|
||||||
// sort in remote_id order, and exclude master, control and hidden routes
|
// sort in remote_id order, and exclude master, control and hidden routes
|
||||||
// and any routes that are already set.
|
// and any routes that are already set.
|
||||||
for ( Session::RouteList::iterator it = routes->begin(); it != routes->end(); ++it )
|
for (RouteList::iterator it = routes->begin(); it != routes->end(); ++it )
|
||||||
{
|
{
|
||||||
Route & route = **it;
|
Route & route = **it;
|
||||||
if (
|
if (
|
||||||
|
|
@ -1460,7 +1460,7 @@ void MackieControlProtocol::notify_parameter_changed( const char * name_str )
|
||||||
}
|
}
|
||||||
|
|
||||||
// RouteList is the set of routes that have just been added
|
// RouteList is the set of routes that have just been added
|
||||||
void MackieControlProtocol::notify_route_added( ARDOUR::Session::RouteList & rl )
|
void MackieControlProtocol::notify_route_added( ARDOUR::RouteList & rl )
|
||||||
{
|
{
|
||||||
// currently assigned banks are less than the full set of
|
// currently assigned banks are less than the full set of
|
||||||
// strips, so activate the new strip now.
|
// strips, so activate the new strip now.
|
||||||
|
|
@ -1471,7 +1471,7 @@ void MackieControlProtocol::notify_route_added( ARDOUR::Session::RouteList & rl
|
||||||
// otherwise route added, but current bank needs no updating
|
// otherwise route added, but current bank needs no updating
|
||||||
|
|
||||||
// make sure remote id changes in the new route are handled
|
// make sure remote id changes in the new route are handled
|
||||||
typedef ARDOUR::Session::RouteList ARS;
|
typedef ARDOUR::RouteList ARS;
|
||||||
for ( ARS::iterator it = rl.begin(); it != rl.end(); ++it )
|
for ( ARS::iterator it = rl.begin(); it != rl.end(); ++it )
|
||||||
{
|
{
|
||||||
connections_back = (*it)->RemoteControlIDChanged.connect( ( mem_fun (*this, &MackieControlProtocol::notify_remote_id_changed) ) );
|
connections_back = (*it)->RemoteControlIDChanged.connect( ( mem_fun (*this, &MackieControlProtocol::notify_remote_id_changed) ) );
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ class MackieControlProtocol
|
||||||
/// Signal handler from Panner::Change
|
/// Signal handler from Panner::Change
|
||||||
void notify_panner_changed( Mackie::RouteSignal *, bool force_update = true );
|
void notify_panner_changed( Mackie::RouteSignal *, bool force_update = true );
|
||||||
/// Signal handler for new routes added
|
/// Signal handler for new routes added
|
||||||
void notify_route_added( ARDOUR::Session::RouteList & );
|
void notify_route_added( ARDOUR::RouteList & );
|
||||||
/// Signal handler for Route::active_changed
|
/// Signal handler for Route::active_changed
|
||||||
void notify_active_changed( Mackie::RouteSignal * );
|
void notify_active_changed( Mackie::RouteSignal * );
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@
|
||||||
#include <ardour/filesystem_paths.h>
|
#include <ardour/filesystem_paths.h>
|
||||||
|
|
||||||
#include "osc.h"
|
#include "osc.h"
|
||||||
|
#include "osc_controllable.h"
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
|
|
@ -74,7 +75,7 @@ OSC::OSC (Session& s, uint32_t port)
|
||||||
|
|
||||||
/* catch up with existing routes */
|
/* catch up with existing routes */
|
||||||
|
|
||||||
boost::shared_ptr<Session::RouteList> rl = session->get_routes ();
|
boost::shared_ptr<RouteList> rl = session->get_routes ();
|
||||||
route_added (*(rl.get()));
|
route_added (*(rl.get()));
|
||||||
|
|
||||||
// session->RouteAdded.connect (mem_fun (*this, &OSC::route_added));
|
// session->RouteAdded.connect (mem_fun (*this, &OSC::route_added));
|
||||||
|
|
@ -562,29 +563,23 @@ OSC::catchall (const char *path, const char *types, lo_arg **argv, int argc, lo_
|
||||||
|
|
||||||
lo_message reply = lo_message_new ();
|
lo_message reply = lo_message_new ();
|
||||||
|
|
||||||
if (argc > 0) {
|
if (argc <= 0) {
|
||||||
int id = argv[0]->i;
|
|
||||||
boost::shared_ptr<Route> r = session->route_by_remote_id (id);
|
|
||||||
|
|
||||||
if (!r) {
|
|
||||||
lo_message_add_string (reply, "not found");
|
|
||||||
cerr << "no such route\n";
|
|
||||||
} else {
|
|
||||||
|
|
||||||
ListenerPair listener;
|
|
||||||
|
|
||||||
listener.first = r.get();
|
|
||||||
listener.second = lo_message_get_source (msg);
|
|
||||||
|
|
||||||
cerr << "add listener\n";
|
|
||||||
|
|
||||||
listen_to_route (listener);
|
|
||||||
|
|
||||||
lo_message_add_string (reply, "0");
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
lo_message_add_string (reply, "syntax error");
|
lo_message_add_string (reply, "syntax error");
|
||||||
|
} else {
|
||||||
|
for (int n = 0; n < argc; ++n) {
|
||||||
|
|
||||||
|
boost::shared_ptr<Route> r = session->route_by_remote_id (argv[n]->i);
|
||||||
|
|
||||||
|
if (!r) {
|
||||||
|
lo_message_add_string (reply, "not found");
|
||||||
|
cerr << "no such route\n";
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
cerr << "add listener\n";
|
||||||
|
listen_to_route (r, lo_message_get_source (msg));
|
||||||
|
lo_message_add_int32 (reply, argv[n]->i);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lo_send_message (lo_message_get_source (msg), "#reply", reply);
|
lo_send_message (lo_message_get_source (msg), "#reply", reply);
|
||||||
|
|
@ -592,17 +587,12 @@ OSC::catchall (const char *path, const char *types, lo_arg **argv, int argc, lo_
|
||||||
|
|
||||||
} else if (strcmp (path, "/routes/ignore") == 0) {
|
} else if (strcmp (path, "/routes/ignore") == 0) {
|
||||||
|
|
||||||
if (argc > 0) {
|
for (int n = 0; n < argc; ++n) {
|
||||||
int id = argv[0]->i;
|
|
||||||
boost::shared_ptr<Route> r = session->route_by_remote_id (id);
|
boost::shared_ptr<Route> r = session->route_by_remote_id (argv[n]->i);
|
||||||
|
|
||||||
if (r) {
|
if (r) {
|
||||||
ListenerPair listener;
|
end_listen (r, lo_message_get_source (msg));
|
||||||
|
|
||||||
listener.first = r.get();
|
|
||||||
listener.second = lo_message_get_source (msg);
|
|
||||||
|
|
||||||
drop_listener_pair (listener);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -611,55 +601,86 @@ OSC::catchall (const char *path, const char *types, lo_arg **argv, int argc, lo_
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
OSC::route_added (Session::RouteList& rl)
|
OSC::route_added (RouteList& rl)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
OSC::listen_to_route (const ListenerPair& lp)
|
OSC::listen_to_route (boost::shared_ptr<Route> route, lo_address addr)
|
||||||
{
|
{
|
||||||
Listeners::iterator x;
|
Controllables::iterator x;
|
||||||
bool route_exists = false;
|
bool route_exists = false;
|
||||||
|
|
||||||
cerr << "listen to route\n";
|
cerr << "listen to route\n";
|
||||||
|
|
||||||
/* check existing listener pairs to avoid duplicate listens */
|
/* avoid duplicate listens */
|
||||||
|
|
||||||
|
for (x = controllables.begin(); x != controllables.end(); ++x) {
|
||||||
|
|
||||||
|
OSCRouteControllable* rc;
|
||||||
|
|
||||||
for (x = listeners.begin(); x != listeners.end(); ++x) {
|
if ((rc = dynamic_cast<OSCRouteControllable*>(*x)) != 0) {
|
||||||
|
|
||||||
if ((*x)->route == lp.first) {
|
if (rc->route() == route) {
|
||||||
route_exists = true;
|
route_exists = true;
|
||||||
|
|
||||||
if ((*x)->addr == lp.second ) {
|
/* XXX NEED lo_address_equal() */
|
||||||
return;
|
|
||||||
|
if (rc->address() == addr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Listener* l = new Listener (lp.first, lp.second);
|
|
||||||
|
|
||||||
cerr << "listener binding to signals\n";
|
cerr << "listener binding to signals\n";
|
||||||
|
|
||||||
l->connections.push_back (lp.first->solo_changed.connect (bind (mem_fun (*this, &OSC::route_changed), RouteSolo, lp.first, lp.second)));
|
OSCControllable* c;
|
||||||
l->connections.push_back (lp.first->mute_changed.connect (bind (mem_fun (*this, &OSC::route_changed), RouteMute, lp.first, lp.second)));
|
string path;
|
||||||
l->connections.push_back (lp.first->gain_control()->Changed.connect (bind (mem_fun (*this, &OSC::route_changed_deux), RouteGain, lp.first, lp.second)));
|
|
||||||
|
path = X_("/route/solo");
|
||||||
|
c = new OSCRouteControllable (addr, path, route->solo_control(), route);
|
||||||
|
controllables.push_back (c);
|
||||||
|
|
||||||
|
path = X_("/route/mute");
|
||||||
|
c = new OSCRouteControllable (addr, path, route->mute_control(), route);
|
||||||
|
controllables.push_back (c);
|
||||||
|
|
||||||
|
path = X_("/route/gain");
|
||||||
|
c = new OSCRouteControllable (addr, path, route->gain_control(), route);
|
||||||
|
controllables.push_back (c);
|
||||||
|
|
||||||
|
cerr << "Now have " << controllables.size() << " controllables\n";
|
||||||
|
|
||||||
|
/* if there is no existing controllable related to this route, make sure we clean up
|
||||||
|
if it is ever deleted.
|
||||||
|
*/
|
||||||
|
|
||||||
if (!route_exists) {
|
if (!route_exists) {
|
||||||
l->route->GoingAway.connect (bind (mem_fun (*this, &OSC::drop_listeners_by_route), l->route));
|
route->GoingAway.connect (bind (mem_fun (*this, &OSC::drop_route), boost::weak_ptr<Route> (route)));
|
||||||
}
|
}
|
||||||
|
|
||||||
listeners.push_back (l);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
OSC::drop_listeners_by_route (Route* r)
|
OSC::drop_route (boost::weak_ptr<Route> wr)
|
||||||
{
|
{
|
||||||
Listeners::iterator x;
|
boost::shared_ptr<Route> r = wr.lock ();
|
||||||
|
|
||||||
for (x = listeners.begin(); x != listeners.end();) {
|
if (!r) {
|
||||||
if ((*x)->route == r) {
|
return;
|
||||||
delete *x;
|
}
|
||||||
x = listeners.erase (x);
|
|
||||||
|
for (Controllables::iterator x = controllables.begin(); x != controllables.end();) {
|
||||||
|
|
||||||
|
OSCRouteControllable* rc;
|
||||||
|
|
||||||
|
if ((rc = dynamic_cast<OSCRouteControllable*>(*x)) != 0) {
|
||||||
|
if (rc->route() == r) {
|
||||||
|
delete *x;
|
||||||
|
x = controllables.erase (x);
|
||||||
|
} else {
|
||||||
|
++x;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
++x;
|
++x;
|
||||||
}
|
}
|
||||||
|
|
@ -667,14 +688,22 @@ OSC::drop_listeners_by_route (Route* r)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
OSC::drop_listener_pair (const ListenerPair& lp)
|
OSC::end_listen (boost::shared_ptr<Route> r, lo_address addr)
|
||||||
{
|
{
|
||||||
Listeners::iterator x;
|
Controllables::iterator x;
|
||||||
|
|
||||||
for (x = listeners.begin(); x != listeners.end(); ++x) {
|
for (x = controllables.begin(); x != controllables.end(); ++x) {
|
||||||
if ((*x)->route == lp.first && (*x)->addr == lp.second) {
|
|
||||||
listeners.erase (x);
|
OSCRouteControllable* rc;
|
||||||
return;
|
|
||||||
|
if ((rc = dynamic_cast<OSCRouteControllable*>(*x)) != 0) {
|
||||||
|
|
||||||
|
/* XXX NEED lo_address_equal () */
|
||||||
|
|
||||||
|
if (rc->route() == r && rc->address() == addr) {
|
||||||
|
controllables.erase (x);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -692,61 +721,6 @@ OSC::session_exported( std::string path, std::string name ) {
|
||||||
lo_send( listener, "/session/exported", "ss", path.c_str(), name.c_str() );
|
lo_send( listener, "/session/exported", "ss", path.c_str(), name.c_str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
OSC::set_send_route_changes (bool yn)
|
|
||||||
{
|
|
||||||
_send_route_changes = yn;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
OSC::route_changed (void* src, RouteChangeType what, Route* r, lo_address addr)
|
|
||||||
{
|
|
||||||
route_changed_deux (what, r, addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
OSC::route_changed_deux (RouteChangeType what, Route* r, lo_address addr)
|
|
||||||
{
|
|
||||||
if (!_send_route_changes) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string prefix = _namespace_root;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
switch (what) {
|
|
||||||
|
|
||||||
case OSC::RouteSolo:
|
|
||||||
prefix += "/changed/route/solo";
|
|
||||||
ret = lo_send (addr, prefix.c_str(), "ii", r->remote_control_id(), (int) r->soloed());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OSC::RouteMute:
|
|
||||||
prefix += "/changed/route/mute";
|
|
||||||
ret = lo_send (addr, prefix.c_str(), "ii", r->remote_control_id(), (int) r->muted());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OSC::RouteGain:
|
|
||||||
prefix += "/changed/route/gain";
|
|
||||||
ret = lo_send (addr, prefix.c_str(), "if", r->remote_control_id(), r->effective_gain());
|
|
||||||
|
|
||||||
default:
|
|
||||||
error << "OSC: unhandled route change\n";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret < 0) {
|
|
||||||
ListenerPair lp;
|
|
||||||
|
|
||||||
lp.first = r;
|
|
||||||
lp.second = addr;
|
|
||||||
|
|
||||||
cerr << "Error sending to listener ... dropping\n";
|
|
||||||
drop_listener_pair (lp);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// end "Application Hook" Handlers //
|
// end "Application Hook" Handlers //
|
||||||
|
|
||||||
/* path callbacks */
|
/* path callbacks */
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2006 Paul Davis
|
* Copyright (C) 2006-2009 Paul Davis
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -25,6 +25,8 @@
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
#include <lo/lo.h>
|
#include <lo/lo.h>
|
||||||
|
|
||||||
#include <sigc++/sigc++.h>
|
#include <sigc++/sigc++.h>
|
||||||
|
|
@ -33,15 +35,17 @@
|
||||||
#include <ardour/session.h>
|
#include <ardour/session.h>
|
||||||
#include <control_protocol/control_protocol.h>
|
#include <control_protocol/control_protocol.h>
|
||||||
|
|
||||||
namespace ARDOUR {
|
class OSCControllable;
|
||||||
|
|
||||||
|
namespace ARDOUR {
|
||||||
class Session;
|
class Session;
|
||||||
class Route;
|
class Route;
|
||||||
|
}
|
||||||
|
|
||||||
class OSC : public ControlProtocol
|
class OSC : public ARDOUR::ControlProtocol
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OSC (Session&, uint32_t port);
|
OSC (ARDOUR::Session&, uint32_t port);
|
||||||
virtual ~OSC();
|
virtual ~OSC();
|
||||||
|
|
||||||
XMLNode& get_state ();
|
XMLNode& get_state ();
|
||||||
|
|
@ -53,8 +57,6 @@ class OSC : public ControlProtocol
|
||||||
bool get_feedback () const;
|
bool get_feedback () const;
|
||||||
|
|
||||||
void set_namespace_root (std::string);
|
void set_namespace_root (std::string);
|
||||||
bool send_route_changes () const { return _send_route_changes; }
|
|
||||||
void set_send_route_changes (bool yn);
|
|
||||||
|
|
||||||
int start ();
|
int start ();
|
||||||
int stop ();
|
int stop ();
|
||||||
|
|
@ -82,21 +84,12 @@ class OSC : public ControlProtocol
|
||||||
|
|
||||||
void register_callbacks ();
|
void register_callbacks ();
|
||||||
|
|
||||||
void route_added (ARDOUR::Session::RouteList&);
|
void route_added (ARDOUR::RouteList&);
|
||||||
|
|
||||||
// Handlers for "Application Hook" signals
|
// Handlers for "Application Hook" signals
|
||||||
void session_loaded (ARDOUR::Session&);
|
void session_loaded (ARDOUR::Session&);
|
||||||
void session_exported (std::string, std::string);
|
void session_exported (std::string, std::string);
|
||||||
|
|
||||||
enum RouteChangeType {
|
|
||||||
RouteSolo,
|
|
||||||
RouteMute,
|
|
||||||
RouteGain
|
|
||||||
};
|
|
||||||
|
|
||||||
void route_changed (void* ignored, RouteChangeType, ARDOUR::Route*, lo_address);
|
|
||||||
void route_changed_deux (RouteChangeType, ARDOUR::Route*, lo_address);
|
|
||||||
|
|
||||||
// end "Application Hook" handles
|
// end "Application Hook" handles
|
||||||
|
|
||||||
std::string get_server_url ();
|
std::string get_server_url ();
|
||||||
|
|
@ -173,24 +166,13 @@ class OSC : public ControlProtocol
|
||||||
int route_set_gain_abs (int rid, float level);
|
int route_set_gain_abs (int rid, float level);
|
||||||
int route_set_gain_dB (int rid, float dB);
|
int route_set_gain_dB (int rid, float dB);
|
||||||
|
|
||||||
struct Listener {
|
void listen_to_route (boost::shared_ptr<ARDOUR::Route>, lo_address);
|
||||||
Route* route;
|
void end_listen (boost::shared_ptr<ARDOUR::Route>, lo_address);
|
||||||
lo_address addr;
|
void drop_route (boost::weak_ptr<ARDOUR::Route>);
|
||||||
std::vector<sigc::connection> connections;
|
|
||||||
|
|
||||||
Listener (Route* r, lo_address a) : route (r), addr (a) {}
|
typedef std::list<OSCControllable*> Controllables;
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::pair<Route*, lo_address> ListenerPair;
|
Controllables controllables;
|
||||||
typedef std::list<Listener*> Listeners;
|
|
||||||
|
|
||||||
Listeners listeners;
|
|
||||||
|
|
||||||
void listen_to_route (const ListenerPair&);
|
|
||||||
void drop_listener_pair (const ListenerPair&);
|
|
||||||
void drop_listeners_by_route (Route*);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // ardour_osc_h
|
#endif // ardour_osc_h
|
||||||
|
|
|
||||||
|
|
@ -22,16 +22,20 @@
|
||||||
#include <pbd/error.h>
|
#include <pbd/error.h>
|
||||||
#include <pbd/xml++.h>
|
#include <pbd/xml++.h>
|
||||||
|
|
||||||
|
#include <ardour/route.h>
|
||||||
|
|
||||||
#include "osc_controllable.h"
|
#include "osc_controllable.h"
|
||||||
|
|
||||||
using namespace sigc;
|
using namespace sigc;
|
||||||
using namespace PBD;
|
using namespace PBD;
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
|
|
||||||
OSCControllable::OSCControllable (lo_address a, Controllable& c)
|
OSCControllable::OSCControllable (lo_address a, const string& p, boost::shared_ptr<Controllable> c)
|
||||||
: controllable (c)
|
: controllable (c)
|
||||||
, addr (a)
|
, addr (a)
|
||||||
|
, path (p)
|
||||||
{
|
{
|
||||||
|
c->Changed.connect (mem_fun (*this, &OSCControllable::send_change));
|
||||||
}
|
}
|
||||||
|
|
||||||
OSCControllable::~OSCControllable ()
|
OSCControllable::~OSCControllable ()
|
||||||
|
|
@ -42,7 +46,7 @@ OSCControllable::~OSCControllable ()
|
||||||
XMLNode&
|
XMLNode&
|
||||||
OSCControllable::get_state ()
|
OSCControllable::get_state ()
|
||||||
{
|
{
|
||||||
XMLNode& root (controllable.get_state());
|
XMLNode& root (controllable->get_state());
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -52,3 +56,43 @@ OSCControllable::set_state (const XMLNode& node)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
OSCControllable::send_change ()
|
||||||
|
{
|
||||||
|
lo_message msg = lo_message_new ();
|
||||||
|
|
||||||
|
lo_message_add_float (msg, (float) controllable->get_value());
|
||||||
|
|
||||||
|
/* XXX thread issues */
|
||||||
|
|
||||||
|
lo_send_message (addr, path.c_str(), msg);
|
||||||
|
lo_message_free (msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*------------------------------------------------------------*/
|
||||||
|
|
||||||
|
OSCRouteControllable::OSCRouteControllable (lo_address a, const string& p,
|
||||||
|
boost::shared_ptr<Controllable> c, boost::shared_ptr<Route> r)
|
||||||
|
: OSCControllable (a, p, c)
|
||||||
|
, _route (r)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
OSCRouteControllable::~OSCRouteControllable ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
OSCRouteControllable::send_change ()
|
||||||
|
{
|
||||||
|
lo_message msg = lo_message_new ();
|
||||||
|
|
||||||
|
lo_message_add_int32 (msg, _route->remote_control_id());
|
||||||
|
lo_message_add_float (msg, (float) controllable->get_value());
|
||||||
|
|
||||||
|
/* XXX thread issues */
|
||||||
|
|
||||||
|
cerr << "ORC: send " << path << " = " << controllable->get_value() << endl;
|
||||||
|
lo_send_message (addr, path.c_str(), msg);
|
||||||
|
lo_message_free (msg);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 1998-2006 Paul Davis
|
Copyright (C) 2009 Paul Davis
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
#define __osc_osccontrollable_h__
|
#define __osc_osccontrollable_h__
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <sigc++/sigc++.h>
|
#include <sigc++/sigc++.h>
|
||||||
#include <lo/lo.h>
|
#include <lo/lo.h>
|
||||||
|
|
||||||
|
|
@ -29,18 +29,46 @@
|
||||||
#include <pbd/stateful.h>
|
#include <pbd/stateful.h>
|
||||||
#include <ardour/types.h>
|
#include <ardour/types.h>
|
||||||
|
|
||||||
|
namespace ARDOUR {
|
||||||
|
|
||||||
|
class Route;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
class OSCControllable : public PBD::Stateful
|
class OSCControllable : public PBD::Stateful
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OSCControllable (lo_address addr, PBD::Controllable&);
|
OSCControllable (lo_address addr, const string& path, boost::shared_ptr<PBD::Controllable>);
|
||||||
virtual ~OSCControllable ();
|
virtual ~OSCControllable ();
|
||||||
|
|
||||||
|
lo_address address() const { return addr; }
|
||||||
|
|
||||||
XMLNode& get_state ();
|
XMLNode& get_state ();
|
||||||
int set_state (const XMLNode& node);
|
int set_state (const XMLNode& node);
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
PBD::Controllable& controllable;
|
boost::shared_ptr<PBD::Controllable> controllable;
|
||||||
lo_address addr;
|
lo_address addr;
|
||||||
|
string path;
|
||||||
|
|
||||||
|
virtual void send_change ();
|
||||||
|
};
|
||||||
|
|
||||||
|
class OSCRouteControllable : public OSCControllable
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
OSCRouteControllable (lo_address addr, const string& path,
|
||||||
|
boost::shared_ptr<PBD::Controllable>,
|
||||||
|
boost::shared_ptr<ARDOUR::Route>);
|
||||||
|
~OSCRouteControllable ();
|
||||||
|
|
||||||
|
boost::shared_ptr<ARDOUR::Route> route() const { return _route; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
boost::shared_ptr<ARDOUR::Route> _route;
|
||||||
|
|
||||||
|
void send_change ();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __osc_osccontrollable_h__ */
|
#endif /* __osc_osccontrollable_h__ */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue