ardour
note_base.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 <iostream>
21 
22 #include "gtkmm2ext/keyboard.h"
23 
24 #include "evoral/Note.hpp"
25 
26 #include "canvas/text.h"
27 
28 #include "note_base.h"
29 #include "public_editor.h"
30 #include "editing_syms.h"
31 #include "keyboard.h"
32 #include "midi_region_view.h"
33 
34 using namespace std;
35 using namespace Gtkmm2ext;
36 using ARDOUR::MidiModel;
37 using namespace ArdourCanvas;
38 
39 PBD::Signal1<void,NoteBase*> NoteBase::NoteBaseDeleted;
40 
42 const uint32_t NoteBase::midi_channel_colors[16] = {
43  0xd32d2dff, 0xd36b2dff, 0xd3972dff, 0xd3d12dff,
44  0xa0d32dff, 0x7dd32dff, 0x2dd45eff, 0x2dd3c4ff,
45  0x2da5d3ff, 0x2d6fd3ff, 0x432dd3ff, 0x662dd3ff,
46  0x832dd3ff, 0xa92dd3ff, 0xd32dbfff, 0xd32d67ff
47  };
48 
49 NoteBase::NoteBase(MidiRegionView& region, bool with_events, const boost::shared_ptr<NoteType> note)
50  : _region(region)
51  , _item (0)
52  , _text(0)
53  , _state(None)
54  , _note(note)
55  , _with_events (with_events)
56  , _selected(false)
57  , _valid (true)
58  , _mouse_x_fraction (-1.0)
59  , _mouse_y_fraction (-1.0)
60 {
61 }
62 
64 {
65  NoteBaseDeleted (this);
66 
67  delete _text;
68 }
69 
70 void
71 NoteBase::set_item (Item* item)
72 {
73  _item = item;
74  _item->set_data ("notebase", this);
75 
76  if (_with_events) {
77  _item->Event.connect (sigc::mem_fun (*this, &NoteBase::event_handler));
78  }
79 }
80 
81 void
83 {
84  _valid = false;
85 }
86 
87 void
89 {
90  _valid = true;
91 }
92 
93 void
95 {
96  if (!_text) {
97  _text = new Text (_item->parent ());
98  _text->set_ignore_events (true);
99  _text->set_color (ARDOUR_UI::config()->color_mod ("midi note velocity text", "midi note velocity text"));
100  _text->set_alignment (Pango::ALIGN_CENTER);
101  }
102 
103  _text->set_x_position ((x0() + x1()) / 2);
104  _text->set_y_position ((y0() + y1()) / 2);
105  ostringstream velo(ios::ate);
106  velo << int(_note->velocity());
107  _text->set (velo.str ());
108  _text->show();
109  _text->raise_to_top();
110 }
111 
112 void
114 {
115  delete _text;
116  _text = 0;
117 }
118 
119 void
121 {
122  // make note change its color if its channel is not marked active
123  if ( (selection & (1 << _note->channel())) == 0 ) {
124  set_fill_color(ARDOUR_UI::config()->color ("midi note inactive channel"));
125  set_outline_color(calculate_outline(ARDOUR_UI::config()->color ("midi note inactive channel"),
126  _selected));
127  } else {
128  // set the color according to the notes selection state
130  }
131  // this forces the item to update..... maybe slow...
132  _item->hide();
133  _item->show();
134 }
135 
136 void
138 {
139  _region.note_selected(this, true);
140  _region.change_channel(channel);
141 }
142 
143 void
145 {
146  if (!_note) {
147  return;
148  }
149 
152 
154 }
155 
156 #define SCALE_USHORT_TO_UINT8_T(x) ((x) / 257)
157 
158 uint32_t
160 {
161  using namespace ARDOUR;
162 
163  ColorMode mode = _region.color_mode();
164 
165  const uint8_t min_opacity = 15;
166  uint8_t opacity = std::max(min_opacity, uint8_t(_note->velocity() + _note->velocity()));
167 
168  switch (mode) {
169  case TrackColor:
170  {
172  return UINT_INTERPOLATE (UINT_RGBA_CHANGE_A (color, opacity),
173  ARDOUR_UI::config()->color ("midi note selected"),
174  0.5);
175  }
176 
177  case ChannelColors:
179  ARDOUR_UI::config()->color ("midi note selected"), 0.5);
180 
181  default:
182  return meter_style_fill_color(_note->velocity(), selected());
183  };
184 
185  return 0;
186 }
187 
188 void
190 {
191  double ix, iy;
192  bool set_cursor = false;
193 
194  switch (ev->type) {
195  case GDK_MOTION_NOTIFY:
196  ix = ev->motion.x;
197  iy = ev->motion.y;
198  set_cursor = true;
199  break;
200  case GDK_ENTER_NOTIFY:
201  ix = ev->crossing.x;
202  iy = ev->crossing.y;
203  set_cursor = true;
204  break;
205  case GDK_BUTTON_PRESS:
206  case GDK_BUTTON_RELEASE:
207  ix = ev->button.x;
208  iy = ev->button.y;
209  break;
210  default:
211  _mouse_x_fraction = -1.0;
212  _mouse_y_fraction = -1.0;
213  return;
214  }
215 
216  boost::optional<ArdourCanvas::Rect> bbox = _item->bounding_box ();
217  assert (bbox);
218 
219  _item->canvas_to_item (ix, iy);
220  /* XXX: CANVAS */
221  /* hmm, something wrong here. w2i should give item-local coordinates
222  but it doesn't. for now, finesse this.
223  */
224  ix = ix - bbox.get().x0;
225  iy = iy - bbox.get().y0;
226 
227  /* fraction of width/height */
228  double xf;
229  double yf;
230  bool notify = false;
231 
232  xf = ix / bbox.get().width ();
233  yf = iy / bbox.get().height ();
234 
235  if (xf != _mouse_x_fraction || yf != _mouse_y_fraction) {
236  notify = true;
237  }
238 
239  _mouse_x_fraction = xf;
240  _mouse_y_fraction = yf;
241 
242  if (notify) {
243  if (big_enough_to_trim()) {
245  } else {
246  /* pretend the mouse is in the middle, because this is not big enough
247  to trim right now.
248  */
249  _region.note_mouse_position (0.5, 0.5, set_cursor);
250  }
251  }
252 }
253 
254 bool
256 {
258  if (!editor.internal_editing()) {
259  return false;
260  }
261 
262  switch (ev->type) {
263  case GDK_ENTER_NOTIFY:
264  _region.note_entered (this);
265  set_mouse_fractions (ev);
266  break;
267 
268  case GDK_LEAVE_NOTIFY:
269  set_mouse_fractions (ev);
270  _region.note_left (this);
271  break;
272 
273  case GDK_MOTION_NOTIFY:
274  set_mouse_fractions (ev);
275  break;
276 
277  case GDK_BUTTON_PRESS:
278  set_mouse_fractions (ev);
279  break;
280 
281  case GDK_BUTTON_RELEASE:
282  set_mouse_fractions (ev);
283  break;
284 
285  default:
286  break;
287  }
288 
289  return editor.canvas_note_event (ev, _item);
290 }
291 
292 bool
294 {
295  return (_mouse_x_fraction >= 0.0 && _mouse_x_fraction < 0.25) ||
296  (_mouse_x_fraction >= 0.75 && _mouse_x_fraction < 1.0);
297 }
298 
299 bool
301 {
302  return (x1() - x0()) > 10;
303 }
304 
void note_mouse_position(float xfraction, float yfraction, bool can_set_cursor=true)
float _mouse_y_fraction
Definition: note_base.h:150
ArdourCanvas::Color color(const std::string &, bool *failed=0) const
Definition: ui_config.cc:567
virtual ArdourCanvas::Coord x1() const =0
TimeAxisView & get_time_axis_view() const
virtual ~NoteBase()
Definition: note_base.cc:63
static const uint32_t midi_channel_colors[16]
hue circle divided into 16 equal-looking parts, courtesy Thorsten Wilms
Definition: note_base.h:132
void on_channel_selection_change(uint16_t selection)
Definition: note_base.cc:120
PublicEditor & editor() const
void note_left(NoteBase *ev)
static uint32_t calculate_outline(uint32_t color, bool selected=false)
calculate outline colors from fill colors of notes
Definition: note_base.h:123
MidiRegionView & _region
Definition: note_base.h:140
static PBD::Signal1< void, NoteBase * > NoteBaseDeleted
Definition: note_base.h:65
virtual ArdourCanvas::Coord x0() const =0
virtual ArdourCanvas::Coord y1() const =0
virtual ArdourCanvas::Coord y0() const =0
uint32_t get_region_color() const
Definition: streamview.h:89
ColorMode
Definition: types.h:215
void validate()
Definition: note_base.cc:88
NoteBase(MidiRegionView &region, bool, const boost::shared_ptr< NoteType > note=boost::shared_ptr< NoteType >())
Definition: note_base.cc:49
virtual void set_outline_color(uint32_t c)=0
Representation of the interface of the Editor class.
Definition: Beats.hpp:239
void note_entered(NoteBase *ev)
virtual bool canvas_note_event(GdkEvent *event, ArdourCanvas::Item *)=0
bool _with_events
Definition: note_base.h:145
#define UINT_RGBA_CHANGE_A(x, a)
Definition: rgb_macros.h:64
MidiStreamView * midi_stream_view() const
float _mouse_x_fraction
Definition: note_base.h:149
void note_selected(NoteBase *ev, bool add, bool extend=false)
ArdourCanvas::Item * item() const
Definition: note_base.h:63
void show_velocity()
Definition: note_base.cc:94
uint32_t base_color()
Definition: note_base.cc:159
ARDOUR::ColorMode color_mode() const
Definition: amp.h:29
static uint32_t meter_style_fill_color(uint8_t vel, bool selected)
Definition: note_base.h:106
void set_selected(bool yn)
Definition: note_base.cc:144
void hide_velocity()
Definition: note_base.cc:113
virtual void set_fill_color(uint32_t c)=0
ArdourCanvas::Item * _item
Definition: note_base.h:141
ArdourCanvas::Text * _text
Definition: note_base.h:142
bool event_handler(GdkEvent *)
Definition: note_base.cc:255
bool mouse_near_ends() const
Definition: note_base.cc:293
virtual bool internal_editing() const =0
void change_channel(uint8_t channel)
static UIConfiguration * config()
Definition: ardour_ui.h:188
bool _valid
Definition: note_base.h:148
void invalidate()
Definition: note_base.cc:82
bool selected() const
Definition: note_base.h:74
bool _selected
Definition: note_base.h:147
#define UINT_INTERPOLATE(c1, c2, t)
Definition: rgb_macros.h:70
const boost::shared_ptr< NoteType > _note
Definition: note_base.h:144
void on_channel_change(uint8_t channel)
Definition: note_base.cc:137
virtual bool big_enough_to_trim() const
Definition: note_base.cc:300
void set_item(ArdourCanvas::Item *)
Definition: note_base.cc:71
void set_mouse_fractions(GdkEvent *)
Definition: note_base.cc:189
LIBARDOUR_API PBD::PropertyDescriptor< bool > color
Definition: route_group.cc:50