X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fmidi_region_view.h;h=1bdccd4986fb20a9ee56b353e58c25d0d006b07a;hb=d357eca668044badcb4bab318e2e74cfffa9a0b0;hp=6b0dcd18047cad06a57464f5b322f0c8c0bf72e6;hpb=79db28b0b87a6fb67ed6f31ec4753f52aad4358a;p=ardour.git diff --git a/gtk2_ardour/midi_region_view.h b/gtk2_ardour/midi_region_view.h index 6b0dcd1804..1bdccd4986 100644 --- a/gtk2_ardour/midi_region_view.h +++ b/gtk2_ardour/midi_region_view.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2001-2007 Paul Davis + Copyright (C) 2001-2007 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -36,7 +36,8 @@ #include "enums.h" #include "canvas.h" #include "canvas-note.h" -#include "canvas-midi-event.h" +#include "canvas-note-event.h" +#include "canvas-program-change.h" namespace ARDOUR { class MidiRegion; @@ -51,16 +52,16 @@ class AutomationRegionView; class MidiRegionView : public RegionView { public: - MidiRegionView (ArdourCanvas::Group *, + MidiRegionView (ArdourCanvas::Group *, RouteTimeAxisView&, boost::shared_ptr, double initial_samples_per_unit, Gdk::Color& basic_color); ~MidiRegionView (); - + virtual void init (Gdk::Color& basic_color, bool wfd); - + inline const boost::shared_ptr midi_region() const { return boost::dynamic_pointer_cast(_region); } @@ -69,94 +70,140 @@ class MidiRegionView : public RegionView inline MidiStreamView* midi_stream_view() const { return midi_view()->midi_view(); } - + void set_y_position_and_height (double, double); - + + void set_frame_color(); + void redisplay_model(); - GhostRegion* add_ghost (AutomationTimeAxisView&); + GhostRegion* add_ghost (TimeAxisView&); - void add_note(const ARDOUR::Note& note, bool copy_note); + void add_note(const boost::shared_ptr note); void resolve_note(uint8_t note_num, double end_time); + + void add_pgm_change(boost::shared_ptr event); void begin_write(); void end_write(); void extend_active_notes(); - void create_note_at(double x, double y, double dur); + void create_note_at(double x, double y, double duration); void display_model(boost::shared_ptr model); - /* This stuff is a bit boilerplatey ATM. Work in progress. */ + void start_delta_command(string name = "midi edit"); + void command_add_note(const boost::shared_ptr note, bool selected); + void command_remove_note(ArdourCanvas::CanvasNoteEvent* ev); - inline void start_remove_command() { - if (!_delta_command) - _delta_command = _model->new_delta_command(); - } - - inline void start_delta_command() { - if (!_delta_command) - _delta_command = _model->new_delta_command(); - } - - void command_add_note(ARDOUR::Note& note) { - if (_delta_command) - _delta_command->add(note); - } - - void command_remove_note(ArdourCanvas::CanvasMidiEvent* ev) { - if (_delta_command && ev->note()) { - _delta_command->remove(*ev->note()); - ev->selected(true); - } - } - - void abort_command() { - delete _delta_command; - _delta_command = NULL; - clear_selection(); - } - - void apply_command() { - if (_delta_command) { - _model->apply_command(_delta_command); - _delta_command = NULL; - } - midi_view()->midi_track()->diskstream()->playlist_modified(); - } - - void note_entered(ArdourCanvas::CanvasMidiEvent* ev); - void unique_select(ArdourCanvas::CanvasMidiEvent* ev); - void note_selected(ArdourCanvas::CanvasMidiEvent* ev, bool add); - void note_deselected(ArdourCanvas::CanvasMidiEvent* ev, bool add); + void apply_command(); + void abort_command(); + + void note_entered(ArdourCanvas::CanvasNoteEvent* ev); + void unique_select(ArdourCanvas::CanvasNoteEvent* ev); + void note_selected(ArdourCanvas::CanvasNoteEvent* ev, bool add); + void note_deselected(ArdourCanvas::CanvasNoteEvent* ev, bool add); void delete_selection(); size_t selection_size() { return _selection.size(); } void move_selection(double dx, double dy); - void note_dropped(ArdourCanvas::CanvasMidiEvent* ev, double dt, uint8_t dnote); + void note_dropped(ArdourCanvas::CanvasNoteEvent* ev, double dt, uint8_t dnote); + + /** + * This function is needed to subtract the region start in pixels + * from world coordinates submitted by the mouse + */ + double get_position_pixels(void); + + /** + * This function is called by CanvasMidiNote when resizing starts, + * i.e. when the user presses mouse-2 on the note + * @param note_end which end of the note, NOTE_ON or NOTE_OFF + */ + void begin_resizing(ArdourCanvas::CanvasNote::NoteEnd note_end); + + /** + * This function is called while the user moves the mouse when resizing notes + * @param note_end which end of the note, NOTE_ON or NOTE_OFF + * @param x the difference in mouse motion, ie the motion difference if relative=true + * or the absolute mouse position (track-relative) if relative is false + * @param relative true if relative resizing is taking place, false if absolute resizing + */ + void update_resizing(ArdourCanvas::CanvasNote::NoteEnd note_end, double x, bool relative); + + /** + * This function is called while the user releases the mouse button when resizing notes + * @param note_end which end of the note, NOTE_ON or NOTE_OFF + * @param event_x the absolute mouse position (track-relative) + * @param relative true if relative resizing is taking place, false if absolute resizing + */ + void commit_resizing(ArdourCanvas::CanvasNote::NoteEnd note_end, double event_x, bool relative); + + /** + * This function is called while the user adjusts the velocity on a selection of notes + * @param velocity the relative or absolute velocity, depending on the value of relative + * @param relative true if the given velocity represents a delta to be applied to all notes, false + * if the absolute value of the note shoud be set + */ + void change_velocity(uint8_t velocity, bool relative=false); + /** + * This function is called when the user adjusts the midi channel of a selection of notes + * @param channel - the channel number of the new channel, zero-based + */ + void change_channel(uint8_t channel); + enum MouseState { None, Pressed, SelectTouchDragging, SelectRectDragging, AddDragging, EraseTouchDragging }; MouseState mouse_state() const { return _mouse_state; } + + struct NoteResizeData { + ArdourCanvas::CanvasNote *canvas_note; + ArdourCanvas::SimpleRect *resize_rect; + double current_x; + }; + + /** + * This function provides the snap function for region position relative coordinates + * for pixel units (double) instead of nframes64_t + * @param x a pixel coordinate relative to region start + * @return the snapped pixel coordinate relative to region start + */ + double snap_to_pixel(double x); + + /** + * This function provides the snap function for region position relative coordinates + * for pixel units (double) instead of nframes64_t + * @param x a pixel coordinate relative to region start + * @return the snapped nframes64_t coordinate relative to region start + */ + nframes64_t snap_to_frame(double x); + + /** + * This function provides the snap function for region position relative coordinates + * @param x a pixel coordinate relative to region start + * @return the snapped nframes64_t coordinate relative to region start + */ + nframes64_t snap_to_frame(nframes64_t x); protected: - /* this constructor allows derived types - to specify their visibility requirements - to the TimeAxisViewItem parent class + /** + * this constructor allows derived types + * to specify their visibility requirements + * to the TimeAxisViewItem parent class */ - - MidiRegionView (ArdourCanvas::Group *, + MidiRegionView (ArdourCanvas::Group *, RouteTimeAxisView&, boost::shared_ptr, double samples_per_unit, Gdk::Color& basic_color, TimeAxisViewItem::Visibility); - + void region_resized (ARDOUR::Change); void set_flags (XMLNode *); void store_flags (); - + void reset_width_dependent_items (double pixel_width); private: @@ -167,23 +214,35 @@ class MidiRegionView : public RegionView bool canvas_event(GdkEvent* ev); bool note_canvas_event(GdkEvent* ev); - void clear_selection_except(ArdourCanvas::CanvasMidiEvent* ev); + void midi_channel_mode_changed(ARDOUR::ChannelMode mode, uint16_t mask); + + void clear_selection_except(ArdourCanvas::CanvasNoteEvent* ev); void clear_selection() { clear_selection_except(NULL); } void update_drag_selection(double last_x, double x, double last_y, double y); - double _default_note_length; + int8_t _force_channel; + uint16_t _last_channel_selection; + double _default_note_length; boost::shared_ptr _model; - std::vector _events; + std::vector _events; + std::vector< boost::shared_ptr > _pgm_changes; ArdourCanvas::CanvasNote** _active_notes; ArdourCanvas::Group* _note_group; ARDOUR::MidiModel::DeltaCommand* _delta_command; - + MouseState _mouse_state; int _pressed_button; - typedef std::set Selection; + typedef std::set Selection; + /// Currently selected CanvasNoteEvents Selection _selection; + + /** New notes (created in the current command) which should be selected + * when they appear after the command is applied. */ + std::set< boost::shared_ptr > _marked_for_selection; + + std::vector _resize_data; }; #endif /* __gtk_ardour_midi_region_view_h__ */