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();
58 AutomationRegionView::init (Gdk::Color
const & basic_color
, bool /*wfd*/)
60 _enable_display
= false;
62 RegionView::init(basic_color
, false);
64 compute_colors (basic_color
);
66 reset_width_dependent_items ((double) _region
->length() / samples_per_unit
);
68 set_height (trackview
.current_height());
72 _enable_display
= true;
76 AutomationRegionView::create_line (boost::shared_ptr
<ARDOUR::AutomationList
> list
)
78 _line
= boost::shared_ptr
<AutomationLine
> (new MidiAutomationLine(
79 ARDOUR::EventTypeMap::instance().to_symbol(list
->parameter()),
80 trackview
, *get_canvas_group(), list
,
81 boost::dynamic_pointer_cast
<ARDOUR::MidiRegion
> (_region
),
85 _line
->set_height ((uint32_t)rint(trackview
.current_height() - NAME_HIGHLIGHT_SIZE
));
87 _line
->show_all_control_points();
88 _line
->set_maximum_time (_region
->length());
89 _line
->set_offset (_region
->start ());
93 AutomationRegionView::canvas_event (GdkEvent
* ev
)
95 PublicEditor
& e
= trackview
.editor ();
97 if (ev
->type
== GDK_BUTTON_PRESS
&& e
.current_mouse_mode() == Editing::MouseObject
) {
99 /* XXX: icky dcast to Editor */
100 e
.drags()->set (new RubberbandSelectDrag (dynamic_cast<Editor
*> (&e
), group
), ev
);
102 } else if (ev
->type
== GDK_BUTTON_RELEASE
) {
104 if (trackview
.editor().drags()->active() && trackview
.editor().drags()->end_grab (ev
)) {
108 double x
= ev
->button
.x
;
109 double y
= ev
->button
.y
;
111 /* convert to item coordinates in the time axis view */
112 automation_view()->canvas_display()->w2i (x
, y
);
116 y
= min (y
, _height
- NAME_HIGHLIGHT_SIZE
);
118 add_automation_event (ev
, trackview
.editor().pixel_to_frame (x
) - _region
->position(), y
);
124 /** @param when Position in frames, where 0 is the start of the region.
125 * @param y y position, relative to our TimeAxisView.
128 AutomationRegionView::add_automation_event (GdkEvent
*, framepos_t when
, double y
)
131 boost::shared_ptr
<Evoral::Control
> c
= _region
->control(_parameter
, true);
132 boost::shared_ptr
<ARDOUR::AutomationControl
> ac
133 = boost::dynamic_pointer_cast
<ARDOUR::AutomationControl
>(c
);
135 create_line(ac
->alist());
139 AutomationTimeAxisView
* const view
= automation_view ();
141 /* compute vertical fractional position */
143 const double h
= trackview
.current_height() - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE
- 2;
148 double when_d
= when
;
149 _line
->view_to_model_coord (when_d
, y
);
151 view
->session()->begin_reversible_command (_("add automation event"));
152 XMLNode
& before
= _line
->the_list()->get_state();
154 _line
->the_list()->add (when_d
, y
);
156 XMLNode
& after
= _line
->the_list()->get_state();
159 boost::shared_ptr
<ARDOUR::MidiRegion
> mr
= boost::dynamic_pointer_cast
<ARDOUR::MidiRegion
> (_region
);
162 view
->session()->commit_reversible_command (
163 new MementoCommand
<ARDOUR::AutomationList
> (new ARDOUR::MidiAutomationListBinder (mr
->midi_source(), _parameter
), &before
, &after
)
167 view
->session()->set_dirty ();
171 AutomationRegionView::set_height (double h
)
173 RegionView::set_height(h
);
176 _line
->set_height ((uint32_t)rint(h
- NAME_HIGHLIGHT_SIZE
));
181 AutomationRegionView::set_position (framepos_t pos
, void* src
, double* ignored
)
184 _line
->set_maximum_time (_region
->length ());
187 return RegionView::set_position(pos
, src
, ignored
);
192 AutomationRegionView::reset_width_dependent_items (double pixel_width
)
194 RegionView::reset_width_dependent_items(pixel_width
);
203 AutomationRegionView::region_resized (const PBD::PropertyChange
& what_changed
)
205 RegionView::region_resized (what_changed
);
211 if (what_changed
.contains (ARDOUR::Properties::start
)) {
212 _line
->set_offset (_region
->start ());
215 if (what_changed
.contains (ARDOUR::Properties::length
)) {
216 _line
->set_maximum_time (_region
->length());
222 AutomationRegionView::entered (bool)
225 _line
->track_entered();
231 AutomationRegionView::exited ()
234 _line
->track_exited();