vector<string>::iterator n;
vector<string>::iterator k;
- for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
- cout << "Action: " << (*n) << " bound to " << (*k) << endl;
+ vector<string>::iterator p;
+ for (n = names.begin(), k = keys.begin(), p = paths.begin(); n != names.end(); ++n, ++k, ++p) {
+ cout << "Action: '" << (*n) << "' bound to '" << (*k) << "' Path: '" << (*p) << "'" << endl;
}
+ halt_connection.disconnect ();
+ AudioEngine::instance()->stop ();
exit (0);
}
} else {
for (TrackSelection::iterator s = editor->get_selection().tracks.begin(); s != editor->get_selection().tracks.end(); ++s) {
RouteTimeAxisView* tav = dynamic_cast<RouteTimeAxisView*> (*s);
- if (tav->route()->order_key() > order_hint) {
+ if (tav && tav->route() && tav->route()->order_key() > order_hint) {
order_hint = tav->route()->order_key();
}
}
}
void
-AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev)
+AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev, bool with_guard_points)
{
if (!gain_line) {
return;
trackview.session()->add_command (new MementoCommand<AudioRegion>(*(audio_region().get()), ®ion_before, ®ion_after));
}
- audio_region()->envelope()->add (fx, y);
+ audio_region()->envelope()->add (fx, y, with_guard_points);
XMLNode &after = audio_region()->envelope()->get_state();
trackview.session()->add_command (new MementoCommand<AutomationList>(*audio_region()->envelope().get(), &before, &after));
void update_envelope_visibility ();
- void add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *event);
+ void add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *event, bool with_guard_points);
void remove_gain_point_event (ArdourCanvas::Item *item, GdkEvent *event);
boost::shared_ptr<AudioRegionGainLine> get_gain_line() const { return gain_line; }
#include "ardour/midi_region.h"
#include "ardour/session.h"
+#include "gtkmm2ext/keyboard.h"
+
#include "automation_region_view.h"
#include "editing.h"
#include "editor.h"
y = std::max (y, 0.0);
y = std::min (y, _height - NAME_HIGHLIGHT_SIZE);
- add_automation_event (ev, trackview.editor().pixel_to_frame (x) - _region->position() + _region->start(), y);
+ /* guard points only if primary modifier is used */
+
+ bool with_guard_points = Gtkmm2ext::Keyboard::modifier_state_equals (ev->button.state, Gtkmm2ext::Keyboard::PrimaryModifier);
+
+ add_automation_event (ev, trackview.editor().pixel_to_frame (x) - _region->position() + _region->start(), y, with_guard_points);
}
return false;
* @param y y position, relative to our TimeAxisView.
*/
void
-AutomationRegionView::add_automation_event (GdkEvent *, framepos_t when, double y)
+AutomationRegionView::add_automation_event (GdkEvent *, framepos_t when, double y, bool with_guard_points)
{
if (!_line) {
boost::shared_ptr<Evoral::Control> c = _region->control(_parameter, true);
view->session()->begin_reversible_command (_("add automation event"));
XMLNode& before = _line->the_list()->get_state();
- _line->the_list()->add (when_d, y);
+ _line->the_list()->add (when_d, y, with_guard_points);
XMLNode& after = _line->the_list()->get_state();
bool set_position(framepos_t pos, void* src, double* ignored);
void region_resized (const PBD::PropertyChange&);
bool canvas_event(GdkEvent* ev);
- void add_automation_event (GdkEvent* event, framepos_t when, double y);
+ void add_automation_event (GdkEvent* event, framepos_t when, double y, bool with_guard_points);
void entered (bool);
void exited();
}
void
-AutomationTimeAxisView::add_automation_event (GdkEvent* event, framepos_t when, double y)
+AutomationTimeAxisView::add_automation_event (GdkEvent* event, framepos_t when, double y, bool with_guard_points)
{
if (!_line) {
return;
_session->begin_reversible_command (_("add automation event"));
XMLNode& before = list->get_state();
- list->add (when, y);
+ list->add (when, y, with_guard_points);
XMLNode& after = list->get_state();
_session->commit_reversible_command (new MementoCommand<ARDOUR::AutomationList> (*list, &before, &after));
void set_samples_per_unit (double);
std::string name() const { return _name; }
- void add_automation_event (GdkEvent *, framepos_t, double);
+ void add_automation_event (GdkEvent *, framepos_t, double, bool with_guard_points);
void clear_lines ();
{
switch (_snap_type) {
case Editing::SnapToCDFrame:
- set_snap_to (Editing::SnapToTimecodeFrame);
+ set_snap_to (Editing::SnapToRegionBoundary);
break;
case Editing::SnapToTimecodeFrame:
- set_snap_to (Editing::SnapToTimecodeSeconds);
+ set_snap_to (Editing::SnapToCDFrame);
break;
case Editing::SnapToTimecodeSeconds:
- set_snap_to (Editing::SnapToTimecodeMinutes);
+ set_snap_to (Editing::SnapToTimecodeFrame);
break;
case Editing::SnapToTimecodeMinutes:
- set_snap_to (Editing::SnapToSeconds);
+ set_snap_to (Editing::SnapToTimecodeSeconds);
break;
case Editing::SnapToSeconds:
- set_snap_to (Editing::SnapToMinutes);
+ set_snap_to (Editing::SnapToTimecodeMinutes);
break;
case Editing::SnapToMinutes:
- set_snap_to (Editing::SnapToBeatDiv128);
+ set_snap_to (Editing::SnapToSeconds);
break;
case Editing::SnapToBeatDiv128:
- set_snap_to (Editing::SnapToBeatDiv64);
+ set_snap_to (Editing::SnapToMinutes);
break;
case Editing::SnapToBeatDiv64:
- set_snap_to (Editing::SnapToBeatDiv32);
+ set_snap_to (Editing::SnapToBeatDiv128);
break;
case Editing::SnapToBeatDiv32:
- set_snap_to (Editing::SnapToBeatDiv28);
+ set_snap_to (Editing::SnapToBeatDiv64);
break;
case Editing::SnapToBeatDiv28:
- set_snap_to (Editing::SnapToBeatDiv24);
+ set_snap_to (Editing::SnapToBeatDiv32);
break;
case Editing::SnapToBeatDiv24:
- set_snap_to (Editing::SnapToBeatDiv20);
+ set_snap_to (Editing::SnapToBeatDiv28);
break;
case Editing::SnapToBeatDiv20:
- set_snap_to (Editing::SnapToBeatDiv16);
+ set_snap_to (Editing::SnapToBeatDiv24);
break;
case Editing::SnapToBeatDiv16:
- set_snap_to (Editing::SnapToBeatDiv14);
+ set_snap_to (Editing::SnapToBeatDiv20);
break;
case Editing::SnapToBeatDiv14:
- set_snap_to (Editing::SnapToBeatDiv12);
+ set_snap_to (Editing::SnapToBeatDiv16);
break;
case Editing::SnapToBeatDiv12:
- set_snap_to (Editing::SnapToBeatDiv10);
+ set_snap_to (Editing::SnapToBeatDiv14);
break;
case Editing::SnapToBeatDiv10:
- set_snap_to (Editing::SnapToBeatDiv8);
+ set_snap_to (Editing::SnapToBeatDiv12);
break;
case Editing::SnapToBeatDiv8:
- set_snap_to (Editing::SnapToBeatDiv7);
+ set_snap_to (Editing::SnapToBeatDiv10);
break;
case Editing::SnapToBeatDiv7:
- set_snap_to (Editing::SnapToBeatDiv6);
+ set_snap_to (Editing::SnapToBeatDiv8);
break;
case Editing::SnapToBeatDiv6:
- set_snap_to (Editing::SnapToBeatDiv5);
+ set_snap_to (Editing::SnapToBeatDiv7);
break;
case Editing::SnapToBeatDiv5:
- set_snap_to (Editing::SnapToBeatDiv4);
+ set_snap_to (Editing::SnapToBeatDiv6);
break;
case Editing::SnapToBeatDiv4:
- set_snap_to (Editing::SnapToBeatDiv3);
+ set_snap_to (Editing::SnapToBeatDiv5);
break;
case Editing::SnapToBeatDiv3:
- set_snap_to (Editing::SnapToBeatDiv2);
+ set_snap_to (Editing::SnapToBeatDiv4);
break;
case Editing::SnapToBeatDiv2:
- set_snap_to (Editing::SnapToBeat);
+ set_snap_to (Editing::SnapToBeatDiv3);
break;
case Editing::SnapToBeat:
- set_snap_to (Editing::SnapToBar);
+ set_snap_to (Editing::SnapToBeatDiv2);
break;
case Editing::SnapToBar:
- set_snap_to (Editing::SnapToMark);
+ set_snap_to (Editing::SnapToBeat);
break;
case Editing::SnapToMark:
- set_snap_to (Editing::SnapToRegionStart);
+ set_snap_to (Editing::SnapToBar);
break;
case Editing::SnapToRegionStart:
- set_snap_to (Editing::SnapToRegionEnd);
+ set_snap_to (Editing::SnapToMark);
break;
case Editing::SnapToRegionEnd:
- set_snap_to (Editing::SnapToRegionSync);
+ set_snap_to (Editing::SnapToRegionStart);
break;
case Editing::SnapToRegionSync:
- set_snap_to (Editing::SnapToRegionBoundary);
+ set_snap_to (Editing::SnapToRegionEnd);
break;
case Editing::SnapToRegionBoundary:
- set_snap_to (Editing::SnapToCDFrame);
+ set_snap_to (Editing::SnapToRegionSync);
break;
}
}
}
void
-LineDrag::finished (GdkEvent* event, bool)
+LineDrag::finished (GdkEvent* event, bool movement_occured)
{
- motion (event, false);
- _line->end_drag (false, 0);
+ if (movement_occured) {
+ motion (event, false);
+ _line->end_drag (false, 0);
+ } else {
+ /* add a new control point on the line */
+
+ AutomationTimeAxisView* atv;
+
+ _line->end_drag (false, 0);
+
+ if ((atv = dynamic_cast<AutomationTimeAxisView*>(_editor->clicked_axisview)) != 0) {
+ framepos_t where = _editor->event_frame (event, 0, 0);
+ atv->add_automation_event (event, where, event->button.y, false);
+ }
+ }
+
_editor->session()->commit_reversible_command ();
}
case AutomationTrackItem:
atv = dynamic_cast<AutomationTimeAxisView*>(clicked_axisview);
if (atv) {
- atv->add_automation_event (event, where, event->button.y);
+ bool with_guard_points = Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier);
+ atv->add_automation_event (event, where, event->button.y, with_guard_points);
}
return true;
break;
*/
AudioRegionView* arv = dynamic_cast<AudioRegionView*> (clicked_regionview);
if (!were_dragging && arv) {
- arv->add_gain_point_event (item, event);
+ bool with_guard_points = Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier);
+ arv->add_gain_point_event (item, event, with_guard_points);
}
return true;
break;
}
- case AutomationTrackItem:
+ case AutomationTrackItem: {
+ bool with_guard_points = Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier);
dynamic_cast<AutomationTimeAxisView*>(clicked_axisview)->
- add_automation_event (event, where, event->button.y);
+ add_automation_event (event, where, event->button.y, with_guard_points);
return true;
break;
+ }
default:
break;
}
GainMeterBase::setup_meters (int len)
{
int meter_width = 5;
+ uint32_t meter_channels = 0;
+ if (_meter) {
+ meter_channels = _meter->input_streams().n_total();
+ } else if (_route) {
+ meter_channels = _route->shared_peak_meter()->input_streams().n_total();
+ }
switch (_width) {
case Wide:
//meter_ticks1_area.show();
//meter_ticks2_area.show();
meter_metric_area.show();
- if (_route && _route->shared_peak_meter()->input_streams().n_total() == 1) {
+ if (meter_channels == 1) {
meter_width = 10;
}
break;
case Narrow:
- if (_route && _route->shared_peak_meter()->input_streams().n_total() > 1) {
+ if (meter_channels > 1) {
meter_width = 4;
}
//meter_ticks1_area.hide();
_meter_type_connection.disconnect();
_meter = meter;
+ color_changed = true;
if (_meter) {
_meter->ConfigurationChanged.connect (_configuration_connection, parent_invalidator, boost::bind (&LevelMeterBase::configuration_changed, this, _1, _2), gui_context());
#include "ardour/audio_track.h"
#include "ardour/audioengine.h"
#include "ardour/internal_send.h"
+#include "ardour/meter.h"
#include "ardour/midi_track.h"
#include "ardour/pannable.h"
#include "ardour/panner.h"
if (panners._panner == 0) {
panners.panshell_changed ();
}
+ update_panner_choices();
}
void
set_current_delivery (send);
+ send->meter()->set_type(_route->shared_peak_meter()->get_type());
send->set_metering (true);
_current_delivery->DropReferences.connect (send_gone_connection, invalidator (*this), boost::bind (&MixerStrip::revert_to_default_display, this), gui_context());
_suspend_menu_callbacks = true;
add_level_meter_item_point (items, group, _("Input"), MeterInput);
- add_level_meter_item_point (items, group, _("Pre-fader"), MeterPreFader);
- add_level_meter_item_point (items, group, _("Post-fader"), MeterPostFader);
+ add_level_meter_item_point (items, group, _("Pre Fader"), MeterPreFader);
+ add_level_meter_item_point (items, group, _("Post Fader"), MeterPostFader);
add_level_meter_item_point (items, group, _("Output"), MeterOutput);
add_level_meter_item_point (items, group, _("Custom"), MeterCustom);
PannerUI::PannerUI (Session* s)
: _current_nouts (-1)
, _current_nins (-1)
+ , _current_uri ("")
, pan_automation_style_button ("")
, pan_automation_state_button ("")
, _panner_list()
int const nouts = _panner ? _panner->out().n_audio() : -1;
int const nins = _panner ? _panner->in().n_audio() : -1;
- if (nouts == _current_nouts && nins == _current_nins) {
+ if (nouts == _current_nouts
+ && nins == _current_nins
+ && _current_uri == _panshell->panner_gui_uri()
+ )
+ {
return;
}
_current_nins = nins;
_current_nouts = nouts;
+ _current_uri = _panshell->panner_gui_uri();
container_clear (pan_vbox);
return;
}
- if (_panshell->panner_gui_uri() == "http://ardour.org/plugin/panner_2in2out#ui")
+ if (_current_uri == "http://ardour.org/plugin/panner_2in2out#ui")
{
delete big_window;
big_window = 0;
boost::weak_ptr<AutomationControl>(ac)));
_stereo_panner->signal_button_release_event().connect (sigc::mem_fun(*this, &PannerUI::pan_button_event));
}
- else if (_panshell->panner_gui_uri() == "http://ardour.org/plugin/panner_1in2out#ui"
- || _panshell->panner_gui_uri() == "http://ardour.org/plugin/panner_balance#ui")
+ else if (_current_uri == "http://ardour.org/plugin/panner_1in2out#ui"
+ || _current_uri == "http://ardour.org/plugin/panner_balance#ui")
{
delete big_window;
big_window = 0;
update_pan_sensitive ();
pan_vbox.pack_start (*_mono_panner, false, false);
}
- else if (_panshell->panner_gui_uri() == "http://ardour.org/plugin/panner_vbap#ui")
+ else if (_current_uri == "http://ardour.org/plugin/panner_vbap#ui")
{
if (!twod_panner) {
twod_panner = new Panner2d (_panshell, 61);
RadioMenuItem::Group group;
items.push_back (SeparatorElem());
- assert(_panshell->user_selected_panner_uri() == ""
- || _panshell->user_selected_panner_uri() == _panshell->current_panner_uri());
-
_suspend_menu_callbacks = true;
for (std::map<std::string,std::string>::const_iterator p = _panner_list.begin(); p != _panner_list.end(); ++p) {
items.push_back (RadioMenuElem (group, p->second,
bool in_pan_update;
int _current_nouts;
int _current_nins;
+ std::string _current_uri;
static const int pan_bar_height;
PluginUIWindow::~PluginUIWindow ()
{
+#ifndef NDEBUG
cerr << "PluginWindow deleted for " << this << endl;
+#endif
delete _pluginui;
}
cairo_move_to (cr, si_x, height);
cairo_line_to (cr, si_x, 0);
cairo_stroke (cr);
+ } else if (midi_sources == 1 && midi_sinks == 1) {
+ /* unusual cases -- removed synth, midi-track w/audio plugins */
+ const float si_x = rintf(width * (sinks > 1 ? .2f : .5f)) + .5f;
+ const float si_x0 = rintf(width * (sources > 1 ? .2f : .5f)) + .5f;
+ cairo_move_to (cr, si_x, height);
+ cairo_curve_to (cr, si_x, 0, si_x0, height, si_x0, 0);
+ cairo_stroke (cr);
}
/* AUDIO */
UINT_RGBA_B_FLT(audio_port_color));
if (_splitting) {
+ assert(audio_sources < 2);
assert(audio_sinks > 1);
- const float si_x0 = rintf(width * .5f) + .5f;
+ /* assume there is only ever one MIDI port */
+ const float si_x0 = rintf(width * (midi_sources > 0 ? .8f : .5f)) + .5f;
for (uint32_t i = midi_sinks; i < sinks; ++i) {
const float si_x = rintf(width * (.2f + .6f * i / (sinks - 1.f))) + .5f;
cairo_move_to (cr, si_x, height);
MenuList& items = mute_menu->items();
- pre_fader_mute_check = manage (new CheckMenuItem(_("Pre Fader")));
+ pre_fader_mute_check = manage (new CheckMenuItem(_("Pre Fader Sends")));
init_mute_menu(MuteMaster::PreFader, pre_fader_mute_check);
pre_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PreFader, pre_fader_mute_check));
items.push_back (CheckMenuElem(*pre_fader_mute_check));
pre_fader_mute_check->show_all();
- post_fader_mute_check = manage (new CheckMenuItem(_("Post Fader")));
+ post_fader_mute_check = manage (new CheckMenuItem(_("Post Fader Sends")));
init_mute_menu(MuteMaster::PostFader, post_fader_mute_check);
post_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PostFader, post_fader_mute_check));
items.push_back (CheckMenuElem(*post_fader_mute_check));
return _("as new tracks");
}
-SoundFileBox::SoundFileBox (bool persistent)
+SoundFileBox::SoundFileBox (bool /*persistent*/)
: table (6, 2),
length_clock ("sfboxLengthClock", true, "", false, false, true, false),
timecode_clock ("sfboxTimecodeClock", true, "", false, false, false, false),
width_control->Changed.connect (panvalue_connections, invalidator(*this), boost::bind (&StereoPanner::value_change, this), gui_context());
_panner_shell->Changed.connect (panshell_connections, invalidator (*this), boost::bind (&StereoPanner::bypass_handler, this), gui_context());
+ _panner_shell->PannableChanged.connect (panshell_connections, invalidator (*this), boost::bind (&StereoPanner::pannable_handler, this), gui_context());
ColorsChanged.connect (sigc::mem_fun (*this, &StereoPanner::color_handler));
}
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&
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
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) {
void set_data (Sample* data, size_t size) {
assert(!_owns_data); // prevent leaks
_capacity = size;
- _size = size;
_data = data;
_silent = false;
_written = false;
*/
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;
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; }
/** 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; }
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;
};
void inc_use_count ();
bool removable () const;
+ bool is_stub () const;
const std::string& origin() const { return _origin; }
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);
friend class iterator_base< const MidiBuffer, const Evoral::MIDIEvent<TimeType> >;
uint8_t* _data; ///< timestamp, event, timestamp, event, ...
+ pframes_t _size;
};
} VstTimeInfo;
-typedef struct _VstTimeInfo VstTimeInfo;
-
typedef intptr_t (* audioMasterCallback) (AEffect *, int32_t, int32_t, intptr_t, void *, float);
#endif
if (_data && size < _capacity) {
/* buffer is already large enough */
-
- if (size < _size) {
- /* truncate */
- _size = size;
- }
-
return;
}
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;
}
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());
+ }
+ }
}
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);
}
}
}
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()));
}
}
{
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();
}
{
bool r = ((_flags & Removable)
&& ((_flags & RemoveAtDestroy) ||
- ((_flags & RemovableIfEmpty) && empty() == 0)));
+ ((_flags & RemovableIfEmpty) && empty())));
return r;
}
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;
+}
+
// 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) {
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;
}
} 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;
}
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);
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());
{
// 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 */
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;
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 ();
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);
}
{
//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);
/* 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 */
++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;
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);
*/
#include <iostream>
+
+#include "pbd/stacktrace.h"
+
#include "evoral/Control.hpp"
#include "evoral/ControlList.hpp"
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);
}
}
{
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;
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) {
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()) {
}
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)
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);
* 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));
}
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) {
++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
}
}
- 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
/* 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;
}
}
{
switch (p.type()) {
case PanAzimuthAutomation:
- return _("Direction");
+ return _("Azimuth");
case PanWidthAutomation:
return _("Width");
case PanElevationAutomation:
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);
}
}
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) {
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;
}
}
}
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;
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;
}
_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++;
}
+_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++;
}
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];
}
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];
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
}
}
+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;
}
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&);
}
}
+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
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);
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;
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.
*
* 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));
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) {
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 ();
}
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;
break;
case 0x04: /* LCP: Confirmation Denied */
+ DEBUG_TRACE (DEBUG::MackieControl, "Logic Control Device denies connection\n");
_active = false;
break;
default:
_active = true;
+ _mcp.device_ready ();
+
for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
(*s)->notify_all ();
}
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
if opt.gprofile:
debug_flags = [ '-pg' ]
- if opt.backtrace:
- if platform != 'darwin' and not is_clang:
- debug_flags = [ '-rdynamic' ]
-
# Autodetect
if opt.dist_target == 'auto':
if platform == 'darwin':
conf.env.append_value('CFLAGS', optimization_flags)
conf.env.append_value('CXXFLAGS', optimization_flags)
+ if opt.backtrace:
+ if platform != 'darwin' and not is_clang:
+ linker_flags += [ '-rdynamic' ]
+
conf.env.append_value('CFLAGS', compiler_flags)
conf.env.append_value('CFLAGS', c_flags)
conf.env.append_value('CXXFLAGS', compiler_flags)