X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Feditor.cc;h=0f77f157f63f78cc228697ac2b68515c4d737f10;hb=f9f5ec85fbfd15d0008f70d4185a84eeadfd3891;hp=a3a73bc9362464a8ba476a6a0f0fee10a5cb76a3;hpb=49ab3aa0b3e78b635c22512b30f44b951c1401f7;p=ardour.git diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index a3a73bc936..0f77f157f6 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -28,6 +28,8 @@ #include #include +#include +#include #include #include @@ -38,7 +40,7 @@ #include #include -#include +#include #include #include #include @@ -47,7 +49,8 @@ #include #include #include -#include + +#include #include "ardour_ui.h" #include "editor.h" @@ -55,11 +58,12 @@ #include "keyboard.h" #include "marker.h" #include "playlist_selector.h" -#include "regionview.h" +#include "audio_region_view.h" #include "rgb_macros.h" #include "selection.h" -#include "streamview.h" +#include "audio_streamview.h" #include "time_axis_view.h" +#include "audio_time_axis.h" #include "utils.h" #include "crossfade_view.h" #include "editing.h" @@ -83,27 +87,20 @@ using namespace std; using namespace sigc; using namespace ARDOUR; +using namespace PBD; using namespace Gtk; using namespace Glib; using namespace Gtkmm2ext; using namespace Editing; using PBD::internationalize; +using PBD::atoi; const double Editor::timebar_height = 15.0; #include "editor_xpms" -static const int32_t slide_index = 0; -static const int32_t splice_index = 1; - -static const gchar *edit_mode_strings[] = { - N_("Slide"), - N_("Splice"), - 0 -}; - -static const gchar *snap_type_strings[] = { +static const gchar *_snap_type_strings[] = { N_("None"), N_("CD Frames"), N_("SMPTE Frames"), @@ -127,18 +124,18 @@ static const gchar *snap_type_strings[] = { 0 }; -static const gchar *snap_mode_strings[] = { +static const gchar *_snap_mode_strings[] = { N_("Normal"), N_("Magnetic"), 0 }; -static const gchar *zoom_focus_strings[] = { +static const gchar *_zoom_focus_strings[] = { N_("Left"), N_("Right"), N_("Center"), N_("Playhead"), - N_("Edit Cursor"), + N_("Edit Cursor"), 0 }; @@ -182,7 +179,7 @@ Editor::Editor (AudioEngine& eng) minsec_label (_("Mins:Secs")), bbt_label (_("Bars:Beats")), - smpte_label (_("SMPTE")), + smpte_label (_("Timecode")), frame_label (_("Frames")), tempo_label (_("Tempo")), meter_label (_("Meter")), @@ -201,38 +198,21 @@ Editor::Editor (AudioEngine& eng) /* tool bar related */ - selection_start_clock (X_("SelectionStartClock"), true), - selection_end_clock (X_("SelectionEndClock"), true), - edit_cursor_clock (X_("EditCursorClock"), true), - zoom_range_clock (X_("ZoomRangeClock"), true, true), + edit_cursor_clock (X_("editcursor"), false, X_("EditCursorClock"), true), + zoom_range_clock (X_("zoomrange"), false, X_("ZoomRangeClock"), true, true), toolbar_selection_clock_table (2,3), - mouse_mode_button_table (2, 3), - - mouse_select_button (_("range")), - mouse_move_button (_("object")), - mouse_gain_button (_("gain")), - mouse_zoom_button (_("zoom")), - mouse_timefx_button (_("timefx")), - mouse_audition_button (_("listen")), - automation_mode_button (_("mode")), global_automation_button (_("automation")), - edit_mode_label (_("Edit Mode")), - snap_type_label (_("Snap To")), - snap_mode_label(_("Snap Mode")), - zoom_focus_label (_("Zoom Focus")), - /* */ image_socket_listener(0), /* */ /* nudge */ - nudge_label (_("Nudge")), - nudge_clock (X_("NudgeClock"), true, true) + nudge_clock (X_("nudge"), false, X_("NudgeClock"), true, true) { constructed = false; @@ -252,17 +232,20 @@ Editor::Editor (AudioEngine& eng) selection->PointsChanged.connect (mem_fun(*this, &Editor::point_selection_changed)); clicked_regionview = 0; - clicked_trackview = 0; - clicked_audio_trackview = 0; + clicked_axisview = 0; + clicked_routeview = 0; clicked_crossfadeview = 0; clicked_control_point = 0; latest_regionview = 0; last_update_frame = 0; drag_info.item = 0; - last_audition_region = 0; 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 = SnapToFrame; set_snap_to (snap_type); snap_mode = SnapNormal; @@ -271,6 +254,7 @@ Editor::Editor (AudioEngine& eng) bbt_beat_subdivision = 4; canvas_width = 0; canvas_height = 0; + autoscroll_active = false; autoscroll_timeout_tag = -1; interthread_progress_window = 0; @@ -285,7 +269,6 @@ Editor::Editor (AudioEngine& eng) first_action_message = 0; export_dialog = 0; show_gain_after_trim = false; - no_zoom_repos_update = false; ignore_route_list_reorder = false; no_route_list_redisplay = false; verbose_cursor_on = true; @@ -298,18 +281,18 @@ Editor::Editor (AudioEngine& eng) _xfade_visibility = true; editor_ruler_menu = 0; no_ruler_shown_update = false; - edit_hscroll_dragging = false; edit_group_list_menu = 0; route_list_menu = 0; region_list_menu = 0; marker_menu = 0; + start_end_marker_menu = 0; range_marker_menu = 0; marker_menu_item = 0; tm_marker_menu = 0; transport_marker_menu = 0; new_transport_marker_menu = 0; editor_mixer_strip_width = Wide; - repos_zoom_queued = false; + show_editor_mixer_when_tracks_arrive = false; region_edit_menu_split_item = 0; temp_location = 0; region_edit_menu_split_multichannel_item = 0; @@ -322,9 +305,12 @@ Editor::Editor (AudioEngine& eng) _new_regionviews_show_envelope = false; current_timestretch = 0; in_edit_group_row_change = false; - + last_canvas_frame = 0; edit_cursor = 0; playhead_cursor = 0; + button_release_can_deselect = true; + canvas_idle_queued = false; + _dragging_playhead = false; location_marker_color = color_map[cLocationMarker]; location_range_color = color_map[cLocationRange]; @@ -337,10 +323,11 @@ Editor::Editor (AudioEngine& eng) set_mouse_mode (MouseObject, true); - frames_per_unit = 2048; /* too early to use set_frames_per_unit */ + frames_per_unit = 2048; /* too early to use reset_zoom () */ reset_hscrollbar_stepping (); zoom_focus = ZoomFocusLeft; + set_zoom_focus (ZoomFocusLeft); zoom_range_clock.ValueChanged.connect (mem_fun(*this, &Editor::zoom_adjustment_changed)); initialize_rulers (); @@ -373,6 +360,8 @@ Editor::Editor (AudioEngine& eng) edit_hscrollbar.signal_button_release_event().connect (mem_fun(*this, &Editor::hscrollbar_button_release)); edit_hscrollbar.signal_size_allocate().connect (mem_fun(*this, &Editor::hscrollbar_allocate)); + edit_hscrollbar.set_name ("EditorHScrollbar"); + build_cursors (); setup_toolbar (); @@ -451,7 +440,7 @@ Editor::Editor (AudioEngine& eng) edit_packer.set_border_width (0); edit_packer.set_name ("EditorWindow"); - edit_packer.attach (edit_vscrollbar, 0, 1, 1, 3, FILL, FILL|EXPAND, 0, 0); + edit_packer.attach (edit_vscrollbar, 3, 4, 1, 2, FILL, FILL|EXPAND, 0, 0); edit_packer.attach (time_button_event_box, 1, 2, 0, 1, FILL, FILL, 0, 0); edit_packer.attach (time_canvas_event_box, 2, 3, 0, 1, FILL|EXPAND, FILL, 0, 0); @@ -459,43 +448,15 @@ Editor::Editor (AudioEngine& eng) edit_packer.attach (controls_layout, 1, 2, 1, 2, FILL, FILL|EXPAND, 0, 0); edit_packer.attach (track_canvas_event_box, 2, 3, 1, 2, FILL|EXPAND, FILL|EXPAND, 0, 0); + edit_packer.attach (zoom_box, 1, 2, 2, 3, FILL, FILL, 0, 0); edit_packer.attach (edit_hscrollbar, 2, 3, 2, 3, FILL|EXPAND, FILL, 0, 0); - zoom_in_button.set_name ("EditorTimeButton"); - zoom_out_button.set_name ("EditorTimeButton"); - ARDOUR_UI::instance()->tooltips().set_tip (zoom_in_button, _("Zoom in")); - ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_button, _("Zoom out")); - - zoom_out_full_button.set_name ("EditorTimeButton"); - ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_full_button, _("Zoom to session")); - - zoom_in_button.add (*(manage (new Image (Stock::ZOOM_IN, ICON_SIZE_BUTTON)))); - zoom_out_button.add (*(manage (new Image (Stock::ZOOM_OUT, ICON_SIZE_BUTTON)))); - zoom_out_full_button.add (*(manage (new Image (Stock::ZOOM_FIT, ICON_SIZE_BUTTON)))); - - zoom_in_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), false)); - zoom_out_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), true)); - zoom_out_full_button.signal_clicked().connect (mem_fun(*this, &Editor::temporal_zoom_session)); - - zoom_indicator_box.pack_start (zoom_out_button, false, false); - zoom_indicator_box.pack_start (zoom_in_button, false, false); - zoom_indicator_box.pack_start (zoom_range_clock, false, false); - zoom_indicator_box.pack_start (zoom_out_full_button, false, false); - - zoom_indicator_label.set_text (_("Zoom Span")); - zoom_indicator_label.set_name ("ToolBarLabel"); - - zoom_indicator_vbox.set_spacing (3); - zoom_indicator_vbox.set_border_width (3); - zoom_indicator_vbox.pack_start (zoom_indicator_label, false, false); - zoom_indicator_vbox.pack_start (zoom_indicator_box, false, false); - - bottom_hbox.set_border_width (3); + bottom_hbox.set_border_width (2); bottom_hbox.set_spacing (3); route_display_model = ListStore::create(route_display_columns); route_list_display.set_model (route_display_model); - route_list_display.append_column (_("Visible"), route_display_columns.visible); + route_list_display.append_column (_("Show"), route_display_columns.visible); route_list_display.append_column (_("Name"), route_display_columns.text); route_list_display.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(0)); route_list_display.get_column (1)->set_data (X_("colnum"), GUINT_TO_POINTER(1)); @@ -521,10 +482,13 @@ Editor::Editor (AudioEngine& eng) edit_group_display.set_model (group_model); edit_group_display.append_column (_("Name"), group_columns.text); edit_group_display.append_column (_("Active"), group_columns.is_active); - edit_group_display.append_column (_("Visible"), group_columns.is_visible); + edit_group_display.append_column (_("Show"), group_columns.is_visible); edit_group_display.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(0)); edit_group_display.get_column (1)->set_data (X_("colnum"), GUINT_TO_POINTER(1)); edit_group_display.get_column (2)->set_data (X_("colnum"), GUINT_TO_POINTER(2)); + edit_group_display.get_column (0)->set_expand (true); + edit_group_display.get_column (1)->set_expand (false); + edit_group_display.get_column (2)->set_expand (false); edit_group_display.set_headers_visible (true); /* name is directly editable */ @@ -543,12 +507,11 @@ Editor::Editor (AudioEngine& eng) active_cell->property_activatable() = true; active_cell->property_radio() = false; - edit_group_display.set_name ("EditGroupList"); - group_model->signal_row_changed().connect (mem_fun (*this, &Editor::edit_group_row_change)); edit_group_display.set_name ("EditGroupList"); edit_group_display.get_selection()->set_mode (SELECTION_SINGLE); + edit_group_display.set_headers_visible (false); edit_group_display.set_reorderable (false); edit_group_display.set_rules_hint (true); edit_group_display.set_size_request (75, -1); @@ -559,7 +522,7 @@ Editor::Editor (AudioEngine& eng) edit_group_display.signal_button_press_event().connect (mem_fun(*this, &Editor::edit_group_list_button_press_event), false); VBox* edit_group_display_packer = manage (new VBox()); - HButtonBox* edit_group_display_button_box = manage (new HButtonBox()); + HBox* edit_group_display_button_box = manage (new HBox()); edit_group_display_button_box->set_homogeneous (true); Button* edit_group_add_button = manage (new Button ()); @@ -634,11 +597,12 @@ Editor::Editor (AudioEngine& eng) named_selection_display.append_column (_("Chunks"), named_selection_columns.text); named_selection_display.set_headers_visible (false); named_selection_display.set_size_request (100, -1); - named_selection_display.set_name ("RegionListDisplay"); + named_selection_display.set_name ("NamedSelectionDisplay"); named_selection_display.get_selection()->set_mode (SELECTION_SINGLE); named_selection_display.set_size_request (100, -1); - named_selection_display.signal_button_press_event().connect (mem_fun(*this, &Editor::named_selection_display_button_press), false); + named_selection_display.signal_button_release_event().connect (mem_fun(*this, &Editor::named_selection_display_button_release), false); + named_selection_display.signal_key_release_event().connect (mem_fun(*this, &Editor::named_selection_display_key_release), false); named_selection_display.get_selection()->signal_changed().connect (mem_fun (*this, &Editor::named_selection_display_selection_changed)); /* SNAPSHOTS */ @@ -646,7 +610,7 @@ Editor::Editor (AudioEngine& eng) snapshot_display_model = ListStore::create (snapshot_display_columns); snapshot_display.set_model (snapshot_display_model); snapshot_display.append_column (X_("snapshot"), snapshot_display_columns.visible_name); - snapshot_display.set_name ("SnapshotDisplayList"); + snapshot_display.set_name ("SnapshotDisplay"); snapshot_display.set_size_request (75, -1); snapshot_display.set_headers_visible (false); snapshot_display.set_reorderable (false); @@ -679,10 +643,12 @@ Editor::Editor (AudioEngine& eng) the_notebook.popup_enable (); the_notebook.set_tab_pos (Gtk::POS_RIGHT); + post_maximal_editor_width = 0; + post_maximal_pane_position = 0; edit_pane.pack1 (edit_packer, true, true); edit_pane.pack2 (the_notebook, false, true); - edit_pane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler), static_cast (&edit_pane))); + edit_pane.signal_size_allocate().connect (bind (mem_fun(*this, &Editor::pane_allocation_handler), static_cast (&edit_pane))); top_hbox.pack_start (toolbar_frame, true, true); @@ -709,23 +675,44 @@ Editor::Editor (AudioEngine& eng) _playlist_selector = new PlaylistSelector(); _playlist_selector->signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), static_cast (_playlist_selector))); - AudioRegionView::AudioRegionViewGoingAway.connect (mem_fun(*this, &Editor::catch_vanishing_audio_regionview)); + RegionView::RegionViewGoingAway.connect (mem_fun(*this, &Editor::catch_vanishing_regionview)); /* nudge stuff */ - nudge_forward_button.add (*(manage (new Image (get_xpm("right_arrow.xpm"))))); - nudge_backward_button.add (*(manage (new Image (get_xpm("left_arrow.xpm"))))); + nudge_forward_button.add (*(manage (new Image (::get_icon("nudge_right"))))); + nudge_backward_button.add (*(manage (new Image (::get_icon("nudge_left"))))); - ARDOUR_UI::instance()->tooltips().set_tip (nudge_forward_button, _("Nudge region/selection forwards")); - ARDOUR_UI::instance()->tooltips().set_tip (nudge_backward_button, _("Nudge region/selection backwards")); + ARDOUR_UI::instance()->tooltips().set_tip (nudge_forward_button, _("Nudge Region/Selection Forwards")); + ARDOUR_UI::instance()->tooltips().set_tip (nudge_backward_button, _("Nudge Region/Selection Backwards")); nudge_forward_button.set_name ("TransportButton"); nudge_backward_button.set_name ("TransportButton"); fade_context_menu.set_name ("ArdourContextMenu"); + /* icons, titles, WM stuff */ + + list > window_icons; + Glib::RefPtr icon; + + if ((icon = ::get_icon ("ardour_icon_16px")) != 0) { + window_icons.push_back (icon); + } + if ((icon = ::get_icon ("ardour_icon_22px")) != 0) { + window_icons.push_back (icon); + } + if ((icon = ::get_icon ("ardour_icon_32px")) != 0) { + window_icons.push_back (icon); + } + if ((icon = ::get_icon ("ardour_icon_48px")) != 0) { + window_icons.push_back (icon); + } + if (!window_icons.empty()) { + set_icon_list (window_icons); + set_default_icon_list (window_icons); + } set_title (_("ardour: editor")); - set_wmclass (_("ardour_editor"), "Ardour"); + set_wmclass (X_("ardour_editor"), "Ardour"); add (vpacker); add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK); @@ -739,6 +726,9 @@ Editor::Editor (AudioEngine& eng) ControlProtocol::ZoomIn.connect (bind (mem_fun (*this, &Editor::temporal_zoom_step), false)); ControlProtocol::ZoomOut.connect (bind (mem_fun (*this, &Editor::temporal_zoom_step), true)); ControlProtocol::ScrollTimeline.connect (mem_fun (*this, &Editor::control_scroll)); + + Config->ParameterChanged.connect (mem_fun (*this, &Editor::parameter_changed)); + constructed = true; instant_save (); } @@ -767,7 +757,7 @@ Editor::add_toplevel_controls (Container& cont) } void -Editor::catch_vanishing_audio_regionview (AudioRegionView *rv) +Editor::catch_vanishing_regionview (RegionView *rv) { /* note: the selection will take care of the vanishing audioregionview by itself. @@ -783,7 +773,7 @@ Editor::catch_vanishing_audio_regionview (AudioRegionView *rv) } void -Editor::set_entered_regionview (AudioRegionView* rv) +Editor::set_entered_regionview (RegionView* rv) { if (rv == entered_regionview) { return; @@ -810,15 +800,6 @@ Editor::set_entered_track (TimeAxisView* tav) } } -gint -Editor::left_track_canvas (GdkEventCrossing *ev) -{ - set_entered_track (0); - set_entered_regionview (0); - return FALSE; -} - - void Editor::show_window () { @@ -846,75 +827,10 @@ Editor::tie_vertical_scrolling () edit_cursor->set_y_axis(y1); } -void -Editor::set_frames_per_unit (double fpu) -{ - jack_nframes_t frames; - - if (fpu == frames_per_unit) { - return; - } - - if (fpu < 1.0) { - fpu = 1.0; - } - - // convert fpu to frame count - - frames = (jack_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. - */ - - if (max_frames / fpu < 800.0) { - return; - } - - frames_per_unit = fpu; - - if (frames != zoom_range_clock.current_duration()) { - zoom_range_clock.set (frames); - } - - /* only update these if we not about to call reposition_x_origin, - which will do the same updates. - */ - - if (!no_zoom_repos_update) { - horizontal_adjustment.set_value (leftmost_frame/frames_per_unit); - update_fixed_rulers (); - tempo_map_changed (Change (0)); - } - - if (mouse_mode == MouseRange && selection->time.start () != selection->time.end_frame ()) { - if (!selection->tracks.empty()) { - for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { - (*i)->reshow_selection (selection->time); - } - } else { - for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { - (*i)->reshow_selection (selection->time); - } - } - } - - ZoomChanged (); /* EMIT_SIGNAL */ - - reset_hscrollbar_stepping (); - reset_scrolling_region (); - - if (edit_cursor) edit_cursor->set_position (edit_cursor->current_frame); - if (playhead_cursor) playhead_cursor->set_position (playhead_cursor->current_frame); - - instant_save (); - -} - void Editor::instant_save () { - if (!constructed || !ARDOUR_UI::instance()->session_loaded) { + if (!constructed || !ARDOUR_UI::instance()->session_loaded) { return; } @@ -925,15 +841,6 @@ Editor::instant_save () } } -void -Editor::reposition_x_origin (jack_nframes_t frame) -{ - if (frame != leftmost_frame) { - leftmost_frame = frame; - horizontal_adjustment.set_value (frame/frames_per_unit); - } -} - void Editor::edit_cursor_clock_changed() { @@ -946,7 +853,7 @@ Editor::edit_cursor_clock_changed() void Editor::zoom_adjustment_changed () { - if (session == 0 || no_zoom_repos_update) { + if (session == 0) { return; } @@ -954,10 +861,10 @@ Editor::zoom_adjustment_changed () if (fpu < 1.0) { fpu = 1.0; - zoom_range_clock.set ((jack_nframes_t) floor (fpu * canvas_width)); + zoom_range_clock.set ((nframes_t) floor (fpu * canvas_width)); } else if (fpu > session->current_end_frame() / canvas_width) { fpu = session->current_end_frame() / canvas_width; - zoom_range_clock.set ((jack_nframes_t) floor (fpu * canvas_width)); + zoom_range_clock.set ((nframes_t) floor (fpu * canvas_width)); } temporal_zoom (fpu); @@ -973,14 +880,14 @@ Editor::control_scroll (float fraction) } double step = fraction * current_page_frames(); - jack_nframes_t target; + nframes_t target; - if ((fraction < 0.0f) && (session->transport_frame() < (jack_nframes_t) fabs(step))) { + if ((fraction < 0.0f) && (session->transport_frame() < (nframes_t) fabs(step))) { target = 0; } else if ((fraction > 0.0f) && (max_frames - session->transport_frame() < step)) { target = (max_frames - (current_page_frames()*2)); // allow room for slop in where the PH is on the screen } else { - target = (session->transport_frame() + (jack_nframes_t) floor ((fraction * current_page_frames()))); + target = (session->transport_frame() + (nframes_t) floor ((fraction * current_page_frames()))); } /* move visuals, we'll catch up with it later */ @@ -989,9 +896,9 @@ Editor::control_scroll (float fraction) if (target > (current_page_frames() / 2)) { /* try to center PH in window */ - reposition_x_origin (target - (current_page_frames()/2)); + reset_x_origin (target - (current_page_frames()/2)); } else { - reposition_x_origin (0); + reset_x_origin (0); } /* cancel the existing */ @@ -1004,54 +911,12 @@ Editor::control_scroll (float fraction) } bool -Editor::deferred_control_scroll (jack_nframes_t target) +Editor::deferred_control_scroll (nframes_t target) { session->request_locate (target); return false; } -void -Editor::canvas_horizontally_scrolled () -{ - leftmost_frame = (jack_nframes_t) floor (horizontal_adjustment.get_value() * frames_per_unit); - - update_fixed_rulers (); - - if (!edit_hscroll_dragging) { - tempo_map_changed (Change (0)); - } else { - update_tempo_based_rulers(); - } -} - -void -Editor::reposition_and_zoom (jack_nframes_t frame, double nfpu) -{ - if (!repos_zoom_queued) { - Glib::signal_idle().connect (bind (mem_fun(*this, &Editor::deferred_reposition_and_zoom), frame, nfpu)); - repos_zoom_queued = true; - } -} - -gint -Editor::deferred_reposition_and_zoom (jack_nframes_t frame, double nfpu) -{ - /* if we need to force an update to the hscroller stuff, - don't set no_zoom_repos_update. - */ - - no_zoom_repos_update = (frame != leftmost_frame); - - set_frames_per_unit (nfpu); - if (no_zoom_repos_update) { - reposition_x_origin (frame); - } - no_zoom_repos_update = false; - repos_zoom_queued = false; - - return FALSE; -} - void Editor::on_realize () { @@ -1059,53 +924,6 @@ Editor::on_realize () Realized (); } -void -Editor::queue_session_control_changed (Session::ControlType t) -{ - Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::session_control_changed), t)); -} - -void -Editor::session_control_changed (Session::ControlType t) -{ - // right now we're only tracking some state here - - switch (t) { - case Session::AutoLoop: - update_loop_range_view (true); - break; - case Session::PunchIn: - case Session::PunchOut: - update_punch_range_view (true); - break; - - case Session::LayeringModel: - update_layering_model (); - break; - - default: - break; - } -} - -void -Editor::fake_handle_new_audio_region (AudioRegion *region) -{ - Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::handle_new_audio_region), region)); -} - -void -Editor::fake_handle_audio_region_removed (AudioRegion *region) -{ - Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::handle_audio_region_removed), region)); -} - -void -Editor::fake_handle_new_duration () -{ - Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &Editor::handle_new_duration)); -} - void Editor::start_scrolling () { @@ -1117,11 +935,10 @@ void Editor::stop_scrolling () { scroll_connection.disconnect (); - slower_update_connection.disconnect (); } void -Editor::map_position_change (jack_nframes_t frame) +Editor::map_position_change (nframes_t frame) { ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::map_position_change), frame)); @@ -1134,7 +951,7 @@ Editor::map_position_change (jack_nframes_t frame) } void -Editor::center_screen (jack_nframes_t frame) +Editor::center_screen (nframes_t frame) { double page = canvas_width * frames_per_unit; @@ -1147,28 +964,32 @@ Editor::center_screen (jack_nframes_t frame) } void -Editor::center_screen_internal (jack_nframes_t frame, float page) +Editor::center_screen_internal (nframes_t frame, float page) { page /= 2; if (frame > page) { - frame -= (jack_nframes_t) page; + frame -= (nframes_t) page; } else { frame = 0; } - reposition_x_origin (frame); + reset_x_origin (frame); } void Editor::handle_new_duration () { - reset_scrolling_region (); + ENSURE_GUI_THREAD (mem_fun (*this, &Editor::handle_new_duration)); - if (session) { - cerr << "Set upper #2 to " << horizontal_adjustment.get_upper () << endl; - horizontal_adjustment.set_value (leftmost_frame/frames_per_unit); + nframes_t new_end = session->get_maximum_extent() + (nframes_t) floorf (current_page_frames() * 0.10f); + + if (new_end > last_canvas_frame) { + last_canvas_frame = new_end; + reset_scrolling_region (); } + + horizontal_adjustment.set_value (leftmost_frame/frames_per_unit); } void @@ -1213,13 +1034,21 @@ Editor::connect_to_session (Session *t) { session = t; + XMLNode* node = ARDOUR_UI::instance()->editor_settings(); + set_state (*node); + + /* catch up with the playhead */ + + session->request_locate (playhead_cursor->current_frame); + if (first_action_message) { first_action_message->hide(); } update_title (); - session->going_away.connect (mem_fun(*this, &Editor::session_going_away)); + session->GoingAway.connect (mem_fun(*this, &Editor::session_going_away)); + session->history().Changed.connect (mem_fun (*this, &Editor::history_changed)); /* These signals can all be emitted by a non-GUI thread. Therefore the handlers for them must not attempt to directly interact with the GUI, @@ -1228,10 +1057,10 @@ Editor::connect_to_session (Session *t) session_connections.push_back (session->TransportStateChange.connect (mem_fun(*this, &Editor::map_transport_state))); session_connections.push_back (session->PositionChanged.connect (mem_fun(*this, &Editor::map_position_change))); - session_connections.push_back (session->RouteAdded.connect (mem_fun(*this, &Editor::handle_new_route_p))); - session_connections.push_back (session->AudioRegionAdded.connect (mem_fun(*this, &Editor::fake_handle_new_audio_region))); - session_connections.push_back (session->AudioRegionRemoved.connect (mem_fun(*this, &Editor::fake_handle_audio_region_removed))); - session_connections.push_back (session->DurationChanged.connect (mem_fun(*this, &Editor::fake_handle_new_duration))); + session_connections.push_back (session->RouteAdded.connect (mem_fun(*this, &Editor::handle_new_route))); + session_connections.push_back (session->RegionAdded.connect (mem_fun(*this, &Editor::handle_new_region))); + session_connections.push_back (session->RegionRemoved.connect (mem_fun(*this, &Editor::handle_region_removed))); + session_connections.push_back (session->DurationChanged.connect (mem_fun(*this, &Editor::handle_new_duration))); session_connections.push_back (session->edit_group_added.connect (mem_fun(*this, &Editor::add_edit_group))); session_connections.push_back (session->edit_group_removed.connect (mem_fun(*this, &Editor::edit_groups_changed))); session_connections.push_back (session->NamedSelectionAdded.connect (mem_fun(*this, &Editor::handle_new_named_selection))); @@ -1242,15 +1071,12 @@ Editor::connect_to_session (Session *t) session_connections.push_back (session->RegionHiddenChange.connect (mem_fun(*this, &Editor::region_hidden))); session_connections.push_back (session->SMPTEOffsetChanged.connect (mem_fun(*this, &Editor::update_just_smpte))); - session_connections.push_back (session->SMPTETypeChanged.connect (mem_fun(*this, &Editor::update_just_smpte))); session_connections.push_back (session->tempo_map().StateChanged.connect (mem_fun(*this, &Editor::tempo_map_changed))); edit_groups_changed (); edit_cursor_clock.set_session (session); - selection_start_clock.set_session (session); - selection_end_clock.set_session (session); zoom_range_clock.set_session (session); _playlist_selector->set_session (session); nudge_clock.set_session (session); @@ -1260,16 +1086,6 @@ Editor::connect_to_session (Session *t) analysis_window->set_session (session); #endif - switch (session->get_edit_mode()) { - case Splice: - edit_mode_selector.set_active_text (edit_mode_strings[splice_index]); - break; - - case Slide: - edit_mode_selector.set_active_text (edit_mode_strings[slide_index]); - break; - } - Location* loc = session->locations()->auto_loop_location(); if (loc == 0) { loc = new Location (0, session->current_end_frame(), _("Loop"),(Location::Flags) (Location::IsAutoLoop | Location::IsHidden)); @@ -1298,10 +1114,8 @@ Editor::connect_to_session (Session *t) loc->set_name (_("Punch")); } - update_loop_range_view (true); - update_punch_range_view (true); + Config->map_parameters (mem_fun (*this, &Editor::parameter_changed)); - session->ControlChanged.connect (mem_fun(*this, &Editor::queue_session_control_changed)); session->StateSaved.connect (mem_fun(*this, &Editor::session_state_saved)); refresh_location_display (); @@ -1311,33 +1125,7 @@ Editor::connect_to_session (Session *t) session->locations()->StateChanged.connect (mem_fun(*this, &Editor::refresh_location_display_s)); session->locations()->end_location()->changed.connect (mem_fun(*this, &Editor::end_location_changed)); - bool yn; - RefPtr act; - - act = ActionManager::get_action (X_("Editor"), X_("toggle-xfades-active")); - if (act) { - RefPtr tact = RefPtr::cast_dynamic(act); - /* do it twice to force the change */ - yn = session->get_crossfades_active(); - tact->set_active (!yn); - tact->set_active (yn); - } - - act = ActionManager::get_action (X_("Editor"), X_("toggle-auto-xfades")); - if (act) { - RefPtr tact = RefPtr::cast_dynamic(act); - /* do it twice to force the change */ - yn = Config->get_auto_xfade (); - tact->set_active (!yn); - tact->set_active (yn); - } - - /* xfade visibility state set from editor::set_state() */ - - update_crossfade_model (); - update_layering_model (); - - reset_scrolling_region (); + handle_new_duration (); redisplay_regions (); redisplay_named_selections (); @@ -1349,26 +1137,12 @@ Editor::connect_to_session (Session *t) (static_cast(*i))->set_samples_per_unit (frames_per_unit); } - /* ::reposition_x_origin() doesn't work right here, since the old - position may be zero already, and it does nothing in such - circumstances. - */ - - leftmost_frame = 0; - - horizontal_adjustment.set_value (0); - restore_ruler_visibility (); - tempo_map_changed (Change (0)); - - edit_cursor->set_position (0); - playhead_cursor->set_position (0); + //tempo_map_changed (Change (0)); + session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks); start_scrolling (); - XMLNode* node = ARDOUR_UI::instance()->editor_settings(); - set_state (*node); - /* don't show master bus in a new session */ if (ARDOUR_UI::instance()->session_is_new ()) { @@ -1380,10 +1154,10 @@ Editor::connect_to_session (Session *t) for (i = rows.begin(); i != rows.end(); ++i) { TimeAxisView *tv = (*i)[route_display_columns.tv]; - AudioTimeAxisView *atv; + RouteTimeAxisView *rtv; - if ((atv = dynamic_cast(tv)) != 0) { - if (atv->route().master()) { + if ((rtv = dynamic_cast(tv)) != 0) { + if (rtv->route()->master()) { route_list_display.get_selection()->unselect (i); } } @@ -1392,6 +1166,10 @@ Editor::connect_to_session (Session *t) no_route_list_redisplay = false; redisplay_route_list (); } + + /* register for undo history */ + + session->register_with_memento_command_factory(_id, this); } void @@ -1454,38 +1232,39 @@ Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* i switch (item_type) { case FadeInItem: case FadeInHandleItem: - if (arv->region.fade_in_active()) { - items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), false))); + if (arv->audio_region()->fade_in_active()) { + items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*this, &Editor::set_fade_in_active), false))); } else { - items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), true))); + items.push_back (MenuElem (_("Activate"), bind (mem_fun (*this, &Editor::set_fade_in_active), true))); } items.push_back (SeparatorElem()); - items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Linear))); - items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogB))); - items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Fast))); - items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogA))); - items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Slow))); + items.push_back (MenuElem (_("Linear"), bind (mem_fun (*this, &Editor::set_fade_in_shape), AudioRegion::Linear))); + items.push_back (MenuElem (_("Slowest"), bind (mem_fun (*this, &Editor::set_fade_in_shape), AudioRegion::LogB))); + items.push_back (MenuElem (_("Slow"), bind (mem_fun (*this, &Editor::set_fade_in_shape), AudioRegion::Fast))); + items.push_back (MenuElem (_("Fast"), bind (mem_fun (*this, &Editor::set_fade_in_shape), AudioRegion::LogA))); + items.push_back (MenuElem (_("Fastest"), bind (mem_fun (*this, &Editor::set_fade_in_shape), AudioRegion::Slow))); break; case FadeOutItem: case FadeOutHandleItem: - if (arv->region.fade_out_active()) { - items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), false))); + if (arv->audio_region()->fade_out_active()) { + items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*this, &Editor::set_fade_out_active), false))); } else { - items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), true))); + items.push_back (MenuElem (_("Activate"), bind (mem_fun (*this, &Editor::set_fade_out_active), true))); } items.push_back (SeparatorElem()); - items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Linear))); - items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Fast))); - items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogB))); - items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogA))); - items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Slow))); + items.push_back (MenuElem (_("Linear"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::Linear))); + items.push_back (MenuElem (_("Slowest"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::Fast))); + items.push_back (MenuElem (_("Slow"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::LogB))); + items.push_back (MenuElem (_("Fast"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::LogA))); + items.push_back (MenuElem (_("Fastest"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::Slow))); break; + default: fatal << _("programming error: ") << X_("non-fade canvas item passed to popup_fade_context_menu()") @@ -1497,16 +1276,16 @@ Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* i } void -Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection, jack_nframes_t frame) +Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection, nframes_t frame) { using namespace Menu_Helpers; - Menu* (Editor::*build_menu_function)(jack_nframes_t); + Menu* (Editor::*build_menu_function)(nframes_t); Menu *menu; switch (item_type) { case RegionItem: - case AudioRegionViewName: - case AudioRegionViewNameHighlight: + case RegionViewName: + case RegionViewNameHighlight: if (with_selection) { build_menu_function = &Editor::build_track_selection_context_menu; } else { @@ -1527,7 +1306,7 @@ Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, break; case StreamItem: - if (clicked_audio_trackview->get_diskstream()) { + if (clicked_routeview->is_track()) { build_menu_function = &Editor::build_track_context_menu; } else { build_menu_function = &Editor::build_track_bus_context_menu; @@ -1546,25 +1325,26 @@ Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, switch (item_type) { case RegionItem: - case AudioRegionViewName: - case AudioRegionViewNameHighlight: + case RegionViewName: + case RegionViewNameHighlight: if (!with_selection) { if (region_edit_menu_split_item) { - if (clicked_regionview && clicked_regionview->region.covers (edit_cursor->current_frame)) { + if (clicked_regionview && clicked_regionview->region()->covers (edit_cursor->current_frame)) { ActionManager::set_sensitive (ActionManager::edit_cursor_in_region_sensitive_actions, true); } else { ActionManager::set_sensitive (ActionManager::edit_cursor_in_region_sensitive_actions, false); } } + /* if (region_edit_menu_split_multichannel_item) { - if (clicked_regionview && clicked_regionview->region.n_channels() > 1) { + if (clicked_regionview && clicked_regionview->region().n_channels() > 1) { // GTK2FIX find the action, change its sensitivity // region_edit_menu_split_multichannel_item->set_sensitive (true); } else { // GTK2FIX see above // region_edit_menu_split_multichannel_item->set_sensitive (false); } - } + }*/ } break; @@ -1582,7 +1362,7 @@ Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, return; } - if (clicked_audio_trackview && clicked_audio_trackview->audio_track()) { + if (clicked_routeview && clicked_routeview->audio_track()) { /* Bounce to disk */ @@ -1591,7 +1371,7 @@ Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, edit_items.push_back (SeparatorElem()); - switch (clicked_audio_trackview->audio_track()->freeze_state()) { + switch (clicked_routeview->audio_track()->freeze_state()) { case AudioTrack::NoFreeze: edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route))); break; @@ -1611,7 +1391,7 @@ Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, } Menu* -Editor::build_track_context_menu (jack_nframes_t ignored) +Editor::build_track_context_menu (nframes_t ignored) { using namespace Menu_Helpers; @@ -1623,7 +1403,7 @@ Editor::build_track_context_menu (jack_nframes_t ignored) } Menu* -Editor::build_track_bus_context_menu (jack_nframes_t ignored) +Editor::build_track_bus_context_menu (nframes_t ignored) { using namespace Menu_Helpers; @@ -1635,22 +1415,22 @@ Editor::build_track_bus_context_menu (jack_nframes_t ignored) } Menu* -Editor::build_track_region_context_menu (jack_nframes_t frame) +Editor::build_track_region_context_menu (nframes_t frame) { using namespace Menu_Helpers; MenuList& edit_items = track_region_context_menu.items(); edit_items.clear(); - AudioTimeAxisView* atv = dynamic_cast (clicked_trackview); + AudioTimeAxisView* atv = dynamic_cast (clicked_axisview); if (atv) { - DiskStream* ds; - Playlist* pl; + boost::shared_ptr ds; + boost::shared_ptr pl; if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) { - Playlist::RegionList* regions = pl->regions_at ((jack_nframes_t) floor ( (double)frame * ds->speed())); + Playlist::RegionList* regions = pl->regions_at ((nframes_t) floor ( (double)frame * ds->speed())); for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) { - add_region_context_items (atv->view, (*i), edit_items); + add_region_context_items (atv->audio_view(), (*i), edit_items); } delete regions; } @@ -1662,20 +1442,20 @@ Editor::build_track_region_context_menu (jack_nframes_t frame) } Menu* -Editor::build_track_crossfade_context_menu (jack_nframes_t frame) +Editor::build_track_crossfade_context_menu (nframes_t frame) { using namespace Menu_Helpers; MenuList& edit_items = track_crossfade_context_menu.items(); edit_items.clear (); - AudioTimeAxisView* atv = dynamic_cast (clicked_trackview); + AudioTimeAxisView* atv = dynamic_cast (clicked_axisview); if (atv) { - DiskStream* ds; - Playlist* pl; - AudioPlaylist* apl; + boost::shared_ptr ds; + boost::shared_ptr pl; + boost::shared_ptr apl; - if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()) != 0) && ((apl = dynamic_cast (pl)) != 0)) { + if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()) != 0) && ((apl = boost::dynamic_pointer_cast (pl)) != 0)) { Playlist::RegionList* regions = pl->regions_at (frame); AudioPlaylist::Crossfades xfades; @@ -1685,11 +1465,11 @@ Editor::build_track_crossfade_context_menu (jack_nframes_t frame) bool many = xfades.size() > 1; for (AudioPlaylist::Crossfades::iterator i = xfades.begin(); i != xfades.end(); ++i) { - add_crossfade_context_items (atv->view, (*i), edit_items, many); + add_crossfade_context_items (atv->audio_view(), (*i), edit_items, many); } for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) { - add_region_context_items (atv->view, (*i), edit_items); + add_region_context_items (atv->audio_view(), (*i), edit_items); } delete regions; @@ -1742,7 +1522,7 @@ Editor::analyze_range_selection() Menu* -Editor::build_track_selection_context_menu (jack_nframes_t ignored) +Editor::build_track_selection_context_menu (nframes_t ignored) { using namespace Menu_Helpers; MenuList& edit_items = track_selection_context_menu.items(); @@ -1755,7 +1535,7 @@ Editor::build_track_selection_context_menu (jack_nframes_t ignored) } void -Editor::add_crossfade_context_items (StreamView* view, Crossfade* xfade, Menu_Helpers::MenuList& edit_items, bool many) +Editor::add_crossfade_context_items (AudioStreamView* view, boost::shared_ptr xfade, Menu_Helpers::MenuList& edit_items, bool many) { using namespace Menu_Helpers; Menu *xfade_menu = manage (new Menu); @@ -1769,8 +1549,8 @@ Editor::add_crossfade_context_items (StreamView* view, Crossfade* xfade, Menu_He str = _("Unmute"); } - items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::toggle_xfade_active), xfade))); - items.push_back (MenuElem (_("Edit"), bind (mem_fun(*this, &Editor::edit_xfade), xfade))); + items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::toggle_xfade_active), boost::weak_ptr (xfade)))); + items.push_back (MenuElem (_("Edit"), bind (mem_fun(*this, &Editor::edit_xfade), boost::weak_ptr (xfade)))); if (xfade->can_follow_overlap()) { @@ -1784,9 +1564,9 @@ Editor::add_crossfade_context_items (StreamView* view, Crossfade* xfade, Menu_He } if (many) { - str = xfade->out().name(); + str = xfade->out()->name(); str += "->"; - str += xfade->in().name(); + str += xfade->in()->name(); } else { str = _("Crossfade"); } @@ -1812,24 +1592,24 @@ Editor::xfade_edit_right_region () } void -Editor::add_region_context_items (StreamView* sv, Region* region, Menu_Helpers::MenuList& edit_items) +Editor::add_region_context_items (AudioStreamView* sv, boost::shared_ptr region, Menu_Helpers::MenuList& edit_items) { using namespace Menu_Helpers; Menu *region_menu = manage (new Menu); MenuList& items = region_menu->items(); region_menu->set_name ("ArdourContextMenu"); - AudioRegion* ar = 0; + boost::shared_ptr ar; if (region) { - ar = dynamic_cast (region); + ar = boost::dynamic_pointer_cast (region); } /* when this particular menu pops up, make the relevant region become selected. */ - region_menu->signal_map_event().connect (bind (mem_fun(*this, &Editor::set_selected_regionview_from_map_event), sv, region)); + region_menu->signal_map_event().connect (bind (mem_fun(*this, &Editor::set_selected_regionview_from_map_event), sv, boost::weak_ptr(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))); @@ -1849,32 +1629,50 @@ Editor::add_region_context_items (StreamView* sv, Region* region, Menu_Helpers:: items.push_back (SeparatorElem()); - /* XXX hopefully this nonsense will go away with SigC++ 2.X, where the compiler - might be able to figure out which overloaded member function to use in - a bind() call ... - */ + items.push_back (CheckMenuElem (_("Lock"), mem_fun(*this, &Editor::toggle_region_lock))); + region_lock_item = static_cast(&items.back()); + if (region->locked()) { + region_lock_item->set_active(); + } + items.push_back (CheckMenuElem (_("Mute"), mem_fun(*this, &Editor::toggle_region_mute))); + region_mute_item = static_cast(&items.back()); + if (region->muted()) { + region_mute_item->set_active(); + } + items.push_back (CheckMenuElem (_("Opaque"), mem_fun(*this, &Editor::toggle_region_opaque))); + region_opaque_item = static_cast(&items.back()); + if (region->opaque()) { + region_opaque_item->set_active(); + } - void (Editor::*type_A_pmf)(void (Region::*pmf)(bool), bool) = &Editor::region_selection_op; + items.push_back (CheckMenuElem (_("Original position"), mem_fun(*this, &Editor::naturalize))); + if (region->at_natural_position()) { + items.back().set_sensitive (false); + } - items.push_back (MenuElem (_("Lock"), bind (mem_fun(*this, type_A_pmf), &Region::set_locked, true))); - items.push_back (MenuElem (_("Unlock"), bind (mem_fun(*this, type_A_pmf), &Region::set_locked, false))); items.push_back (SeparatorElem()); - if (region->muted()) { - items.push_back (MenuElem (_("Unmute"), bind (mem_fun(*this, type_A_pmf), &Region::set_muted, false))); - } else { - items.push_back (MenuElem (_("Mute"), bind (mem_fun(*this, type_A_pmf), &Region::set_muted, true))); - } - items.push_back (SeparatorElem()); + if (ar) { + + RegionView* rv = sv->find_view (ar); + AudioRegionView* arv = dynamic_cast(rv); - items.push_back (MenuElem (_("Original position"), mem_fun(*this, &Editor::naturalize))); - items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Reset Envelope"), mem_fun(*this, &Editor::reset_region_gain_envelopes))); + + items.push_back (CheckMenuElem (_("Envelope Visible"), mem_fun(*this, &Editor::toggle_gain_envelope_visibility))); + region_envelope_visible_item = static_cast (&items.back()); + + if (arv->envelope_visible()) { + region_envelope_visible_item->set_active (true); + } + items.push_back (CheckMenuElem (_("Envelope Active"), mem_fun(*this, &Editor::toggle_gain_envelope_active))); + region_envelope_active_item = static_cast (&items.back()); - if (ar) { + if (ar->envelope_active()) { + region_envelope_active_item->set_active (true); + } - items.push_back (MenuElem (_("Toggle envelope visibility"), mem_fun(*this, &Editor::toggle_gain_envelope_visibility))); - items.push_back (MenuElem (_("Toggle envelope active"), mem_fun(*this, &Editor::toggle_gain_envelope_active))); items.push_back (SeparatorElem()); if (ar->scale_amplitude() != 1.0f) { @@ -1890,7 +1688,7 @@ Editor::add_region_context_items (StreamView* sv, Region* region, Menu_Helpers:: /* range related stuff */ items.push_back (MenuElem (_("Add Range Markers"), mem_fun (*this, &Editor::add_location_from_audio_region))); - items.push_back (MenuElem (_("Set Range"), mem_fun (*this, &Editor::set_selection_from_audio_region))); + items.push_back (MenuElem (_("Set Range Selection"), mem_fun (*this, &Editor::set_selection_from_audio_region))); items.push_back (SeparatorElem()); /* Nudge region */ @@ -1927,8 +1725,6 @@ Editor::add_region_context_items (StreamView* sv, Region* region, Menu_Helpers:: 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_clicked_region))); - items.push_back (SeparatorElem()); - items.push_back (MenuElem (_("Destroy"), mem_fun(*this, &Editor::destroy_clicked_region))); /* OK, stick the region submenu at the top of the list, and then add the standard items. @@ -1973,13 +1769,14 @@ Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items) items.push_back (SeparatorElem()); items.push_back (MenuElem (_("Select all in range"), mem_fun(*this, &Editor::select_all_selectables_using_time_selection))); items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Add Range Markers"), mem_fun (*this, &Editor::add_location_from_selection))); items.push_back (MenuElem (_("Set range to loop range"), mem_fun(*this, &Editor::set_selection_from_loop))); items.push_back (MenuElem (_("Set range to punch range"), mem_fun(*this, &Editor::set_selection_from_punch))); items.push_back (SeparatorElem()); items.push_back (MenuElem (_("Crop region to range"), mem_fun(*this, &Editor::crop_region_to_selection))); items.push_back (MenuElem (_("Fill range with region"), mem_fun(*this, &Editor::region_fill_selection))); items.push_back (MenuElem (_("Duplicate range"), bind (mem_fun(*this, &Editor::duplicate_dialog), false))); - items.push_back (MenuElem (_("Create chunk from range"), mem_fun(*this, &Editor::name_selection))); + items.push_back (MenuElem (_("Create chunk from range"), mem_fun(*this, &Editor::create_named_selection))); items.push_back (SeparatorElem()); items.push_back (MenuElem (_("Bounce range"), mem_fun(*this, &Editor::bounce_range_selection))); items.push_back (MenuElem (_("Export range"), mem_fun(*this, &Editor::export_selection))); @@ -1999,7 +1796,7 @@ Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items) MenuList& play_items = play_menu->items(); play_menu->set_name ("ArdourContextMenu"); - play_items.push_back (MenuElem (_("Play from edit cursor"))); + play_items.push_back (MenuElem (_("Play from edit cursor"), mem_fun(*this, &Editor::play_from_edit_cursor))); play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start))); play_items.push_back (MenuElem (_("Play region"), mem_fun(*this, &Editor::play_selected_region))); play_items.push_back (SeparatorElem()); @@ -2084,7 +1881,7 @@ Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items) MenuList& play_items = play_menu->items(); play_menu->set_name ("ArdourContextMenu"); - play_items.push_back (MenuElem (_("Play from edit cursor"))); + play_items.push_back (MenuElem (_("Play from edit cursor"), mem_fun(*this, &Editor::play_from_edit_cursor))); play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start))); edit_items.push_back (MenuElem (_("Play"), *play_menu)); @@ -2133,10 +1930,13 @@ Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items) void Editor::set_snap_to (SnapType st) -{ +{ snap_type = st; - vector txt = internationalize (snap_type_strings); - snap_type_selector.set_active_text (txt[(int)st]); + string str = snap_type_strings[(int) st]; + + if (str != snap_type_selector.get_active_text()) { + snap_type_selector.set_active_text (str); + } instant_save (); @@ -2157,8 +1957,11 @@ void Editor::set_snap_mode (SnapMode mode) { snap_mode = mode; - vector txt = internationalize (snap_mode_strings); - snap_mode_selector.set_active_text (txt[(int)mode]); + string str = snap_mode_strings[(int)mode]; + + if (str != snap_mode_selector.get_active_text ()) { + snap_mode_selector.set_active_text (str); + } instant_save (); } @@ -2171,6 +1974,9 @@ Editor::set_state (const XMLNode& node) int x, y, xoff, yoff; Gdk::Geometry g; + if ((prop = node.property ("id")) != 0) { + _id = prop->value (); + } if ((geometry = find_named_node (node, "geometry")) == 0) { @@ -2191,16 +1997,37 @@ Editor::set_state (const XMLNode& node) yoff = atoi(geometry->property("y_off")->value()); } - set_geometry_hints (vpacker, g, Gdk::HINT_BASE_SIZE); set_default_size (g.base_width, g.base_height); move (x, y); + if (session && (prop = node.property ("playhead"))) { + nframes_t pos = atol (prop->value().c_str()); + playhead_cursor->set_position (pos); + } else { + playhead_cursor->set_position (0); + + /* reset_x_origin() doesn't work right here, since the old + position may be zero already, and it does nothing in such + circumstances. + */ + + leftmost_frame = 0; + horizontal_adjustment.set_value (0); + } + + if (session && (prop = node.property ("edit-cursor"))) { + nframes_t pos = atol (prop->value().c_str()); + edit_cursor->set_position (pos); + } else { + edit_cursor->set_position (0); + } + if ((prop = node.property ("zoom-focus"))) { set_zoom_focus ((ZoomFocus) atoi (prop->value())); } if ((prop = node.property ("zoom"))) { - set_frames_per_unit (atof (prop->value())); + reset_zoom (PBD::atof (prop->value())); } if ((prop = node.property ("snap-to"))) { @@ -2283,6 +2110,7 @@ Editor::set_state (const XMLNode& node) Glib::RefPtr act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer")); if (act) { + Glib::RefPtr tact = Glib::RefPtr::cast_dynamic(act); bool yn = (prop->value() == X_("yes")); @@ -2293,6 +2121,7 @@ Editor::set_state (const XMLNode& node) } } + return 0; } @@ -2302,8 +2131,11 @@ Editor::get_state () XMLNode* node = new XMLNode ("Editor"); char buf[32]; + _id.print (buf, sizeof (buf)); + node->add_property ("id", buf); + if (is_realized()) { - Glib::RefPtr win = get_window(); + Glib::RefPtr win = get_window(); int x, y, xoff, yoff, width, height; win->get_root_origin(x, y); @@ -2311,7 +2143,7 @@ Editor::get_state () win->get_size(width, height); XMLNode* geometry = new XMLNode ("geometry"); - char buf[32]; + snprintf(buf, sizeof(buf), "%d", width); geometry->add_property("x_size", string(buf)); snprintf(buf, sizeof(buf), "%d", height); @@ -2339,6 +2171,11 @@ Editor::get_state () snprintf (buf, sizeof(buf), "%d", (int) snap_mode); node->add_property ("snap-mode", buf); + snprintf (buf, sizeof (buf), "%" PRIu32, playhead_cursor->current_frame); + node->add_property ("playhead", buf); + snprintf (buf, sizeof (buf), "%" PRIu32, edit_cursor->current_frame); + node->add_property ("edit-cursor", buf); + node->add_property ("show-waveforms", _show_waveforms ? "yes" : "no"); node->add_property ("show-waveforms-recording", _show_waveforms_recording ? "yes" : "no"); node->add_property ("show-measures", _show_measures ? "yes" : "no"); @@ -2361,18 +2198,11 @@ Editor::get_state () TimeAxisView * Editor::trackview_by_y_position (double y) { - TrackViewList::iterator iter; - TimeAxisView *tv; - - for (iter = track_views.begin(); iter != track_views.end(); ++iter) { - - tv = *iter; + for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) { - if (tv->hidden()) { - continue; - } + TimeAxisView *tv; - if (tv->y_position <= y && y < ((tv->y_position + tv->height + track_spacing))) { + if ((tv = (*iter)->covers_y_position (y)) != 0) { return tv; } } @@ -2381,7 +2211,7 @@ Editor::trackview_by_y_position (double y) } void -Editor::snap_to (jack_nframes_t& start, int32_t direction, bool for_mark) +Editor::snap_to (nframes_t& start, int32_t direction, bool for_mark) { Location* before = 0; Location* after = 0; @@ -2390,10 +2220,11 @@ Editor::snap_to (jack_nframes_t& start, int32_t direction, bool for_mark) return; } - const jack_nframes_t one_second = session->frame_rate(); - const jack_nframes_t one_minute = session->frame_rate() * 60; - - jack_nframes_t presnap = start; + const nframes_t one_second = session->frame_rate(); + const nframes_t one_minute = session->frame_rate() * 60; + const nframes_t one_smpte_second = (nframes_t)(rint(session->smpte_frames_per_second()) * session->frames_per_smpte_frame()); + nframes_t one_smpte_minute = (nframes_t)(rint(session->smpte_frames_per_second()) * session->frames_per_smpte_frame() * 60); + nframes_t presnap = start; switch (snap_type) { case SnapToFrame: @@ -2401,16 +2232,17 @@ Editor::snap_to (jack_nframes_t& start, int32_t direction, bool for_mark) case SnapToCDFrame: if (direction) { - start = (jack_nframes_t) ceil ((double) start / (one_second / 75)) * (one_second / 75); + start = (nframes_t) ceil ((double) start / (one_second / 75)) * (one_second / 75); } else { - start = (jack_nframes_t) floor ((double) start / (one_second / 75)) * (one_second / 75); + start = (nframes_t) floor ((double) start / (one_second / 75)) * (one_second / 75); } break; + case SnapToSMPTEFrame: - if (direction) { - start = (jack_nframes_t) (ceil ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame()); + if (fmod((double)start, (double)session->frames_per_smpte_frame()) > (session->frames_per_smpte_frame() / 2)) { + start = (nframes_t) (ceil ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame()); } else { - start = (jack_nframes_t) (floor ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame()); + start = (nframes_t) (floor ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame()); } break; @@ -2421,10 +2253,10 @@ Editor::snap_to (jack_nframes_t& start, int32_t direction, bool for_mark) } else { start -= session->smpte_offset (); } - if (direction > 0) { - start = (jack_nframes_t) ceil ((double) start / one_second) * one_second; + if (start % one_smpte_second > one_smpte_second / 2) { + start = (nframes_t) ceil ((double) start / one_smpte_second) * one_smpte_second; } else { - start = (jack_nframes_t) floor ((double) start / one_second) * one_second; + start = (nframes_t) floor ((double) start / one_smpte_second) * one_smpte_second; } if (session->smpte_offset_negative()) @@ -2442,10 +2274,10 @@ Editor::snap_to (jack_nframes_t& start, int32_t direction, bool for_mark) } else { start -= session->smpte_offset (); } - if (direction) { - start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute; + if (start % one_smpte_minute > one_smpte_minute / 2) { + start = (nframes_t) ceil ((double) start / one_smpte_minute) * one_smpte_minute; } else { - start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute; + start = (nframes_t) floor ((double) start / one_smpte_minute) * one_smpte_minute; } if (session->smpte_offset_negative()) { @@ -2456,18 +2288,18 @@ Editor::snap_to (jack_nframes_t& start, int32_t direction, bool for_mark) break; case SnapToSeconds: - if (direction) { - start = (jack_nframes_t) ceil ((double) start / one_second) * one_second; + if (start % one_second > one_second / 2) { + start = (nframes_t) ceil ((double) start / one_second) * one_second; } else { - start = (jack_nframes_t) floor ((double) start / one_second) * one_second; + start = (nframes_t) floor ((double) start / one_second) * one_second; } break; case SnapToMinutes: - if (direction) { - start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute; + if (start % one_minute > one_minute / 2) { + start = (nframes_t) ceil ((double) start / one_minute) * one_minute; } else { - start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute; + start = (nframes_t) floor ((double) start / one_minute) * one_minute; } break; @@ -2548,7 +2380,7 @@ Editor::snap_to (jack_nframes_t& start, int32_t direction, bool for_mark) case SnapToRegionSync: case SnapToRegionBoundary: if (!region_boundary_cache.empty()) { - vector::iterator i; + vector::iterator i; if (direction > 0) { i = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start); @@ -2592,30 +2424,60 @@ void Editor::setup_toolbar () { string pixmap_path; + + const guint32 FUDGE = 18; // Combo's are stupid - they steal space from the entry for the button + + + /* Mode Buttons (tool selection) */ + vector mouse_mode_buttons; + 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); + 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); + mouse_timefx_button.add (*(manage (new Image (::get_icon("tool_stretch"))))); + mouse_timefx_button.set_relief(Gtk::RELIEF_NONE); mouse_mode_buttons.push_back (&mouse_timefx_button); + mouse_audition_button.add (*(manage (new Image (::get_icon("tool_audition"))))); + mouse_audition_button.set_relief(Gtk::RELIEF_NONE); mouse_mode_buttons.push_back (&mouse_audition_button); + mouse_mode_button_set = new GroupedButtons (mouse_mode_buttons); - mouse_mode_button_table.set_homogeneous (true); - mouse_mode_button_table.set_col_spacings (2); - mouse_mode_button_table.set_row_spacings (2); - mouse_mode_button_table.set_border_width (5); + HBox* mode_box = manage(new HBox); + mode_box->set_border_width (2); + 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); + mouse_mode_button_box.pack_start(mouse_zoom_button, true, true); + 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.set_homogeneous(true); + + vector edit_mode_strings; + edit_mode_strings.push_back (edit_mode_to_string (Splice)); + edit_mode_strings.push_back (edit_mode_to_string (Slide)); - mouse_mode_button_table.attach (mouse_move_button, 0, 1, 0, 1); - mouse_mode_button_table.attach (mouse_select_button, 1, 2, 0, 1); - mouse_mode_button_table.attach (mouse_zoom_button, 2, 3, 0, 1); - - mouse_mode_button_table.attach (mouse_gain_button, 0, 1, 1, 2); - mouse_mode_button_table.attach (mouse_timefx_button, 1, 2, 1, 2); - mouse_mode_button_table.attach (mouse_audition_button, 2, 3, 1, 2); + edit_mode_selector.set_name ("EditModeSelector"); + Gtkmm2ext::set_size_request_to_display_given_text (edit_mode_selector, longest (edit_mode_strings).c_str(), 2+FUDGE, 10); + set_popdown_strings (edit_mode_selector, edit_mode_strings); + edit_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::edit_mode_selection_done)); - mouse_mode_tearoff = manage (new TearOff (mouse_mode_button_table)); + mode_box->pack_start(edit_mode_selector); + mode_box->pack_start(mouse_mode_button_box); + + mouse_mode_tearoff = manage (new TearOff (*mode_box)); mouse_mode_tearoff->set_name ("MouseModeBase"); mouse_mode_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast(&toolbar_hbox), @@ -2634,12 +2496,12 @@ Editor::setup_toolbar () mouse_timefx_button.set_name ("MouseModeButton"); mouse_audition_button.set_name ("MouseModeButton"); - ARDOUR_UI::instance()->tooltips().set_tip (mouse_move_button, _("select/move objects")); - ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("select/move ranges")); - ARDOUR_UI::instance()->tooltips().set_tip (mouse_gain_button, _("draw gain automation")); - ARDOUR_UI::instance()->tooltips().set_tip (mouse_zoom_button, _("select zoom range")); - ARDOUR_UI::instance()->tooltips().set_tip (mouse_timefx_button, _("stretch/shrink regions")); - ARDOUR_UI::instance()->tooltips().set_tip (mouse_audition_button, _("listen to specific regions")); + ARDOUR_UI::instance()->tooltips().set_tip (mouse_move_button, _("Select/Move Objects")); + ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("Select/Move Ranges")); + ARDOUR_UI::instance()->tooltips().set_tip (mouse_gain_button, _("Draw Gain Automation")); + ARDOUR_UI::instance()->tooltips().set_tip (mouse_zoom_button, _("Select Zoom Range")); + ARDOUR_UI::instance()->tooltips().set_tip (mouse_timefx_button, _("Stretch/Shrink Regions")); + ARDOUR_UI::instance()->tooltips().set_tip (mouse_audition_button, _("Listen to Specific Regions")); mouse_move_button.unset_flags (CAN_FOCUS); mouse_select_button.unset_flags (CAN_FOCUS); @@ -2658,160 +2520,81 @@ Editor::setup_toolbar () mouse_audition_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseAudition)); // mouse_move_button.set_active (true); + - /* automation control */ - - global_automation_button.set_name ("MouseModeButton"); - automation_mode_button.set_name ("MouseModeButton"); - - automation_box.set_spacing (2); - automation_box.set_border_width (2); - automation_box.pack_start (global_automation_button, false, false); - automation_box.pack_start (automation_mode_button, false, false); - - /* Edit mode */ - - edit_mode_label.set_name ("ToolBarLabel"); - - edit_mode_selector.set_name ("EditModeSelector"); + /* Zoom */ + + zoom_box.set_spacing (1); + zoom_box.set_border_width (2); - edit_mode_box.set_spacing (3); - edit_mode_box.set_border_width (3); + zoom_in_button.set_name ("EditorTimeButton"); + zoom_in_button.set_size_request(-1,16); + zoom_in_button.add (*(manage (new Image (::get_icon("zoom_in"))))); + zoom_in_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), false)); + ARDOUR_UI::instance()->tooltips().set_tip (zoom_in_button, _("Zoom In")); + + zoom_out_button.set_name ("EditorTimeButton"); + zoom_out_button.set_size_request(-1,16); + zoom_out_button.add (*(manage (new Image (::get_icon("zoom_out"))))); + zoom_out_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), true)); + ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_button, _("Zoom Out")); - /* XXX another disgusting hack because of the way combo boxes size themselves */ + zoom_out_full_button.set_name ("EditorTimeButton"); + zoom_out_full_button.set_size_request(-1,16); + zoom_out_full_button.add (*(manage (new Image (::get_icon("zoom_full"))))); + zoom_out_full_button.signal_clicked().connect (mem_fun(*this, &Editor::temporal_zoom_session)); + ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_full_button, _("Zoom to Session")); - const guint32 FUDGE = 20; // Combo's are stupid - they steal space from the entry for the button - Gtkmm2ext::set_size_request_to_display_given_text (edit_mode_selector, "EdgtMode", 2+FUDGE, 10); - set_popdown_strings (edit_mode_selector, internationalize (edit_mode_strings)); - edit_mode_box.pack_start (edit_mode_label, false, false); - edit_mode_box.pack_start (edit_mode_selector, false, false); + zoom_focus_selector.set_name ("ZoomFocusSelector"); + Gtkmm2ext::set_size_request_to_display_given_text (zoom_focus_selector, "Edit Cursor", 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")); - edit_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::edit_mode_selection_done)); + zoom_box.pack_start (zoom_focus_selector, true, true); + zoom_box.pack_start (zoom_out_button, false, false); + zoom_box.pack_start (zoom_in_button, false, false); + zoom_box.pack_start (zoom_out_full_button, false, false); - /* Snap Type */ + /* Edit Cursor / Snap */ - snap_type_label.set_name ("ToolBarLabel"); + snap_box.set_spacing (1); + snap_box.set_border_width (2); snap_type_selector.set_name ("SnapTypeSelector"); - - snap_type_box.set_spacing (3); - snap_type_box.set_border_width (3); - - /* XXX another disgusting hack because of the way combo boxes size themselves */ - Gtkmm2ext::set_size_request_to_display_given_text (snap_type_selector, "SMPTE Seconds", 2+FUDGE, 10); - set_popdown_strings (snap_type_selector, internationalize (snap_type_strings)); - - snap_type_box.pack_start (snap_type_label, false, false); - snap_type_box.pack_start (snap_type_selector, false, false); - + set_popdown_strings (snap_type_selector, snap_type_strings); snap_type_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_type_selection_done)); - - /* Snap mode, not snap type */ - - snap_mode_label.set_name ("ToolBarLabel"); + ARDOUR_UI::instance()->tooltips().set_tip (snap_type_selector, _("Unit to snap cursors and ranges to")); snap_mode_selector.set_name ("SnapModeSelector"); - - snap_mode_box.set_spacing (3); - snap_mode_box.set_border_width (3); - - Gtkmm2ext::set_size_request_to_display_given_text (snap_mode_selector, "SngpMode", 2+FUDGE, 10); - set_popdown_strings (snap_mode_selector, internationalize (snap_mode_strings)); - - snap_mode_box.pack_start (snap_mode_label, false, false); - snap_mode_box.pack_start (snap_mode_selector, false, false); - + 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)); - /* Zoom focus mode */ - - zoom_focus_label.set_name ("ToolBarLabel"); - - zoom_focus_selector.set_name ("ZoomFocusSelector"); - - zoom_focus_box.set_spacing (3); - zoom_focus_box.set_border_width (3); + 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); - /* XXX another disgusting hack because of the way combo boxes size themselves */ - Gtkmm2ext::set_size_request_to_display_given_text (zoom_focus_selector, "Edgt Cursor", 2+FUDGE, 10); - set_popdown_strings (zoom_focus_selector, internationalize (zoom_focus_strings)); + /* Nudge */ - zoom_focus_box.pack_start (zoom_focus_label, false, false); - zoom_focus_box.pack_start (zoom_focus_selector, false, false); + HBox *nudge_box = manage (new HBox); + nudge_box->set_spacing(1); + nudge_box->set_border_width (2); - zoom_focus_selector.signal_changed().connect (mem_fun(*this, &Editor::zoom_focus_selection_done)); - - /* selection/cursor clocks */ - - toolbar_selection_cursor_label.set_name ("ToolBarLabel"); - selection_start_clock_label.set_name ("ToolBarLabel"); - selection_end_clock_label.set_name ("ToolBarLabel"); - edit_cursor_clock_label.set_name ("ToolBarLabel"); - - selection_start_clock_label.set_text (_("Start:")); - selection_end_clock_label.set_text (_("End:")); - edit_cursor_clock_label.set_text (_("Edit")); - - /* the zoom in/out buttons are generally taller than the clocks, so - put all the toolbar clocks into a size group with one of the - buttons to make them all equal height. - - this also applies to the various toolbar combos - */ - - RefPtr toolbar_clock_size_group = SizeGroup::create (SIZE_GROUP_VERTICAL); - toolbar_clock_size_group->add_widget (zoom_out_button); - toolbar_clock_size_group->add_widget (edit_cursor_clock); - toolbar_clock_size_group->add_widget (zoom_range_clock); - toolbar_clock_size_group->add_widget (nudge_clock); - toolbar_clock_size_group->add_widget (edit_mode_selector); - toolbar_clock_size_group->add_widget (snap_type_selector); - toolbar_clock_size_group->add_widget (snap_mode_selector); - toolbar_clock_size_group->add_widget (zoom_focus_selector); - - HBox* edit_clock_hbox = manage (new HBox()); - VBox* edit_clock_vbox = manage (new VBox()); - - edit_clock_hbox->pack_start (edit_cursor_clock, false, false); - - edit_clock_vbox->set_spacing (3); - edit_clock_vbox->set_border_width (3); - edit_clock_vbox->pack_start (edit_cursor_clock_label, false, false); - edit_clock_vbox->pack_start (*edit_clock_hbox, false, false); - - HBox* hbox = new HBox; - - hbox->pack_start (*edit_clock_vbox, false, false); - hbox->pack_start (zoom_indicator_vbox, false, false); - hbox->pack_start (zoom_focus_box, false, false); - hbox->pack_start (snap_type_box, false, false); - hbox->pack_start (snap_mode_box, false, false); - hbox->pack_start (edit_mode_box, false, false); - - VBox *vbox = manage (new VBox); - - vbox->set_spacing (3); - vbox->set_border_width (3); - - HBox *nbox = manage (new HBox); - nudge_forward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_forward), false)); nudge_backward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_backward), false)); - nbox->pack_start (nudge_backward_button, false, false); - nbox->pack_start (nudge_forward_button, false, false); - nbox->pack_start (nudge_clock, false, false, 5); + nudge_box->pack_start (nudge_backward_button, false, false); + nudge_box->pack_start (nudge_forward_button, false, false); + nudge_box->pack_start (nudge_clock, false, false); - nudge_label.set_name ("ToolBarLabel"); - vbox->pack_start (nudge_label, false, false); - vbox->pack_start (*nbox, false, false); + /* Pack everything in... */ - hbox->pack_start (*vbox, false, false); - - hbox->show_all (); + HBox* hbox = new HBox; + hbox->set_spacing(10); tools_tearoff = new TearOff (*hbox); tools_tearoff->set_name ("MouseModeBase"); @@ -2825,11 +2608,18 @@ Editor::setup_toolbar () tools_tearoff->Visible.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast (&toolbar_hbox), &tools_tearoff->tearoff_window(), 0)); - toolbar_hbox.set_spacing (8); - toolbar_hbox.set_border_width (2); + toolbar_hbox.set_spacing (10); + toolbar_hbox.set_border_width (1); - toolbar_hbox.pack_start (*tools_tearoff, false, false); toolbar_hbox.pack_start (*mouse_mode_tearoff, false, false); + toolbar_hbox.pack_start (*tools_tearoff, false, false); + + + hbox->pack_start (snap_box, false, false); + // hbox->pack_start (zoom_box, false, false); + hbox->pack_start (*nudge_box, false, false); + + hbox->show_all (); toolbar_base.set_name ("ToolBarBase"); toolbar_base.add (toolbar_hbox); @@ -2839,101 +2629,6 @@ Editor::setup_toolbar () toolbar_frame.add (toolbar_base); } -gint -Editor::_autoscroll_canvas (void *arg) -{ - return ((Editor *) arg)->autoscroll_canvas (); -} - -gint -Editor::autoscroll_canvas () -{ - jack_nframes_t new_frame; - bool keep_calling = true; - - if (autoscroll_direction < 0) { - if (leftmost_frame < autoscroll_distance) { - new_frame = 0; - } else { - new_frame = leftmost_frame - autoscroll_distance; - } - } else { - if (leftmost_frame > max_frames - autoscroll_distance) { - new_frame = max_frames; - } else { - new_frame = leftmost_frame + autoscroll_distance; - } - } - - if (new_frame != leftmost_frame) { - reposition_x_origin (new_frame); - } - - if (new_frame == 0 || new_frame == max_frames) { - /* we are done */ - return FALSE; - } - - autoscroll_cnt++; - - if (autoscroll_cnt == 1) { - - /* connect the timeout so that we get called repeatedly */ - - autoscroll_timeout_tag = gtk_timeout_add (100, _autoscroll_canvas, this); - keep_calling = false; - - } else if (autoscroll_cnt > 10 && autoscroll_cnt < 20) { - - /* after about a while, speed up a bit by changing the timeout interval */ - - autoscroll_timeout_tag = gtk_timeout_add (50, _autoscroll_canvas, this); - keep_calling = false; - - } else if (autoscroll_cnt >= 20 && autoscroll_cnt < 30) { - - /* after about another while, speed up some more */ - - autoscroll_timeout_tag = gtk_timeout_add (25, _autoscroll_canvas, this); - keep_calling = false; - - } else if (autoscroll_cnt >= 30) { - - /* we've been scrolling for a while ... crank it up */ - - autoscroll_distance = 10 * (jack_nframes_t) floor (canvas_width * frames_per_unit); - } - - return keep_calling; -} - -void -Editor::start_canvas_autoscroll (int dir) -{ - if (!session) { - return; - } - - stop_canvas_autoscroll (); - - autoscroll_direction = dir; - autoscroll_distance = (jack_nframes_t) floor ((canvas_width * frames_per_unit)/10.0); - autoscroll_cnt = 0; - - /* do it right now, which will start the repeated callbacks */ - - autoscroll_canvas (); -} - -void -Editor::stop_canvas_autoscroll () -{ - if (autoscroll_timeout_tag >= 0) { - gtk_timeout_remove (autoscroll_timeout_tag); - autoscroll_timeout_tag = -1; - } -} - int Editor::convert_drop_to_paths (vector& paths, const RefPtr& context, @@ -3003,7 +2698,7 @@ Editor::convert_drop_to_paths (vector& paths, for (vector::iterator i = uris.begin(); i != uris.end(); ++i) { if ((*i).substr (0,7) == "file://") { string p = *i; - url_decode (p); + PBD::url_decode (p); paths.push_back (p.substr (7)); } } @@ -3072,8 +2767,8 @@ void Editor::begin_reversible_command (string name) { if (session) { - UndoAction ua = get_memento(); - session->begin_reversible_command (name, &ua); + before = &get_state(); + session->begin_reversible_command (name); } } @@ -3081,305 +2776,10 @@ void Editor::commit_reversible_command () { if (session) { - UndoAction ua = get_memento(); - session->commit_reversible_command (&ua); + session->commit_reversible_command (new MementoCommand(*this, before, &get_state())); } } -void -Editor::set_selected_track_from_click (Selection::Operation op, bool with_undo, bool no_remove) -{ - if (!clicked_trackview) { - return; - } - - if (with_undo) { - begin_reversible_command (_("set selected trackview")); - } - - switch (op) { - case Selection::Toggle: - if (selection->selected (clicked_trackview)) { - if (!no_remove) { - selection->remove (clicked_trackview); - } - } else { - selection->toggle (clicked_trackview); - } - break; - case Selection::Set: - if (selection->selected (clicked_trackview) && selection->tracks.size() == 1) { - /* no commit necessary */ - return; - } - - selection->set (clicked_trackview); - break; - - case Selection::Extend: - /* not defined yet */ - break; - } - - if (with_undo) { - commit_reversible_command (); - } -} - -void -Editor::set_selected_control_point_from_click (Selection::Operation op, bool with_undo, bool no_remove) -{ - if (!clicked_control_point) { - return; - } - - if (with_undo) { - begin_reversible_command (_("set selected control point")); - } - - switch (op) { - case Selection::Set: - break; - case Selection::Toggle: - break; - case Selection::Extend: - break; - } - if (with_undo) { - commit_reversible_command (); - } -} - -void -Editor::mapover_audio_tracks (slot sl) -{ - set relevant_tracks; - - /* step one: get all selected tracks and all tracks in the relevant edit groups */ - - for (TrackSelection::iterator ti = selection->tracks.begin(); ti != selection->tracks.end(); ++ti) { - - AudioTimeAxisView* atv = dynamic_cast(*ti); - - if (!atv) { - continue; - } - - RouteGroup* group = atv->route().edit_group(); - - if (group && group->is_active()) { - - /* active group for this track, loop over all tracks and get every member of the group */ - - for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { - - AudioTimeAxisView* tatv; - - if ((tatv = dynamic_cast (*i)) != 0) { - - if (tatv->route().edit_group() == group) { - relevant_tracks.insert (tatv); - } - } - } - - } else { - - /* no active group, or no group */ - - relevant_tracks.insert (atv); - } - - } - - /* step two: apply operation to each track */ - - uint32_t sz = relevant_tracks.size(); - - for (set::iterator ati = relevant_tracks.begin(); ati != relevant_tracks.end(); ++ati) { - sl (**ati, sz); - } -} - -void -Editor::mapped_set_selected_regionview_from_click (AudioTimeAxisView& atv, uint32_t ignored, - AudioRegionView* basis, vector* all_equivs) -{ - AudioPlaylist* pl; - vector results; - AudioRegionView* marv; - DiskStream* ds; - - if ((ds = atv.get_diskstream()) == 0) { - /* bus */ - return; - } - - if ((pl = ds->playlist()) != 0) { - pl->get_equivalent_regions (basis->region, results); - } - - for (vector::iterator ir = results.begin(); ir != results.end(); ++ir) { - if ((marv = atv.view->find_view (**ir)) != 0) { - all_equivs->push_back (marv); - } - } -} - -void -Editor::set_selected_regionview_from_click (Selection::Operation op, bool no_track_remove) -{ - cerr << "In SSRfC\n"; - - vector all_equivalent_regions; - - if (!clicked_regionview) { - return; - } - - mapover_audio_tracks (bind (mem_fun (*this, &Editor::mapped_set_selected_regionview_from_click), - clicked_regionview, &all_equivalent_regions)); - - - cerr << "mapover done\n"; - - begin_reversible_command (_("set selected regionview")); - - switch (op) { - case Selection::Toggle: - selection->toggle (clicked_regionview); -#if 0 - if (clicked_regionview->get_selected()) { - if (/* group && group->is_active() && */ selection->audio_regions.size() > 1) { - /* reduce selection down to just the one clicked */ - selection->set (clicked_regionview); - } else { - selection->remove (clicked_regionview); - } - } else { - selection->add (all_equivalent_regions); - } -#endif - set_selected_track_from_click (op, false, no_track_remove); - break; - - case Selection::Set: - // karsten wiese suggested these two lines to make - // a selected region rise to the top. but this - // leads to a mismatch between actual layering - // and visual layering. resolution required .... - // - // gnome_canvas_item_raise_to_top (clicked_regionview->get_canvas_group()); - // gnome_canvas_item_raise_to_top (clicked_regionview->get_time_axis_view().canvas_display); - - if (clicked_regionview->get_selected()) { - /* no commit necessary: we are the one selected. */ - return; - - } else { - - selection->set (all_equivalent_regions); - set_selected_track_from_click (op, false, false); - } - break; - - case Selection::Extend: - /* not defined yet */ - break; - } - cerr << "case done\n"; - - commit_reversible_command () ; -} - -void -Editor::set_selected_regionview_from_region_list (Region& r, Selection::Operation op) -{ - vector all_equivalent_regions; - AudioRegion* region; - - if ((region = dynamic_cast(&r)) == 0) { - return; - } - - for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { - - AudioTimeAxisView* tatv; - - if ((tatv = dynamic_cast (*i)) != 0) { - - AudioPlaylist* pl; - vector results; - AudioRegionView* marv; - 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::iterator ir = results.begin(); ir != results.end(); ++ir) { - if ((marv = tatv->view->find_view (**ir)) != 0) { - all_equivalent_regions.push_back (marv); - } - } - - } - } - - begin_reversible_command (_("set selected regions")); - - switch (op) { - case Selection::Toggle: - /* XXX this is not correct */ - selection->add (all_equivalent_regions); - break; - case Selection::Set: - selection->set (all_equivalent_regions); - break; - case Selection::Extend: - /* not defined yet */ - break; - } - - commit_reversible_command () ; -} - -bool -Editor::set_selected_regionview_from_map_event (GdkEventAny* ev, StreamView* sv, Region* r) -{ - AudioRegionView* rv; - AudioRegion* ar; - - if ((ar = dynamic_cast (r)) == 0) { - return TRUE; - } - - if ((rv = sv->find_view (*ar)) == 0) { - return TRUE; - } - - /* don't reset the selection if its something other than - a single other region. - */ - - if (selection->audio_regions.size() > 1) { - return TRUE; - } - - begin_reversible_command (_("set selected regions")); - - selection->set (rv); - - commit_reversible_command () ; - - return TRUE; -} - void Editor::set_edit_group_solo (Route& route, bool yn) { @@ -3405,89 +2805,27 @@ Editor::set_edit_group_mute (Route& route, bool yn) } void -Editor::set_edit_menu (Menu& menu) -{ - edit_menu = &menu; - edit_menu->signal_map_event().connect (mem_fun(*this, &Editor::edit_menu_map_handler)); -} - -bool -Editor::edit_menu_map_handler (GdkEventAny* ev) +Editor::history_changed () { - using namespace Menu_Helpers; - MenuList& edit_items = edit_menu->items(); string label; - /* Nuke all the old items */ - - edit_items.clear (); - - if (session == 0) { - return false; - } - - if (session->undo_depth() == 0) { - label = _("Undo"); - } else { - label = string_compose(_("Undo (%1)"), session->next_undo()); - } - - edit_items.push_back (MenuElem (label, bind (mem_fun(*this, &Editor::undo), 1U))); - - if (session->undo_depth() == 0) { - edit_items.back().set_sensitive (false); - } - - if (session->redo_depth() == 0) { - label = _("Redo"); - } else { - label = string_compose(_("Redo (%1)"), session->next_redo()); - } - - edit_items.push_back (MenuElem (label, bind (mem_fun(*this, &Editor::redo), 1U))); - if (session->redo_depth() == 0) { - edit_items.back().set_sensitive (false); - } - - vector mitems; - - edit_items.push_back (SeparatorElem()); - edit_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut))); - mitems.push_back (&edit_items.back()); - edit_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy))); - mitems.push_back (&edit_items.back()); - edit_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f))); - mitems.push_back (&edit_items.back()); - edit_items.push_back (SeparatorElem()); - edit_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint))); - mitems.push_back (&edit_items.back()); - edit_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint))); - mitems.push_back (&edit_items.back()); - edit_items.push_back (SeparatorElem()); - - if (selection->empty()) { - for (vector::iterator i = mitems.begin(); i != mitems.end(); ++i) { - (*i)->set_sensitive (false); + if (undo_action && session) { + if (session->undo_depth() == 0) { + label = _("Undo"); + } else { + label = string_compose(_("Undo (%1)"), session->next_undo()); } + undo_action->property_label() = label; } - Menu* import_menu = manage (new Menu()); - import_menu->set_name ("ArdourContextMenu"); - MenuList& import_items = import_menu->items(); - - import_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportAsTrack))); - import_items.push_back (MenuElem (_("... as new region"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportAsRegion))); - - edit_items.push_back (MenuElem (_("Import audio (copy)"), *import_menu)); - edit_items.push_back (SeparatorElem()); - - edit_items.push_back (MenuElem (_("Remove last capture"), mem_fun(*this, &Editor::remove_last_capture))); - - if (!session->have_captured()) { - edit_items.back().set_sensitive (false); + if (redo_action && session) { + if (session->redo_depth() == 0) { + label = _("Redo"); + } else { + label = string_compose(_("Redo (%1)"), session->next_redo()); + } + redo_action->property_label() = label; } - - return false; } void @@ -3516,7 +2854,7 @@ Editor::duplicate_dialog (bool dup_region) entry.set_text ("1"); set_size_request_to_display_given_text (entry, X_("12345678"), 20, 15); - entry.select_region (0, entry.get_text_length()); + entry.select_region (0, -1); entry.grab_focus (); @@ -3532,7 +2870,7 @@ Editor::duplicate_dialog (bool dup_region) if (sscanf (text.c_str(), "%f", ×) == 1) { if (dup_region) { - AudioRegionSelection regions; + RegionSelection regions; regions.add (clicked_regionview); duplicate_some_regions (regions, times); } else { @@ -3583,36 +2921,32 @@ Editor::edit_mode_selection_done () string choice = edit_mode_selector.get_active_text(); EditMode mode = Slide; - if (choice == _("Splice")) { + if (choice == _("Splice Edit")) { mode = Splice; - } else if (choice == _("Slide")) { + } else if (choice == _("Slide Edit")) { mode = Slide; } - session->set_edit_mode (mode); + Config->set_edit_mode (mode); } void Editor::snap_type_selection_done () { - if (session == 0) { - return; - } - string choice = snap_type_selector.get_active_text(); SnapType snaptype = SnapToFrame; - + if (choice == _("Beats/3")) { - snaptype = SnapToAThirdBeat; - } else if (choice == _("Beats/4")) { - snaptype = SnapToAQuarterBeat; - } else if (choice == _("Beats/8")) { - snaptype = SnapToAEighthBeat; - } else if (choice == _("Beats/16")) { - snaptype = SnapToASixteenthBeat; - } else if (choice == _("Beats/32")) { - snaptype = SnapToAThirtysecondBeat; - } else if (choice == _("Beats")) { + snaptype = SnapToAThirdBeat; + } else if (choice == _("Beats/4")) { + snaptype = SnapToAQuarterBeat; + } else if (choice == _("Beats/8")) { + snaptype = SnapToAEighthBeat; + } else if (choice == _("Beats/16")) { + snaptype = SnapToASixteenthBeat; + } else if (choice == _("Beats/32")) { + snaptype = SnapToAThirtysecondBeat; + } else if (choice == _("Beats")) { snaptype = SnapToBeat; } else if (choice == _("Bars")) { snaptype = SnapToBar; @@ -3640,20 +2974,19 @@ Editor::snap_type_selection_done () snaptype = SnapToSeconds; } else if (choice == _("Minutes")) { snaptype = SnapToMinutes; - } else if (choice == _("None")) { + } else if (choice == _("None")) { snaptype = SnapToFrame; } - - set_snap_to (snaptype); + + RefPtr ract = snap_type_action (snaptype); + if (ract) { + ract->set_active (); + } } void Editor::snap_mode_selection_done () { - if(session == 0) { - return; - } - string choice = snap_mode_selector.get_active_text(); SnapMode mode = SnapNormal; @@ -3663,16 +2996,16 @@ Editor::snap_mode_selection_done () mode = SnapMagnetic; } - set_snap_mode (mode); + RefPtr ract = snap_mode_action (mode); + + if (ract) { + ract->set_active (true); + } } void Editor::zoom_focus_selection_done () { - if (session == 0) { - return; - } - string choice = zoom_focus_selector.get_active_text(); ZoomFocus focus_type = ZoomFocusLeft; @@ -3682,13 +3015,17 @@ Editor::zoom_focus_selection_done () focus_type = ZoomFocusRight; } else if (choice == _("Center")) { focus_type = ZoomFocusCenter; - } else if (choice == _("Playhead")) { + } else if (choice == _("Playhead")) { focus_type = ZoomFocusPlayhead; - } else if (choice == _("Edit Cursor")) { + } else if (choice == _("Edit Cursor")) { focus_type = ZoomFocusEdit; } + + RefPtr ract = zoom_focus_action (focus_type); - set_zoom_focus (focus_type); + if (ract) { + ract->set_active (); + } } gint @@ -3700,82 +3037,16 @@ Editor::edit_controls_button_release (GdkEventButton* ev) return TRUE; } -void -Editor::track_selection_changed () -{ - switch (selection->tracks.size()){ - case 0: - break; - default: - set_selected_mixer_strip (*(selection->tracks.front())); - break; - } - - 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); - } - } -} - -void -Editor::time_selection_changed () -{ - for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { - (*i)->hide_selection (); - } - - if (selection->tracks.empty()) { - for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { - (*i)->show_selection (selection->time); - } - } else { - for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { - (*i)->show_selection (selection->time); - } - } - - if (selection->time.empty()) { - ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, false); - } else { - ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, true); - } -} - -void -Editor::region_selection_changed () -{ - for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { - (*i)->set_selected_regionviews (selection->audio_regions); - } -} - -void -Editor::point_selection_changed () -{ - for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { - (*i)->set_selected_points (selection->points); - } -} - gint Editor::mouse_select_button_release (GdkEventButton* ev) { /* this handles just right-clicks */ if (ev->button != 3) { - return FALSE; + return false; } - return TRUE; + return true; } Editor::TrackViewList * @@ -3819,10 +3090,15 @@ Editor::get_valid_views (TimeAxisView* track, RouteGroup* group) void Editor::set_zoom_focus (ZoomFocus f) { + string str = zoom_focus_strings[(int)f]; + + if (str != zoom_focus_selector.get_active_text()) { + zoom_focus_selector.set_active_text (str); + } + if (zoom_focus != f) { zoom_focus = f; - vector txt = internationalize (zoom_focus_strings); - zoom_focus_selector.set_active_text (txt[(int)f]); + ZoomFocusChanged (); /* EMIT_SIGNAL */ instant_save (); @@ -3934,21 +3210,33 @@ Editor::set_follow_playhead (bool yn) } void -Editor::toggle_xfade_active (Crossfade* xfade) +Editor::toggle_xfade_active (boost::weak_ptr wxfade) { - xfade->set_active (!xfade->active()); + boost::shared_ptr xfade (wxfade.lock()); + if (xfade) { + xfade->set_active (!xfade->active()); + } } void -Editor::toggle_xfade_length (Crossfade* xfade) +Editor::toggle_xfade_length (boost::weak_ptr wxfade) { - xfade->set_follow_overlap (!xfade->following_overlap()); + boost::shared_ptr xfade (wxfade.lock()); + if (xfade) { + xfade->set_follow_overlap (!xfade->following_overlap()); + } } void -Editor::edit_xfade (Crossfade* xfade) +Editor::edit_xfade (boost::weak_ptr wxfade) { - CrossfadeEditor cew (*session, *xfade, xfade->fade_in().get_min_y(), 1.0); + boost::shared_ptr xfade (wxfade.lock()); + + if (!xfade) { + return; + } + + CrossfadeEditor cew (*session, xfade, xfade->fade_in().get_min_y(), 1.0); ensure_float (cew); @@ -3969,10 +3257,10 @@ Editor::playlist_selector () const return *_playlist_selector; } -jack_nframes_t -Editor::get_nudge_distance (jack_nframes_t pos, jack_nframes_t& next) +nframes_t +Editor::get_nudge_distance (nframes_t pos, nframes_t& next) { - jack_nframes_t ret; + nframes_t ret; ret = nudge_clock.current_duration (pos); next = ret + 1; /* XXXX fix me */ @@ -3988,17 +3276,19 @@ Editor::end_location_changed (Location* location) } int -Editor::playlist_deletion_dialog (Playlist* pl) +Editor::playlist_deletion_dialog (boost::shared_ptr pl) { ArdourDialog dialog ("playlist deletion dialog"); Label label (string_compose (_("Playlist %1 is currently unused.\n" - "If left alone, no audio files used by it will be cleaned.\n" - "If deleted, audio files used by it alone by will cleaned."), - pl->name())); - + "If left alone, no audio files used by it will be cleaned.\n" + "If deleted, audio files used by it alone by will cleaned."), + pl->name())); + dialog.set_position (WIN_POS_CENTER); dialog.get_vbox()->pack_start (label); + label.show (); + dialog.add_button (_("Delete playlist"), RESPONSE_ACCEPT); dialog.add_button (_("Keep playlist"), RESPONSE_CANCEL); dialog.add_button (_("Cancel"), RESPONSE_CANCEL); @@ -4022,10 +3312,10 @@ Editor::playlist_deletion_dialog (Playlist* pl) } bool -Editor::audio_region_selection_covers (jack_nframes_t where) +Editor::audio_region_selection_covers (nframes_t where) { - for (AudioRegionSelection::iterator a = selection->audio_regions.begin(); a != selection->audio_regions.end(); ++a) { - if ((*a)->region.covers (where)) { + for (RegionSelection::iterator a = selection->regions.begin(); a != selection->regions.end(); ++a) { + if ((*a)->region()->covers (where)) { return true; } } @@ -4036,10 +3326,10 @@ Editor::audio_region_selection_covers (jack_nframes_t where) void Editor::prepare_for_cleanup () { - cut_buffer->clear_audio_regions (); + cut_buffer->clear_regions (); cut_buffer->clear_playlists (); - selection->clear_audio_regions (); + selection->clear_regions (); selection->clear_playlists (); } @@ -4129,7 +3419,19 @@ Editor::redisplay_snapshots () for (vector::iterator i = states->begin(); i != states->end(); ++i) { string statename = *(*i); TreeModel::Row row = *(snapshot_display_model->append()); - row[snapshot_display_columns.visible_name] = statename; + + /* this lingers on in case we ever want to change the visible + name of the snapshot. + */ + + string display_name; + display_name = statename; + + if (statename == session->snap_name()) { + snapshot_display.get_selection()->select(row); + } + + row[snapshot_display_columns.visible_name] = display_name; row[snapshot_display_columns.real_name] = statename; } @@ -4146,30 +3448,55 @@ Editor::session_state_saved (string snap_name) void Editor::maximise_editing_space () { + initial_ruler_update_required = true; + mouse_mode_tearoff->set_visible (false); tools_tearoff->set_visible (false); pre_maximal_pane_position = edit_pane.get_position(); - edit_pane.set_position (edit_pane.get_width()); + pre_maximal_editor_width = this->get_width(); + + if(post_maximal_pane_position == 0) { + post_maximal_pane_position = edit_pane.get_width(); + } + fullscreen(); + if(post_maximal_editor_width) { + edit_pane.set_position (post_maximal_pane_position - + abs(post_maximal_editor_width - pre_maximal_editor_width)); + } else { + edit_pane.set_position (post_maximal_pane_position); + } } void Editor::restore_editing_space () { + initial_ruler_update_required = true; + + // user changed width of pane during fullscreen + if(post_maximal_pane_position != edit_pane.get_position()) { + post_maximal_pane_position = edit_pane.get_position(); + } + + unfullscreen(); + mouse_mode_tearoff->set_visible (true); tools_tearoff->set_visible (true); - edit_pane.set_position (pre_maximal_pane_position); + post_maximal_editor_width = this->get_width(); - unfullscreen(); + + edit_pane.set_position ( + pre_maximal_pane_position + abs(this->get_width() - pre_maximal_editor_width) + ); } void Editor::new_playlists () { begin_reversible_command (_("new playlists")); - mapover_audio_tracks (mem_fun (*this, &Editor::mapped_use_new_playlist)); + mapover_tracks (mem_fun (*this, &Editor::mapped_use_new_playlist)); commit_reversible_command (); } @@ -4177,7 +3504,7 @@ void Editor::copy_playlists () { begin_reversible_command (_("copy playlists")); - mapover_audio_tracks (mem_fun (*this, &Editor::mapped_use_copy_playlist)); + mapover_tracks (mem_fun (*this, &Editor::mapped_use_copy_playlist)); commit_reversible_command (); } @@ -4185,24 +3512,24 @@ void Editor::clear_playlists () { begin_reversible_command (_("clear playlists")); - mapover_audio_tracks (mem_fun (*this, &Editor::mapped_clear_playlist)); + mapover_tracks (mem_fun (*this, &Editor::mapped_clear_playlist)); commit_reversible_command (); } void -Editor::mapped_use_new_playlist (AudioTimeAxisView& atv, uint32_t sz) +Editor::mapped_use_new_playlist (RouteTimeAxisView& atv, uint32_t sz) { atv.use_new_playlist (sz > 1 ? false : true); } void -Editor::mapped_use_copy_playlist (AudioTimeAxisView& atv, uint32_t sz) +Editor::mapped_use_copy_playlist (RouteTimeAxisView& atv, uint32_t sz) { atv.use_copy_playlist (sz > 1 ? false : true); } void -Editor::mapped_clear_playlist (AudioTimeAxisView& atv, uint32_t sz) +Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t sz) { atv.clear_playlist (); } @@ -4214,50 +3541,169 @@ Editor::on_key_press_event (GdkEventKey* ev) } void -Editor::update_layering_model () +Editor::reset_x_origin (nframes_t frame) { - RefPtr act; + queue_visual_change (frame); +} - switch (session->get_layer_model()) { - case Session::LaterHigher: - act = ActionManager::get_action (X_("Editor"), X_("LayerLaterHigher")); - break; - case Session::MoveAddHigher: - act = ActionManager::get_action (X_("Editor"), X_("LayerMoveAddHigher")); - break; - case Session::AddHigher: - act = ActionManager::get_action (X_("Editor"), X_("LayerAddHigher")); - break; +void +Editor::reset_zoom (double fpu) +{ + queue_visual_change (fpu); +} + +void +Editor::reposition_and_zoom (nframes_t frame, double fpu) +{ + reset_x_origin (frame); + reset_zoom (fpu); +} + +void +Editor::set_frames_per_unit (double fpu) +{ + nframes_t frames; + + /* 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. + */ + + if (fpu == frames_per_unit) { + return; } - if (act) { - RefPtr ract = RefPtr::cast_dynamic(act); - if (ract && !ract->get_active()) { - ract->set_active (true); + if (fpu < 2.0) { + 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. + */ + + if (max_frames / fpu < 800.0) { + return; + } + + if (fpu == frames_per_unit) { + return; + } + + frames_per_unit = fpu; + + if (frames != 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()) { + for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { + (*i)->reshow_selection (selection->time); + } + } else { + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { + (*i)->reshow_selection (selection->time); + } } } + + ZoomChanged (); /* EMIT_SIGNAL */ + + reset_hscrollbar_stepping (); + reset_scrolling_region (); + + if (edit_cursor) edit_cursor->set_position (edit_cursor->current_frame); + if (playhead_cursor) playhead_cursor->set_position (playhead_cursor->current_frame); + + instant_save (); +} + +void +Editor::canvas_horizontally_scrolled () +{ + /* this is the core function that controls horizontal scrolling of the canvas. it is called + whenever the horizontal_adjustment emits its "value_changed" signal. it executes in an + idle handler. + */ + + leftmost_frame = (nframes_t) floor (horizontal_adjustment.get_value() * frames_per_unit); + nframes_t rightmost_frame = leftmost_frame + current_page_frames (); + + if (rightmost_frame > last_canvas_frame) { + last_canvas_frame = rightmost_frame; + reset_scrolling_region (); + } + + update_fixed_rulers (); + tempo_map_changed (Change (0)); } +void +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); + } +} void -Editor::update_crossfade_model () +Editor::queue_visual_change (double fpu) { - RefPtr act; + pending_visual_change.pending = VisualChange::Type (pending_visual_change.pending | VisualChange::ZoomLevel); + pending_visual_change.frames_per_unit = fpu; - switch (session->get_xfade_model()) { - case FullCrossfade: - act = ActionManager::get_action (X_("Editor"), X_("CrossfadesFull")); - break; - case ShortCrossfade: - act = ActionManager::get_action (X_("Editor"), X_("CrossfadesShort")); - break; + if (pending_visual_change.idle_handler_id < 0) { + pending_visual_change.idle_handler_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE, _idle_visual_changer, this, 0); } +} - if (act) { - RefPtr ract = RefPtr::cast_dynamic(act); - if (ract && !ract->get_active()) { - ract->set_active (true); +int +Editor::_idle_visual_changer (void* arg) +{ + return static_cast(arg)->idle_visual_changer (); +} + +int +Editor::idle_visual_changer () +{ + VisualChange::Type p = pending_visual_change.pending; + + pending_visual_change.pending = (VisualChange::Type) 0; + pending_visual_change.idle_handler_id = -1; + + if (p & VisualChange::ZoomLevel) { + set_frames_per_unit (pending_visual_change.frames_per_unit); + } + + if (p & VisualChange::TimeOrigin) { + if (pending_visual_change.time_origin != leftmost_frame) { + horizontal_adjustment.set_value (pending_visual_change.time_origin/frames_per_unit); + /* the signal handler will do the rest */ + } else { + update_fixed_rulers(); + tempo_map_changed (Change (0)); } } + + return 0; +} + +struct EditorOrderTimeAxisSorter { + bool operator() (const TimeAxisView* a, const TimeAxisView* b) const { + return a->order < b->order; + } +}; + +void +Editor::sort_track_selection () +{ + EditorOrderTimeAxisSorter cmp; + selection->tracks.sort (cmp); }