2 Copyright (C) 2007 Paul Davis
3 Author: David Robillard
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "pbd/memento_command.h"
21 #include "ardour/automation_control.h"
22 #include "ardour/event_type_map.h"
23 #include "ardour/session.h"
24 #include "ardour/source.h"
25 #include "ardour/midi_automation_list_binder.h"
26 #include "ardour/midi_region.h"
28 #include "automation_region_view.h"
29 #include "gui_thread.h"
30 #include "public_editor.h"
31 #include "midi_automation_line.h"
32 #include "editor_drag.h"
38 AutomationRegionView::AutomationRegionView (ArdourCanvas::Group
* parent
,
39 AutomationTimeAxisView
& time_axis
,
40 boost::shared_ptr
<ARDOUR::Region
> region
,
41 const Evoral::Parameter
& param
,
42 boost::shared_ptr
<ARDOUR::AutomationList
> list
,
44 Gdk::Color
const & basic_color
)
45 : RegionView(parent
, time_axis
, region
, spu
, basic_color
, true)
49 assert(list
->parameter() == param
);
53 group
->signal_event().connect (sigc::mem_fun (this, &AutomationRegionView::canvas_event
), false);
54 group
->raise_to_top();
57 AutomationRegionView::~AutomationRegionView ()
62 AutomationRegionView::init (Gdk::Color
const & basic_color
, bool /*wfd*/)
64 _enable_display
= false;
66 RegionView::init(basic_color
, false);
68 compute_colors (basic_color
);
70 reset_width_dependent_items ((double) _region
->length() / samples_per_unit
);
72 set_height (trackview
.current_height());
76 _enable_display
= true;
80 AutomationRegionView::create_line (boost::shared_ptr
<ARDOUR::AutomationList
> list
)
82 _line
= boost::shared_ptr
<AutomationLine
> (new MidiAutomationLine(
83 ARDOUR::EventTypeMap::instance().to_symbol(list
->parameter()),
84 trackview
, *get_canvas_group(), list
,
85 boost::dynamic_pointer_cast
<ARDOUR::MidiRegion
> (_region
),
87 &_source_relative_time_converter
));
89 _line
->set_height ((uint32_t)rint(trackview
.current_height() - NAME_HIGHLIGHT_SIZE
));
91 _line
->show_all_control_points();
92 _line
->set_maximum_time (_region
->length());
93 _line
->set_offset (_region
->start ());
97 AutomationRegionView::canvas_event (GdkEvent
* ev
)
99 PublicEditor
& e
= trackview
.editor ();
101 if (ev
->type
== GDK_BUTTON_PRESS
&& e
.current_mouse_mode() == Editing::MouseObject
) {
103 /* XXX: icky dcast to Editor */
104 e
.drags()->set (new RubberbandSelectDrag (dynamic_cast<Editor
*> (&e
), group
), ev
);
106 } else if (ev
->type
== GDK_BUTTON_RELEASE
) {
108 if (trackview
.editor().drags()->active() && trackview
.editor().drags()->end_grab (ev
)) {
112 double x
= ev
->button
.x
;
113 double y
= ev
->button
.y
;
115 /* convert to item coordinates in the time axis view */
116 automation_view()->canvas_display()->w2i (x
, y
);
120 y
= min (y
, _height
- NAME_HIGHLIGHT_SIZE
);
122 add_automation_event (ev
, trackview
.editor().pixel_to_frame (x
) - _region
->position() + _region
->start(), y
);
128 /** @param when Position in frames, where 0 is the start of the region.
129 * @param y y position, relative to our TimeAxisView.
132 AutomationRegionView::add_automation_event (GdkEvent
*, framepos_t when
, double y
)
135 boost::shared_ptr
<Evoral::Control
> c
= _region
->control(_parameter
, true);
136 boost::shared_ptr
<ARDOUR::AutomationControl
> ac
137 = boost::dynamic_pointer_cast
<ARDOUR::AutomationControl
>(c
);
139 create_line(ac
->alist());
143 AutomationTimeAxisView
* const view
= automation_view ();
145 /* compute vertical fractional position */
147 const double h
= trackview
.current_height() - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE
- 2;
152 double when_d
= when
;
153 _line
->view_to_model_coord (when_d
, y
);
155 view
->session()->begin_reversible_command (_("add automation event"));
156 XMLNode
& before
= _line
->the_list()->get_state();
158 _line
->the_list()->add (when_d
, y
);
160 XMLNode
& after
= _line
->the_list()->get_state();
163 boost::shared_ptr
<ARDOUR::MidiRegion
> mr
= boost::dynamic_pointer_cast
<ARDOUR::MidiRegion
> (_region
);
166 view
->session()->commit_reversible_command (
167 new MementoCommand
<ARDOUR::AutomationList
> (new ARDOUR::MidiAutomationListBinder (mr
->midi_source(), _parameter
), &before
, &after
)
171 view
->session()->set_dirty ();
175 AutomationRegionView::set_height (double h
)
177 RegionView::set_height(h
);
180 _line
->set_height ((uint32_t)rint(h
- NAME_HIGHLIGHT_SIZE
));
185 AutomationRegionView::set_position (framepos_t pos
, void* src
, double* ignored
)
188 _line
->set_maximum_time (_region
->length ());
191 return RegionView::set_position(pos
, src
, ignored
);
196 AutomationRegionView::reset_width_dependent_items (double pixel_width
)
198 RegionView::reset_width_dependent_items(pixel_width
);
207 AutomationRegionView::region_resized (const PBD::PropertyChange
& what_changed
)
209 RegionView::region_resized (what_changed
);
215 if (what_changed
.contains (ARDOUR::Properties::start
)) {
216 _line
->set_offset (_region
->start ());
219 if (what_changed
.contains (ARDOUR::Properties::length
)) {
220 _line
->set_maximum_time (_region
->length());
226 AutomationRegionView::entered (bool)
229 _line
->track_entered();
235 AutomationRegionView::exited ()
238 _line
->track_exited();