diff --git a/gtk2_ardour/analysis_window.cc b/gtk2_ardour/analysis_window.cc
index afa277e8e4..c4948f5092 100644
--- a/gtk2_ardour/analysis_window.cc
+++ b/gtk2_ardour/analysis_window.cc
@@ -334,6 +334,7 @@ AnalysisWindow::analyze_data (Gtk::Button */*button*/)
n = length - x;
}
+ memset (buf, 0, n * sizeof (Sample));
n = arv->audio_region()->read_at(buf, mixbuf, gain, arv->region()->position() + x, n, channel);
if (n == 0)
diff --git a/gtk2_ardour/ardev_common.sh.in b/gtk2_ardour/ardev_common.sh.in
index 58e6c4e0ba..d8bdeb430d 100644
--- a/gtk2_ardour/ardev_common.sh.in
+++ b/gtk2_ardour/ardev_common.sh.in
@@ -8,6 +8,7 @@ export ARDOUR_PATH=$TOP/gtk2_ardour/icons:$TOP/gtk2_ardour/pixmaps:$TOP/build/gt
export ARDOUR_SURFACES_PATH=$libs/surfaces/osc:$libs/surfaces/generic_midi:$libs/surfaces/tranzport:$libs/surfaces/powermate:$libs/surfaces/mackie
export ARDOUR_PANNER_PATH=$libs/panners/2in2out:$libs/panners/1in2out:$libs/panners/vbap
export ARDOUR_DATA_PATH=$TOP/gtk2_ardour:build/gtk2_ardour:.
+export ARDOUR_MIDIMAPS_PATH=$TOP/midi_maps:.
export ARDOUR_MCP_PATH=$TOP/mcp:.
if test -d $HOME/gtk/inst ; then
diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc
index e97745e946..8063164eb5 100644
--- a/gtk2_ardour/ardour_ui.cc
+++ b/gtk2_ardour/ardour_ui.cc
@@ -925,7 +925,7 @@ ARDOUR_UI::update_sample_rate (framecnt_t)
if (!engine->connected()) {
- snprintf (buf, sizeof (buf), _("disconnected"));
+ snprintf (buf, sizeof (buf), "%s", _("disconnected"));
} else {
@@ -1063,7 +1063,7 @@ ARDOUR_UI::update_disk_space()
framecnt_t fr = _session->frame_rate();
if (frames == max_framecnt) {
- snprintf (buf, sizeof (buf), _("Disk: 24hrs+"));
+ snprintf (buf, sizeof (buf), "%s", _("Disk: 24hrs+"));
} else {
rec_enabled_streams = 0;
_session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
@@ -1079,7 +1079,7 @@ ARDOUR_UI::update_disk_space()
hrs = frames / (fr * 3600);
if (hrs > 24) {
- snprintf (buf, sizeof (buf), _("Disk: >24 hrs"));
+ snprintf (buf, sizeof (buf), "%s", _("Disk: >24 hrs"));
} else {
frames -= hrs * fr * 3600;
mins = frames / (fr * 60);
diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc
index f5ee554c3f..35100e940b 100644
--- a/gtk2_ardour/ardour_ui_ed.cc
+++ b/gtk2_ardour/ardour_ui_ed.cc
@@ -706,7 +706,7 @@ ARDOUR_UI::float_big_clock (Gtk::Window* parent)
}
void
-ARDOUR_UI::big_clock_size_allocate (Gtk::Allocation& alloc)
+ARDOUR_UI::big_clock_size_allocate (Gtk::Allocation&)
{
if (!big_clock_resize_in_progress) {
Glib::signal_idle().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::idle_big_clock_text_resizer), 0, 0));
diff --git a/gtk2_ardour/ardour_window.cc b/gtk2_ardour/ardour_window.cc
index 94d3f55d12..8d3821fe87 100644
--- a/gtk2_ardour/ardour_window.cc
+++ b/gtk2_ardour/ardour_window.cc
@@ -36,7 +36,7 @@ ArdourWindow::ArdourWindow (string title)
init ();
}
-ArdourWindow::ArdourWindow (Gtk::Window& parent, string title)
+ArdourWindow::ArdourWindow (Gtk::Window& parent, string /*title*/)
: Window ()
{
init ();
diff --git a/gtk2_ardour/audio_clock.cc b/gtk2_ardour/audio_clock.cc
index a4cb473a72..76abb9d6bb 100644
--- a/gtk2_ardour/audio_clock.cc
+++ b/gtk2_ardour/audio_clock.cc
@@ -796,7 +796,7 @@ AudioClock::parse_as_timecode_distance (const std::string& str)
}
framecnt_t
-AudioClock::parse_as_bbt_distance (const std::string& str)
+AudioClock::parse_as_bbt_distance (const std::string&)
{
return 0;
}
@@ -1001,7 +1001,7 @@ AudioClock::set_frames (framepos_t when, bool /*force*/)
}
void
-AudioClock::set_minsec (framepos_t when, bool force)
+AudioClock::set_minsec (framepos_t when, bool /*force*/)
{
char buf[32];
framecnt_t left;
@@ -1046,7 +1046,7 @@ AudioClock::set_minsec (framepos_t when, bool force)
}
void
-AudioClock::set_timecode (framepos_t when, bool force)
+AudioClock::set_timecode (framepos_t when, bool /*force*/)
{
char buf[32];
Timecode::Time TC;
@@ -1112,7 +1112,7 @@ AudioClock::set_timecode (framepos_t when, bool force)
}
void
-AudioClock::set_bbt (framepos_t when, bool force)
+AudioClock::set_bbt (framepos_t when, bool /*force*/)
{
char buf[16];
Timecode::BBT_Time BBT;
@@ -1740,7 +1740,7 @@ AudioClock::get_frame_step (Field field, framepos_t pos, int dir)
}
framepos_t
-AudioClock::current_time (framepos_t pos) const
+AudioClock::current_time (framepos_t) const
{
return last_when;
}
@@ -1795,7 +1795,7 @@ AudioClock::bbt_validate_edit (const string& str)
}
bool
-AudioClock::timecode_validate_edit (const string& str)
+AudioClock::timecode_validate_edit (const string&)
{
Timecode::Time TC;
diff --git a/gtk2_ardour/audio_region_view.cc b/gtk2_ardour/audio_region_view.cc
index 70966b1dff..6ab858f1c9 100644
--- a/gtk2_ardour/audio_region_view.cc
+++ b/gtk2_ardour/audio_region_view.cc
@@ -20,6 +20,8 @@
#include
#include
+#include
+
#include
#include
@@ -43,6 +45,7 @@
#include "waveview.h"
#include "public_editor.h"
#include "audio_region_editor.h"
+#include "audio_streamview.h"
#include "region_gain_line.h"
#include "control_point.h"
#include "ghostregion.h"
@@ -73,13 +76,18 @@ AudioRegionView::AudioRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView
, fade_in_handle(0)
, fade_out_handle(0)
, fade_position_line(0)
+ , start_xfade_in (0)
+ , start_xfade_out (0)
+ , start_xfade_rect (0)
+ , end_xfade_in (0)
+ , end_xfade_out (0)
+ , end_xfade_rect (0)
, _amplitude_above_axis(1.0)
, _flags(0)
, fade_color(0)
{
}
-
AudioRegionView::AudioRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &tv, boost::shared_ptr r, double spu,
Gdk::Color const & basic_color, bool recording, TimeAxisViewItem::Visibility visibility)
: RegionView (parent, tv, r, spu, basic_color, recording, visibility)
@@ -89,6 +97,12 @@ AudioRegionView::AudioRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView
, fade_in_handle(0)
, fade_out_handle(0)
, fade_position_line(0)
+ , start_xfade_in (0)
+ , start_xfade_out (0)
+ , start_xfade_rect (0)
+ , end_xfade_in (0)
+ , end_xfade_out (0)
+ , end_xfade_rect (0)
, _amplitude_above_axis(1.0)
, _flags(0)
, fade_color(0)
@@ -102,6 +116,12 @@ AudioRegionView::AudioRegionView (const AudioRegionView& other, boost::shared_pt
, fade_in_handle(0)
, fade_out_handle(0)
, fade_position_line(0)
+ , start_xfade_in (0)
+ , start_xfade_out (0)
+ , start_xfade_rect (0)
+ , end_xfade_in (0)
+ , end_xfade_out (0)
+ , end_xfade_rect (0)
, _amplitude_above_axis (other._amplitude_above_axis)
, _flags (other._flags)
, fade_color(0)
@@ -288,6 +308,7 @@ AudioRegionView::fade_out_changed ()
{
reset_fade_out_shape ();
}
+
void
AudioRegionView::fade_in_active_changed ()
{
@@ -534,10 +555,31 @@ AudioRegionView::reset_fade_in_shape ()
void
AudioRegionView::reset_fade_in_shape_width (framecnt_t width)
{
+ if (dragging()) {
+ return;
+ }
+
+ if (audio_region()->fade_in_is_xfade()) {
+ if (fade_in_handle) {
+ fade_in_handle->hide ();
+ fade_in_shape->hide ();
+ }
+ redraw_start_xfade ();
+ return;
+ } else {
+ if (start_xfade_in) {
+ start_xfade_in->hide ();
+ start_xfade_out->hide ();
+ start_xfade_rect->hide ();
+ }
+ }
+
if (fade_in_handle == 0) {
return;
}
+ fade_in_handle->show ();
+
/* smallest size for a fade is 64 frames */
width = std::max ((framecnt_t) 64, width);
@@ -621,10 +663,31 @@ AudioRegionView::reset_fade_out_shape ()
void
AudioRegionView::reset_fade_out_shape_width (framecnt_t width)
{
+ if (dragging()) {
+ return;
+ }
+
+ if (audio_region()->fade_out_is_xfade()) {
+ if (fade_out_handle) {
+ fade_out_handle->hide ();
+ fade_out_shape->hide ();
+ }
+ redraw_end_xfade ();
+ return;
+ } else {
+ if (end_xfade_in) {
+ end_xfade_in->hide ();
+ end_xfade_out->hide ();
+ end_xfade_rect->hide ();
+ }
+ }
+
if (fade_out_handle == 0) {
return;
}
+ fade_out_handle->show ();
+
/* smallest size for a fade is 64 frames */
width = std::max ((framecnt_t) 64, width);
@@ -1462,6 +1525,287 @@ void
AudioRegionView::thaw_after_trim ()
{
RegionView::thaw_after_trim ();
-
unhide_envelope ();
+ drag_end ();
+}
+
+void
+AudioRegionView::redraw_start_xfade ()
+{
+ boost::shared_ptr ar (audio_region());
+
+ if (!ar->fade_in() || ar->fade_in()->empty()) {
+ return;
+ }
+
+ if (!ar->fade_in_is_xfade()) {
+ if (start_xfade_in) {
+ start_xfade_in->hide ();
+ start_xfade_out->hide ();
+ start_xfade_rect->hide ();
+ }
+ return;
+ }
+
+ redraw_start_xfade_to (ar, ar->fade_in()->back()->when);
+}
+
+void
+AudioRegionView::redraw_start_xfade_to (boost::shared_ptr ar, framecnt_t len)
+{
+ int32_t const npoints = trackview.editor().frame_to_pixel (len);
+
+ if (npoints < 3) {
+ return;
+ }
+
+ if (!start_xfade_in) {
+ start_xfade_in = new ArdourCanvas::Line (*group);
+ start_xfade_in->property_width_pixels() = 1;
+ start_xfade_in->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_GainLine.get();
+ }
+
+ if (!start_xfade_out) {
+ start_xfade_out = new ArdourCanvas::Line (*group);
+ start_xfade_out->property_width_pixels() = 1;
+ start_xfade_out->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_GainLine.get();
+ }
+
+ if (!start_xfade_rect) {
+ start_xfade_rect = new ArdourCanvas::SimpleRect (*group);
+ start_xfade_rect->property_draw() = true;
+ start_xfade_rect->property_fill() = true;;
+ start_xfade_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_ActiveCrossfade.get();
+ start_xfade_rect->property_outline_pixels() = 0;
+ start_xfade_rect->signal_event().connect (sigc::bind (sigc::mem_fun (PublicEditor::instance(), &PublicEditor::canvas_start_xfade_event), start_xfade_rect, this));
+ start_xfade_rect->set_data ("regionview", this);
+ }
+
+ Points* points = get_canvas_points ("xfade edit redraw", npoints);
+ boost::scoped_ptr vec (new float[npoints]);
+ double effective_height = _height - NAME_HIGHLIGHT_SIZE - 1.0;
+
+ ar->fade_in()->curve().get_vector (0, ar->fade_in()->back()->when, vec.get(), npoints);
+
+ for (int i = 0, pci = 0; i < npoints; ++i) {
+ Gnome::Art::Point &p ((*points)[pci++]);
+ p.set_x (i);
+ p.set_y (1.0 + effective_height - (effective_height * vec.get()[i]));
+ }
+
+ start_xfade_rect->property_x1() = ((*points)[0]).get_x();
+ start_xfade_rect->property_y1() = 1.0;
+ start_xfade_rect->property_x2() = ((*points)[npoints-1]).get_x();
+ start_xfade_rect->property_y2() = effective_height;
+ start_xfade_rect->show ();
+ start_xfade_rect->raise_to_top ();
+
+ start_xfade_in->property_points() = *points;
+ start_xfade_in->show ();
+ start_xfade_in->raise_to_top ();
+
+ /* fade out line */
+
+ boost::shared_ptr inverse = ar->inverse_fade_in();
+
+ if (!inverse) {
+
+ for (int i = 0, pci = 0; i < npoints; ++i) {
+ Gnome::Art::Point &p ((*points)[pci++]);
+ p.set_x (i);
+ p.set_y (1.0 + effective_height - (effective_height * (1.0 - vec.get()[i])));
+ }
+
+ } else {
+
+ inverse->curve().get_vector (0, inverse->back()->when, vec.get(), npoints);
+
+ for (int i = 0, pci = 0; i < npoints; ++i) {
+ Gnome::Art::Point &p ((*points)[pci++]);
+ p.set_x (i);
+ p.set_y (1.0 + effective_height - (effective_height * vec.get()[i]));
+ }
+ }
+
+ start_xfade_out->property_points() = *points;
+ start_xfade_out->show ();
+ start_xfade_out->raise_to_top ();
+
+ delete points;
+}
+
+void
+AudioRegionView::redraw_end_xfade ()
+{
+ boost::shared_ptr ar (audio_region());
+
+ if (!ar->fade_out() || ar->fade_out()->empty()) {
+ return;
+ }
+
+ if (!ar->fade_out_is_xfade()) {
+ if (end_xfade_in) {
+ end_xfade_in->hide ();
+ end_xfade_out->hide ();
+ end_xfade_rect->hide ();
+ }
+ return;
+ }
+
+ redraw_end_xfade_to (ar, ar->fade_out()->back()->when);
+}
+
+void
+AudioRegionView::redraw_end_xfade_to (boost::shared_ptr ar, framecnt_t len)
+{
+ int32_t const npoints = trackview.editor().frame_to_pixel (len);
+
+ if (npoints < 3) {
+ return;
+ }
+
+ if (!end_xfade_in) {
+ end_xfade_in = new ArdourCanvas::Line (*group);
+ end_xfade_in->property_width_pixels() = 1;
+ end_xfade_in->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_GainLine.get();
+ }
+
+ if (!end_xfade_out) {
+ end_xfade_out = new ArdourCanvas::Line (*group);
+ end_xfade_out->property_width_pixels() = 1;
+ end_xfade_out->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_GainLine.get();
+ }
+
+ if (!end_xfade_rect) {
+ end_xfade_rect = new ArdourCanvas::SimpleRect (*group);
+ end_xfade_rect->property_draw() = true;
+ end_xfade_rect->property_fill() = true;;
+ end_xfade_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_ActiveCrossfade.get();
+ end_xfade_rect->property_outline_pixels() = 0;
+ end_xfade_rect->signal_event().connect (sigc::bind (sigc::mem_fun (PublicEditor::instance(), &PublicEditor::canvas_end_xfade_event), end_xfade_rect, this));
+ end_xfade_rect->set_data ("regionview", this);
+ }
+
+ Points* points = get_canvas_points ("xfade edit redraw", npoints);
+ boost::scoped_ptr vec (new float[npoints]);
+
+ ar->fade_out()->curve().get_vector (0, ar->fade_out()->back()->when, vec.get(), npoints);
+
+ double rend = trackview.editor().frame_to_pixel (_region->length() - len);
+ double effective_height = _height - NAME_HIGHLIGHT_SIZE - 1;
+
+ for (int i = 0, pci = 0; i < npoints; ++i) {
+ Gnome::Art::Point &p ((*points)[pci++]);
+ p.set_x (rend + i);
+ p.set_y (1.0 + effective_height - (effective_height * vec.get()[i]));
+ }
+
+ end_xfade_rect->property_x1() = ((*points)[0]).get_x();
+ end_xfade_rect->property_y1() = 1;
+ end_xfade_rect->property_x2() = ((*points)[npoints-1]).get_x();
+ end_xfade_rect->property_y2() = effective_height;
+ end_xfade_rect->show ();
+ end_xfade_rect->raise_to_top ();
+
+ end_xfade_in->property_points() = *points;
+ end_xfade_in->show ();
+ end_xfade_in->raise_to_top ();
+
+ /* fade in line */
+
+ boost::shared_ptr inverse = ar->inverse_fade_out ();
+
+ if (!inverse) {
+
+ for (int i = 0, pci = 0; i < npoints; ++i) {
+ Gnome::Art::Point &p ((*points)[pci++]);
+ p.set_x (rend + i);
+ p.set_y (1.0 + effective_height - (effective_height * (1.0 - vec.get()[i])));
+ }
+
+ } else {
+
+ inverse->curve().get_vector (inverse->front()->when, inverse->back()->when, vec.get(), npoints);
+
+ for (int i = 0, pci = 0; i < npoints; ++i) {
+ Gnome::Art::Point &p ((*points)[pci++]);
+ p.set_x (rend + i);
+ p.set_y (1.0 + effective_height - (effective_height * vec.get()[i]));
+ }
+ }
+
+ end_xfade_out->property_points() = *points;
+ end_xfade_out->show ();
+ end_xfade_out->raise_to_top ();
+
+
+ delete points;
+}
+
+void
+AudioRegionView::hide_xfades ()
+{
+ if (start_xfade_in) {
+ start_xfade_in->hide();
+ }
+ if (start_xfade_out) {
+ start_xfade_out->hide();
+ }
+ if (start_xfade_rect) {
+ start_xfade_rect->hide ();
+ }
+ if (end_xfade_in) {
+ end_xfade_in->hide();
+ }
+ if (end_xfade_out) {
+ end_xfade_out->hide();
+ }
+ if (end_xfade_rect) {
+ end_xfade_rect->hide ();
+ }
+}
+
+void
+AudioRegionView::show_xfades ()
+{
+ if (start_xfade_in) {
+ start_xfade_in->show();
+ }
+ if (start_xfade_out) {
+ start_xfade_out->show();
+ }
+ if (start_xfade_rect) {
+ start_xfade_rect->show ();
+ }
+ if (end_xfade_in) {
+ end_xfade_in->show();
+ }
+ if (end_xfade_out) {
+ end_xfade_out->show();
+ }
+ if (end_xfade_rect) {
+ end_xfade_rect->show ();
+ }
+}
+
+void
+AudioRegionView::drag_start ()
+{
+ TimeAxisViewItem::drag_start ();
+ AudioTimeAxisView* atav = dynamic_cast (&trackview);
+
+ if (atav) {
+ AudioStreamView* av = atav->audio_view();
+ if (av) {
+ /* this will hide our xfades too */
+ av->hide_xfades_with (audio_region());
+ }
+ }
+}
+
+void
+AudioRegionView::drag_end ()
+{
+ TimeAxisViewItem::drag_end ();
+ /* fades will be redrawn if they changed */
}
diff --git a/gtk2_ardour/audio_region_view.h b/gtk2_ardour/audio_region_view.h
index 9dc7e507a1..233b53475b 100644
--- a/gtk2_ardour/audio_region_view.h
+++ b/gtk2_ardour/audio_region_view.h
@@ -117,6 +117,17 @@ class AudioRegionView : public RegionView
void thaw_after_trim ();
+ void drag_start ();
+ void drag_end ();
+
+ void redraw_start_xfade_to (boost::shared_ptr, framecnt_t);
+ void redraw_end_xfade_to (boost::shared_ptr, framecnt_t);
+ void redraw_start_xfade ();
+ void redraw_end_xfade ();
+
+ void hide_xfades ();
+ void show_xfades ();
+
protected:
/* this constructor allows derived types
@@ -142,6 +153,14 @@ class AudioRegionView : public RegionView
ArdourCanvas::SimpleRect* fade_out_handle; ///< fade out handle, or 0
ArdourCanvas::SimpleLine* fade_position_line;
+ ArdourCanvas::Line *start_xfade_in;
+ ArdourCanvas::Line *start_xfade_out;
+ ArdourCanvas::SimpleRect* start_xfade_rect;
+
+ ArdourCanvas::Line *end_xfade_in;
+ ArdourCanvas::Line *end_xfade_out;
+ ArdourCanvas::SimpleRect* end_xfade_rect;
+
boost::shared_ptr gain_line;
double _amplitude_above_axis;
@@ -180,7 +199,6 @@ class AudioRegionView : public RegionView
void transients_changed();
private:
-
void setup_fade_handle_positions ();
/** A ScopedConnection for each PeaksReady callback (one per channel). Each member
diff --git a/gtk2_ardour/audio_streamview.cc b/gtk2_ardour/audio_streamview.cc
index e9ee8fe647..be8601170f 100644
--- a/gtk2_ardour/audio_streamview.cc
+++ b/gtk2_ardour/audio_streamview.cc
@@ -532,6 +532,23 @@ AudioStreamView::hide_all_fades ()
}
}
+void
+AudioStreamView::hide_xfades_with (boost::shared_ptr ar)
+{
+ for (list::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+ AudioRegionView* const arv = dynamic_cast(*i);
+ if (arv) {
+ switch (arv->region()->coverage (ar->position(), ar->last_frame())) {
+ case Evoral::OverlapNone:
+ break;
+ default:
+ arv->hide_xfades ();
+ break;
+ }
+ }
+ }
+}
+
void
AudioStreamView::color_handler ()
{
diff --git a/gtk2_ardour/audio_streamview.h b/gtk2_ardour/audio_streamview.h
index 4812903a35..cb3175798e 100644
--- a/gtk2_ardour/audio_streamview.h
+++ b/gtk2_ardour/audio_streamview.h
@@ -61,6 +61,8 @@ class AudioStreamView : public StreamView
void show_all_fades ();
void hide_all_fades ();
+ void hide_xfades_with (boost::shared_ptr ar);
+
RegionView* create_region_view (boost::shared_ptr, bool, bool);
private:
diff --git a/gtk2_ardour/automation_time_axis.cc b/gtk2_ardour/automation_time_axis.cc
index 4b10ea5cb5..3332a066d9 100644
--- a/gtk2_ardour/automation_time_axis.cc
+++ b/gtk2_ardour/automation_time_axis.cc
@@ -900,3 +900,69 @@ AutomationTimeAxisView::parse_state_id (
return true;
}
+
+void
+AutomationTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
+{
+ list > lines;
+ if (_line) {
+ lines.push_back (_line);
+ } else if (_view) {
+ lines = _view->get_lines ();
+ }
+
+ for (list >::iterator i = lines.begin(); i != lines.end(); ++i) {
+ cut_copy_clear_one (**i, selection, op);
+ }
+}
+
+void
+AutomationTimeAxisView::cut_copy_clear_one (AutomationLine& line, Selection& selection, CutCopyOp op)
+{
+ boost::shared_ptr what_we_got;
+ boost::shared_ptr alist (line.the_list());
+
+ XMLNode &before = alist->get_state();
+
+ /* convert time selection to automation list model coordinates */
+ const Evoral::TimeConverter& tc = line.time_converter ();
+ double const start = tc.from (selection.time.front().start - tc.origin_b ());
+ double const end = tc.from (selection.time.front().end - tc.origin_b ());
+
+ switch (op) {
+ case Delete:
+ if (alist->cut (start, end) != 0) {
+ _session->add_command(new MementoCommand(*alist.get(), &before, &alist->get_state()));
+ }
+ break;
+
+ case Cut:
+
+ if ((what_we_got = alist->cut (start, end)) != 0) {
+ _editor.get_cut_buffer().add (what_we_got);
+ _session->add_command(new MementoCommand(*alist.get(), &before, &alist->get_state()));
+ }
+ break;
+ case Copy:
+ if ((what_we_got = alist->copy (start, end)) != 0) {
+ _editor.get_cut_buffer().add (what_we_got);
+ }
+ break;
+
+ case Clear:
+ if ((what_we_got = alist->cut (start, end)) != 0) {
+ _session->add_command(new MementoCommand(*alist.get(), &before, &alist->get_state()));
+ }
+ break;
+ }
+
+ if (what_we_got) {
+ for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) {
+ double when = (*x)->when;
+ double val = (*x)->value;
+ line.model_to_view_coord (when, val);
+ (*x)->when = when;
+ (*x)->value = val;
+ }
+ }
+}
diff --git a/gtk2_ardour/automation_time_axis.h b/gtk2_ardour/automation_time_axis.h
index 913cd1b467..d883b189c0 100644
--- a/gtk2_ardour/automation_time_axis.h
+++ b/gtk2_ardour/automation_time_axis.h
@@ -91,6 +91,7 @@ class AutomationTimeAxisView : public TimeAxisView {
/* editing operations */
+ void cut_copy_clear (Selection&, Editing::CutCopyOp);
bool paste (ARDOUR::framepos_t, float times, Selection&, size_t nth);
int set_state (const XMLNode&, int version);
@@ -166,6 +167,7 @@ class AutomationTimeAxisView : public TimeAxisView {
void build_display_menu ();
+ void cut_copy_clear_one (AutomationLine&, Selection&, Editing::CutCopyOp);
bool paste_one (AutomationLine&, ARDOUR::framepos_t, float times, Selection&, size_t nth);
void route_going_away ();
diff --git a/gtk2_ardour/button_joiner.cc b/gtk2_ardour/button_joiner.cc
index 86bb055d01..085d5d30b2 100644
--- a/gtk2_ardour/button_joiner.cc
+++ b/gtk2_ardour/button_joiner.cc
@@ -138,7 +138,7 @@ ButtonJoiner::on_size_allocate (Allocation& alloc)
}
bool
-ButtonJoiner::on_button_release_event (GdkEventButton* ev)
+ButtonJoiner::on_button_release_event (GdkEventButton*)
{
if (_action) {
_action->activate ();
diff --git a/gtk2_ardour/canvas-simpleline.c b/gtk2_ardour/canvas-simpleline.c
index 39a1901f57..efff5034f9 100644
--- a/gtk2_ardour/canvas-simpleline.c
+++ b/gtk2_ardour/canvas-simpleline.c
@@ -389,8 +389,8 @@ gnome_canvas_simpleline_render (GnomeCanvasItem *item,
}
static void
-gnome_canvas_simpleline_draw (GnomeCanvasItem *canvas,
- GdkDrawable *drawable,
+gnome_canvas_simpleline_draw (GnomeCanvasItem* canvas,
+ GdkDrawable* drawable,
int x, int y,
int width, int height)
{
diff --git a/gtk2_ardour/crossfade_edit.cc b/gtk2_ardour/crossfade_edit.cc
index 65031917c7..3f6610d49d 100644
--- a/gtk2_ardour/crossfade_edit.cc
+++ b/gtk2_ardour/crossfade_edit.cc
@@ -889,7 +889,7 @@ CrossfadeEditor::build_presets ()
/* FADE IN */
- p = new Preset ("Linear (-6dB)", "crossfade-in-linear");
+ p = new Preset ("Linear (-6dB)", "fadein-linear");
p->push_back (PresetPoint (0, 0));
p->push_back (PresetPoint (0.000000, 0.000000));
p->push_back (PresetPoint (0.166667, 0.166366));
@@ -900,7 +900,7 @@ CrossfadeEditor::build_presets ()
p->push_back (PresetPoint (1.000000, 1.000000));
fade_in_presets->push_back (p);
- p = new Preset ("S(1)-curve", "crossfade-in-S1");
+ p = new Preset ("S(1)-curve", "fadein-S1");
p->push_back (PresetPoint (0, 0));
p->push_back (PresetPoint (0.1, 0.01));
p->push_back (PresetPoint (0.2, 0.03));
@@ -909,7 +909,7 @@ CrossfadeEditor::build_presets ()
p->push_back (PresetPoint (1, 1));
fade_in_presets->push_back (p);
- p = new Preset ("S(2)-curve", "crossfade-in-S2");
+ p = new Preset ("S(2)-curve", "fadein-S2");
p->push_back (PresetPoint (0.0, 0.0));
p->push_back (PresetPoint (0.055, 0.222));
p->push_back (PresetPoint (0.163, 0.35));
@@ -918,7 +918,7 @@ CrossfadeEditor::build_presets ()
p->push_back (PresetPoint (1.0, 1.0));
fade_in_presets->push_back (p);
- p = new Preset ("Constant Power (-3dB)", "crossfade-in-constant-power");
+ p = new Preset ("Constant Power (-3dB)", "fadein-constant-power");
p->push_back (PresetPoint (0.000000, 0.000000));
p->push_back (PresetPoint (0.166667, 0.282192));
@@ -932,7 +932,7 @@ CrossfadeEditor::build_presets ()
if (!Profile->get_sae()) {
- p = new Preset ("Short cut", "crossfade-in-short-cut");
+ p = new Preset ("Short cut", "fadein-short-cut");
p->push_back (PresetPoint (0, 0));
p->push_back (PresetPoint (0.389401, 0.0333333));
p->push_back (PresetPoint (0.629032, 0.0861111));
@@ -942,7 +942,7 @@ CrossfadeEditor::build_presets ()
p->push_back (PresetPoint (1, 1));
fade_in_presets->push_back (p);
- p = new Preset ("Slow cut", "crossfade-in-slow-cut");
+ p = new Preset ("Slow cut", "fadein-slow-cut");
p->push_back (PresetPoint (0, 0));
p->push_back (PresetPoint (0.304147, 0.0694444));
p->push_back (PresetPoint (0.529954, 0.152778));
@@ -952,7 +952,7 @@ CrossfadeEditor::build_presets ()
p->push_back (PresetPoint (1, 1));
fade_in_presets->push_back (p);
- p = new Preset ("Fast cut", "crossfade-in-fast-cut");
+ p = new Preset ("Fast cut", "fadein-fast-cut");
p->push_back (PresetPoint (0, 0));
p->push_back (PresetPoint (0.0737327, 0.308333));
p->push_back (PresetPoint (0.246544, 0.658333));
@@ -962,7 +962,7 @@ CrossfadeEditor::build_presets ()
p->push_back (PresetPoint (1, 1));
fade_in_presets->push_back (p);
- p = new Preset ("Long cut", "crossfade-in-long-cut");
+ p = new Preset ("Long cut", "fadein-long-cut");
p->push_back (PresetPoint (0, 0));
p->push_back (PresetPoint (0.0207373, 0.197222));
p->push_back (PresetPoint (0.0645161, 0.525));
@@ -977,7 +977,7 @@ CrossfadeEditor::build_presets ()
/* FADE OUT */
// p = new Preset ("regout.xpm");
- p = new Preset ("Linear (-6dB cut)", "crossfade-out-linear");
+ p = new Preset ("Linear (-6dB cut)", "fadeout-linear");
p->push_back (PresetPoint (0, 1));
p->push_back (PresetPoint (0.000000, 1.000000));
p->push_back (PresetPoint (0.166667, 0.833033));
@@ -988,7 +988,7 @@ CrossfadeEditor::build_presets ()
p->push_back (PresetPoint (1.000000, 0.000000));
fade_out_presets->push_back (p);
- p = new Preset ("S(1)-Curve", "crossfade-out-S1");
+ p = new Preset ("S(1)-Curve", "fadeout-S1");
p->push_back (PresetPoint (0, 1));
p->push_back (PresetPoint (0.1, 0.99));
p->push_back (PresetPoint (0.2, 0.97));
@@ -997,7 +997,7 @@ CrossfadeEditor::build_presets ()
p->push_back (PresetPoint (1, 0));
fade_out_presets->push_back (p);
- p = new Preset ("S(2)-Curve", "crossfade-out-S2");
+ p = new Preset ("S(2)-Curve", "fadeout-S2");
p->push_back (PresetPoint (0.0, 1.0));
p->push_back (PresetPoint (0.163, 0.678));
p->push_back (PresetPoint (0.055, 0.783));
@@ -1007,7 +1007,7 @@ CrossfadeEditor::build_presets ()
fade_out_presets->push_back (p);
// p = new Preset ("linout.xpm");
- p = new Preset ("Constant Power (-3dB cut)", "crossfade-out-constant-power");
+ p = new Preset ("Constant Power (-3dB cut)", "fadeout-constant-power");
p->push_back (PresetPoint (0.000000, 1.000000));
p->push_back (PresetPoint (0.166667, 0.948859));
p->push_back (PresetPoint (0.333333, 0.851507));
@@ -1019,7 +1019,7 @@ CrossfadeEditor::build_presets ()
if (!Profile->get_sae()) {
// p = new Preset ("hiout.xpm");
- p = new Preset ("Short cut", "crossfade-out-short-cut");
+ p = new Preset ("Short cut", "fadeout-short-cut");
p->push_back (PresetPoint (0, 1));
p->push_back (PresetPoint (0.305556, 1));
p->push_back (PresetPoint (0.548611, 0.991736));
@@ -1029,7 +1029,7 @@ CrossfadeEditor::build_presets ()
p->push_back (PresetPoint (1, 0));
fade_out_presets->push_back (p);
- p = new Preset ("Slow cut", "crossfade-out-slow-cut");
+ p = new Preset ("Slow cut", "fadeout-slow-cut");
p->push_back (PresetPoint (0, 1));
p->push_back (PresetPoint (0.228111, 0.988889));
p->push_back (PresetPoint (0.347926, 0.972222));
@@ -1039,7 +1039,7 @@ CrossfadeEditor::build_presets ()
p->push_back (PresetPoint (1, 0));
fade_out_presets->push_back (p);
- p = new Preset ("Fast cut", "crossfade-out-fast-cut");
+ p = new Preset ("Fast cut", "fadeout-fast-cut");
p->push_back (PresetPoint (0, 1));
p->push_back (PresetPoint (0.080645, 0.730556));
p->push_back (PresetPoint (0.277778, 0.289256));
@@ -1049,7 +1049,7 @@ CrossfadeEditor::build_presets ()
fade_out_presets->push_back (p);
// p = new Preset ("loout.xpm");
- p = new Preset ("Long cut", "crossfade-out-long-cut");
+ p = new Preset ("Long cut", "fadeout-long-cut");
p->push_back (PresetPoint (0, 1));
p->push_back (PresetPoint (0.023041, 0.697222));
p->push_back (PresetPoint (0.0553, 0.483333));
diff --git a/gtk2_ardour/curvetest.cc b/gtk2_ardour/curvetest.cc
index 498ed45eba..b3431e3f39 100644
--- a/gtk2_ardour/curvetest.cc
+++ b/gtk2_ardour/curvetest.cc
@@ -32,6 +32,11 @@ using namespace PBD;
int
curvetest (string filename)
{
+ // needed to initialize ID objects/counter used
+ // by Curve et al.
+
+ PBD::ID::init ();
+
ifstream in (filename.c_str());
stringstream line;
//Evoral::Parameter param(GainAutomation, -1.0, +1.0, 0.0);
@@ -40,11 +45,6 @@ curvetest (string filename)
double minx = DBL_MAX;
double maxx = DBL_MIN;
- // needed to initialize ID objects/counter used
- // by Curve et al.
-
- PBD::ID::init ();
-
while (in) {
double x, y;
diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc
index b7f768adca..5e3810977c 100644
--- a/gtk2_ardour/editor.cc
+++ b/gtk2_ardour/editor.cc
@@ -548,7 +548,7 @@ Editor::Editor ()
add_notebook_page (_("Regions"), _regions->widget ());
add_notebook_page (_("Tracks & Busses"), _routes->widget ());
add_notebook_page (_("Snapshots"), _snapshots->widget ());
- add_notebook_page (_("Route Groups"), _route_groups->widget ());
+ add_notebook_page (_("Track & Bus Groups"), _route_groups->widget ());
add_notebook_page (_("Ranges & Marks"), _locations->widget ());
_the_notebook.set_show_tabs (true);
@@ -721,6 +721,7 @@ Editor::Editor ()
ControlProtocol::AddRouteToSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Add), gui_context());
ControlProtocol::RemoveRouteFromSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
ControlProtocol::SetRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Set), gui_context());
+ ControlProtocol::ToggleRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
ControlProtocol::ClearRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_unselect, this), gui_context());
BasicUI::AccessAction.connect (*this, invalidator (*this), boost::bind (&Editor::access_action, this, _1, _2), gui_context());
@@ -1340,6 +1341,101 @@ Editor::action_pre_activated (Glib::RefPtr const & a)
}
}
+void
+Editor::fill_xfade_menu (Menu_Helpers::MenuList& items, bool start)
+{
+ using namespace Menu_Helpers;
+
+ void (Editor::*emf)(FadeShape);
+ std::map* images;
+
+ if (start) {
+ images = &_xfade_in_images;
+ emf = &Editor::set_fade_in_shape;
+ } else {
+ images = &_xfade_out_images;
+ emf = &Editor::set_fade_out_shape;
+ }
+
+ items.push_back (
+ ImageMenuElem (
+ _("Linear (for highly correlated material)"),
+ *(*images)[FadeLinear],
+ sigc::bind (sigc::mem_fun (*this, emf), FadeLinear)
+ )
+ );
+
+ dynamic_cast(&items.back())->set_always_show_image ();
+
+ items.push_back (
+ ImageMenuElem (
+ _("ConstantPower"),
+ *(*images)[FadeConstantPower],
+ sigc::bind (sigc::mem_fun (*this, emf), FadeConstantPower)
+ ));
+
+ dynamic_cast(&items.back())->set_always_show_image ();
+
+ items.push_back (
+ ImageMenuElem (
+ _("Symmetric"),
+ *(*images)[FadeSymmetric],
+ sigc::bind (sigc::mem_fun (*this, emf), FadeSymmetric)
+ )
+ );
+
+ dynamic_cast(&items.back())->set_always_show_image ();
+
+ items.push_back (
+ ImageMenuElem (
+ _("Slow"),
+ *(*images)[FadeSlow],
+ sigc::bind (sigc::mem_fun (*this, emf), FadeSlow)
+ ));
+
+ dynamic_cast(&items.back())->set_always_show_image ();
+
+ items.push_back (
+ ImageMenuElem (
+ _("Fast"),
+ *(*images)[FadeFast],
+ sigc::bind (sigc::mem_fun (*this, emf), FadeFast)
+ ));
+
+ dynamic_cast(&items.back())->set_always_show_image ();
+}
+
+/** Pop up a context menu for when the user clicks on a start crossfade */
+void
+Editor::popup_xfade_in_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType item_type)
+{
+ using namespace Menu_Helpers;
+
+ MenuList& items (xfade_in_context_menu.items());
+
+ if (items.empty()) {
+ fill_xfade_menu (items, true);
+ }
+
+ xfade_in_context_menu.popup (button, time);
+}
+
+/** Pop up a context menu for when the user clicks on an end crossfade */
+void
+Editor::popup_xfade_out_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType item_type)
+{
+ using namespace Menu_Helpers;
+
+ MenuList& items (xfade_out_context_menu.items());
+
+ if (items.empty()) {
+ fill_xfade_menu (items, false);
+ }
+
+ xfade_out_context_menu.popup (button, time);
+}
+
+
/** Pop up a context menu for when the user clicks on a fade in or fade out */
void
Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType item_type)
@@ -1386,7 +1482,16 @@ Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* i
items.push_back (
ImageMenuElem (
- _("Slowest"),
+ _("Slow"),
+ *_fade_in_images[FadeSlow],
+ sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_shape), FadeSlow)
+ ));
+
+ dynamic_cast(&items.back())->set_always_show_image ();
+
+ items.push_back (
+ ImageMenuElem (
+ _("Fast"),
*_fade_in_images[FadeFast],
sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_shape), FadeFast)
));
@@ -1395,27 +1500,16 @@ Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* i
items.push_back (
ImageMenuElem (
- _("Slow"),
- *_fade_in_images[FadeLogB],
- sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_shape), FadeLogB)
- ));
-
- dynamic_cast(&items.back())->set_always_show_image ();
-
- items.push_back (
- ImageMenuElem (
- _("Fast"),
- *_fade_in_images[FadeLogA],
- sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_shape), FadeLogA)
- ));
-
- dynamic_cast(&items.back())->set_always_show_image ();
-
- items.push_back (
- ImageMenuElem (
- _("Fastest"),
+ _("Symmetric"),
*_fade_in_images[FadeSlow],
- sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_shape), FadeSlow)
+ sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_shape), FadeSymmetric)
+ ));
+
+ items.push_back (
+ ImageMenuElem (
+ _("Constant Power"),
+ *_fade_in_images[FadeConstantPower],
+ sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_shape), FadeConstantPower)
));
dynamic_cast(&items.back())->set_always_show_image ();
@@ -1450,36 +1544,34 @@ Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* i
items.push_back (
ImageMenuElem (
- _("Slowest"),
- *_fade_out_images[FadeFast],
+ _("Slow"),
+ *_fade_out_images[FadeSlow],
sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_shape), FadeSlow)
));
dynamic_cast(&items.back())->set_always_show_image ();
- items.push_back (
- ImageMenuElem (
- _("Slow"),
- *_fade_out_images[FadeLogB],
- sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_shape), FadeLogA)
- ));
-
- dynamic_cast(&items.back())->set_always_show_image ();
-
items.push_back (
ImageMenuElem (
_("Fast"),
- *_fade_out_images[FadeLogA],
- sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_shape), FadeLogB)
+ *_fade_out_images[FadeFast],
+ sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_shape), FadeFast)
));
dynamic_cast(&items.back())->set_always_show_image ();
items.push_back (
ImageMenuElem (
- _("Fastest"),
+ _("Symmetric"),
*_fade_out_images[FadeSlow],
- sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_shape), FadeFast)
+ sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_shape), FadeSymmetric)
+ ));
+
+ items.push_back (
+ ImageMenuElem (
+ _("Constant Power"),
+ *_fade_out_images[FadeConstantPower],
+ sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_shape), FadeConstantPower)
));
dynamic_cast(&items.back())->set_always_show_image ();
@@ -5282,17 +5374,30 @@ Editor::update_region_layering_order_editor ()
void
Editor::setup_fade_images ()
{
- _fade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("crossfade-in-linear")));
- _fade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("crossfade-in-short-cut")));
- _fade_in_images[FadeLogB] = new Gtk::Image (get_icon_path (X_("crossfade-in-slow-cut")));
- _fade_in_images[FadeLogA] = new Gtk::Image (get_icon_path (X_("crossfade-in-fast-cut")));
- _fade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("crossfade-in-long-cut")));
+ _fade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
+ _fade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-short-cut")));
+ _fade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
+ _fade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
+ _fade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-long-cut")));
+
+ _fade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
+ _fade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-short-cut")));
+ _fade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
+ _fade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
+ _fade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-long-cut")));
+
+ _xfade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
+ _xfade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-short-cut")));
+ _xfade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
+ _xfade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
+ _xfade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-long-cut")));
+
+ _xfade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
+ _xfade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-short-cut")));
+ _xfade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
+ _xfade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
+ _xfade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-long-cut")));
- _fade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("crossfade-out-linear")));
- _fade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("crossfade-out-short-cut")));
- _fade_out_images[FadeLogB] = new Gtk::Image (get_icon_path (X_("crossfade-out-slow-cut")));
- _fade_out_images[FadeLogA] = new Gtk::Image (get_icon_path (X_("crossfade-out-fast-cut")));
- _fade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("crossfade-out-long-cut")));
}
/** @return Gtk::manage()d menu item for a given action from `editor_actions' */
diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
index 589b0ead6c..2e203e9c75 100644
--- a/gtk2_ardour/editor.h
+++ b/gtk2_ardour/editor.h
@@ -1337,6 +1337,12 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
Gtk::Menu fade_context_menu;
void popup_fade_context_menu (int, int, ArdourCanvas::Item*, ItemType);
+ Gtk::Menu xfade_in_context_menu;
+ Gtk::Menu xfade_out_context_menu;
+ void popup_xfade_in_context_menu (int, int, ArdourCanvas::Item*, ItemType);
+ void popup_xfade_out_context_menu (int, int, ArdourCanvas::Item*, ItemType);
+ void fill_xfade_menu (Gtk::Menu_Helpers::MenuList& items, bool start);
+
void set_fade_in_shape (ARDOUR::FadeShape);
void set_fade_out_shape (ARDOUR::FadeShape);
@@ -1374,6 +1380,8 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
bool canvas_selection_rect_event (GdkEvent* event,ArdourCanvas::Item*, SelectionRect*);
bool canvas_selection_start_trim_event (GdkEvent* event,ArdourCanvas::Item*, SelectionRect*);
bool canvas_selection_end_trim_event (GdkEvent* event,ArdourCanvas::Item*, SelectionRect*);
+ bool canvas_start_xfade_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*);
+ bool canvas_end_xfade_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*);
bool canvas_fade_in_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*);
bool canvas_fade_in_handle_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*);
bool canvas_fade_out_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*);
@@ -2057,6 +2065,8 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
void setup_fade_images ();
std::map _fade_in_images;
std::map _fade_out_images;
+ std::map _xfade_in_images;
+ std::map _xfade_out_images;
Gtk::MenuItem& action_menu_item (std::string const &);
void action_pre_activated (Glib::RefPtr const &);
diff --git a/gtk2_ardour/editor_canvas_events.cc b/gtk2_ardour/editor_canvas_events.cc
index 72de353500..77bc5ec27b 100644
--- a/gtk2_ardour/editor_canvas_events.cc
+++ b/gtk2_ardour/editor_canvas_events.cc
@@ -348,6 +348,70 @@ Editor::canvas_automation_track_event (GdkEvent *event, ArdourCanvas::Item* item
return ret;
}
+bool
+Editor::canvas_start_xfade_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
+{
+ if (!rv->sensitive()) {
+ return false;
+ }
+
+ switch (event->type) {
+ case GDK_BUTTON_PRESS:
+ clicked_regionview = rv;
+ clicked_control_point = 0;
+ clicked_axisview = &rv->get_time_axis_view();
+ clicked_routeview = dynamic_cast(clicked_axisview);
+ if (event->button.button == 3) {
+ return button_press_handler (item, event, StartCrossFadeItem);
+ }
+ break;
+
+ case GDK_BUTTON_RELEASE:
+ if (event->button.button == 3) {
+ return button_release_handler (item, event, StartCrossFadeItem);
+ }
+ break;
+
+ default:
+ break;
+
+ }
+
+ return typed_event (item, event, StartCrossFadeItem);
+}
+
+bool
+Editor::canvas_end_xfade_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
+{
+ if (!rv->sensitive()) {
+ return false;
+ }
+
+ switch (event->type) {
+ case GDK_BUTTON_PRESS:
+ clicked_regionview = rv;
+ clicked_control_point = 0;
+ clicked_axisview = &rv->get_time_axis_view();
+ clicked_routeview = dynamic_cast(clicked_axisview);
+ if (event->button.button == 3) {
+ return button_press_handler (item, event, EndCrossFadeItem);
+ }
+ break;
+
+ case GDK_BUTTON_RELEASE:
+ if (event->button.button == 3) {
+ return button_release_handler (item, event, EndCrossFadeItem);
+ }
+ break;
+
+ default:
+ break;
+
+ }
+
+ return typed_event (item, event, EndCrossFadeItem);
+}
+
bool
Editor::canvas_fade_in_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
{
diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc
index c418e85018..97590be1a9 100644
--- a/gtk2_ardour/editor_drag.cc
+++ b/gtk2_ardour/editor_drag.cc
@@ -663,7 +663,7 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
if (first_move) {
- rv->get_time_axis_view().hide_dependent_views (*rv);
+ rv->drag_start ();
/* Absolutely no idea why this is necessary, but it is; without
it, the region view disappears after the reparent.
@@ -698,15 +698,15 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
if (tv->view()->layer_display() == Stacked) {
tv->view()->set_layer_display (Expanded);
}
-
+
/* We're only allowed to go -ve in layer on Expanded views */
if (tv->view()->layer_display() != Expanded && (i->layer + this_delta_layer) < 0) {
this_delta_layer = - i->layer;
}
-
+
/* Set height */
rv->set_height (tv->view()->child_height ());
-
+
/* Update show/hidden status as the region view may have come from a hidden track,
or have moved to one.
*/
@@ -1063,7 +1063,7 @@ RegionMoveDrag::finished_no_copy (
rv->get_canvas_group()->reparent (*dest_rtv->view()->canvas_item());
rv->get_canvas_group()->property_y() = i->initial_y;
- rv->get_time_axis_view().reveal_dependent_views (*rv);
+ rv->drag_end ();
/* just change the model */
@@ -1277,7 +1277,7 @@ RegionMotionDrag::aborted (bool)
assert (rtv);
rv->get_canvas_group()->reparent (*rtv->view()->canvas_item());
rv->get_canvas_group()->property_y() = 0;
- rv->get_time_axis_view().reveal_dependent_views (*rv);
+ rv->drag_end ();
rv->fake_set_opaque (false);
rv->move (-_total_x_delta, 0);
rv->set_height (rtv->view()->child_height ());
@@ -1706,6 +1706,7 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
if (arv) {
arv->temporarily_hide_envelope ();
+ arv->drag_start ();
}
boost::shared_ptr pl = rv->region()->playlist();
@@ -4360,7 +4361,7 @@ MidiRubberbandSelectDrag::MidiRubberbandSelectDrag (Editor* e, MidiRegionView* r
}
void
-MidiRubberbandSelectDrag::select_things (int button_state, framepos_t x1, framepos_t x2, double y1, double y2, bool drag_in_progress)
+MidiRubberbandSelectDrag::select_things (int button_state, framepos_t x1, framepos_t x2, double y1, double y2, bool /*drag_in_progress*/)
{
framepos_t const p = _region_view->region()->position ();
double const y = _region_view->midi_view()->y_position ();
@@ -4393,7 +4394,7 @@ MidiVerticalSelectDrag::MidiVerticalSelectDrag (Editor* e, MidiRegionView* rv)
}
void
-MidiVerticalSelectDrag::select_things (int button_state, framepos_t x1, framepos_t x2, double y1, double y2, bool drag_in_progress)
+MidiVerticalSelectDrag::select_things (int button_state, framepos_t /*x1*/, framepos_t /*x2*/, double y1, double y2, bool /*drag_in_progress*/)
{
double const y = _region_view->midi_view()->y_position ();
@@ -4516,7 +4517,7 @@ NoteCreateDrag::motion (GdkEvent* event, bool)
}
void
-NoteCreateDrag::finished (GdkEvent* event, bool had_movement)
+NoteCreateDrag::finished (GdkEvent*, bool had_movement)
{
if (!had_movement) {
return;
@@ -4550,3 +4551,100 @@ NoteCreateDrag::aborted (bool)
{
}
+
+/*------------*/
+
+CrossfadeEdgeDrag::CrossfadeEdgeDrag (Editor* e, AudioRegionView* rv, ArdourCanvas::Item* i, bool start_yn)
+ : Drag (e, i)
+ , arv (rv)
+ , start (start_yn)
+{
+}
+
+void
+CrossfadeEdgeDrag::start_grab (GdkEvent* event, Gdk::Cursor *cursor)
+{
+ Drag::start_grab (event, cursor);
+}
+
+void
+CrossfadeEdgeDrag::motion (GdkEvent*, bool)
+{
+ double distance;
+ double new_length;
+ framecnt_t len;
+
+ boost::shared_ptr ar (arv->audio_region());
+
+ if (start) {
+ distance = _drags->current_pointer_x() - grab_x();
+ len = ar->fade_in()->back()->when;
+ } else {
+ distance = grab_x() - _drags->current_pointer_x();
+ len = ar->fade_out()->back()->when;
+ }
+
+ /* how long should it be ? */
+
+ new_length = len + _editor->unit_to_frame (distance);
+
+ /* now check with the region that this is legal */
+
+ new_length = ar->verify_xfade_bounds (new_length, start);
+
+ if (start) {
+ arv->redraw_start_xfade_to (ar, new_length);
+ } else {
+ arv->redraw_end_xfade_to (ar, new_length);
+ }
+}
+
+void
+CrossfadeEdgeDrag::finished (GdkEvent*, bool)
+{
+ double distance;
+ double new_length;
+ framecnt_t len;
+
+ boost::shared_ptr ar (arv->audio_region());
+
+ if (start) {
+ distance = _drags->current_pointer_x() - grab_x();
+ len = ar->fade_in()->back()->when;
+ } else {
+ distance = grab_x() - _drags->current_pointer_x();
+ len = ar->fade_out()->back()->when;
+ }
+
+ new_length = ar->verify_xfade_bounds (len + _editor->unit_to_frame (distance), start);
+
+ _editor->begin_reversible_command ("xfade trim");
+ ar->playlist()->clear_owned_changes ();
+
+ if (start) {
+ ar->set_fade_in_length (new_length);
+ } else {
+ ar->set_fade_out_length (new_length);
+ }
+
+ /* Adjusting the xfade may affect other regions in the playlist, so we need
+ to get undo Commands from the whole playlist rather than just the
+ region.
+ */
+
+ vector cmds;
+ ar->playlist()->rdiff (cmds);
+ _editor->session()->add_commands (cmds);
+
+}
+
+void
+CrossfadeEdgeDrag::aborted (bool)
+{
+ if (start) {
+ arv->redraw_start_xfade ();
+ } else {
+ arv->redraw_end_xfade ();
+ }
+}
+
diff --git a/gtk2_ardour/editor_drag.h b/gtk2_ardour/editor_drag.h
index 0d457a39d9..2f81e06efc 100644
--- a/gtk2_ardour/editor_drag.h
+++ b/gtk2_ardour/editor_drag.h
@@ -972,5 +972,30 @@ private:
bool _nothing_to_drag;
};
+/** Drag of one edge of an xfade
+ */
+class CrossfadeEdgeDrag : public Drag
+{
+ public:
+ CrossfadeEdgeDrag (Editor*, AudioRegionView*, ArdourCanvas::Item*, bool start);
+
+ void start_grab (GdkEvent*, Gdk::Cursor* c = 0);
+ void motion (GdkEvent*, bool);
+ void finished (GdkEvent*, bool);
+ void aborted (bool);
+
+ bool y_movement_matters () const {
+ return false;
+ }
+
+ virtual std::pair move_threshold () const {
+ return std::make_pair (4, 4);
+ }
+
+ private:
+ AudioRegionView* arv;
+ bool start;
+};
+
#endif /* __gtk2_ardour_editor_drag_h_ */
diff --git a/gtk2_ardour/editor_items.h b/gtk2_ardour/editor_items.h
index 36a5a9e36f..51db6dbc87 100644
--- a/gtk2_ardour/editor_items.h
+++ b/gtk2_ardour/editor_items.h
@@ -50,6 +50,8 @@ enum ItemType {
FeatureLineItem,
LeftFrameHandle,
RightFrameHandle,
+ StartCrossFadeItem,
+ EndCrossFadeItem,
#ifdef WITH_CMT
MarkerViewItem,
diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc
index bd5cdd3f8f..d7d1c34280 100644
--- a/gtk2_ardour/editor_mouse.cc
+++ b/gtk2_ardour/editor_mouse.cc
@@ -640,11 +640,12 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
}
break;
-
case FadeInHandleItem:
case FadeInItem:
case FadeOutHandleItem:
case FadeOutItem:
+ case StartCrossFadeItem:
+ case EndCrossFadeItem:
if (doing_object_stuff() || (mouse_mode != MouseRange && mouse_mode != MouseObject)) {
set_selected_regionview_from_click (press, op);
} else if (event->type == GDK_BUTTON_PRESS) {
@@ -931,6 +932,14 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
return true;
}
+ case StartCrossFadeItem:
+ _drags->set (new CrossfadeEdgeDrag (this, reinterpret_cast(item->get_data("regionview")), item, true), event, 0);
+ break;
+
+ case EndCrossFadeItem:
+ _drags->set (new CrossfadeEdgeDrag (this, reinterpret_cast(item->get_data("regionview")), item, false), event, 0);
+ break;
+
case FeatureLineItem:
{
if (Keyboard::modifier_state_contains (event->button.state, Keyboard::TertiaryModifier)) {
@@ -1471,6 +1480,14 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
popup_fade_context_menu (1, event->button.time, item, item_type);
break;
+ case StartCrossFadeItem:
+ popup_xfade_in_context_menu (1, event->button.time, item, item_type);
+ break;
+
+ case EndCrossFadeItem:
+ popup_xfade_out_context_menu (1, event->button.time, item, item_type);
+ break;
+
case StreamItem:
popup_track_context_menu (1, event->button.time, item_type, false);
break;
@@ -1486,7 +1503,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
case SelectionItem:
popup_track_context_menu (1, event->button.time, item_type, true);
break;
-
+
case AutomationTrackItem:
popup_track_context_menu (1, event->button.time, item_type, false);
break;
diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc
index bae511e031..a8f1d1f6d7 100644
--- a/gtk2_ardour/editor_ops.cc
+++ b/gtk2_ardour/editor_ops.cc
@@ -4708,8 +4708,7 @@ Editor::quantize_region ()
qd->hide ();
if (r == Gtk::RESPONSE_OK) {
- Quantize quant (*_session, Plain,
- qd->snap_start(), qd->snap_end(),
+ Quantize quant (*_session, qd->snap_start(), qd->snap_end(),
qd->start_grid_size(), qd->end_grid_size(),
qd->strength(), qd->swing(), qd->threshold());
@@ -5250,6 +5249,10 @@ Editor::set_fade_out_active (bool yn)
void
Editor::toggle_region_fades (int dir)
{
+ if (_ignore_region_action) {
+ return;
+ }
+
boost::shared_ptr ar;
bool yn = false;
diff --git a/gtk2_ardour/editor_route_groups.cc b/gtk2_ardour/editor_route_groups.cc
index 1b72425032..2fd08e7609 100644
--- a/gtk2_ardour/editor_route_groups.cc
+++ b/gtk2_ardour/editor_route_groups.cc
@@ -380,7 +380,7 @@ EditorRouteGroups::button_press_event (GdkEventButton* ev)
}
void
-EditorRouteGroups::row_change (const Gtk::TreeModel::Path& path, const Gtk::TreeModel::iterator& iter)
+EditorRouteGroups::row_change (const Gtk::TreeModel::Path&, const Gtk::TreeModel::iterator& iter)
{
RouteGroup* group;
@@ -487,7 +487,7 @@ EditorRouteGroups::groups_changed ()
}
void
-EditorRouteGroups::property_changed (RouteGroup* group, const PropertyChange& change)
+EditorRouteGroups::property_changed (RouteGroup* group, const PropertyChange&)
{
_in_row_change = true;
diff --git a/gtk2_ardour/editor_selection.cc b/gtk2_ardour/editor_selection.cc
index fe93516063..20ab6673a8 100644
--- a/gtk2_ardour/editor_selection.cc
+++ b/gtk2_ardour/editor_selection.cc
@@ -1055,6 +1055,10 @@ Editor::sensitize_the_right_region_actions ()
bool have_envelope_inactive = false;
bool have_non_unity_scale_amplitude = false;
bool have_compound_regions = false;
+ bool have_inactive_fade_in = false;
+ bool have_inactive_fade_out = false;
+ bool have_active_fade_in = false;
+ bool have_active_fade_out = false;
for (list::const_iterator i = rs.begin(); i != rs.end(); ++i) {
@@ -1114,6 +1118,18 @@ Editor::sensitize_the_right_region_actions ()
if (ar->scale_amplitude() != 1) {
have_non_unity_scale_amplitude = true;
}
+
+ if (ar->fade_in_active ()) {
+ have_active_fade_in = true;
+ } else {
+ have_inactive_fade_in = true;
+ }
+
+ if (ar->fade_out_active ()) {
+ have_active_fade_out = true;
+ } else {
+ have_inactive_fade_out = true;
+ }
}
}
@@ -1168,7 +1184,7 @@ Editor::sensitize_the_right_region_actions ()
if (have_envelope_active && !have_envelope_inactive) {
Glib::RefPtr::cast_dynamic (_region_actions->get_action("toggle-region-gain-envelope-active"))->set_active ();
} else if (have_envelope_active && have_envelope_inactive) {
- // _region_actions->get_action("toggle-region-gain-envelope-active")->set_inconsistent ();
+ // Glib::RefPtr::cast_dynamic (_region_actions->get_action("toggle-region-gain-envelope-active"))->set_inconsistent ();
}
} else {
@@ -1184,25 +1200,29 @@ Editor::sensitize_the_right_region_actions ()
_region_actions->get_action("reset-region-scale-amplitude")->set_sensitive (false);
}
- Glib::RefPtr::cast_dynamic (_region_actions->get_action("toggle-region-lock"))->set_active (have_locked && !have_unlocked);
+ Glib::RefPtr a = Glib::RefPtr::cast_dynamic (_region_actions->get_action("toggle-region-lock"));
+ a->set_active (have_locked && !have_unlocked);
if (have_locked && have_unlocked) {
- // _region_actions->get_action("toggle-region-lock")->set_inconsistent ();
+ // a->set_inconsistent ();
}
- Glib::RefPtr::cast_dynamic (_region_actions->get_action("toggle-region-lock-style"))->set_active (have_position_lock_style_music && !have_position_lock_style_audio);
+ a = Glib::RefPtr::cast_dynamic (_region_actions->get_action("toggle-region-lock-style"));
+ a->set_active (have_position_lock_style_music && !have_position_lock_style_audio);
if (have_position_lock_style_music && have_position_lock_style_audio) {
- // _region_actions->get_action("toggle-region-lock-style")->set_inconsistent ();
+ // a->set_inconsistent ();
}
- Glib::RefPtr::cast_dynamic (_region_actions->get_action("toggle-region-mute"))->set_active (have_muted && !have_unmuted);
+ a = Glib::RefPtr::cast_dynamic (_region_actions->get_action("toggle-region-mute"));
+ a->set_active (have_muted && !have_unmuted);
if (have_muted && have_unmuted) {
- // _region_actions->get_action("toggle-region-mute")->set_inconsistent ();
+ // a->set_inconsistent ();
}
- Glib::RefPtr::cast_dynamic (_region_actions->get_action("toggle-opaque-region"))->set_active (have_opaque && !have_non_opaque);
+ a = Glib::RefPtr::cast_dynamic (_region_actions->get_action("toggle-opaque-region"));
+ a->set_active (have_opaque && !have_non_opaque);
if (have_opaque && have_non_opaque) {
- // _region_actions->get_action("toggle-opaque-region")->set_inconsistent ();
+ // a->set_inconsistent ();
}
if (!have_not_at_natural_position) {
@@ -1216,6 +1236,29 @@ Editor::sensitize_the_right_region_actions ()
_region_actions->get_action("insert-region-from-region-list")->set_sensitive (true);
}
+ a = Glib::RefPtr::cast_dynamic (_region_actions->get_action("toggle-region-fade-in"));
+ a->set_active (have_active_fade_in && !have_inactive_fade_in);
+ if (have_active_fade_in && have_inactive_fade_in) {
+ // a->set_inconsistent ();
+ }
+
+ a = Glib::RefPtr::cast_dynamic (_region_actions->get_action("toggle-region-fade-out"));
+ a->set_active (have_active_fade_out && !have_inactive_fade_out);
+
+ if (have_active_fade_out && have_inactive_fade_out) {
+ // a->set_inconsistent ();
+ }
+
+ bool const have_active_fade = have_active_fade_in || have_active_fade_out;
+ bool const have_inactive_fade = have_inactive_fade_in || have_inactive_fade_out;
+
+ a = Glib::RefPtr::cast_dynamic (_region_actions->get_action("toggle-region-fades"));
+ a->set_active (have_active_fade && !have_inactive_fade);
+
+ if (have_active_fade && have_inactive_fade) {
+ // a->set_inconsistent ();
+ }
+
_ignore_region_action = false;
_all_region_actions_sensitized = false;
diff --git a/gtk2_ardour/editor_snapshots.cc b/gtk2_ardour/editor_snapshots.cc
index d9c1489e82..c47c815984 100644
--- a/gtk2_ardour/editor_snapshots.cc
+++ b/gtk2_ardour/editor_snapshots.cc
@@ -121,7 +121,7 @@ EditorSnapshots::popup_context_menu (int button, int32_t time, std::string snaps
add_item_with_sensitivity (items, MenuElem (_("Remove"), sigc::bind (sigc::mem_fun (*this, &EditorSnapshots::remove), snapshot_name)), modification_allowed);
- add_item_with_sensitivity (items, MenuElem (_("Rename"), sigc::bind (sigc::mem_fun (*this, &EditorSnapshots::rename), snapshot_name)), modification_allowed);
+ add_item_with_sensitivity (items, MenuElem (_("Rename..."), sigc::bind (sigc::mem_fun (*this, &EditorSnapshots::rename), snapshot_name)), modification_allowed);
_menu.popup (button, time);
}
@@ -134,6 +134,7 @@ EditorSnapshots::rename (std::string old_name)
string new_name;
prompter.set_name ("Prompter");
+ prompter.set_title (_("Rename Snapshot"));
prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
prompter.set_prompt (_("New name of snapshot"));
prompter.set_initial_text (old_name);
diff --git a/gtk2_ardour/export_format_selector.cc b/gtk2_ardour/export_format_selector.cc
index d3ffce936a..146b31ab51 100644
--- a/gtk2_ardour/export_format_selector.cc
+++ b/gtk2_ardour/export_format_selector.cc
@@ -96,7 +96,7 @@ ExportFormatSelector::update_format_list ()
tree_it->set_value (format_cols.label, (*it)->description());
}
- if (format_combo.get_active_row_number() == -1) {
+ if (format_combo.get_active_row_number() == -1 && format_combo.get_model()->children().size() > 0) {
format_combo.set_active (0);
}
diff --git a/gtk2_ardour/group_tabs.cc b/gtk2_ardour/group_tabs.cc
index 9fa9c8bf73..5dbeeffd09 100644
--- a/gtk2_ardour/group_tabs.cc
+++ b/gtk2_ardour/group_tabs.cc
@@ -180,7 +180,7 @@ GroupTabs::on_motion_notify_event (GdkEventMotion* ev)
bool
-GroupTabs::on_button_release_event (GdkEventButton* ev)
+GroupTabs::on_button_release_event (GdkEventButton*)
{
if (_dragging == 0) {
return false;
diff --git a/gtk2_ardour/gtk_pianokeyboard.c b/gtk2_ardour/gtk_pianokeyboard.c
index 7332299bfb..1e5768040e 100644
--- a/gtk2_ardour/gtk_pianokeyboard.c
+++ b/gtk2_ardour/gtk_pianokeyboard.c
@@ -527,7 +527,7 @@ piano_keyboard_expose(GtkWidget *widget, GdkEventExpose *event)
}
static void
-piano_keyboard_size_request(GtkWidget* widget, GtkRequisition *requisition)
+piano_keyboard_size_request(GtkWidget* w, GtkRequisition *requisition)
{
requisition->width = PIANO_KEYBOARD_DEFAULT_WIDTH;
requisition->height = PIANO_KEYBOARD_DEFAULT_HEIGHT;
diff --git a/gtk2_ardour/icons/crossfade-in-S1.png b/gtk2_ardour/icons/fadein-S1.png
similarity index 100%
rename from gtk2_ardour/icons/crossfade-in-S1.png
rename to gtk2_ardour/icons/fadein-S1.png
diff --git a/gtk2_ardour/icons/crossfade-in-S2.png b/gtk2_ardour/icons/fadein-S2.png
similarity index 100%
rename from gtk2_ardour/icons/crossfade-in-S2.png
rename to gtk2_ardour/icons/fadein-S2.png
diff --git a/gtk2_ardour/icons/crossfade-in-constant-power.png b/gtk2_ardour/icons/fadein-constant-power.png
similarity index 100%
rename from gtk2_ardour/icons/crossfade-in-constant-power.png
rename to gtk2_ardour/icons/fadein-constant-power.png
diff --git a/gtk2_ardour/icons/crossfade-in-fast-cut.png b/gtk2_ardour/icons/fadein-fast-cut.png
similarity index 100%
rename from gtk2_ardour/icons/crossfade-in-fast-cut.png
rename to gtk2_ardour/icons/fadein-fast-cut.png
diff --git a/gtk2_ardour/icons/crossfade-in-linear.png b/gtk2_ardour/icons/fadein-linear.png
similarity index 100%
rename from gtk2_ardour/icons/crossfade-in-linear.png
rename to gtk2_ardour/icons/fadein-linear.png
diff --git a/gtk2_ardour/icons/crossfade-in-long-cut.png b/gtk2_ardour/icons/fadein-long-cut.png
similarity index 100%
rename from gtk2_ardour/icons/crossfade-in-long-cut.png
rename to gtk2_ardour/icons/fadein-long-cut.png
diff --git a/gtk2_ardour/icons/crossfade-in-short-cut.png b/gtk2_ardour/icons/fadein-short-cut.png
similarity index 100%
rename from gtk2_ardour/icons/crossfade-in-short-cut.png
rename to gtk2_ardour/icons/fadein-short-cut.png
diff --git a/gtk2_ardour/icons/crossfade-in-slow-cut.png b/gtk2_ardour/icons/fadein-slow-cut.png
similarity index 100%
rename from gtk2_ardour/icons/crossfade-in-slow-cut.png
rename to gtk2_ardour/icons/fadein-slow-cut.png
diff --git a/gtk2_ardour/icons/crossfade-out-S1.png b/gtk2_ardour/icons/fadeout-S1.png
similarity index 100%
rename from gtk2_ardour/icons/crossfade-out-S1.png
rename to gtk2_ardour/icons/fadeout-S1.png
diff --git a/gtk2_ardour/icons/crossfade-out-S2.png b/gtk2_ardour/icons/fadeout-S2.png
similarity index 100%
rename from gtk2_ardour/icons/crossfade-out-S2.png
rename to gtk2_ardour/icons/fadeout-S2.png
diff --git a/gtk2_ardour/icons/crossfade-out-constant-power.png b/gtk2_ardour/icons/fadeout-constant-power.png
similarity index 100%
rename from gtk2_ardour/icons/crossfade-out-constant-power.png
rename to gtk2_ardour/icons/fadeout-constant-power.png
diff --git a/gtk2_ardour/icons/crossfade-out-fast-cut.png b/gtk2_ardour/icons/fadeout-fast-cut.png
similarity index 100%
rename from gtk2_ardour/icons/crossfade-out-fast-cut.png
rename to gtk2_ardour/icons/fadeout-fast-cut.png
diff --git a/gtk2_ardour/icons/crossfade-out-linear.png b/gtk2_ardour/icons/fadeout-linear.png
similarity index 100%
rename from gtk2_ardour/icons/crossfade-out-linear.png
rename to gtk2_ardour/icons/fadeout-linear.png
diff --git a/gtk2_ardour/icons/crossfade-out-long-cut.png b/gtk2_ardour/icons/fadeout-long-cut.png
similarity index 100%
rename from gtk2_ardour/icons/crossfade-out-long-cut.png
rename to gtk2_ardour/icons/fadeout-long-cut.png
diff --git a/gtk2_ardour/icons/crossfade-out-short-cut.png b/gtk2_ardour/icons/fadeout-short-cut.png
similarity index 100%
rename from gtk2_ardour/icons/crossfade-out-short-cut.png
rename to gtk2_ardour/icons/fadeout-short-cut.png
diff --git a/gtk2_ardour/icons/crossfade-out-slow-cut.png b/gtk2_ardour/icons/fadeout-slow-cut.png
similarity index 100%
rename from gtk2_ardour/icons/crossfade-out-slow-cut.png
rename to gtk2_ardour/icons/fadeout-slow-cut.png
diff --git a/gtk2_ardour/location_ui.cc b/gtk2_ardour/location_ui.cc
index 60e0be5676..4ef413aef7 100644
--- a/gtk2_ardour/location_ui.cc
+++ b/gtk2_ardour/location_ui.cc
@@ -687,8 +687,9 @@ LocationEditRow::position_lock_style_changed (ARDOUR::Location*)
}
void
-LocationEditRow::focus_name() {
- name_entry.grab_focus();
+LocationEditRow::focus_name()
+{
+ name_entry.grab_focus ();
}
void
@@ -862,9 +863,9 @@ LocationUI::location_redraw_ranges ()
}
struct LocationSortByStart {
- bool operator() (Location *a, Location *b) {
- return a->start() < b->start();
- }
+ bool operator() (Location *a, Location *b) {
+ return a->start() < b->start();
+ }
};
void
@@ -879,7 +880,7 @@ LocationUI::location_added (Location* location)
loc.sort (LocationSortByStart ());
LocationEditRow* erow = manage (new LocationEditRow (_session, location));
-
+
erow->set_clock_group (*_clock_group);
erow->remove_requested.connect (sigc::mem_fun (*this, &LocationUI::location_remove_requested));
@@ -910,6 +911,11 @@ LocationUI::location_added (Location* location)
range_rows.show_all ();
location_rows.show_all ();
+
+ if (location == newest_location) {
+ newest_location = 0;
+ erow->focus_name();
+ }
}
}
@@ -959,10 +965,6 @@ LocationUI::map_locations (Locations::LocationList& locations)
Box_Helpers::BoxList & loc_children = location_rows.children();
loc_children.push_back(Box_Helpers::Element(*erow, PACK_SHRINK, 1, PACK_START));
- if (location == newest_location) {
- newest_location = 0;
- erow->focus_name();
- }
} else if (location->is_auto_punch()) {
punch_edit_row.set_session (_session);
punch_edit_row.set_location (location);
diff --git a/gtk2_ardour/location_ui.h b/gtk2_ardour/location_ui.h
index 5a6e8649c7..b850b89ddd 100644
--- a/gtk2_ardour/location_ui.h
+++ b/gtk2_ardour/location_ui.h
@@ -162,6 +162,10 @@ class LocationUI : public Gtk::HBox, public ARDOUR::SessionHandlePtr
private:
ARDOUR::LocationStack* locations;
+ /** set to the location that has just been created with the LocationUI `add' button
+ (if Config->get_name_new_markers() is true); if it is non-0, the name entry of
+ the location is given the focus by location_added().
+ */
ARDOUR::Location *newest_location;
void session_going_away ();
diff --git a/gtk2_ardour/main.cc b/gtk2_ardour/main.cc
index a853d7b61b..d7b7428b7e 100644
--- a/gtk2_ardour/main.cc
+++ b/gtk2_ardour/main.cc
@@ -21,6 +21,7 @@
#include
#include
#include
+#include
#include
#include
@@ -197,6 +198,7 @@ fixup_bundle_environment (int, char* [])
export_search_path (dir_path, "ARDOUR_PANNER_PATH", "/../Panners");
export_search_path (dir_path, "ARDOUR_SURFACES_PATH", "/../Surfaces");
export_search_path (dir_path, "ARDOUR_MIDIMAPS_PATH", "/../MidiMaps");
+ export_search_path (dir_path, "ARDOUR_MCP_PATH", "../MCP");
export_search_path (dir_path, "ARDOUR_EXPORT_FORMATS_PATH", "/../ExportFormats");
path = dir_path;
@@ -289,6 +291,10 @@ fixup_bundle_environment (int, char* [])
void
fixup_bundle_environment (int /*argc*/, char* argv[])
{
+ /* THIS IS FOR LINUX - its just about the only place where its
+ * acceptable to build paths directly using '/'.
+ */
+
if (!getenv ("ARDOUR_BUNDLED")) {
return;
}
@@ -340,6 +346,7 @@ fixup_bundle_environment (int /*argc*/, char* argv[])
export_search_path (dir_path, "ARDOUR_PANNER_PATH", "/lib/panners");
export_search_path (dir_path, "ARDOUR_SURFACES_PATH", "/lib/surfaces");
export_search_path (dir_path, "ARDOUR_MIDIMAPS_PATH", "/share/midi_maps");
+ export_search_path (dir_path, "ARDOUR_MCP_PATH", "/share/mcp");
export_search_path (dir_path, "ARDOUR_EXPORT_FORMATS_PATH", "/share/export");
path = dir_path;
@@ -359,6 +366,22 @@ fixup_bundle_environment (int /*argc*/, char* argv[])
setenv ("GTK_LOCALEDIR", localedir, 1);
}
+ /* Tell fontconfig where to find fonts.conf. Use the system version
+ if it exists, otherwise use the stuff we included in t
+ */
+
+ if (Glib::file_test ("/etc/fonts/fonts.conf", Glib::FILE_TEST_EXISTS)) {
+ setenv ("FONTCONFIG_FILE", "/etc/fonts/fonts.conf", 1);
+ setenv ("FONTCONFIG_PATH", "/etc/fonts", 1);
+ } else {
+ /* use the one included in the bundle */
+
+ path = Glib::build_filename (dir_path, "etc/fonts/fonts.conf");
+ setenv ("FONTCONFIG_FILE", path.c_str(), 1);
+ path = Glib::build_filename (dir_path, "etc/fonts");
+ setenv ("FONTCONFIG_PATH", "/etc/fonts", 1);
+ }
+
/* write a pango.rc file and tell pango to use it. we'd love
to put this into the Ardour.app bundle and leave it there,
but the user may not have write permission. so ...
@@ -370,32 +393,32 @@ fixup_bundle_environment (int /*argc*/, char* argv[])
if (g_mkdir_with_parents (userconfigdir.c_str(), 0755) < 0) {
error << string_compose (_("cannot create user ardour folder %1 (%2)"), userconfigdir, strerror (errno))
<< endmsg;
+ return;
+ }
+
+ Glib::ustring mpath;
+
+ path = Glib::build_filename (userconfigdir, "pango.rc");
+
+ std::ofstream pangorc (path.c_str());
+ if (!pangorc) {
+ error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
} else {
-
- Glib::ustring mpath;
-
- path = Glib::build_filename (userconfigdir, "pango.rc");
-
- std::ofstream pangorc (path.c_str());
- if (!pangorc) {
- error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
- } else {
- mpath = Glib::build_filename (userconfigdir, "pango.modules");
-
- pangorc << "[Pango]\nModuleFiles=";
- pangorc << mpath << endl;
- pangorc.close ();
- }
-
- setenv ("PANGO_RC_FILE", path.c_str(), 1);
-
- /* similar for GDK pixbuf loaders, but there's no RC file required
- to specify where it lives.
- */
-
- mpath = Glib::build_filename (userconfigdir, "gdk-pixbuf.loaders");
- setenv ("GDK_PIXBUF_MODULE_FILE", mpath.c_str(), 1);
+ mpath = Glib::build_filename (userconfigdir, "pango.modules");
+
+ pangorc << "[Pango]\nModuleFiles=";
+ pangorc << mpath << endl;
+ pangorc.close ();
}
+
+ setenv ("PANGO_RC_FILE", path.c_str(), 1);
+
+ /* similar for GDK pixbuf loaders, but there's no RC file required
+ to specify where it lives.
+ */
+
+ mpath = Glib::build_filename (userconfigdir, "gdk-pixbuf.loaders");
+ setenv ("GDK_PIXBUF_MODULE_FILE", mpath.c_str(), 1);
}
#endif
diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc
index 154cd158dc..76db1a7b69 100644
--- a/gtk2_ardour/midi_region_view.cc
+++ b/gtk2_ardour/midi_region_view.cc
@@ -89,7 +89,6 @@ PBD::Signal1 MidiRegionView::SelectionCleared;
MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &tv,
boost::shared_ptr r, double spu, Gdk::Color const & basic_color)
: RegionView (parent, tv, r, spu, basic_color)
- , _force_channel(-1)
, _last_channel_selection(0xFFFF)
, _current_range_min(0)
, _current_range_max(0)
@@ -126,7 +125,6 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &
boost::shared_ptr r, double spu, Gdk::Color& basic_color,
TimeAxisViewItem::Visibility visibility)
: RegionView (parent, tv, r, spu, basic_color, false, visibility)
- , _force_channel(-1)
, _last_channel_selection(0xFFFF)
, _current_range_min(0)
, _current_range_max(0)
@@ -171,7 +169,6 @@ MidiRegionView::parameter_changed (std::string const & p)
MidiRegionView::MidiRegionView (const MidiRegionView& other)
: sigc::trackable(other)
, RegionView (other)
- , _force_channel(-1)
, _last_channel_selection(0xFFFF)
, _current_range_min(0)
, _current_range_max(0)
@@ -206,7 +203,6 @@ MidiRegionView::MidiRegionView (const MidiRegionView& other)
MidiRegionView::MidiRegionView (const MidiRegionView& other, boost::shared_ptr region)
: RegionView (other, boost::shared_ptr (region))
- , _force_channel(-1)
, _last_channel_selection(0xFFFF)
, _current_range_min(0)
, _current_range_max(0)
@@ -853,7 +849,7 @@ MidiRegionView::create_note_at (framepos_t t, double y, double length, bool snap
view->update_note_range(new_note->note());
- MidiModel::NoteDiffCommand* cmd = _model->new_note_diff_command("add note");
+ MidiModel::NoteDiffCommand* cmd = _model->new_note_diff_command(_("add note"));
cmd->add (new_note);
_model->apply_command(*trackview.session(), cmd);
@@ -3109,15 +3105,9 @@ MidiRegionView::set_frame_color()
void
MidiRegionView::midi_channel_mode_changed(ChannelMode mode, uint16_t mask)
{
- switch (mode) {
- case AllChannels:
- case FilterChannels:
- _force_channel = -1;
- break;
- case ForceChannel:
- _force_channel = mask;
+ if (mode == ForceChannel) {
mask = 0xFFFF; // Show all notes as active (below)
- };
+ }
// Update notes for selection
for (Events::iterator i = _events.begin(); i != _events.end(); ++i) {
diff --git a/gtk2_ardour/midi_region_view.h b/gtk2_ardour/midi_region_view.h
index e34c80de44..c3084aee38 100644
--- a/gtk2_ardour/midi_region_view.h
+++ b/gtk2_ardour/midi_region_view.h
@@ -363,7 +363,6 @@ private:
void show_verbose_cursor (std::string const &, double, double) const;
void show_verbose_cursor (boost::shared_ptr) const;
- int8_t _force_channel;
uint16_t _last_channel_selection;
uint8_t _current_range_min;
uint8_t _current_range_max;
diff --git a/gtk2_ardour/plugin_selector.cc b/gtk2_ardour/plugin_selector.cc
index 75040eca06..1ec07d1bbe 100644
--- a/gtk2_ardour/plugin_selector.cc
+++ b/gtk2_ardour/plugin_selector.cc
@@ -199,7 +199,7 @@ PluginSelector::~PluginSelector ()
}
void
-PluginSelector::row_activated(Gtk::TreeModel::Path path, Gtk::TreeViewColumn* col)
+PluginSelector::row_activated(Gtk::TreeModel::Path, Gtk::TreeViewColumn*)
{
btn_add_clicked();
}
@@ -319,15 +319,22 @@ PluginSelector::refiller (const PluginInfoList& plugs, const::std::string& filte
newrow[plugin_columns.creator] = creator;
- snprintf (buf, sizeof(buf), "%d", (*i)->n_inputs.n_audio());
- newrow[plugin_columns.audio_ins] = buf;
- snprintf (buf, sizeof(buf), "%d", (*i)->n_inputs.n_midi());
- newrow[plugin_columns.midi_ins] = buf;
-
- snprintf (buf, sizeof(buf), "%d", (*i)->n_outputs.n_audio());
- newrow[plugin_columns.audio_outs] = buf;
- snprintf (buf, sizeof(buf), "%d", (*i)->n_outputs.n_midi());
- newrow[plugin_columns.midi_outs] = buf;
+ if ((*i)->reconfigurable_io ()) {
+ newrow[plugin_columns.audio_ins] = _("variable");
+ newrow[plugin_columns.midi_ins] = _("variable");
+ newrow[plugin_columns.audio_outs] = _("variable");
+ newrow[plugin_columns.midi_outs] = _("variable");
+ } else {
+ snprintf (buf, sizeof(buf), "%d", (*i)->n_inputs.n_audio());
+ newrow[plugin_columns.audio_ins] = buf;
+ snprintf (buf, sizeof(buf), "%d", (*i)->n_inputs.n_midi());
+ newrow[plugin_columns.midi_ins] = buf;
+
+ snprintf (buf, sizeof(buf), "%d", (*i)->n_outputs.n_audio());
+ newrow[plugin_columns.audio_outs] = buf;
+ snprintf (buf, sizeof(buf), "%d", (*i)->n_outputs.n_midi());
+ newrow[plugin_columns.midi_outs] = buf;
+ }
newrow[plugin_columns.plugin] = *i;
}
diff --git a/gtk2_ardour/port_matrix.cc b/gtk2_ardour/port_matrix.cc
index d942c99c89..a259f357ce 100644
--- a/gtk2_ardour/port_matrix.cc
+++ b/gtk2_ardour/port_matrix.cc
@@ -444,10 +444,8 @@ PortMatrix::popup_menu (BundleChannel column, BundleChannel row, uint32_t t)
if (bc[dim].channel != -1) {
add_remove_option (sub, w, bc[dim].channel);
} else {
-
- snprintf (buf, sizeof (buf), _("Remove all"));
sub.push_back (
- MenuElem (buf, sigc::bind (sigc::mem_fun (*this, &PortMatrix::remove_all_channels), w))
+ MenuElem (_("Remove all"), sigc::bind (sigc::mem_fun (*this, &PortMatrix::remove_all_channels), w))
);
if (bc[dim].bundle->nchannels().n_total() > 1) {
diff --git a/gtk2_ardour/processor_box.cc b/gtk2_ardour/processor_box.cc
index e2d33b9891..1bba2c8af1 100644
--- a/gtk2_ardour/processor_box.cc
+++ b/gtk2_ardour/processor_box.cc
@@ -965,7 +965,7 @@ ProcessorBox::enter_notify (GdkEventCrossing*)
}
bool
-ProcessorBox::leave_notify (GdkEventCrossing* ev)
+ProcessorBox::leave_notify (GdkEventCrossing*)
{
return false;
}
diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h
index ee4c7162cb..ce625e1889 100644
--- a/gtk2_ardour/public_editor.h
+++ b/gtk2_ardour/public_editor.h
@@ -314,6 +314,8 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible {
virtual bool canvas_selection_rect_event (GdkEvent* event, ArdourCanvas::Item*, SelectionRect*) = 0;
virtual bool canvas_selection_start_trim_event (GdkEvent* event, ArdourCanvas::Item*, SelectionRect*) = 0;
virtual bool canvas_selection_end_trim_event (GdkEvent* event, ArdourCanvas::Item*, SelectionRect*) = 0;
+ virtual bool canvas_start_xfade_event (GdkEvent* event, ArdourCanvas::Item*, AudioRegionView*) = 0;
+ virtual bool canvas_end_xfade_event (GdkEvent* event, ArdourCanvas::Item*, AudioRegionView*) = 0;
virtual bool canvas_fade_in_event (GdkEvent* event, ArdourCanvas::Item*, AudioRegionView*) = 0;
virtual bool canvas_fade_in_handle_event (GdkEvent* event, ArdourCanvas::Item*, AudioRegionView*) = 0;
virtual bool canvas_fade_out_event (GdkEvent* event, ArdourCanvas::Item*, AudioRegionView*) = 0;
diff --git a/gtk2_ardour/quantize_dialog.cc b/gtk2_ardour/quantize_dialog.cc
index 82b7ef3009..623a5d8033 100644
--- a/gtk2_ardour/quantize_dialog.cc
+++ b/gtk2_ardour/quantize_dialog.cc
@@ -46,20 +46,11 @@ static const gchar *_grid_strings[] = {
0
};
-static const gchar *_type_strings[] = {
- N_("Grid"),
- N_("Legato"),
- N_("Groove"),
- 0
-};
-
std::vector QuantizeDialog::grid_strings;
-std::vector QuantizeDialog::type_strings;
QuantizeDialog::QuantizeDialog (PublicEditor& e)
: ArdourDialog (_("Quantize"), false, false)
, editor (e)
- , type_label (_("Quantize Type"))
, strength_adjustment (100.0, 0.0, 100.0, 1.0, 10.0)
, strength_spinner (strength_adjustment)
, strength_label (_("Strength"))
@@ -74,7 +65,6 @@ QuantizeDialog::QuantizeDialog (PublicEditor& e)
{
if (grid_strings.empty()) {
grid_strings = I18N (_grid_strings);
- type_strings = I18N (_type_strings);
}
set_popdown_strings (start_grid_combo, grid_strings);
@@ -82,20 +72,12 @@ QuantizeDialog::QuantizeDialog (PublicEditor& e)
set_popdown_strings (end_grid_combo, grid_strings);
end_grid_combo.set_active_text (grid_strings.front());
- set_popdown_strings (type_combo, type_strings);
- type_combo.set_active_text (type_strings.front());
-
Table* table = manage (new Table (6, 2));
table->set_spacings (12);
table->set_border_width (12);
int r = 0;
- type_label.set_alignment (0, 0.5);
- table->attach (type_label, 0, 1, r, r + 1);
- table->attach (type_combo, 1, 2, r, r + 1);
- ++r;
-
table->attach (snap_start_button, 0, 1, r, r + 1);
table->attach (start_grid_combo, 1, 2, r, r + 1);
++r;
diff --git a/gtk2_ardour/quantize_dialog.h b/gtk2_ardour/quantize_dialog.h
index 97cb82c86e..8203875e98 100644
--- a/gtk2_ardour/quantize_dialog.h
+++ b/gtk2_ardour/quantize_dialog.h
@@ -45,7 +45,6 @@ class QuantizeDialog : public ArdourDialog
QuantizeDialog (PublicEditor&);
~QuantizeDialog ();
- ARDOUR::QuantizeType type() const;
double start_grid_size() const;
double end_grid_size() const;
bool snap_start() const { return snap_start_button.get_active(); }
@@ -57,10 +56,8 @@ class QuantizeDialog : public ArdourDialog
private:
PublicEditor& editor;
- Gtk::ComboBoxText type_combo;
Gtk::ComboBoxText start_grid_combo;
Gtk::ComboBoxText end_grid_combo;
- Gtk::Label type_label;
Gtk::Adjustment strength_adjustment;
Gtk::SpinButton strength_spinner;
Gtk::Label strength_label;
diff --git a/gtk2_ardour/rc_option_editor.cc b/gtk2_ardour/rc_option_editor.cc
index 8bdc9f2610..ac9c11a5bb 100644
--- a/gtk2_ardour/rc_option_editor.cc
+++ b/gtk2_ardour/rc_option_editor.cc
@@ -722,7 +722,18 @@ private:
if (!was_enabled) {
ControlProtocolManager::instance().instantiate (*cpi);
} else {
+ Gtk::Window* win = r[_model.editor];
+ if (win) {
+ win->hide ();
+ }
+
ControlProtocolManager::instance().teardown (*cpi);
+
+ if (win) {
+ delete win;
+ }
+ r[_model.editor] = 0;
+ cpi->requested = false;
}
}
@@ -1573,7 +1584,7 @@ RCOptionEditor::RCOptionEditor ()
add_option (S_("Visual|Interface"),
new BoolOption (
"use-own-plugin-gui",
- _("Use plugins' own interface instead of a builtin one"),
+ _("Use plugins' own interfaces instead of Ardour's"),
sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_plugin_own_gui),
sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_plugin_own_gui)
));
diff --git a/gtk2_ardour/route_group_dialog.cc b/gtk2_ardour/route_group_dialog.cc
index eb74887771..3e2c497475 100644
--- a/gtk2_ardour/route_group_dialog.cc
+++ b/gtk2_ardour/route_group_dialog.cc
@@ -33,7 +33,7 @@ using namespace std;
using namespace PBD;
RouteGroupDialog::RouteGroupDialog (RouteGroup* g, bool creating_new)
- : ArdourDialog (_("Route Group"))
+ : ArdourDialog (_("Track/bus Group"))
, _group (g)
, _initial_name (g->name ())
, _active (_("Active"))
@@ -44,7 +44,7 @@ RouteGroupDialog::RouteGroupDialog (RouteGroup* g, bool creating_new)
, _rec_enable (_("Record enable"))
, _select (_("Selection"))
, _edit (_("Editing"))
- , _route_active (_("Route active state"))
+ , _route_active (_("Active state"))
, _share_color (_("Color"))
, _share_monitoring (_("Monitoring"))
{
diff --git a/gtk2_ardour/route_time_axis.cc b/gtk2_ardour/route_time_axis.cc
index ef2cba7f9b..4d50a41272 100644
--- a/gtk2_ardour/route_time_axis.cc
+++ b/gtk2_ardour/route_time_axis.cc
@@ -2362,13 +2362,16 @@ RouteTimeAxisView::set_button_names ()
switch (Config->get_listen_position()) {
case AfterFaderListen:
solo_button->set_text (_("A"));
+ ARDOUR_UI::instance()->set_tip (*solo_button, _("After-fade listen (AFL)"));
break;
case PreFaderListen:
solo_button->set_text (_("P"));
+ ARDOUR_UI::instance()->set_tip (*solo_button, _("Pre-fade listen (PFL)"));
break;
}
} else {
solo_button->set_text (_("s"));
+ ARDOUR_UI::instance()->set_tip (*solo_button, _("Solo"));
}
}
mute_button->set_text (_("m"));
diff --git a/gtk2_ardour/route_ui.cc b/gtk2_ardour/route_ui.cc
index 8d8c4224b0..64ba5b067d 100644
--- a/gtk2_ardour/route_ui.cc
+++ b/gtk2_ardour/route_ui.cc
@@ -629,7 +629,7 @@ RouteUI::update_monitoring_display ()
}
bool
-RouteUI::monitor_input_press(GdkEventButton* ev)
+RouteUI::monitor_input_press(GdkEventButton*)
{
return true;
}
@@ -641,7 +641,7 @@ RouteUI::monitor_input_release(GdkEventButton* ev)
}
bool
-RouteUI::monitor_disk_press (GdkEventButton* ev)
+RouteUI::monitor_disk_press (GdkEventButton*)
{
return true;
}
diff --git a/gtk2_ardour/session_option_editor.cc b/gtk2_ardour/session_option_editor.cc
index 62d555c13d..b9f54f94e8 100644
--- a/gtk2_ardour/session_option_editor.cc
+++ b/gtk2_ardour/session_option_editor.cc
@@ -115,7 +115,7 @@ SessionOptionEditor::SessionOptionEditor (Session* s)
ClockOption* co = new ClockOption (
"timecode-offset",
- _("Timecode Offset"),
+ _("Timecode offset"),
sigc::mem_fun (*_session_config, &SessionConfiguration::get_timecode_offset),
sigc::mem_fun (*_session_config, &SessionConfiguration::set_timecode_offset)
);
@@ -154,6 +154,19 @@ SessionOptionEditor::SessionOptionEditor (Session* s)
add_option (_("Fades"), cfm);
+ ComboOption* cfc = new ComboOption (
+ "xfade-choice",
+ _("Crossfade type"),
+ sigc::mem_fun (*_session_config, &SessionConfiguration::get_xfade_choice),
+ sigc::mem_fun (*_session_config, &SessionConfiguration::set_xfade_choice)
+ );
+
+ cfc->add (ConstantPowerMinus3dB, _("constant power (-3dB)"));
+ cfc->add (ConstantPowerMinus6dB, _("constant power (-6dB)"));
+ cfc->add (RegionFades, _("use existing region fade shape"));
+
+ add_option (_("Fades"), cfc);
+
add_option (_("Fades"), new SpinOption (
_("short-xfade-seconds"),
_("Short crossfade length"),
@@ -179,20 +192,6 @@ SessionOptionEditor::SessionOptionEditor (Session* s)
sigc::mem_fun (*_session_config, &SessionConfiguration::set_auto_xfade)
));
- add_option (_("Fades"), new BoolOption (
- "xfades-active",
- _("Crossfades active"),
- sigc::mem_fun (*_session_config, &SessionConfiguration::get_xfades_active),
- sigc::mem_fun (*_session_config, &SessionConfiguration::set_xfades_active)
- ));
-
- add_option (_("Fades"), new BoolOption (
- "xfades-visible",
- _("Crossfades visible"),
- sigc::mem_fun (*_session_config, &SessionConfiguration::get_xfades_visible),
- sigc::mem_fun (*_session_config, &SessionConfiguration::set_xfades_visible)
- ));
-
add_option (_("Fades"), new BoolOption (
"use-region-fades",
_("Region fades active"),
diff --git a/gtk2_ardour/sfdb_freesound_mootcher.cc b/gtk2_ardour/sfdb_freesound_mootcher.cc
index 7e13c4f68b..70d04abb66 100644
--- a/gtk2_ardour/sfdb_freesound_mootcher.cc
+++ b/gtk2_ardour/sfdb_freesound_mootcher.cc
@@ -369,7 +369,7 @@ std::string Mootcher::getAudioFile(std::string originalFileName, std::string ID,
}
//---------
-int Mootcher::progress_callback(void *caller, double dltotal, double dlnow, double ultotal, double ulnow)
+int Mootcher::progress_callback(void *caller, double dltotal, double dlnow, double /*ultotal*/, double /*ulnow*/)
{
SoundFileBrowser *sfb = (SoundFileBrowser *) caller;
diff --git a/gtk2_ardour/shuttle_control.cc b/gtk2_ardour/shuttle_control.cc
index 3b5f8dbb78..abbd39ac16 100644
--- a/gtk2_ardour/shuttle_control.cc
+++ b/gtk2_ardour/shuttle_control.cc
@@ -522,7 +522,7 @@ ShuttleControl::on_expose_event (GdkEventExpose*)
if (Config->get_shuttle_units() == Percentage) {
if (speed == 1.0) {
- snprintf (buf, sizeof (buf), _("Playing"));
+ snprintf (buf, sizeof (buf), "%s", _("Playing"));
} else {
if (speed < 0.0) {
snprintf (buf, sizeof (buf), "<<< %d%%", (int) round (-speed * 100));
@@ -544,7 +544,7 @@ ShuttleControl::on_expose_event (GdkEventExpose*)
}
} else {
- snprintf (buf, sizeof (buf), _("Stopped"));
+ snprintf (buf, sizeof (buf), "%s", _("Stopped"));
}
last_speed_displayed = speed;
@@ -559,10 +559,10 @@ ShuttleControl::on_expose_event (GdkEventExpose*)
switch (Config->get_shuttle_behaviour()) {
case Sprung:
- snprintf (buf, sizeof (buf), _("Sprung"));
+ snprintf (buf, sizeof (buf), "%s", _("Sprung"));
break;
case Wheel:
- snprintf (buf, sizeof (buf), _("Wheel"));
+ snprintf (buf, sizeof (buf), "%s", _("Wheel"));
break;
}
diff --git a/gtk2_ardour/startup.cc b/gtk2_ardour/startup.cc
index 0a07e4ec98..220f406287 100644
--- a/gtk2_ardour/startup.cc
+++ b/gtk2_ardour/startup.cc
@@ -511,7 +511,7 @@ greater control in monitoring without affecting the mix."));
use_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
no_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
- monitor_section_label.set_markup(_("You can change this preference at any time, via the Preferences dialog). You can also add or remove the monitor section to/from any session.\n\n\
+ monitor_section_label.set_markup(_("You can change this preference at any time via the Preferences dialog.\nYou can also add or remove the monitor section to/from any session.\n\n\
If you do not understand what this is about, just accept the default."));
monitor_section_label.set_alignment (0.0, 0.0);
diff --git a/gtk2_ardour/stereo_panner.cc b/gtk2_ardour/stereo_panner.cc
index bceb009b75..730ef58910 100644
--- a/gtk2_ardour/stereo_panner.cc
+++ b/gtk2_ardour/stereo_panner.cc
@@ -111,7 +111,7 @@ StereoPanner::set_drag_data ()
}
bool
-StereoPanner::on_expose_event (GdkEventExpose* ev)
+StereoPanner::on_expose_event (GdkEventExpose*)
{
Glib::RefPtr win (get_window());
Glib::RefPtr gc (get_style()->get_base_gc (get_state()));
diff --git a/gtk2_ardour/tempo_dialog.cc b/gtk2_ardour/tempo_dialog.cc
index d3c4ef17b8..3557727394 100644
--- a/gtk2_ardour/tempo_dialog.cc
+++ b/gtk2_ardour/tempo_dialog.cc
@@ -36,7 +36,7 @@ using namespace Gtkmm2ext;
using namespace ARDOUR;
using namespace PBD;
-TempoDialog::TempoDialog (TempoMap& map, framepos_t frame, const string & action)
+TempoDialog::TempoDialog (TempoMap& map, framepos_t frame, const string&)
: ArdourDialog (_("New Tempo"))
, bpm_adjustment (60.0, 1.0, 999.9, 0.1, 1.0)
, bpm_spinner (bpm_adjustment)
@@ -51,7 +51,7 @@ TempoDialog::TempoDialog (TempoMap& map, framepos_t frame, const string & action
init (when, tempo.beats_per_minute(), tempo.note_type(), true);
}
-TempoDialog::TempoDialog (TempoSection& section, const string & action)
+TempoDialog::TempoDialog (TempoSection& section, const string&)
: ArdourDialog ("Edit Tempo")
, bpm_adjustment (60.0, 1.0, 999.9, 0.1, 1.0)
, bpm_spinner (bpm_adjustment)
@@ -251,7 +251,7 @@ TempoDialog::pulse_change ()
}
-MeterDialog::MeterDialog (TempoMap& map, framepos_t frame, const string & action)
+MeterDialog::MeterDialog (TempoMap& map, framepos_t frame, const string&)
: ArdourDialog ("New Meter")
{
Timecode::BBT_Time when;
@@ -262,7 +262,7 @@ MeterDialog::MeterDialog (TempoMap& map, framepos_t frame, const string & action
init (when, meter.divisions_per_bar(), meter.note_divisor(), true);
}
-MeterDialog::MeterDialog (MeterSection& section, const string & action)
+MeterDialog::MeterDialog (MeterSection& section, const string&)
: ArdourDialog ("Edit Meter")
{
init (section.start(), section.divisions_per_bar(), section.note_divisor(), section.movable());
diff --git a/gtk2_ardour/time_axis_view.h b/gtk2_ardour/time_axis_view.h
index 03c50e7ccb..ba69b3b154 100644
--- a/gtk2_ardour/time_axis_view.h
+++ b/gtk2_ardour/time_axis_view.h
@@ -160,9 +160,6 @@ class TimeAxisView : public virtual AxisView
virtual void show_timestretch (framepos_t start, framepos_t end);
virtual void hide_timestretch ();
- virtual void hide_dependent_views (TimeAxisViewItem&) {}
- virtual void reveal_dependent_views (TimeAxisViewItem&) {}
-
/* editing operations */
virtual void cut_copy_clear (Selection&, Editing::CutCopyOp) {}
diff --git a/gtk2_ardour/time_axis_view_item.cc b/gtk2_ardour/time_axis_view_item.cc
index c0a90f7111..0f184c1da7 100644
--- a/gtk2_ardour/time_axis_view_item.cc
+++ b/gtk2_ardour/time_axis_view_item.cc
@@ -52,7 +52,8 @@ using namespace Gtkmm2ext;
Pango::FontDescription TimeAxisViewItem::NAME_FONT;
const double TimeAxisViewItem::NAME_X_OFFSET = 15.0;
-const double TimeAxisViewItem::GRAB_HANDLE_LENGTH = 6;
+const double TimeAxisViewItem::GRAB_HANDLE_TOP = 6;
+const double TimeAxisViewItem::GRAB_HANDLE_WIDTH = 5;
int TimeAxisViewItem::NAME_HEIGHT;
double TimeAxisViewItem::NAME_Y_OFFSET;
@@ -102,6 +103,7 @@ TimeAxisViewItem::TimeAxisViewItem(
, _height (1.0)
, _recregion (recording)
, _automation (automation)
+ , _dragging (false)
{
group = new ArdourCanvas::Group (parent);
@@ -115,6 +117,7 @@ TimeAxisViewItem::TimeAxisViewItem (const TimeAxisViewItem& other)
, trackview (other.trackview)
, _recregion (other._recregion)
, _automation (other._automation)
+ , _dragging (other._dragging)
{
Gdk::Color c;
@@ -131,10 +134,8 @@ TimeAxisViewItem::TimeAxisViewItem (const TimeAxisViewItem& other)
_selected = other._selected;
- init (
- other.item_name, other.samples_per_unit, c, other.frame_position,
- other.item_duration, other.visibility, other.wide_enough_for_name, other.high_enough_for_name
- );
+ init (other.item_name, other.samples_per_unit, c, other.frame_position,
+ other.item_duration, other.visibility, other.wide_enough_for_name, other.high_enough_for_name);
}
void
@@ -215,9 +216,12 @@ TimeAxisViewItem::init (
/* create our grab handles used for trimming/duration etc */
if (!_recregion && !_automation) {
- frame_handle_start = new ArdourCanvas::SimpleRect (*group, 0.0, TimeAxisViewItem::GRAB_HANDLE_LENGTH, 5.0, trackview.current_height());
+ double top = TimeAxisViewItem::GRAB_HANDLE_TOP;
+ double width = TimeAxisViewItem::GRAB_HANDLE_WIDTH;
+
+ frame_handle_start = new ArdourCanvas::SimpleRect (*group, 0.0, top, width, trackview.current_height());
frame_handle_start->property_outline_what() = 0x0;
- frame_handle_end = new ArdourCanvas::SimpleRect (*group, 0.0, TimeAxisViewItem::GRAB_HANDLE_LENGTH, 5.0, trackview.current_height());
+ frame_handle_end = new ArdourCanvas::SimpleRect (*group, 0.0, top, width, trackview.current_height());
frame_handle_end->property_outline_what() = 0x0;
} else {
frame_handle_start = frame_handle_end = 0;
@@ -807,14 +811,6 @@ TimeAxisViewItem::set_samples_per_unit (double spu)
void
TimeAxisViewItem::reset_width_dependent_items (double pixel_width)
{
- if (pixel_width < GRAB_HANDLE_LENGTH * 2) {
-
- if (frame_handle_start) {
- frame_handle_start->hide();
- frame_handle_end->hide();
- }
-
- }
if (pixel_width < 2.0) {
@@ -862,14 +858,20 @@ TimeAxisViewItem::reset_width_dependent_items (double pixel_width)
}
if (frame_handle_start) {
- if (pixel_width < (2*TimeAxisViewItem::GRAB_HANDLE_LENGTH)) {
+ if (pixel_width < (3 * TimeAxisViewItem::GRAB_HANDLE_WIDTH)) {
+ /*
+ * there's less than GRAB_HANDLE_WIDTH of the region between
+ * the right-hand end of frame_handle_start and the left-hand
+ * end of frame_handle_end, so disable the handles
+ */
frame_handle_start->hide();
frame_handle_end->hide();
+ } else {
+ frame_handle_start->show();
+ frame_handle_end->property_x1() = pixel_width - (TimeAxisViewItem::GRAB_HANDLE_WIDTH);
+ frame_handle_end->property_x2() = pixel_width;
+ frame_handle_end->show();
}
- frame_handle_start->show();
- frame_handle_end->property_x1() = pixel_width - (TimeAxisViewItem::GRAB_HANDLE_LENGTH);
- frame_handle_end->show();
- frame_handle_end->property_x2() = pixel_width;
}
wide_enough_for_name = true;
diff --git a/gtk2_ardour/time_axis_view_item.h b/gtk2_ardour/time_axis_view_item.h
index 6b4bc09ec1..3985b8ffd8 100644
--- a/gtk2_ardour/time_axis_view_item.h
+++ b/gtk2_ardour/time_axis_view_item.h
@@ -78,6 +78,10 @@ class TimeAxisViewItem : public Selectable, public PBD::ScopedConnectionList
double get_samples_per_unit();
+ virtual void drag_start() { _dragging = true; }
+ virtual void drag_end() { _dragging = false; }
+ bool dragging() const { return _dragging; }
+
virtual void raise () { return; }
virtual void raise_to_top () { return; }
virtual void lower () { return; }
@@ -93,7 +97,8 @@ class TimeAxisViewItem : public Selectable, public PBD::ScopedConnectionList
static Pango::FontDescription NAME_FONT;
static void set_constant_heights ();
static const double NAME_X_OFFSET;
- static const double GRAB_HANDLE_LENGTH;
+ static const double GRAB_HANDLE_TOP;
+ static const double GRAB_HANDLE_WIDTH;
/* these are not constant, but vary with the pixel size
of the font used to display the item name.
@@ -239,6 +244,7 @@ class TimeAxisViewItem : public Selectable, public PBD::ScopedConnectionList
Visibility visibility;
bool _recregion;
bool _automation; ///< true if this is an automation region view
+ bool _dragging;
private:
diff --git a/libs/ardour/ardour/audio_unit.h b/libs/ardour/ardour/audio_unit.h
index 14665da301..36e82da802 100644
--- a/libs/ardour/ardour/audio_unit.h
+++ b/libs/ardour/ardour/audio_unit.h
@@ -104,7 +104,6 @@ class AUPlugin : public ARDOUR::Plugin
bool has_editor () const;
- bool reconfigurable_io() const { return true; }
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
ChanCount output_streams() const;
ChanCount input_streams() const;
@@ -241,6 +240,8 @@ class AUPluginInfo : public PluginInfo {
AUPluginCachedInfo cache;
+ bool reconfigurable_io() const { return true; }
+
static PluginInfoList* discover ();
static void get_names (CAComponentDescription&, std::string& name, std::string& maker);
static std::string stringify_descriptor (const CAComponentDescription&);
diff --git a/libs/ardour/ardour/audioregion.h b/libs/ardour/ardour/audioregion.h
index 7236cd69a9..c03f32cb63 100644
--- a/libs/ardour/ardour/audioregion.h
+++ b/libs/ardour/ardour/audioregion.h
@@ -89,8 +89,15 @@ class AudioRegion : public Region
bool fade_in_active () const { return _fade_in_active; }
bool fade_out_active () const { return _fade_out_active; }
+ bool fade_in_is_xfade() const { return _fade_in_is_xfade; }
+ void set_fade_in_is_xfade (bool yn);
+ bool fade_out_is_xfade() const { return _fade_out_is_xfade; }
+ void set_fade_out_is_xfade (bool yn);
+
boost::shared_ptr fade_in() { return _fade_in; }
+ boost::shared_ptr inverse_fade_in() { return _inverse_fade_in; }
boost::shared_ptr fade_out() { return _fade_out; }
+ boost::shared_ptr inverse_fade_out() { return _inverse_fade_out; }
boost::shared_ptr envelope() { return _envelope; }
Evoral::Range body_range () const;
@@ -101,13 +108,6 @@ class AudioRegion : public Region
/* Readable interface */
- enum ReadOps {
- ReadOpsNone = 0x0,
- ReadOpsOwnAutomation = 0x1,
- ReadOpsOwnScaling = 0x2,
- ReadOpsFades = 0x4
- };
-
virtual framecnt_t read (Sample*, framepos_t pos, framecnt_t cnt, int channel) const;
virtual framecnt_t readable_length() const { return length(); }
@@ -142,6 +142,8 @@ class AudioRegion : public Region
void set_default_fade_in ();
void set_default_fade_out ();
+
+ framecnt_t verify_xfade_bounds (framecnt_t, bool start);
void set_envelope_active (bool yn);
void set_default_envelope ();
@@ -178,7 +180,6 @@ class AudioRegion : public Region
private:
friend class RegionFactory;
- friend class Crossfade;
AudioRegion (boost::shared_ptr);
AudioRegion (const SourceList &);
@@ -208,11 +209,7 @@ class AudioRegion : public Region
void recompute_gain_at_end ();
void recompute_gain_at_start ();
- framecnt_t _read_at (const SourceList&, framecnt_t limit,
- Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
- framepos_t position, framecnt_t cnt,
- uint32_t chan_n = 0,
- ReadOps readops = ReadOps (~0)) const;
+ framecnt_t read_from_sources (SourceList const &, framecnt_t, Sample *, framepos_t, framecnt_t, uint32_t) const;
void recompute_at_start ();
void recompute_at_end ();
@@ -228,10 +225,19 @@ class AudioRegion : public Region
Automatable _automatable;
boost::shared_ptr _fade_in;
+ boost::shared_ptr _inverse_fade_in;
boost::shared_ptr _fade_out;
+ boost::shared_ptr _inverse_fade_out;
boost::shared_ptr _envelope;
uint32_t _fade_in_suspended;
uint32_t _fade_out_suspended;
+ /* This is not a Property because its not subject to user control,
+ or undo/redo. XXX this may prove to be a mistake.
+ */
+ bool _fade_in_is_xfade;
+ bool _fade_out_is_xfade;
+
+ boost::shared_ptr get_single_other_xfade_region (bool start) const;
protected:
/* default constructor for derived (compound) types */
diff --git a/libs/ardour/ardour/delivery.h b/libs/ardour/ardour/delivery.h
index 4ee171c033..314b223538 100644
--- a/libs/ardour/ardour/delivery.h
+++ b/libs/ardour/ardour/delivery.h
@@ -89,7 +89,7 @@ public:
/* Panning */
static int disable_panners (void);
- static int reset_panners (void);
+ static void reset_panners ();
boost::shared_ptr panner_shell() const { return _panshell; }
boost::shared_ptr panner() const;
@@ -115,9 +115,9 @@ public:
boost::shared_ptr _mute_master;
static bool panners_legal;
- static PBD::Signal0 PannersLegal;
+ static PBD::Signal0 PannersLegal;
- int panners_became_legal ();
+ void panners_became_legal ();
PBD::ScopedConnection panner_legal_c;
void output_changed (IOChange, void*);
diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h
index 2451611b1b..1ba27a7449 100644
--- a/libs/ardour/ardour/io.h
+++ b/libs/ardour/ardour/io.h
@@ -152,7 +152,7 @@ class IO : public SessionObject, public Latent
typedef bool result_type;
template
- bool operator() (Iter first, Iter last) const {
+ result_type operator() (Iter first, Iter last) const {
bool r = false;
while (first != last) {
if (*first) {
diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h
index be848d381b..a853c501f0 100644
--- a/libs/ardour/ardour/playlist.h
+++ b/libs/ardour/ardour/playlist.h
@@ -39,6 +39,7 @@
#include "pbd/stateful.h"
#include "pbd/statefuldestructible.h"
#include "pbd/sequence_property.h"
+#include "pbd/stacktrace.h"
#include "evoral/types.hpp"
@@ -234,7 +235,10 @@ public:
protected:
struct RegionLock {
RegionLock (Playlist *pl, bool do_block_notify = true) : playlist (pl), block_notify (do_block_notify) {
- playlist->region_lock.lock();
+ if (!playlist->region_lock.trylock()) {
+ std::cerr << "Lock for playlist " << pl->name() << " already held\n";
+ PBD::stacktrace (std::cerr, 10);
+ }
if (block_notify) {
playlist->delay_notifications();
}
@@ -249,8 +253,6 @@ public:
bool block_notify;
};
- friend class RegionLock;
-
RegionListProperty regions; /* the current list of regions in the playlist */
std::set > all_regions; /* all regions ever added to this playlist */
PBD::ScopedConnectionList region_state_changed_connections;
@@ -258,11 +260,6 @@ public:
int _sort_id;
mutable gint block_notifications;
mutable gint ignore_state_changes;
-#ifdef HAVE_GLIB_THREADS_RECMUTEX
- mutable Glib::Threads::RecMutex region_lock;
-#else
- mutable Glib::RecMutex region_lock;
-#endif
std::set > pending_adds;
std::set > pending_removes;
RegionList pending_bounds;
@@ -309,6 +306,8 @@ public:
void _set_sort_id ();
+ boost::shared_ptr regions_touched_locked (framepos_t start, framepos_t end);
+
void notify_region_removed (boost::shared_ptr);
void notify_region_added (boost::shared_ptr);
void notify_layering_changed ();
@@ -373,9 +372,12 @@ public:
*/
virtual void pre_uncombine (std::vector >&, boost::shared_ptr) {}
-private:
+ private:
+ friend class RegionLock;
+ mutable Glib::Mutex region_lock;
- void setup_layering_indices (RegionList const &) const;
+ private:
+ void setup_layering_indices (RegionList const &);
void coalesce_and_check_crossfades (std::list >);
boost::shared_ptr find_regions_at (framepos_t);
};
diff --git a/libs/ardour/ardour/plugin.h b/libs/ardour/ardour/plugin.h
index 069a579ff7..cfdf0e8121 100644
--- a/libs/ardour/ardour/plugin.h
+++ b/libs/ardour/ardour/plugin.h
@@ -67,6 +67,18 @@ class PluginInfo {
virtual PluginPtr load (Session& session) = 0;
virtual bool is_instrument() const;
+ /* NOTE: this block of virtual methods looks like the interface
+ to a Processor, but Plugin does not inherit from Processor.
+ It is therefore not required that these precisely match
+ the interface, but it is likely that they will evolve together.
+ */
+
+ /* this returns true if the plugin can change its inputs or outputs on demand.
+ LADSPA, LV2 and VST plugins cannot do this. AudioUnits can.
+ */
+
+ virtual bool reconfigurable_io() const { return false; }
+
protected:
friend class PluginManager;
uint32_t index;
@@ -118,8 +130,8 @@ class Plugin : public PBD::StatefulDestructible, public Latent
virtual uint32_t parameter_count () const = 0;
virtual float default_value (uint32_t port) = 0;
virtual float get_parameter(uint32_t which) const = 0;
- virtual std::string get_docs() const { return ""; }
- virtual std::string get_parameter_docs(uint32_t which) const { return ""; }
+ virtual std::string get_docs () const { return ""; }
+ virtual std::string get_parameter_docs (uint32_t /*which*/) const { return ""; }
virtual int get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const = 0;
virtual uint32_t nth_parameter (uint32_t which, bool& ok) const = 0;
@@ -203,19 +215,6 @@ class Plugin : public PBD::StatefulDestructible, public Latent
/** Emitted when any parameter changes */
PBD::Signal2 ParameterChanged;
- /* NOTE: this block of virtual methods looks like the interface
- to a Processor, but Plugin does not inherit from Processor.
- It is therefore not required that these precisely match
- the interface, but it is likely that they will evolve together.
- */
-
- /* this returns true if the plugin can change its inputs or outputs on demand.
- LADSPA, LV2 and VST plugins cannot do this. AudioUnits can.
- */
-
- virtual bool reconfigurable_io() const { return false; }
-
- /* this is only called if reconfigurable_io() returns true */
virtual bool configure_io (ChanCount /*in*/, ChanCount /*out*/) { return true; }
/* specific types of plugins can overload this. As of September 2008, only
diff --git a/libs/ardour/ardour/quantize.h b/libs/ardour/ardour/quantize.h
index e1ca2b2395..e56927767e 100644
--- a/libs/ardour/ardour/quantize.h
+++ b/libs/ardour/ardour/quantize.h
@@ -30,8 +30,7 @@ class Session;
class Quantize : public MidiOperator {
public:
- Quantize (ARDOUR::Session&, QuantizeType type,
- bool snap_start, bool snap_end,
+ Quantize (ARDOUR::Session&, bool snap_start, bool snap_end,
double start_grid, double end_grid,
float strength, float swing, float threshold);
~Quantize ();
diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h
index 788a8d90c9..1d7894fac5 100644
--- a/libs/ardour/ardour/region.h
+++ b/libs/ardour/ardour/region.h
@@ -141,6 +141,15 @@ class Region
framepos_t first_frame () const { return _position; }
framepos_t last_frame () const { return _position + _length - 1; }
+ /** Return the earliest possible value of _position given the
+ * value of _start within the region's sources
+ */
+ framepos_t earliest_possible_position () const;
+ /** Return the last possible value of _last_frame given the
+ * value of _startin the regions's sources
+ */
+ framepos_t latest_possible_frame () const;
+
Evoral::Range last_range () const {
return Evoral::Range (_last_position, _last_position + _last_length - 1);
}
diff --git a/libs/ardour/ardour/session_configuration_vars.h b/libs/ardour/ardour/session_configuration_vars.h
index a6147f9140..489105e5ac 100644
--- a/libs/ardour/ardour/session_configuration_vars.h
+++ b/libs/ardour/ardour/session_configuration_vars.h
@@ -26,10 +26,9 @@
*****************************************************/
CONFIG_VARIABLE (CrossfadeModel, xfade_model, "xfade-model", FullCrossfade)
+CONFIG_VARIABLE (CrossfadeChoice, xfade_choice, "xfade-choice", ConstantPowerMinus3dB)
CONFIG_VARIABLE (bool, auto_xfade, "auto-xfade", true)
CONFIG_VARIABLE (float, short_xfade_seconds, "short-xfade-seconds", 0.015)
-CONFIG_VARIABLE (bool, xfades_active, "xfades-active", true)
-CONFIG_VARIABLE (bool, xfades_visible, "xfades-visible", true)
CONFIG_VARIABLE (uint32_t, destructive_xfade_msecs, "destructive-xfade-msecs", 2)
CONFIG_VARIABLE (bool, use_region_fades, "use-region-fades", true)
CONFIG_VARIABLE (bool, show_region_fades, "show-region-fades", true)
diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h
index b3c1666dbb..6ac9ebfe70 100644
--- a/libs/ardour/ardour/types.h
+++ b/libs/ardour/ardour/types.h
@@ -406,6 +406,12 @@ namespace ARDOUR {
ShortCrossfade
};
+ enum CrossfadeChoice {
+ RegionFades,
+ ConstantPowerMinus3dB,
+ ConstantPowerMinus6dB,
+ };
+
enum ListenPosition {
AfterFaderListen,
PreFaderListen
@@ -504,12 +510,6 @@ namespace ARDOUR {
Rectified
};
- enum QuantizeType {
- Plain,
- Legato,
- Groove
- };
-
struct CleanupReport {
std::vector paths;
size_t space;
@@ -557,8 +557,8 @@ namespace ARDOUR {
FadeLinear,
FadeFast,
FadeSlow,
- FadeLogA,
- FadeLogB
+ FadeConstantPower,
+ FadeSymmetric,
};
} // namespace ARDOUR
@@ -579,6 +579,7 @@ std::istream& operator>>(std::istream& o, ARDOUR::RemoteModel& sf);
std::istream& operator>>(std::istream& o, ARDOUR::ListenPosition& sf);
std::istream& operator>>(std::istream& o, ARDOUR::InsertMergePolicy& sf);
std::istream& operator>>(std::istream& o, ARDOUR::CrossfadeModel& sf);
+std::istream& operator>>(std::istream& o, ARDOUR::CrossfadeChoice& sf);
std::istream& operator>>(std::istream& o, ARDOUR::SyncSource& sf);
std::istream& operator>>(std::istream& o, ARDOUR::ShuttleBehaviour& sf);
std::istream& operator>>(std::istream& o, ARDOUR::ShuttleUnits& sf);
@@ -599,6 +600,7 @@ std::ostream& operator<<(std::ostream& o, const ARDOUR::RemoteModel& sf);
std::ostream& operator<<(std::ostream& o, const ARDOUR::ListenPosition& sf);
std::ostream& operator<<(std::ostream& o, const ARDOUR::InsertMergePolicy& sf);
std::ostream& operator<<(std::ostream& o, const ARDOUR::CrossfadeModel& sf);
+std::ostream& operator<<(std::ostream& o, const ARDOUR::CrossfadeChoice& sf);
std::ostream& operator<<(std::ostream& o, const ARDOUR::SyncSource& sf);
std::ostream& operator<<(std::ostream& o, const ARDOUR::ShuttleBehaviour& sf);
std::ostream& operator<<(std::ostream& o, const ARDOUR::ShuttleUnits& sf);
diff --git a/libs/ardour/audio_playlist.cc b/libs/ardour/audio_playlist.cc
index ebebc62c33..9b433d160b 100644
--- a/libs/ardour/audio_playlist.cc
+++ b/libs/ardour/audio_playlist.cc
@@ -186,16 +186,12 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, fr
its OK to block (for short intervals).
*/
-#ifdef HAVE_GLIB_THREADS_RECMUTEX
- Glib::Threads::RecMutex::Lock lm (region_lock);
-#else
- Glib::RecMutex::Lock rm (region_lock);
-#endif
+ Playlist::RegionLock rl (this, false);
/* Find all the regions that are involved in the bit we are reading,
and sort them by descending layer and ascending position.
*/
- boost::shared_ptr all = regions_touched (start, start + cnt - 1);
+ boost::shared_ptr all = regions_touched_locked (start, start + cnt - 1);
all->sort (ReadSorter ());
/* This will be a list of the bits of our read range that we have
@@ -290,7 +286,6 @@ AudioPlaylist::check_crossfades (Evoral::Range range)
continue;
}
-
boost::shared_ptr top;
boost::shared_ptr bottom;
@@ -317,8 +312,9 @@ AudioPlaylist::check_crossfades (Evoral::Range range)
*/
if (done_start.find (top) == done_start.end() && done_end.find (bottom) == done_end.end ()) {
- /* Top's fade-in will cause an implicit fade-out of bottom */
+ /* Top's fade-in will cause an implicit fade-out of bottom */
+
framecnt_t len = 0;
switch (_session.config.get_xfade_model()) {
case FullCrossfade:
@@ -328,11 +324,27 @@ AudioPlaylist::check_crossfades (Evoral::Range range)
len = _session.config.get_short_xfade_seconds() * _session.frame_rate();
break;
}
-
- top->set_fade_in_length (len);
+
top->set_fade_in_active (true);
+ top->set_fade_in_is_xfade (true);
+
+ /* XXX may 2012: -3dB and -6dB curves
+ * are the same right now
+ */
+
+ switch (_session.config.get_xfade_choice ()) {
+ case ConstantPowerMinus3dB:
+ top->set_fade_in (FadeConstantPower, len);
+ break;
+ case ConstantPowerMinus6dB:
+ top->set_fade_in (FadeConstantPower, len);
+ break;
+ case RegionFades:
+ top->set_fade_in_length (len);
+ break;
+ }
+
done_start.insert (top);
- done_end.insert (bottom);
}
} else if (c == Evoral::OverlapEnd) {
@@ -349,17 +361,29 @@ AudioPlaylist::check_crossfades (Evoral::Range range)
framecnt_t len = 0;
switch (_session.config.get_xfade_model()) {
case FullCrossfade:
- len = bottom->last_frame () - top->first_frame ();
+ len = top->last_frame () - bottom->first_frame ();
break;
case ShortCrossfade:
len = _session.config.get_short_xfade_seconds() * _session.frame_rate();
break;
}
-
- top->set_fade_out_length (len);
+
top->set_fade_out_active (true);
+ top->set_fade_out_is_xfade (true);
+
+ switch (_session.config.get_xfade_choice ()) {
+ case ConstantPowerMinus3dB:
+ top->set_fade_out (FadeConstantPower, len);
+ break;
+ case ConstantPowerMinus6dB:
+ top->set_fade_out (FadeConstantPower, len);
+ break;
+ case RegionFades:
+ top->set_fade_out_length (len);
+ break;
+ }
+
done_end.insert (top);
- done_start.insert (bottom);
}
}
}
diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc
index e4a7504ec1..739987dc56 100644
--- a/libs/ardour/audioregion.cc
+++ b/libs/ardour/audioregion.cc
@@ -65,6 +65,90 @@ namespace ARDOUR {
}
}
+static const double VERY_SMALL_SIGNAL = 0.0000001; //-140dB
+
+/* Curve manipulations */
+
+static void
+reverse_curve (boost::shared_ptr dst, boost::shared_ptr src)
+{
+ size_t len = src->back()->when;
+
+ for (Evoral::ControlList::const_iterator it = src->begin(); it!=src->end(); it++) {
+ dst->add ( len - (*it)->when, (*it)->value );
+ }
+}
+
+static void
+generate_inverse_power_curve (boost::shared_ptr dst, boost::shared_ptr src)
+{
+ //calc inverse curve using sum of squares
+ for (Evoral::ControlList::const_iterator it = src->begin(); it!=src->end(); ++it ) {
+ float value = (*it)->value;
+ value = 1 - powf(value,2);
+ value = sqrtf(value);
+ dst->fast_simple_add ( (*it)->when, value );
+ }
+}
+
+/*
+static void
+generate_inverse_coefficient_curve (boost::shared_ptr dst, boost::shared_ptr src)
+{
+ //calc inverse gain coefficient curve
+ for (Evoral::ControlList::const_iterator it = src->begin(); it!=src->end(); ++it ) {
+ float value = 1.0 - (*it)->value;
+ dst->fast_simple_add ( (*it)->when, value );
+ }
+}
+*/
+
+static void
+generate_db_fade (boost::shared_ptr dst, double len, int num_steps, float dB_drop)
+{
+ dst->fast_simple_add (0, 1);
+
+ //generate a fade-out curve by successively applying a gain drop
+ float fade_speed = dB_to_coefficient(dB_drop / (float) num_steps);
+ for (int i = 1; i < (num_steps-1); i++) {
+ float coeff = 1.0;
+ for (int j = 0; j < i; j++) {
+ coeff *= fade_speed;
+ }
+ dst->fast_simple_add (len*(double)i/(double)num_steps, coeff);
+ }
+
+ dst->fast_simple_add (len, VERY_SMALL_SIGNAL);
+}
+
+static void
+merge_curves (boost::shared_ptr dst,
+ boost::shared_ptr curve1,
+ boost::shared_ptr curve2)
+{
+ Evoral::ControlList::EventList::size_type size = curve1->size();
+
+ //curve lengths must match for now
+ if (size != curve2->size()) {
+ return;
+ }
+
+ Evoral::ControlList::const_iterator c1 = curve1->begin();
+ int count = 0;
+ for (Evoral::ControlList::const_iterator c2 = curve2->begin(); c2!=curve2->end(); c2++ ) {
+ float v1 = accurate_coefficient_to_dB((*c1)->value);
+ float v2 = accurate_coefficient_to_dB((*c2)->value);
+
+ double interp = v1 * ( 1.0-( (double)count / (double)size) );
+ interp += v2 * ( (double)count / (double)size );
+
+ interp = dB_to_coefficient(interp);
+ dst->add ( (*c1)->when, interp );
+ c1++;
+ count++;
+ }
+}
+
void
AudioRegion::make_property_quarks ()
{
@@ -133,10 +217,14 @@ AudioRegion::AudioRegion (Session& s, framepos_t start, framecnt_t len, std::str
, AUDIOREGION_STATE_DEFAULT
, _automatable (s)
, _fade_in (new AutomationList(Evoral::Parameter(FadeInAutomation)))
+ , _inverse_fade_in (new AutomationList(Evoral::Parameter(FadeInAutomation)))
, _fade_out (new AutomationList(Evoral::Parameter(FadeOutAutomation)))
+ , _inverse_fade_out (new AutomationList(Evoral::Parameter(FadeOutAutomation)))
, _envelope (new AutomationList(Evoral::Parameter(EnvelopeAutomation)))
, _fade_in_suspended (0)
, _fade_out_suspended (0)
+ , _fade_in_is_xfade (false)
+ , _fade_out_is_xfade (false)
{
init ();
assert (_sources.size() == _master_sources.size());
@@ -148,10 +236,14 @@ AudioRegion::AudioRegion (const SourceList& srcs)
, AUDIOREGION_STATE_DEFAULT
, _automatable(srcs[0]->session())
, _fade_in (new AutomationList(Evoral::Parameter(FadeInAutomation)))
+ , _inverse_fade_in (new AutomationList(Evoral::Parameter(FadeInAutomation)))
, _fade_out (new AutomationList(Evoral::Parameter(FadeOutAutomation)))
+ , _inverse_fade_out (new AutomationList(Evoral::Parameter(FadeOutAutomation)))
, _envelope (new AutomationList(Evoral::Parameter(EnvelopeAutomation)))
, _fade_in_suspended (0)
, _fade_out_suspended (0)
+ , _fade_in_is_xfade (false)
+ , _fade_out_is_xfade (false)
{
init ();
assert (_sources.size() == _master_sources.size());
@@ -162,13 +254,17 @@ AudioRegion::AudioRegion (boost::shared_ptr other)
, AUDIOREGION_COPY_STATE (other)
, _automatable (other->session())
, _fade_in (new AutomationList (*other->_fade_in))
+ , _inverse_fade_in (new AutomationList(*other->_inverse_fade_in))
, _fade_out (new AutomationList (*other->_fade_out))
+ , _inverse_fade_out (new AutomationList (*other->_inverse_fade_out))
/* As far as I can see, the _envelope's times are relative to region position, and have nothing
to do with sources (and hence _start). So when we copy the envelope, we just use the supplied offset.
*/
, _envelope (new AutomationList (*other->_envelope, 0, other->_length))
, _fade_in_suspended (0)
, _fade_out_suspended (0)
+ , _fade_in_is_xfade (false)
+ , _fade_out_is_xfade (false)
{
/* don't use init here, because we got fade in/out from the other region
*/
@@ -186,13 +282,17 @@ AudioRegion::AudioRegion (boost::shared_ptr other, framecnt_t
, AUDIOREGION_COPY_STATE (other)
, _automatable (other->session())
, _fade_in (new AutomationList (*other->_fade_in))
+ , _inverse_fade_in (new AutomationList(*other->_inverse_fade_in))
, _fade_out (new AutomationList (*other->_fade_out))
+ , _inverse_fade_out (new AutomationList (*other->_inverse_fade_out))
/* As far as I can see, the _envelope's times are relative to region position, and have nothing
to do with sources (and hence _start). So when we copy the envelope, we just use the supplied offset.
*/
, _envelope (new AutomationList (*other->_envelope, offset, other->_length))
, _fade_in_suspended (0)
, _fade_out_suspended (0)
+ , _fade_in_is_xfade (false)
+ , _fade_out_is_xfade (false)
{
/* don't use init here, because we got fade in/out from the other region
*/
@@ -210,10 +310,14 @@ AudioRegion::AudioRegion (boost::shared_ptr other, const Sour
, AUDIOREGION_COPY_STATE (other)
, _automatable (other->session())
, _fade_in (new AutomationList (*other->_fade_in))
+ , _inverse_fade_in (new AutomationList(*other->_inverse_fade_in))
, _fade_out (new AutomationList (*other->_fade_out))
+ , _inverse_fade_out (new AutomationList (*other->_inverse_fade_out))
, _envelope (new AutomationList (*other->_envelope))
, _fade_in_suspended (0)
, _fade_out_suspended (0)
+ , _fade_in_is_xfade (false)
+ , _fade_out_is_xfade (false)
{
/* make-a-sort-of-copy-with-different-sources constructor (used by audio filter) */
@@ -231,10 +335,14 @@ AudioRegion::AudioRegion (SourceList& srcs)
, AUDIOREGION_STATE_DEFAULT
, _automatable(srcs[0]->session())
, _fade_in (new AutomationList(Evoral::Parameter(FadeInAutomation)))
+ , _inverse_fade_in (new AutomationList(Evoral::Parameter(FadeInAutomation)))
, _fade_out (new AutomationList(Evoral::Parameter(FadeOutAutomation)))
+ , _inverse_fade_out (new AutomationList(Evoral::Parameter(FadeOutAutomation)))
, _envelope (new AutomationList(Evoral::Parameter(EnvelopeAutomation)))
, _fade_in_suspended (0)
, _fade_out_suspended (0)
+ , _fade_in_is_xfade (false)
+ , _fade_out_is_xfade (false)
{
init ();
@@ -341,45 +449,43 @@ AudioRegion::read_peaks (PeakData *buf, framecnt_t npeaks, framecnt_t offset, fr
}
}
+/** @param buf Buffer to write data to (existing data will be overwritten).
+ * @param pos Position to read from as an offset from the region position.
+ * @param cnt Number of frames to read.
+ * @param channel Channel to read from.
+ */
framecnt_t
-AudioRegion::read (Sample* buf, framepos_t timeline_position, framecnt_t cnt, int channel) const
+AudioRegion::read (Sample* buf, framepos_t pos, framecnt_t cnt, int channel) const
{
/* raw read, no fades, no gain, nada */
- /* XXX: xfade: passes no mixbuf... */
- return _read_at (_sources, _length, buf, 0, 0, _position + timeline_position, cnt, channel, ReadOps (0));
+ return read_from_sources (_sources, _length, buf, _position + pos, cnt, channel);
}
framecnt_t
-AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
- framepos_t position, framecnt_t cnt, uint32_t chan_n) const
-{
- /* regular diskstream/butler read complete with fades etc */
- return _read_at (_sources, _length, buf, mixdown_buffer, gain_buffer,
- position, cnt, chan_n, ReadOps (~0));
-}
-
-framecnt_t
-AudioRegion::master_read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
+AudioRegion::master_read_at (Sample *buf, Sample* /*mixdown_buffer*/, float* /*gain_buffer*/,
framepos_t position, framecnt_t cnt, uint32_t chan_n) const
{
/* do not read gain/scaling/fades and do not count this disk i/o in statistics */
assert (cnt >= 0);
-
- return _read_at (_master_sources, _master_sources.front()->length(_master_sources.front()->timeline_position()),
- buf, mixdown_buffer, gain_buffer, position, cnt, chan_n, ReadOps (0));
+ return read_from_sources (
+ _master_sources, _master_sources.front()->length (_master_sources.front()->timeline_position()),
+ buf, position, cnt, chan_n
+ );
}
-/** @param position Position within the session to read from.
+/** @param buf Buffer to mix data into.
+ * @param mixdown_buffer Scratch buffer for audio data.
+ * @param gain_buffer Scratch buffer for gain data.
+ * @param position Position within the session to read from.
* @param cnt Number of frames to read.
+ * @param chan_n Channel number to read.
*/
framecnt_t
-AudioRegion::_read_at (const SourceList& srcs, framecnt_t limit,
- Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
- framepos_t position,
- framecnt_t cnt,
- uint32_t chan_n,
- ReadOps rops) const
+AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
+ framepos_t position,
+ framecnt_t cnt,
+ uint32_t chan_n) const
{
/* We are reading data from this region into buf (possibly via mixdown_buffer).
The caller has verified that we cover the desired section.
@@ -395,7 +501,7 @@ AudioRegion::_read_at (const SourceList& srcs, framecnt_t limit,
return 0;
}
- if (muted() && rops != ReadOpsNone) {
+ if (muted()) {
return 0; /* read nothing */
}
@@ -407,11 +513,11 @@ AudioRegion::_read_at (const SourceList& srcs, framecnt_t limit,
assert (position >= _position);
frameoffset_t const internal_offset = position - _position;
- if (internal_offset >= limit) {
+ if (internal_offset >= _length) {
return 0; /* read nothing */
}
- if ((to_read = min (cnt, limit - internal_offset)) == 0) {
+ if ((to_read = min (cnt, _length - internal_offset)) == 0) {
return 0; /* read nothing */
}
@@ -431,52 +537,49 @@ AudioRegion::_read_at (const SourceList& srcs, framecnt_t limit,
framecnt_t fade_interval_start = 0;
- if (rops & ReadOpsFades) {
-
- /* Fade in */
+ /* Fade in */
+
+ if (_fade_in_active && _session.config.get_use_region_fades()) {
- if (_fade_in_active && _session.config.get_use_region_fades()) {
-
- framecnt_t fade_in_length = (framecnt_t) _fade_in->back()->when;
-
- /* see if this read is within the fade in */
-
- if (internal_offset < fade_in_length) {
- fade_in_limit = min (to_read, fade_in_length - internal_offset);
- }
+ framecnt_t fade_in_length = (framecnt_t) _fade_in->back()->when;
+
+ /* see if this read is within the fade in */
+
+ if (internal_offset < fade_in_length) {
+ fade_in_limit = min (to_read, fade_in_length - internal_offset);
}
-
- /* Fade out */
-
- if (_fade_out_active && _session.config.get_use_region_fades()) {
-
- /* see if some part of this read is within the fade out */
+ }
+
+ /* Fade out */
+
+ if (_fade_out_active && _session.config.get_use_region_fades()) {
+
+ /* see if some part of this read is within the fade out */
/* ................. >| REGION
- limit
+ _length
{ } FADE
fade_out_length
^
- limit - fade_out_length
+ _length - fade_out_length
|--------------|
^internal_offset
^internal_offset + to_read
we need the intersection of [internal_offset,internal_offset+to_read] with
- [limit - fade_out_length, limit]
+ [_length - fade_out_length, _length]
*/
- fade_interval_start = max (internal_offset, limit - framecnt_t (_fade_out->back()->when));
- framecnt_t fade_interval_end = min(internal_offset + to_read, limit);
-
- if (fade_interval_end > fade_interval_start) {
- /* (part of the) the fade out is in this buffer */
- fade_out_limit = fade_interval_end - fade_interval_start;
- fade_out_offset = fade_interval_start - internal_offset;
- }
+ fade_interval_start = max (internal_offset, _length - framecnt_t (_fade_out->back()->when));
+ framecnt_t fade_interval_end = min(internal_offset + to_read, _length.val());
+
+ if (fade_interval_end > fade_interval_start) {
+ /* (part of the) the fade out is in this buffer */
+ fade_out_limit = fade_interval_end - fade_interval_start;
+ fade_out_offset = fade_interval_start - internal_offset;
}
}
@@ -486,10 +589,146 @@ AudioRegion::_read_at (const SourceList& srcs, framecnt_t limit,
must always mix.
*/
+ if (read_from_sources (_sources, _length, mixdown_buffer, position, to_read, chan_n) != to_read) {
+ return 0;
+ }
+
+ /* APPLY REGULAR GAIN CURVES AND SCALING TO mixdown_buffer */
+
+ if (envelope_active()) {
+ _envelope->curve().get_vector (internal_offset, internal_offset + to_read, gain_buffer, to_read);
+
+ if (_scale_amplitude != 1.0f) {
+ for (framecnt_t n = 0; n < to_read; ++n) {
+ mixdown_buffer[n] *= gain_buffer[n] * _scale_amplitude;
+ }
+ } else {
+ for (framecnt_t n = 0; n < to_read; ++n) {
+ mixdown_buffer[n] *= gain_buffer[n];
+ }
+ }
+ } else if (_scale_amplitude != 1.0f) {
+ apply_gain_to_buffer (mixdown_buffer, to_read, _scale_amplitude);
+ }
+
+
+ /* APPLY FADES TO THE DATA IN mixdown_buffer AND MIX THE RESULTS INTO
+ * buf. The key things to realize here: (1) the fade being applied is
+ * (as of April 26th 2012) just the inverse of the fade in curve (2)
+ * "buf" contains data from lower regions already. So this operation
+ * fades out the existing material.
+ */
+
+ if (fade_in_limit != 0) {
+ if (_inverse_fade_in) {
+
+ /* explicit inverse fade in curve (e.g. for constant
+ * power), so we have to fetch it.
+ */
+
+ _inverse_fade_in->curve().get_vector (internal_offset, internal_offset + fade_in_limit, gain_buffer, fade_in_limit);
+
+ /* Fade the data from lower layers out */
+ for (framecnt_t n = 0; n < fade_in_limit; ++n) {
+ buf[n] *= gain_buffer[n];
+ }
+
+ /* refill gain buffer with the fade in */
+
+ _fade_in->curve().get_vector (internal_offset, internal_offset + fade_in_limit, gain_buffer, fade_in_limit);
+
+ } else {
+
+ /* no explicit inverse fade in, so just use (1 - fade
+ * in) for the fade out of lower layers
+ */
+
+ _fade_in->curve().get_vector (internal_offset, internal_offset + fade_in_limit, gain_buffer, fade_in_limit);
+
+ for (framecnt_t n = 0; n < fade_in_limit; ++n) {
+ buf[n] *= 1 - gain_buffer[n];
+ }
+ }
+
+ /* Mix our newly-read data in, with the fade */
+ for (framecnt_t n = 0; n < fade_in_limit; ++n) {
+ buf[n] += mixdown_buffer[n] * gain_buffer[n];
+ }
+ }
+
+ if (fade_out_limit != 0) {
+
+ framecnt_t const curve_offset = fade_interval_start - (_length - _fade_out->back()->when);
+
+ if (_inverse_fade_out) {
+
+ _inverse_fade_out->curve().get_vector (curve_offset, curve_offset + fade_out_limit, gain_buffer, fade_out_limit);
+
+ /* Fade the data from lower levels out */
+ for (framecnt_t n = 0, m = fade_out_offset; n < fade_out_limit; ++n, ++m) {
+ buf[m] *= gain_buffer[n];
+ }
+
+ /* fetch the actual fade out */
+
+ _fade_out->curve().get_vector (curve_offset, curve_offset + fade_out_limit, gain_buffer, fade_out_limit);
+
+ } else {
+
+ /* no explicit inverse fade out, so just use (1 - fade
+ * out) for the fade in of lower layers
+ */
+
+ _fade_out->curve().get_vector (curve_offset, curve_offset + fade_out_limit, gain_buffer, fade_out_limit);
+
+ for (framecnt_t n = 0, m = fade_out_offset; n < fade_out_limit; ++n, ++m) {
+ buf[m] *= 1 - gain_buffer[n];
+ }
+ }
+
+ /* Mix our newly-read data out, with the fade */
+ for (framecnt_t n = 0, m = fade_out_offset; n < fade_out_limit; ++n, ++m) {
+ buf[m] += mixdown_buffer[m] * gain_buffer[n];
+ }
+ }
+
+
+ /* MIX THE REGION BODY FROM mixdown_buffer INTO buf */
+
+ mix_buffers_no_gain (buf + fade_in_limit, mixdown_buffer + fade_in_limit, to_read - fade_in_limit - fade_out_limit);
+
+ return to_read;
+}
+
+/** Read data directly from one of our sources, accounting for the situation when the track has a different channel
+ * count to the region.
+ *
+ * @param srcs Source list to get our source from.
+ * @param limit Furthest that we should read, as an offset from the region position.
+ * @param buf Buffer to write data into (existing contents of the buffer will be overwritten)
+ * @param position Position to read from, in session frames.
+ * @param cnt Number of frames to read.
+ * @param chan_n Channel to read from.
+ * @return Number of frames read.
+ */
+
+framecnt_t
+AudioRegion::read_from_sources (SourceList const & srcs, framecnt_t limit, Sample* buf, framepos_t position, framecnt_t cnt, uint32_t chan_n) const
+{
+ frameoffset_t const internal_offset = position - _position;
+ if (internal_offset >= limit) {
+ return 0;
+ }
+
+ framecnt_t const to_read = min (cnt, limit - internal_offset);
+ if (to_read == 0) {
+ return 0;
+ }
+
if (chan_n < n_channels()) {
boost::shared_ptr src = boost::dynamic_pointer_cast (srcs[chan_n]);
- if (src->read (mixdown_buffer, _start + internal_offset, to_read) != to_read) {
+ if (src->read (buf, _start + internal_offset, to_read) != to_read) {
return 0; /* "read nothing" */
}
@@ -506,67 +745,12 @@ AudioRegion::_read_at (const SourceList& srcs, framecnt_t limit,
uint32_t channel = n_channels() % chan_n;
boost::shared_ptr src = boost::dynamic_pointer_cast (srcs[channel]);
- if (src->read (mixdown_buffer, _start + internal_offset, to_read) != to_read) {
+ if (src->read (buf, _start + internal_offset, to_read) != to_read) {
return 0; /* "read nothing" */
}
}
}
- /* APPLY REGULAR GAIN CURVES AND SCALING TO mixdown_buffer */
-
- if ((rops & ReadOpsOwnAutomation) && envelope_active()) {
- _envelope->curve().get_vector (internal_offset, internal_offset + to_read, gain_buffer, to_read);
-
- if ((rops & ReadOpsOwnScaling) && _scale_amplitude != 1.0f) {
- for (framecnt_t n = 0; n < to_read; ++n) {
- mixdown_buffer[n] *= gain_buffer[n] * _scale_amplitude;
- }
- } else {
- for (framecnt_t n = 0; n < to_read; ++n) {
- mixdown_buffer[n] *= gain_buffer[n];
- }
- }
- } else if ((rops & ReadOpsOwnScaling) && _scale_amplitude != 1.0f) {
- apply_gain_to_buffer (mixdown_buffer, to_read, _scale_amplitude);
- }
-
-
- /* APPLY FADES TO THE DATA IN mixdown_buffer AND MIX THE RESULTS INTO buf */
-
- if (fade_in_limit != 0) {
- _fade_in->curve().get_vector (internal_offset, internal_offset + fade_in_limit, gain_buffer, fade_in_limit);
-
- /* Fade the current data out */
- for (framecnt_t n = 0; n < fade_in_limit; ++n) {
- buf[n] *= 1 - gain_buffer[n];
- }
-
- /* Mix our newly-read data in, with the fade */
- for (framecnt_t n = 0; n < fade_in_limit; ++n) {
- buf[n] += mixdown_buffer[n] * gain_buffer[n];
- }
- }
-
- if (fade_out_limit != 0) {
- framecnt_t const curve_offset = fade_interval_start - (limit - _fade_out->back()->when);
- _fade_out->curve().get_vector (curve_offset, curve_offset + fade_out_limit, gain_buffer, fade_out_limit);
-
- /* Fade the current data in */
- for (framecnt_t n = 0, m = fade_out_offset; n < fade_out_limit; ++n, ++m) {
- buf[m] *= 1 - gain_buffer[n];
- }
-
- /* Mix our newly-read data in, with the fade */
- for (framecnt_t n = 0, m = fade_out_offset; n < fade_out_limit; ++n, ++m) {
- buf[m] += mixdown_buffer[m] * gain_buffer[n];
- }
- }
-
-
- /* MIX THE REGION BODY FROM mixdown_buffer INTO buf */
-
- mix_buffers_no_gain (buf + fade_in_limit, mixdown_buffer + fade_in_limit, to_read - fade_in_limit - fade_out_limit);
-
return to_read;
}
@@ -605,6 +789,7 @@ AudioRegion::state ()
}
child = node.add_child (X_("FadeIn"));
+ child->add_property ("is-xfade", (_fade_in_is_xfade ? "yes" : "no"));
if (_default_fade_in) {
child->add_property ("default", "yes");
@@ -612,7 +797,13 @@ AudioRegion::state ()
child->add_child_nocopy (_fade_in->get_state ());
}
+ if (_inverse_fade_in) {
+ child = node.add_child (X_("InvFadeIn"));
+ child->add_child_nocopy (_inverse_fade_in->get_state ());
+ }
+
child = node.add_child (X_("FadeOut"));
+ child->add_property ("is-xfade", (_fade_out_is_xfade ? "yes" : "no"));
if (_default_fade_out) {
child->add_property ("default", "yes");
@@ -620,6 +811,11 @@ AudioRegion::state ()
child->add_child_nocopy (_fade_out->get_state ());
}
+ if (_inverse_fade_out) {
+ child = node.add_child (X_("InvFadeOut"));
+ child->add_child_nocopy (_inverse_fade_out->get_state ());
+ }
+
return node;
}
@@ -677,7 +873,7 @@ AudioRegion::_set_state (const XMLNode& node, int version, PropertyChange& what_
_fade_in->clear ();
- if ((prop = child->property ("default")) != 0 || (prop = child->property ("steepness")) != 0) {
+ if (((prop = child->property ("default")) != 0 && string_is_affirmative (prop->value())) || (prop = child->property ("steepness")) != 0) {
set_default_fade_in ();
} else {
XMLNode* grandchild = child->child ("AutomationList");
@@ -686,6 +882,12 @@ AudioRegion::_set_state (const XMLNode& node, int version, PropertyChange& what_
}
}
+ if ((prop = child->property ("is-xfade")) != 0) {
+ _fade_in_is_xfade = string_is_affirmative (prop->value());
+ } else {
+ _fade_in_is_xfade = false;
+ }
+
if ((prop = child->property ("active")) != 0) {
if (string_is_affirmative (prop->value())) {
set_fade_in_active (true);
@@ -698,7 +900,7 @@ AudioRegion::_set_state (const XMLNode& node, int version, PropertyChange& what_
_fade_out->clear ();
- if ((prop = child->property ("default")) != 0 || (prop = child->property ("steepness")) != 0) {
+ if (((prop = child->property ("default")) != 0 && (string_is_affirmative (prop->value()))) || (prop = child->property ("steepness")) != 0) {
set_default_fade_out ();
} else {
XMLNode* grandchild = child->child ("AutomationList");
@@ -707,7 +909,13 @@ AudioRegion::_set_state (const XMLNode& node, int version, PropertyChange& what_
}
}
- if ((prop = child->property ("active")) != 0) {
+ if ((prop = child->property ("is-xfade")) != 0) {
+ _fade_out_is_xfade = string_is_affirmative (prop->value());
+ } else {
+ _fade_out_is_xfade = false;
+ }
+
+ if ((prop = child->property ("active")) != 0) {
if (string_is_affirmative (prop->value())) {
set_fade_out_active (true);
} else {
@@ -715,6 +923,16 @@ AudioRegion::_set_state (const XMLNode& node, int version, PropertyChange& what_
}
}
+ } else if (child->name() == "InvFadeIn") {
+ XMLNode* grandchild = child->child ("AutomationList");
+ if (grandchild) {
+ _inverse_fade_in->set_state (*grandchild, version);
+ }
+ } else if (child->name() == "InvFadeOut") {
+ XMLNode* grandchild = child->child ("AutomationList");
+ if (grandchild) {
+ _inverse_fade_out->set_state (*grandchild, version);
+ }
}
}
@@ -757,6 +975,7 @@ AudioRegion::set_fade_in (boost::shared_ptr f)
_fade_in->freeze ();
*_fade_in = *f;
_fade_in->thaw ();
+ _default_fade_in = false;
send_change (PropertyChange (Properties::fade_in));
}
@@ -764,57 +983,64 @@ AudioRegion::set_fade_in (boost::shared_ptr f)
void
AudioRegion::set_fade_in (FadeShape shape, framecnt_t len)
{
+ boost::shared_ptr c1 (new Evoral::ControlList (FadeInAutomation));
+ boost::shared_ptr c2 (new Evoral::ControlList (FadeInAutomation));
+ boost::shared_ptr c3 (new Evoral::ControlList (FadeInAutomation));
+
_fade_in->freeze ();
_fade_in->clear ();
+ _inverse_fade_in->clear ();
switch (shape) {
case FadeLinear:
_fade_in->fast_simple_add (0.0, 0.0);
_fade_in->fast_simple_add (len, 1.0);
+ reverse_curve (_inverse_fade_in, _fade_in);
break;
case FadeFast:
- _fade_in->fast_simple_add (0, 0);
- _fade_in->fast_simple_add (len * 0.389401, 0.0333333);
- _fade_in->fast_simple_add (len * 0.629032, 0.0861111);
- _fade_in->fast_simple_add (len * 0.829493, 0.233333);
- _fade_in->fast_simple_add (len * 0.9447, 0.483333);
- _fade_in->fast_simple_add (len * 0.976959, 0.697222);
- _fade_in->fast_simple_add (len, 1);
+ generate_db_fade (_fade_in, len, 10, -60);
+ reverse_curve (c1, _fade_in);
+ _fade_in->copy_events (*c1);
+ generate_inverse_power_curve (_inverse_fade_in, _fade_in);
break;
case FadeSlow:
- _fade_in->fast_simple_add (0, 0);
- _fade_in->fast_simple_add (len * 0.0207373, 0.197222);
- _fade_in->fast_simple_add (len * 0.0645161, 0.525);
- _fade_in->fast_simple_add (len * 0.152074, 0.802778);
- _fade_in->fast_simple_add (len * 0.276498, 0.919444);
- _fade_in->fast_simple_add (len * 0.481567, 0.980556);
- _fade_in->fast_simple_add (len * 0.767281, 1);
- _fade_in->fast_simple_add (len, 1);
+ generate_db_fade (c1, len, 10, -1); // start off with a slow fade
+ generate_db_fade (c2, len, 10, -80); // end with a fast fade
+ merge_curves (_fade_in, c1, c2);
+ generate_inverse_power_curve (_inverse_fade_in, _fade_in);
break;
- case FadeLogA:
- _fade_in->fast_simple_add (0, 0);
- _fade_in->fast_simple_add (len * 0.0737327, 0.308333);
- _fade_in->fast_simple_add (len * 0.246544, 0.658333);
- _fade_in->fast_simple_add (len * 0.470046, 0.886111);
- _fade_in->fast_simple_add (len * 0.652074, 0.972222);
- _fade_in->fast_simple_add (len * 0.771889, 0.988889);
- _fade_in->fast_simple_add (len, 1);
+ case FadeConstantPower:
+ for (int i = 0; i < 9; ++i) {
+ float dist = (float) i / 10.0f;
+ _fade_in->fast_simple_add (len*dist, sin (dist*M_PI/2));
+ }
+ _fade_in->fast_simple_add (len, 1.0);
+ reverse_curve (_inverse_fade_in, _fade_in);
break;
+
+ case FadeSymmetric:
+ // starts kind of like a constant power but has a slower fadeout
+ // however it is NOT constant power and there will be a level drop in the middle of the crossfade
+ c1->fast_simple_add (0.0, 1.0);
+ for ( int i = 1; i < 9; i++ ) {
+ float dist = (float)i/10.0;
+ c1->fast_simple_add ((len * dist), cos(dist*M_PI/10.0));
+ }
+ c1->fast_simple_add (len, VERY_SMALL_SIGNAL);
- case FadeLogB:
- _fade_in->fast_simple_add (0, 0);
- _fade_in->fast_simple_add (len * 0.304147, 0.0694444);
- _fade_in->fast_simple_add (len * 0.529954, 0.152778);
- _fade_in->fast_simple_add (len * 0.725806, 0.333333);
- _fade_in->fast_simple_add (len * 0.847926, 0.558333);
- _fade_in->fast_simple_add (len * 0.919355, 0.730556);
- _fade_in->fast_simple_add (len, 1);
+ //curve 2 is a slow fade at end
+ generate_db_fade (c2, len, 10, -30 );
+
+ merge_curves (c3, c1, c2);
+ reverse_curve (_fade_in, c3);
+ reverse_curve (_inverse_fade_in, _fade_in );
break;
}
+ _default_fade_in = false;
_fade_in->thaw ();
send_change (PropertyChange (Properties::fade_in));
}
@@ -825,6 +1051,7 @@ AudioRegion::set_fade_out (boost::shared_ptr f)
_fade_out->freeze ();
*_fade_out = *f;
_fade_out->thaw ();
+ _default_fade_out = false;
send_change (PropertyChange (Properties::fade_in));
}
@@ -832,57 +1059,65 @@ AudioRegion::set_fade_out (boost::shared_ptr f)
void
AudioRegion::set_fade_out (FadeShape shape, framecnt_t len)
{
+ boost::shared_ptr c1 (new Evoral::ControlList (FadeOutAutomation));
+ boost::shared_ptr c2 (new Evoral::ControlList (FadeOutAutomation));
+
_fade_out->freeze ();
_fade_out->clear ();
+ _inverse_fade_out->clear ();
switch (shape) {
- case FadeFast:
- _fade_out->fast_simple_add (len * 0, 1);
- _fade_out->fast_simple_add (len * 0.023041, 0.697222);
- _fade_out->fast_simple_add (len * 0.0553, 0.483333);
- _fade_out->fast_simple_add (len * 0.170507, 0.233333);
- _fade_out->fast_simple_add (len * 0.370968, 0.0861111);
- _fade_out->fast_simple_add (len * 0.610599, 0.0333333);
- _fade_out->fast_simple_add (len * 1, 0);
- break;
-
- case FadeLogA:
- _fade_out->fast_simple_add (len * 0, 1);
- _fade_out->fast_simple_add (len * 0.228111, 0.988889);
- _fade_out->fast_simple_add (len * 0.347926, 0.972222);
- _fade_out->fast_simple_add (len * 0.529954, 0.886111);
- _fade_out->fast_simple_add (len * 0.753456, 0.658333);
- _fade_out->fast_simple_add (len * 0.9262673, 0.308333);
- _fade_out->fast_simple_add (len * 1, 0);
- break;
-
- case FadeSlow:
- _fade_out->fast_simple_add (len * 0, 1);
- _fade_out->fast_simple_add (len * 0.305556, 1);
- _fade_out->fast_simple_add (len * 0.548611, 0.991736);
- _fade_out->fast_simple_add (len * 0.759259, 0.931129);
- _fade_out->fast_simple_add (len * 0.918981, 0.68595);
- _fade_out->fast_simple_add (len * 0.976852, 0.22865);
- _fade_out->fast_simple_add (len * 1, 0);
- break;
-
- case FadeLogB:
- _fade_out->fast_simple_add (len * 0, 1);
- _fade_out->fast_simple_add (len * 0.080645, 0.730556);
- _fade_out->fast_simple_add (len * 0.277778, 0.289256);
- _fade_out->fast_simple_add (len * 0.470046, 0.152778);
- _fade_out->fast_simple_add (len * 0.695853, 0.0694444);
- _fade_out->fast_simple_add (len * 1, 0);
- break;
-
case FadeLinear:
- _fade_out->fast_simple_add (len * 0, 1);
- _fade_out->fast_simple_add (len * 1, 0);
+ _fade_out->fast_simple_add (0.0, 1.0);
+ _fade_out->fast_simple_add (len, VERY_SMALL_SIGNAL);
+ reverse_curve (_inverse_fade_out, _fade_out);
+ break;
+
+ case FadeFast:
+ generate_db_fade (_fade_out, len, 10, -60 );
+ generate_inverse_power_curve (_inverse_fade_out, _fade_out);
+ break;
+
+ case FadeSlow:
+ generate_db_fade (c1, len, 10, -1 ); //start off with a slow fade
+ generate_db_fade (c2, len, 10, -80 ); //end with a fast fade
+ merge_curves (_fade_out, c1, c2);
+ generate_inverse_power_curve (_inverse_fade_out, _fade_out);
+ break;
+
+ case FadeConstantPower:
+ //constant-power fades use a sin/cos relationship
+ //the cutoff is abrupt but it has the benefit of being symmetrical
+ _fade_out->fast_simple_add (0.0, 1.0);
+ for (int i = 1; i < 9; i++ ) {
+ float dist = (float)i/10.0;
+ _fade_out->fast_simple_add ((len * dist), cos(dist*M_PI/2));
+ }
+ _fade_out->fast_simple_add (len, VERY_SMALL_SIGNAL);
+ reverse_curve (_inverse_fade_out, _fade_out);
+ break;
+
+ case FadeSymmetric:
+ //starts kind of like a constant power but has a slower fadeout
+ //however it is NOT constant power and there will be a level drop in the middle of the crossfade
+ c1->fast_simple_add (0.0, 1.0);
+ for ( int i = 1; i < 9; i++ ) {
+ float dist = (float)i/10.0;
+ c1->fast_simple_add ((len * dist), cos(dist*M_PI/10.0)); //cheesy way of making a flat line
+ }
+ c1->fast_simple_add (len, VERY_SMALL_SIGNAL);
+
+ //curve 2 is a slow fade at end
+ generate_db_fade (c2, len, 10, -30);
+
+ merge_curves (_fade_out, c1, c2);
+ reverse_curve (_inverse_fade_out, _fade_out);
break;
}
+ _default_fade_out = false;
_fade_out->thaw ();
- send_change (PropertyChange (Properties::fade_in));
+ send_change (PropertyChange (Properties::fade_out));
}
void
@@ -891,10 +1126,32 @@ AudioRegion::set_fade_in_length (framecnt_t len)
if (len > _length) {
len = _length - 1;
}
+
+ if (len < 64) {
+ len = 64;
+ }
bool changed = _fade_in->extend_to (len);
if (changed) {
+ if (_inverse_fade_in) {
+ _inverse_fade_in->extend_to (len);
+ }
+
+ if (_session.config.get_xfade_model() == FullCrossfade &&
+ _session.config.get_auto_xfade() &&
+ _fade_in_is_xfade) {
+
+ /* trim a single other region below us to the new start
+ of the fade.
+ */
+
+ boost::shared_ptr other = get_single_other_xfade_region (true);
+ if (other) {
+ other->trim_end (position() + len);
+ }
+ }
+
_default_fade_in = false;
send_change (PropertyChange (Properties::fade_in));
}
@@ -907,10 +1164,33 @@ AudioRegion::set_fade_out_length (framecnt_t len)
len = _length - 1;
}
+ if (len < 64) {
+ len = 64;
+ }
+
bool changed = _fade_out->extend_to (len);
if (changed) {
+
+ if (_inverse_fade_out) {
+ _inverse_fade_out->extend_to (len);
+ }
_default_fade_out = false;
+
+ if (_session.config.get_xfade_model() == FullCrossfade &&
+ _session.config.get_auto_xfade() &&
+ _fade_out_is_xfade) {
+
+ /* trim a single other region below us to the new start
+ of the fade.
+ */
+
+ boost::shared_ptr other = get_single_other_xfade_region (false);
+ if (other) {
+ other->trim_front (last_frame() - len);
+ }
+ }
+
send_change (PropertyChange (Properties::fade_out));
}
}
@@ -952,6 +1232,7 @@ void
AudioRegion::set_default_fade_in ()
{
_fade_in_suspended = 0;
+ _fade_in_is_xfade = false;
set_fade_in (FadeLinear, 64);
}
@@ -959,6 +1240,7 @@ void
AudioRegion::set_default_fade_out ()
{
_fade_out_suspended = 0;
+ _fade_out_is_xfade = false;
set_fade_out (FadeLinear, 64);
}
@@ -1527,6 +1809,85 @@ AudioRegion::body_range () const
return Evoral::Range (first_frame() + _fade_in->back()->when, last_frame() - _fade_out->back()->when);
}
+void
+AudioRegion::set_fade_in_is_xfade (bool yn)
+{
+ _fade_in_is_xfade = yn;
+}
+
+void
+AudioRegion::set_fade_out_is_xfade (bool yn)
+{
+ _fade_out_is_xfade = yn;
+}
+
+boost::shared_ptr
+AudioRegion::get_single_other_xfade_region (bool start) const
+{
+ boost::shared_ptr pl (playlist());
+
+ if (!pl) {
+ /* not currently in a playlist - xfade length is unbounded
+ (and irrelevant)
+ */
+ return boost::shared_ptr ();
+ }
+
+ boost::shared_ptr rl;
+
+ if (start) {
+ rl = pl->regions_at (position());
+ } else {
+ rl = pl->regions_at (last_frame());
+ }
+
+ RegionList::iterator i;
+ boost::shared_ptr other;
+ uint32_t n = 0;
+
+ /* count and find the other region in a single pass through the list */
+
+ for (i = rl->begin(); i != rl->end(); ++i) {
+ if ((*i).get() != this) {
+ other = *i;
+ }
+ ++n;
+ }
+
+ if (n != 2) {
+ /* zero or multiple regions stacked here - don't care about xfades */
+ return boost::shared_ptr ();
+ }
+
+ return other;
+}
+
+framecnt_t
+AudioRegion::verify_xfade_bounds (framecnt_t len, bool start)
+{
+ boost::shared_ptr other = get_single_other_xfade_region (start);
+ framecnt_t maxlen;
+
+ if (!other) {
+ /* zero or > 2 regions here, don't care about len */
+ return len;
+ }
+
+ /* we overlap a single region. clamp the length of an xfade to
+ the maximum possible duration of the overlap (if the other
+ region were trimmed appropriately).
+ */
+
+ if (start) {
+ maxlen = other->latest_possible_frame() - position();
+ } else {
+ maxlen = last_frame() - other->earliest_possible_position();
+ }
+
+ return min (maxlen, len);
+
+}
+
extern "C" {
int region_read_peaks_from_c (void *arg, uint32_t npeaks, uint32_t start, uint32_t cnt, intptr_t data, uint32_t n_chan, double samples_per_unit)
diff --git a/libs/ardour/broadcast_info.cc b/libs/ardour/broadcast_info.cc
index af760629ff..d31104d545 100644
--- a/libs/ardour/broadcast_info.cc
+++ b/libs/ardour/broadcast_info.cc
@@ -81,7 +81,7 @@ BroadcastInfo::set_originator (std::string const & str)
}
void
-BroadcastInfo::set_originator_ref_from_session (Session const & session)
+BroadcastInfo::set_originator_ref_from_session (Session const & /*session*/)
{
_has_info = true;
diff --git a/libs/ardour/control_protocol_manager.cc b/libs/ardour/control_protocol_manager.cc
index 6aa0c51da2..59001dce14 100644
--- a/libs/ardour/control_protocol_manager.cc
+++ b/libs/ardour/control_protocol_manager.cc
@@ -19,6 +19,8 @@
#include
+#include
+
#include "pbd/compose.h"
#include "pbd/file_utils.h"
#include "pbd/error.h"
@@ -169,6 +171,8 @@ ControlProtocolManager::teardown (ControlProtocolInfo& cpi)
}
cpi.protocol = 0;
+ delete cpi.state;
+ cpi.state = 0;
dlclose (cpi.descriptor->module);
return 0;
}
@@ -200,10 +204,10 @@ ControlProtocolManager::discover_control_protocols ()
Glib::PatternSpec dylib_extension_pattern("*.dylib");
find_matching_files_in_search_path (control_protocol_search_path (),
- so_extension_pattern, cp_modules);
+ so_extension_pattern, cp_modules);
find_matching_files_in_search_path (control_protocol_search_path (),
- dylib_extension_pattern, cp_modules);
+ dylib_extension_pattern, cp_modules);
DEBUG_TRACE (DEBUG::ControlProtocols,
string_compose (_("looking for control protocols in %1"), control_protocol_search_path().to_string()));
@@ -218,6 +222,13 @@ ControlProtocolManager::control_protocol_discover (string path)
{
ControlProtocolDescriptor* descriptor;
+ /* don't load shared objects that are just symlinks to the real thing.
+ */
+
+ if (Glib::file_test (path, Glib::FILE_TEST_IS_SYMLINK)) {
+ return 0;
+ }
+
if ((descriptor = get_descriptor (path)) != 0) {
if (!descriptor->probe (descriptor)) {
diff --git a/libs/ardour/delivery.cc b/libs/ardour/delivery.cc
index 2fc8d82e47..86ce419340 100644
--- a/libs/ardour/delivery.cc
+++ b/libs/ardour/delivery.cc
@@ -47,7 +47,7 @@ using namespace std;
using namespace PBD;
using namespace ARDOUR;
-PBD::Signal0 Delivery::PannersLegal;
+PBD::Signal0 Delivery::PannersLegal;
bool Delivery::panners_legal = false;
/* deliver to an existing IO object */
@@ -402,7 +402,7 @@ Delivery::reset_panner ()
}
}
-int
+void
Delivery::panners_became_legal ()
{
if (_panshell) {
@@ -414,7 +414,6 @@ Delivery::panners_became_legal ()
}
panner_legal_c.disconnect ();
- return 0;
}
void
@@ -438,11 +437,11 @@ Delivery::disable_panners ()
return 0;
}
-int
+void
Delivery::reset_panners ()
{
panners_legal = true;
- return *PannersLegal ();
+ PannersLegal ();
}
void
diff --git a/libs/ardour/enums.cc b/libs/ardour/enums.cc
index 4559ed457d..c0d6107639 100644
--- a/libs/ardour/enums.cc
+++ b/libs/ardour/enums.cc
@@ -73,6 +73,7 @@ setup_enum_writer ()
RemoteModel _RemoteModel;
DenormalModel _DenormalModel;
CrossfadeModel _CrossfadeModel;
+ CrossfadeChoice _CrossfadeChoice;
InsertMergePolicy _InsertMergePolicy;
ListenPosition _ListenPosition;
SampleFormat _SampleFormat;
@@ -121,7 +122,6 @@ setup_enum_writer ()
MidiModel::PatchChangeDiffCommand::Property _MidiModel_PatchChangeDiffCommand_Property;
WaveformScale _WaveformScale;
WaveformShape _WaveformShape;
- QuantizeType _QuantizeType;
Session::PostTransportWork _Session_PostTransportWork;
Session::SlaveState _Session_SlaveState;
MTC_Status _MIDI_MTC_Status;
@@ -257,6 +257,11 @@ setup_enum_writer ()
REGISTER_ENUM (ShortCrossfade);
REGISTER (_CrossfadeModel);
+ REGISTER_ENUM (RegionFades);
+ REGISTER_ENUM (ConstantPowerMinus3dB);
+ REGISTER_ENUM (ConstantPowerMinus6dB);
+ REGISTER (_CrossfadeChoice);
+
REGISTER_ENUM (InsertMergeReject);
REGISTER_ENUM (InsertMergeRelax);
REGISTER_ENUM (InsertMergeReplace);
@@ -409,8 +414,8 @@ setup_enum_writer ()
REGISTER_ENUM (FadeLinear);
REGISTER_ENUM (FadeFast);
REGISTER_ENUM (FadeSlow);
- REGISTER_ENUM (FadeLogA);
- REGISTER_ENUM (FadeLogB);
+ REGISTER_ENUM (FadeConstantPower);
+ REGISTER_ENUM (FadeSymmetric);
REGISTER (_FadeShape);
REGISTER_CLASS_ENUM (Diskstream, Recordable);
@@ -569,11 +574,6 @@ setup_enum_writer ()
REGISTER_ENUM(Rectified);
REGISTER(_WaveformShape);
- REGISTER_ENUM(Plain);
- REGISTER_ENUM(Legato);
- REGISTER_ENUM(Groove);
- REGISTER(_QuantizeType);
-
REGISTER_ENUM(AudioTime);
REGISTER_ENUM(MusicTime);
REGISTER(_PositionLockStyle);
@@ -732,6 +732,21 @@ std::ostream& operator<<(std::ostream& o, const CrossfadeModel& var)
std::string s = enum_2_string (var);
return o << s;
}
+
+std::istream& operator>>(std::istream& o, CrossfadeChoice& var)
+{
+ std::string s;
+ o >> s;
+ var = (CrossfadeChoice) string_2_enum (s, var);
+ return o;
+}
+
+std::ostream& operator<<(std::ostream& o, const CrossfadeChoice& var)
+{
+ std::string s = enum_2_string (var);
+ return o << s;
+}
+
std::istream& operator>>(std::istream& o, SyncSource& var)
{
std::string s;
diff --git a/libs/ardour/filesystem_paths.cc b/libs/ardour/filesystem_paths.cc
index 11ddc88502..2d14494764 100644
--- a/libs/ardour/filesystem_paths.cc
+++ b/libs/ardour/filesystem_paths.cc
@@ -30,8 +30,6 @@
#include "i18n.h"
-#define WITH_STATIC_PATHS 1
-
using namespace PBD;
namespace ARDOUR {
@@ -109,11 +107,7 @@ ardour_search_path ()
SearchPath
system_config_search_path ()
{
-#ifdef WITH_STATIC_PATHS
- SearchPath config_path(string(CONFIG_DIR));
-#else
SearchPath config_path(system_config_directories());
-#endif
config_path.add_subdirectory_to_paths("ardour3");
@@ -123,11 +117,7 @@ system_config_search_path ()
SearchPath
system_data_search_path ()
{
-#ifdef WITH_STATIC_PATHS
- SearchPath data_path(string(DATA_DIR));
-#else
SearchPath data_path(system_data_directories());
-#endif
data_path.add_subdirectory_to_paths("ardour3");
diff --git a/libs/ardour/graph.cc b/libs/ardour/graph.cc
index 556748e2de..300271c21a 100644
--- a/libs/ardour/graph.cc
+++ b/libs/ardour/graph.cc
@@ -108,14 +108,18 @@ Graph::reset_thread_list ()
drop_threads ();
}
- if (AudioEngine::instance()->create_process_thread (boost::bind (&Graph::main_thread, this), &a_thread, 100000) == 0) {
- _thread_list.push_back (a_thread);
+ if (AudioEngine::instance()->create_process_thread (boost::bind (&Graph::main_thread, this), &a_thread, 100000) != 0) {
+ throw failed_constructor ();
}
+ _thread_list.push_back (a_thread);
+
for (uint32_t i = 1; i < num_threads; ++i) {
- if (AudioEngine::instance()->create_process_thread (boost::bind (&Graph::helper_thread, this), &a_thread, 100000) == 0) {
- _thread_list.push_back (a_thread);
+ if (AudioEngine::instance()->create_process_thread (boost::bind (&Graph::helper_thread, this), &a_thread, 100000) != 0) {
+ throw failed_constructor ();
}
+
+ _thread_list.push_back (a_thread);
}
}
diff --git a/libs/ardour/internal_send.cc b/libs/ardour/internal_send.cc
index b4d89fb986..dfb0204c8c 100644
--- a/libs/ardour/internal_send.cc
+++ b/libs/ardour/internal_send.cc
@@ -359,7 +359,7 @@ InternalSend::set_can_pan (bool yn)
}
void
-InternalSend::cycle_start (pframes_t nframes)
+InternalSend::cycle_start (pframes_t /*nframes*/)
{
for (BufferSet::audio_iterator b = mixbufs.audio_begin(); b != mixbufs.audio_end(); ++b) {
b->prepare ();
diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc
index a278852e77..26432c66ef 100644
--- a/libs/ardour/io.cc
+++ b/libs/ardour/io.cc
@@ -256,8 +256,8 @@ IO::remove_port (boost::shared_ptr port, void* src)
ChanCount after = before;
after.set (port->type(), after.get (port->type()) - 1);
- bool const r = PortCountChanging (after); /* EMIT SIGNAL */
- if (r) {
+ boost::optional const r = PortCountChanging (after); /* EMIT SIGNAL */
+ if (r.get_value_or (false)) {
return -1;
}
diff --git a/libs/ardour/lv2_plugin.cc b/libs/ardour/lv2_plugin.cc
index 0b3bc3cd18..46c09a1227 100644
--- a/libs/ardour/lv2_plugin.cc
+++ b/libs/ardour/lv2_plugin.cc
@@ -175,7 +175,8 @@ LV2Plugin::LV2Plugin (AudioEngine& engine,
Session& session,
void* c_plugin,
framecnt_t rate)
- : Plugin(engine, session)
+ : Plugin (engine, session)
+ , Workee ()
, _impl(new Impl())
, _features(NULL)
, _worker(NULL)
@@ -185,7 +186,8 @@ LV2Plugin::LV2Plugin (AudioEngine& engine,
}
LV2Plugin::LV2Plugin (const LV2Plugin& other)
- : Plugin(other)
+ : Plugin (other)
+ , Workee ()
, _impl(new Impl())
, _features(NULL)
, _worker(NULL)
diff --git a/libs/ardour/midi_playlist.cc b/libs/ardour/midi_playlist.cc
index 7e3d70bfe0..81b14dd933 100644
--- a/libs/ardour/midi_playlist.cc
+++ b/libs/ardour/midi_playlist.cc
@@ -107,11 +107,8 @@ MidiPlaylist::read (Evoral::EventSink& dst, framepos_t start, framec
its OK to block (for short intervals).
*/
-#ifdef HAVE_GLIB_THREADS_RECMUTEX
- Glib::Threads::RecMutex::Lock rm (region_lock);
-#else
- Glib::RecMutex::Lock rm (region_lock);
-#endif
+ Playlist::RegionLock rl (this, false);
+
DEBUG_TRACE (DEBUG::MidiPlaylistIO, string_compose ("++++++ %1 .. %2 +++++++ %3 trackers +++++++++++++++++\n",
start, start + dur, _note_trackers.size()));
@@ -298,11 +295,8 @@ MidiPlaylist::read (Evoral::EventSink& dst, framepos_t start, framec
void
MidiPlaylist::clear_note_trackers ()
{
-#ifdef HAVE_GLIB_THREADS_RECMUTEX
- Glib::Threads::RecMutex::Lock rm (region_lock);
-#else
- Glib::RecMutex::Lock rm (region_lock);
-#endif
+ Playlist::RegionLock rl (this, false);
+
for (NoteTrackers::iterator n = _note_trackers.begin(); n != _note_trackers.end(); ++n) {
delete n->second;
}
@@ -407,12 +401,7 @@ MidiPlaylist::contained_automation()
its OK to block (for short intervals).
*/
-#ifdef HAVE_GLIB_THREADS_RECMUTEX
- Glib::Threads::RecMutex::Lock rm (region_lock);
-#else
- Glib::RecMutex::Lock rm (region_lock);
-#endif
-
+ Playlist::RegionLock rl (this, false);
set ret;
for (RegionList::const_iterator r = regions.begin(); r != regions.end(); ++r) {
diff --git a/libs/ardour/midi_playlist_source.cc b/libs/ardour/midi_playlist_source.cc
index 208b2b0460..957531f520 100644
--- a/libs/ardour/midi_playlist_source.cc
+++ b/libs/ardour/midi_playlist_source.cc
@@ -142,7 +142,7 @@ MidiPlaylistSource::read_unlocked (Evoral::EventSink& dst,
}
framecnt_t
-MidiPlaylistSource::write_unlocked (MidiRingBuffer& dst,
+MidiPlaylistSource::write_unlocked (MidiRingBuffer&,
framepos_t,
framecnt_t)
{
diff --git a/libs/ardour/midi_ui.cc b/libs/ardour/midi_ui.cc
index 770a371457..78da32e427 100644
--- a/libs/ardour/midi_ui.cc
+++ b/libs/ardour/midi_ui.cc
@@ -45,7 +45,7 @@ MidiControlUI* MidiControlUI::_instance = 0;
#include "pbd/abstract_ui.cc" /* instantiate the template */
MidiControlUI::MidiControlUI (Session& s)
- : AbstractUI (_("midiui"))
+ : AbstractUI (X_("midiui"))
, _session (s)
{
MIDI::Manager::instance()->PortsChanged.connect_same_thread (rebind_connection, boost::bind (&MidiControlUI::change_midi_ports, this));
diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc
index cb40b4df91..1b546ce4ed 100644
--- a/libs/ardour/playlist.cc
+++ b/libs/ardour/playlist.cc
@@ -32,6 +32,7 @@
#include "pbd/failed_constructor.h"
#include "pbd/stateful_diff_command.h"
#include "pbd/xml++.h"
+#include "pbd/stacktrace.h"
#include "ardour/debug.h"
#include "ardour/playlist.h"
@@ -608,11 +609,7 @@ Playlist::flush_notifications (bool from_undo)
*/
}
- if (
- ((regions_changed || pending_contents_change) && !in_set_state) ||
- pending_layering
- ) {
-
+ if (((regions_changed || pending_contents_change) && !in_set_state) || pending_layering) {
relayer ();
}
@@ -1761,6 +1758,12 @@ boost::shared_ptr
Playlist::regions_touched (framepos_t start, framepos_t end)
{
RegionLock rlock (this);
+ return regions_touched_locked (start, end);
+}
+
+boost::shared_ptr
+Playlist::regions_touched_locked (framepos_t start, framepos_t end)
+{
boost::shared_ptr rlist (new RegionList);
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
@@ -1772,126 +1775,125 @@ Playlist::regions_touched (framepos_t start, framepos_t end)
return rlist;
}
- framepos_t
- Playlist::find_next_transient (framepos_t from, int dir)
- {
- RegionLock rlock (this);
- AnalysisFeatureList points;
- AnalysisFeatureList these_points;
+framepos_t
+Playlist::find_next_transient (framepos_t from, int dir)
+{
+ RegionLock rlock (this);
+ AnalysisFeatureList points;
+ AnalysisFeatureList these_points;
+
+ for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
+ if (dir > 0) {
+ if ((*i)->last_frame() < from) {
+ continue;
+ }
+ } else {
+ if ((*i)->first_frame() > from) {
+ continue;
+ }
+ }
+
+ (*i)->get_transients (these_points);
+
+ /* add first frame, just, err, because */
+
+ these_points.push_back ((*i)->first_frame());
+
+ points.insert (points.end(), these_points.begin(), these_points.end());
+ these_points.clear ();
+ }
+
+ if (points.empty()) {
+ return -1;
+ }
+
+ TransientDetector::cleanup_transients (points, _session.frame_rate(), 3.0);
+ bool reached = false;
+
+ if (dir > 0) {
+ for (AnalysisFeatureList::iterator x = points.begin(); x != points.end(); ++x) {
+ if ((*x) >= from) {
+ reached = true;
+ }
+
+ if (reached && (*x) > from) {
+ return *x;
+ }
+ }
+ } else {
+ for (AnalysisFeatureList::reverse_iterator x = points.rbegin(); x != points.rend(); ++x) {
+ if ((*x) <= from) {
+ reached = true;
+ }
+
+ if (reached && (*x) < from) {
+ return *x;
+ }
+ }
+ }
+
+ return -1;
+}
- for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
- if (dir > 0) {
- if ((*i)->last_frame() < from) {
- continue;
- }
- } else {
- if ((*i)->first_frame() > from) {
- continue;
- }
- }
-
- (*i)->get_transients (these_points);
-
- /* add first frame, just, err, because */
-
- these_points.push_back ((*i)->first_frame());
-
- points.insert (points.end(), these_points.begin(), these_points.end());
- these_points.clear ();
- }
-
- if (points.empty()) {
- return -1;
- }
-
- TransientDetector::cleanup_transients (points, _session.frame_rate(), 3.0);
- bool reached = false;
-
- if (dir > 0) {
- for (AnalysisFeatureList::iterator x = points.begin(); x != points.end(); ++x) {
- if ((*x) >= from) {
- reached = true;
- }
-
- if (reached && (*x) > from) {
- return *x;
- }
- }
- } else {
- for (AnalysisFeatureList::reverse_iterator x = points.rbegin(); x != points.rend(); ++x) {
- if ((*x) <= from) {
- reached = true;
- }
-
- if (reached && (*x) < from) {
- return *x;
- }
- }
- }
-
- return -1;
- }
-
- boost::shared_ptr
- Playlist::find_next_region (framepos_t frame, RegionPoint point, int dir)
- {
- RegionLock rlock (this);
- boost::shared_ptr ret;
- framepos_t closest = max_framepos;
-
- bool end_iter = false;
-
- for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
-
- if(end_iter) break;
-
- frameoffset_t distance;
- boost::shared_ptr r = (*i);
- framepos_t pos = 0;
-
- switch (point) {
- case Start:
- pos = r->first_frame ();
- break;
- case End:
- pos = r->last_frame ();
- break;
- case SyncPoint:
- pos = r->sync_position ();
- break;
- }
-
- switch (dir) {
- case 1: /* forwards */
-
- if (pos > frame) {
- if ((distance = pos - frame) < closest) {
- closest = distance;
- ret = r;
- end_iter = true;
- }
- }
-
- break;
-
- default: /* backwards */
-
- if (pos < frame) {
- if ((distance = frame - pos) < closest) {
- closest = distance;
- ret = r;
- }
- }
- else {
- end_iter = true;
- }
-
- break;
- }
- }
-
- return ret;
- }
+boost::shared_ptr
+Playlist::find_next_region (framepos_t frame, RegionPoint point, int dir)
+{
+ RegionLock rlock (this);
+ boost::shared_ptr ret;
+ framepos_t closest = max_framepos;
+
+ bool end_iter = false;
+
+ for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
+
+ if(end_iter) break;
+
+ frameoffset_t distance;
+ boost::shared_ptr r = (*i);
+ framepos_t pos = 0;
+
+ switch (point) {
+ case Start:
+ pos = r->first_frame ();
+ break;
+ case End:
+ pos = r->last_frame ();
+ break;
+ case SyncPoint:
+ pos = r->sync_position ();
+ break;
+ }
+
+ switch (dir) {
+ case 1: /* forwards */
+
+ if (pos > frame) {
+ if ((distance = pos - frame) < closest) {
+ closest = distance;
+ ret = r;
+ end_iter = true;
+ }
+ }
+
+ break;
+
+ default: /* backwards */
+
+ if (pos < frame) {
+ if ((distance = frame - pos) < closest) {
+ closest = distance;
+ ret = r;
+ }
+ } else {
+ end_iter = true;
+ }
+
+ break;
+ }
+ }
+
+ return ret;
+}
framepos_t
Playlist::find_next_region_boundary (framepos_t frame, int dir)
@@ -2276,15 +2278,16 @@ Playlist::set_layer (boost::shared_ptr region, double new_layer)
}
void
-Playlist::setup_layering_indices (RegionList const & regions) const
+Playlist::setup_layering_indices (RegionList const & regions)
{
uint64_t j = 0;
+ list > xf;
+
for (RegionList::const_iterator k = regions.begin(); k != regions.end(); ++k) {
(*k)->set_layering_index (j++);
}
}
-
/** Take the layering indices of each of our regions, compute the layers
* that they should be on, and write the layers back to the regions.
*/
@@ -2400,7 +2403,7 @@ Playlist::relayer ()
notify_layering_changed ();
/* This relayer() may have been called as a result of a region removal, in which
- case we need to setup layering indices so account for the one that has just
+ case we need to setup layering indices to account for the one that has just
gone away.
*/
setup_layering_indices (copy);
@@ -2411,6 +2414,7 @@ Playlist::raise_region (boost::shared_ptr region)
{
set_layer (region, region->layer() + 1.5);
relayer ();
+ check_crossfades (region->range ());
}
void
@@ -2418,6 +2422,7 @@ Playlist::lower_region (boost::shared_ptr region)
{
set_layer (region, region->layer() - 1.5);
relayer ();
+ check_crossfades (region->range ());
}
void
@@ -2425,6 +2430,7 @@ Playlist::raise_region_to_top (boost::shared_ptr region)
{
set_layer (region, DBL_MAX);
relayer ();
+ check_crossfades (region->range ());
}
void
@@ -2432,6 +2438,7 @@ Playlist::lower_region_to_bottom (boost::shared_ptr region)
{
set_layer (region, -0.5);
relayer ();
+ check_crossfades (region->range ());
}
void
@@ -2577,8 +2584,6 @@ Playlist::shuffle (boost::shared_ptr region, int dir)
_shuffling = true;
- Evoral::Range old_range = region->range ();
-
{
RegionLock rlock (const_cast (this));
@@ -2677,12 +2682,6 @@ Playlist::shuffle (boost::shared_ptr region, int dir)
if (moved) {
relayer ();
-
- list > xf;
- xf.push_back (old_range);
- xf.push_back (region->range ());
- coalesce_and_check_crossfades (xf);
-
notify_contents_changed();
}
@@ -3096,6 +3095,9 @@ Playlist::set_orig_track_id (const PBD::ID& id)
_orig_track_id = id;
}
+/** Take a list of ranges, coalesce any that can be coalesced, then call
+ * check_crossfades for each one.
+ */
void
Playlist::coalesce_and_check_crossfades (list > ranges)
{
diff --git a/libs/ardour/plugin_insert.cc b/libs/ardour/plugin_insert.cc
index 796ec9420c..20180b285b 100644
--- a/libs/ardour/plugin_insert.cc
+++ b/libs/ardour/plugin_insert.cc
@@ -138,12 +138,14 @@ PluginInsert::output_streams() const
{
assert (!_plugins.empty());
- if (_plugins.front()->reconfigurable_io()) {
+ PluginInfoPtr info = _plugins.front()->get_info();
+
+ if (info->reconfigurable_io()) {
ChanCount out = _plugins.front()->output_streams ();
// DEBUG_TRACE (DEBUG::Processors, string_compose ("Plugin insert, reconfigur(able) output streams = %1\n", out));
return out;
} else {
- ChanCount out = _plugins.front()->get_info()->n_outputs;
+ ChanCount out = info->n_outputs;
// DEBUG_TRACE (DEBUG::Processors, string_compose ("Plugin insert, static output streams = %1 for %2 plugins\n", out, _plugins.size()));
out.set_audio (out.n_audio() * _plugins.size());
out.set_midi (out.n_midi() * _plugins.size());
@@ -158,11 +160,13 @@ PluginInsert::input_streams() const
ChanCount in;
- if (_plugins.front()->reconfigurable_io()) {
+ PluginInfoPtr info = _plugins.front()->get_info();
+
+ if (info->reconfigurable_io()) {
assert (_plugins.size() == 1);
in = _plugins.front()->input_streams();
} else {
- in = _plugins[0]->get_info()->n_inputs;
+ in = info->n_inputs;
}
DEBUG_TRACE (DEBUG::Processors, string_compose ("Plugin insert, input streams = %1, match using %2\n", in, _match.method));
@@ -712,7 +716,9 @@ PluginInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out)
PluginInsert::Match
PluginInsert::private_can_support_io_configuration (ChanCount const & in, ChanCount& out) const
{
- if (_plugins.front()->reconfigurable_io()) {
+ PluginInfoPtr info = _plugins.front()->get_info();
+
+ if (info->reconfigurable_io()) {
/* Plugin has flexible I/O, so delegate to it */
bool const r = _plugins.front()->can_support_io_configuration (in, out);
if (!r) {
@@ -722,8 +728,8 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & in, ChanCo
return Match (Delegate, 1);
}
- ChanCount inputs = _plugins[0]->get_info()->n_inputs;
- ChanCount outputs = _plugins[0]->get_info()->n_outputs;
+ ChanCount inputs = info->n_inputs;
+ ChanCount outputs = info->n_outputs;
bool no_inputs = true;
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
diff --git a/libs/ardour/quantize.cc b/libs/ardour/quantize.cc
index 7ede60b578..563b7bf4e7 100644
--- a/libs/ardour/quantize.cc
+++ b/libs/ardour/quantize.cc
@@ -40,8 +40,7 @@ using namespace ARDOUR;
* 0.25 = quantize to beats/4, etc.
*/
-Quantize::Quantize (Session& s, QuantizeType /* type */,
- bool snap_start, bool snap_end,
+Quantize::Quantize (Session& s, bool snap_start, bool snap_end,
double start_grid, double end_grid,
float strength, float swing, float threshold)
: session (s)
diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc
index efaa104d35..a4a1584792 100644
--- a/libs/ardour/region.cc
+++ b/libs/ardour/region.cc
@@ -1654,3 +1654,33 @@ Region::set_start_internal (framecnt_t s)
{
_start = s;
}
+
+framepos_t
+Region::earliest_possible_position () const
+{
+ if (_start > _position) {
+ return 0;
+ } else {
+ return _position - _start;
+ }
+}
+
+framecnt_t
+Region::latest_possible_frame () const
+{
+ framecnt_t minlen = max_framecnt;
+
+ for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
+ /* non-audio regions have a length that may vary based on their
+ * position, so we have to pass it in the call.
+ */
+ minlen = min (minlen, (*i)->length (_position));
+ }
+
+ /* the latest possible last frame is determined by the current
+ * position, plus the shortest source extent past _start.
+ */
+
+ return _position + (minlen - _start) - 1;
+}
+
diff --git a/libs/ardour/run-tests.sh b/libs/ardour/run-tests.sh
index 1af623c3f2..1097804994 100755
--- a/libs/ardour/run-tests.sh
+++ b/libs/ardour/run-tests.sh
@@ -16,6 +16,7 @@ libs='libs'
export LD_LIBRARY_PATH=$libs/audiographer:$libs/vamp-sdk:$libs/surfaces:$libs/surfaces/control_protocol:$libs/ardour:$libs/midi++2:$libs/pbd:$libs/rubberband:$libs/soundtouch:$libs/gtkmm2ext:$libs/appleutility:$libs/taglib:$libs/evoral:$libs/evoral/src/libsmf:$libs/timecode:/usr/local/lib:/usr/local/lib64:$LD_LIBRARY_PATH
export ARDOUR_PANNER_PATH=$libs/panners/2in2out:$libs/panners/1in2out:$libs/panners/vbap
+export ARDOUR_SURFACES_PATH=$libs/surfaces/osc:$libs/surfaces/generic_midi:$libs/surfaces/tranzport:$libs/surfaces/powermate:$libs/surfaces/mackie
if [ "$1" == "--debug" ]; then
gdb ./libs/ardour/run-tests
diff --git a/libs/ardour/session_metadata.cc b/libs/ardour/session_metadata.cc
index 00f5d31ed8..e1eb166bb6 100644
--- a/libs/ardour/session_metadata.cc
+++ b/libs/ardour/session_metadata.cc
@@ -182,7 +182,7 @@ SessionMetadata::get_state ()
}
int
-SessionMetadata::set_state (const XMLNode & state, int version_num)
+SessionMetadata::set_state (const XMLNode & state, int /*version_num*/)
{
const XMLNodeList & children = state.children();
string name;
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index 48e7f206e7..2f67915ce5 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -926,8 +926,12 @@ Session::load_state (string snapshot_name)
Stateful::loading_state_version = 1000;
} else {
if (prop->value().find ('.')) {
- /* old school version format - lock at 3000 */
- Stateful::loading_state_version = 3000;
+ /* old school version format */
+ if (prop->value()[0] == '2') {
+ Stateful::loading_state_version = 2000;
+ } else {
+ Stateful::loading_state_version = 3000;
+ }
} else {
Stateful::loading_state_version = atoi (prop->value());
}
diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc
index df3dddbd6d..798ced17b4 100644
--- a/libs/ardour/tempo.cc
+++ b/libs/ardour/tempo.cc
@@ -19,11 +19,10 @@
#include
#include
+#include
#include
-#include
-
#include
#include "pbd/xml++.h"
#include "evoral/types.hpp"
@@ -1195,7 +1194,7 @@ TempoMap::bbt_duration_at (framepos_t pos, const BBT_Time& bbt, int dir)
}
framecnt_t
-TempoMap::bbt_duration_at_unlocked (const BBT_Time& when, const BBT_Time& bbt, int dir)
+TempoMap::bbt_duration_at_unlocked (const BBT_Time& when, const BBT_Time& bbt, int /*dir*/)
{
if (bbt.bars == 0 && bbt.beats == 0 && bbt.ticks == 0) {
return 0;
diff --git a/libs/ardour/test/audio_region_test.cc b/libs/ardour/test/audio_region_test.cc
index 72e886b4e1..cd1986b19b 100644
--- a/libs/ardour/test/audio_region_test.cc
+++ b/libs/ardour/test/audio_region_test.cc
@@ -23,19 +23,10 @@ AudioRegionTest::readTest ()
/* Simple read: 256 frames from start of region, no fades */
- /* gbuf should be ignored; set it to 0 to ensure that it is */
- for (int i = 0; i < N; ++i) {
- gbuf[i] = 0;
- }
-
ar->set_position (P);
ar->set_length (1024);
- for (int i = 0; i < N; ++i) {
- buf[i] = 0;
- }
-
- ar->_read_at (ar->_sources, ar->_length, buf, mbuf, gbuf, P, 256, 0, AudioRegion::ReadOps (0));
+ ar->read_from_sources (ar->_sources, ar->_length, buf, P, 256, 0);
check_staircase (buf, 0, 256);
for (int i = 0; i < N; ++i) {
@@ -43,7 +34,7 @@ AudioRegionTest::readTest ()
}
/* Offset read: 256 frames from 128 frames into the region, no fades */
- ar->_read_at (ar->_sources, ar->_length, buf, mbuf, gbuf, P + 128, 256, 0, AudioRegion::ReadOps (0));
+ ar->read_from_sources (ar->_sources, ar->_length, buf, P + 128, 256, 0);
check_staircase (buf, 128, 256);
/* Simple read with a fade-in: 256 frames from start of region, with fades */
diff --git a/libs/ardour/test/control_surfaces_test.cc b/libs/ardour/test/control_surfaces_test.cc
new file mode 100644
index 0000000000..82127a2524
--- /dev/null
+++ b/libs/ardour/test/control_surfaces_test.cc
@@ -0,0 +1,23 @@
+#include "control_surfaces_test.h"
+#include "ardour/control_protocol_manager.h"
+#include "ardour/session.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION (ControlSurfacesTest);
+
+using namespace std;
+using namespace ARDOUR;
+
+void
+ControlSurfacesTest::instantiateAndTeardownTest ()
+{
+ cout << "HELLO!\n";
+ _session->new_audio_track (1, 2, Normal, 0, 1, "Test");
+
+ ControlProtocolManager& m = ControlProtocolManager::instance ();
+ cout << "CST: Test " << m.control_protocol_info.size() << "\n";
+ for (list::iterator i = m.control_protocol_info.begin(); i != m.control_protocol_info.end(); ++i) {
+ cout << "CST: Test " << (*i)->name << "\n";
+ m.instantiate (**i);
+ m.teardown (**i);
+ }
+}
diff --git a/libs/ardour/test/control_surfaces_test.h b/libs/ardour/test/control_surfaces_test.h
new file mode 100644
index 0000000000..97662c6ea3
--- /dev/null
+++ b/libs/ardour/test/control_surfaces_test.h
@@ -0,0 +1,11 @@
+#include "test_needing_session.h"
+
+class ControlSurfacesTest : public TestNeedingSession
+{
+ CPPUNIT_TEST_SUITE (ControlSurfacesTest);
+ CPPUNIT_TEST (instantiateAndTeardownTest);
+ CPPUNIT_TEST_SUITE_END ();
+
+public:
+ void instantiateAndTeardownTest ();
+};
diff --git a/libs/ardour/test/test_needing_session.cc b/libs/ardour/test/test_needing_session.cc
index e2da42c475..625d5735b2 100644
--- a/libs/ardour/test/test_needing_session.cc
+++ b/libs/ardour/test/test_needing_session.cc
@@ -6,6 +6,8 @@
#include "ardour/audioengine.h"
#include "test_needing_session.h"
+extern void setup_libpbd_enums ();
+
using namespace std;
using namespace ARDOUR;
using namespace PBD;
@@ -57,13 +59,16 @@ TestNeedingSession::setUp ()
init (false, true);
SessionEvent::create_per_thread_pool ("test", 512);
+ setup_libpbd_enums ();
+
test_receiver.listen_to (error);
test_receiver.listen_to (info);
test_receiver.listen_to (fatal);
test_receiver.listen_to (warning);
AudioEngine* engine = new AudioEngine ("test", "");
- MIDI::Manager::create (engine->jack ());
+ init_post_engine ();
+
CPPUNIT_ASSERT (engine->start () == 0);
_session = new Session (*engine, test_session_path, "test_session");
@@ -74,6 +79,7 @@ void
TestNeedingSession::tearDown ()
{
AudioEngine::instance()->remove_session ();
+ AudioEngine::instance()->stop (true);
delete _session;
diff --git a/libs/ardour/wscript b/libs/ardour/wscript
index c493f830e7..8d1c679f0f 100644
--- a/libs/ardour/wscript
+++ b/libs/ardour/wscript
@@ -436,6 +436,7 @@ def build(bld):
test/framepos_minus_beats_test.cc
test/playlist_layering_test.cc
test/playlist_read_test.cc
+ test/control_surfaces_test.cc
test/testrunner.cc
'''.split()
diff --git a/libs/audiographer/tests/type_utils_test.cc b/libs/audiographer/tests/type_utils_test.cc
index af9e923d1b..a2b2c96f11 100644
--- a/libs/audiographer/tests/type_utils_test.cc
+++ b/libs/audiographer/tests/type_utils_test.cc
@@ -38,6 +38,7 @@ class TypeUtilsTest : public CppUnit::TestFixture
void testZeroFillNonPod()
{
+ /* does not compile on OS X Lion
unsigned frames = 10;
NonPodType buf[frames];
TypeUtils::zero_fill (buf, frames);
@@ -45,6 +46,7 @@ class TypeUtilsTest : public CppUnit::TestFixture
for (unsigned i = 0; i < frames; ++i) {
CPPUNIT_ASSERT (zero == buf[i]);
}
+ */
}
void testMoveBackward()
diff --git a/libs/evoral/evoral/ControlList.hpp b/libs/evoral/evoral/ControlList.hpp
index 30b9fca430..c54c231ca7 100644
--- a/libs/evoral/evoral/ControlList.hpp
+++ b/libs/evoral/evoral/ControlList.hpp
@@ -95,6 +95,7 @@ public:
ControlList& operator= (const ControlList&);
bool operator== (const ControlList&);
+ void copy_events (const ControlList&);
virtual void freeze();
virtual void thaw ();
diff --git a/libs/evoral/evoral/Event.hpp b/libs/evoral/evoral/Event.hpp
index da8036c8f6..5c287fd714 100644
--- a/libs/evoral/evoral/Event.hpp
+++ b/libs/evoral/evoral/Event.hpp
@@ -60,7 +60,7 @@ struct Event {
const Event& operator=(const Event& copy);
- void set(uint8_t* buf, uint32_t size, Time t);
+ void set(const uint8_t* buf, uint32_t size, Time t);
inline bool operator==(const Event& other) const {
if (_type != other._type)
diff --git a/libs/evoral/src/ControlList.cpp b/libs/evoral/src/ControlList.cpp
index 9c38f67b29..9a820294ef 100644
--- a/libs/evoral/src/ControlList.cpp
+++ b/libs/evoral/src/ControlList.cpp
@@ -80,9 +80,7 @@ ControlList::ControlList (const ControlList& other)
_search_cache.first = _events.end();
_sort_pending = false;
- for (const_iterator i = other._events.begin(); i != other._events.end(); ++i) {
- _events.push_back (new ControlEvent (**i));
- }
+ copy_events (other);
mark_dirty ();
}
@@ -106,9 +104,7 @@ ControlList::ControlList (const ControlList& other, double start, double end)
boost::shared_ptr section = const_cast(&other)->copy (start, end);
if (!section->empty()) {
- for (iterator i = section->begin(); i != section->end(); ++i) {
- _events.push_back (new ControlEvent ((*i)->when, (*i)->value));
- }
+ copy_events (*(section.get()));
}
mark_dirty ();
@@ -147,23 +143,30 @@ ControlList::operator= (const ControlList& other)
{
if (this != &other) {
- _events.clear ();
-
- for (const_iterator i = other._events.begin(); i != other._events.end(); ++i) {
- _events.push_back (new ControlEvent (**i));
- }
-
_min_yval = other._min_yval;
_max_yval = other._max_yval;
_default_value = other._default_value;
-
- mark_dirty ();
- maybe_signal_changed ();
+
+ copy_events (other);
}
return *this;
}
+void
+ControlList::copy_events (const ControlList& other)
+{
+ {
+ Glib::Mutex::Lock lm (_lock);
+ _events.clear ();
+ for (const_iterator i = other.begin(); i != other.end(); ++i) {
+ _events.push_back (new ControlEvent ((*i)->when, (*i)->value));
+ }
+ mark_dirty ();
+ }
+ maybe_signal_changed ();
+}
+
void
ControlList::create_curve()
{
diff --git a/libs/evoral/src/Event.cpp b/libs/evoral/src/Event.cpp
index d0e0e8ac3a..e315d811e0 100644
--- a/libs/evoral/src/Event.cpp
+++ b/libs/evoral/src/Event.cpp
@@ -118,7 +118,7 @@ Event::operator=(const Event& copy)
template
void
-Event::set(uint8_t* buf, uint32_t size, Timestamp t)
+Event::set (const uint8_t* buf, uint32_t size, Timestamp t)
{
if (_owns_buf) {
if (_size < size) {
@@ -126,7 +126,11 @@ Event::set(uint8_t* buf, uint32_t size, Timestamp t)
}
memcpy (_buf, buf, size);
} else {
- _buf = buf;
+ /* XXX this is really dangerous given the
+ const-ness of buf. The API should really
+ intervene here.
+ */
+ _buf = const_cast (buf);
}
_original_time = t;
diff --git a/libs/gtkmm2ext/cairo_packer.cc b/libs/gtkmm2ext/cairo_packer.cc
index 70f51281dd..6145f7dd50 100644
--- a/libs/gtkmm2ext/cairo_packer.cc
+++ b/libs/gtkmm2ext/cairo_packer.cc
@@ -3,7 +3,7 @@
#include "gtkmm2ext/cairo_packer.h"
void
-CairoPacker::draw_background (Gtk::Widget& w, GdkEventExpose* ev)
+CairoPacker::draw_background (Gtk::Widget& w, GdkEventExpose*)
{
int x, y;
Gtk::Widget* window_parent;
diff --git a/libs/gtkmm2ext/gtk_ui.cc b/libs/gtkmm2ext/gtk_ui.cc
index 255b18b2fb..11b06b78ff 100644
--- a/libs/gtkmm2ext/gtk_ui.cc
+++ b/libs/gtkmm2ext/gtk_ui.cc
@@ -64,6 +64,8 @@ BaseUI::RequestType Gtkmm2ext::AddTimeout = BaseUI::new_request_type();
UI::UI (string namestr, int *argc, char ***argv)
: AbstractUI (namestr)
+ , _receiver (*this)
+
{
theMain = new Main (argc, argv);
@@ -252,10 +254,10 @@ UI::load_rcfile (string path, bool themechange)
void
UI::run (Receiver &old_receiver)
{
- listen_to (error);
- listen_to (info);
- listen_to (warning);
- listen_to (fatal);
+ _receiver.listen_to (error);
+ _receiver.listen_to (info);
+ _receiver.listen_to (warning);
+ _receiver.listen_to (fatal);
/* stop the old receiver (text/console) once we hit the first idle */
@@ -266,7 +268,7 @@ UI::run (Receiver &old_receiver)
theMain->run ();
_active = false;
stopping ();
- hangup ();
+ _receiver.hangup ();
return;
}
@@ -356,7 +358,7 @@ UI::set_tip (Widget *w, const gchar *tip, const gchar *hlp)
if (!abbrev.empty()) {
replace_all (abbrev, "<", "");
replace_all (abbrev, ">", "-");
- msg.append("\n\nKey: ").append (abbrev);
+ msg.append(_("\n\nKey: ")).append (abbrev);
}
}
}
@@ -565,10 +567,15 @@ UI::process_error_message (Transmitter::Channel chn, const char *str)
handle_fatal (str);
} else {
- display_message (prefix, prefix_len, ptag, mtag, str);
-
- if (!errors->is_visible() && chn != Transmitter::Info) {
- show_errors ();
+ if (!ptag || !mtag) {
+ /* oops, message sent before we set up tags - don't crash */
+ cerr << prefix << str << endl;
+ } else {
+ display_message (prefix, prefix_len, ptag, mtag, str);
+
+ if (!errors->is_visible() && chn != Transmitter::Info) {
+ show_errors ();
+ }
}
}
diff --git a/libs/gtkmm2ext/gtkmm2ext/binding_proxy.h b/libs/gtkmm2ext/gtkmm2ext/binding_proxy.h
index 69d1ebdaad..b541582f6f 100644
--- a/libs/gtkmm2ext/gtkmm2ext/binding_proxy.h
+++ b/libs/gtkmm2ext/gtkmm2ext/binding_proxy.h
@@ -24,7 +24,7 @@
#include
#include
#include
-#include
+#include "pbd/signals.h"
namespace PBD {
class Controllable;
@@ -50,7 +50,7 @@ class BindingProxy : public sigc::trackable
boost::shared_ptr controllable;
guint bind_button;
guint bind_statemask;
- boost::signals2::scoped_connection learning_connection;
+ PBD::ScopedConnection learning_connection;
void learning_finished ();
bool prompter_hiding (GdkEventAny *);
};
diff --git a/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h b/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h
index bba3fb6fdf..4bf82fb1aa 100644
--- a/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h
+++ b/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h
@@ -88,8 +88,21 @@ struct UIRequest : public BaseUI::BaseRequestObject {
}
};
-class UI : public Receiver, public AbstractUI
+class UI : public AbstractUI
{
+ private:
+ class MyReceiver : public Receiver {
+ public:
+ MyReceiver (UI& ui) : _ui (ui) {}
+ void receive (Transmitter::Channel chn, const char *msg) {
+ _ui.receive (chn, msg);
+ }
+ private:
+ UI& _ui;
+ };
+
+ MyReceiver _receiver;
+
public:
UI (std::string name, int *argc, char **argv[]);
virtual ~UI ();
@@ -183,6 +196,7 @@ class UI : public Receiver, public AbstractUI
bool color_picked;
void do_request (UIRequest*);
+
};
} /* namespace */
diff --git a/libs/midi++2/ipmidi_port.cc b/libs/midi++2/ipmidi_port.cc
index 50777634f1..7e30752c38 100644
--- a/libs/midi++2/ipmidi_port.cc
+++ b/libs/midi++2/ipmidi_port.cc
@@ -246,11 +246,11 @@ IPMIDIPort::open_sockets (int base_port, const string& ifname)
}
int
-IPMIDIPort::write (byte* msg, size_t msglen, timestamp_t /* ignored */) {
+IPMIDIPort::write (const byte* msg, size_t msglen, timestamp_t /* ignored */) {
if (sockout) {
Glib::Mutex::Lock lm (write_lock);
- if (::sendto (sockout, (char *) msg, msglen, 0, (struct sockaddr *) &addrout, sizeof(struct sockaddr_in)) < 0) {
+ if (::sendto (sockout, (const char *) msg, msglen, 0, (struct sockaddr *) &addrout, sizeof(struct sockaddr_in)) < 0) {
::perror("sendto");
return -1;
}
@@ -260,7 +260,7 @@ IPMIDIPort::write (byte* msg, size_t msglen, timestamp_t /* ignored */) {
}
int
-IPMIDIPort::read (byte* buf, size_t bufsize)
+IPMIDIPort::read (byte* /*buf*/, size_t /*bufsize*/)
{
/* nothing to do here - all handled by parse() */
return 0;
diff --git a/libs/midi++2/jack_midi_port.cc b/libs/midi++2/jack_midi_port.cc
index 729fc789d4..05eebc5aa1 100644
--- a/libs/midi++2/jack_midi_port.cc
+++ b/libs/midi++2/jack_midi_port.cc
@@ -76,7 +76,7 @@ JackMIDIPort::JackMIDIPort (const XMLNode& node, jack_client_t* jack_client)
}
void
-JackMIDIPort::init (string const & name, Flags flags)
+JackMIDIPort::init (const string& /*name*/, Flags /*flags*/)
{
if (!create_port ()) {
_ok = true;
@@ -206,7 +206,7 @@ JackMIDIPort::drain (int check_interval_usecs)
}
int
-JackMIDIPort::write(byte * msg, size_t msglen, timestamp_t timestamp)
+JackMIDIPort::write (const byte * msg, size_t msglen, timestamp_t timestamp)
{
int ret = 0;
diff --git a/libs/midi++2/midi++/ipmidi_port.h b/libs/midi++2/midi++/ipmidi_port.h
index 7df9642321..0441626565 100644
--- a/libs/midi++2/midi++/ipmidi_port.h
+++ b/libs/midi++2/midi++/ipmidi_port.h
@@ -55,7 +55,7 @@ class IPMIDIPort : public Port {
XMLNode& get_state () const;
void set_state (const XMLNode&);
- int write (byte *msg, size_t msglen, timestamp_t timestamp);
+ int write (const byte *msg, size_t msglen, timestamp_t timestamp);
int read (byte *buf, size_t bufsize);
void parse (framecnt_t timestamp);
int selectable () const;
diff --git a/libs/midi++2/midi++/jack_midi_port.h b/libs/midi++2/midi++/jack_midi_port.h
index e381120a99..b8d208c77a 100644
--- a/libs/midi++2/midi++/jack_midi_port.h
+++ b/libs/midi++2/midi++/jack_midi_port.h
@@ -54,7 +54,7 @@ class JackMIDIPort : public Port {
void cycle_end ();
void parse (framecnt_t timestamp);
- int write (byte *msg, size_t msglen, timestamp_t timestamp);
+ int write (const byte *msg, size_t msglen, timestamp_t timestamp);
int read (byte *buf, size_t bufsize);
void drain (int check_interval_usecs);
int selectable () const { return xthread.selectable(); }
diff --git a/libs/midi++2/midi++/port.h b/libs/midi++2/midi++/port.h
index a2315f7284..03abd1a41c 100644
--- a/libs/midi++2/midi++/port.h
+++ b/libs/midi++2/midi++/port.h
@@ -57,7 +57,7 @@ class Port {
// FIXME: make Manager a friend of port so these can be hidden?
/* Only for use by MidiManager. Don't ever call this. */
- virtual void cycle_start (pframes_t nframes) {}
+ virtual void cycle_start (pframes_t) {}
/* Only for use by MidiManager. Don't ever call this. */
virtual void cycle_end () {}
@@ -67,7 +67,7 @@ class Port {
* @param timestamp Time stamp in frames of this message (relative to cycle start)
* @return number of bytes successfully written
*/
- virtual int write (byte *msg, size_t msglen, timestamp_t timestamp) = 0;
+ virtual int write (const byte *msg, size_t msglen, timestamp_t timestamp) = 0;
/** Read raw bytes from a port.
* @param buf memory to store read data in
@@ -82,7 +82,7 @@ class Port {
* executes any part of a JACK process callback (will
* simply return immediately in that situation).
*/
- virtual void drain (int check_interval_usecs) {}
+ virtual void drain (int /* check_interval_usecs */) {}
/** Write a message to port.
* @return true on success.
diff --git a/libs/pbd/base_ui.cc b/libs/pbd/base_ui.cc
index 6c21549e8b..14a3ef644d 100644
--- a/libs/pbd/base_ui.cc
+++ b/libs/pbd/base_ui.cc
@@ -76,9 +76,19 @@ BaseUI::main_thread ()
DEBUG_TRACE (DEBUG::EventLoop, string_compose ("%1: event loop running in thread %2\n", name(), pthread_self()));
set_event_loop_for_thread (this);
thread_init ();
+ _main_loop->get_context()->signal_idle().connect (sigc::mem_fun (*this, &BaseUI::signal_running));
_main_loop->run ();
}
+bool
+BaseUI::signal_running ()
+{
+ Glib::Mutex::Lock lm (_run_lock);
+ _running.signal ();
+
+ return false; // don't call it again
+}
+
void
BaseUI::run ()
{
@@ -91,13 +101,15 @@ BaseUI::run ()
/* glibmm hack - drop the refptr to the IOSource now before it can hurt */
request_channel.drop_ios ();
+ Glib::Mutex::Lock lm (_run_lock);
run_loop_thread = Thread::create (mem_fun (*this, &BaseUI::main_thread), true);
+ _running.wait (_run_lock);
}
void
BaseUI::quit ()
{
- if (_main_loop->is_running()) {
+ if (_main_loop && _main_loop->is_running()) {
_main_loop->quit ();
run_loop_thread->join ();
}
diff --git a/libs/pbd/convert.cc b/libs/pbd/convert.cc
index 07407e2fad..1787d3b70d 100644
--- a/libs/pbd/convert.cc
+++ b/libs/pbd/convert.cc
@@ -28,6 +28,8 @@
#endif
#include
+#include
+
#include "pbd/convert.h"
#include "i18n.h"
@@ -264,15 +266,15 @@ string_is_affirmative (const std::string& str)
return false;
}
- /* the use of g_strncasecmp() is solely to get around issues with
+ /* the use of g_ascii_strncasecmp() is solely to get around issues with
* charsets posed by trying to use C++ for the same
* comparison. switching a std::string to its lower- or upper-case
* version has several issues, but handled by default
* in the way we desire when doing it in C.
*/
- return str == "1" || str == "y" || str == "Y" || (!g_strncasecmp(str.c_str(), "yes", str.length())) ||
- (!g_strncasecmp(str.c_str(), "true", str.length()));
+ return str == "1" || str == "y" || str == "Y" || (!g_ascii_strncasecmp(str.c_str(), "yes", str.length())) ||
+ (!g_ascii_strncasecmp(str.c_str(), "true", str.length()));
}
/** A wrapper for dgettext that takes a msgid of the form Context|Text.
diff --git a/libs/pbd/crossthread.cc b/libs/pbd/crossthread.cc
index 0fbd1034bd..2ffede5163 100644
--- a/libs/pbd/crossthread.cc
+++ b/libs/pbd/crossthread.cc
@@ -104,7 +104,7 @@ CrossThreadChannel::drain (int fd)
{
/* drain selectable fd */
char buf[64];
- while (::read (fd, buf, sizeof (buf)) > 0) {}
+ while (::read (fd, buf, sizeof (buf)) > 0) {};
}
int
diff --git a/libs/pbd/pbd/base_ui.h b/libs/pbd/pbd/base_ui.h
index 414c9970d9..65a9f27b49 100644
--- a/libs/pbd/pbd/base_ui.h
+++ b/libs/pbd/pbd/base_ui.h
@@ -41,7 +41,7 @@
*/
-class BaseUI : virtual public sigc::trackable, public PBD::EventLoop
+class BaseUI : public sigc::trackable, public PBD::EventLoop
{
public:
BaseUI (const std::string& name);
@@ -76,6 +76,14 @@ class BaseUI : virtual public sigc::trackable, public PBD::EventLoop
Glib::RefPtr _main_loop;
Glib::Thread* run_loop_thread;
+ Glib::Mutex _run_lock;
+ Glib::Cond _running;
+
+ /* this signals _running from within the event loop,
+ from an idle callback
+ */
+
+ bool signal_running ();
/** Derived UI objects can implement thread_init()
* which will be called by the event loop thread
diff --git a/libs/pbd/pbd/receiver.h b/libs/pbd/pbd/receiver.h
index 5e32c7d67f..32fb84fa38 100644
--- a/libs/pbd/pbd/receiver.h
+++ b/libs/pbd/pbd/receiver.h
@@ -28,7 +28,7 @@
class strstream;
-class Receiver : virtual public sigc::trackable
+class Receiver : public sigc::trackable
{
public:
Receiver ();
diff --git a/libs/pbd/pbd/semaphore.h b/libs/pbd/pbd/semaphore.h
index f1b07ea4f5..e54063a15a 100644
--- a/libs/pbd/pbd/semaphore.h
+++ b/libs/pbd/pbd/semaphore.h
@@ -81,7 +81,7 @@ private:
inline
Semaphore::Semaphore(unsigned initial)
{
- if (semaphore_create(mach_task_self(), &sem->sem, SYNC_POLICY_FIFO, 0)) {
+ if (semaphore_create(mach_task_self(), &_sem, SYNC_POLICY_FIFO, initial)) {
throw failed_constructor();
}
}
@@ -148,7 +148,7 @@ Semaphore::wait()
inline bool
Semaphore::try_wait()
{
- return WaitForSingleObject(sem->sem, 0) == WAIT_OBJECT_0;
+ return WaitForSingleObject(_sem, 0) == WAIT_OBJECT_0;
}
#else /* !defined(__APPLE__) && !defined(_WIN32) */
diff --git a/libs/pbd/pbd/signal.h.py b/libs/pbd/pbd/signal.h.py
new file mode 100644
index 0000000000..70a1a2d88c
--- /dev/null
+++ b/libs/pbd/pbd/signal.h.py
@@ -0,0 +1,214 @@
+#!/usr/bin/python
+
+import sys
+
+if len(sys.argv) < 2:
+ print 'Syntax: %s ' % sys.argv[0]
+ sys.exit(1)
+
+f = open(sys.argv[1], 'w')
+
+print >>f,"""
+/** THIS FILE IS AUTOGENERATED: DO NOT EDIT.
+ *
+ * This file is generated by signals.h.py.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include "pbd/stacktrace.h"
+
+namespace PBD {
+
+class Connection;
+
+class SignalBase : public boost::enable_shared_from_this
+{
+public:
+ virtual ~SignalBase () {}
+ virtual void disconnect (boost::shared_ptr) = 0;
+
+protected:
+ boost::mutex _mutex;
+};
+
+class Connection : public boost::enable_shared_from_this
+{
+public:
+ Connection (boost::shared_ptr b) : _signal (b) {}
+
+ void disconnect ()
+ {
+ if (_signal) {
+ _signal->disconnect (shared_from_this ());
+ }
+ }
+
+private:
+ boost::shared_ptr _signal;
+};
+
+template
+class OptionalLastValue
+{
+public:
+ typedef boost::optional result_type;
+
+ template
+ result_type operator() (Iter first, Iter last) const {
+ result_type r;
+ while (first != last) {
+ r = *first;
+ ++first;
+ }
+
+ return r;
+ }
+};
+"""
+
+def comma_separated(n, prefix = ""):
+ r = ""
+ for i in range(0, len(n)):
+ if i > 0:
+ r += ", "
+ r += "%s%s" % (prefix, n[i])
+ return r
+
+def simple_signal(f, n, v):
+
+ An = []
+ for i in range(0, n):
+ An.append("A%d" % (i + 1))
+
+ if v:
+ print >>f,"template <%s>" % comma_separated(An, "typename ")
+ print >>f,"class SimpleSignal%d<%s> : public SignalBase" % (n, comma_separated(["void"] + An))
+ else:
+ print >>f,"template <%s>" % comma_separated(["R"] + An + ["C = OptionalLastValue "], "typename ")
+ print >>f,"class SimpleSignal%d : public SignalBase" % n
+
+ print >>f,"{"
+ print >>f,"public:"
+ print >>f,""
+ if v:
+ print >>f,"\ttypedef boost::function slot_function_type;" % comma_separated(An)
+ print >>f,"\ttypedef void result_type;"
+ else:
+ print >>f,"\ttypedef boost::function slot_function_type;" % comma_separated(An)
+ print >>f,"\ttypedef boost::optional result_type;"
+
+ print >>f,"private:"
+ print >>f,""
+
+ print >>f,"""
+ typedef std::map