summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorColin Fletcher <colin.m.fletcher@googlemail.com>2014-02-24 18:11:48 +0000
committerColin Fletcher <colin.m.fletcher@googlemail.com>2014-02-24 18:11:48 +0000
commit57077093b706c5938f9fd70f70d031cae2c59217 (patch)
treea4adfba29ac589479ad1b3a5888d6e6cf0ba9c60 /libs
parenta643c9fdc08f98c7750a2474004a75e143077be9 (diff)
parentce4d125d1fd91bb3cdf82319dcce53abb35afcca (diff)
Merge branch 'master' into export-dialog
Diffstat (limited to 'libs')
-rw-r--r--libs/ardour/amp.cc23
-rw-r--r--libs/ardour/ardour/audio_buffer.h7
-rw-r--r--libs/ardour/ardour/buffer.h12
-rw-r--r--libs/ardour/ardour/file_source.h1
-rw-r--r--libs/ardour/ardour/midi_buffer.h3
-rw-r--r--libs/ardour/ardour/vestige/aeffectx.h2
-rw-r--r--libs/ardour/audio_buffer.cc11
-rw-r--r--libs/ardour/automation_control.cc20
-rw-r--r--libs/ardour/automation_watch.cc2
-rw-r--r--libs/ardour/delivery.cc2
-rw-r--r--libs/ardour/export_channel.cc2
-rw-r--r--libs/ardour/file_source.cc20
-rw-r--r--libs/ardour/internal_send.cc2
-rw-r--r--libs/ardour/lv2_evbuf.c2
-rw-r--r--libs/ardour/plugin_insert.cc32
-rw-r--r--libs/ardour/plugin_manager.cc4
-rw-r--r--libs/ardour/route.cc28
-rw-r--r--libs/ardour/session_state.cc46
-rw-r--r--libs/evoral/evoral/ControlList.hpp2
-rw-r--r--libs/evoral/src/Control.cpp11
-rw-r--r--libs/evoral/src/ControlList.cpp34
-rw-r--r--libs/panners/vbap/vbap.cc2
-rw-r--r--libs/panners/vbap/vbap_speakers.cc87
-rw-r--r--libs/surfaces/mackie/mackie_control_protocol.cc18
-rw-r--r--libs/surfaces/mackie/mackie_control_protocol.h2
-rw-r--r--libs/surfaces/mackie/strip.cc11
-rw-r--r--libs/surfaces/mackie/strip.h1
-rw-r--r--libs/surfaces/mackie/surface.cc35
28 files changed, 263 insertions, 159 deletions
diff --git a/libs/ardour/amp.cc b/libs/ardour/amp.cc
index c97d624440..132be2e1c6 100644
--- a/libs/ardour/amp.cc
+++ b/libs/ardour/amp.cc
@@ -372,19 +372,9 @@ Amp::inc_gain (gain_t factor, void *src)
}
void
-Amp::set_gain (gain_t val, void *src)
+Amp::set_gain (gain_t val, void *)
{
- val = min (val, max_gain_coefficient);
-
- if (src != _gain_control.get()) {
- _gain_control->set_value (val);
- // bit twisty, this will come back and call us again
- // (this keeps control in sync with reality)
- return;
- }
-
- _gain_control->set_double (val);
- _session.set_dirty();
+ _gain_control->set_value (val);
}
XMLNode&
@@ -414,13 +404,8 @@ Amp::set_state (const XMLNode& node, int version)
void
Amp::GainControl::set_value (double val)
{
- if (val > max_gain_coefficient) {
- val = max_gain_coefficient;
- }
-
- _amp->set_gain (val, this);
-
- AutomationControl::set_value(val);
+ AutomationControl::set_value (min (val, (double) max_gain_coefficient));
+ _amp->session().set_dirty ();
}
double
diff --git a/libs/ardour/ardour/audio_buffer.h b/libs/ardour/ardour/audio_buffer.h
index c356ed82b9..aaad961abb 100644
--- a/libs/ardour/ardour/audio_buffer.h
+++ b/libs/ardour/ardour/audio_buffer.h
@@ -62,7 +62,7 @@ public:
assert(&src != this);
assert(_capacity > 0);
assert(src.type() == DataType::AUDIO);
- assert(len <= _capacity);
+ assert(dst_offset + len <= _capacity);
assert( src_offset <= ((framecnt_t) src.capacity()-len));
memcpy(_data + dst_offset, ((const AudioBuffer&)src).data() + src_offset, sizeof(Sample) * len);
if (dst_offset == 0 && src_offset == 0 && len == _capacity) {
@@ -173,7 +173,6 @@ public:
void set_data (Sample* data, size_t size) {
assert(!_owns_data); // prevent leaks
_capacity = size;
- _size = size;
_data = data;
_silent = false;
_written = false;
@@ -185,8 +184,6 @@ public:
*/
void resize (size_t nframes);
- bool empty() const { return _size == 0; }
-
const Sample* data (framecnt_t offset = 0) const {
assert(offset <= _capacity);
return _data + offset;
@@ -198,7 +195,7 @@ public:
return _data + offset;
}
- bool check_silence (pframes_t, bool, pframes_t&) const;
+ bool check_silence (pframes_t, pframes_t&) const;
void prepare () { _written = false; _silent = false; }
bool written() const { return _written; }
diff --git a/libs/ardour/ardour/buffer.h b/libs/ardour/ardour/buffer.h
index 0d0f5d3758..87f7a90fc3 100644
--- a/libs/ardour/ardour/buffer.h
+++ b/libs/ardour/ardour/buffer.h
@@ -46,16 +46,9 @@ public:
/** Factory function */
static Buffer* create(DataType type, size_t capacity);
- /** Maximum capacity of buffer.
- * Note in some cases the entire buffer may not contain valid data, use size. */
+ /** Maximum capacity of buffer. */
size_t capacity() const { return _capacity; }
- /** Amount of valid data in buffer. Use this over capacity almost always. */
- size_t size() const { return _size; }
-
- /** Return true if the buffer contains no data, false otherwise */
- virtual bool empty() const { return _size == 0; }
-
/** Type of this buffer.
* Based on this you can static cast a Buffer* to the desired type. */
DataType type() const { return _type; }
@@ -80,12 +73,11 @@ public:
protected:
Buffer(DataType type)
- : _type(type), _capacity(0), _size(0), _silent (true)
+ : _type(type), _capacity(0), _silent (true)
{}
DataType _type;
pframes_t _capacity;
- pframes_t _size;
bool _silent;
};
diff --git a/libs/ardour/ardour/file_source.h b/libs/ardour/ardour/file_source.h
index 5898d04f0a..3d9c8c623f 100644
--- a/libs/ardour/ardour/file_source.h
+++ b/libs/ardour/ardour/file_source.h
@@ -74,6 +74,7 @@ public:
void inc_use_count ();
bool removable () const;
+ bool is_stub () const;
const std::string& origin() const { return _origin; }
diff --git a/libs/ardour/ardour/midi_buffer.h b/libs/ardour/ardour/midi_buffer.h
index 781396a598..c67eef178a 100644
--- a/libs/ardour/ardour/midi_buffer.h
+++ b/libs/ardour/ardour/midi_buffer.h
@@ -48,6 +48,8 @@ public:
uint8_t* reserve(TimeType time, size_t size);
void resize(size_t);
+ size_t size() const { return _size; }
+ bool empty() const { return _size == 0; }
bool merge_in_place(const MidiBuffer &other);
@@ -159,6 +161,7 @@ private:
friend class iterator_base< const MidiBuffer, const Evoral::MIDIEvent<TimeType> >;
uint8_t* _data; ///< timestamp, event, timestamp, event, ...
+ pframes_t _size;
};
diff --git a/libs/ardour/ardour/vestige/aeffectx.h b/libs/ardour/ardour/vestige/aeffectx.h
index bd2e3a1479..4007ecf5ef 100644
--- a/libs/ardour/ardour/vestige/aeffectx.h
+++ b/libs/ardour/ardour/vestige/aeffectx.h
@@ -270,8 +270,6 @@ typedef struct _VstTimeInfo
} VstTimeInfo;
-typedef struct _VstTimeInfo VstTimeInfo;
-
typedef intptr_t (* audioMasterCallback) (AEffect *, int32_t, int32_t, intptr_t, void *, float);
#endif
diff --git a/libs/ardour/audio_buffer.cc b/libs/ardour/audio_buffer.cc
index aa4f64755a..de2c1ddf00 100644
--- a/libs/ardour/audio_buffer.cc
+++ b/libs/ardour/audio_buffer.cc
@@ -57,12 +57,6 @@ AudioBuffer::resize (size_t size)
if (_data && size < _capacity) {
/* buffer is already large enough */
-
- if (size < _size) {
- /* truncate */
- _size = size;
- }
-
return;
}
@@ -71,14 +65,13 @@ AudioBuffer::resize (size_t size)
cache_aligned_malloc ((void**) &_data, sizeof (Sample) * size);
_capacity = size;
- _size = 0;
_silent = false;
}
bool
-AudioBuffer::check_silence (pframes_t nframes, bool wholebuffer, pframes_t& n) const
+AudioBuffer::check_silence (pframes_t nframes, pframes_t& n) const
{
- for (n = 0; (wholebuffer || n < _size) && n < nframes; ++n) {
+ for (n = 0; n < nframes; ++n) {
if (_data[n] != Sample (0)) {
return false;
}
diff --git a/libs/ardour/automation_control.cc b/libs/ardour/automation_control.cc
index 2586a14b58..355b0176ce 100644
--- a/libs/ardour/automation_control.cc
+++ b/libs/ardour/automation_control.cc
@@ -117,15 +117,23 @@ AutomationControl::set_automation_style (AutoStyle as)
void
AutomationControl::start_touch(double when)
{
- set_touching (true);
- alist()->start_touch(when);
- AutomationWatch::instance().add_automation_watch (shared_from_this());
+ if (!touching()) {
+ if (alist()->automation_state() == Touch) {
+ alist()->start_touch (when);
+ AutomationWatch::instance().add_automation_watch (shared_from_this());
+ }
+ set_touching (true);
+ }
}
void
AutomationControl::stop_touch(bool mark, double when)
{
- set_touching (false);
- alist()->stop_touch (mark, when);
- AutomationWatch::instance().remove_automation_watch (shared_from_this());
+ if (touching()) {
+ set_touching (false);
+ if (alist()->automation_state() == Touch) {
+ alist()->stop_touch (mark, when);
+ AutomationWatch::instance().remove_automation_watch (shared_from_this());
+ }
+ }
}
diff --git a/libs/ardour/automation_watch.cc b/libs/ardour/automation_watch.cc
index 16e10c95f9..87ac08abc2 100644
--- a/libs/ardour/automation_watch.cc
+++ b/libs/ardour/automation_watch.cc
@@ -122,7 +122,7 @@ AutomationWatch::timer ()
for (AutomationWatches::iterator aw = automation_watches.begin(); aw != automation_watches.end(); ++aw) {
if ((*aw)->alist()->automation_write()) {
- (*aw)->list()->add (time, (*aw)->user_double());
+ (*aw)->list()->add (time, (*aw)->user_double(), true);
}
}
}
diff --git a/libs/ardour/delivery.cc b/libs/ardour/delivery.cc
index 4a392a8145..8c12d44e51 100644
--- a/libs/ardour/delivery.cc
+++ b/libs/ardour/delivery.cc
@@ -397,7 +397,7 @@ Delivery::reset_panner ()
if (panners_legal) {
if (!_no_panner_reset) {
- if (_panshell && _role != Insert) {
+ if (_panshell && _role != Insert && _role != Listen) {
_panshell->configure_io (ChanCount (DataType::AUDIO, pans_required()), ChanCount (DataType::AUDIO, pan_outs()));
}
}
diff --git a/libs/ardour/export_channel.cc b/libs/ardour/export_channel.cc
index c67f33bb91..0e029a01f7 100644
--- a/libs/ardour/export_channel.cc
+++ b/libs/ardour/export_channel.cc
@@ -239,7 +239,7 @@ RouteExportChannel::read (Sample const *& data, framecnt_t frames) const
{
assert(processor);
AudioBuffer const & buffer = processor->get_capture_buffers().get_audio (channel);
- assert (frames <= (framecnt_t) buffer.size());
+ assert (frames <= (framecnt_t) buffer.capacity());
data = buffer.data();
}
diff --git a/libs/ardour/file_source.cc b/libs/ardour/file_source.cc
index 0921498186..c6f3a9cd5d 100644
--- a/libs/ardour/file_source.cc
+++ b/libs/ardour/file_source.cc
@@ -101,7 +101,7 @@ FileSource::removable () const
{
bool r = ((_flags & Removable)
&& ((_flags & RemoveAtDestroy) ||
- ((_flags & RemovableIfEmpty) && empty() == 0)));
+ ((_flags & RemovableIfEmpty) && empty())));
return r;
}
@@ -589,3 +589,21 @@ FileSource::inc_use_count ()
Source::inc_use_count ();
}
+bool
+FileSource::is_stub () const
+{
+ if (!empty()) {
+ return false;
+ }
+
+ if (!removable()) {
+ return false;
+ }
+
+ if (Glib::file_test (_path, Glib::FILE_TEST_EXISTS)) {
+ return false;
+ }
+
+ return true;
+}
+
diff --git a/libs/ardour/internal_send.cc b/libs/ardour/internal_send.cc
index 1d4e18d06e..17a3ca1f42 100644
--- a/libs/ardour/internal_send.cc
+++ b/libs/ardour/internal_send.cc
@@ -129,7 +129,7 @@ InternalSend::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame
// we have to copy the input, because we may alter the buffers with the amp
// in-place, which a send must never do.
- if (_panshell && !_panshell->bypassed()) {
+ if (_panshell && !_panshell->bypassed() && role() != Listen) {
_panshell->run (bufs, mixbufs, start_frame, end_frame, nframes);
} else {
if (role() == Listen) {
diff --git a/libs/ardour/lv2_evbuf.c b/libs/ardour/lv2_evbuf.c
index 8942d19a9b..f0e62d9b65 100644
--- a/libs/ardour/lv2_evbuf.c
+++ b/libs/ardour/lv2_evbuf.c
@@ -203,7 +203,7 @@ lv2_evbuf_get(LV2_Evbuf_Iterator iter,
switch (iter.evbuf->type) {
case LV2_EVBUF_EVENT:
ebuf = &iter.evbuf->buf.event;
- ev = (LV2_Event*)ebuf->data + iter.offset;
+ ev = (LV2_Event*)((char*)ebuf->data + iter.offset);
*frames = ev->frames;
*subframes = ev->subframes;
*type = ev->type;
diff --git a/libs/ardour/plugin_insert.cc b/libs/ardour/plugin_insert.cc
index f2689bf998..2f90017498 100644
--- a/libs/ardour/plugin_insert.cc
+++ b/libs/ardour/plugin_insert.cc
@@ -464,39 +464,31 @@ PluginInsert::run (BufferSet& bufs, framepos_t /*start_frame*/, framepos_t /*end
}
} else {
- if (has_no_audio_inputs()) {
+ uint32_t in = input_streams ().n_audio ();
+ uint32_t out = output_streams().n_audio ();
+
+ if (has_no_audio_inputs() || in == 0) {
/* silence all (audio) outputs. Should really declick
* at the transitions of "active"
*/
- uint32_t out = output_streams().n_audio ();
-
for (uint32_t n = 0; n < out; ++n) {
bufs.get_audio (n).silence (nframes);
}
- bufs.count().set_audio (out);
-
- } else {
-
- /* does this need to be done with MIDI? it appears not */
+ } else if (out > in) {
- uint32_t in = input_streams ().n_audio ();
- uint32_t out = output_streams().n_audio ();
+ /* not active, but something has make up for any channel count increase */
- if (out > in) {
-
- /* not active, but something has make up for any channel count increase */
-
- // TODO: option round-robin (n % in) or silence additional buffers ??
- for (uint32_t n = in; n < out; ++n) {
- bufs.get_audio(n).read_from(bufs.get_audio(in - 1), nframes);
- }
+ // TODO: option round-robin (n % in) or silence additional buffers ??
+ // for now , simply replicate last buffer
+ for (uint32_t n = in; n < out; ++n) {
+ bufs.get_audio(n).read_from(bufs.get_audio(in - 1), nframes);
}
-
- bufs.count().set_audio (out);
}
+
+ bufs.count().set_audio (out);
}
_active = _pending_active;
diff --git a/libs/ardour/plugin_manager.cc b/libs/ardour/plugin_manager.cc
index 90522a7e06..df1b7fc441 100644
--- a/libs/ardour/plugin_manager.cc
+++ b/libs/ardour/plugin_manager.cc
@@ -646,7 +646,9 @@ PluginManager::lxvst_refresh ()
}
if (lxvst_path.length() == 0) {
- lxvst_path = "/usr/local/lib64/lxvst:/usr/local/lib/lxvst:/usr/lib64/lxvst:/usr/lib/lxvst";
+ lxvst_path = "/usr/local/lib64/lxvst:/usr/local/lib/lxvst:/usr/lib64/lxvst:/usr/lib/lxvst:"
+ "/usr/local/lib64/linux_vst:/usr/local/lib/linux_vst:/usr/lib64/linux_vst:/usr/lib/linux_vst:"
+ "/usr/lib/vst:/usr/local/lib/vst";
}
lxvst_discover_from_path (lxvst_path);
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index 9e649362ee..71af69fdee 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -419,6 +419,9 @@ Route::process_output_buffers (BufferSet& bufs,
framepos_t start_frame, framepos_t end_frame, pframes_t nframes,
int declick, bool gain_automation_ok)
{
+ /* Caller must hold process lock */
+ assert (!AudioEngine::instance()->process_lock().trylock());
+
Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
assert(lm.locked());
@@ -1382,7 +1385,16 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
{
// TODO once the export point can be configured properly, do something smarter here
if (processor == _capturing_processor) {
+ Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock (), Glib::Threads::NOT_LOCK);
+ if (need_process_lock) {
+ lx.acquire();
+ }
+
_capturing_processor.reset();
+
+ if (need_process_lock) {
+ lx.release();
+ }
}
/* these can never be removed */
@@ -1402,7 +1414,12 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
if (need_process_lock) {
lx.acquire();
}
- Glib::Threads::RWLock::WriterLock lm (_processor_lock);
+
+ /* Caller must hold process lock */
+ assert (!AudioEngine::instance()->process_lock().trylock());
+
+ Glib::Threads::RWLock::WriterLock lm (_processor_lock); // XXX deadlock after export
+
ProcessorState pstate (this);
ProcessorList::iterator i;
@@ -3062,6 +3079,7 @@ Route::set_meter_point (MeterPoint p, bool force)
bool meter_was_visible_to_user = _meter->display_to_user ();
{
+ Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
Glib::Threads::RWLock::WriterLock lm (_processor_lock);
maybe_note_meter_position ();
@@ -3147,12 +3165,16 @@ Route::listen_position_changed ()
boost::shared_ptr<CapturingProcessor>
Route::add_export_point()
{
+ Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
if (!_capturing_processor) {
+ lm.release();
+ Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
+ Glib::Threads::RWLock::WriterLock lw (_processor_lock);
_capturing_processor.reset (new CapturingProcessor (_session));
_capturing_processor->activate ();
- configure_processors (0);
+ configure_processors_unlocked (0);
}
@@ -4132,7 +4154,7 @@ Route::non_realtime_locate (framepos_t pos)
{
//Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
- Glib::Threads::RWLock::WriterLock lm (_processor_lock);
+ Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
(*i)->transport_located (pos);
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index f3ad9d66dd..ffbe55afbf 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -136,13 +136,21 @@ Session::pre_engine_init (string fullpath)
/* discover canonical fullpath */
char buf[PATH_MAX+1];
- if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) {
- error << string_compose(_("Could not use path %1 (%2)"), buf, strerror(errno)) << endmsg;
- destroy ();
- throw failed_constructor();
- }
- _path = string(buf);
+ if (!realpath (fullpath.c_str(), buf)) {
+ if (errno == ENOENT) {
+ /* fullpath does not exist yet, so realpath() returned
+ * ENOENT. Just use it as-is
+ */
+ _path = fullpath;
+ } else {
+ error << string_compose(_("Could not use path %1 (%2)"), buf, strerror(errno)) << endmsg;
+ destroy ();
+ throw failed_constructor();
+ }
+ } else {
+ _path = string(buf);
+ }
/* we require _path to end with a dir separator */
@@ -2692,19 +2700,23 @@ Session::cleanup_sources (CleanupReport& rep)
++tmp;
if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
- if (playlists->source_use_count (fs) != 0) {
- all_sources.insert (fs->path());
- } else {
- /* we might not remove this source from disk, because it may be used
- by other snapshots, but its not being used in this version
- so lets get rid of it now, along with any representative regions
- in the region list.
- */
+ if (!fs->is_stub()) {
- RegionFactory::remove_regions_using_source (i->second);
- sources.erase (i);
- }
+ if (playlists->source_use_count (fs) != 0) {
+ all_sources.insert (fs->path());
+ } else {
+
+ /* we might not remove this source from disk, because it may be used
+ by other snapshots, but its not being used in this version
+ so lets get rid of it now, along with any representative regions
+ in the region list.
+ */
+
+ RegionFactory::remove_regions_using_source (i->second);
+ sources.erase (i);
+ }
+ }
}
i = tmp;
diff --git a/libs/evoral/evoral/ControlList.hpp b/libs/evoral/evoral/ControlList.hpp
index 967e08d619..5f1a8d3a75 100644
--- a/libs/evoral/evoral/ControlList.hpp
+++ b/libs/evoral/evoral/ControlList.hpp
@@ -115,7 +115,7 @@ public:
virtual bool clamp_value (double& /*when*/, double& /*value*/) const { return true; }
- virtual void add (double when, double value);
+ virtual void add (double when, double value, bool with_guards=true);
void fast_simple_add (double when, double value);
void erase_range (double start, double end);
diff --git a/libs/evoral/src/Control.cpp b/libs/evoral/src/Control.cpp
index bb272ea8b3..480d027ccc 100644
--- a/libs/evoral/src/Control.cpp
+++ b/libs/evoral/src/Control.cpp
@@ -17,6 +17,9 @@
*/
#include <iostream>
+
+#include "pbd/stacktrace.h"
+
#include "evoral/Control.hpp"
#include "evoral/ControlList.hpp"
@@ -49,9 +52,13 @@ void
Control::set_double (double value, double frame, bool to_list)
{
_user_value = value;
+
+ /* if we're in a write pass, the automation watcher will determine the
+ values and add them to the list, so we we don't need to bother.
+ */
- if (to_list) {
- _list->add (frame, value);
+ if (to_list && !_list->in_write_pass()) {
+ _list->add (frame, value, false);
}
}
diff --git a/libs/evoral/src/ControlList.cpp b/libs/evoral/src/ControlList.cpp
index a095daa135..f34bfa3faf 100644
--- a/libs/evoral/src/ControlList.cpp
+++ b/libs/evoral/src/ControlList.cpp
@@ -342,21 +342,25 @@ ControlList::start_write_pass (double when)
{
Glib::Threads::Mutex::Lock lm (_lock);
+ DEBUG_TRACE (DEBUG::ControlList, string_compose ("%1: setup write pass @ %2\n", this, when));
+
new_write_pass = true;
did_write_during_pass = false;
insert_position = when;
-
+
/* leave the insert iterator invalid, so that we will do the lookup
of where it should be in a "lazy" way - deferring it until
we actually add the first point (which may never happen).
*/
-
+
unlocked_invalidate_insert_iterator ();
}
void
ControlList::write_pass_finished (double /*when*/)
{
+ DEBUG_TRACE (DEBUG::ControlList, "write pass finished\n");
+
if (did_write_during_pass) {
thin ();
did_write_during_pass = false;
@@ -367,7 +371,9 @@ ControlList::write_pass_finished (double /*when*/)
void
ControlList::set_in_write_pass (bool yn, bool add_point, double when)
-{
+{
+ DEBUG_TRACE (DEBUG::ControlList, string_compose ("now in write pass @ %1, add point ? %2\n", when, add_point));
+
_in_write_pass = yn;
if (yn && add_point) {
@@ -381,8 +387,6 @@ ControlList::add_guard_point (double when)
ControlEvent cp (when, 0.0);
most_recent_insert_iterator = lower_bound (_events.begin(), _events.end(), &cp, time_comparator);
- DEBUG_TRACE (DEBUG::ControlList, string_compose ("@%1 ADD GUARD POINT @ %2looked up insert iterator for new write pass\n", this, when));
-
double eval_value = unlocked_eval (insert_position);
if (most_recent_insert_iterator == _events.end()) {
@@ -437,7 +441,7 @@ ControlList::in_write_pass () const
}
void
-ControlList::add (double when, double value)
+ControlList::add (double when, double value, bool with_guards)
{
/* this is for making changes from some kind of user interface or
control surface (GUI, MIDI, OSC etc)
@@ -447,8 +451,8 @@ ControlList::add (double when, double value)
return;
}
- DEBUG_TRACE (DEBUG::ControlList, string_compose ("@%1 add %2 at %3 w/erase = %4 at end ? %5\n",
- this, value, when, _in_write_pass, (most_recent_insert_iterator == _events.end())));
+ DEBUG_TRACE (DEBUG::ControlList, string_compose ("@%1 add %2 at %3 w/erase = %4 (new ? %6) at end ? %5\n",
+ this, value, when, _in_write_pass, (most_recent_insert_iterator == _events.end()), new_write_pass));
{
Glib::Threads::Mutex::Lock lm (_lock);
ControlEvent cp (when, 0.0f);
@@ -460,7 +464,7 @@ ControlList::add (double when, double value)
* add an "anchor" point there.
*/
- if (when > 1) {
+ if (when >= 1) {
_events.insert (_events.end(), new ControlEvent (0, _default_value));
DEBUG_TRACE (DEBUG::ControlList, string_compose ("@%1 added default value %2 at zero\n", this, _default_value));
}
@@ -468,8 +472,10 @@ ControlList::add (double when, double value)
if (_in_write_pass && new_write_pass) {
- add_guard_point (insert_position);
- did_write_during_pass = true;
+ if (with_guards) {
+ add_guard_point (insert_position);
+ did_write_during_pass = true;
+ }
} else if (most_recent_insert_iterator == _events.end() || when > (*most_recent_insert_iterator)->when) {
@@ -492,7 +498,7 @@ ControlList::add (double when, double value)
++most_recent_insert_iterator;
}
- if (most_recent_insert_iterator != _events.end()) {
+ if (with_guards && most_recent_insert_iterator != _events.end()) {
if ((*most_recent_insert_iterator)->when - when > 64) {
/* next control point is some
* distance from where our new
@@ -631,7 +637,7 @@ ControlList::add (double when, double value)
}
}
- if (most_recent_insert_iterator != _events.end()) {
+ if (with_guards && most_recent_insert_iterator != _events.end()) {
if ((*most_recent_insert_iterator)->when - when > 64) {
/* next control point is some
* distance from where our new
@@ -1729,7 +1735,7 @@ ControlList::dump (ostream& o)
/* NOT LOCKED ... for debugging only */
for (EventList::iterator x = _events.begin(); x != _events.end(); ++x) {
- o << (*x)->value << " @ " << (*x)->when << endl;
+ o << (*x)->value << " @ " << (uint64_t) (*x)->when << endl;
}
}
diff --git a/libs/panners/vbap/vbap.cc b/libs/panners/vbap/vbap.cc
index 8c1390832f..ea2d26fb31 100644
--- a/libs/panners/vbap/vbap.cc
+++ b/libs/panners/vbap/vbap.cc
@@ -403,7 +403,7 @@ VBAPanner::describe_parameter (Evoral::Parameter p)
{
switch (p.type()) {
case PanAzimuthAutomation:
- return _("Direction");
+ return _("Azimuth");
case PanWidthAutomation:
return _("Width");
case PanElevationAutomation:
diff --git a/libs/panners/vbap/vbap_speakers.cc b/libs/panners/vbap/vbap_speakers.cc
index 313fe7a5cd..4c662a8c6d 100644
--- a/libs/panners/vbap/vbap_speakers.cc
+++ b/libs/panners/vbap/vbap_speakers.cc
@@ -115,27 +115,36 @@ VBAPSpeakers::choose_speaker_triplets(struct ls_triplet_chain **ls_triplets)
int i,j,k,l,table_size;
int n_speakers = _speakers.size ();
- int connections[n_speakers][n_speakers];
- float distance_table[((n_speakers * (n_speakers - 1)) / 2)];
- int distance_table_i[((n_speakers * (n_speakers - 1)) / 2)];
- int distance_table_j[((n_speakers * (n_speakers - 1)) / 2)];
- float distance;
- struct ls_triplet_chain *trip_ptr, *prev, *tmp_ptr;
if (n_speakers == 0) {
return;
}
+ /* variable length arrays arrived in C99, became optional in C11, and
+ are only planned for C++14. Use alloca which is functionally
+ identical (but uglier to read).
+ */
+ int* connections = (int*) alloca (sizeof (int) * n_speakers * n_speakers);
+ float* distance_table = (float *) alloca (sizeof (float) * ((n_speakers * (n_speakers - 1)) / 2));
+ int* distance_table_i = (int *) alloca (sizeof (int) * ((n_speakers * (n_speakers - 1)) / 2));
+ int* distance_table_j = (int *) alloca (sizeof (int) * ((n_speakers * (n_speakers - 1)) / 2));
+ float distance;
+ struct ls_triplet_chain *trip_ptr, *prev, *tmp_ptr;
+
+ for (i = 0; i < n_speakers * n_speakers; i++) {
+ connections[i] = 0;
+ }
+
for (i = 0; i < n_speakers; i++) {
for (j = i+1; j < n_speakers; j++) {
for(k = j+1; k < n_speakers; k++) {
if (vol_p_side_lgth(i, j, k, _speakers) > MIN_VOL_P_SIDE_LGTH) {
- connections[i][j]=1;
- connections[j][i]=1;
- connections[i][k]=1;
- connections[k][i]=1;
- connections[j][k]=1;
- connections[k][j]=1;
+ connections[(i*n_speakers)+j]=1;
+ connections[(j*n_speakers)+i]=1;
+ connections[(i*n_speakers)+k]=1;
+ connections[(k*n_speakers)+i]=1;
+ connections[(j*n_speakers)+k]=1;
+ connections[(k*n_speakers)+j]=1;
add_ldsp_triplet(i,j,k,ls_triplets);
}
}
@@ -150,7 +159,7 @@ VBAPSpeakers::choose_speaker_triplets(struct ls_triplet_chain **ls_triplets)
for (i = 0;i < n_speakers; i++) {
for (j = i+1; j < n_speakers; j++) {
- if (connections[i][j] == 1) {
+ if (connections[(i*n_speakers)+j] == 1) {
distance = fabs(vec_angle(_speakers[i].coords(),_speakers[j].coords()));
k=0;
while(distance_table[k] < distance) {
@@ -175,13 +184,13 @@ VBAPSpeakers::choose_speaker_triplets(struct ls_triplet_chain **ls_triplets)
for (i = 0; i < table_size; i++) {
int fst_ls = distance_table_i[i];
int sec_ls = distance_table_j[i];
- if (connections[fst_ls][sec_ls] == 1) {
+ if (connections[(fst_ls*n_speakers)+sec_ls] == 1) {
for (j = 0; j < n_speakers; j++) {
for (k = j+1; k < n_speakers; k++) {
if ((j != fst_ls) && (k != sec_ls) && (k != fst_ls) && (j != sec_ls)) {
if (lines_intersect(fst_ls, sec_ls, j, k) == 1){
- connections[j][k] = 0;
- connections[k][j] = 0;
+ connections[(j*n_speakers)+k] = 0;
+ connections[(k*n_speakers)+j] = 0;
}
}
}
@@ -197,9 +206,9 @@ VBAPSpeakers::choose_speaker_triplets(struct ls_triplet_chain **ls_triplets)
i = trip_ptr->ls_nos[0];
j = trip_ptr->ls_nos[1];
k = trip_ptr->ls_nos[2];
- if (connections[i][j] == 0 ||
- connections[i][k] == 0 ||
- connections[j][k] == 0 ||
+ if (connections[(i*n_speakers)+j] == 0 ||
+ connections[(i*n_speakers)+k] == 0 ||
+ connections[(j*n_speakers)+k] == 0 ||
any_ls_inside_triplet(i,j,k) == 1 ){
if (prev != 0) {
prev->next = trip_ptr->next;
@@ -526,19 +535,23 @@ VBAPSpeakers::choose_speaker_pairs (){
matrices and stores the data to a global array
*/
const int n_speakers = _speakers.size();
- const double AZIMUTH_DELTA_THRESHOLD_DEGREES = (180.0/M_PI) * (M_PI - 0.175);
- int sorted_speakers[n_speakers];
- bool exists[n_speakers];
- double inverse_matrix[n_speakers][4];
- int expected_pairs = 0;
- int pair;
- int speaker;
-
if (n_speakers == 0) {
return;
}
+ const double AZIMUTH_DELTA_THRESHOLD_DEGREES = (180.0/M_PI) * (M_PI - 0.175);
+ /* variable length arrays arrived in C99, became optional in C11, and
+ are only planned for C++14. Use alloca which is functionally
+ identical (but uglier to read).
+ */
+ int* sorted_speakers = (int*) alloca (sizeof (int) * n_speakers);
+ bool* exists = (bool*) alloca (sizeof(bool) * n_speakers);
+ double* inverse_matrix = (double*) alloca (sizeof (double) * n_speakers * 4);
+ int expected_pairs = 0;
+ int pair;
+ int speaker;
+
for (speaker = 0; speaker < n_speakers; ++speaker) {
exists[speaker] = false;
}
@@ -553,7 +566,7 @@ VBAPSpeakers::choose_speaker_pairs (){
_speakers[sorted_speakers[speaker]].angles().azi) <= AZIMUTH_DELTA_THRESHOLD_DEGREES) {
if (calc_2D_inv_tmatrix( _speakers[sorted_speakers[speaker]].angles().azi,
_speakers[sorted_speakers[speaker+1]].angles().azi,
- inverse_matrix[speaker]) != 0){
+ &inverse_matrix[4 * speaker]) != 0){
exists[speaker] = true;
expected_pairs++;
}
@@ -564,7 +577,7 @@ VBAPSpeakers::choose_speaker_pairs (){
+_speakers[sorted_speakers[0]].angles().azi) <= AZIMUTH_DELTA_THRESHOLD_DEGREES) {
if (calc_2D_inv_tmatrix(_speakers[sorted_speakers[n_speakers-1]].angles().azi,
_speakers[sorted_speakers[0]].angles().azi,
- inverse_matrix[n_speakers-1]) != 0) {
+ &inverse_matrix[4*(n_speakers-1)]) != 0) {
exists[n_speakers-1] = true;
expected_pairs++;
}
@@ -582,10 +595,10 @@ VBAPSpeakers::choose_speaker_pairs (){
for (speaker = 0; speaker < n_speakers - 1; speaker++) {
if (exists[speaker]) {
- _matrices[pair][0] = inverse_matrix[speaker][0];
- _matrices[pair][1] = inverse_matrix[speaker][1];
- _matrices[pair][2] = inverse_matrix[speaker][2];
- _matrices[pair][3] = inverse_matrix[speaker][3];
+ _matrices[pair][0] = inverse_matrix[(speaker*4)+0];
+ _matrices[pair][1] = inverse_matrix[(speaker*4)+1];
+ _matrices[pair][2] = inverse_matrix[(speaker*4)+2];
+ _matrices[pair][3] = inverse_matrix[(speaker*4)+3];
_speaker_tuples[pair][0] = sorted_speakers[speaker];
_speaker_tuples[pair][1] = sorted_speakers[speaker+1];
@@ -595,10 +608,10 @@ VBAPSpeakers::choose_speaker_pairs (){
}
if (exists[n_speakers-1]) {
- _matrices[pair][0] = inverse_matrix[speaker][0];
- _matrices[pair][1] = inverse_matrix[speaker][1];
- _matrices[pair][2] = inverse_matrix[speaker][2];
- _matrices[pair][3] = inverse_matrix[speaker][3];
+ _matrices[pair][0] = inverse_matrix[(speaker*4)+0];
+ _matrices[pair][1] = inverse_matrix[(speaker*4)+1];
+ _matrices[pair][2] = inverse_matrix[(speaker*4)+2];
+ _matrices[pair][3] = inverse_matrix[(speaker*4)+3];
_speaker_tuples[pair][0] = sorted_speakers[n_speakers-1];
_speaker_tuples[pair][1] = sorted_speakers[0];
diff --git a/libs/surfaces/mackie/mackie_control_protocol.cc b/libs/surfaces/mackie/mackie_control_protocol.cc
index e9bef5a9b0..fc1491d9e8 100644
--- a/libs/surfaces/mackie/mackie_control_protocol.cc
+++ b/libs/surfaces/mackie/mackie_control_protocol.cc
@@ -345,7 +345,9 @@ MackieControlProtocol::switch_banks (uint32_t initial, bool force)
if (_current_initial_bank <= sorted.size()) {
- DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch to %1, %2, available routes %3\n", _current_initial_bank, strip_cnt, sorted.size()));
+ DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch to %1, %2, available routes %3 on %4 surfaces\n",
+ _current_initial_bank, strip_cnt, sorted.size(),
+ surfaces.size()));
// link routes to strips
@@ -521,11 +523,23 @@ MackieControlProtocol::update_global_led (int id, LedState ls)
}
}
+void
+MackieControlProtocol::device_ready ()
+{
+ /* this is not required to be called, but for devices which do
+ * handshaking, it can be called once the device has verified the
+ * connection.
+ */
+
+ DEBUG_TRACE (DEBUG::MackieControl, string_compose ("device ready init (active=%1)\n", active()));
+ update_surfaces ();
+}
+
// send messages to surface to set controls to correct values
void
MackieControlProtocol::update_surfaces()
{
- DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::update_surfaces() init\n");
+ DEBUG_TRACE (DEBUG::MackieControl, string_compose ("MackieControlProtocol::update_surfaces() init (active=%1)\n", active()));
if (!active()) {
return;
}
diff --git a/libs/surfaces/mackie/mackie_control_protocol.h b/libs/surfaces/mackie/mackie_control_protocol.h
index e1a71a2460..fc965d868b 100644
--- a/libs/surfaces/mackie/mackie_control_protocol.h
+++ b/libs/surfaces/mackie/mackie_control_protocol.h
@@ -119,6 +119,8 @@ class MackieControlProtocol
const Mackie::DeviceInfo& device_info() const { return _device_info; }
Mackie::DeviceProfile& device_profile() { return _device_profile; }
+ void device_ready ();
+
int set_active (bool yn);
int set_device (const std::string&);
void set_profile (const std::string&);
diff --git a/libs/surfaces/mackie/strip.cc b/libs/surfaces/mackie/strip.cc
index ef4447d900..1893e31b8d 100644
--- a/libs/surfaces/mackie/strip.cc
+++ b/libs/surfaces/mackie/strip.cc
@@ -627,12 +627,21 @@ Strip::do_parameter_display (AutomationType type, float val)
}
void
+Strip::handle_fader_touch (Fader& fader, bool touch_on)
+{
+ if (touch_on) {
+ fader.start_touch (_surface->mcp().transport_frame());
+ } else {
+ fader.stop_touch (_surface->mcp().transport_frame(), false);
+ }
+}
+
+void
Strip::handle_fader (Fader& fader, float position)
{
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader to %1\n", position));
fader.set_value (position);
- fader.start_touch (_surface->mcp().transport_frame());
queue_display_reset (2000);
// must echo bytes back to slider now, because
diff --git a/libs/surfaces/mackie/strip.h b/libs/surfaces/mackie/strip.h
index 225783d0fe..c330e0e54d 100644
--- a/libs/surfaces/mackie/strip.h
+++ b/libs/surfaces/mackie/strip.h
@@ -61,6 +61,7 @@ public:
void handle_button (Button&, ButtonState bs);
void handle_fader (Fader&, float position);
+ void handle_fader_touch (Fader&, bool touch_on);
void handle_pot (Pot&, float delta);
void periodic (uint64_t now_usecs);
diff --git a/libs/surfaces/mackie/surface.cc b/libs/surfaces/mackie/surface.cc
index 694c73b1bc..09c5fff051 100644
--- a/libs/surfaces/mackie/surface.cc
+++ b/libs/surfaces/mackie/surface.cc
@@ -369,7 +369,7 @@ Surface::connect_to_signals ()
p->controller.connect_same_thread (*this, boost::bind (&Surface::handle_midi_controller_message, this, _1, _2));
/* Button messages are NoteOn */
p->note_on.connect_same_thread (*this, boost::bind (&Surface::handle_midi_note_on_message, this, _1, _2));
- /* Button messages are NoteOn. libmidi++ sends note-on w/velocity = 0 as note-off so catch them too */
+ /* Button messages are NoteOn but libmidi++ sends note-on w/velocity = 0 as note-off so catch them too */
p->note_off.connect_same_thread (*this, boost::bind (&Surface::handle_midi_note_on_message, this, _1, _2));
/* Fader messages are Pitchbend */
uint32_t i;
@@ -386,7 +386,7 @@ Surface::connect_to_signals ()
void
Surface::handle_midi_pitchbend_message (MIDI::Parser&, MIDI::pitchbend_t pb, uint32_t fader_id)
{
- /* Pitchbend messages are fader messages. Nothing in the data we get
+ /* Pitchbend messages are fader position messages. Nothing in the data we get
* from the MIDI::Parser conveys the fader ID, which was given by the
* channel ID in the status byte.
*
@@ -394,7 +394,6 @@ Surface::handle_midi_pitchbend_message (MIDI::Parser&, MIDI::pitchbend_t pb, uin
* when we connected to the per-channel pitchbend events.
*/
-
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface::handle_midi_pitchbend_message on port %3, fader = %1 value = %2\n",
fader_id, pb, _number));
@@ -429,6 +428,28 @@ Surface::handle_midi_note_on_message (MIDI::Parser &, MIDI::EventTwoBytes* ev)
turn_it_on ();
}
+ /* fader touch sense is given by "buttons" 0xe..0xe7 and 0xe8 for the
+ * master.
+ */
+
+ if (ev->note_number >= 0xE0 && ev->note_number <= 0xE8) {
+ Fader* fader = faders[ev->note_number];
+
+ DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface: fader touch message, fader = %1\n", fader));
+
+ if (fader) {
+
+ Strip* strip = dynamic_cast<Strip*> (&fader->group());
+
+ if (ev->velocity > 64) {
+ strip->handle_fader_touch (*fader, true);
+ } else {
+ strip->handle_fader_touch (*fader, false);
+ }
+ }
+ return;
+ }
+
Button* button = buttons[ev->note_number];
if (button) {
@@ -516,8 +537,10 @@ Surface::handle_midi_sysex (MIDI::Parser &, MIDI::byte * raw_bytes, size_t count
LCP: Connection Challenge
*/
if (bytes[4] == 0x10 || bytes[4] == 0x11) {
+ DEBUG_TRACE (DEBUG::MackieControl, "Logic Control Device connection challenge\n");
write_sysex (host_connection_query (bytes));
} else {
+ DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Mackie Control Device ready, current status = %1\n", _active));
if (!_active) {
turn_it_on ();
}
@@ -525,6 +548,7 @@ Surface::handle_midi_sysex (MIDI::Parser &, MIDI::byte * raw_bytes, size_t count
break;
case 0x03: /* LCP Connection Confirmation */
+ DEBUG_TRACE (DEBUG::MackieControl, "Logic Control Device confirms connection, ardour replies\n");
if (bytes[4] == 0x10 || bytes[4] == 0x11) {
write_sysex (host_connection_confirmation (bytes));
_active = true;
@@ -532,6 +556,7 @@ Surface::handle_midi_sysex (MIDI::Parser &, MIDI::byte * raw_bytes, size_t count
break;
case 0x04: /* LCP: Confirmation Denied */
+ DEBUG_TRACE (DEBUG::MackieControl, "Logic Control Device denies connection\n");
_active = false;
break;
default:
@@ -610,6 +635,8 @@ Surface::turn_it_on ()
_active = true;
+ _mcp.device_ready ();
+
for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
(*s)->notify_all ();
}
@@ -739,6 +766,8 @@ Surface::map_routes (const vector<boost::shared_ptr<Route> >& routes)
vector<boost::shared_ptr<Route> >::const_iterator r;
Strips::iterator s = strips.begin();
+ DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Mapping %1 routes", routes.size()));
+
for (r = routes.begin(); r != routes.end() && s != strips.end(); ++s) {
/* don't try to assign routes to a locked strip. it won't