ardour
midi_region_view.h
Go to the documentation of this file.
1 /*
2  Copyright (C) 2001-2011 Paul Davis
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18 
19 #ifndef __gtk_ardour_midi_region_view_h__
20 #define __gtk_ardour_midi_region_view_h__
21 
22 #include <string>
23 #include <vector>
24 #include <stdint.h>
25 
26 #include "pbd/signals.h"
27 
28 #include "ardour/midi_model.h"
29 #include "ardour/types.h"
30 
31 #include "editing.h"
32 #include "region_view.h"
33 #include "midi_time_axis.h"
34 #include "time_axis_view_item.h"
35 #include "automation_line.h"
36 #include "enums.h"
37 
38 namespace ARDOUR {
39  class MidiRegion;
40  class MidiModel;
41  class Filter;
42 };
43 
44 namespace MIDI {
45  namespace Name {
46  struct PatchPrimaryKey;
47  };
48 };
49 
50 class SysEx;
51 class NoteBase;
52 class Note;
53 class Hit;
54 class MidiTimeAxisView;
55 class GhostRegion;
58 class MidiCutBuffer;
59 class MidiListEditor;
60 class EditNoteDialog;
61 class PatchChange;
62 class ItemCounts;
63 class CursorContext;
64 
65 class MidiRegionView : public RegionView
66 {
67 public:
70 
71  MidiRegionView (ArdourCanvas::Container* parent,
74  double samples_per_pixel,
75  uint32_t basic_color);
76 
77  MidiRegionView (ArdourCanvas::Container* parent,
80  double samples_per_pixel,
81  uint32_t basic_color,
82  bool recording,
84 
85 
86  MidiRegionView (const MidiRegionView& other);
88 
89  ~MidiRegionView ();
90 
91  void init (bool wfd);
92 
94 
95  inline MidiTimeAxisView* midi_view() const
96  { return dynamic_cast<MidiTimeAxisView*>(&trackview); }
97 
99  { return midi_view()->midi_view(); }
100 
101  void step_add_note (uint8_t channel, uint8_t number, uint8_t velocity,
102  Evoral::Beats pos, Evoral::Beats len);
103  void step_sustain (Evoral::Beats beats);
104  void set_height (double);
105  void apply_note_range(uint8_t lowest, uint8_t highest, bool force=false);
106 
107  inline ARDOUR::ColorMode color_mode() const { return midi_view()->color_mode(); }
108 
109  uint32_t get_fill_color() const;
110  void color_handler ();
111 
114  void hide_step_edit_cursor ();
116 
117  void redisplay_model();
118 
120 
121  NoteBase* add_note(const boost::shared_ptr<NoteType> note, bool visible);
122  void resolve_note(uint8_t note_num, Evoral::Beats end_time);
123 
125  bool paste (framepos_t pos, const ::Selection& selection, PasteContext& ctx);
126  void paste_internal (framepos_t pos, unsigned paste_count, float times, const MidiCutBuffer&);
127 
128  void add_canvas_patch_change (ARDOUR::MidiModel::PatchChangePtr patch, const std::string& displaytext, bool);
129 
136  void get_patch_key_at (Evoral::Beats time, uint8_t channel, MIDI::Name::PatchPrimaryKey& key) const;
137 
140  MIDI::Name::PatchPrimaryKey patch_change_to_patch_key (ARDOUR::MidiModel::PatchChangePtr);
141 
146  void change_patch_change (PatchChange& old_patch, const MIDI::Name::PatchPrimaryKey& new_patch);
148 
153 
154  void delete_sysex (SysEx*);
155 
160  void step_patch (PatchChange& patch, bool bank, int delta);
161 
164  void display_patch_changes();
165 
168  void display_sysexes();
169 
170  void begin_write();
171  void end_write();
172  void extend_active_notes();
173 
175 
176  void start_note_diff_command (std::string name = "midi edit");
179  void note_diff_add_note (const boost::shared_ptr<NoteType> note, bool selected, bool show_velocity = false);
180  void note_diff_remove_note (NoteBase* ev);
181 
182  void apply_diff (bool as_subcommand = false);
183  void abort_command();
184 
185  void note_entered(NoteBase* ev);
186  void note_left(NoteBase* ev);
187  void patch_entered (PatchChange *);
188  void patch_left (PatchChange *);
189  void sysex_entered (SysEx* p);
190  void sysex_left (SysEx* p);
191  void note_mouse_position (float xfraction, float yfraction, bool can_set_cursor=true);
192  void unique_select(NoteBase* ev);
193  void note_selected(NoteBase* ev, bool add, bool extend=false);
194  void note_deselected(NoteBase* ev);
195  void delete_selection();
197  size_t selection_size() { return _selection.size(); }
198  void select_all_notes ();
200  void invert_selection ();
201 
202  void move_selection(double dx, double dy, double cumulative_dy);
203  void note_dropped (NoteBase* ev, ARDOUR::frameoffset_t, int8_t d_note);
204 
205  void select_notes (std::list<boost::shared_ptr<NoteType> >);
206  void select_matching_notes (uint8_t notenum, uint16_t channel_mask, bool add, bool extend);
207  void toggle_matching_notes (uint8_t notenum, uint16_t channel_mask);
208 
212  bool note_in_region_range(const boost::shared_ptr<NoteType> note, bool& visible) const;
213 
215  double get_position_pixels();
216 
218  double get_end_position_pixels();
219 
224  void begin_resizing(bool at_front);
225 
226  void update_resizing (NoteBase*, bool, double, bool);
227  void commit_resizing (NoteBase*, bool, double, bool);
228  void abort_resizing ();
229 
233  void change_channel(uint8_t channel);
234 
235  enum MouseState {
242  };
243 
244  MouseState mouse_state() const { return _mouse_state; }
245 
246  struct NoteResizeData {
248  ArdourCanvas::Rectangle *resize_rect;
249  };
250 
255  double snap_to_pixel(double x);
256 
262 
267  return _region->position() + region_beats_to_region_frames (beats);
268  }
271 
277  }
280 
283  }
284 
287  }
288 
290  void goto_next_note (bool add_to_selection);
291  void change_note_lengths (bool, bool, Evoral::Beats beats, bool start, bool end);
292  void change_velocities (bool up, bool fine, bool allow_smush, bool all_together);
293  void transpose (bool up, bool fine, bool allow_smush);
294  void nudge_notes (bool forward, bool fine);
295  void channel_edit ();
296  void velocity_edit ();
297 
298  void show_list_editor ();
299 
300  typedef std::set<NoteBase*> Selection;
301  Selection selection () const {
302  return _selection;
303  }
304 
305  void selection_as_notelist (Notes& selected, bool allow_all_if_none_selected = false);
306 
307  void enable_display (bool);
308 
311 
312  void trim_front_starting ();
313  void trim_front_ending ();
314 
321  void create_note_at (framepos_t t, double y, Evoral::Beats length, bool snap_t);
322 
324 
326 
327 protected:
328  void region_resized (const PBD::PropertyChange&);
329 
330  void set_flags (XMLNode *);
331  void store_flags ();
332 
334 
335  void parameter_changed (std::string const & p);
336 
337 private:
338 
341 
346  static PBD::Signal1<void, MidiRegionView*> SelectionCleared;
349 
354 
355  friend class EditNoteDialog;
356 
362  void start_playing_midi_chord (std::vector<boost::shared_ptr<NoteType> > notes);
363 
364  void clear_events (bool with_selection_signal = true);
365 
366  bool canvas_group_event(GdkEvent* ev);
367  bool note_canvas_event(GdkEvent* ev);
368 
373 
374  void change_note_channel (NoteBase *, int8_t, bool relative=false);
375  void change_note_velocity(NoteBase* ev, int8_t vel, bool relative=false);
376  void change_note_note(NoteBase* ev, int8_t note, bool relative=false);
379  void trim_note(NoteBase* ev, ARDOUR::MidiModel::TimeType start_delta,
380  ARDOUR::MidiModel::TimeType end_delta);
381 
382  void clear_selection_except (NoteBase* ev, bool signal = true);
383  void update_drag_selection (framepos_t start, framepos_t end, double y0, double y1, bool extend);
384  void update_vertical_drag_selection (double last_y, double y, bool extend);
385 
386  void add_to_selection (NoteBase*);
388 
389  void show_verbose_cursor (std::string const &, double, double) const;
391 
393 
396 
397  typedef std::list<NoteBase*> Events;
398  typedef std::vector< boost::shared_ptr<PatchChange> > PatchChanges;
399  typedef std::vector< boost::shared_ptr<SysEx> > SysExes;
400 
403 
405  Events _events;
406  PatchChanges _patch_changes;
407  SysExes _sys_exes;
409  ArdourCanvas::Container* _note_group;
414  ArdourCanvas::Rectangle* _step_edit_cursor;
418 
422  ArdourCanvas::Container* _temporary_note_group;
423 
426 
428  Selection _selection;
429 
431  void time_sort_events ();
432 
434 
437  std::set< boost::shared_ptr<NoteType> > _marked_for_selection;
438 
440  std::set< boost::shared_ptr<NoteType> > _pending_note_selection;
441 
444  std::set< boost::shared_ptr<NoteType> > _marked_for_velocity;
445 
446  std::vector<NoteResizeData *> _resize_data;
447 
450 
452  NoteBase* find_canvas_note (NoteType);
453  Events::iterator _optimization_iterator;
454 
455  void update_note (NoteBase*, bool update_ghost_regions = true);
456  void update_sustained (Note *, bool update_ghost_regions = true);
457  void update_hit (Hit *, bool update_ghost_regions = true);
458 
459  void create_ghost_note (double, double);
460  void update_ghost_note (double, double);
461 
464 
467 
468  void snap_changed ();
470 
471  bool motion (GdkEventMotion*);
472  bool scroll (GdkEventScroll*);
473  bool key_press (GdkEventKey*);
474  bool key_release (GdkEventKey*);
475  bool button_press (GdkEventButton*);
476  bool button_release (GdkEventButton*);
477  bool enter_notify (GdkEventCrossing*);
478  bool leave_notify (GdkEventCrossing*);
479 
480  void drop_down_keys ();
481  void maybe_select_by_position (GdkEventButton* ev, double x, double y);
482  void get_events (Events& e, Evoral::Sequence<Evoral::Beats>::NoteOperator op, uint8_t val, int chan_mask = 0);
483 
484  void display_patch_changes_on_channel (uint8_t, bool);
485 
486  void connect_to_diskstream ();
488 
491 
492  void remove_ghost_note ();
493  void mouse_mode_changed ();
494  void enter_internal ();
495  void leave_internal ();
496 
498 
502  bool _entered;
503 
505 
507 
509 
511 
513  uint16_t get_selected_channels () const;
514 };
515 
516 
517 #endif /* __gtk_ardour_midi_region_view_h__ */
std::set< boost::shared_ptr< NoteType > > _pending_note_selection
MidiTimeAxisView * midi_view() const
PBD::ScopedConnection _clear_midi_selection_connection
void note_mouse_position(float xfraction, float yfraction, bool can_set_cursor=true)
void sysex_entered(SysEx *p)
NoteBase * _ghost_note
void delete_sysex(SysEx *)
void patch_left(PatchChange *)
PBD::ScopedConnection content_connection
void delete_patch_change(PatchChange *)
ARDOUR::MidiModel::NoteDiffCommand * _note_diff_command
void remove_from_selection(NoteBase *)
MIDI::Name::PatchPrimaryKey patch_change_to_patch_key(ARDOUR::MidiModel::PatchChangePtr)
void midi_channel_mode_changed()
void get_patch_key_at(Evoral::Beats time, uint8_t channel, MIDI::Name::PatchPrimaryKey &key) const
std::multiset< NotePtr, EarlierNoteComparator > Notes
Definition: Sequence.hpp:153
boost::shared_ptr< ARDOUR::MidiModel > _model
bool leave_notify(GdkEventCrossing *)
void note_left(NoteBase *ev)
void get_events(Events &e, Evoral::Sequence< Evoral::Beats >::NoteOperator op, uint8_t val, int chan_mask=0)
void update_drag_selection(framepos_t start, framepos_t end, double y0, double y1, bool extend)
boost::shared_ptr< ARDOUR::Region > _region
Definition: region_view.h:159
PatchChanges _patch_changes
uint8_t _current_range_max
void store_flags()
Definition: note.h:32
Events::iterator _optimization_iterator
void clear_selection_except(NoteBase *ev, bool signal=true)
void trim_note(NoteBase *ev, ARDOUR::MidiModel::TimeType start_delta, ARDOUR::MidiModel::TimeType end_delta)
void change_note_lengths(bool, bool, Evoral::Beats beats, bool start, bool end)
void update_ghost_note(double, double)
ARDOUR::BeatsFramesConverter _region_relative_time_converter
void update_sustained(Note *, bool update_ghost_regions=true)
void selection_cleared(MidiRegionView *)
bool scroll(GdkEventScroll *)
NoteBase * channel_selector_scoped_note()
void create_note_at(framepos_t t, double y, Evoral::Beats length, bool snap_t)
void change_note_channel(NoteBase *, int8_t, bool relative=false)
ColorMode
Definition: types.h:215
MidiRegionView(ArdourCanvas::Container *parent, RouteTimeAxisView &tv, boost::shared_ptr< ARDOUR::MidiRegion > r, double samples_per_pixel, uint32_t basic_color)
framepos_t source_beats_to_region_frames(Evoral::Beats beats) const
Evoral::Beats _step_edit_cursor_width
void set_channel_selector_scoped_note(NoteBase *note)
void create_ghost_note(double, double)
TimeAxisView & trackview
Evoral::Sequence< Evoral::Beats >::Notes Notes
framecnt_t _last_display_zoom
void sysex_left(SysEx *p)
void goto_next_note(bool add_to_selection)
ARDOUR::InstrumentInfo & instrument_info() const
void set_flags(XMLNode *)
void step_sustain(Evoral::Beats beats)
bool key_release(GdkEventKey *)
ChannelMode
Definition: types.h:209
Evoral::Beats get_grid_beats(framepos_t pos) const
MouseState _mouse_state
void unique_select(NoteBase *ev)
void note_entered(NoteBase *ev)
Evoral::Beats region_frames_to_region_beats(framepos_t) const
LIBARDOUR_API PBD::PropertyDescriptor< framepos_t > start
Definition: region.cc:63
bool enter_notify(GdkEventCrossing *)
std::vector< NoteResizeData * > _resize_data
void transpose(bool up, bool fine, bool allow_smush)
void cut_copy_clear(Editing::CutCopyOp)
framepos_t source_beats_to_absolute_frames(Evoral::Beats beats) const
ArdourCanvas::Rectangle * resize_rect
void change_note_velocity(NoteBase *ev, int8_t vel, bool relative=false)
MidiStreamView * midi_stream_view() const
void reset_width_dependent_items(double pixel_width)
void change_patch_change(PatchChange &old_patch, const MIDI::Name::PatchPrimaryKey &new_patch)
Selection selection() const
framepos_t snap_pixel_to_sample(double x)
NoteBase * add_note(const boost::shared_ptr< NoteType > note, bool visible)
void note_selected(NoteBase *ev, bool add, bool extend=false)
uint16_t get_selected_channels() const
MidiListEditor * _list_editor
bool motion(GdkEventMotion *)
void start_playing_midi_note(boost::shared_ptr< NoteType > note)
void select_range(framepos_t start, framepos_t end)
void update_hit(Hit *, bool update_ghost_regions=true)
int64_t framecnt_t
Definition: types.h:76
ARDOUR::ChannelMode get_channel_mode() const
Definition: hit.h:30
void change_note_time(NoteBase *ev, ARDOUR::MidiModel::TimeType, bool relative=false)
Definition: sys_ex.h:29
void show_step_edit_cursor(Evoral::Beats pos)
void show_verbose_cursor(std::string const &, double, double) const
ARDOUR::ColorMode color_mode() const
void note_deselected(NoteBase *ev)
const boost::shared_ptr< ARDOUR::MidiRegion > midi_region() const
void selection_as_notelist(Notes &selected, bool allow_all_if_none_selected=false)
void toggle_matching_notes(uint8_t notenum, uint16_t channel_mask)
void delete_note(boost::shared_ptr< NoteType >)
void display_model(boost::shared_ptr< ARDOUR::MidiModel > model)
boost::shared_ptr< CursorContext > _press_cursor_ctx
framepos_t region_beats_to_region_frames(Evoral::Beats beats) const
bool note_in_region_range(const boost::shared_ptr< NoteType > note, bool &visible) const
Definition: amp.h:29
void parameter_changed(std::string const &p)
ARDOUR::BeatsFramesConverter _source_relative_time_converter
ARDOUR::BeatsFramesConverter const & source_relative_time_converter() const
void update_vertical_drag_selection(double last_y, double y, bool extend)
ARDOUR::BeatsFramesConverter const & region_relative_time_converter() const
Selection _selection
void maybe_remove_deleted_note_from_selection(NoteBase *)
void step_patch(PatchChange &patch, bool bank, int delta)
ArdourCanvas::Container * _note_group
PBD::ScopedConnection snap_changed_connection
void instrument_settings_changed()
PBD::ScopedConnection _instrument_changed_connection
size_t selection_size()
int64_t frameoffset_t
Definition: types.h:71
MidiCutBuffer * selection_as_cut_buffer() const
void move_step_edit_cursor(Evoral::Beats pos)
double get_end_position_pixels()
void update_resizing(NoteBase *, bool, double, bool)
framepos_t region_beats_to_absolute_frames(Evoral::Beats beats) const
void patch_entered(PatchChange *)
uint8_t _current_range_min
ArdourCanvas::Container * _temporary_note_group
void display_patch_changes_on_channel(uint8_t, bool)
std::vector< boost::shared_ptr< SysEx > > SysExes
void region_resized(const PBD::PropertyChange &)
CutCopyOp
Definition: editing.h:198
NoteBase * find_canvas_note(boost::shared_ptr< NoteType >)
uint8_t get_velocity_for_add(ARDOUR::MidiModel::TimeType time) const
framepos_t position() const
Definition: region.h:112
void set_step_edit_cursor_width(Evoral::Beats beats)
void maybe_select_by_position(GdkEventButton *ev, double x, double y)
void connect_to_diskstream()
void change_note_length(NoteBase *, ARDOUR::MidiModel::TimeType)
void play_midi_note(boost::shared_ptr< NoteType > note)
void clear_midi_selection()
void add_canvas_patch_change(ARDOUR::MidiModel::PatchChangePtr patch, const std::string &displaytext, bool)
double snap_to_pixel(double x)
PBD::ScopedConnection _mouse_mode_connection
bool note_canvas_event(GdkEvent *ev)
std::set< boost::shared_ptr< NoteType > > _marked_for_velocity
std::set< NoteBase * > Selection
const char * name
void commit_resizing(NoteBase *, bool, double, bool)
void step_add_note(uint8_t channel, uint8_t number, uint8_t velocity, Evoral::Beats pos, Evoral::Beats len)
void paste_internal(framepos_t pos, unsigned paste_count, float times, const MidiCutBuffer &)
framepos_t snap_frame_to_grid_underneath(framepos_t p, framecnt_t &) const
void change_channel(uint8_t channel)
LIBARDOUR_API PBD::PropertyDescriptor< bool > relative
Definition: route_group.cc:42
void select_matching_notes(uint8_t notenum, uint16_t channel_mask, bool add, bool extend)
void enable_display(bool)
bool button_press(GdkEventButton *)
void move_patch_change(PatchChange &, Evoral::Beats)
Definition: xml++.h:95
void note_diff_remove_note(NoteBase *ev)
void start_playing_midi_chord(std::vector< boost::shared_ptr< NoteType > > notes)
void change_velocities(bool up, bool fine, bool allow_smush, bool all_together)
uint32_t get_fill_color() const
void move_selection(double dx, double dy, double cumulative_dy)
void update_note(NoteBase *, bool update_ghost_regions=true)
void change_note_note(NoteBase *ev, int8_t note, bool relative=false)
bool key_press(GdkEventKey *)
GhostRegion * add_ghost(TimeAxisView &)
bool button_release(GdkEventButton *)
std::set< boost::shared_ptr< NoteType > > _marked_for_selection
bool paste(framepos_t pos, const ::Selection &selection, PasteContext &ctx)
void set_height(double)
PBD::ScopedConnection note_delete_connection
void note_dropped(NoteBase *ev, ARDOUR::frameoffset_t, int8_t d_note)
void add_to_selection(NoteBase *)
void goto_previous_note(bool add_to_selection)
static PBD::Signal1< void, MidiRegionView * > SelectionCleared
NoteBase * _channel_selection_scoped_note
void note_diff_add_change(NoteBase *ev, ARDOUR::MidiModel::NoteDiffCommand::Property, uint8_t val)
void apply_diff(bool as_subcommand=false)
LIBGTKMM2EXT_API int pixel_width(const std::string &str, Pango::FontDescription &font)
void select_notes(std::list< boost::shared_ptr< NoteType > >)
void resolve_note(uint8_t note_num, Evoral::Beats end_time)
void nudge_notes(bool forward, bool fine)
void start_note_diff_command(std::string name="midi edit")
void clear_events(bool with_selection_signal=true)
double get_position_pixels()
std::vector< boost::shared_ptr< PatchChange > > PatchChanges
Evoral::Beats _step_edit_cursor_position
void begin_resizing(bool at_front)
void data_recorded(boost::weak_ptr< ARDOUR::MidiSource >)
std::list< NoteBase * > Events
int64_t framepos_t
void edit_patch_change(PatchChange *)
PBD::ScopedConnection _selection_cleared_connection
MidiStreamView * midi_view()
void note_diff_add_note(const boost::shared_ptr< NoteType > note, bool selected, bool show_velocity=false)
bool canvas_group_event(GdkEvent *ev)
PBD::ScopedConnection _channel_mode_changed_connection
Definition: ardour.h:41
ARDOUR::ColorMode color_mode() const
MouseState mouse_state() const
void add_patch_change(framecnt_t, Evoral::PatchChange< Evoral::Beats > const &)
Evoral::Beats absolute_frames_to_source_beats(framepos_t) const
void clear_selection(bool signal=true)
Evoral::Note< Evoral::Beats > NoteType
LIBARDOUR_API PBD::PropertyDescriptor< framecnt_t > length
Definition: region.cc:64
ArdourCanvas::Rectangle * _step_edit_cursor
def signal
Definition: signals.py:53
void apply_note_range(uint8_t lowest, uint8_t highest, bool force=false)
void init(bool wfd)