From badc087263990ecf360792c10e4d9f2d60828d43 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Thu, 8 Nov 2007 01:40:25 +0000 Subject: merged with 2.0-ongoing changes 2582-2605 (not thoroughly tested but it compiles, start up, and creates a new session) git-svn-id: svn://localhost/ardour2/trunk@2606 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/ardour_ui_ed.cc | 2 +- gtk2_ardour/editing.h | 11 ++ gtk2_ardour/editing_syms.h | 6 + gtk2_ardour/editor.cc | 127 ++++++++++++++---- gtk2_ardour/editor.h | 47 ++++--- gtk2_ardour/editor_actions.cc | 58 ++++++++ gtk2_ardour/editor_audio_import.cc | 8 +- gtk2_ardour/editor_canvas_events.cc | 1 - gtk2_ardour/editor_markers.cc | 8 +- gtk2_ardour/editor_mouse.cc | 257 ++++++++++++++---------------------- gtk2_ardour/editor_ops.cc | 133 ++++++++++++------- gtk2_ardour/editor_selection.cc | 15 +-- gtk2_ardour/editor_timefx.cc | 51 ++++--- gtk2_ardour/enums.cc | 6 + gtk2_ardour/marker_selection.h | 31 +++++ gtk2_ardour/public_editor.h | 10 +- gtk2_ardour/selection.cc | 52 +++++++- gtk2_ardour/selection.h | 10 +- gtk2_ardour/time_axis_view.cc | 10 +- gtk2_ardour/utils.cc | 56 ++++++++ gtk2_ardour/utils.h | 2 + 21 files changed, 596 insertions(+), 305 deletions(-) create mode 100644 gtk2_ardour/marker_selection.h (limited to 'gtk2_ardour') diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc index 74b5a70738..7f4a0a1e69 100644 --- a/gtk2_ardour/ardour_ui_ed.cc +++ b/gtk2_ardour/ardour_ui_ed.cc @@ -155,7 +155,7 @@ ARDOUR_UI::install_actions () Glib::RefPtr jack_actions = ActionGroup::create (X_("JACK")); ActionManager::register_action (jack_actions, X_("JACK"), _("JACK")); ActionManager::register_action (jack_actions, X_("Latency"), _("Latency")); - + act = ActionManager::register_action (jack_actions, X_("JACKReconnect"), _("Reconnect"), mem_fun (*(ARDOUR_UI::instance()), &ARDOUR_UI::reconnect_to_jack)); ActionManager::jack_opposite_sensitive_actions.push_back (act); diff --git a/gtk2_ardour/editing.h b/gtk2_ardour/editing.h index 93bbb603ee..2b4519ec9c 100644 --- a/gtk2_ardour/editing.h +++ b/gtk2_ardour/editing.h @@ -36,6 +36,7 @@ #define IMPORTMODE(a) /*empty*/ #define IMPORTPOSITION(a) #define IMPORTDISPOSITION(a) +#define EDITPOINT(a) /*empty*/ namespace Editing { @@ -168,6 +169,16 @@ enum ImportDisposition { #undef IMPORTDISPOSITION #define IMPORTDISPOSITION(a) /*empty*/ +// EDITPOINT +#undef EDITPOINT +#define EDITPOINT(a) a, +enum EditPoint { + #include "editing_syms.h" +}; + +#undef EDITPOINT +#define EDITPOINT(a) /*empty*/ + ///////////////////// // These don't need their state saved. yet... enum CutCopyOp { diff --git a/gtk2_ardour/editing_syms.h b/gtk2_ardour/editing_syms.h index f731d33efe..29fd1234a8 100644 --- a/gtk2_ardour/editing_syms.h +++ b/gtk2_ardour/editing_syms.h @@ -71,6 +71,7 @@ ZOOMFOCUS(ZoomFocusLeft) ZOOMFOCUS(ZoomFocusRight) ZOOMFOCUS(ZoomFocusCenter) ZOOMFOCUS(ZoomFocusPlayhead) +ZOOMFOCUS(ZoomFocusMouse) ZOOMFOCUS(ZoomFocusEdit) DISPLAYCONTROL(FollowPlayhead) @@ -95,3 +96,8 @@ IMPORTDISPOSITION(ImportDistinctFiles=0) IMPORTDISPOSITION(ImportMergeFiles=1) IMPORTDISPOSITION(ImportSerializeFiles=2) IMPORTDISPOSITION(ImportDistinctChannels=3) + + +EDITPOINT(EditAtPlayhead) +EDITPOINT(EditAtSelectedMarker) +EDITPOINT(EditAtMouse) diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 1e726277d2..bf05cc5485 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -139,11 +139,19 @@ static const gchar *_snap_mode_strings[] = { 0 }; +static const gchar *_edit_point_strings[] = { + N_("Playhead"), + N_("Marker"), + N_("Mouse"), + 0 +}; + static const gchar *_zoom_focus_strings[] = { N_("Left"), N_("Right"), N_("Center"), N_("Playhead"), + N_("Mouse"), N_("Edit Cursor"), 0 }; @@ -170,20 +178,6 @@ show_me_the_size (Requisition* r, const char* what) cerr << "size of " << what << " = " << r->width << " x " << r->height << endl; } -void -check_adjustment (Gtk::Adjustment* adj) -{ - cerr << "CHANGE adj = " - << adj->get_lower () << ' ' - << adj->get_upper () << ' ' - << adj->get_value () << ' ' - << adj->get_step_increment () << ' ' - << adj->get_page_increment () << ' ' - << adj->get_page_size () << ' ' - << endl; - -} - Editor::Editor () : /* time display buttons */ @@ -256,14 +250,20 @@ Editor::Editor () current_mixer_strip = 0; current_bbt_points = 0; - snap_type_strings = I18N (_snap_type_strings); - snap_mode_strings = I18N (_snap_mode_strings); - zoom_focus_strings = I18N(_zoom_focus_strings); + snap_type_strings = I18N (_snap_type_strings); + snap_mode_strings = I18N (_snap_mode_strings); + zoom_focus_strings = I18N (_zoom_focus_strings); + edit_point_strings = I18N (_edit_point_strings); snap_type = SnapToFrame; set_snap_to (snap_type); + snap_mode = SnapNormal; set_snap_mode (snap_mode); + + _edit_point = EditAtMouse; + set_edit_point (_edit_point); + snap_threshold = 5.0; bbt_beat_subdivision = 4; canvas_width = 0; @@ -329,13 +329,7 @@ Editor::Editor () _dragging_playhead = false; _dragging_hscrollbar = false; - _scrubbing = false; - mouse_direction = 1; - mouse_speed_update = -1; - mouse_speed_size = 16; - mouse_speed = new double[mouse_speed_size]; - memset (mouse_speed, 0, sizeof(double) * mouse_speed_size); - mouse_speed_entries = 0; + scrubbing_direction = 0; sfbrowser = 0; ignore_route_order_sync = false; @@ -2005,6 +1999,18 @@ Editor::set_snap_mode (SnapMode mode) instant_save (); } +void +Editor::set_edit_point (EditPoint ep) +{ + _edit_point = ep; + string str = edit_point_strings[(int)ep]; + + if (str != edit_point_selector.get_active_text ()) { + edit_point_selector.set_active_text (str); + } + + instant_save (); +} int Editor::set_state (const XMLNode& node) @@ -2082,6 +2088,10 @@ Editor::set_state (const XMLNode& node) set_snap_mode ((SnapMode) atoi (prop->value())); } + if ((prop = node.property ("edit-point"))) { + set_edit_point ((EditPoint) string_2_enum (prop->value(), _edit_point)); + } + if ((prop = node.property ("mouse-mode"))) { MouseMode m = str2mousemode(prop->value()); mouse_mode = MouseMode ((int) m + 1); /* lie, force mode switch */ @@ -2233,6 +2243,8 @@ Editor::get_state () snprintf (buf, sizeof(buf), "%d", (int) snap_mode); node->add_property ("snap-mode", buf); + node->add_property ("edit-point", enum_2_string (_edit_point)); + snprintf (buf, sizeof (buf), "%" PRIu32, playhead_cursor->current_frame); node->add_property ("playhead", buf); snprintf (buf, sizeof (buf), "%" PRIu32, edit_cursor->current_frame); @@ -2400,7 +2412,7 @@ Editor::snap_to (nframes64_t& start, int32_t direction, bool for_mark) break; case SnapToEditCursor: - start = edit_cursor->current_frame; + start = get_preferred_edit_position (); break; case SnapToMark: @@ -2681,17 +2693,24 @@ Editor::setup_toolbar () Gtkmm2ext::set_size_request_to_display_given_text (snap_type_selector, "SMPTE Seconds", 2+FUDGE, 10); set_popdown_strings (snap_type_selector, snap_type_strings); snap_type_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_type_selection_done)); - ARDOUR_UI::instance()->tooltips().set_tip (snap_type_selector, _("Unit to snap cursors and ranges to")); + ARDOUR_UI::instance()->tooltips().set_tip (snap_type_selector, _("Snap/Grid Units")); snap_mode_selector.set_name ("SnapModeSelector"); Gtkmm2ext::set_size_request_to_display_given_text (snap_mode_selector, "Magnetic Snap", 2+FUDGE, 10); set_popdown_strings (snap_mode_selector, snap_mode_strings); snap_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_mode_selection_done)); + ARDOUR_UI::instance()->tooltips().set_tip (snap_mode_selector, _("Snap/Grid Mode")); + + edit_point_selector.set_name ("SnapModeSelector"); + Gtkmm2ext::set_size_request_to_display_given_text (edit_point_selector, "Playhead", 2+FUDGE, 10); + set_popdown_strings (edit_point_selector, edit_point_strings); + edit_point_selector.signal_changed().connect (mem_fun(*this, &Editor::edit_point_selection_done)); + ARDOUR_UI::instance()->tooltips().set_tip (edit_point_selector, _("Edit point")); snap_box.pack_start (edit_cursor_clock, false, false); snap_box.pack_start (snap_mode_selector, false, false); snap_box.pack_start (snap_type_selector, false, false); - + snap_box.pack_start (edit_point_selector, false, false); /* Nudge */ @@ -2845,8 +2864,6 @@ Editor::convert_drop_to_paths (vector& paths, vector uris = data.get_uris(); - cerr << "there were " << uris.size() << " in that drag data\n"; - if (uris.empty()) { /* This is seriously fucked up. Nautilus doesn't say that its URI lists @@ -3228,6 +3245,27 @@ Editor::snap_mode_selection_done () } } +void +Editor::edit_point_selection_done () +{ + string choice = edit_point_selector.get_active_text(); + EditPoint ep = EditAtSelectedMarker; + + if (choice == _("Marker")) { + _edit_point = EditAtSelectedMarker; + } else if (choice == _("Playhead")) { + _edit_point = EditAtPlayhead; + } else { + _edit_point = EditAtMouse; + } + + RefPtr ract = edit_point_action (ep); + + if (ract) { + ract->set_active (true); + } +} + void Editor::zoom_focus_selection_done () { @@ -3244,6 +3282,8 @@ Editor::zoom_focus_selection_done () focus_type = ZoomFocusPlayhead; } else if (choice == _("Edit")) { focus_type = ZoomFocusEdit; + } else { + focus_type = ZoomFocusMouse; } RefPtr ract = zoom_focus_action (focus_type); @@ -4025,6 +4065,35 @@ Editor::edit_cursor_position(bool sync) return edit_cursor->current_frame; } +nframes64_t +Editor::get_preferred_edit_position() const +{ + bool ignored; + nframes64_t where; + + switch (_edit_point) { + case EditAtPlayhead: + return playhead_cursor->current_frame; + + case EditAtSelectedMarker: + if (!selection->markers.empty()) { + bool whocares; + Location* loc = find_location_from_marker (selection->markers.front(), whocares); + if (loc) { + return loc->start(); + } + } + /* fallthru */ + + default: + case EditAtMouse: + if (mouse_frame (where, ignored)) { + return where; + } + } + + return -1; +} void Editor::set_loop_range (nframes_t start, nframes_t end, string cmd) diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 96c1d1004d..9f68929bfb 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -46,6 +46,7 @@ #include #include +#include #include #include #include @@ -183,15 +184,15 @@ class Editor : public PublicEditor /* undo related */ - nframes_t unit_to_frame (double unit) { + nframes_t unit_to_frame (double unit) const { return (nframes_t) rint (unit * frames_per_unit); } - double frame_to_unit (nframes_t frame) { + double frame_to_unit (nframes_t frame) const { return rint ((double) frame / (double) frames_per_unit); } - double frame_to_unit (double frame) { + double frame_to_unit (double frame) const { return rint (frame / frames_per_unit); } @@ -202,7 +203,7 @@ class Editor : public PublicEditor xscroll_adjustment. */ - nframes_t pixel_to_frame (double pixel) { + nframes64_t pixel_to_frame (double pixel) const { /* pixel can be less than zero when motion events are processed. since we've already run the world->canvas @@ -217,7 +218,7 @@ class Editor : public PublicEditor } } - gulong frame_to_pixel (nframes_t frame) { + gulong frame_to_pixel (nframes64_t frame) const { return (gulong) rint ((frame / (frames_per_unit * GNOME_CANVAS(track_canvas.gobj())->pixels_per_unit))); } @@ -354,6 +355,8 @@ class Editor : public PublicEditor void reposition_and_zoom (nframes_t, double); nframes_t edit_cursor_position(bool); + nframes64_t get_preferred_edit_position () const; + bool update_mouse_speed (); bool decelerate_mouse_speed (); @@ -424,8 +427,8 @@ class Editor : public PublicEditor void set_color_rgba (uint32_t); }; - LocationMarkers *find_location_markers (ARDOUR::Location *); - ARDOUR::Location* find_location_from_marker (Marker *, bool& is_start); + LocationMarkers *find_location_markers (ARDOUR::Location *) const; + ARDOUR::Location* find_location_from_marker (Marker *, bool& is_start) const; typedef std::map LocationMarkerMap; LocationMarkerMap location_markers; @@ -1136,16 +1139,8 @@ class Editor : public PublicEditor void stop_scrolling (); bool _scrubbing; - bool have_full_mouse_speed; - nframes64_t last_scrub_frame; - double last_scrub_time; - int mouse_speed_update; - double mouse_direction; - double compute_mouse_speed (); - void add_mouse_speed (double, double); - double* mouse_speed; - size_t mouse_speed_entries; - size_t mouse_speed_size; + double last_scrub_x; + int scrubbing_direction; void keyboard_selection_begin (); void keyboard_selection_finish (bool add); @@ -1834,14 +1829,18 @@ class Editor : public PublicEditor void duplicate_dialog (bool for_region); - nframes_t event_frame (GdkEvent*, double* px = 0, double* py = 0); + nframes64_t event_frame (GdkEvent*, double* px = 0, double* py = 0) const; + + /* returns false if mouse pointer is not in track or marker canvas + */ + bool mouse_frame (nframes64_t&, bool& in_track_canvas) const; void time_fx_motion (ArdourCanvas::Item*, GdkEvent*); void start_time_fx (ArdourCanvas::Item*, GdkEvent*); void end_time_fx (ArdourCanvas::Item*, GdkEvent*); struct TimeStretchDialog : public ArdourDialog { - ARDOUR::Session::TimeStretchRequest request; + ARDOUR::TimeStretchRequest request; Editor& editor; RegionSelection regions; Gtk::ProgressBar progress_bar; @@ -2001,6 +2000,16 @@ class Editor : public PublicEditor void history_changed (); Gtk::HBox status_bar_hpacker; + + Editing::EditPoint _edit_point; + + Gtk::ComboBoxText edit_point_selector; + + void set_edit_point (Editing::EditPoint ep); + void edit_point_selection_done (); + void edit_point_chosen (Editing::EditPoint); + Glib::RefPtr edit_point_action (Editing::EditPoint); + std::vector edit_point_strings; }; #endif /* __ardour_editor_h__ */ diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc index db81531583..b68f4bf2b7 100644 --- a/gtk2_ardour/editor_actions.cc +++ b/gtk2_ardour/editor_actions.cc @@ -291,6 +291,8 @@ Editor::register_actions () ActionManager::session_sensitive_actions.push_back (act); ActionManager::register_radio_action (zoom_actions, zoom_group, "zoom-focus-playhead", _("Zoom Focus Playhead"), bind (mem_fun(*this, &Editor::zoom_focus_chosen), Editing::ZoomFocusPlayhead)); ActionManager::session_sensitive_actions.push_back (act); + ActionManager::register_radio_action (zoom_actions, zoom_group, "zoom-focus-mouse", _("Zoom Focus Mouse"), bind (mem_fun(*this, &Editor::zoom_focus_chosen), Editing::ZoomFocusMouse)); + ActionManager::session_sensitive_actions.push_back (act); ActionManager::register_radio_action (zoom_actions, zoom_group, "zoom-focus-edit", _("Zoom Focus Edit"), bind (mem_fun(*this, &Editor::zoom_focus_chosen), Editing::ZoomFocusEdit)); ActionManager::session_sensitive_actions.push_back (act); @@ -304,6 +306,11 @@ Editor::register_actions () ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-timefx", _("Timefx Tool"), bind (mem_fun(*this, &Editor::set_mouse_mode), Editing::MouseTimeFX, false)); ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-note", _("Note Tool"), bind (mem_fun(*this, &Editor::set_mouse_mode), Editing::MouseNote, false)); + RadioAction::Group edit_point_group; + ActionManager::register_radio_action (editor_actions, edit_point_group, X_("edit-at-playhead"), _("Playhead"), (bind (mem_fun(*this, &Editor::edit_point_chosen), Editing::EditAtPlayhead))); + ActionManager::register_radio_action (editor_actions, edit_point_group, X_("edit-at-mouse"), _("Mouse"), (bind (mem_fun(*this, &Editor::edit_point_chosen), Editing::EditAtPlayhead))); + ActionManager::register_radio_action (editor_actions, edit_point_group, X_("edit-at-selected-marker"), _("Marker"), (bind (mem_fun(*this, &Editor::edit_point_chosen), Editing::EditAtPlayhead))); + ActionManager::register_action (editor_actions, X_("SnapTo"), _("Snap To")); ActionManager::register_action (editor_actions, X_("SnapMode"), _("Snap Mode")); @@ -829,6 +836,54 @@ Editor::snap_mode_chosen (SnapMode mode) } } +RefPtr +Editor::edit_point_action (EditPoint ep) +{ + const char* action = 0; + RefPtr act; + + switch (ep) { + case Editing::EditAtPlayhead: + action = X_("edit-at-playhead"); + break; + case Editing::EditAtSelectedMarker: + action = X_("edit-at-selected-marker"); + break; + case Editing::EditAtMouse: + action = X_("edit-at-mouse"); + break; + default: + fatal << string_compose (_("programming error: %1: %2"), "Editor: impossible edit point type", (int) ep) << endmsg; + /*NOTREACHED*/ + } + + act = ActionManager::get_action (X_("Editor"), action); + + if (act) { + RefPtr ract = RefPtr::cast_dynamic(act); + return ract; + + } else { + error << string_compose (_("programming error: %1: %2"), "Editor::edit_point_action could not find action to match edit point.", action) << endmsg; + return RefPtr (); + } +} + +void +Editor::edit_point_chosen (EditPoint ep) +{ + /* this is driven by a toggle on a radio group, and so is invoked twice, + once for the item that became inactive and once for the one that became + active. + */ + + RefPtr ract = edit_point_action (ep); + + if (ract && ract->get_active()) { + set_edit_point (ep); + } +} + RefPtr Editor::zoom_focus_action (ZoomFocus focus) @@ -849,6 +904,9 @@ Editor::zoom_focus_action (ZoomFocus focus) case ZoomFocusPlayhead: action = X_("zoom-focus-playhead"); break; + case ZoomFocusMouse: + action = X_("zoom-focus-mouse"); + break; case ZoomFocusEdit: action = X_("zoom-focus-edit"); break; diff --git a/gtk2_ardour/editor_audio_import.cc b/gtk2_ardour/editor_audio_import.cc index 0dc0d707c0..b609918f09 100644 --- a/gtk2_ardour/editor_audio_import.cc +++ b/gtk2_ardour/editor_audio_import.cc @@ -144,7 +144,7 @@ Editor::external_audio_dialog () switch (pos) { case ImportAtEditCursor: - where = edit_cursor->current_frame; + where = get_preferred_edit_position (); break; case ImportAtTimestamp: where = -1; @@ -157,6 +157,10 @@ Editor::external_audio_dialog () break; } + if (where < 0) { + return; + } + SrcQuality quality = sfbrowser->get_src_quality(); if (sfbrowser->copy_files_btn.get_active()) { @@ -591,7 +595,7 @@ Editor::add_sources (vector paths, SourceList& sources, nframes64 pos = sources[0]->natural_position(); } else { // XXX is this the best alternative ? - pos = edit_cursor->current_frame; + pos = get_preferred_edit_position (); } } diff --git a/gtk2_ardour/editor_canvas_events.cc b/gtk2_ardour/editor_canvas_events.cc index 394d35e245..a22edea7e0 100644 --- a/gtk2_ardour/editor_canvas_events.cc +++ b/gtk2_ardour/editor_canvas_events.cc @@ -202,7 +202,6 @@ Editor::typed_event (ArdourCanvas::Item* item, GdkEvent *event, ItemType type) default: break; } - return ret; } diff --git a/gtk2_ardour/editor_markers.cc b/gtk2_ardour/editor_markers.cc index 724ff2c31a..50bf950054 100644 --- a/gtk2_ardour/editor_markers.cc +++ b/gtk2_ardour/editor_markers.cc @@ -188,9 +188,9 @@ Editor::LocationMarkers::~LocationMarkers () } Editor::LocationMarkers * -Editor::find_location_markers (Location *location) +Editor::find_location_markers (Location *location) const { - LocationMarkerMap::iterator i; + LocationMarkerMap::const_iterator i; for (i = location_markers.begin(); i != location_markers.end(); ++i) { if ((*i).first == location) { @@ -202,9 +202,9 @@ Editor::find_location_markers (Location *location) } Location * -Editor::find_location_from_marker (Marker *marker, bool& is_start) +Editor::find_location_from_marker (Marker *marker, bool& is_start) const { - LocationMarkerMap::iterator i; + LocationMarkerMap::const_iterator i; for (i = location_markers.begin(); i != location_markers.end(); ++i) { LocationMarkers *lm = (*i).second; diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index 8efce4daac..7857082be3 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -76,8 +76,46 @@ using namespace Editing; const static double ZERO_GAIN_FRACTION = gain_to_slider_position(dB_to_coefficient(0.0)); -nframes_t -Editor::event_frame (GdkEvent* event, double* pcx, double* pcy) +bool +Editor::mouse_frame (nframes64_t& where, bool& in_track_canvas) const +{ + int x, y; + double wx, wy; + Gdk::ModifierType mask; + Glib::RefPtr canvas_window = const_cast(this)->track_canvas.get_window(); + Glib::RefPtr pointer_window; + + pointer_window = canvas_window->get_pointer (x, y, mask); + + if (pointer_window == track_canvas.get_bin_window()) { + + track_canvas.window_to_world (x, y, wx, wy); + in_track_canvas = true; + + } else { + in_track_canvas = false; + + if (pointer_window == time_canvas.get_bin_window()) { + time_canvas.window_to_world (x, y, wx, wy); + } else { + return false; + } + } + + wx += horizontal_adjustment.get_value(); + wy += vertical_adjustment.get_value(); + + GdkEvent event; + event.type = GDK_BUTTON_RELEASE; + event.button.x = wx; + event.button.y = wy; + + where = event_frame (&event, 0, 0); + return true; +} + +nframes64_t +Editor::event_frame (GdkEvent* event, double* pcx, double* pcy) const { double cx, cy; @@ -773,10 +811,8 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp case MouseAudition: _scrubbing = true; - last_scrub_frame = 0; - last_scrub_time = 0; - have_full_mouse_speed = false; - memset (mouse_speed, 0, sizeof (double) * mouse_speed_size); + last_scrub_x = event->button.x; + scrubbing_direction = 0; /* rest handled in motion & release */ break; @@ -1110,7 +1146,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT case MouseAudition: _scrubbing = false; - if (last_scrub_frame == 0) { + if (scrubbing_direction == 0) { /* no drag, just a click */ switch (item_type) { case RegionItem: @@ -1467,12 +1503,6 @@ Editor::left_automation_track () return false; } -static gboolean -_update_mouse_speed (void *arg) -{ - return static_cast(arg)->update_mouse_speed (); -} - bool Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type, bool from_autoscroll) { @@ -1509,56 +1539,53 @@ Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item switch (mouse_mode) { case MouseAudition: if (_scrubbing) { - struct timeval tmnow; - - if (last_scrub_frame == 0) { - /* first motion, just set up the variables */ + double delta; - last_scrub_frame = (nframes64_t) drag_info.current_pointer_frame; - gettimeofday (&tmnow, 0); - last_scrub_time = tmnow.tv_sec * 1000000.0 + tmnow.tv_usec; - session->request_locate (last_scrub_frame, true); + if (scrubbing_direction == 0) { + /* first move */ + session->request_locate (drag_info.current_pointer_frame, false); + session->request_transport_speed (0.1); + scrubbing_direction = 1; } else { - /* how fast is the mouse moving ? */ - - double speed; - nframes_t distance; - double time; - double dir; -#if 1 - if (last_scrub_frame < (nframes64_t) drag_info.current_pointer_frame) { - distance = (nframes64_t) drag_info.current_pointer_frame - last_scrub_frame; - dir = 1.0; - } else { - distance = last_scrub_frame - (nframes64_t) drag_info.current_pointer_frame; - dir = -1.0; - } -#else - if (drag_info.grab_x < drag_info.current_pointer_x) { - distance = drag_info.current_pointer_x - drag_info.grab_x; - dir = -1.0; + + if (last_scrub_x > drag_info.current_pointer_x) { + /* move to the left */ + + if (scrubbing_direction > 0) { + /* we reversed direction to go backwards */ + + session->request_transport_speed (-0.1); + + } else { + /* still moving to the left (backwards) */ + + delta = 0.005 * (last_scrub_x - drag_info.current_pointer_x); + session->request_transport_speed (session->transport_speed() - delta); + } + + scrubbing_direction = -1; + } else { - distance = drag_info.grab_x - drag_info.current_pointer_x; - dir = 1.0; - } -#endif - - gettimeofday (&tmnow, 0); - time = (tmnow.tv_sec * 1000000.0 + tmnow.tv_usec) - last_scrub_time; - last_scrub_frame = drag_info.current_pointer_frame; - last_scrub_time = (tmnow.tv_sec * 1000000.0) + tmnow.tv_usec; - speed = ((double)distance/session->frame_rate()) / (time/1000000.0); // frames/sec - - add_mouse_speed (speed, dir); - - if (mouse_speed_update < 0) { - mouse_speed_update = g_timeout_add (10, _update_mouse_speed, this); - update_mouse_speed (); + /* move to the right */ + if (scrubbing_direction < 0) { + /* we reversed direction to go forward */ + + session->request_transport_speed (0.1); + } else { + /* still moving to the right */ + + delta = 0.005 * (drag_info.current_pointer_x - last_scrub_x); + session->request_transport_speed (session->transport_speed() + delta); + } + + scrubbing_direction = 1; } } + + last_scrub_x = drag_info.current_pointer_x; } default: @@ -2607,8 +2634,7 @@ Editor::start_control_point_grab (ArdourCanvas::Item* item, GdkEvent* event) drag_info.grab_x = control_point->get_x(); drag_info.grab_y = control_point->get_y(); control_point->line().parent_group().i2w(drag_info.grab_x, drag_info.grab_y); - track_canvas.w2c(drag_info.grab_x, drag_info.grab_y, - drag_info.grab_x, drag_info.grab_y); + track_canvas.w2c(drag_info.grab_x, drag_info.grab_y, drag_info.grab_x, drag_info.grab_y); drag_info.grab_frame = pixel_to_frame(drag_info.grab_x); @@ -3757,12 +3783,13 @@ Editor::create_region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent snap_to (start, -1); const Meter& m = session->tempo_map().meter_at(start); const Tempo& t = session->tempo_map().tempo_at(start); - double length = m.frames_per_bar(t, session->frame_rate()); + double length = floor (m.frames_per_bar(t, session->frame_rate())); boost::shared_ptr src = session->create_midi_source_for_session(*diskstream.get()); - mtv->playlist()->add_region (boost::dynamic_pointer_cast(RegionFactory::create( - src, 0, length, PBD::basename_nosuffix(src->name()))), start); + mtv->playlist()->add_region (boost::dynamic_pointer_cast + (RegionFactory::create(src, 0, (nframes_t) length, + PBD::basename_nosuffix(src->name()))), start); XMLNode &after = mtv->playlist()->get_state(); session->add_command(new MementoCommand(*mtv->playlist().get(), &before, &after)); commit_reversible_command(); @@ -3788,17 +3815,22 @@ Editor::region_view_item_click (AudioRegionView& rv, GdkEventButton* event) speed = rtv->get_diskstream()->speed(); } - if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Alt))) { - - align_region (rv.region(), SyncPoint, (nframes_t) (edit_cursor->current_frame * speed)); - - } else if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) { + nframes64_t where = get_preferred_edit_position(); - align_region (rv.region(), End, (nframes_t) (edit_cursor->current_frame * speed)); + if (where >= 0) { - } else { - - align_region (rv.region(), Start, (nframes_t) (edit_cursor->current_frame * speed)); + if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Alt))) { + + align_region (rv.region(), SyncPoint, (nframes_t) (where * speed)); + + } else if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) { + + align_region (rv.region(), End, (nframes_t) (where * speed)); + + } else { + + align_region (rv.region(), Start, (nframes_t) (where * speed)); + } } } } @@ -5197,90 +5229,3 @@ Editor::track_height_step_timeout () return true; } - -void -Editor::add_mouse_speed (double speed, double dir) -{ - size_t index; - - mouse_direction = dir; - - index = mouse_speed_entries; - - if (++index >= mouse_speed_size) { - index = 0; - have_full_mouse_speed = true; - } - - mouse_speed[index] = speed; - mouse_speed_entries = index; -} - -double -Editor::compute_mouse_speed () -{ - double total = 0; - - if (!have_full_mouse_speed) { - - /* partial speed buffer, just use whatever we have so far */ - - if (mouse_speed_entries == 0 ) { - return 0.0; - } - - for (size_t n = 0; n < mouse_speed_entries; ++n) { - total += mouse_speed[n]; - } - - return mouse_direction * total/mouse_speed_entries; - } - - /* compute the average (effectively low-pass filtering) mouse speed - across the entire buffer. - */ - - for (size_t n = 0; n < mouse_speed_size; ++n) { - total += mouse_speed[n]; - } - - - return mouse_direction * total/mouse_speed_size; -} - -bool -Editor::update_mouse_speed () -{ - double speed; - - if (!_scrubbing) { - session->request_transport_speed (0.0); - mouse_speed_update = -1; - return false; - } - - speed = compute_mouse_speed (); - - struct timeval tmnow; - - gettimeofday (&tmnow, 0); - double now = (tmnow.tv_sec * 1000000.0) + tmnow.tv_usec; - - if (now - last_scrub_time > 250000) { - - // 0.25 seconds since last mouse motion, start to brake - - if (fabs (speed) < 0.1) { - /* don't asymptotically approach zero */ - memset (mouse_speed, 0, sizeof (double) * mouse_speed_size); - speed = 0.0; - } else if (fabs (speed) < 0.25) { - add_mouse_speed (fabs (speed * 0.2), mouse_direction); - } else { - add_mouse_speed (fabs (speed * 0.6), mouse_direction); - } - } - - session->request_transport_speed (speed); - return _scrubbing; -} diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index 2cc30aee17..7ae7706928 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -95,17 +95,10 @@ Editor::redo (uint32_t n) } } -int -Editor::ensure_cursor (nframes_t *pos) -{ - *pos = edit_cursor->current_frame; - return 0; -} - void Editor::split_region () { - split_region_at (edit_cursor->current_frame); + split_region_at (get_preferred_edit_position()); } void @@ -137,8 +130,21 @@ Editor::split_regions_at (nframes_t where, RegionSelection& regions) snap_to (where); } + for (RegionSelection::iterator a = regions.begin(); a != regions.end(); ) { - for (RegionSelection::iterator a = regions.begin(); a != regions.end(); ++a) { + RegionSelection::iterator tmp; + + /* XXX this test needs to be more complicated, to make sure we really + have something to split. + */ + + if (!(*a)->region()->covers (where)) { + ++a; + continue; + } + + tmp = a; + ++tmp; boost::shared_ptr pl = (*a)->region()->playlist(); @@ -161,6 +167,7 @@ Editor::split_regions_at (nframes_t where, RegionSelection& regions) session->add_command(new MementoCommand(*pl, &before, &after)); } + a = tmp; } while (used_playlists.size() > 0) { @@ -883,7 +890,7 @@ Editor::cursor_align (bool playhead_to_edit) { if (playhead_to_edit) { if (session) { - session->request_locate (edit_cursor->current_frame); + session->request_locate (get_preferred_edit_position()); } } else { edit_cursor->set_position (playhead_cursor->current_frame); @@ -893,8 +900,8 @@ Editor::cursor_align (bool playhead_to_edit) void Editor::edit_cursor_backward () { - nframes_t pos; - nframes_t cnt; + nframes64_t pos; + nframes64_t cnt; float prefix; bool was_floating; @@ -908,9 +915,11 @@ Editor::edit_cursor_backward () } } - pos = edit_cursor->current_frame; + if ((pos = get_preferred_edit_position()) < 0) { + return; + } - if ((nframes_t) pos < cnt) { + if (pos < cnt) { pos = 0; } else { pos -= cnt; @@ -1099,12 +1108,14 @@ Editor::temporal_zoom (gdouble fpu) { if (!session) return; - nframes_t current_page = current_page_frames(); - nframes_t current_leftmost = leftmost_frame; - nframes_t current_rightmost; - nframes_t current_center; - nframes_t new_page; - nframes_t leftmost_after_zoom = 0; + nframes64_t current_page = current_page_frames(); + nframes64_t current_leftmost = leftmost_frame; + nframes64_t current_rightmost; + nframes64_t current_center; + nframes64_t new_page; + nframes64_t leftmost_after_zoom = 0; + nframes64_t where; + bool in_track_canvas; double nfpu; nfpu = fpu; @@ -1143,10 +1154,38 @@ Editor::temporal_zoom (gdouble fpu) } break; + case ZoomFocusMouse: + /* try to keep the mouse over the same point in the display */ + + if (!mouse_frame (where, in_track_canvas)) { + /* use playhead instead */ + where = playhead_cursor->current_frame; + + if (where > new_page/2) { + leftmost_after_zoom = where - (new_page/2); + } else { + leftmost_after_zoom = 0; + } + + } else { + + double l = - ((new_page * ((where - current_leftmost)/(double)current_page)) - where); + + if (l < 0) { + leftmost_after_zoom = 0; + } else if (l > max_frames) { + leftmost_after_zoom = max_frames - new_page; + } else { + leftmost_after_zoom = (nframes64_t) l; + } + } + + break; + case ZoomFocusEdit: /* try to keep the edit cursor in the center */ - if (edit_cursor->current_frame > new_page/2) { - leftmost_after_zoom = edit_cursor->current_frame - (new_page/2); + if (get_preferred_edit_position() > new_page/2) { + leftmost_after_zoom = get_preferred_edit_position() - (new_page/2); } else { leftmost_after_zoom = 0; } @@ -1160,6 +1199,8 @@ Editor::temporal_zoom (gdouble fpu) // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), current_leftmost, frames_per_unit)); // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_after_zoom, nfpu)); // commit_reversible_command (); + + // cerr << "repos & zoom to " << leftmost_after_zoom << " @ " << nfpu << endl; reposition_and_zoom (leftmost_after_zoom, nfpu); } @@ -1579,7 +1620,7 @@ Editor::insert_region_list_selection (float times) begin_reversible_command (_("insert region")); XMLNode &before = playlist->get_state(); - playlist->add_region ((RegionFactory::create (region)), edit_cursor->current_frame, times); + playlist->add_region ((RegionFactory::create (region)), get_preferred_edit_position(), times); session->add_command(new MementoCommand(*playlist, &before, &playlist->get_state())); commit_reversible_command (); } @@ -1666,7 +1707,7 @@ Editor::play_from_start () void Editor::play_from_edit_cursor () { - session->request_locate (edit_cursor->current_frame, true); + session->request_locate (get_preferred_edit_position(), true); } void @@ -2275,7 +2316,8 @@ Editor::set_region_sync_from_edit_cursor () { /* Check that at the edit cursor is in at least one of the selected regions */ RegionSelection::const_iterator i = selection->regions.begin(); - while (i != selection->regions.end() && !(*i)->region()->covers (edit_cursor->current_frame)) { + + while (i != selection->regions.end() && !(*i)->region()->covers (get_preferred_edit_position())) { ++i; } @@ -2290,11 +2332,11 @@ Editor::set_region_sync_from_edit_cursor () for (RegionSelection::iterator j = selection->regions.begin(); j != selection->regions.end(); ++j) { boost::shared_ptr r = (*j)->region(); XMLNode &before = r->playlist()->get_state(); - r->set_sync_position (edit_cursor->current_frame); + r->set_sync_position (get_preferred_edit_position()); XMLNode &after = r->playlist()->get_state(); session->add_command(new MementoCommand(*(r->playlist()), &before, &after)); } - + commit_reversible_command (); } @@ -2334,13 +2376,13 @@ Editor::naturalize () void Editor::align (RegionPoint what) { - align_selection (what, edit_cursor->current_frame); + align_selection (what, get_preferred_edit_position()); } void Editor::align_relative (RegionPoint what) { - align_selection_relative (what, edit_cursor->current_frame); + align_selection_relative (what, get_preferred_edit_position()); } struct RegionSortByTime { @@ -2481,7 +2523,7 @@ Editor::trim_region_to_edit_cursor () } XMLNode &before = region->playlist()->get_state(); - region->trim_end( session_frame_to_track_frame(edit_cursor->current_frame, speed), this); + region->trim_end( session_frame_to_track_frame(get_preferred_edit_position(), speed), this); XMLNode &after = region->playlist()->get_state(); session->add_command(new MementoCommand(*(region->playlist()), &before, &after)); } @@ -2513,12 +2555,10 @@ Editor::trim_region_from_edit_cursor () } XMLNode &before = region->playlist()->get_state(); - region->trim_front ( session_frame_to_track_frame(edit_cursor->current_frame, speed), this); + region->trim_front ( session_frame_to_track_frame(get_preferred_edit_position(), speed), this); XMLNode &after = region->playlist()->get_state(); session->add_command(new MementoCommand(*(region->playlist()), &before, &after)); } - - commit_reversible_command (); } /** Unfreeze selected routes */ @@ -2945,26 +2985,19 @@ Editor::cut_copy_ranges (CutCopyOp op) void Editor::paste (float times) { - paste_internal (edit_cursor->current_frame, times); + paste_internal (get_preferred_edit_position(), times); } void Editor::mouse_paste () { - int x, y; - double wx, wy; + nframes64_t where; + bool ignored; - track_canvas.get_pointer (x, y); - track_canvas.window_to_world (x, y, wx, wy); - wx += horizontal_adjustment.get_value(); - wy += vertical_adjustment.get_value(); + if (!mouse_frame (where, ignored)) { + return; + } - GdkEvent event; - event.type = GDK_BUTTON_RELEASE; - event.button.x = wx; - event.button.y = wy; - - nframes_t where = event_frame (&event, 0, 0); snap_to (where); paste_internal (where, 1); } @@ -2979,7 +3012,7 @@ Editor::paste_internal (nframes_t position, float times) } if (position == max_frames) { - position = edit_cursor->current_frame; + position = get_preferred_edit_position(); } begin_reversible_command (_("paste")); @@ -3050,7 +3083,7 @@ Editor::paste_named_selection (float times) ++tmp; XMLNode &before = apl->get_state(); - apl->paste (*chunk, edit_cursor->current_frame, times); + apl->paste (*chunk, get_preferred_edit_position(), times); session->add_command(new MementoCommand(*apl, &before, &apl->get_state())); if (tmp != ns->playlists.end()) { @@ -3162,7 +3195,7 @@ Editor::center_edit_cursor () { float page = canvas_width * frames_per_unit; - center_screen_internal (edit_cursor->current_frame, page); + center_screen_internal (get_preferred_edit_position(), page); } void @@ -3185,7 +3218,7 @@ Editor::nudge_selected_tracks (bool use_edit_cursor, bool forwards) nframes_t start; if (use_edit_cursor) { - start = edit_cursor->current_frame; + start = get_preferred_edit_position(); } else { start = 0; } diff --git a/gtk2_ardour/editor_selection.cc b/gtk2_ardour/editor_selection.cc index 910534690e..12ca558ea4 100644 --- a/gtk2_ardour/editor_selection.cc +++ b/gtk2_ardour/editor_selection.cc @@ -616,16 +616,10 @@ Editor::track_selection_changed () } for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { - (*i)->set_selected (false); - if (mouse_mode == MouseRange) { - (*i)->hide_selection (); - } - } - - for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { - (*i)->set_selected (true); - if (mouse_mode == MouseRange) { - (*i)->show_selection (selection->time); + if (find (selection->tracks.begin(), selection->tracks.end(), *i) != selection->tracks.end()) { + (*i)->set_selected (true); + } else { + (*i)->set_selected (false); } } } @@ -652,6 +646,7 @@ Editor::time_selection_changed () } else { ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, true); } + } void diff --git a/gtk2_ardour/editor_timefx.cc b/gtk2_ardour/editor_timefx.cc index 2efdc03f8f..df0a73c965 100644 --- a/gtk2_ardour/editor_timefx.cc +++ b/gtk2_ardour/editor_timefx.cc @@ -39,6 +39,7 @@ #include #include #include +#include #include "i18n.h" @@ -87,29 +88,29 @@ gint Editor::TimeStretchDialog::update_progress () { progress_bar.set_fraction (request.progress); - return request.running; + return !request.done; } void Editor::TimeStretchDialog::cancel_timestretch_in_progress () { status = -2; - request.running = false; + request.cancel = true; + first_cancel.disconnect(); } gint Editor::TimeStretchDialog::delete_timestretch_in_progress (GdkEventAny* ev) { status = -2; - request.running = false; + request.cancel = true; + first_delete.disconnect(); return TRUE; } int Editor::run_timestretch (RegionSelection& regions, float fraction) { - pthread_t thread; - if (current_timestretch == 0) { current_timestretch = new TimeStretchDialog (*this); } @@ -130,27 +131,30 @@ Editor::run_timestretch (RegionSelection& regions, float fraction) current_timestretch->request.quick_seek = current_timestretch->quick_button.get_active(); current_timestretch->request.antialias = !current_timestretch->antialias_button.get_active(); current_timestretch->request.progress = 0.0f; - current_timestretch->request.running = true; + current_timestretch->request.done = false; + current_timestretch->request.cancel = false; /* re-connect the cancel button and delete events */ current_timestretch->first_cancel.disconnect(); current_timestretch->first_delete.disconnect(); - current_timestretch->cancel_button->signal_clicked().connect (mem_fun (current_timestretch, &TimeStretchDialog::cancel_timestretch_in_progress)); - current_timestretch->signal_delete_event().connect (mem_fun (current_timestretch, &TimeStretchDialog::delete_timestretch_in_progress)); + current_timestretch->first_cancel = current_timestretch->cancel_button->signal_clicked().connect + (mem_fun (current_timestretch, &TimeStretchDialog::cancel_timestretch_in_progress)); + current_timestretch->first_delete = current_timestretch->signal_delete_event().connect + (mem_fun (current_timestretch, &TimeStretchDialog::delete_timestretch_in_progress)); - if (pthread_create_and_store ("timestretch", &thread, 0, timestretch_thread, current_timestretch)) { + if (pthread_create_and_store ("timestretch", ¤t_timestretch->request.thread, 0, timestretch_thread, current_timestretch)) { current_timestretch->hide (); error << _("timestretch cannot be started - thread creation error") << endmsg; return -1; } - pthread_detach (thread); + pthread_detach (current_timestretch->request.thread); sigc::connection c = Glib::signal_timeout().connect (mem_fun (current_timestretch, &TimeStretchDialog::update_progress), 100); - while (current_timestretch->request.running) { + while (!current_timestretch->request.done) { gtk_main_iteration (); } @@ -195,31 +199,34 @@ Editor::do_timestretch (TimeStretchDialog& dialog) continue; } - dialog.request.region = region; - - if (!dialog.request.running) { + if (dialog.request.cancel) { /* we were cancelled */ dialog.status = 1; return; } - if ((new_region = session->tempoize_region (dialog.request)) == 0) { + Stretch stretch (*session, dialog.request); + + if (stretch.run (region)) { dialog.status = -1; - dialog.request.running = false; + dialog.request.done = true; return; } - XMLNode &before = playlist->get_state(); - playlist->replace_region (region, new_region, region->position()); - XMLNode &after = playlist->get_state(); - session->add_command (new MementoCommand(*playlist, &before, &after)); + if (!stretch.results.empty()) { + new_region = stretch.results.front(); + + XMLNode &before = playlist->get_state(); + playlist->replace_region (region, new_region, region->position()); + XMLNode &after = playlist->get_state(); + session->add_command (new MementoCommand(*playlist, &before, &after)); + } i = tmp; } dialog.status = 0; - dialog.request.running = false; - dialog.request.region.reset (); + dialog.request.done = true; } void* diff --git a/gtk2_ardour/enums.cc b/gtk2_ardour/enums.cc index c33b2965c3..f626bfb968 100644 --- a/gtk2_ardour/enums.cc +++ b/gtk2_ardour/enums.cc @@ -38,6 +38,7 @@ setup_gtk_ardour_enums () AudioClock::Mode clock_mode; Width width; ImportMode import_mode; + EditPoint edit_point; #define REGISTER(e) enum_writer.register_distinct (typeid(e).name(), i, s); i.clear(); s.clear() #define REGISTER_BITS(e) enum_writer.register_bits (typeid(e).name(), i, s); i.clear(); s.clear() @@ -60,4 +61,9 @@ setup_gtk_ardour_enums () REGISTER_ENUM (ImportAsRegion); REGISTER_ENUM (ImportAsTapeTrack); REGISTER (import_mode); + + REGISTER_ENUM (EditAtPlayhead); + REGISTER_ENUM (EditAtMouse); + REGISTER_ENUM (EditAtSelectedMarker); + REGISTER (edit_point); } diff --git a/gtk2_ardour/marker_selection.h b/gtk2_ardour/marker_selection.h new file mode 100644 index 0000000000..aa1413ed3e --- /dev/null +++ b/gtk2_ardour/marker_selection.h @@ -0,0 +1,31 @@ +/* + Copyright (C) 2000-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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __ardour_gtk_marker_selection_h__ +#define __ardour_gtk_marker_selection_h__ + +#include + +#include "marker.h" + +struct MarkerSelection : public std::list +{ +}; + +#endif /* __ardour_gtk_marker_selection_h__ */ diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h index 03d5897c1a..f32c0565e3 100644 --- a/gtk2_ardour/public_editor.h +++ b/gtk2_ardour/public_editor.h @@ -185,11 +185,11 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulThingWithGoingAway virtual void toggle_playback (bool with_abort) = 0; virtual void transition_to_rolling (bool fwd) = 0; - virtual nframes_t unit_to_frame (double unit) = 0; - virtual double frame_to_unit (nframes_t frame) = 0; - virtual double frame_to_unit (double frame) = 0; - virtual nframes_t pixel_to_frame (double pixel) = 0; - virtual gulong frame_to_pixel (nframes_t frame) = 0; + virtual nframes_t unit_to_frame (double unit) const = 0; + virtual double frame_to_unit (nframes_t frame) const = 0; + virtual double frame_to_unit (double frame) const = 0; + virtual nframes64_t pixel_to_frame (double pixel) const = 0; + virtual gulong frame_to_pixel (nframes64_t frame) const = 0; virtual Selection& get_selection () const = 0; virtual Selection& get_cut_buffer () const = 0; virtual bool extend_selection_to_track (TimeAxisView&) = 0; diff --git a/gtk2_ardour/selection.cc b/gtk2_ardour/selection.cc index f0037588a0..c6bb5c37af 100644 --- a/gtk2_ardour/selection.cc +++ b/gtk2_ardour/selection.cc @@ -143,6 +143,15 @@ Selection::clear_lines () } } +void +Selection::clear_markers () +{ + if (!markers.empty()) { + markers.clear (); + MarkersChanged(); + } +} + void Selection::toggle (boost::shared_ptr pl) { @@ -575,7 +584,8 @@ Selection::empty () playlists.empty () && lines.empty () && time.empty () && - playlists.empty () + playlists.empty () && + markers.empty() ; } @@ -700,3 +710,43 @@ Selection::select_edit_group_regions () add (*i); } } + +void +Selection::set (Marker* m) +{ + clear_markers (); + add (m); +} + +void +Selection::toggle (Marker* m) +{ + MarkerSelection::iterator i; + + if ((i = find (markers.begin(), markers.end(), m)) == markers.end()) { + add (m); + } else { + remove (m); + } +} + +void +Selection::remove (Marker* m) +{ + MarkerSelection::iterator i; + + if ((i = find (markers.begin(), markers.end(), m)) != markers.end()) { + markers.erase (i); + MarkersChanged(); + } +} + + +void +Selection::add (Marker* m) +{ + if (find (markers.begin(), markers.end(), m) == markers.end()) { + markers.push_back (m); + MarkersChanged(); + } +} diff --git a/gtk2_ardour/selection.h b/gtk2_ardour/selection.h index 5e9bc04759..2b2db77360 100644 --- a/gtk2_ardour/selection.h +++ b/gtk2_ardour/selection.h @@ -32,6 +32,7 @@ #include "playlist_selection.h" #include "processor_selection.h" #include "point_selection.h" +#include "marker_selection.h" class TimeAxisView; class RegionView; @@ -71,6 +72,7 @@ class Selection : public sigc::trackable AutomationSelection lines; PlaylistSelection playlists; PointSelection points; + MarkerSelection markers; Selection (PublicEditor const * e) : editor (e), next_time_id (0) { clear(); @@ -84,6 +86,7 @@ class Selection : public sigc::trackable sigc::signal LinesChanged; sigc::signal PlaylistsChanged; sigc::signal PointsChanged; + sigc::signal MarkersChanged; void clear (); bool empty(); @@ -106,6 +109,7 @@ class Selection : public sigc::trackable void set (boost::shared_ptr); void set (const std::list >&); void set (AutomationSelectable*); + void set (Marker*); void toggle (TimeAxisView*); void toggle (const std::list&); @@ -116,6 +120,7 @@ class Selection : public sigc::trackable void toggle (boost::shared_ptr); void toggle (const std::list >&); void toggle (const std::vector&); + void toggle (Marker*); void add (TimeAxisView*); void add (const std::list&); @@ -125,7 +130,8 @@ class Selection : public sigc::trackable void add (ARDOUR::AutomationList*); void add (boost::shared_ptr); void add (const std::list >&); - + void add (Marker*); + void remove (TimeAxisView*); void remove (const std::list&); void remove (RegionView*); @@ -135,6 +141,7 @@ class Selection : public sigc::trackable void remove (boost::shared_ptr); void remove (const std::list >&); void remove (const list&); + void remove (Marker*); void replace (uint32_t time_index, nframes_t start, nframes_t end); @@ -144,6 +151,7 @@ class Selection : public sigc::trackable void clear_lines (); void clear_playlists (); void clear_points (); + void clear_markers (); void foreach_region (void (ARDOUR::Region::*method)(void)); void foreach_regionview (void (RegionView::*method)(void)); diff --git a/gtk2_ardour/time_axis_view.cc b/gtk2_ardour/time_axis_view.cc index 4d2533ebff..cf0e39cdbd 100644 --- a/gtk2_ardour/time_axis_view.cc +++ b/gtk2_ardour/time_axis_view.cc @@ -545,12 +545,16 @@ TimeAxisView::popup_size_menu (guint32 when) void TimeAxisView::set_selected (bool yn) { - AxisView::set_selected (yn); + if (yn == _selected) { + return; + } + + Selectable::set_selected (yn); if (_selected) { controls_ebox.set_name (controls_base_selected_name); controls_frame.set_name (controls_base_selected_name); - + /* propagate any existing selection, if the mode is right */ if (editor.current_mouse_mode() == Editing::MouseRange && !editor.get_selection().time.empty()) { @@ -571,8 +575,6 @@ TimeAxisView::set_selected (bool yn) for (Children::iterator i = children.begin(); i != children.end(); ++i) { (*i)->set_selected (false); } - - } } diff --git a/gtk2_ardour/utils.cc b/gtk2_ardour/utils.cc index 570a481c11..941132396a 100644 --- a/gtk2_ardour/utils.cc +++ b/gtk2_ardour/utils.cc @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -325,6 +326,61 @@ rgba_from_style (string style, uint32_t r, uint32_t g, uint32_t b, uint32_t a, s } } + +Gdk::Color +color_from_style (string widget_style_name, int state, string attr) +{ + GtkStyle* style; + + style = gtk_rc_get_style_by_paths (gtk_settings_get_default(), + widget_style_name.c_str(), + 0, G_TYPE_NONE); + + if (!style) { + error << string_compose (_("no style found for %1, using red"), style) << endmsg; + return Gdk::Color ("red"); + } + + cerr << "got style for " << widget_style_name << endl; + + if (attr == "fg") { + return Gdk::Color (&style->fg[state]); + } + + if (attr == "bg") { + cerr << "returning color from bg\n"; + return Gdk::Color (&style->bg[state]); + } + + if (attr == "light") { + return Gdk::Color (&style->light[state]); + } + + if (attr == "dark") { + return Gdk::Color (&style->dark[state]); + } + + if (attr == "mid") { + return Gdk::Color (&style->mid[state]); + } + + if (attr == "text") { + return Gdk::Color (&style->text[state]); + } + + if (attr == "base") { + return Gdk::Color (&style->base[state]); + } + + if (attr == "text_aa") { + return Gdk::Color (&style->text_aa[state]); + } + + error << string_compose (_("unknown style attribute %1 requested for color; using \"red\""), attr) << endmsg; + return Gdk::Color ("red"); +} + + bool canvas_item_visible (ArdourCanvas::Item* item) { diff --git a/gtk2_ardour/utils.h b/gtk2_ardour/utils.h index cae78f3d0a..74a6eebd21 100644 --- a/gtk2_ardour/utils.h +++ b/gtk2_ardour/utils.h @@ -67,6 +67,8 @@ Pango::FontDescription* get_font_for_style (std::string widgetname); uint32_t rgba_from_style (std::string, uint32_t, uint32_t, uint32_t, uint32_t, std::string = "fg", int = Gtk::STATE_NORMAL, bool = true); +Gdk::Color color_from_style (std::string widget_style_name, int state, std::string attr); + void decorate (Gtk::Window& w, Gdk::WMDecoration d); bool canvas_item_visible (ArdourCanvas::Item* item); -- cgit v1.2.3