diff options
-rw-r--r-- | gtk2_ardour/editing.cc | 20 | ||||
-rw-r--r-- | gtk2_ardour/editing.h | 15 | ||||
-rw-r--r-- | gtk2_ardour/editing_syms.h | 4 | ||||
-rw-r--r-- | gtk2_ardour/editor.cc | 82 | ||||
-rw-r--r-- | gtk2_ardour/editor.h | 26 | ||||
-rw-r--r-- | gtk2_ardour/editor_mouse.cc | 53 | ||||
-rw-r--r-- | gtk2_ardour/midi_region_view.cc | 7 | ||||
-rw-r--r-- | gtk2_ardour/public_editor.h | 12 |
8 files changed, 213 insertions, 6 deletions
diff --git a/gtk2_ardour/editing.cc b/gtk2_ardour/editing.cc index c9efa1feb2..963b83647c 100644 --- a/gtk2_ardour/editing.cc +++ b/gtk2_ardour/editing.cc @@ -31,6 +31,7 @@ using namespace std; #define SNAPMODE(a) /*empty*/ #define REGIONLISTSORTTYPE(a) /*empty*/ #define MOUSEMODE(a) /*empty*/ +#define MIDIEDITMODE(a) /*empty*/ #define ZOOMFOCUS(a) /*empty*/ #define DISPLAYCONTROL(a) /*empty*/ @@ -113,6 +114,25 @@ const char *mousemodestrs[] = { #undef MOUSEMODE #define MOUSEMODE(a) /*empty*/ +// MIDIEDITMODE +#undef MIDIEDITMODE +#define MIDIEDITMODE(s) if (!strcmp(type, #s)) {return s;} +MidiEditMode +str2midieditmode (const string & str) { + const char* type = str.c_str(); + #include "editing_syms.h" + return MidiEditSelect; +} + +#undef MIDIEDITMODE +#define MIDIEDITMODE(s) N_(#s), +const char *midieditmodestrs[] = { + #include "editing_syms.h" + 0 +}; +#undef MIDIEDITMODE +#define MIDIEDITMODE(a) /*empty*/ + // ZOOMFOCUS #undef ZOOMFOCUS #define ZOOMFOCUS(s) if (!strcmp(type, #s)) {return s;} diff --git a/gtk2_ardour/editing.h b/gtk2_ardour/editing.h index 0d1078cf16..d7f8f6ece8 100644 --- a/gtk2_ardour/editing.h +++ b/gtk2_ardour/editing.h @@ -30,6 +30,7 @@ #define SNAPMODE(a) /*empty*/ #define REGIONLISTSORTTYPE(a) /*empty*/ #define MOUSEMODE(a) /*empty*/ +#define MIDIEDITMODE(a) /*empty*/ #define ZOOMFOCUS(a) /*empty*/ #define DISPLAYCONTROL(a) /*empty*/ #define IMPORTMODE(a) /*empty*/ @@ -92,6 +93,20 @@ MouseMode str2mousemode(const std::string &); #undef MOUSEMODE #define MOUSEMODE(a) /*empty*/ +// MIDIEDITMODE +#undef MIDIEDITMODE +#define MIDIEDITMODE(a) a, +enum MidiEditMode { + #include "editing_syms.h" +}; + +extern const char *midieditmodestrs[]; +inline const char* enum2str(MidiEditMode m) {return midieditmodestrs[m];} +MidiEditMode str2midieditmode(const std::string &); + +#undef MIDIEDITMODE +#define MIDIEDITMODE(a) /*empty*/ + // ZOOMFOCUS #undef ZOOMFOCUS #define ZOOMFOCUS(a) a, diff --git a/gtk2_ardour/editing_syms.h b/gtk2_ardour/editing_syms.h index 7ae45c4c06..a057f6dd64 100644 --- a/gtk2_ardour/editing_syms.h +++ b/gtk2_ardour/editing_syms.h @@ -62,6 +62,10 @@ MOUSEMODE(MouseZoom) MOUSEMODE(MouseAudition) MOUSEMODE(MouseNote) +MIDIEDITMODE(MidiEditSelect) +MIDIEDITMODE(MidiEditPencil) +MIDIEDITMODE(MidiEditErase) + /* Changing this order will break the menu */ ZOOMFOCUS(ZoomFocusLeft) ZOOMFOCUS(ZoomFocusRight) diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 7da62d743f..952e5b098a 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -368,6 +368,7 @@ Editor::Editor () build_cursors (); setup_toolbar (); + setup_midi_toolbar (); edit_cursor_clock.ValueChanged.connect (mem_fun(*this, &Editor::edit_cursor_clock_changed)); @@ -667,7 +668,8 @@ Editor::Editor () edit_pane.signal_size_allocate().connect (bind (mem_fun(*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&edit_pane))); - top_hbox.pack_start (toolbar_frame, true, true); + top_hbox.pack_start (toolbar_frame, false, true); + top_hbox.pack_start (midi_toolbar_frame, false, true); HBox *hbox = manage (new HBox); hbox->pack_start (edit_pane, true, true); @@ -2575,6 +2577,84 @@ Editor::setup_toolbar () toolbar_frame.add (toolbar_base); } + +void +Editor::setup_midi_toolbar () +{ + string pixmap_path; + + /* Mode Buttons (tool selection) */ + + vector<ToggleButton *> midi_tool_buttons; + + midi_tool_select_button.add (*(manage (new Image (::get_icon("midi_tool_select"))))); + midi_tool_select_button.set_relief(Gtk::RELIEF_NONE); + midi_tool_buttons.push_back (&midi_tool_select_button); + midi_tool_pencil_button.add (*(manage (new Image (::get_icon("midi_tool_pencil"))))); + midi_tool_pencil_button.set_relief(Gtk::RELIEF_NONE); + midi_tool_buttons.push_back (&midi_tool_pencil_button); + midi_tool_erase_button.add (*(manage (new Image (::get_icon("midi_tool_erase"))))); + midi_tool_erase_button.set_relief(Gtk::RELIEF_NONE); + midi_tool_buttons.push_back (&midi_tool_erase_button); + + midi_tool_select_button.set_active(true); + + midi_tool_button_set = new GroupedButtons (midi_tool_buttons); + + midi_tool_button_box.set_border_width (2); + midi_tool_button_box.set_spacing(4); + midi_tool_button_box.set_spacing(1); + midi_tool_button_box.pack_start(midi_tool_select_button, true, true); + midi_tool_button_box.pack_start(midi_tool_pencil_button, true, true); + midi_tool_button_box.pack_start(midi_tool_erase_button, true, true); + midi_tool_button_box.set_homogeneous(true); + + midi_tool_select_button.set_name ("MouseModeButton"); + midi_tool_pencil_button.set_name ("MouseModeButton"); + midi_tool_erase_button.set_name ("MouseModeButton"); + + ARDOUR_UI::instance()->tooltips().set_tip (midi_tool_select_button, _("Select/Move Notes")); + ARDOUR_UI::instance()->tooltips().set_tip (midi_tool_pencil_button, _("Add/Move/Stretch Notes")); + ARDOUR_UI::instance()->tooltips().set_tip (midi_tool_erase_button, _("Erase Notes")); + + midi_tool_select_button.unset_flags (CAN_FOCUS); + midi_tool_pencil_button.unset_flags (CAN_FOCUS); + midi_tool_erase_button.unset_flags (CAN_FOCUS); + + + /* Pack everything in... */ + + midi_tools_tearoff = new TearOff (midi_tool_button_box); + midi_tools_tearoff->set_name ("MouseModeBase"); + + /* + midi_tools_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&midi_toolbar_hbox), + &midi_tools_tearoff->tearoff_window())); + midi_tools_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&midi_toolbar_hbox), + &midi_tools_tearoff->tearoff_window(), 0)); + midi_tools_tearoff->Hidden.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&midi_toolbar_hbox), + &midi_tools_tearoff->tearoff_window())); + midi_tools_tearoff->Visible.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&midi_toolbar_hbox), + &midi_tools_tearoff->tearoff_window(), 0)); + */ + + midi_toolbar_hbox.set_spacing (10); + midi_toolbar_hbox.set_border_width (1); + + midi_toolbar_hbox.pack_start (*midi_tools_tearoff, false, true); + + midi_tool_button_box.show_all (); + midi_toolbar_hbox.show_all(); + midi_tools_tearoff->show_all(); + + midi_toolbar_base.set_name ("ToolBarBase"); + midi_toolbar_base.add (midi_toolbar_hbox); + + midi_toolbar_frame.set_shadow_type (SHADOW_OUT); + midi_toolbar_frame.set_name ("BaseFrame"); + midi_toolbar_frame.add (midi_toolbar_base); +} + int Editor::convert_drop_to_paths (vector<ustring>& paths, const RefPtr<Gdk::DragContext>& context, diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 8bf814a472..cae4da5a04 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -142,6 +142,9 @@ class Editor : public PublicEditor void set_mouse_mode (Editing::MouseMode, bool force=true); void step_mouse_mode (bool next); Editing::MouseMode current_mouse_mode () const { return mouse_mode; } + + void set_midi_edit_mode (Editing::MidiEditMode, bool force=true); + Editing::MidiEditMode current_midi_edit_mode () const { return midi_edit_mode; } #ifdef WITH_CMT void add_imageframe_time_axis(const std::string & track_name, void*) ; @@ -360,7 +363,8 @@ class Editor : public PublicEditor void set_frames_per_unit (double); - Editing::MouseMode mouse_mode; + Editing::MouseMode mouse_mode; + Editing::MidiEditMode midi_edit_mode; int post_maximal_editor_width; int post_maximal_pane_position; @@ -1371,11 +1375,29 @@ class Editor : public PublicEditor void setup_toolbar (); - Gtkmm2ext::TearOff* tools_tearoff; + Gtkmm2ext::TearOff* tools_tearoff; Gtk::HBox toolbar_hbox; Gtk::EventBox toolbar_base; Gtk::Frame toolbar_frame; + /* midi toolbar */ + + Gtk::HBox midi_tool_button_box; + Gtkmm2ext::TearOff* midi_tool_tearoff; + Gtk::ToggleButton midi_tool_select_button; + Gtk::ToggleButton midi_tool_pencil_button; + Gtk::ToggleButton midi_tool_erase_button; + GroupedButtons *midi_tool_button_set; + //void midi_tool_toggled (Editing::MouseMode m); + //bool ignore_midi_tool_toggle; + + Gtkmm2ext::TearOff* midi_tools_tearoff; + Gtk::HBox midi_toolbar_hbox; + Gtk::EventBox midi_toolbar_base; + Gtk::Frame midi_toolbar_frame; + + void setup_midi_toolbar (); + /* selection process */ Selection* selection; diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index be2d0bc47d..0423e1aab3 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -213,7 +213,7 @@ Editor::set_mouse_mode (MouseMode m, bool force) } } - /* XXX the hack of unsetting all other buttongs should go + /* XXX the hack of unsetting all other buttons should go away once GTK2 allows us to use regular radio buttons drawn like normal buttons, rather than my silly GroupedButton hack. */ @@ -257,6 +257,11 @@ Editor::set_mouse_mode (MouseMode m, bool force) break; } + if (mouse_mode == MouseNote) + midi_toolbar_frame.show(); + else + midi_toolbar_frame.hide(); + ignore_mouse_mode_toggle = false; if (is_drawable()) { @@ -306,6 +311,52 @@ Editor::step_mouse_mode (bool next) } void +Editor::set_midi_edit_mode (MidiEditMode m, bool force) +{ + if (drag_info.item) { + return; + } + + if (!force && m == midi_edit_mode) { + return; + } + + midi_edit_mode = m; + + instant_save (); + + //ignore_midi_edit_mode_toggle = true; + + switch (midi_edit_mode) { + case MidiEditSelect: + midi_tool_select_button.set_active (true); + //current_canvas_cursor = selector_cursor; + break; + + case MidiEditPencil: + midi_tool_pencil_button.set_active (true); + //current_canvas_cursor = selector_cursor; + break; + + case MidiEditErase: + midi_tool_erase_button.set_active (true); + //current_canvas_cursor = selector_cursor; + break; + } + + if (mouse_mode == MouseNote) + midi_toolbar_frame.show(); + else + midi_toolbar_frame.hide(); + + //ignore_midi_edit_mode_toggle = false; + + /*if (is_drawable()) { + track_canvas.get_window()->set_cursor(*current_canvas_cursor); + }*/ +} + +void Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type) { bool commit = false; diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index 88e7a98e7b..8e90087697 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -139,14 +139,17 @@ MidiRegionView::canvas_event(GdkEvent* ev) switch (ev->type) { case GDK_KEY_PRESS: - if (ev->key.keyval == GDK_Delete) + if (ev->key.keyval == GDK_Delete) { + trackview.editor.set_midi_edit_mode(MidiEditErase); start_remove_command(); + } break; case GDK_KEY_RELEASE: if (_command_mode == Remove && ev->key.keyval == GDK_Delete) { delete_selection(); apply_command(); + trackview.editor.set_midi_edit_mode(MidiEditSelect); } break; @@ -554,7 +557,7 @@ void MidiRegionView::add_note (const MidiModel::Note& note) { assert(note.time() >= 0); - assert(note.time() < _region->length()); + //assert(note.time() < _region->length()); ArdourCanvas::Group* const group = (ArdourCanvas::Group*)get_canvas_group(); diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h index 97618dcbc2..5031387290 100644 --- a/gtk2_ardour/public_editor.h +++ b/gtk2_ardour/public_editor.h @@ -145,6 +145,18 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulThingWithGoingAway * (defined in editing_syms.h) */ virtual Editing::MouseMode current_mouse_mode () const = 0; + + /** Set the midi edit mode (select, pencil, eraser, etc.) + * @param m Midi edit mode (defined in editing_syms.h) + * @param force Perform the effects of the change even if no change is required + * (ie even if the current midi edit mode is equal to \ref m) + */ + virtual void set_midi_edit_mode (Editing::MidiEditMode m, bool force = false) = 0; + + /** @return The current mouse mode (gain, object, range, timefx etc.) + * (defined in editing_syms.h) + */ + virtual Editing::MidiEditMode current_midi_edit_mode () const = 0; /** Possibly start the audition of a region. If \ref r is 0, or not an AudioRegion * any current audition is cancelled. If we are currently auditioning \ref r, |