diff options
Diffstat (limited to 'gtk2_ardour/editor.cc')
-rw-r--r-- | gtk2_ardour/editor.cc | 487 |
1 files changed, 367 insertions, 120 deletions
diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index e0f8b24b53..613c34f551 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -110,7 +110,6 @@ const double Editor::timebar_height = 15.0; #include "editor_xpms" static const gchar *_snap_type_strings[] = { - N_("None"), N_("CD Frames"), N_("SMPTE Frames"), N_("SMPTE Seconds"), @@ -125,7 +124,6 @@ static const gchar *_snap_type_strings[] = { N_("Beats"), N_("Bars"), N_("Marks"), - N_("Edit Point"), N_("Region starts"), N_("Region ends"), N_("Region syncs"), @@ -134,7 +132,8 @@ static const gchar *_snap_type_strings[] = { }; static const gchar *_snap_mode_strings[] = { - N_("Normal"), + N_("No Grid"), + N_("Grid"), N_("Magnetic"), 0 }; @@ -152,7 +151,7 @@ static const gchar *_zoom_focus_strings[] = { N_("Center"), N_("Playhead"), N_("Mouse"), - N_("Marker"), + N_("Edit Point"), 0 }; @@ -186,14 +185,15 @@ Editor::Editor () minsec_label (_("Mins:Secs")), bbt_label (_("Bars:Beats")), smpte_label (_("Timecode")), - frame_label (_("Frames")), + frame_label (_("Samples")), tempo_label (_("Tempo")), meter_label (_("Meter")), mark_label (_("Location Markers")), range_mark_label (_("Range Markers")), transport_mark_label (_("Loop/Punch Ranges")), + cd_mark_label (_("CD Markers")), - edit_packer (3, 3, false), + edit_packer (3, 3, true), /* the values here don't matter: layout widgets reset them as needed. @@ -221,7 +221,8 @@ Editor::Editor () /* nudge */ - nudge_clock (X_("nudge"), false, X_("NudgeClock"), true, true) + nudge_clock (X_("nudge"), false, X_("NudgeClock"), true, true), + meters_running(false) { constructed = false; @@ -246,7 +247,6 @@ Editor::Editor () clicked_routeview = 0; clicked_crossfadeview = 0; clicked_control_point = 0; - latest_regionview = 0; last_update_frame = 0; drag_info.item = 0; current_mixer_strip = 0; @@ -257,15 +257,6 @@ Editor::Editor () 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_preference (_edit_point); - snap_threshold = 5.0; bbt_beat_subdivision = 4; canvas_width = 0; @@ -292,7 +283,8 @@ Editor::Editor () verbose_cursor_on = true; route_removal = false; show_automatic_regions_in_region_list = true; - region_list_sort_type = (Editing::RegionListSortType) 0; + + region_list_sort_type = (Editing::RegionListSortType) 0; have_pending_keyboard_selection = false; _follow_playhead = true; _xfade_visibility = true; @@ -322,7 +314,7 @@ Editor::Editor () entered_marker = 0; clear_entered_track = false; _new_regionviews_show_envelope = false; - current_timestretch = 0; + current_timefx = 0; in_edit_group_row_change = false; last_canvas_frame = 0; playhead_cursor = 0; @@ -331,6 +323,8 @@ Editor::Editor () _dragging_playhead = false; _dragging_edit_point = false; _dragging_hscrollbar = false; + select_new_marker = false; + zoomed_to_region = false; scrubbing_direction = 0; @@ -350,6 +344,8 @@ Editor::Editor () set_midi_edit_mode (MidiEditPencil, true); set_mouse_mode (MouseObject, true); + last_visual_state.frames_per_unit = 0; + frames_per_unit = 2048; /* too early to use reset_zoom () */ reset_hscrollbar_stepping (); @@ -361,7 +357,7 @@ Editor::Editor () initialize_canvas (); edit_controls_vbox.set_spacing (0); - horizontal_adjustment.signal_value_changed().connect (mem_fun(*this, &Editor::canvas_horizontally_scrolled)); + horizontal_adjustment.signal_value_changed().connect (mem_fun(*this, &Editor::canvas_horizontally_scrolled), false); vertical_adjustment.signal_value_changed().connect (mem_fun(*this, &Editor::tie_vertical_scrolling), true); track_canvas.set_hadjustment (horizontal_adjustment); @@ -438,6 +434,10 @@ Editor::Editor () mark_label.set_size_request (-1, (int)timebar_height); mark_label.set_alignment (1.0, 0.5); mark_label.set_padding (5,0); + cd_mark_label.set_name ("EditorTimeButton"); + cd_mark_label.set_size_request (-1, (int)timebar_height); + cd_mark_label.set_alignment (1.0, 0.5); + cd_mark_label.set_padding (5,0); range_mark_label.set_name ("EditorTimeButton"); range_mark_label.set_size_request (-1, (int)timebar_height); range_mark_label.set_alignment (1.0, 0.5); @@ -510,7 +510,7 @@ Editor::Editor () CellRendererToggle* route_list_visible_cell = dynamic_cast<CellRendererToggle*>(route_list_display.get_column_cell_renderer (0)); route_list_visible_cell->property_activatable() = true; route_list_visible_cell->property_radio() = false; - + route_display_model->signal_row_deleted().connect (mem_fun (*this, &Editor::route_list_delete)); route_display_model->signal_row_changed().connect (mem_fun (*this, &Editor::route_list_change)); @@ -599,6 +599,10 @@ Editor::Editor () region_list_display.append_column (_("Regions"), region_list_columns.name); region_list_display.set_headers_visible (false); + CellRendererText* region_name_cell = dynamic_cast<CellRendererText*>(region_list_display.get_column_cell_renderer (0)); + region_name_cell->property_editable() = true; + region_name_cell->signal_edited().connect (mem_fun (*this, &Editor::region_name_edit)); + region_list_display.get_selection()->set_select_function (mem_fun (*this, &Editor::region_list_selection_filter)); TreeViewColumn* tv_col = region_list_display.get_column(0); @@ -675,9 +679,12 @@ Editor::Editor () nlabel = manage (new Label (_("Edit Groups"))); nlabel->set_angle (-90); the_notebook.append_page (*edit_group_display_packer, *nlabel); - nlabel = manage (new Label (_("Chunks"))); - nlabel->set_angle (-90); - the_notebook.append_page (named_selection_scroller, *nlabel); + + if (!Profile->get_sae()) { + nlabel = manage (new Label (_("Chunks"))); + nlabel->set_angle (-90); + the_notebook.append_page (named_selection_scroller, *nlabel); + } the_notebook.set_show_tabs (true); the_notebook.set_scrollable (true); @@ -713,7 +720,14 @@ Editor::Editor () /* register actions now so that set_state() can find them and set toggles/checks etc */ register_actions (); - + + snap_type = SnapToBeat; + set_snap_to (snap_type); + snap_mode = SnapOff; + set_snap_mode (snap_mode); + _edit_point = EditAtMouse; + set_edit_point_preference (_edit_point); + XMLNode* node = ARDOUR_UI::instance()->editor_settings(); set_state (*node); @@ -882,19 +896,6 @@ Editor::tie_vertical_scrolling () } controls_layout.get_vadjustment()->set_value (y1); - -#ifdef GTKOSX - /* the way idle updates and immediate window flushing work on GTK-Quartz - requires that we force an immediate redraw right here. The controls - layout will do the same all by itself, as does the canvas widget, but - most of the time, the canvas itself hasn't updated itself because its - idle handler hasn't run. consequently, the call that its layout makes - to gdk_window_process_updates() finds nothing to do. here, we force - the update to happen, then request a flush of the new window state. - */ - track_canvas.update_now (); - gdk_window_process_updates (GTK_LAYOUT(track_canvas.gobj())->bin_window, true); -#endif } void @@ -1277,6 +1278,8 @@ Editor::connect_to_session (Session *t) /* register for undo history */ session->register_with_memento_command_factory(_id, this); + + start_updating (); } void @@ -1320,6 +1323,14 @@ Editor::build_cursors () transparent_cursor = new Gdk::Cursor (bits, bits, c, c, 0, 0); } + { + RefPtr<Bitmap> bits; + char pix[4] = { 0, 0, 0, 0 }; + bits = Bitmap::create (pix, 2, 2); + Gdk::Color c; + transparent_cursor = new Gdk::Cursor (bits, bits, c, c, 0, 0); + } + grabber_cursor = new Gdk::Cursor (HAND2); cross_hair_cursor = new Gdk::Cursor (CROSSHAIR); trimmer_cursor = new Gdk::Cursor (SB_H_DOUBLE_ARROW); @@ -1602,10 +1613,21 @@ Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items) items.push_back (MenuElem (_("Sync points"), *sync_point_menu)); - add_item_with_sensitivity (items, MenuElem (_("Audition"), mem_fun(*this, &Editor::audition_selected_region)), selection->regions.size() == 1); + //add_item_with_sensitivity (items, MenuElem (_("Audition"), mem_fun(*this, &Editor::audition_selected_region)), selection->regions.size() == 1); add_item_with_sensitivity (items, MenuElem (_("Export"), mem_fun(*this, &Editor::export_region)), selection->regions.size() == 1); + items.push_back (MenuElem (_("Rename"), mem_fun(*this, &Editor::rename_region))); + items.push_back (MenuElem (_("Popup region editor"), mem_fun(*this, &Editor::edit_region))); + items.push_back (MenuElem (_("Raise to top layer"), mem_fun(*this, &Editor::raise_region_to_top))); + items.push_back (MenuElem (_("Lower to bottom layer"), mem_fun (*this, &Editor::lower_region_to_bottom))); + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Define sync point"), mem_fun(*this, &Editor::set_region_sync_from_edit_point))); + items.push_back (MenuElem (_("Remove sync point"), mem_fun(*this, &Editor::remove_region_sync))); + items.push_back (SeparatorElem()); + + items.push_back (MenuElem (_("Audition"), mem_fun(*this, &Editor::play_selected_region))); + items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_region))); items.push_back (MenuElem (_("Bounce"), mem_fun(*this, &Editor::bounce_region_selection))); #ifdef FFT_ANALYSIS @@ -1779,7 +1801,8 @@ Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items) items.push_back (MenuElem (_("Trim"), *trim_menu)); items.push_back (MenuElem (_("Split"), (mem_fun(*this, &Editor::split_region)))); items.push_back (MenuElem (_("Make mono regions"), (mem_fun(*this, &Editor::split_multichannel_region)))); - items.push_back (MenuElem (_("Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), true)))); + items.push_back (MenuElem (_("Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), false)))); + items.push_back (MenuElem (_("Multi-Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), true)))); items.push_back (MenuElem (_("Fill track"), (mem_fun(*this, &Editor::region_fill_track)))); items.push_back (SeparatorElem()); items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_selected_regions))); @@ -1990,8 +2013,15 @@ Editor::add_bus_or_audio_track_context_items (Menu_Helpers::MenuList& edit_items void Editor::set_snap_to (SnapType st) { + unsigned int snap_ind = (unsigned int)st; snap_type = st; - string str = snap_type_strings[(int) st]; + + if ( snap_ind > snap_type_strings.size() - 1 ) { + snap_ind = 0; + snap_type = (SnapType)snap_ind; + } + + string str = snap_type_strings[snap_ind]; if (str != snap_type_selector.get_active_text()) { snap_type_selector.set_active_text (str); @@ -2029,6 +2059,8 @@ Editor::set_snap_mode (SnapMode mode) void Editor::set_edit_point_preference (EditPoint ep) { + bool changed = _edit_point != ep; + _edit_point = ep; string str = edit_point_strings[(int)ep]; @@ -2036,6 +2068,33 @@ Editor::set_edit_point_preference (EditPoint ep) edit_point_selector.set_active_text (str); } + if (!changed) { + return; + } + + if (Profile->get_sae()) { + + switch (zoom_focus) { + case ZoomFocusMouse: + case ZoomFocusPlayhead: + case ZoomFocusEdit: + switch (_edit_point) { + case EditAtMouse: + set_zoom_focus (ZoomFocusMouse); + break; + case EditAtPlayhead: + set_zoom_focus (ZoomFocusPlayhead); + break; + case EditAtSelectedMarker: + set_zoom_focus (ZoomFocusEdit); + break; + } + break; + default: + break; + } + } + instant_save (); } @@ -2314,7 +2373,7 @@ Editor::snap_to (nframes64_t& start, int32_t direction, bool for_mark) Location* before = 0; Location* after = 0; - if (!session) { + if (!session || snap_mode == SnapOff) { return; } @@ -2325,9 +2384,6 @@ Editor::snap_to (nframes64_t& start, int32_t direction, bool for_mark) nframes64_t presnap = start; switch (snap_type) { - case SnapToFrame: - break; - case SnapToCDFrame: if (direction) { start = (nframes_t) ceil ((double) start / (one_second / 75)) * (one_second / 75); @@ -2429,10 +2485,6 @@ Editor::snap_to (nframes64_t& start, int32_t direction, bool for_mark) start = session->tempo_map().round_to_beat_subdivision (start, 3); break; - case SnapToEditPoint: - start = get_preferred_edit_position (); - break; - case SnapToMark: if (for_mark) { return; @@ -2513,6 +2565,7 @@ Editor::snap_to (nframes64_t& start, int32_t direction, bool for_mark) } default: + /* handled at entry */ return; } @@ -2563,8 +2616,11 @@ Editor::setup_toolbar () { string pixmap_path; +#ifdef GTKOSX + const guint32 FUDGE = 38; // Combo's are stupid - they steal space from the entry for the button +#else const guint32 FUDGE = 18; // Combo's are stupid - they steal space from the entry for the button - +#endif /* Mode Buttons (tool selection) */ @@ -2573,12 +2629,17 @@ Editor::setup_toolbar () mouse_move_button.add (*(manage (new Image (::get_icon("tool_object"))))); mouse_move_button.set_relief(Gtk::RELIEF_NONE); mouse_mode_buttons.push_back (&mouse_move_button); - mouse_select_button.add (*(manage (new Image (get_xpm("tool_range.xpm"))))); - mouse_select_button.set_relief(Gtk::RELIEF_NONE); - mouse_mode_buttons.push_back (&mouse_select_button); - mouse_gain_button.add (*(manage (new Image (::get_icon("tool_gain"))))); - mouse_gain_button.set_relief(Gtk::RELIEF_NONE); - mouse_mode_buttons.push_back (&mouse_gain_button); + + if (!Profile->get_sae()) { + mouse_select_button.add (*(manage (new Image (get_xpm("tool_range.xpm"))))); + mouse_select_button.set_relief(Gtk::RELIEF_NONE); + mouse_mode_buttons.push_back (&mouse_select_button); + + mouse_gain_button.add (*(manage (new Image (::get_icon("tool_gain"))))); + mouse_gain_button.set_relief(Gtk::RELIEF_NONE); + mouse_mode_buttons.push_back (&mouse_gain_button); + } + mouse_zoom_button.add (*(manage (new Image (::get_icon("tool_zoom"))))); mouse_zoom_button.set_relief(Gtk::RELIEF_NONE); mouse_mode_buttons.push_back (&mouse_zoom_button); @@ -2599,9 +2660,13 @@ Editor::setup_toolbar () mode_box->set_spacing(4); mouse_mode_button_box.set_spacing(1); mouse_mode_button_box.pack_start(mouse_move_button, true, true); - mouse_mode_button_box.pack_start(mouse_select_button, true, true); + if (!Profile->get_sae()) { + mouse_mode_button_box.pack_start(mouse_select_button, true, true); + } mouse_mode_button_box.pack_start(mouse_zoom_button, true, true); - mouse_mode_button_box.pack_start(mouse_gain_button, true, true); + if (!Profile->get_sae()) { + mouse_mode_button_box.pack_start(mouse_gain_button, true, true); + } mouse_mode_button_box.pack_start(mouse_timefx_button, true, true); mouse_mode_button_box.pack_start(mouse_audition_button, true, true); mouse_mode_button_box.pack_start(mouse_note_button, true, true); @@ -2692,7 +2757,7 @@ Editor::setup_toolbar () ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_full_button, _("Zoom to Session")); zoom_focus_selector.set_name ("ZoomFocusSelector"); - Gtkmm2ext::set_size_request_to_display_given_text (zoom_focus_selector, "Playhead", FUDGE, 0); + Gtkmm2ext::set_size_request_to_display_given_text (zoom_focus_selector, _("Playhead"), FUDGE, 0); set_popdown_strings (zoom_focus_selector, zoom_focus_strings); zoom_focus_selector.signal_changed().connect (mem_fun(*this, &Editor::zoom_focus_selection_done)); ARDOUR_UI::instance()->tooltips().set_tip (zoom_focus_selector, _("Zoom focus")); @@ -2706,19 +2771,19 @@ Editor::setup_toolbar () snap_box.set_border_width (2); snap_type_selector.set_name ("SnapTypeSelector"); - Gtkmm2ext::set_size_request_to_display_given_text (snap_type_selector, "SMPTE Seconds", 2+FUDGE, 10); + 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, _("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); + 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); + 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")); @@ -3090,50 +3155,67 @@ Editor::history_changed () } void -Editor::duplicate_dialog (bool dup_region) +Editor::duplicate_dialog (bool with_dialog) { - if (selection->regions.empty() && (selection->time.length() == 0)) { - return; - } - - ArdourDialog win ("duplicate dialog"); - Label label (_("Duplicate how many times?")); - Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0); - SpinButton spinner (adjustment); + float times = 1.0f; - win.get_vbox()->set_spacing (12); - win.get_vbox()->pack_start (label); - - /* dialogs have ::add_action_widget() but that puts the spinner in the wrong - place, visually. so do this by hand. - */ - - win.get_vbox()->pack_start (spinner); - spinner.signal_activate().connect (sigc::bind (mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT)); + if (mouse_mode == MouseRange) { + if (selection->time.length() == 0) { + return; + } + } - label.show (); - spinner.show (); + + if (mouse_mode != MouseRange) { - win.add_button (Stock::CANCEL, RESPONSE_CANCEL); - win.add_button (Stock::OK, RESPONSE_ACCEPT); + ensure_entered_region_selected (true); - win.set_position (WIN_POS_MOUSE); + if (selection->regions.empty()) { + return; + } + } - spinner.grab_focus (); + if (with_dialog) { - switch (win.run ()) { - case RESPONSE_ACCEPT: - break; - default: - return; + ArdourDialog win ("duplicate dialog"); + Label label (_("Duplicate how many times?")); + Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0); + SpinButton spinner (adjustment); + + win.get_vbox()->set_spacing (12); + win.get_vbox()->pack_start (label); + + /* dialogs have ::add_action_widget() but that puts the spinner in the wrong + place, visually. so do this by hand. + */ + + win.get_vbox()->pack_start (spinner); + spinner.signal_activate().connect (sigc::bind (mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT)); + + label.show (); + spinner.show (); + + win.add_button (Stock::OK, RESPONSE_ACCEPT); + win.add_button (Stock::CANCEL, RESPONSE_CANCEL); + + win.set_position (WIN_POS_MOUSE); + + spinner.grab_focus (); + + switch (win.run ()) { + case RESPONSE_ACCEPT: + break; + default: + return; + } + + times = adjustment.get_value(); } - float times = adjustment.get_value(); - - if (!selection->regions.empty()) { - duplicate_some_regions (selection->regions, times); - } else { + if (mouse_mode == MouseRange) { duplicate_selection (times); + } else { + duplicate_some_regions (selection->regions, times); } } @@ -3170,6 +3252,25 @@ Editor::set_verbose_canvas_cursor_text (const string & txt) } void +Editor::set_edit_mode (EditMode m) +{ + Config->set_edit_mode (m); +} + +void +Editor::cycle_edit_mode () +{ + switch (Config->get_edit_mode()) { + case Slide: + Config->set_edit_mode (Splice); + break; + case Splice: + Config->set_edit_mode (Slide); + break; + } +} + +void Editor::edit_mode_selection_done () { if (session == 0) { @@ -3192,7 +3293,7 @@ void Editor::snap_type_selection_done () { string choice = snap_type_selector.get_active_text(); - SnapType snaptype = SnapToFrame; + SnapType snaptype = SnapToBeat; if (choice == _("Beats/3")) { snaptype = SnapToAThirdBeat; @@ -3210,8 +3311,6 @@ Editor::snap_type_selection_done () snaptype = SnapToBar; } else if (choice == _("Marks")) { snaptype = SnapToMark; - } else if (choice == _("Edit Point")) { - snaptype = SnapToEditPoint; } else if (choice == _("Region starts")) { snaptype = SnapToRegionStart; } else if (choice == _("Region ends")) { @@ -3232,8 +3331,6 @@ Editor::snap_type_selection_done () snaptype = SnapToSeconds; } else if (choice == _("Minutes")) { snaptype = SnapToMinutes; - } else if (choice == _("None")) { - snaptype = SnapToFrame; } RefPtr<RadioAction> ract = snap_type_action (snaptype); @@ -3248,7 +3345,9 @@ Editor::snap_mode_selection_done () string choice = snap_mode_selector.get_active_text(); SnapMode mode = SnapNormal; - if (choice == _("Normal")) { + if (choice == _("No Grid")) { + mode = SnapOff; + } else if (choice == _("Grid")) { mode = SnapNormal; } else if (choice == _("Magnetic")) { mode = SnapMagnetic; @@ -3262,17 +3361,37 @@ Editor::snap_mode_selection_done () } void +Editor::cycle_edit_point (bool with_marker) +{ + switch (_edit_point) { + case EditAtMouse: + set_edit_point_preference (EditAtPlayhead); + break; + case EditAtPlayhead: + if (with_marker) { + set_edit_point_preference (EditAtSelectedMarker); + } else { + set_edit_point_preference (EditAtMouse); + } + break; + case EditAtSelectedMarker: + set_edit_point_preference (EditAtMouse); + break; + } +} + +void Editor::edit_point_selection_done () { string choice = edit_point_selector.get_active_text(); EditPoint ep = EditAtSelectedMarker; if (choice == _("Marker")) { - _edit_point = EditAtSelectedMarker; + set_edit_point_preference (EditAtSelectedMarker); } else if (choice == _("Playhead")) { - _edit_point = EditAtPlayhead; + set_edit_point_preference (EditAtPlayhead); } else { - _edit_point = EditAtMouse; + set_edit_point_preference (EditAtMouse); } RefPtr<RadioAction> ract = edit_point_action (ep); @@ -3925,6 +4044,13 @@ Editor::on_key_press_event (GdkEventKey* ev) return key_press_focus_accelerator_handler (*this, ev); } +bool +Editor::on_key_release_event (GdkEventKey* ev) +{ + return Gtk::Window::on_key_release_event (ev); + // return key_press_focus_accelerator_handler (*this, ev); +} + void Editor::reset_x_origin (nframes_t frame) { @@ -3945,10 +4071,26 @@ Editor::reposition_and_zoom (nframes_t frame, double fpu) } void -Editor::set_frames_per_unit (double fpu) +Editor::swap_visual_state () { - nframes_t frames; + if (last_visual_state.frames_per_unit == 0) { + // never set + return; + } + /* note: the correct functionality here is very dependent on the ordering of + setting zoom focus, horizontal position and finally zoom. this is because + it is set_frames_per_unit() that overwrites last_visual_state. + */ + + set_zoom_focus (last_visual_state.zoom_focus); + reposition_and_zoom (last_visual_state.leftmost_frame, last_visual_state.frames_per_unit); + zoomed_to_region = false; +} + +void +Editor::set_frames_per_unit (double fpu) +{ /* this is the core function that controls the zoom level of the canvas. it is called whenever one or more calls are made to reset_zoom(). it executes in an idle handler. */ @@ -3961,9 +4103,6 @@ Editor::set_frames_per_unit (double fpu) fpu = 2.0; } - // convert fpu to frame count - - frames = (nframes_t) floor (fpu * canvas_width); /* don't allow zooms that fit more than the maximum number of frames into an 800 pixel wide space. @@ -3976,8 +4115,25 @@ Editor::set_frames_per_unit (double fpu) if (fpu == frames_per_unit) { return; } + + last_visual_state.frames_per_unit = frames_per_unit; + last_visual_state.leftmost_frame = leftmost_frame; + last_visual_state.zoom_focus = zoom_focus; frames_per_unit = fpu; + post_zoom (); +} + +void +Editor::post_zoom () +{ + // convert fpu to frame count + + nframes_t frames = (nframes_t) floor (frames_per_unit * canvas_width); + + if (frames_per_unit != zoom_range_clock.current_duration()) { + zoom_range_clock.set (frames); + } if (mouse_mode == MouseRange && selection->time.start () != selection->time.end_frame ()) { if (!selection->tracks.empty()) { @@ -3995,7 +4151,7 @@ Editor::set_frames_per_unit (double fpu) reset_hscrollbar_stepping (); reset_scrolling_region (); - + if (playhead_cursor) playhead_cursor->set_position (playhead_cursor->current_frame); instant_save (); @@ -4006,7 +4162,7 @@ Editor::queue_visual_change (nframes_t where) { pending_visual_change.pending = VisualChange::Type (pending_visual_change.pending | VisualChange::TimeOrigin); pending_visual_change.time_origin = where; - + if (pending_visual_change.idle_handler_id < 0) { pending_visual_change.idle_handler_id = g_idle_add (_idle_visual_changer, this); } @@ -4036,7 +4192,7 @@ Editor::idle_visual_changer () VisualChange::Type p = pending_visual_change.pending; pending_visual_change.pending = (VisualChange::Type) 0; - + if (p & VisualChange::ZoomLevel) { set_frames_per_unit (pending_visual_change.frames_per_unit); @@ -4046,9 +4202,11 @@ Editor::idle_visual_changer () update_tempo_based_rulers (); } if (p & VisualChange::TimeOrigin) { - if (pending_visual_change.time_origin != leftmost_frame) { + + nframes_t time_origin = (nframes_t) floor (horizontal_adjustment.get_value() * frames_per_unit); + + if (time_origin != pending_visual_change.time_origin) { horizontal_adjustment.set_value (pending_visual_change.time_origin/frames_per_unit); - /* the signal handler will do the rest */ } else { update_fixed_rulers(); redisplay_tempo (true); @@ -4073,22 +4231,35 @@ Editor::sort_track_selection () } nframes64_t -Editor::get_preferred_edit_position() +Editor::get_preferred_edit_position (bool ignore_playhead) { bool ignored; nframes64_t where = 0; + EditPoint ep = _edit_point; - switch (_edit_point) { + if (entered_marker) { + return entered_marker->position(); + } + + if (ignore_playhead && ep == EditAtPlayhead) { + ep = EditAtSelectedMarker; + } + + switch (ep) { case EditAtPlayhead: where = session->audible_frame(); break; case EditAtSelectedMarker: if (!selection->markers.empty()) { - bool whocares; - Location* loc = find_location_from_marker (selection->markers.front(), whocares); + bool is_start; + Location* loc = find_location_from_marker (selection->markers.front(), is_start); if (loc) { - where = loc->start(); + if (is_start) { + where = loc->start(); + } else { + where = loc->end(); + } break; } } @@ -4204,6 +4375,48 @@ Editor::get_regions_at (nframes64_t where, const TrackSelection& ts) const return rs; } + +RegionSelection +Editor::get_regions_after (nframes64_t where, const TrackSelection& ts) const +{ + RegionSelection rs; + const TrackSelection* tracks; + + if (ts.empty()) { + tracks = &track_views; + } else { + tracks = &ts; + } + + for (TrackSelection::const_iterator t = tracks->begin(); t != tracks->end(); ++t) { + + AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(*t); + + if (atv) { + boost::shared_ptr<Diskstream> ds; + boost::shared_ptr<Playlist> pl; + + if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) { + + Playlist::RegionList* regions = pl->regions_touched ((nframes_t) floor ( (double)where * ds->speed()), max_frames); + + for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) { + + RegionView* rv = atv->audio_view()->find_view (*i); + + if (rv) { + rs.push_back (rv); + } + } + + delete regions; + } + } + } + + return rs; +} + RegionSelection& Editor::get_regions_for_action () { @@ -4215,3 +4428,37 @@ Editor::get_regions_for_action () tmp_regions = get_regions_at (where, selection->tracks); return tmp_regions; } + +void +Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions) +{ + + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { + + RouteTimeAxisView* tatv; + + if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) { + + boost::shared_ptr<Playlist> pl; + vector<boost::shared_ptr<Region> > results; + RegionView* marv; + boost::shared_ptr<Diskstream> ds; + + if ((ds = tatv->get_diskstream()) == 0) { + /* bus */ + continue; + } + + if ((pl = (ds->playlist())) != 0) { + pl->get_region_list_equivalent_regions (region, results); + } + + for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) { + if ((marv = tatv->view()->find_view (*ir)) != 0) { + regions.push_back (marv); + } + } + + } + } +} |