summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/SConscript2
-rw-r--r--gtk2_ardour/ardour2_ui_default.conf6
-rw-r--r--gtk2_ardour/audio_region_view.cc5
-rw-r--r--gtk2_ardour/audio_time_axis.cc29
-rw-r--r--gtk2_ardour/audio_time_axis.h1
-rw-r--r--gtk2_ardour/automation_line.cc303
-rw-r--r--gtk2_ardour/automation_line.h51
-rw-r--r--gtk2_ardour/automation_time_axis.cc71
-rw-r--r--gtk2_ardour/automation_time_axis.h9
-rw-r--r--gtk2_ardour/control_point.cc202
-rw-r--r--gtk2_ardour/control_point.h102
-rw-r--r--gtk2_ardour/diamond.cc35
-rw-r--r--gtk2_ardour/diamond.h38
-rw-r--r--gtk2_ardour/editor.cc6
-rw-r--r--gtk2_ardour/editor_canvas_events.cc3
-rw-r--r--gtk2_ardour/editor_mouse.cc39
-rw-r--r--gtk2_ardour/editor_selection.cc1
-rw-r--r--gtk2_ardour/midi_region_view.cc83
-rw-r--r--gtk2_ardour/midi_region_view.h1
-rw-r--r--gtk2_ardour/midi_streamview.h4
-rw-r--r--gtk2_ardour/midi_time_axis.cc45
-rw-r--r--gtk2_ardour/midi_time_axis.h13
-rw-r--r--gtk2_ardour/route_time_axis.cc22
-rw-r--r--gtk2_ardour/route_time_axis.h3
-rw-r--r--gtk2_ardour/streamview.h3
-rw-r--r--libs/ardour/ardour/automation_event.h10
-rw-r--r--libs/ardour/ardour/midi_track.h6
-rw-r--r--libs/ardour/ardour/parameter.h22
-rw-r--r--libs/ardour/ardour/types.h5
-rw-r--r--libs/ardour/automatable.cc1
-rw-r--r--libs/ardour/automation_control.cc1
-rw-r--r--libs/ardour/automation_event.cc34
-rw-r--r--libs/ardour/enums.cc12
-rw-r--r--libs/ardour/midi_track.cc18
34 files changed, 819 insertions, 367 deletions
diff --git a/gtk2_ardour/SConscript b/gtk2_ardour/SConscript
index cf8b8dbfaa..605e7d132b 100644
--- a/gtk2_ardour/SConscript
+++ b/gtk2_ardour/SConscript
@@ -96,6 +96,7 @@ ardour_ui_options.cc
audio_clock.cc
audio_time_axis.cc
audio_region_editor.cc
+control_point.cc
automation_line.cc
automation_time_axis.cc
automation_controller.cc
@@ -107,6 +108,7 @@ simpleline.cc
canvas-simplerect.c
simplerect.cc
canvas-waveview.c
+diamond.cc
crossfade_edit.cc
crossfade_view.cc
curvetest.cc
diff --git a/gtk2_ardour/ardour2_ui_default.conf b/gtk2_ardour/ardour2_ui_default.conf
index d2272c7ac1..893c4ba6cd 100644
--- a/gtk2_ardour/ardour2_ui_default.conf
+++ b/gtk2_ardour/ardour2_ui_default.conf
@@ -13,11 +13,11 @@
<Option name="time-stretch-outline" value="63636396"/>
<Option name="automation line" value="44bc59ff"/>
<Option name="processor automation line" value="7aa3f9ff"/>
- <Option name="control point fill" value="000000ff"/>
- <Option name="control point outline" value="000000ff"/>
+ <Option name="control point fill" value="ffffff66"/>
+ <Option name="control point outline" value="ffffffaa"/>
<Option name="entered control point outline" value="ff0000ee"/>
<Option name="entered control point selected" value="ff3535ff"/>
- <Option name="entered control point" value="000000cc"/>
+ <Option name="entered control point" value="ffffffaa"/>
<Option name="control point selected" value="00ff00ff"/>
<Option name="control point" value="ff0000ff"/>
<Option name="automation track fill" value="a0a0ce68"/>
diff --git a/gtk2_ardour/audio_region_view.cc b/gtk2_ardour/audio_region_view.cc
index f3a8819cb8..dc6de8d0f6 100644
--- a/gtk2_ardour/audio_region_view.cc
+++ b/gtk2_ardour/audio_region_view.cc
@@ -40,6 +40,7 @@
#include "public_editor.h"
#include "audio_region_editor.h"
#include "region_gain_line.h"
+#include "control_point.h"
#include "ghostregion.h"
#include "audio_time_axis.h"
#include "utils.h"
@@ -961,8 +962,8 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev)
void
AudioRegionView::remove_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev)
{
- ControlPoint *cp = reinterpret_cast<ControlPoint *> (item->get_data ("control_point"));
- audio_region()->envelope()->erase (cp->model);
+ ControlPoint *cp = reinterpret_cast<ControlPoint *> (item->get_data ("control_point"));
+ audio_region()->envelope()->erase (cp->model());
}
void
diff --git a/gtk2_ardour/audio_time_axis.cc b/gtk2_ardour/audio_time_axis.cc
index 73500f3ea1..db88982089 100644
--- a/gtk2_ardour/audio_time_axis.cc
+++ b/gtk2_ardour/audio_time_axis.cc
@@ -218,6 +218,35 @@ AudioTimeAxisView::append_extra_display_menu_items ()
items.push_back (MenuElem (_("Layers"), *layers_menu));
}
+
+Gtk::Menu*
+AudioTimeAxisView::build_mode_menu()
+{
+ using namespace Menu_Helpers;
+
+ Menu* mode_menu = manage (new Menu);
+ MenuList& items = mode_menu->items();
+ mode_menu->set_name ("ArdourContextMenu");
+
+ RadioMenuItem::Group mode_group;
+ items.push_back (RadioMenuElem (mode_group, _("Normal"),
+ bind (mem_fun (*this, &AudioTimeAxisView::set_track_mode), ARDOUR::Normal)));
+ normal_track_mode_item = dynamic_cast<RadioMenuItem*>(&items.back());
+ items.push_back (RadioMenuElem (mode_group, _("Tape"),
+ bind (mem_fun (*this, &AudioTimeAxisView::set_track_mode), ARDOUR::Destructive)));
+ destructive_track_mode_item = dynamic_cast<RadioMenuItem*>(&items.back());
+
+ switch (track()->mode()) {
+ case ARDOUR::Destructive:
+ destructive_track_mode_item->set_active ();
+ break;
+ case ARDOUR::Normal:
+ normal_track_mode_item->set_active ();
+ break;
+ }
+
+ return mode_menu;
+}
void
AudioTimeAxisView::toggle_waveforms ()
diff --git a/gtk2_ardour/audio_time_axis.h b/gtk2_ardour/audio_time_axis.h
index b0183e5e19..822fbcadf0 100644
--- a/gtk2_ardour/audio_time_axis.h
+++ b/gtk2_ardour/audio_time_axis.h
@@ -91,6 +91,7 @@ class AudioTimeAxisView : public RouteTimeAxisView
void route_active_changed ();
void append_extra_display_menu_items ();
+ Gtk::Menu* build_mode_menu();
void toggle_show_waveforms ();
void set_waveform_shape (WaveformShape);
diff --git a/gtk2_ardour/automation_line.cc b/gtk2_ardour/automation_line.cc
index f396a92d82..d9d1b827f9 100644
--- a/gtk2_ardour/automation_line.cc
+++ b/gtk2_ardour/automation_line.cc
@@ -32,6 +32,7 @@
#include "simplerect.h"
#include "automation_line.h"
+#include "control_point.h"
#include "rgb_macros.h"
#include "ardour_ui.h"
#include "public_editor.h"
@@ -54,178 +55,13 @@ using namespace PBD;
using namespace Editing;
using namespace Gnome; // for Canvas
-ControlPoint::ControlPoint (AutomationLine& al)
- : line (al)
-{
- model = al.the_list()->end();
- view_index = 0;
- can_slide = true;
- _x = 0;
- _y = 0;
- _shape = Full;
- _size = 4.0;
- selected = false;
-
- item = new Canvas::SimpleRect (line.canvas_group());
- item->property_draw() = true;
- item->property_fill() = false;
- item->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_ControlPointFill.get();
- item->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_ControlPointOutline.get();
- item->property_outline_pixels() = 1;
- item->set_data ("control_point", this);
- item->signal_event().connect (mem_fun (this, &ControlPoint::event_handler));
-
- hide ();
- set_visible (false);
-}
-
-ControlPoint::ControlPoint (const ControlPoint& other, bool dummy_arg_to_force_special_copy_constructor)
- : line (other.line)
-{
- if (&other == this) {
- return;
- }
-
- model = other.model;
- view_index = other.view_index;
- can_slide = other.can_slide;
- _x = other._x;
- _y = other._y;
- _shape = other._shape;
- _size = other._size;
- selected = false;
-
- item = new Canvas::SimpleRect (line.canvas_group());
- item->property_fill() = false;
- item->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_EnteredControlPointOutline.get();
- item->property_outline_pixels() = 1;
-
- /* NOTE: no event handling in copied ControlPoints */
-
- hide ();
- set_visible (false);
-}
-
-ControlPoint::~ControlPoint ()
-{
- delete item;
-}
-
-bool
-ControlPoint::event_handler (GdkEvent* event)
-{
- return PublicEditor::instance().canvas_control_point_event (event, item, this);
-}
-
-void
-ControlPoint::hide ()
-{
- item->hide();
-}
-
-void
-ControlPoint::show()
-{
- item->show();
-}
-
-void
-ControlPoint::set_visible (bool yn)
-{
- item->property_draw() = (gboolean) yn;
-}
-
-void
-ControlPoint::reset (double x, double y, AutomationList::iterator mi, uint32_t vi, ShapeType shape)
-{
- model = mi;
- view_index = vi;
- move_to (x, y, shape);
-}
-
-void
-ControlPoint::show_color (bool entered, bool hide_too)
-{
- if (entered) {
- if (selected) {
- item->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_EnteredControlPointSelected.get();
- set_visible(true);
- } else {
- item->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_EnteredControlPoint.get();
- if (hide_too) {
- set_visible(false);
- }
- }
-
- } else {
- if (selected) {
- item->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_ControlPointSelected.get();
- set_visible(true);
- } else {
- item->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_ControlPoint.get();
- if (hide_too) {
- set_visible(false);
- }
- }
- }
-}
-
-void
-ControlPoint::set_size (double sz)
-{
- _size = sz;
-
-#if 0
- if (_size > 6.0) {
- item->property_fill() = (gboolean) TRUE;
- } else {
- item->property_fill() = (gboolean) FALSE;
- }
-#endif
-
- move_to (_x, _y, _shape);
-}
-
-void
-ControlPoint::move_to (double x, double y, ShapeType shape)
-{
- double x1 = 0;
- double x2 = 0;
- double half_size = rint(_size/2.0);
-
- switch (shape) {
- case Full:
- x1 = x - half_size;
- x2 = x + half_size;
- break;
- case Start:
- x1 = x;
- x2 = x + half_size;
- break;
- case End:
- x1 = x - half_size;
- x2 = x;
- break;
- }
-
- item->property_x1() = x1;
- item->property_x2() = x2;
- item->property_y1() = y - half_size;
- item->property_y2() = y + half_size;
-
- _x = x;
- _y = y;
- _shape = shape;
-}
-
-/*****/
-
AutomationLine::AutomationLine (const string & name, TimeAxisView& tv, ArdourCanvas::Group& parent, boost::shared_ptr<AutomationList> al)
: trackview (tv),
_name (name),
alist (al),
_parent_group (parent)
{
+ _interpolation = al->interpolation();
points_visible = false;
update_pending = false;
_vc_uses_gain_mapping = false;
@@ -251,6 +87,8 @@ AutomationLine::AutomationLine (const string & name, TimeAxisView& tv, ArdourCan
if (alist->parameter().type() == GainAutomation)
set_verbose_cursor_uses_gain_mapping (true);
+
+ set_interpolation(alist->interpolation());
}
AutomationLine::~AutomationLine ()
@@ -277,7 +115,8 @@ AutomationLine::queue_reset ()
void
AutomationLine::show ()
{
- line->show();
+ if (_interpolation != AutomationList::Discrete)
+ line->show();
if (points_visible) {
for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
@@ -301,6 +140,11 @@ AutomationLine::hide ()
double
AutomationLine::control_point_box_size ()
{
+ if (_interpolation == AutomationList::Discrete) {
+ return max((_height*4.0) / (double)(alist->parameter().max() - alist->parameter().min()),
+ 4.0);
+ }
+
if (_height > TimeAxisView::hLarger) {
return 8.0;
} else if (_height > (guint32) TimeAxisView::hNormal) {
@@ -380,7 +224,7 @@ AutomationLine::modify_view_point (ControlPoint& cp, double x, double y, bool wi
y = min (1.0, y);
y = _y_position + _height - (y * _height);
- if (cp.can_slide) {
+ if (cp.can_slide()) {
/* x-coord cannot move beyond adjacent points or the start/end, and is
already in frames. it needs to be converted to canvas units.
@@ -393,8 +237,8 @@ AutomationLine::modify_view_point (ControlPoint& cp, double x, double y, bool wi
ControlPoint *before;
ControlPoint *after;
- if (cp.view_index) {
- before = nth (cp.view_index - 1);
+ if (cp.view_index()) {
+ before = nth (cp.view_index() - 1);
x = max (x, before->get_x()+1.0);
} else {
before = &cp;
@@ -402,9 +246,9 @@ AutomationLine::modify_view_point (ControlPoint& cp, double x, double y, bool wi
if (!with_push) {
- if (cp.view_index < control_points.size() - 1) {
+ if (cp.view_index() < control_points.size() - 1) {
- after = nth (cp.view_index + 1);
+ after = nth (cp.view_index() + 1);
/*if it is a "spike" leave the x alone */
@@ -424,10 +268,10 @@ AutomationLine::modify_view_point (ControlPoint& cp, double x, double y, bool wi
/* find the first point that can't move */
- for (uint32_t n = cp.view_index + 1; (after = nth (n)) != 0; ++n) {
- if (!after->can_slide) {
+ for (uint32_t n = cp.view_index() + 1; (after = nth (n)) != 0; ++n) {
+ if (!after->can_slide()) {
x_limit = after->get_x() - 1.0;
- last_movable = after->view_index;
+ last_movable = after->view_index();
break;
}
}
@@ -439,7 +283,7 @@ AutomationLine::modify_view_point (ControlPoint& cp, double x, double y, bool wi
/* leave the x-coordinate alone */
- x = trackview.editor.frame_to_unit ((*cp.model)->when);
+ x = trackview.editor.frame_to_unit ((*cp.model())->when);
}
@@ -462,11 +306,11 @@ AutomationLine::modify_view_point (ControlPoint& cp, double x, double y, bool wi
/* now move all subsequent control points, to reflect the motion.
*/
- for (uint32_t i = cp.view_index + 1; i < limit; ++i) {
+ for (uint32_t i = cp.view_index() + 1; i < limit; ++i) {
ControlPoint *p = nth (i);
double new_x;
- if (p->can_slide) {
+ if (p->can_slide()) {
new_x = min (p->get_x() + delta, x_limit);
p->move_to (new_x, p->get_y(), ControlPoint::Full);
reset_line_coords (*p);
@@ -478,9 +322,9 @@ AutomationLine::modify_view_point (ControlPoint& cp, double x, double y, bool wi
void
AutomationLine::reset_line_coords (ControlPoint& cp)
{
- if (cp.view_index < line_points.size()) {
- line_points[cp.view_index].set_x (cp.get_x());
- line_points[cp.view_index].set_y (cp.get_y());
+ if (cp.view_index() < line_points.size()) {
+ line_points[cp.view_index()].set_x (cp.get_x());
+ line_points[cp.view_index()].set_y (cp.get_y());
}
}
@@ -511,8 +355,8 @@ AutomationLine::model_representation (ControlPoint& cp, ModelRepresentation& mr)
/* if xval has not changed, set it directly from the model to avoid rounding errors */
- if (mr.xval == trackview.editor.frame_to_unit((*cp.model)->when)) {
- mr.xval = (nframes_t) (*cp.model)->when;
+ if (mr.xval == trackview.editor.frame_to_unit((*cp.model())->when)) {
+ mr.xval = (nframes_t) (*cp.model())->when;
} else {
mr.xval = trackview.editor.unit_to_frame (mr.xval);
}
@@ -526,8 +370,8 @@ AutomationLine::model_representation (ControlPoint& cp, ModelRepresentation& mr)
/* part 2: find out where the model point is now
*/
- mr.xpos = (nframes_t) (*cp.model)->when;
- mr.ypos = (*cp.model)->value;
+ mr.xpos = (nframes_t) (*cp.model())->when;
+ mr.ypos = (*cp.model())->value;
/* part 3: get the position of the visual control
points before and after us.
@@ -536,31 +380,31 @@ AutomationLine::model_representation (ControlPoint& cp, ModelRepresentation& mr)
ControlPoint* before;
ControlPoint* after;
- if (cp.view_index) {
- before = nth (cp.view_index - 1);
+ if (cp.view_index()) {
+ before = nth (cp.view_index() - 1);
} else {
before = 0;
}
- after = nth (cp.view_index + 1);
+ after = nth (cp.view_index() + 1);
if (before) {
- mr.xmin = (nframes_t) (*before->model)->when;
- mr.ymin = (*before->model)->value;
- mr.start = before->model;
+ mr.xmin = (nframes_t) (*before->model())->when;
+ mr.ymin = (*before->model())->value;
+ mr.start = before->model();
++mr.start;
} else {
mr.xmin = mr.xpos;
mr.ymin = mr.ypos;
- mr.start = cp.model;
+ mr.start = cp.model();
}
if (after) {
- mr.end = after->model;
+ mr.end = after->model();
} else {
mr.xmax = mr.xpos;
mr.ymax = mr.ypos;
- mr.end = cp.model;
+ mr.end = cp.model();
++mr.end;
}
}
@@ -678,21 +522,21 @@ AutomationLine::determine_visible_control_points (ALPoints& points)
if (!terminal_points_can_slide) {
if (pi == 0) {
- control_points[view_index]->can_slide = false;
+ control_points[view_index]->set_can_slide(false);
if (tx == 0) {
shape = ControlPoint::Start;
} else {
shape = ControlPoint::Full;
}
} else if (pi == npoints - 1) {
- control_points[view_index]->can_slide = false;
+ control_points[view_index]->set_can_slide(false);
shape = ControlPoint::End;
} else {
- control_points[view_index]->can_slide = true;
+ control_points[view_index]->set_can_slide(true);
shape = ControlPoint::Full;
}
} else {
- control_points[view_index]->can_slide = true;
+ control_points[view_index]->set_can_slide(true);
shape = ControlPoint::Full;
}
@@ -727,7 +571,7 @@ AutomationLine::determine_visible_control_points (ALPoints& points)
}
if (!terminal_points_can_slide) {
- control_points.back()->can_slide = false;
+ control_points.back()->set_can_slide(false);
}
delete [] slope;
@@ -753,9 +597,8 @@ AutomationLine::determine_visible_control_points (ALPoints& points)
line->property_points() = line_points;
- if (_visible) {
- line->show ();
- }
+ if (_visible && _interpolation != AutomationList::Discrete)
+ line->show();
}
@@ -916,7 +759,7 @@ AutomationLine::sync_model_with_view_point (ControlPoint& cp, bool did_push, int
/* change all points before the primary point */
- for (AutomationList::iterator i = mr.start; i != cp.model; ++i) {
+ for (AutomationList::iterator i = mr.start; i != cp.model(); ++i) {
double fract = ((*i)->when - mr.xmin) / (mr.xpos - mr.xmin);
double y_delta = ydelta * fract;
@@ -932,12 +775,12 @@ AutomationLine::sync_model_with_view_point (ControlPoint& cp, bool did_push, int
/* change the primary point */
update_pending = true;
- alist->modify (cp.model, mr.xval, mr.yval);
+ alist->modify (cp.model(), mr.xval, mr.yval);
/* change later points */
- AutomationList::iterator i = cp.model;
+ AutomationList::iterator i = cp.model();
++i;
@@ -982,12 +825,12 @@ AutomationLine::control_points_adjacent (double xval, uint32_t & before, uint32_
if (!bcp || (*i)->get_x() > bcp->get_x()) {
bcp = *i;
- before = bcp->view_index;
+ before = bcp->view_index();
}
} else if ((*i)->get_x() > unit_xval) {
acp = *i;
- after = acp->view_index;
+ after = acp->view_index();
break;
}
}
@@ -1067,7 +910,7 @@ AutomationLine::get_selectables (nframes_t& start, nframes_t& end,
for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
- nframes_t when = (nframes_t) (*(*i)->model)->when;
+ nframes_t when = (nframes_t) (*(*i)->model())->when;
if (when >= start && when <= end) {
@@ -1111,7 +954,7 @@ AutomationLine::set_selected_points (PointSelection& points)
double bot;
for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
- (*i)->selected = false;
+ (*i)->set_selected(false);
}
if (points.empty()) {
@@ -1140,7 +983,7 @@ AutomationLine::set_selected_points (PointSelection& points)
if ((*i)->get_y() >= bot && (*i)->get_y() <= top) {
- (*i)->selected = true;
+ (*i)->set_selected(true);
}
}
@@ -1168,7 +1011,7 @@ AutomationLine::show_selection ()
for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
- (*i)->selected = false;
+ (*i)->set_selected(false);
for (list<AudioRange>::iterator r = time.begin(); r != time.end(); ++r) {
double rstart, rend;
@@ -1177,7 +1020,7 @@ AutomationLine::show_selection ()
rend = trackview.editor.frame_to_unit ((*r).end);
if ((*i)->get_x() >= rstart && (*i)->get_x() <= rend) {
- (*i)->selected = true;
+ (*i)->set_selected(true);
break;
}
}
@@ -1267,6 +1110,7 @@ AutomationLine::show_all_control_points ()
points_visible = true;
for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
+ (*i)->show_color((_interpolation != AutomationList::Discrete), false);
(*i)->show ();
(*i)->set_visible (true);
}
@@ -1275,14 +1119,32 @@ AutomationLine::show_all_control_points ()
void
AutomationLine::hide_all_but_selected_control_points ()
{
+ if (alist->interpolation() == AutomationList::Discrete)
+ return;
+
points_visible = false;
for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
- if (!(*i)->selected) {
+ if (!(*i)->selected()) {
(*i)->set_visible (false);
}
}
}
+
+void
+AutomationLine::track_entered()
+{
+ if (alist->interpolation() != AutomationList::Discrete)
+ show_all_control_points();
+}
+
+void
+AutomationLine::track_exited()
+{
+ if (alist->interpolation() != AutomationList::Discrete) {
+ hide_all_but_selected_control_points();
+ }
+}
XMLNode &
AutomationLine::get_state (void)
@@ -1330,3 +1192,18 @@ AutomationLine::model_to_view_y (double& y)
}
}
+
+void
+AutomationLine::set_interpolation(AutomationList::InterpolationStyle style)
+{
+ _interpolation = style;
+
+ if (style == AutomationList::Discrete) {
+ show_all_control_points();
+ line->hide();
+ } else {
+ hide_all_but_selected_control_points();
+ line->show();
+ }
+}
+
diff --git a/gtk2_ardour/automation_line.h b/gtk2_ardour/automation_line.h
index 3f01ae6cf9..6ce548e55d 100644
--- a/gtk2_ardour/automation_line.h
+++ b/gtk2_ardour/automation_line.h
@@ -53,48 +53,6 @@ namespace Gnome {
}
}
-class ControlPoint
-{
- public:
- ControlPoint (AutomationLine& al);
- ControlPoint (const ControlPoint&, bool dummy_arg_to_force_special_copy_constructor);
- virtual ~ControlPoint ();
-
- enum ShapeType {
- Full,
- Start,
- End
- };
-
- void move_to (double x, double y, ShapeType);
- void reset (double x, double y, ARDOUR::AutomationList::iterator, uint32_t, ShapeType);
- double get_x() const { return _x; }
- double get_y() const { return _y; }
-
- void hide ();
- void show ();
- void show_color (bool entered, bool hide_too);
-
- void set_size (double);
- void set_visible (bool);
-
- ArdourCanvas::SimpleRect* item;
- AutomationLine& line;
- uint32_t view_index;
- ARDOUR::AutomationList::iterator model;
- bool can_slide;
- bool selected;
-
- protected:
- virtual bool event_handler (GdkEvent*);
-
- private:
- double _x;
- double _y;
- double _size;
- ShapeType _shape;
-};
-
class AutomationLine : public sigc::trackable, public PBD::StatefulThingWithGoingAway
{
public:
@@ -129,9 +87,11 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulThingWithGoin
guint32 height() const { return _height; }
guint32 y_position() const { return _y_position; }
- void set_line_color (uint32_t);
+ void set_line_color (uint32_t);
uint32_t get_line_color() const { return _line_color; }
+ void set_interpolation(ARDOUR::AutomationList::InterpolationStyle style);
+
void show ();
void hide ();
void set_y_position_and_height (uint32_t, uint32_t);
@@ -155,6 +115,9 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulThingWithGoin
void show_all_control_points ();
void hide_all_but_selected_control_points ();
+ void track_entered();
+ void track_exited();
+
bool is_last_point (ControlPoint &);
bool is_first_point (ControlPoint &);
@@ -215,6 +178,8 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulThingWithGoin
uint32_t line_drag_cp2;
int64_t drag_x;
int64_t drag_distance;
+
+ ARDOUR::AutomationList::InterpolationStyle _interpolation;
void modify_view_point(ControlPoint&, double, double, bool with_push);
void reset_line_coords (ControlPoint&);
diff --git a/gtk2_ardour/automation_time_axis.cc b/gtk2_ardour/automation_time_axis.cc
index 5c5cd53dec..f14e70b52e 100644
--- a/gtk2_ardour/automation_time_axis.cc
+++ b/gtk2_ardour/automation_time_axis.cc
@@ -77,6 +77,9 @@ AutomationTimeAxisView::AutomationTimeAxisView (Session& s, boost::shared_ptr<Ro
auto_touch_item = 0;
auto_write_item = 0;
auto_play_item = 0;
+ mode_discrete_item = 0;
+ mode_line_item = 0;
+
ignore_state_request = false;
first_call_to_set_height = true;
@@ -321,6 +324,31 @@ AutomationTimeAxisView::automation_state_changed ()
}
void
+AutomationTimeAxisView::interpolation_changed ()
+{
+ AutomationList::InterpolationStyle style = _control->list()->interpolation();
+
+ if (mode_line_item && mode_discrete_item) {
+ if (style == AutomationList::Discrete) {
+ mode_discrete_item->set_active(true);
+ mode_line_item->set_active(false);
+ } else {
+ mode_line_item->set_active(true);
+ mode_discrete_item->set_active(false);
+ }
+ }
+
+ _line->set_interpolation(style);
+}
+
+void
+AutomationTimeAxisView::set_interpolation (AutomationList::InterpolationStyle style)
+{
+ _control->list()->set_interpolation(style);
+ _line->set_interpolation(style);
+}
+
+void
AutomationTimeAxisView::height_clicked ()
{
popup_size_menu (0);
@@ -493,6 +521,8 @@ AutomationTimeAxisView::build_display_menu ()
items.push_back (MenuElem (_("Clear"), mem_fun(*this, &AutomationTimeAxisView::clear_clicked)));
items.push_back (SeparatorElem());
+ /* state menu */
+
Menu* auto_state_menu = manage (new Menu);
auto_state_menu->set_name ("ArdourContextMenu");
MenuList& as_items = auto_state_menu->items();
@@ -514,10 +544,35 @@ AutomationTimeAxisView::build_display_menu ()
auto_touch_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
items.push_back (MenuElem (_("State"), *auto_state_menu));
+
+ /* mode menu */
+
+ if (_control->parameter().type() == MidiCCAutomation) {
+ Menu* auto_mode_menu = manage (new Menu);
+ auto_mode_menu->set_name ("ArdourContextMenu");
+ MenuList& am_items = auto_mode_menu->items();
+
+ RadioMenuItem::Group group;
+
+ am_items.push_back (RadioMenuElem (group, _("Discrete"), bind (
+ mem_fun(*this, &AutomationTimeAxisView::set_interpolation),
+ AutomationList::Discrete)));
+ mode_discrete_item = dynamic_cast<CheckMenuItem*>(&am_items.back());
+ //mode_discrete_item->set_active(_control->list()->interpolation() == AutomationList::Discrete);
+
+ am_items.push_back (RadioMenuElem (group, _("Line"), bind (
+ mem_fun(*this, &AutomationTimeAxisView::set_interpolation),
+ AutomationList::Linear)));
+ mode_line_item = dynamic_cast<CheckMenuItem*>(&am_items.back());
+ //mode_line_item->set_active(_control->list()->interpolation() == AutomationList::Linear);
+
+ items.push_back (MenuElem (_("Mode"), *auto_mode_menu));
+ }
/* make sure the automation menu state is correct */
automation_state_changed ();
+ interpolation_changed ();
}
void
@@ -816,27 +871,15 @@ AutomationTimeAxisView::add_line (boost::shared_ptr<AutomationLine> line)
}
void
-AutomationTimeAxisView::show_all_control_points ()
-{
- _line->show_all_control_points ();
-}
-
-void
-AutomationTimeAxisView::hide_all_but_selected_control_points ()
-{
- _line->hide_all_but_selected_control_points ();
-}
-
-void
AutomationTimeAxisView::entered()
{
- show_all_control_points ();
+ _line->track_entered();
}
void
AutomationTimeAxisView::exited ()
{
- hide_all_but_selected_control_points ();
+ _line->track_exited();
}
void
diff --git a/gtk2_ardour/automation_time_axis.h b/gtk2_ardour/automation_time_axis.h
index c3be6ffd00..b708b6f58e 100644
--- a/gtk2_ardour/automation_time_axis.h
+++ b/gtk2_ardour/automation_time_axis.h
@@ -94,8 +94,6 @@ class AutomationTimeAxisView : public TimeAxisView {
void add_ghost (GhostRegion*);
void remove_ghost (GhostRegion*);
- void show_all_control_points ();
- void hide_all_but_selected_control_points ();
void set_state (const XMLNode&);
guint32 show_at (double y, int& nth, Gtk::VBox *parent);
@@ -133,6 +131,9 @@ class AutomationTimeAxisView : public TimeAxisView {
Gtk::CheckMenuItem* auto_touch_item;
Gtk::CheckMenuItem* auto_write_item;
+ Gtk::CheckMenuItem* mode_discrete_item;
+ Gtk::CheckMenuItem* mode_line_item;
+
void add_line (boost::shared_ptr<AutomationLine>);
void clear_clicked ();
@@ -153,6 +154,10 @@ class AutomationTimeAxisView : public TimeAxisView {
bool ignore_state_request;
void automation_state_changed ();
+
+ void set_interpolation (ARDOUR::AutomationList::InterpolationStyle);
+ void interpolation_changed ();
+
sigc::connection automation_connection;
void update_extra_xml_shown (bool editor_shown);
diff --git a/gtk2_ardour/control_point.cc b/gtk2_ardour/control_point.cc
new file mode 100644
index 0000000000..b43826720c
--- /dev/null
+++ b/gtk2_ardour/control_point.cc
@@ -0,0 +1,202 @@
+/*
+ Copyright (C) 2002-2007 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "control_point.h"
+#include "diamond.h"
+#include "automation_line.h"
+#include "ardour_ui.h"
+#include "public_editor.h"
+
+#include "i18n.h"
+
+using namespace std;
+using namespace sigc;
+using namespace ARDOUR;
+using namespace PBD;
+using namespace Gnome; // for Canvas
+
+ControlPoint::ControlPoint (AutomationLine& al)
+ : _line (al)
+{
+ _model = al.the_list()->end();
+ _view_index = 0;
+ _can_slide = true;
+ _x = 0;
+ _y = 0;
+ _shape = Full;
+ _size = 4.0;
+ _selected = false;
+
+ _item = new Canvas::SimpleRect (_line.canvas_group());
+ _item->property_draw() = true;
+ _item->property_fill() = false;
+ _item->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_ControlPointFill.get();
+ _item->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_ControlPointOutline.get();
+ _item->property_outline_pixels() = 1;
+ _item->set_data ("control_point", this);
+ _item->signal_event().connect (mem_fun (this, &ControlPoint::event_handler));
+
+ hide ();
+ set_visible (false);
+}
+
+ControlPoint::ControlPoint (const ControlPoint& other, bool dummy_arg_to_force_special_copy_constructor)
+ : _line (other._line)
+{
+ if (&other == this) {
+ return;
+ }
+
+ _model = other._model;
+ _view_index = other._view_index;
+ _can_slide = other._can_slide;
+ _x = other._x;
+ _y = other._y;
+ _shape = other._shape;
+ _size = other._size;
+ _selected = false;
+
+ _item = new Canvas::SimpleRect (_line.canvas_group());
+ _item->property_fill() = false;
+ _item->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_ControlPointOutline.get();
+ _item->property_outline_pixels() = 1;
+
+ /* NOTE: no event handling in copied ControlPoints */
+
+ hide ();
+ set_visible (false);
+}
+
+ControlPoint::~ControlPoint ()
+{
+ delete _item;
+}
+
+bool
+ControlPoint::event_handler (GdkEvent* event)
+{
+ return PublicEditor::instance().canvas_control_point_event (event, _item, this);
+}
+
+void
+ControlPoint::hide ()
+{
+ _item->hide();
+}
+
+void
+ControlPoint::show()
+{
+ _item->show();
+}
+
+void
+ControlPoint::set_visible (bool yn)
+{
+ _item->property_draw() = (gboolean) yn;
+}
+
+void
+ControlPoint::reset (double x, double y, AutomationList::iterator mi, uint32_t vi, ShapeType shape)
+{
+ _model = mi;
+ _view_index = vi;
+ move_to (x, y, shape);
+}
+
+void
+ControlPoint::show_color (bool entered, bool hide_too)
+{
+ uint32_t color = 0;
+
+ if (entered) {
+ if (_selected) {
+ color = ARDOUR_UI::config()->canvasvar_EnteredControlPointSelected.get();
+ set_visible(true);
+ } else {
+ color = ARDOUR_UI::config()->canvasvar_EnteredControlPointOutline.get();
+ if (hide_too) {
+ set_visible(false);
+ }
+ }
+
+ } else {
+ if (_selected) {
+ color = ARDOUR_UI::config()->canvasvar_ControlPointSelected.get();
+ set_visible(true);
+ } else {
+ color = ARDOUR_UI::config()->canvasvar_ControlPointOutline.get();
+ if (hide_too) {
+ set_visible(false);
+ }
+ }
+ }
+
+ _item->property_outline_color_rgba() = color;
+ _item->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_ControlPointFill.get();
+}
+
+void
+ControlPoint::set_size (double sz)
+{
+ _size = sz;
+
+#if 0
+ if (_size > 6.0) {
+ item->property_fill() = (gboolean) TRUE;
+ } else {
+ item->property_fill() = (gboolean) FALSE;
+ }
+#endif
+
+ move_to (_x, _y, _shape);
+}
+
+void
+ControlPoint::move_to (double x, double y, ShapeType shape)
+{
+ double x1 = 0;
+ double x2 = 0;
+ double half_size = rint(_size/2.0);
+
+ switch (shape) {
+ case Full:
+ x1 = x - half_size;
+ x2 = x + half_size;
+ break;
+ case Start:
+ x1 = x;
+ x2 = x + half_size;
+ break;
+ case End:
+ x1 = x - half_size;
+ x2 = x;
+ break;
+ }
+
+ _item->property_x1() = x1;
+ _item->property_x2() = x2;
+ _item->property_y1() = y - half_size;
+ _item->property_y2() = y + half_size;
+
+ _x = x;
+ _y = y;
+ _shape = shape;
+}
+
diff --git a/gtk2_ardour/control_point.h b/gtk2_ardour/control_point.h
new file mode 100644
index 0000000000..47b0d131b7
--- /dev/null
+++ b/gtk2_ardour/control_point.h
@@ -0,0 +1,102 @@
+/*
+ Copyright (C) 2002-2007 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __ardour_control_point_h__
+#define __ardour_control_point_h__
+
+#include <sys/types.h>
+
+#include <ardour/automation_event.h>
+
+#include "canvas.h"
+#include "simplerect.h"
+
+class AutomationLine;
+class ControlPoint;
+class PointSelection;
+class TimeAxisView;
+class AutomationTimeAxisView;
+class Selectable;
+class Selection;
+
+namespace Gnome {
+ namespace Canvas {
+ class SimpleRect;
+ class Diamond;
+ }
+}
+
+class ControlPoint
+{
+ public:
+ ControlPoint (AutomationLine& al);
+ ControlPoint (const ControlPoint&, bool dummy_arg_to_force_special_copy_constructor);
+ virtual ~ControlPoint ();
+
+ enum ShapeType {
+ Full,
+ Start,
+ End
+ };
+
+ void move_to (double x, double y, ShapeType);
+ void reset (double x, double y, ARDOUR::AutomationList::iterator, uint32_t, ShapeType);
+ double get_x() const { return _x; }
+ double get_y() const { return _y; }
+
+ void hide ();
+ void show ();
+ void show_color (bool entered, bool hide_too);
+
+ void set_size (double);
+ void set_visible (bool);
+
+ bool can_slide() const { return _can_slide; }
+ void set_can_slide(bool yn) { _can_slide = yn; }
+ bool selected() const { return _selected; }
+ void set_selected(bool yn) { _selected = yn; }
+ uint32_t view_index() const { return _view_index; }
+ void set_view_index(uint32_t i) { _view_index = i; }
+
+ ARDOUR::AutomationList::iterator model() const { return _model; }
+ AutomationLine& line() const { return _line; }
+ ArdourCanvas::Item* item() const { return _item; }
+
+ protected:
+ ArdourCanvas::SimpleRect* _item;
+
+ AutomationLine& _line;
+
+ ARDOUR::AutomationList::iterator _model;
+ uint32_t _view_index;
+ bool _can_slide;
+ bool _selected;
+
+ virtual bool event_handler (GdkEvent*);
+
+ private:
+ double _x;
+ double _y;
+ double _size;
+ ShapeType _shape;
+};
+
+
+#endif /* __ardour_control_point_h__ */
+
diff --git a/gtk2_ardour/diamond.cc b/gtk2_ardour/diamond.cc
new file mode 100644
index 0000000000..31761597cd
--- /dev/null
+++ b/gtk2_ardour/diamond.cc
@@ -0,0 +1,35 @@
+/*
+ Copyright (C) 2007 Paul Davis
+ Author: Dave Robillard
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "diamond.h"
+
+using namespace Gnome::Canvas;
+using namespace Gnome::Art;
+
+Diamond::Diamond(Group& group, double height)
+ : Polygon(group)
+{
+ Points points;
+ points.push_back(Point(0, height*2));
+ points.push_back(Point(height, height));
+ points.push_back(Point(0, 0));
+ points.push_back(Point(-height, height));
+ property_points() = points;
+}
+
diff --git a/gtk2_ardour/diamond.h b/gtk2_ardour/diamond.h
new file mode 100644
index 0000000000..a7f8c684ff
--- /dev/null
+++ b/gtk2_ardour/diamond.h
@@ -0,0 +1,38 @@
+/*
+ Copyright (C) 2007 Paul Davis
+ Author: Dave Robillard
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __ardour_diamond_h__
+#define __ardour_diamond_h__
+
+#include <libgnomecanvasmm/polygon.h>
+
+namespace Gnome {
+namespace Canvas {
+
+
+class Diamond : public Gnome::Canvas::Polygon {
+public:
+ Diamond(Gnome::Canvas::Group& group, double height);
+};
+
+
+} // namespace Canvas
+} // namespace Gnome
+
+#endif /* __ardour_diamond_h__ */
diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc
index 7ba3d9c537..a771fb51b4 100644
--- a/gtk2_ardour/editor.cc
+++ b/gtk2_ardour/editor.cc
@@ -2754,15 +2754,15 @@ Editor::duplicate_dialog (bool dup_region)
void
Editor::show_verbose_canvas_cursor ()
{
- verbose_canvas_cursor->raise_to_top();
- verbose_canvas_cursor->show();
+ verbose_canvas_cursor->raise_to_top();
+ verbose_canvas_cursor->show();
verbose_cursor_visible = true;
}
void
Editor::hide_verbose_canvas_cursor ()
{
- verbose_canvas_cursor->hide();
+ verbose_canvas_cursor->hide();
verbose_cursor_visible = false;
}
diff --git a/gtk2_ardour/editor_canvas_events.cc b/gtk2_ardour/editor_canvas_events.cc
index e4908ccba9..394d35e245 100644
--- a/gtk2_ardour/editor_canvas_events.cc
+++ b/gtk2_ardour/editor_canvas_events.cc
@@ -36,6 +36,7 @@
#include "automation_line.h"
#include "automation_time_axis.h"
#include "automation_line.h"
+#include "control_point.h"
#include "canvas_impl.h"
#include "simplerect.h"
@@ -566,7 +567,7 @@ Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, C
case GDK_2BUTTON_PRESS:
case GDK_3BUTTON_PRESS:
clicked_control_point = cp;
- clicked_axisview = &cp->line.trackview;
+ clicked_axisview = &cp->line().trackview;
clicked_routeview = dynamic_cast<RouteTimeAxisView*>(clicked_axisview);
clicked_regionview = 0;
break;
diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc
index fe17b31abf..406eda01db 100644
--- a/gtk2_ardour/editor_mouse.cc
+++ b/gtk2_ardour/editor_mouse.cc
@@ -39,6 +39,7 @@
#include "streamview.h"
#include "region_gain_line.h"
#include "automation_time_axis.h"
+#include "control_point.h"
#include "prompter.h"
#include "utils.h"
#include "selection.h"
@@ -1019,13 +1020,13 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
double at_x, at_y;
at_x = cp->get_x();
at_y = cp->get_y ();
- cp->item->i2w (at_x, at_y);
+ cp->item()->i2w (at_x, at_y);
at_x += 20.0;
at_y += 20.0;
- fraction = 1.0 - (cp->get_y() / cp->line.height());
+ fraction = 1.0 - (cp->get_y() / cp->line().height());
- set_verbose_canvas_cursor (cp->line.get_verbose_cursor_string (fraction), at_x, at_y);
+ set_verbose_canvas_cursor (cp->line().get_verbose_cursor_string (fraction), at_x, at_y);
show_verbose_canvas_cursor ();
if (is_drawable()) {
@@ -1196,8 +1197,8 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
switch (item_type) {
case ControlPointItem:
cp = reinterpret_cast<ControlPoint*>(item->get_data ("control_point"));
- if (cp->line.npoints() > 1) {
- if (!cp->selected) {
+ if (cp->line().the_list()->interpolation() != AutomationList::Discrete) {
+ if (cp->line().npoints() > 1 && !cp->selected()) {
cp->set_visible (false);
}
}
@@ -2334,16 +2335,16 @@ Editor::remove_gain_control_point (ArdourCanvas::Item*item, GdkEvent* event)
}
// We shouldn't remove the first or last gain point
- if (control_point->line.is_last_point(*control_point) ||
- control_point->line.is_first_point(*control_point)) {
+ if (control_point->line().is_last_point(*control_point) ||
+ control_point->line().is_first_point(*control_point)) {
return;
}
- control_point->line.remove_point (*control_point);
+ control_point->line().remove_point (*control_point);
}
void
-Editor::remove_control_point (ArdourCanvas::Item*item, GdkEvent* event)
+Editor::remove_control_point (ArdourCanvas::Item* item, GdkEvent* event)
{
ControlPoint* control_point;
@@ -2352,7 +2353,7 @@ Editor::remove_control_point (ArdourCanvas::Item*item, GdkEvent* event)
/*NOTREACHED*/
}
- control_point->line.remove_point (*control_point);
+ control_point->line().remove_point (*control_point);
}
void
@@ -2372,10 +2373,10 @@ Editor::start_control_point_grab (ArdourCanvas::Item* item, GdkEvent* event)
start_grab (event, fader_cursor);
- control_point->line.start_drag (control_point, drag_info.grab_frame, 0);
+ control_point->line().start_drag (control_point, drag_info.grab_frame, 0);
- double fraction = 1.0 - ((control_point->get_y() - control_point->line.y_position()) / (double)control_point->line.height());
- set_verbose_canvas_cursor (control_point->line.get_verbose_cursor_string (fraction),
+ double fraction = 1.0 - ((control_point->get_y() - control_point->line().y_position()) / (double)control_point->line().height());
+ set_verbose_canvas_cursor (control_point->line().get_verbose_cursor_string (fraction),
drag_info.current_pointer_x + 20, drag_info.current_pointer_y + 20);
show_verbose_canvas_cursor ();
@@ -2399,11 +2400,11 @@ Editor::control_point_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent*
cy = drag_info.grab_y;
}
- cp->line.parent_group().w2i (cx, cy);
+ cp->line().parent_group().w2i (cx, cy);
cx = max (0.0, cx);
cy = max (0.0, cy);
- cy = min ((double) (cp->line.y_position() + cp->line.height()), cy);
+ cy = min ((double) (cp->line().y_position() + cp->line().height()), cy);
//translate cx to frames
nframes_t cx_frames = unit_to_frame (cx);
@@ -2412,7 +2413,7 @@ Editor::control_point_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent*
snap_to (cx_frames);
}
- const double fraction = 1.0 - ((cy - cp->line.y_position()) / (double)cp->line.height());
+ const double fraction = 1.0 - ((cy - cp->line().y_position()) / (double)cp->line().height());
bool push;
@@ -2422,9 +2423,9 @@ Editor::control_point_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent*
push = false;
}
- cp->line.point_drag (*cp, cx_frames , fraction, push);
+ cp->line().point_drag (*cp, cx_frames , fraction, push);
- set_verbose_canvas_cursor_text (cp->line.get_verbose_cursor_string (fraction));
+ set_verbose_canvas_cursor_text (cp->line().get_verbose_cursor_string (fraction));
drag_info.first_move = false;
}
@@ -2445,7 +2446,7 @@ Editor::control_point_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent
} else {
control_point_drag_motion_callback (item, event);
}
- cp->line.end_drag (cp);
+ cp->line().end_drag (cp);
}
void
diff --git a/gtk2_ardour/editor_selection.cc b/gtk2_ardour/editor_selection.cc
index 3f3edfe65b..41b6d32a0b 100644
--- a/gtk2_ardour/editor_selection.cc
+++ b/gtk2_ardour/editor_selection.cc
@@ -29,6 +29,7 @@
#include "audio_region_view.h"
#include "audio_streamview.h"
#include "automation_line.h"
+#include "control_point.h"
#include "i18n.h"
diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc
index 80e239e660..e4cb80bca0 100644
--- a/gtk2_ardour/midi_region_view.cc
+++ b/gtk2_ardour/midi_region_view.cc
@@ -36,6 +36,7 @@
#include "midi_time_axis.h"
#include "simplerect.h"
#include "simpleline.h"
+#include "diamond.h"
#include "public_editor.h"
#include "ghostregion.h"
#include "midi_time_axis.h"
@@ -96,12 +97,20 @@ MidiRegionView::init (Gdk::Color& basic_color, bool wfd)
void
-MidiRegionView::display_events()
+MidiRegionView::clear_events()
{
for (std::vector<ArdourCanvas::Item*>::iterator i = _events.begin(); i != _events.end(); ++i)
delete *i;
_events.clear();
+}
+
+
+void
+MidiRegionView::display_events()
+{
+ clear_events();
+
begin_write();
for (size_t i=0; i < midi_region()->midi_source(0)->model()->n_events(); ++i)
@@ -182,8 +191,6 @@ MidiRegionView::add_ghost (AutomationTimeAxisView& atv)
double unit_position = _region->position () / samples_per_unit;
GhostRegion* ghost = new GhostRegion (atv, unit_position);
- cerr << "FIXME: add notes to MIDI region ghost." << endl;
-
ghost->set_height ();
ghost->set_duration (_region->length() / samples_per_unit);
ghosts.push_back (ghost);
@@ -226,42 +233,56 @@ MidiRegionView::add_event (const MidiEvent& ev)
MidiTimeAxisView* const mtv = dynamic_cast<MidiTimeAxisView*>(&trackview);
MidiStreamView* const view = mtv->midi_view();
-
+ ArdourCanvas::Group* const group = (ArdourCanvas::Group*)get_canvas_group();
+
const uint8_t note_range = view->highest_note() - view->lowest_note() + 1;
const double footer_height = name_highlight->property_y2() - name_highlight->property_y1();
const double pixel_range = (trackview.height - footer_height - 5.0) / (double)note_range;
- if ((ev.buffer[0] & 0xF0) == MIDI_CMD_NOTE_ON) {
+ if (mtv->note_mode() == Note) {
+ if ((ev.buffer[0] & 0xF0) == MIDI_CMD_NOTE_ON) {
+ const Byte& note = ev.buffer[1];
+ const double y1 = trackview.height - (pixel_range * (note - view->lowest_note() + 1))
+ - footer_height - 3.0;
+
+ ArdourCanvas::SimpleRect * ev_rect = new Gnome::Canvas::SimpleRect(*group);
+ ev_rect->property_x1() = trackview.editor.frame_to_pixel (
+ (nframes_t)ev.time);
+ ev_rect->property_y1() = y1;
+ ev_rect->property_x2() = trackview.editor.frame_to_pixel (
+ _region->length());
+ ev_rect->property_y2() = y1 + ceil(pixel_range);
+ ev_rect->property_outline_color_rgba() = 0xFFFFFFAA;
+ /* outline all but right edge */
+ ev_rect->property_outline_what() = (guint32) (0x1 & 0x4 & 0x8);
+ ev_rect->property_fill_color_rgba() = 0xFFFFFF66;
+
+ _events.push_back(ev_rect);
+ if (_active_notes)
+ _active_notes[note] = ev_rect;
+
+ } else if ((ev.buffer[0] & 0xF0) == MIDI_CMD_NOTE_OFF) {
+ const Byte& note = ev.buffer[1];
+ if (_active_notes && _active_notes[note]) {
+ _active_notes[note]->property_x2() = trackview.editor.frame_to_pixel((nframes_t)ev.time);
+ _active_notes[note]->property_outline_what() = (guint32) 0xF; // all edges
+ _active_notes[note] = NULL;
+ }
+ }
+
+ } else if (mtv->note_mode() == Percussion) {
const Byte& note = ev.buffer[1];
- const double y1 = trackview.height - (pixel_range * (note - view->lowest_note() + 1))
+ const double x = trackview.editor.frame_to_pixel((nframes_t)ev.time);
+ const double y = trackview.height - (pixel_range * (note - view->lowest_note() + 1))
- footer_height - 3.0;
- ArdourCanvas::SimpleRect * ev_rect = new Gnome::Canvas::SimpleRect(
- *(ArdourCanvas::Group*)get_canvas_group());
- ev_rect->property_x1() = trackview.editor.frame_to_pixel (
- (nframes_t)ev.time);
- ev_rect->property_y1() = y1;
- ev_rect->property_x2() = trackview.editor.frame_to_pixel (
- _region->length());
- ev_rect->property_y2() = y1 + ceil(pixel_range);
- ev_rect->property_outline_color_rgba() = 0xFFFFFFAA;
- /* outline all but right edge */
- ev_rect->property_outline_what() = (guint32) (0x1 & 0x4 & 0x8);
- ev_rect->property_fill_color_rgba() = 0xFFFFFF66;
-
- _events.push_back(ev_rect);
- if (_active_notes)
- _active_notes[note] = ev_rect;
-
- } else if ((ev.buffer[0] & 0xF0) == MIDI_CMD_NOTE_OFF) {
- const Byte& note = ev.buffer[1];
- if (_active_notes && _active_notes[note]) {
- _active_notes[note]->property_x2() = trackview.editor.frame_to_pixel((nframes_t)ev.time);
- _active_notes[note]->property_outline_what() = (guint32) 0xF; // all edges
- _active_notes[note] = NULL;
- }
+ Diamond* ev_diamond = new Diamond(*group, std::min(pixel_range, 5.0));
+ ev_diamond->move(x, y);
+ ev_diamond->show();
+ ev_diamond->property_outline_color_rgba() = 0xFFFFFFDD;
+ ev_diamond->property_fill_color_rgba() = 0xFFFFFF66;
+ _events.push_back(ev_diamond);
}
-
}
diff --git a/gtk2_ardour/midi_region_view.h b/gtk2_ardour/midi_region_view.h
index e8175fe069..88ef43243b 100644
--- a/gtk2_ardour/midi_region_view.h
+++ b/gtk2_ardour/midi_region_view.h
@@ -93,6 +93,7 @@ class MidiRegionView : public RegionView
private:
void display_events();
+ void clear_events();
std::vector<ArdourCanvas::Item*> _events;
ArdourCanvas::SimpleRect** _active_notes;
diff --git a/gtk2_ardour/midi_streamview.h b/gtk2_ardour/midi_streamview.h
index 0122eb4e1b..ce459e2fad 100644
--- a/gtk2_ardour/midi_streamview.h
+++ b/gtk2_ardour/midi_streamview.h
@@ -60,6 +60,8 @@ class MidiStreamView : public StreamView
uint8_t lowest_note() const { return _lowest_note; }
uint8_t highest_note() const { return _highest_note; }
+
+ void redisplay_diskstream ();
private:
void setup_rec_box ();
@@ -69,8 +71,6 @@ class MidiStreamView : public StreamView
RegionView* add_region_view_internal (boost::shared_ptr<ARDOUR::Region>, bool wait_for_waves);
void display_region(MidiRegionView* region_view, bool redisplay_events);
- void redisplay_diskstream ();
-
void color_handler ();
uint8_t _lowest_note;
diff --git a/gtk2_ardour/midi_time_axis.cc b/gtk2_ardour/midi_time_axis.cc
index a843659cbc..48aa78dc06 100644
--- a/gtk2_ardour/midi_time_axis.cc
+++ b/gtk2_ardour/midi_time_axis.cc
@@ -79,8 +79,10 @@ using namespace Editing;
MidiTimeAxisView::MidiTimeAxisView (PublicEditor& ed, Session& sess, boost::shared_ptr<Route> rt, Canvas& canvas)
- : AxisView(sess), // FIXME: won't compile without this, why??
- RouteTimeAxisView(ed, sess, rt, canvas)
+ : AxisView(sess) // FIXME: won't compile without this, why??
+ , RouteTimeAxisView(ed, sess, rt, canvas)
+ , _note_mode_item(NULL)
+ , _percussion_mode_item(NULL)
{
subplugin_menu.set_name ("ArdourContextMenu");
@@ -91,10 +93,12 @@ MidiTimeAxisView::MidiTimeAxisView (PublicEditor& ed, Session& sess, boost::shar
mute_button->set_active (false);
solo_button->set_active (false);
- if (is_midi_track())
+ if (is_midi_track()) {
controls_ebox.set_name ("MidiTimeAxisViewControlsBaseUnselected");
- else // bus
+ _note_mode = midi_track()->note_mode();
+ } else { // MIDI bus (which doesn't exist yet..)
controls_ebox.set_name ("MidiBusControlsBaseUnselected");
+ }
/* map current state of the route */
@@ -167,6 +171,39 @@ MidiTimeAxisView::build_automation_action_menu ()
mem_fun(*this, &MidiTimeAxisView::add_controller_track)));
}
+Gtk::Menu*
+MidiTimeAxisView::build_mode_menu()
+{
+ using namespace Menu_Helpers;
+
+ Menu* mode_menu = manage (new Menu);
+ MenuList& items = mode_menu->items();
+ mode_menu->set_name ("ArdourContextMenu");
+
+ RadioMenuItem::Group mode_group;
+ items.push_back (RadioMenuElem (mode_group, _("Note"),
+ bind (mem_fun (*this, &MidiTimeAxisView::set_note_mode), Note)));
+ _note_mode_item = dynamic_cast<RadioMenuItem*>(&items.back());
+ _note_mode_item->set_active(_note_mode == Note);
+
+ items.push_back (RadioMenuElem (mode_group, _("Percussion"),
+ bind (mem_fun (*this, &MidiTimeAxisView::set_note_mode), Percussion)));
+ _percussion_mode_item = dynamic_cast<RadioMenuItem*>(&items.back());
+ _percussion_mode_item->set_active(_note_mode == Percussion);
+
+ return mode_menu;
+}
+
+void
+MidiTimeAxisView::set_note_mode(NoteMode mode)
+{
+ if (_note_mode != mode) {
+ _note_mode = mode;
+ midi_track()->set_note_mode(mode);
+ _view->redisplay_diskstream();
+ }
+}
+
/** Prompt for a controller with a dialog and add an automation track for it
*/
void
diff --git a/gtk2_ardour/midi_time_axis.h b/gtk2_ardour/midi_time_axis.h
index 6a5ba07a38..039affd979 100644
--- a/gtk2_ardour/midi_time_axis.h
+++ b/gtk2_ardour/midi_time_axis.h
@@ -66,15 +66,24 @@ class MidiTimeAxisView : public RouteTimeAxisView
void add_controller_track ();
void create_automation_child (ARDOUR::Parameter param, bool show);
+ ARDOUR::NoteMode note_mode() const { return _note_mode; }
+
private:
void build_automation_action_menu ();
-
+ Gtk::Menu* build_mode_menu();
+
+ void set_note_mode(ARDOUR::NoteMode mode);
+
void route_active_changed ();
void add_insert_to_subplugin_menu (ARDOUR::Processor *);
- Gtk::Menu subplugin_menu;
+ Gtk::Menu _subplugin_menu;
+
+ ARDOUR::NoteMode _note_mode;
+ Gtk::RadioMenuItem* _note_mode_item;
+ Gtk::RadioMenuItem* _percussion_mode_item;
};
#endif /* __ardour_midi_time_axis_h__ */
diff --git a/gtk2_ardour/route_time_axis.cc b/gtk2_ardour/route_time_axis.cc
index caead7fdd1..e0d93bd41a 100644
--- a/gtk2_ardour/route_time_axis.cc
+++ b/gtk2_ardour/route_time_axis.cc
@@ -521,25 +521,11 @@ RouteTimeAxisView::build_display_menu ()
items.push_back (MenuElem (_("Alignment"), *alignment_menu));
get_diskstream()->AlignmentStyleChanged.connect (
- mem_fun(*this, &RouteTimeAxisView::align_style_changed));
-
- RadioMenuItem::Group mode_group;
- items.push_back (RadioMenuElem (mode_group, _("Normal mode"),
- bind (mem_fun (*this, &RouteTimeAxisView::set_track_mode), ARDOUR::Normal)));
- normal_track_mode_item = dynamic_cast<RadioMenuItem*>(&items.back());
- items.push_back (RadioMenuElem (mode_group, _("Tape mode"),
- bind (mem_fun (*this, &RouteTimeAxisView::set_track_mode), ARDOUR::Destructive)));
- destructive_track_mode_item = dynamic_cast<RadioMenuItem*>(&items.back());
-
+ mem_fun(*this, &RouteTimeAxisView::align_style_changed));
- switch (track()->mode()) {
- case ARDOUR::Destructive:
- destructive_track_mode_item->set_active ();
- break;
- case ARDOUR::Normal:
- normal_track_mode_item->set_active ();
- break;
- }
+ mode_menu = build_mode_menu();
+ if (mode_menu)
+ items.push_back (MenuElem (_("Mode"), *mode_menu));
}
items.push_back (SeparatorElem());
diff --git a/gtk2_ardour/route_time_axis.h b/gtk2_ardour/route_time_axis.h
index 0a6c3f0173..0d42f331a9 100644
--- a/gtk2_ardour/route_time_axis.h
+++ b/gtk2_ardour/route_time_axis.h
@@ -247,6 +247,9 @@ protected:
Gtk::Menu* playlist_menu;
Gtk::Menu* playlist_action_menu;
Gtk::MenuItem* playlist_item;
+ Gtk::Menu* mode_menu;
+
+ virtual Gtk::Menu* build_mode_menu() { return NULL; }
void use_playlist (boost::weak_ptr<ARDOUR::Playlist>);
diff --git a/gtk2_ardour/streamview.h b/gtk2_ardour/streamview.h
index 389000c7ef..3c9bd43666 100644
--- a/gtk2_ardour/streamview.h
+++ b/gtk2_ardour/streamview.h
@@ -93,6 +93,8 @@ public:
void add_region_view (boost::shared_ptr<ARDOUR::Region>);
void region_layered (RegionView*);
+ virtual void redisplay_diskstream () = 0;
+
sigc::signal<void,RegionView*> RegionViewAdded;
protected:
@@ -114,7 +116,6 @@ protected:
void display_diskstream (boost::shared_ptr<ARDOUR::Diskstream>);
virtual void undisplay_diskstream ();
- virtual void redisplay_diskstream () = 0;
void diskstream_changed ();
virtual void playlist_changed (boost::shared_ptr<ARDOUR::Diskstream>);
diff --git a/libs/ardour/ardour/automation_event.h b/libs/ardour/ardour/automation_event.h
index 8a9b110714..ac8ce70ff1 100644
--- a/libs/ardour/ardour/automation_event.h
+++ b/libs/ardour/ardour/automation_event.h
@@ -229,6 +229,15 @@ class AutomationList : public PBD::StatefulDestructible
Curve& curve() { return *_curve; }
const Curve& curve() const { return *_curve; }
+ enum InterpolationStyle {
+ Discrete,
+ Linear,
+ Curved
+ };
+
+ InterpolationStyle interpolation() const { return _interpolation; }
+ void set_interpolation(InterpolationStyle style) { _interpolation = style; }
+
protected:
/** Called by unlocked_eval() to handle cases of 3 or more control points.
@@ -247,6 +256,7 @@ class AutomationList : public PBD::StatefulDestructible
mutable SearchCache _search_cache;
Parameter _parameter;
+ InterpolationStyle _interpolation;
EventList _events;
mutable Glib::Mutex _lock;
int8_t _frozen;
diff --git a/libs/ardour/ardour/midi_track.h b/libs/ardour/ardour/midi_track.h
index aea032f725..2317cd0549 100644
--- a/libs/ardour/ardour/midi_track.h
+++ b/libs/ardour/ardour/midi_track.h
@@ -57,7 +57,7 @@ public:
int use_diskstream (string name);
int use_diskstream (const PBD::ID& id);
- int set_mode (TrackMode m);
+ //int set_mode (TrackMode m);
void set_latency_delay (nframes_t);
@@ -85,6 +85,9 @@ public:
MidiTrack* _route;
};
+ NoteMode note_mode() const { return _note_mode; }
+ void set_note_mode (NoteMode m) { _note_mode = m; }
+
protected:
XMLNode& state (bool full);
@@ -101,6 +104,7 @@ private:
void set_state_part_three ();
MidiRingBuffer _immediate_events;
+ NoteMode _note_mode;
};
} /* namespace ARDOUR*/
diff --git a/libs/ardour/ardour/parameter.h b/libs/ardour/ardour/parameter.h
index 42159a2bbb..803bd889cb 100644
--- a/libs/ardour/ardour/parameter.h
+++ b/libs/ardour/ardour/parameter.h
@@ -127,6 +127,28 @@ public:
}
}
+ /* The below properties are only used for CC right now, but unchanging properties
+ * of parameters (rather than changing parameters of automation lists themselves)
+ * should be moved here */
+
+ inline double min() const {
+ if (_type == MidiCCAutomation)
+ return 0.0;
+ else
+ return DBL_MIN;
+ }
+
+ inline double max() const {
+ if (_type == MidiCCAutomation)
+ return 127.0;
+ else
+ return DBL_MAX;
+ }
+
+ inline bool is_integer() const {
+ return (_type == MidiCCAutomation);
+ }
+
private:
// default copy constructor is ok
AutomationType _type;
diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h
index cfb9dd49b0..ab54b6c26c 100644
--- a/libs/ardour/ardour/types.h
+++ b/libs/ardour/ardour/types.h
@@ -143,6 +143,11 @@ namespace ARDOUR {
Destructive
};
+ enum NoteMode {
+ Note,
+ Percussion
+ };
+
struct BBT_Time {
uint32_t bars;
uint32_t beats;
diff --git a/libs/ardour/automatable.cc b/libs/ardour/automatable.cc
index 885034056d..dfdcf82cab 100644
--- a/libs/ardour/automatable.cc
+++ b/libs/ardour/automatable.cc
@@ -463,3 +463,4 @@ Automatable::control_factory(boost::shared_ptr<AutomationList> list)
return boost::shared_ptr<AutomationControl>(new AutomationControl(_session, list));
}
}
+
diff --git a/libs/ardour/automation_control.cc b/libs/ardour/automation_control.cc
index 73d5819bc4..4885a6fed9 100644
--- a/libs/ardour/automation_control.cc
+++ b/libs/ardour/automation_control.cc
@@ -35,7 +35,6 @@ AutomationControl::AutomationControl(Session& session, boost::shared_ptr<Automat
, _list(list)
, _user_value(list->default_value())
{
- cerr << "Created AutomationControl " << name << "(" << list->parameter().to_string() << ")" << endl;
}
diff --git a/libs/ardour/automation_event.cc b/libs/ardour/automation_event.cc
index 2bb987ad24..a024391980 100644
--- a/libs/ardour/automation_event.cc
+++ b/libs/ardour/automation_event.cc
@@ -28,6 +28,7 @@
#include <ardour/automation_event.h>
#include <ardour/curve.h>
#include <pbd/stacktrace.h>
+#include <pbd/enumwriter.h>
#include "i18n.h"
@@ -56,6 +57,7 @@ static void dumpit (const AutomationList& al, string prefix = "")
AutomationList::AutomationList (Parameter id, double min_val, double max_val, double default_val)
: _parameter(id)
+ , _interpolation(Linear)
, _curve(new Curve(*this))
{
_parameter = id;
@@ -81,6 +83,7 @@ AutomationList::AutomationList (Parameter id, double min_val, double max_val, do
AutomationList::AutomationList (const AutomationList& other)
: _parameter(other._parameter)
+ , _interpolation(Linear)
, _curve(new Curve(*this))
{
_frozen = 0;
@@ -108,6 +111,7 @@ AutomationList::AutomationList (const AutomationList& other)
AutomationList::AutomationList (const AutomationList& other, double start, double end)
: _parameter(other._parameter)
+ , _interpolation(Linear)
, _curve(new Curve(*this))
{
_frozen = 0;
@@ -146,7 +150,8 @@ AutomationList::AutomationList (const AutomationList& other, double start, doubl
* in or below the <AutomationList> node. It is used if \a id is non-null.
*/
AutomationList::AutomationList (const XMLNode& node, Parameter id)
- : _curve(new Curve(*this))
+ : _interpolation(Linear)
+ , _curve(new Curve(*this))
{
_frozen = 0;
_changed_when_thawed = false;
@@ -925,6 +930,9 @@ AutomationList::unlocked_eval (double x) const
upos = _events.back()->when;
uval = _events.back()->value;
+ if (_interpolation == Discrete)
+ return lval;
+
/* linear interpolation betweeen the two points
*/
@@ -953,6 +961,22 @@ AutomationList::multipoint_eval (double x) const
double upos, lpos;
double uval, lval;
double fraction;
+
+ /* "Stepped" lookup (no interpolation) */
+ /* FIXME: no cache. significant? */
+ if (_interpolation == Discrete) {
+ const ControlEvent cp (x, 0);
+ TimeComparator cmp;
+ EventList::const_iterator i = lower_bound (_events.begin(), _events.end(), &cp, cmp);
+
+ // shouldn't have made it to multipoint_eval
+ assert(i != _events.end());
+
+ if (i == _events.begin() || (*i)->when == x)
+ return (*i)->value;
+ else
+ return (*(--i))->value;
+ }
/* Only do the range lookup if x is in a different range than last time
* this was called (or if the lookup cache has been marked "dirty" (left<0) */
@@ -1279,6 +1303,8 @@ AutomationList::state (bool full)
root->add_property ("max_yval", buf);
snprintf (buf, sizeof (buf), "%.12g", _max_xval);
root->add_property ("max_xval", buf);
+
+ root->add_property ("interpolation-style", enum_2_string (_interpolation));
if (full) {
root->add_property ("state", auto_state_to_string (_state));
@@ -1438,6 +1464,12 @@ AutomationList::set_state (const XMLNode& node)
warning << "Legacy session: automation list has no automation-id property.";
}
+ if ((prop = node.property (X_("interpolation-style"))) != 0) {
+ _interpolation = (InterpolationStyle)string_2_enum(prop->value(), _interpolation);
+ } else {
+ _interpolation = Linear;
+ }
+
if ((prop = node.property (X_("default"))) != 0){
_default_value = atof (prop->value().c_str());
} else {
diff --git a/libs/ardour/enums.cc b/libs/ardour/enums.cc
index 5a65135f75..faa74860f9 100644
--- a/libs/ardour/enums.cc
+++ b/libs/ardour/enums.cc
@@ -28,6 +28,7 @@
#include <ardour/route_group.h>
#include <ardour/panner.h>
#include <ardour/track.h>
+#include <ardour/midi_track.h>
using namespace std;
using namespace PBD;
@@ -44,6 +45,7 @@ setup_enum_writer ()
AlignStyle _AlignStyle;
MeterPoint _MeterPoint;
TrackMode _TrackMode;
+ NoteMode _NoteMode;
MeterFalloff _MeterFalloff;
MeterHold _MeterHold;
EditMode _EditMode;
@@ -81,6 +83,7 @@ setup_enum_writer ()
RouteGroup::Flag _RouteGroup_Flag;
Region::Flag _Region_Flag;
Track::FreezeState _Track_FreezeState;
+ AutomationList::InterpolationStyle _AutomationList_InterpolationStyle;
#define REGISTER(e) enum_writer->register_distinct (typeid(e).name(), i, s); i.clear(); s.clear()
#define REGISTER_BITS(e) enum_writer->register_bits (typeid(e).name(), i, s); i.clear(); s.clear()
@@ -132,6 +135,10 @@ setup_enum_writer ()
REGISTER_ENUM (Normal);
REGISTER_ENUM (Destructive);
REGISTER (_TrackMode);
+
+ REGISTER_ENUM (Note);
+ REGISTER_ENUM (Percussion);
+ REGISTER (_NoteMode);
REGISTER_ENUM (MeterFalloffOff);
REGISTER_ENUM (MeterFalloffSlowest);
@@ -361,4 +368,9 @@ setup_enum_writer ()
REGISTER_CLASS_ENUM (Track, UnFrozen);
REGISTER (_Track_FreezeState);
+ REGISTER_CLASS_ENUM (AutomationList, Discrete);
+ REGISTER_CLASS_ENUM (AutomationList, Linear);
+ REGISTER_CLASS_ENUM (AutomationList, Curved);
+ REGISTER (_AutomationList_InterpolationStyle);
+
}
diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc
index 6e52bb19c0..f714bf47f9 100644
--- a/libs/ardour/midi_track.cc
+++ b/libs/ardour/midi_track.cc
@@ -161,10 +161,15 @@ MidiTrack::_set_state (const XMLNode& node, bool call_base)
return -1;
}
- if ((prop = node.property (X_("mode"))) != 0) {
- _mode = TrackMode (string_2_enum (prop->value(), _mode));
+ // No destructive MIDI tracks (yet?)
+ _mode = Normal;
+
+ if ((prop = node.property (X_("note-mode"))) != 0) {
+ _note_mode = NoteMode (string_2_enum (prop->value(), _note_mode));
+ cerr << "NOTE MODE: " << prop->value() << " -> " << _note_mode << endl;
} else {
- _mode = Normal;
+ cerr << "NO NOTE MODE" << endl;
+ _note_mode = Note;
}
if ((prop = node.property ("diskstream-id")) == 0) {
@@ -245,7 +250,7 @@ MidiTrack::state(bool full_state)
align_node->add_property (X_("style"), enum_2_string (as));
root.add_child_nocopy (*align_node);
- root.add_property (X_("mode"), enum_2_string (_mode));
+ root.add_property (X_("note-mode"), enum_2_string (_note_mode));
/* we don't return diskstream state because we don't
own the diskstream exclusively. control of the diskstream
@@ -682,7 +687,7 @@ MidiTrack::unfreeze ()
_freeze_record.state = UnFrozen;
FreezeChange (); /* EMIT SIGNAL */
}
-
+#if 0
int
MidiTrack::set_mode (TrackMode m)
{
@@ -701,7 +706,8 @@ MidiTrack::set_mode (TrackMode m)
return 0;
}
-
+#endif
+
/** \return true on success, false on failure (no buffer space left)
*/
bool