summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2007-07-07 03:19:04 +0000
committerDavid Robillard <d@drobilla.net>2007-07-07 03:19:04 +0000
commit68653307e666b8daabd2931ce0731d400d947707 (patch)
tree773e4d462feddba5e0fb6fa1bdebd45eec930e95
parentf87954eeb5d6a2a8b12e681ddb171dc1f6d76095 (diff)
Note modes: note, percussion.
Percussion tracks display diamonds. Separated/fixed MIDI and audio mode menus. CC automation modes: discrete, line. Bar controllers follow setting (hard steps or line) on playback. Sent CC data is always discrete (line not implemented yet). Discrete tracks show no lines, and always show control points. Separated ControlPoint from AutomationLine. Added some basic information (range) to Parameter (to be fleshed out..). git-svn-id: svn://localhost/ardour2/trunk@2123 d708f5d6-7413-0410-9779-e7cbd77b26cf
-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