ardour
automation_region_view.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2007 Paul Davis
3  Author: David Robillard
4 
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.
9 
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.
14 
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.
18 */
19 
20 #include <utility>
21 
22 #include "pbd/memento_command.h"
23 
25 #include "ardour/event_type_map.h"
27 #include "ardour/midi_region.h"
28 #include "ardour/session.h"
29 
30 #include "gtkmm2ext/keyboard.h"
31 
32 #include "ardour_ui.h"
33 #include "automation_region_view.h"
34 #include "editing.h"
35 #include "editor.h"
36 #include "editor_drag.h"
37 #include "gui_thread.h"
38 #include "midi_automation_line.h"
39 #include "public_editor.h"
40 
41 #include "i18n.h"
42 
43 AutomationRegionView::AutomationRegionView (ArdourCanvas::Container* parent,
44  AutomationTimeAxisView& time_axis,
46  const Evoral::Parameter& param,
48  double spu,
49  uint32_t basic_color)
50  : RegionView(parent, time_axis, region, spu, basic_color, true)
51  , _region_relative_time_converter(region->session().tempo_map(), region->position())
52  , _source_relative_time_converter(region->session().tempo_map(), region->position() - region->start())
53  , _parameter(param)
54 {
55  if (list) {
56  assert(list->parameter() == param);
57  create_line(list);
58  }
59 
60  group->raise_to_top();
61 
63  boost::bind (&AutomationRegionView::mouse_mode_changed, this),
64  gui_context ());
65 }
66 
68 {
69  RegionViewGoingAway (this); /* EMIT_SIGNAL */
70 }
71 
72 void
74 {
75  _enable_display = false;
76 
77  RegionView::init (false);
78 
80 
82 
83  fill_color_name = "midi frame base";
84  set_colors ();
85 
86  _enable_display = true;
87 }
88 
89 void
91 {
93  ARDOUR::EventTypeMap::instance().to_symbol(list->parameter()),
94  trackview, *get_canvas_group(), list,
96  _parameter,
98  _line->set_colors();
99  _line->set_height ((uint32_t)rint(trackview.current_height() - 2.5 - NAME_HIGHLIGHT_SIZE));
102  _line->set_offset (_region->start ());
103 }
104 
105 uint32_t
107 {
108  const std::string mod_name = (_dragging ? "dragging region" :
109  trackview.editor().internal_editing() ? "editable region" :
110  "midi frame base");
111  if (_selected) {
112  return ARDOUR_UI::config()->color_mod ("selected region base", mod_name);
113  } else if (high_enough_for_name || !ARDOUR_UI::config()->get_color_regions_using_track_color()) {
114  return ARDOUR_UI::config()->color_mod ("midi frame base", mod_name);
115  }
116  return ARDOUR_UI::config()->color_mod (fill_color, mod_name);
117 }
118 
119 void
121 {
122  // Adjust frame colour (become more transparent for internal tools)
123  set_frame_color();
124 }
125 
126 bool
128 {
129  if (in_destructor) {
130  return false;
131  }
132 
133  PublicEditor& e = trackview.editor ();
134 
136  ev->type == GDK_BUTTON_RELEASE &&
137  e.current_mouse_mode() == Editing::MouseDraw &&
138  !e.drags()->active()) {
139 
140  double x = ev->button.x;
141  double y = ev->button.y;
142 
143  /* convert to item coordinates in the time axis view */
144  automation_view()->canvas_display()->canvas_to_item (x, y);
145 
146  /* clamp y */
147  y = std::max (y, 0.0);
148  y = std::min (y, _height - NAME_HIGHLIGHT_SIZE);
149 
150  /* guard points only if primary modifier is used */
151  bool with_guard_points = Gtkmm2ext::Keyboard::modifier_state_equals (ev->button.state, Gtkmm2ext::Keyboard::PrimaryModifier);
152  add_automation_event (ev, e.pixel_to_sample (x) - _region->position() + _region->start(), y, with_guard_points);
153  return true;
154  }
155 
156  return RegionView::canvas_group_event (ev);
157 }
158 
162 void
163 AutomationRegionView::add_automation_event (GdkEvent *, framepos_t when, double y, bool with_guard_points)
164 {
165  if (!_line) {
169  assert(ac);
170  create_line(ac->alist());
171  }
172  assert(_line);
173 
174  AutomationTimeAxisView* const view = automation_view ();
175 
176  /* compute vertical fractional position */
177 
179  y = 1.0 - (y / h);
180 
181  /* snap frame */
182 
183  when = snap_frame_to_frame (when - _region->start ()) + _region->start ();
184 
185  /* map using line */
186 
187  double when_d = when;
188  _line->view_to_model_coord (when_d, y);
189 
190  view->editor().begin_reversible_command (_("add automation event"));
191  XMLNode& before = _line->the_list()->get_state();
192 
193  _line->the_list()->add (when_d, y, with_guard_points, false);
194 
195  XMLNode& after = _line->the_list()->get_state();
196 
199 
200  view->session()->set_dirty ();
201 }
202 
203 bool
205  unsigned paste_count,
206  float times,
208 {
209  AutomationTimeAxisView* const view = automation_view();
211 
212  if (view->session()->transport_rolling() && my_list->automation_write()) {
213  /* do not paste if this control is in write mode and we're rolling */
214  return false;
215  }
216 
217  /* add multi-paste offset if applicable */
218  pos += view->editor().get_paste_offset(
219  pos, paste_count, _source_relative_time_converter.to(slist->length()));
220 
221  const double model_pos = _source_relative_time_converter.from(
223 
224  XMLNode& before = my_list->get_state();
225  my_list->paste(*slist, model_pos, times);
226  view->session()->add_command(
228 
229  return true;
230 }
231 
232 void
234 {
236 
237  if (_line) {
238  _line->set_height ((uint32_t)rint(h - 2.5 - NAME_HIGHLIGHT_SIZE));
239  }
240 }
241 
242 bool
243 AutomationRegionView::set_position (framepos_t pos, void* src, double* ignored)
244 {
245  if (_line) {
247  }
248 
249  return RegionView::set_position(pos, src, ignored);
250 }
251 
252 
253 void
255 {
257 
258  if (_line) {
259  _line->reset();
260  }
261 }
262 
263 
264 void
266 {
267  RegionView::region_resized (what_changed);
268 
269  if (what_changed.contains (ARDOUR::Properties::position)) {
271  }
272 
273  if (what_changed.contains (ARDOUR::Properties::start) ||
274  what_changed.contains (ARDOUR::Properties::position)) {
276  }
277 
278  if (!_line) {
279  return;
280  }
281 
282  if (what_changed.contains (ARDOUR::Properties::start)) {
283  _line->set_offset (_region->start ());
284  }
285 
286  if (what_changed.contains (ARDOUR::Properties::length)) {
288  }
289 }
290 
291 
292 void
294 {
295  if (_line) {
296  _line->track_entered();
297  }
298 }
299 
300 
301 void
303 {
304  if (_line) {
305  _line->track_exited();
306  }
307 }
bool transport_rolling() const
Definition: session.h:592
bool active() const
Definition: editor_drag.h:74
ArdourCanvas::Item * get_canvas_group()
static PBD::Signal1< void, RegionView * > RegionViewGoingAway
Definition: region_view.h:100
AutomationTimeAxisView * automation_view() const
virtual void region_resized(const PBD::PropertyChange &)
Definition: region_view.cc:405
PublicEditor & editor() const
bool in_destructor
Definition: region_view.h:172
boost::shared_ptr< ARDOUR::Region > _region
Definition: region_view.h:159
virtual Editing::MouseMode current_mouse_mode() const =0
bool paste(framepos_t pos, unsigned paste_count, float times, boost::shared_ptr< const ARDOUR::AutomationList > slist)
void create_line(boost::shared_ptr< ARDOUR::AutomationList > list)
shared_ptr< T > dynamic_pointer_cast(shared_ptr< U > const &r)
Definition: shared_ptr.hpp:396
void view_to_model_coord(double &x, double &y) const
boost::shared_ptr< ARDOUR::AutomationList > the_list() const
bool _enable_display
see StreamView::redisplay_diskstream()
Definition: region_view.h:170
void add_command(Command *const cmd)
Definition: session.h:787
Representation of the interface of the Editor class.
TimeAxisView & trackview
std::string fill_color_name
LIBARDOUR_API PBD::PropertyDescriptor< framepos_t > start
Definition: region.cc:63
uint32_t current_height() const
#define invalidator(x)
Definition: gui_thread.h:40
boost::shared_ptr< AutomationLine > _line
PBD::ScopedConnection _mouse_mode_connection
uint32_t get_fill_color() const
void region_resized(const PBD::PropertyChange &)
bool set_position(framepos_t pos, void *src, double *delta=0)
Definition: region_view.cc:464
#define _(Text)
Definition: i18n.h:11
bool canvas_group_event(GdkEvent *)
Definition: region_view.cc:217
virtual DragManager * drags() const =0
void set_offset(ARDOUR::framecnt_t)
static uint32_t PrimaryModifier
Definition: keyboard.h:55
virtual void init(bool wait_for_data)
Definition: region_view.cc:149
ArdourCanvas::Container * canvas_display()
double length() const
ARDOUR::frameoffset_t snap_frame_to_frame(ARDOUR::frameoffset_t) const
Definition: region_view.cc:945
ARDOUR::Session * session() const
Definition: axis_view.h:52
virtual void begin_reversible_command(std::string cmd_name)=0
#define gui_context()
Definition: gui_thread.h:36
virtual void set_frame_color()
virtual void commit_reversible_command()=0
virtual boost::shared_ptr< Evoral::Control > control(const Evoral::Parameter &id, bool create=false)=0
double from(framepos_t frames) const
bool canvas_group_event(GdkEvent *ev)
bool automation_write() const
static EventTypeMap & instance()
virtual void reset_width_dependent_items(double pixel_width)
Definition: region_view.cc:432
const Parameter & parameter() const
Evoral::Parameter _parameter
bool _selected
Definition: selectable.h:45
framepos_t position() const
Definition: region.h:112
ARDOUR::DoubleBeatsFramesConverter _region_relative_time_converter
void reset_width_dependent_items(double pixel_width)
virtual bool internal_editing() const =0
virtual framecnt_t get_paste_offset(framepos_t pos, unsigned paste_count, framecnt_t duration)=0
virtual void set_height(double)
Definition: region_view.cc:730
virtual MementoCommandBinder< ARDOUR::AutomationList > * memento_command_binder()
Definition: xml++.h:95
ArdourCanvas::Color color_mod(std::string const &color, std::string const &modifier) const
Definition: ui_config.cc:555
LIBARDOUR_API PBD::PropertyDescriptor< framepos_t > position
Definition: region.cc:65
static UIConfiguration * config()
Definition: ardour_ui.h:188
framepos_t to(double beats) const
bool paste(const ControlList &, double position, float times)
void set_maximum_time(ARDOUR::framecnt_t)
virtual framepos_t pixel_to_sample(double pixel) const =0
ArdourCanvas::Container * group
bool contains(PropertyDescriptor< T > p) const
boost::shared_ptr< AutomationList > alist() const
void add_automation_event(GdkEvent *event, framepos_t when, double y, bool with_guard_points)
framecnt_t length() const
Definition: region.h:114
framepos_t start() const
Definition: region.h:113
void set_height(guint32)
static bool modifier_state_equals(guint state, ModifierMask)
Definition: keyboard.cc:526
LIBGTKMM2EXT_API int pixel_width(const std::string &str, Pango::FontDescription &font)
bool set_position(framepos_t pos, void *src, double *ignored)
virtual void add(double when, double value, bool with_guards=true, bool with_default=true)
AutomationRegionView(ArdourCanvas::Container *, AutomationTimeAxisView &, boost::shared_ptr< ARDOUR::Region >, const Evoral::Parameter &parameter, boost::shared_ptr< ARDOUR::AutomationList >, double initial_samples_per_pixel, uint32_t basic_color)
int64_t framepos_t
PBD::Signal0< void > MouseModeChanged
virtual void set_colors()
Definition: region_view.cc:514
ARDOUR::DoubleBeatsFramesConverter _source_relative_time_converter
static double NAME_HIGHLIGHT_SIZE
void set_visibility(VisibleAspects)
LIBARDOUR_API PBD::PropertyDescriptor< framecnt_t > length
Definition: region.cc:64