summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/ardour_ui.cc2
-rw-r--r--gtk2_ardour/editor.h2
-rw-r--r--gtk2_ardour/editor_route_list.cc8
-rw-r--r--gtk2_ardour/export_channel_selector.cc4
-rw-r--r--gtk2_ardour/gain_meter.cc11
-rw-r--r--gtk2_ardour/mixer_ui.cc8
-rw-r--r--gtk2_ardour/mixer_ui.h2
-rw-r--r--gtk2_ardour/plugin_ui.cc6
-rw-r--r--gtk2_ardour/port_group.cc4
-rw-r--r--gtk2_ardour/port_matrix.cc4
-rw-r--r--gtk2_ardour/processor_box.cc16
-rw-r--r--gtk2_ardour/route_params_ui.cc6
-rw-r--r--gtk2_ardour/route_params_ui.h2
-rw-r--r--libs/ardour/SConscript1
-rw-r--r--libs/ardour/ardour/ardour.h3
-rw-r--r--libs/ardour/ardour/audio_buffer.h23
-rw-r--r--libs/ardour/ardour/audio_port.h6
-rw-r--r--libs/ardour/ardour/audio_track.h4
-rw-r--r--libs/ardour/ardour/automatable.h7
-rw-r--r--libs/ardour/ardour/buffer.h6
-rw-r--r--libs/ardour/ardour/buffer_set.h3
-rw-r--r--libs/ardour/ardour/io.h29
-rw-r--r--libs/ardour/ardour/io_processor.h4
-rw-r--r--libs/ardour/ardour/port.h10
-rw-r--r--libs/ardour/ardour/processor.h7
-rw-r--r--libs/ardour/ardour/session.h1
-rw-r--r--libs/ardour/ardour/types.h5
-rw-r--r--libs/ardour/audio_buffer.cc34
-rw-r--r--libs/ardour/audio_port.cc126
-rw-r--r--libs/ardour/audio_track.cc40
-rw-r--r--libs/ardour/audioengine.cc9
-rw-r--r--libs/ardour/buffer_set.cc6
-rw-r--r--libs/ardour/io.cc102
-rw-r--r--libs/ardour/io_processor.cc8
-rw-r--r--libs/ardour/port.cc123
-rw-r--r--libs/ardour/processor.cc7
-rw-r--r--libs/ardour/route.cc60
-rw-r--r--libs/ardour/send.cc10
-rw-r--r--libs/ardour/session.cc7
-rw-r--r--libs/gtkmm2ext/pixfader.cc8
-rw-r--r--libs/pbd/SConscript2
-rw-r--r--libs/pbd/stacktrace.cc1
-rw-r--r--libs/surfaces/mackie/mackie_control_protocol.cc8
-rw-r--r--libs/surfaces/mackie/mackie_control_protocol.h2
-rw-r--r--libs/surfaces/osc/osc.cc206
-rw-r--r--libs/surfaces/osc/osc.h46
-rw-r--r--libs/surfaces/osc/osc_controllable.cc48
-rw-r--r--libs/surfaces/osc/osc_controllable.h38
48 files changed, 675 insertions, 400 deletions
diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc
index e51edbb631..9298353cab 100644
--- a/gtk2_ardour/ardour_ui.cc
+++ b/gtk2_ardour/ardour_ui.cc
@@ -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)
{
list<boost::shared_ptr<AudioTrack> > tracks;
- Session::RouteList routes;
+ RouteList routes;
if (session == 0) {
warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
index aaaa7397e8..379716ed36 100644
--- a/gtk2_ardour/editor.h
+++ b/gtk2_ardour/editor.h
@@ -595,7 +595,7 @@ class Editor : public PublicEditor
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 *);
bool route_removal;
diff --git a/gtk2_ardour/editor_route_list.cc b/gtk2_ardour/editor_route_list.cc
index 52a1f62243..2847416397 100644
--- a/gtk2_ardour/editor_route_list.cc
+++ b/gtk2_ardour/editor_route_list.cc
@@ -48,7 +48,7 @@ using namespace Glib;
const char* _order_key = N_("editor");
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));
@@ -60,7 +60,7 @@ Editor::handle_new_route (Session::RouteList& routes)
route_redisplay_does_not_sync_order_keys = 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);
if (route->is_hidden()) {
@@ -592,8 +592,8 @@ struct EditorOrderRouteSorter {
void
Editor::initial_route_list_display ()
{
- boost::shared_ptr<Session::RouteList> routes = session->get_routes();
- Session::RouteList r (*routes);
+ boost::shared_ptr<RouteList> routes = session->get_routes();
+ RouteList r (*routes);
EditorOrderRouteSorter sorter;
r.sort (sorter);
diff --git a/gtk2_ardour/export_channel_selector.cc b/gtk2_ardour/export_channel_selector.cc
index f01a029c0c..62380c1604 100644
--- a/gtk2_ardour/export_channel_selector.cc
+++ b/gtk2_ardour/export_channel_selector.cc
@@ -105,14 +105,14 @@ void
PortExportChannelSelector::fill_route_list ()
{
channel_view.clear_routes ();
- Session::RouteList routes = *session->get_routes();
+ RouteList routes = *session->get_routes();
/* Add master bus and then everything else */
ARDOUR::IO * master = session->master_out().get();
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) {
continue;
}
diff --git a/gtk2_ardour/gain_meter.cc b/gtk2_ardour/gain_meter.cc
index a74df66bc0..8438147746 100644
--- a/gtk2_ardour/gain_meter.cc
+++ b/gtk2_ardour/gain_meter.cc
@@ -35,6 +35,7 @@
#include <gtkmm2ext/gtk_ui.h>
#include <midi++/manager.h>
#include <pbd/fastlog.h>
+#include <pbd/stacktrace.h>
#include "ardour_ui.h"
#include "gain_meter.h"
@@ -160,6 +161,8 @@ GainMeterBase::~GainMeterBase ()
void
GainMeterBase::set_io (boost::shared_ptr<IO> io)
{
+ cerr << this << " Clear all connections\n";
+
connections.clear ();
_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)));
gain_changed ();
@@ -371,8 +376,11 @@ GainMeterBase::show_gain ()
void
GainMeterBase::gain_adjusted ()
{
+ cerr << this << " for " << _io->name() << " GAIN ADJUSTED\n";
if (!ignore_toggle) {
+ cerr << "Set GC\n";
_io->gain_control()->set_value (slider_position_to_gain (gain_adjustment.get_value()));
+ cerr << "Set GC OUT\n";
}
show_gain ();
}
@@ -382,6 +390,9 @@ GainMeterBase::effective_gain_display ()
{
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) {
ignore_toggle = true;
gain_adjustment.set_value (value);
diff --git a/gtk2_ardour/mixer_ui.cc b/gtk2_ardour/mixer_ui.cc
index 06b30c700c..2c223f5bda 100644
--- a/gtk2_ardour/mixer_ui.cc
+++ b/gtk2_ardour/mixer_ui.cc
@@ -297,7 +297,7 @@ Mixer_UI::hide_window (GdkEventAny *ev)
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));
@@ -306,7 +306,7 @@ Mixer_UI::add_strip (Session::RouteList& routes)
no_track_list_redisplay = 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);
if (route->is_hidden()) {
@@ -885,8 +885,8 @@ struct SignalOrderRouteSorter {
void
Mixer_UI::initial_track_display ()
{
- boost::shared_ptr<Session::RouteList> routes = session->get_routes();
- Session::RouteList copy (*routes);
+ boost::shared_ptr<RouteList> routes = session->get_routes();
+ RouteList copy (*routes);
SignalOrderRouteSorter sorter;
copy.sort (sorter);
diff --git a/gtk2_ardour/mixer_ui.h b/gtk2_ardour/mixer_ui.h
index 2b48ade6e0..f5e1ae211d 100644
--- a/gtk2_ardour/mixer_ui.h
+++ b/gtk2_ardour/mixer_ui.h
@@ -120,7 +120,7 @@ class Mixer_UI : public Gtk::Window
bool strip_scroller_button_release (GdkEventButton*);
- void add_strip (ARDOUR::Session::RouteList&);
+ void add_strip (ARDOUR::RouteList&);
void remove_strip (MixerStrip *);
void hide_all_strips (bool with_select);
diff --git a/gtk2_ardour/plugin_ui.cc b/gtk2_ardour/plugin_ui.cc
index dbb5f3969e..336b7ea3df 100644
--- a/gtk2_ardour/plugin_ui.cc
+++ b/gtk2_ardour/plugin_ui.cc
@@ -429,7 +429,11 @@ PlugUIBase::bypass_toggled ()
bool x;
if ((x = bypass_button.get_active()) == insert->active()) {
- insert->set_active (!x);
+ if (x) {
+ insert->deactivate ();
+ } else {
+ insert->activate ();
+ }
}
}
diff --git a/gtk2_ardour/port_group.cc b/gtk2_ardour/port_group.cc
index af2fd24bc5..e68c8364ec 100644
--- a/gtk2_ardour/port_group.cc
+++ b/gtk2_ardour/port_group.cc
@@ -142,9 +142,9 @@ PortGroupList::gather (ARDOUR::Session& session)
/* Find the bundles for routes. We take their bundles, copy them,
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 */
boost::shared_ptr<ARDOUR::Bundle> bundle (
new ARDOUR::Bundle (
diff --git a/gtk2_ardour/port_matrix.cc b/gtk2_ardour/port_matrix.cc
index c080b3365d..55cd6a46b5 100644
--- a/gtk2_ardour/port_matrix.cc
+++ b/gtk2_ardour/port_matrix.cc
@@ -89,8 +89,8 @@ PortMatrix::routes_changed ()
i->disconnect ();
}
- boost::shared_ptr<ARDOUR::Session::RouteList> routes = _session.get_routes ();
- for (ARDOUR::Session::RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
+ boost::shared_ptr<ARDOUR::RouteList> routes = _session.get_routes ();
+ for (ARDOUR::RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
_route_connections.push_back (
(*i)->processors_changed.connect (sigc::mem_fun (*this, &PortMatrix::setup))
);
diff --git a/gtk2_ardour/processor_box.cc b/gtk2_ardour/processor_box.cc
index 0c97c59ae4..567dc2985f 100644
--- a/gtk2_ardour/processor_box.cc
+++ b/gtk2_ardour/processor_box.cc
@@ -342,7 +342,11 @@ ProcessorBox::processor_button_release_event (GdkEventButton *ev)
/* button2-click with no modifiers */
- processor->set_active (!processor->active());
+ if (processor->active()) {
+ processor->deactivate ();
+ } else {
+ processor->activate ();
+ }
ret = true;
}
@@ -396,7 +400,7 @@ ProcessorBox::use_plugins (const SelectedPlugins& plugins)
Route::ProcessorStreams err_streams;
if (Config->get_new_plugins_active()) {
- processor->set_active (true);
+ processor->activate ();
}
if (_route->add_processor (processor, &err_streams)) {
@@ -405,7 +409,7 @@ ProcessorBox::use_plugins (const SelectedPlugins& plugins)
} else {
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)));
}
@@ -545,7 +549,7 @@ ProcessorBox::send_io_finished (IOSelector::Result r, boost::weak_ptr<Processor>
case IOSelector::Accepted:
_route->add_processor (processor);
if (Profile->get_sae()) {
- processor->set_active (true);
+ processor->activate ();
}
break;
}
@@ -982,13 +986,13 @@ could not match the configuration of this track.");
void
ProcessorBox::activate_processor (boost::shared_ptr<Processor> r)
{
- r->set_active (true);
+ r->activate ();
}
void
ProcessorBox::deactivate_processor (boost::shared_ptr<Processor> r)
{
- r->set_active (false);
+ r->deactivate ();
}
void
diff --git a/gtk2_ardour/route_params_ui.cc b/gtk2_ardour/route_params_ui.cc
index 13807a1521..30a939022e 100644
--- a/gtk2_ardour/route_params_ui.cc
+++ b/gtk2_ardour/route_params_ui.cc
@@ -171,11 +171,11 @@ RouteParams_UI::~RouteParams_UI ()
}
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));
- 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);
if (route->is_hidden()) {
@@ -423,7 +423,7 @@ RouteParams_UI::set_session (Session *sess)
route_display_model->clear();
if (session) {
- boost::shared_ptr<Session::RouteList> r = session->get_routes();
+ boost::shared_ptr<RouteList> r = session->get_routes();
add_routes (*r);
session->GoingAway.connect (mem_fun(*this, &ArdourDialog::session_gone));
session->RouteAdded.connect (mem_fun(*this, &RouteParams_UI::add_routes));
diff --git a/gtk2_ardour/route_params_ui.h b/gtk2_ardour/route_params_ui.h
index e9fca333ab..a41a092440 100644
--- a/gtk2_ardour/route_params_ui.h
+++ b/gtk2_ardour/route_params_ui.h
@@ -167,7 +167,7 @@ class RouteParams_UI : public ArdourDialog
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_removed (boost::shared_ptr<ARDOUR::Route> route);
diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript
index f34dd9b078..59ffd764bc 100644
--- a/libs/ardour/SConscript
+++ b/libs/ardour/SConscript
@@ -92,6 +92,7 @@ gain.cc
gdither.cc
globals.cc
import.cc
+internal_send.cc
io.cc
io_processor.cc
jack_slave.cc
diff --git a/libs/ardour/ardour/ardour.h b/libs/ardour/ardour/ardour.h
index 635e8a31ca..7321daf097 100644
--- a/libs/ardour/ardour/ardour.h
+++ b/libs/ardour/ardour/ardour.h
@@ -42,9 +42,6 @@ namespace MIDI {
namespace ARDOUR {
class AudioEngine;
- class OSC;
-
- extern OSC* osc;
static const nframes_t max_frames = JACK_MAX_FRAMES;
extern sigc::signal<void,std::string> BootMessage;
diff --git a/libs/ardour/ardour/audio_buffer.h b/libs/ardour/ardour/audio_buffer.h
index 9a41e8e093..829288a7af 100644
--- a/libs/ardour/ardour/audio_buffer.h
+++ b/libs/ardour/ardour/audio_buffer.h
@@ -68,9 +68,14 @@ public:
/** Accumulate (add) @a len frames FROM THE START OF @a src into self at @a offset
* scaling by @a gain_coeff */
void accumulate_with_gain_from(const AudioBuffer& src, nframes_t len, nframes_t offset, gain_t gain_coeff) {
+
assert(_capacity > 0);
assert(offset + len <= _capacity);
+ if (src.silent()) {
+ return;
+ }
+
Sample* const dst_raw = _data + offset;
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
* scaling by @a 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(offset + len <= _capacity);
@@ -123,7 +129,22 @@ public:
Sample* data (nframes_t nframes, nframes_t 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;
Sample* _data; ///< Actual buffer contents
};
diff --git a/libs/ardour/ardour/audio_port.h b/libs/ardour/ardour/audio_port.h
index 339165da0f..304902bccb 100644
--- a/libs/ardour/ardour/audio_port.h
+++ b/libs/ardour/ardour/audio_port.h
@@ -51,12 +51,16 @@ class AudioPort : public Port
AudioPort (std::string const &, Flags, bool, nframes_t);
+ bool using_internal_data() const;
+ void use_internal_data ();
+ void use_external_data ();
+
private:
void mixdown (nframes_t, nframes_t, bool);
bool _has_been_mixed_down;
AudioBuffer* _buffer;
- bool _own_buffer;
+ bool _internal_buffer;
};
} // namespace ARDOUR
diff --git a/libs/ardour/ardour/audio_track.h b/libs/ardour/ardour/audio_track.h
index fe7dcb58ff..48609271d7 100644
--- a/libs/ardour/ardour/audio_track.h
+++ b/libs/ardour/ardour/audio_track.h
@@ -73,6 +73,10 @@ class AudioTrack : public Track
int deprecated_use_diskstream_connections ();
void set_state_part_two ();
void set_state_part_three ();
+
+ void catch_up_on_busses (ARDOUR::RouteList&);
+ void add_internal_send (boost::shared_ptr<ARDOUR::Route>);
+
};
} // namespace ARDOUR
diff --git a/libs/ardour/ardour/automatable.h b/libs/ardour/ardour/automatable.h
index fc61e2200d..d99960334d 100644
--- a/libs/ardour/ardour/automatable.h
+++ b/libs/ardour/ardour/automatable.h
@@ -94,15 +94,16 @@ public:
Evoral::ControlSet& data() { 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;
void can_automate(Evoral::Parameter);
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 old_set_automation_state(const XMLNode&);
diff --git a/libs/ardour/ardour/buffer.h b/libs/ardour/ardour/buffer.h
index e03489568c..02d6975fad 100644
--- a/libs/ardour/ardour/buffer.h
+++ b/libs/ardour/ardour/buffer.h
@@ -68,7 +68,7 @@ public:
* passed to the constructor must have been non-zero.
*/
virtual void resize(size_t) = 0;
-
+
/** Clear (eg zero, or empty) buffer starting at TIME @a offset */
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;
-protected:
+ protected:
Buffer(DataType type, size_t capacity)
- : _type(type), _capacity(capacity), _size(0), _silent(true)
+ : _type(type), _capacity(capacity), _size(0), _silent(true)
{}
DataType _type;
diff --git a/libs/ardour/ardour/buffer_set.h b/libs/ardour/ardour/buffer_set.h
index c750615798..3f7a6e7665 100644
--- a/libs/ardour/ardour/buffer_set.h
+++ b/libs/ardour/ardour/buffer_set.h
@@ -23,6 +23,7 @@
#include <vector>
#include <ardour/chan_count.h>
#include <ardour/data_type.h>
+#include <ardour/types.h>
namespace ARDOUR {
@@ -53,7 +54,7 @@ public:
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(DataType type, size_t num_buffers, size_t buffer_capacity);
diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h
index 2d5b55c502..32962fef0d 100644
--- a/libs/ardour/ardour/io.h
+++ b/libs/ardour/ardour/io.h
@@ -109,6 +109,8 @@ class IO : public SessionObject, public AutomatableControls, public Latent
void just_meter_input (nframes_t start_frame, nframes_t end_frame,
nframes_t nframes, nframes_t offset);
+ BufferSet& output_buffers() { return *_output_buffers; }
+
gain_t gain () const { return _desired_gain; }
virtual gain_t effective_gain () const;
@@ -121,6 +123,7 @@ class IO : public SessionObject, public AutomatableControls, public Latent
Panner& panner() { return *_panner; }
PeakMeter& peak_meter() { return *_meter; }
const Panner& panner() const { return *_panner; }
+ void reset_panner ();
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&);
static int disable_connecting (void);
-
static int enable_connecting (void);
-
static int disable_ports (void);
-
static int enable_ports (void);
-
static int disable_panners (void);
-
static int reset_panners (void);
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<int> PortsCreated;
- static void update_meters();
+ static void update_meters();
private:
-
- static sigc::signal<void> Meter;
- static Glib::StaticMutex m_meter_signal_lock;
- sigc::connection m_meter_connection;
+
+ static sigc::signal<void> Meter;
+ static Glib::StaticMutex m_meter_signal_lock;
+ sigc::connection m_meter_connection;
public:
-
+
/* automation */
struct GainControl : public AutomationControl {
@@ -292,8 +290,6 @@ class IO : public SessionObject, public AutomatableControls, public Latent
virtual void set_deferred_state() {}
- void reset_panner ();
-
virtual uint32_t pans_required() const
{ return _inputs.count().n_audio(); }
@@ -314,14 +310,11 @@ class IO : public SessionObject, public AutomatableControls, public Latent
static bool connecting_legal;
static bool ports_legal;
- BufferSet& output_buffers() { return *_output_buffers; }
-
private:
+ static bool panners_legal;
- friend class Send;
+ void copy_to_outputs (BufferSet& bufs, DataType type, nframes_t nframes, nframes_t offset);
- static bool panners_legal;
-
int connecting_became_legal ();
int panners_became_legal ();
sigc::connection connection_legal_c;
diff --git a/libs/ardour/ardour/io_processor.h b/libs/ardour/ardour/io_processor.h
index d2bd210516..3739c496c5 100644
--- a/libs/ardour/ardour/io_processor.h
+++ b/libs/ardour/ardour/io_processor.h
@@ -53,7 +53,9 @@ class IOProcessor : public Processor
{
public:
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&);
virtual ~IOProcessor ();
diff --git a/libs/ardour/ardour/port.h b/libs/ardour/ardour/port.h
index 7539aac9d5..759d532e82 100644
--- a/libs/ardour/ardour/port.h
+++ b/libs/ardour/ardour/port.h
@@ -71,6 +71,7 @@ public:
}
bool connected () const;
+ bool externally_connected () const;
int disconnect_all ();
int get_connections (std::vector<std::string> &) const;
@@ -81,7 +82,7 @@ public:
/* connection by Port* */
bool connected_to (Port *) const;
- int connect (Port *);
+ virtual int connect (Port *);
int disconnect (Port *);
void ensure_monitor_input (bool);
@@ -113,6 +114,12 @@ protected:
std::set<Port*> _connections; ///< internal Ports that we are connected to
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:
friend class AudioEngine;
@@ -130,6 +137,7 @@ private:
/// list of JACK ports that we are connected to; we only keep this around
/// so that we can implement ::reconnect ()
std::set<std::string> _named_connections;
+
};
}
diff --git a/libs/ardour/ardour/processor.h b/libs/ardour/ardour/processor.h
index 4b236d159e..da00c77dab 100644
--- a/libs/ardour/ardour/processor.h
+++ b/libs/ardour/ardour/processor.h
@@ -39,6 +39,7 @@ class XMLNode;
namespace ARDOUR {
class Session;
+class Route;
/* A mixer strip element - plugin, send, meter, etc.
*/
@@ -60,7 +61,6 @@ class Processor : public SessionObject, public AutomatableControls, public Laten
void set_placement (Placement);
bool active () const { return _active; }
- void set_active (bool yn);
bool get_next_ab_is_active () const { return _next_ab_is_active; }
void set_next_ab_is_active (bool yn) { _next_ab_is_active = yn; }
@@ -77,8 +77,8 @@ class Processor : public SessionObject, public AutomatableControls, public Laten
virtual void silence (nframes_t nframes, nframes_t offset) {}
- virtual void activate () { _active = true; ActiveChanged.emit(); }
- virtual void deactivate () { _active = false; ActiveChanged.emit(); }
+ void activate () { _active = true; ActiveChanged(); }
+ void deactivate () { _active = false; ActiveChanged(); }
virtual bool configure_io (ChanCount in, ChanCount out);
@@ -108,6 +108,7 @@ class Processor : public SessionObject, public AutomatableControls, public Laten
sigc::signal<void> PlacementChanged;
protected:
+ int _pending_active;
bool _active;
bool _next_ab_is_active;
bool _configured;
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index 1a88882eb6..7cdc11a054 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -306,7 +306,6 @@ class Session : public PBD::StatefulDestructible
uint32_t n_diskstreams() const;
typedef std::list<boost::shared_ptr<Diskstream> > DiskstreamList;
- typedef std::list<boost::shared_ptr<Route> > RouteList;
int load_routes (const XMLNode&);
boost::shared_ptr<RouteList> get_routes() const {
diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h
index cb058254bf..125c8569a8 100644
--- a/libs/ardour/ardour/types.h
+++ b/libs/ardour/ardour/types.h
@@ -51,6 +51,7 @@ namespace ARDOUR {
class Source;
class AudioSource;
+ class Route;
typedef jack_default_audio_sample_t Sample;
typedef float pan_t;
@@ -419,9 +420,11 @@ namespace ARDOUR {
typedef std::list<nframes64_t> AnalysisFeatureList;
+ typedef std::list<boost::shared_ptr<Route> > RouteList;
+
class Bundle;
typedef std::vector<boost::shared_ptr<Bundle> > BundleList;
-
+
} // namespace ARDOUR
std::istream& operator>>(std::istream& o, ARDOUR::SampleFormat& sf);
diff --git a/libs/ardour/audio_buffer.cc b/libs/ardour/audio_buffer.cc
index 915fdeb948..506b34eb04 100644
--- a/libs/ardour/audio_buffer.cc
+++ b/libs/ardour/audio_buffer.cc
@@ -29,9 +29,7 @@ static const int CPU_CACHE_ALIGN = 16; /* arguably 32 on most arches, but it mat
#endif
using namespace PBD;
-
-namespace ARDOUR {
-
+using namespace ARDOUR;
AudioBuffer::AudioBuffer(size_t capacity)
: Buffer(DataType::AUDIO, capacity)
@@ -41,6 +39,7 @@ AudioBuffer::AudioBuffer(size_t capacity)
if (_capacity > 0) {
_owns_data = true; // prevent resize() from gagging
resize (_capacity);
+ _silent = false; // force silence on the intial buffer state
silence (_capacity);
}
}
@@ -51,10 +50,28 @@ AudioBuffer::~AudioBuffer()
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
AudioBuffer::resize (size_t size)
{
- if (!_owns_data || (size < _capacity)) {
+ if (!_owns_data) {
+ return;
+ }
+
+ if (size < _capacity) {
+ _size = size;
return;
}
@@ -74,9 +91,12 @@ AudioBuffer::resize (size_t size)
CPU_CACHE_ALIGN, sizeof (Sample) * _capacity, strerror (errno)) << endmsg;
}
#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);
+}
diff --git a/libs/ardour/audio_port.cc b/libs/ardour/audio_port.cc
index 55d65d850d..0e48c2a699 100644
--- a/libs/ardour/audio_port.cc
+++ b/libs/ardour/audio_port.cc
@@ -29,9 +29,10 @@ AudioPort::AudioPort (const std::string& name, Flags flags, bool ext, nframes_t
: Port (name, DataType::AUDIO, flags, ext)
, _has_been_mixed_down (false)
, _buffer (0)
+ , _internal_buffer (false)
{
assert (name.find_first_of (':') == string::npos);
-
+
if (external ()) {
/* 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 */
_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 */
- _has_been_mixed_down = false;
+ /* For external (JACK) ports, get_buffer() must only be run
+ on outputs here in cycle_start().
- if (external ()) {
- /* external ports use JACK's memory */
- _buffer->set_data ((Sample *) jack_port_get_buffer (_jack_port, nframes), nframes + offset);
+ Inputs must be done in the correct processing order, which
+ requires interleaving with route processing. that will
+ 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 */
- if (_has_been_mixed_down) {
- return *_buffer;
- }
-
- if (receives_input ()) {
-
- /* INPUT */
+ if (receives_input () && !_has_been_mixed_down) {
- /* 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 ());
+ /* external ports use JACK's memory unless otherwise noted */
- } else {
-
- /* OUTPUT */
-
- if (!external ()) {
- /* start internal output buffers with silence */
- _buffer->silence (nframes, offset);
+ if (external()) {
+ if (!using_internal_data()) {
+ _buffer->set_data ((Sample *) jack_port_get_buffer (_jack_port, nframes) + offset, nframes);
+ } else {
+ _buffer->silence (nframes, offset);
+ }
}
-
- }
-
- if (nframes) {
- _has_been_mixed_down = true;
- }
+ mixdown (nframes, offset, !external ());
+ }
+
return *_buffer;
}
@@ -111,22 +109,46 @@ AudioPort::cycle_end (nframes_t nframes, nframes_t offset)
void
AudioPort::mixdown (nframes_t cnt, nframes_t offset, bool first_overwrite)
{
+ /* note: this is only called for input ports */
+
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);
+ }
+
+ } 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) {
- _buffer->read_from (dynamic_cast<AudioPort*>(*p)->get_audio_buffer (cnt, offset), cnt, offset);
- ++p;
+ for (; p != _connections.end (); ++p) {
+ _buffer->accumulate_from (dynamic_cast<AudioPort*>(*p)->get_audio_buffer (cnt, offset), cnt, offset);
+
+ }
}
- for (; p != _connections.end (); ++p) {
- _buffer->accumulate_from (dynamic_cast<AudioPort*>(*p)->get_audio_buffer (cnt, offset), cnt, offset);
+ /* XXX horrible heuristic designed to check that we worked the whole buffer.
+ Needs fixing but its a hard problem.
+ */
+
+ if (cnt && offset == 0) {
+ _has_been_mixed_down = true;
}
}
@@ -140,3 +162,23 @@ AudioPort::reset ()
_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 ();
+}
diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc
index ada5a183dc..5749afd265 100644
--- a/libs/ardour/audio_track.cc
+++ b/libs/ardour/audio_track.cc
@@ -40,6 +40,7 @@
#include <ardour/utils.h>
#include <ardour/buffer_set.h>
#include <ardour/audio_buffer.h>
+#include <ardour/internal_send.h>
#include "i18n.h"
using namespace std;
@@ -65,6 +66,8 @@ AudioTrack::AudioTrack (Session& sess, string name, Route::Flag flag, TrackMode
_session.add_diskstream (ds);
+ _session.RouteAdded.connect (mem_fun (*this, &AudioTrack::catch_up_on_busses));
+
set_diskstream (boost::dynamic_pointer_cast<AudioDiskstream> (ds), this);
}
@@ -72,12 +75,47 @@ AudioTrack::AudioTrack (Session& sess, const XMLNode& node)
: Track (sess, node)
{
_set_state (node, false);
+
+ _session.RouteAdded.connect (mem_fun (*this, &AudioTrack::catch_up_on_busses));
}
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
AudioTrack::set_mode (TrackMode m)
{
@@ -879,7 +917,7 @@ AudioTrack::freeze (InterThreadInfo& itt)
/* now deactivate the processor */
- processor->set_active (false);
+ processor->deactivate ();
_session.set_dirty ();
}
}
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index 4d8f18423f..27b5fcc5c5 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -348,13 +348,6 @@ AudioEngine::process_callback (nframes_t nframes)
boost::shared_ptr<Ports> p = ports.reader();
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);
}
@@ -416,10 +409,8 @@ AudioEngine::process_callback (nframes_t nframes)
// Finalize ports (ie write data if necessary)
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
-
(*i)->cycle_end (nframes, 0);
}
-
_processed_frames = next_processed_frames;
return 0;
}
diff --git a/libs/ardour/buffer_set.cc b/libs/ardour/buffer_set.cc
index 5b6f071150..09fd880451 100644
--- a/libs/ardour/buffer_set.cc
+++ b/libs/ardour/buffer_set.cc
@@ -16,6 +16,7 @@
675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <iostream>
#include <algorithm>
#include <ardour/buffer_set.h>
#include <ardour/buffer.h>
@@ -61,7 +62,7 @@ BufferSet::clear()
/** Make this BufferSet a direct mirror of a PortSet's buffers.
*/
void
-BufferSet::attach_buffers(PortSet& ports)
+BufferSet::attach_buffers(PortSet& ports, nframes_t nframes, nframes_t offset)
{
clear();
@@ -71,9 +72,8 @@ BufferSet::attach_buffers(PortSet& ports)
for (PortSet::iterator p = ports.begin(*t); p != ports.end(*t); ++p) {
assert(p->type() == *t);
- v.push_back(&(p->get_buffer(0,0)));
+ v.push_back(&(p->get_buffer(nframes, offset)));
}
-
}
_count = ports.count();
diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc
index a5a330cc36..dbe7b3c526 100644
--- a/libs/ardour/io.cc
+++ b/libs/ardour/io.cc
@@ -153,9 +153,6 @@ IO::IO (Session& s, const string& name,
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);
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));
}
- // Connect to our own PortCountChanged signal to connect output buffers
- IO::PortCountChanged.connect (mem_fun (*this, &IO::attach_buffers));
-
_session.add_controllable (_gain_control);
create_bundles_for_inputs_and_outputs ();
@@ -222,7 +216,6 @@ IO::~IO ()
delete _meter;
delete _panner;
- delete _output_buffers;
}
void
@@ -266,48 +259,61 @@ IO::deliver_output (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame,
_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
- 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);
+
} else {
- const DataType type = DataType::AUDIO;
-
- // Copy any audio 1:1 to outputs
-
- BufferSet::iterator o = output_buffers().begin(type);
- 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;
- }
- /* extra outputs get a copy of the last buffer */
+ /* do a 1:1 copy of data to output ports */
- while (o != output_buffers().end(type)) {
- o->read_from(*prev, nframes, offset);
- ++o;
+ if (bufs.count().n_audio() > 0 && _outputs.count().n_audio () > 0) {
+ copy_to_outputs (bufs, DataType::AUDIO, nframes, offset);
+ }
+ if (bufs.count().n_midi() > 0 && _outputs.count().n_midi () > 0) {
+ copy_to_outputs (bufs, DataType::MIDI, nframes, offset);
}
}
+}
- /* ********** 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
- if (bufs.count().n_midi() == 0 || output_buffers().count().n_midi () == 0) {
- return;
+ prev = i;
+ ++i;
+ ++o;
}
-
- const DataType type = DataType::MIDI;
-
- // Copy any MIDI 1:1 to outputs
- assert(bufs.count().n_midi() == output_buffers().count().n_midi());
- BufferSet::iterator o = output_buffers().begin(type);
- for (BufferSet::iterator i = bufs.begin(type); i != bufs.end(type); ++i, ++o) {
- o->read_from(*i, nframes, offset);
+
+ /* extra outputs get a copy of the last buffer */
+
+ while (o != _outputs.end(type)) {
+ Buffer& port_buffer (o->get_buffer (nframes, offset));
+ port_buffer.read_from(*prev, nframes, offset);
+ ++o;
}
}
@@ -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) {
BufferSet::iterator o = outs.begin(*t);
- for (PortSet::iterator i = _inputs.begin(*t); i != _inputs.end(*t); ++i, ++o) {
- o->read_from(i->get_buffer(nframes,offset), nframes, offset);
+ PortSet::iterator e = _inputs.end (*t);
+ 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;
}
-/** 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
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;
}
+ cerr << "set desired gain to " << val << " when curgain = " << _gain_control->get_value () << endl;
+
if (src != _gain_control.get()) {
_gain_control->set_value(val);
// 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 "";
}
+
+
diff --git a/libs/ardour/io_processor.cc b/libs/ardour/io_processor.cc
index 08530b924c..fb27ba6f54 100644
--- a/libs/ardour/io_processor.cc
+++ b/libs/ardour/io_processor.cc
@@ -43,10 +43,12 @@ using namespace ARDOUR;
using namespace PBD;
IOProcessor::IOProcessor (Session& s, const string& name, Placement p,
- int input_min, int input_max,
- int output_min, int output_max)
+ int input_min, int input_max,
+ int output_min, int output_max,
+ DataType dtype,
+ bool public_ports)
: 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;
_sort_key = 0;
diff --git a/libs/ardour/port.cc b/libs/ardour/port.cc
index b200888508..74de1922fe 100644
--- a/libs/ardour/port.cc
+++ b/libs/ardour/port.cc
@@ -25,19 +25,30 @@
#include "pbd/compose.h"
#include <stdexcept>
-ARDOUR::AudioEngine* ARDOUR::Port::_engine = 0;
+using namespace std;
+using namespace ARDOUR;
+
+AudioEngine* Port::_engine = 0;
/** @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
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);
if (e) {
try {
+ cerr << "NEW PORT " << _name << " ext = " << e << endl;
do_make_external (t);
}
catch (...) {
@@ -47,7 +58,7 @@ ARDOUR::Port::Port (std::string const & n, DataType t, Flags f, bool e) : _jack_
}
/** Port destructor */
-ARDOUR::Port::~Port ()
+Port::~Port ()
{
if (_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.
*/
void
-ARDOUR::Port::do_make_external (DataType t)
+Port::do_make_external (DataType t)
{
if (_jack_port) {
/* already external */
return;
}
- _jack_port = jack_port_register (_engine->jack (), _name.c_str (), t.to_jack_type (), _flags, 0);
- if (_jack_port == 0) {
+ if ((_jack_port = jack_port_register (_engine->jack (), _name.c_str (), t.to_jack_type (), _flags, 0)) == 0) {
throw std::runtime_error ("Could not register JACK port");
}
}
void
-ARDOUR::Port::make_external ()
+Port::make_external ()
{
do_make_external (type ());
}
/** @return true if this port is connected to anything */
bool
-ARDOUR::Port::connected () const
+Port::connected () const
{
if (!_connections.empty ()) {
/* connected to a Port* */
@@ -94,8 +104,20 @@ ARDOUR::Port::connected () const
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
-ARDOUR::Port::disconnect_all ()
+Port::disconnect_all ()
{
/* Disconnect from Port* connections */
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);
_named_connections.clear ();
+ check_buffer_status ();
+
return 0;
}
@@ -115,7 +139,7 @@ ARDOUR::Port::disconnect_all ()
* @return true if this port is connected to o, otherwise false.
*/
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 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 */
int
-ARDOUR::Port::get_connections (std::vector<std::string> & c) const
+Port::get_connections (std::vector<std::string> & c) const
{
int n = 0;
@@ -163,7 +187,7 @@ ARDOUR::Port::get_connections (std::vector<std::string> & c) const
}
int
-ARDOUR::Port::connect (std::string const & other)
+Port::connect (std::string const & other)
{
/* caller must hold process lock */
@@ -197,11 +221,13 @@ ARDOUR::Port::connect (std::string const & other)
}
}
+ check_buffer_status ();
+
return r;
}
int
-ARDOUR::Port::disconnect (std::string const & other)
+Port::disconnect (std::string const & other)
{
/* caller must hold process lock */
@@ -227,6 +253,8 @@ ARDOUR::Port::disconnect (std::string const & other)
if (r == 0) {
_named_connections.erase (other);
}
+
+ check_buffer_status ();
}
return r;
@@ -234,13 +262,13 @@ ARDOUR::Port::disconnect (std::string const & other)
bool
-ARDOUR::Port::connected_to (Port* o) const
+Port::connected_to (Port* o) const
{
return connected_to (o->name ());
}
int
-ARDOUR::Port::connect (Port* o)
+Port::connect (Port* o)
{
/* caller must hold process lock */
@@ -253,11 +281,14 @@ ARDOUR::Port::connect (Port* o)
_connections.insert (o);
o->_connections.insert (this);
+ check_buffer_status ();
+ o->check_buffer_status ();
+
return 0;
}
int
-ARDOUR::Port::disconnect (Port* o)
+Port::disconnect (Port* o)
{
if (external () && o->external ()) {
/* we're both external; try disconnecting using name */
@@ -270,17 +301,20 @@ ARDOUR::Port::disconnect (Port* o)
_connections.erase (o);
o->_connections.erase (this);
+ check_buffer_status ();
+ o->check_buffer_status ();
+
return 0;
}
void
-ARDOUR::Port::set_engine (AudioEngine* e)
+Port::set_engine (AudioEngine* e)
{
_engine = e;
}
void
-ARDOUR::Port::ensure_monitor_input (bool yn)
+Port::ensure_monitor_input (bool yn)
{
if (_jack_port) {
jack_port_ensure_monitor (_jack_port, yn);
@@ -288,7 +322,7 @@ ARDOUR::Port::ensure_monitor_input (bool yn)
}
bool
-ARDOUR::Port::monitoring_input () const
+Port::monitoring_input () const
{
if (_jack_port) {
return jack_port_monitoring_input (_jack_port);
@@ -298,7 +332,7 @@ ARDOUR::Port::monitoring_input () const
}
void
-ARDOUR::Port::reset ()
+Port::reset ()
{
_last_monitor = false;
@@ -308,7 +342,7 @@ ARDOUR::Port::reset ()
}
void
-ARDOUR::Port::recompute_total_latency () const
+Port::recompute_total_latency () const
{
#ifdef HAVE_JACK_RECOMPUTE_LATENCY
if (_jack_port) {
@@ -318,7 +352,7 @@ ARDOUR::Port::recompute_total_latency () const
}
nframes_t
-ARDOUR::Port::total_latency () const
+Port::total_latency () const
{
if (_jack_port) {
return jack_port_get_total_latency (_engine->jack (), _jack_port);
@@ -328,7 +362,7 @@ ARDOUR::Port::total_latency () const
}
int
-ARDOUR::Port::reestablish ()
+Port::reestablish ()
{
if (!_jack_port) {
return 0;
@@ -348,7 +382,7 @@ ARDOUR::Port::reestablish ()
int
-ARDOUR::Port::reconnect ()
+Port::reconnect ()
{
/* caller must hold process lock; intended to be used only after reestablish() */
@@ -367,7 +401,7 @@ ARDOUR::Port::reconnect ()
/** @param n Short name */
int
-ARDOUR::Port::set_name (std::string const & n)
+Port::set_name (std::string const & n)
{
assert (_name.find_first_of (':') == std::string::npos);
@@ -386,15 +420,48 @@ ARDOUR::Port::set_name (std::string const & n)
}
void
-ARDOUR::Port::set_latency (nframes_t n)
+Port::set_latency (nframes_t n)
{
_latency = n;
}
void
-ARDOUR::Port::request_monitor_input (bool yn)
+Port::request_monitor_input (bool yn)
{
if (_jack_port) {
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 ();
+ }
+ }
+ }
+ }
+}
diff --git a/libs/ardour/processor.cc b/libs/ardour/processor.cc
index a541ae0423..a528a4587c 100644
--- a/libs/ardour/processor.cc
+++ b/libs/ardour/processor.cc
@@ -105,13 +105,6 @@ Processor::set_placement (Placement p)
}
}
-void
-Processor::set_active (bool yn)
-{
- _active = yn;
- ActiveChanged ();
-}
-
XMLNode&
Processor::get_state (void)
{
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index fab3c085db..14a8537068 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -35,6 +35,7 @@
#include <ardour/plugin_insert.h>
#include <ardour/port_insert.h>
#include <ardour/send.h>
+#include <ardour/internal_send.h>
#include <ardour/session.h>
#include <ardour/utils.h>
#include <ardour/configuration.h>
@@ -1229,6 +1230,11 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams*
int
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;
if (!_session.engine().connected()) {
@@ -1292,7 +1298,7 @@ Route::disable_processors (Placement p)
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
if ((*i)->placement() == p) {
- (*i)->set_active (false);
+ (*i)->deactivate ();
}
}
@@ -1308,7 +1314,7 @@ Route::disable_processors ()
Glib::RWLock::ReaderLock lm (_processor_lock);
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
- (*i)->set_active (false);
+ (*i)->deactivate ();
}
_session.set_dirty ();
@@ -1325,7 +1331,7 @@ Route::disable_plugins (Placement p)
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
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) {
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()) {
- (*i)->set_active (false);
+ (*i)->deactivate ();
(*i)->set_next_ab_is_active (true);
} else {
(*i)->set_next_ab_is_active (false);
@@ -1385,9 +1391,9 @@ Route::ab_plugins (bool forward)
}
if ((*i)->get_next_ab_is_active()) {
- (*i)->set_active (true);
+ (*i)->activate ();
} 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) {
++send_cnt;
+ } else if (boost::dynamic_pointer_cast<InternalSend> (*r) != 0) {
+ ++send_cnt;
}
}
-
+
if (insert_cnt == 0) {
if (send_cnt) {
goto recompute;
@@ -1665,20 +1673,32 @@ Route::_reset_processor_counts (ProcessorStreams* err)
for (r = _processors.begin(); r != _processors.end(); prev = r, ++r) {
boost::shared_ptr<Send> s;
+ boost::shared_ptr<InternalSend> is;
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()) {
s->expect_inputs (n_inputs());
} else {
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 {
- /* 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_midi = max ((*r)->output_streams ().n_midi(), max_midi);
}
@@ -1711,8 +1731,6 @@ Route::apply_some_processor_counts (list<ProcessorCount>& iclist)
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)) {
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) {
- 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 (err) {
err->index = index;
@@ -1853,7 +1869,11 @@ Route::all_processors_flip ()
bool first_is_on = _processors.front()->active();
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 ();
@@ -1874,7 +1894,11 @@ Route::all_processors_active (Placement p, bool state)
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
if ((*i)->placement() == p) {
- (*i)->set_active (state);
+ if (state) {
+ (*i)->activate ();
+ } else {
+ (*i)->deactivate ();
+ }
}
}
diff --git a/libs/ardour/send.cc b/libs/ardour/send.cc
index 58352a5dfe..d562ddff3f 100644
--- a/libs/ardour/send.cc
+++ b/libs/ardour/send.cc
@@ -140,7 +140,7 @@ Send::set_state(const XMLNode& node)
if ((*niter)->name() == "IOProcessor") {
insert_node = *niter;
} 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);
if (_metering) {
- if (_io->_gain == 0) {
- _io->_meter->reset();
+ if (_io->effective_gain() == 0) {
+ _io->peak_meter().reset();
} 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);
if (_metering) {
- _io->_meter->reset();
+ _io->peak_meter().reset();
}
}
}
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index 59b873e87f..6e7fe3a0f6 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -72,6 +72,7 @@
#include <ardour/named_selection.h>
#include <ardour/crossfade.h>
#include <ardour/playlist.h>
+#include <ardour/internal_send.h>
#include <ardour/click.h>
#include <ardour/data_type.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)
{
char bus_name[32];
@@ -3685,6 +3686,8 @@ Session::add_processor (Processor* processor)
_plugin_inserts.insert (_plugin_inserts.begin(), plugin_insert);
} else if ((send = dynamic_cast<Send *> (processor)) != 0) {
_sends.insert (_sends.begin(), send);
+ } else if (dynamic_cast<InternalSend *> (processor) != 0) {
+ /* relax */
} else {
fatal << _("programming error: unknown type of Insert created!") << endmsg;
/*NOTREACHED*/
@@ -3710,6 +3713,8 @@ Session::remove_processor (Processor* processor)
}
} else if ((plugin_insert = dynamic_cast<PluginInsert *> (processor)) != 0) {
_plugin_inserts.remove (plugin_insert);
+ } else if (dynamic_cast<InternalSend *> (processor) != 0) {
+ /* relax */
} else if ((send = dynamic_cast<Send *> (processor)) != 0) {
list<Send*>::iterator x = find (_sends.begin(), _sends.end(), send);
if (x != _sends.end()) {
diff --git a/libs/gtkmm2ext/pixfader.cc b/libs/gtkmm2ext/pixfader.cc
index 521a6cb9ca..af2cef5678 100644
--- a/libs/gtkmm2ext/pixfader.cc
+++ b/libs/gtkmm2ext/pixfader.cc
@@ -151,14 +151,22 @@ PixFader::on_button_release_event (GdkEventButton* ev)
/* no motion - just a click */
if (ev->state & Gdk::SHIFT_MASK) {
+ cerr << "SV A\n";
adjustment.set_value (default_value);
+ cerr << "SV A OUT\n";
} else if (ev->state & fine_scale_modifier) {
+ cerr << "SV B\n";
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())) {
/* above the current display height, remember X Window coords */
+ cerr << "SV C\n";
adjustment.set_value (adjustment.get_value() + adjustment.get_step_increment());
+ cerr << "SV C OUT\n";
} else {
+ cerr << "SV D\n";
adjustment.set_value (adjustment.get_value() - adjustment.get_step_increment());
+ cerr << "SV D OUT\n";
}
}
diff --git a/libs/pbd/SConscript b/libs/pbd/SConscript
index d7981be771..5a395641ca 100644
--- a/libs/pbd/SConscript
+++ b/libs/pbd/SConscript
@@ -54,6 +54,8 @@ xml++.cc
conf = Configure(pbd)
if conf.CheckFunc('getmntent'):
conf.env.Append(CCFLAGS="-DHAVE_GETMNTENT")
+if conf.CheckCHeader('execinfo.h'):
+ conf.env.Append(CXXFLAGS="-DHAVE_EXECINFO")
pbd = conf.Finish()
pbd.Merge ([ libraries['sigc2'],
diff --git a/libs/pbd/stacktrace.cc b/libs/pbd/stacktrace.cc
index 39dd46be3d..c517967fa2 100644
--- a/libs/pbd/stacktrace.cc
+++ b/libs/pbd/stacktrace.cc
@@ -30,7 +30,6 @@ PBD::trace_twb ()
#ifdef HAVE_EXECINFO
#include <execinfo.h>
-#include <cstdlib>
void
PBD::stacktrace (std::ostream& out, int levels)
diff --git a/libs/surfaces/mackie/mackie_control_protocol.cc b/libs/surfaces/mackie/mackie_control_protocol.cc
index b29c26b0d3..18dbd28c0e 100644
--- a/libs/surfaces/mackie/mackie_control_protocol.cc
+++ b/libs/surfaces/mackie/mackie_control_protocol.cc
@@ -218,7 +218,7 @@ MackieControlProtocol::Sorted MackieControlProtocol::get_sorted_routes()
Sorted sorted;
// 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;
// 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
// 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;
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
-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
// 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
// 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 )
{
connections_back = (*it)->RemoteControlIDChanged.connect( ( mem_fun (*this, &MackieControlProtocol::notify_remote_id_changed) ) );
diff --git a/libs/surfaces/mackie/mackie_control_protocol.h b/libs/surfaces/mackie/mackie_control_protocol.h
index 7d726e70ee..456fb49485 100644
--- a/libs/surfaces/mackie/mackie_control_protocol.h
+++ b/libs/surfaces/mackie/mackie_control_protocol.h
@@ -102,7 +102,7 @@ class MackieControlProtocol
/// Signal handler from Panner::Change
void notify_panner_changed( Mackie::RouteSignal *, bool force_update = true );
/// 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
void notify_active_changed( Mackie::RouteSignal * );
diff --git a/libs/surfaces/osc/osc.cc b/libs/surfaces/osc/osc.cc
index 4503993360..d8ff311486 100644
--- a/libs/surfaces/osc/osc.cc
+++ b/libs/surfaces/osc/osc.cc
@@ -43,6 +43,7 @@
#include <ardour/filesystem_paths.h>
#include "osc.h"
+#include "osc_controllable.h"
#include "i18n.h"
using namespace ARDOUR;
@@ -74,7 +75,7 @@ OSC::OSC (Session& s, uint32_t port)
/* 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()));
// 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 ();
- 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;
+ if (argc <= 0) {
+ lo_message_add_string (reply, "syntax error");
+ } else {
+ for (int n = 0; n < argc; ++n) {
- listener.first = r.get();
- listener.second = lo_message_get_source (msg);
-
- cerr << "add listener\n";
+ boost::shared_ptr<Route> r = session->route_by_remote_id (argv[n]->i);
- listen_to_route (listener);
-
- lo_message_add_string (reply, "0");
+ 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);
+ }
}
-
- } else {
- lo_message_add_string (reply, "syntax error");
}
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) {
- if (argc > 0) {
- int id = argv[0]->i;
- boost::shared_ptr<Route> r = session->route_by_remote_id (id);
+ for (int n = 0; n < argc; ++n) {
+
+ boost::shared_ptr<Route> r = session->route_by_remote_id (argv[n]->i);
if (r) {
- ListenerPair listener;
-
- listener.first = r.get();
- listener.second = lo_message_get_source (msg);
-
- drop_listener_pair (listener);
+ end_listen (r, lo_message_get_source (msg));
}
}
}
@@ -611,55 +601,86 @@ OSC::catchall (const char *path, const char *types, lo_arg **argv, int argc, lo_
}
void
-OSC::route_added (Session::RouteList& rl)
+OSC::route_added (RouteList& rl)
{
}
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;
cerr << "listen to route\n";
- /* check existing listener pairs to avoid duplicate listens */
-
- for (x = listeners.begin(); x != listeners.end(); ++x) {
-
- if ((*x)->route == lp.first) {
- route_exists = true;
+ /* avoid duplicate listens */
+
+ for (x = controllables.begin(); x != controllables.end(); ++x) {
+
+ OSCRouteControllable* rc;
- if ((*x)->addr == lp.second ) {
- return;
+ if ((rc = dynamic_cast<OSCRouteControllable*>(*x)) != 0) {
+
+ if (rc->route() == route) {
+ route_exists = true;
+
+ /* XXX NEED lo_address_equal() */
+
+ if (rc->address() == addr) {
+ return;
+ }
}
}
}
- Listener* l = new Listener (lp.first, lp.second);
-
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)));
- l->connections.push_back (lp.first->mute_changed.connect (bind (mem_fun (*this, &OSC::route_changed), RouteMute, lp.first, lp.second)));
- l->connections.push_back (lp.first->gain_control()->Changed.connect (bind (mem_fun (*this, &OSC::route_changed_deux), RouteGain, lp.first, lp.second)));
+ OSCControllable* c;
+ string path;
+
+ 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) {
- 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
-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 ();
+
+ if (!r) {
+ return;
+ }
+
+ for (Controllables::iterator x = controllables.begin(); x != controllables.end();) {
- for (x = listeners.begin(); x != listeners.end();) {
- if ((*x)->route == r) {
- delete *x;
- x = listeners.erase (x);
+ OSCRouteControllable* rc;
+
+ if ((rc = dynamic_cast<OSCRouteControllable*>(*x)) != 0) {
+ if (rc->route() == r) {
+ delete *x;
+ x = controllables.erase (x);
+ } else {
+ ++x;
+ }
} else {
++x;
}
@@ -667,14 +688,22 @@ OSC::drop_listeners_by_route (Route* r)
}
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) {
- if ((*x)->route == lp.first && (*x)->addr == lp.second) {
- listeners.erase (x);
- return;
+ for (x = controllables.begin(); x != controllables.end(); ++x) {
+
+ OSCRouteControllable* rc;
+
+ 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() );
}
-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 //
/* path callbacks */
diff --git a/libs/surfaces/osc/osc.h b/libs/surfaces/osc/osc.h
index b2417474fc..4eebc906bb 100644
--- a/libs/surfaces/osc/osc.h
+++ b/libs/surfaces/osc/osc.h
@@ -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
* it under the terms of the GNU General Public License as published by
@@ -25,6 +25,8 @@
#include <sys/time.h>
#include <pthread.h>
+#include <boost/shared_ptr.hpp>
+
#include <lo/lo.h>
#include <sigc++/sigc++.h>
@@ -33,15 +35,17 @@
#include <ardour/session.h>
#include <control_protocol/control_protocol.h>
-namespace ARDOUR {
+class OSCControllable;
+namespace ARDOUR {
class Session;
class Route;
+}
-class OSC : public ControlProtocol
+class OSC : public ARDOUR::ControlProtocol
{
public:
- OSC (Session&, uint32_t port);
+ OSC (ARDOUR::Session&, uint32_t port);
virtual ~OSC();
XMLNode& get_state ();
@@ -53,8 +57,6 @@ class OSC : public ControlProtocol
bool get_feedback () const;
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 stop ();
@@ -82,21 +84,12 @@ class OSC : public ControlProtocol
void register_callbacks ();
- void route_added (ARDOUR::Session::RouteList&);
+ void route_added (ARDOUR::RouteList&);
// Handlers for "Application Hook" signals
void session_loaded (ARDOUR::Session&);
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
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_dB (int rid, float dB);
- struct Listener {
- Route* route;
- lo_address addr;
- std::vector<sigc::connection> connections;
-
- Listener (Route* r, lo_address a) : route (r), addr (a) {}
- };
-
- typedef std::pair<Route*, lo_address> ListenerPair;
- typedef std::list<Listener*> Listeners;
+ void listen_to_route (boost::shared_ptr<ARDOUR::Route>, lo_address);
+ void end_listen (boost::shared_ptr<ARDOUR::Route>, lo_address);
+ void drop_route (boost::weak_ptr<ARDOUR::Route>);
- Listeners listeners;
+ typedef std::list<OSCControllable*> Controllables;
- void listen_to_route (const ListenerPair&);
- void drop_listener_pair (const ListenerPair&);
- void drop_listeners_by_route (Route*);
+ Controllables controllables;
};
-}
-
#endif // ardour_osc_h
diff --git a/libs/surfaces/osc/osc_controllable.cc b/libs/surfaces/osc/osc_controllable.cc
index 12959652b8..66e70c7e7a 100644
--- a/libs/surfaces/osc/osc_controllable.cc
+++ b/libs/surfaces/osc/osc_controllable.cc
@@ -22,16 +22,20 @@
#include <pbd/error.h>
#include <pbd/xml++.h>
+#include <ardour/route.h>
+
#include "osc_controllable.h"
using namespace sigc;
using namespace PBD;
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)
, addr (a)
+ , path (p)
{
+ c->Changed.connect (mem_fun (*this, &OSCControllable::send_change));
}
OSCControllable::~OSCControllable ()
@@ -42,7 +46,7 @@ OSCControllable::~OSCControllable ()
XMLNode&
OSCControllable::get_state ()
{
- XMLNode& root (controllable.get_state());
+ XMLNode& root (controllable->get_state());
return root;
}
@@ -52,3 +56,43 @@ OSCControllable::set_state (const XMLNode& node)
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);
+}
diff --git a/libs/surfaces/osc/osc_controllable.h b/libs/surfaces/osc/osc_controllable.h
index 48183138ec..61261a8f1c 100644
--- a/libs/surfaces/osc/osc_controllable.h
+++ b/libs/surfaces/osc/osc_controllable.h
@@ -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
it under the terms of the GNU General Public License as published by
@@ -21,7 +21,7 @@
#define __osc_osccontrollable_h__
#include <string>
-
+#include <boost/shared_ptr.hpp>
#include <sigc++/sigc++.h>
#include <lo/lo.h>
@@ -29,18 +29,46 @@
#include <pbd/stateful.h>
#include <ardour/types.h>
+namespace ARDOUR {
+
+class Route;
+
+}
+
class OSCControllable : public PBD::Stateful
{
public:
- OSCControllable (lo_address addr, PBD::Controllable&);
+ OSCControllable (lo_address addr, const string& path, boost::shared_ptr<PBD::Controllable>);
virtual ~OSCControllable ();
+ lo_address address() const { return addr; }
+
XMLNode& get_state ();
int set_state (const XMLNode& node);
- private:
- PBD::Controllable& controllable;
+ protected:
+ boost::shared_ptr<PBD::Controllable> controllable;
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__ */