diff options
-rw-r--r-- | SConstruct | 2 | ||||
-rw-r--r-- | gtk2_ardour/SConscript | 1 | ||||
-rw-r--r-- | gtk2_ardour/audio_time_axis.cc | 2 | ||||
-rw-r--r-- | gtk2_ardour/draginfo.h | 2 | ||||
-rw-r--r-- | gtk2_ardour/editor.cc | 289 | ||||
-rw-r--r-- | gtk2_ardour/editor.h | 13 | ||||
-rw-r--r-- | gtk2_ardour/editor_canvas.cc | 1 | ||||
-rw-r--r-- | gtk2_ardour/editor_mouse.cc | 344 | ||||
-rw-r--r-- | gtk2_ardour/opts.cc | 2 | ||||
-rw-r--r-- | gtk2_ardour/selection.cc | 23 | ||||
-rw-r--r-- | libs/ardour/ardour/audioregion.h | 9 | ||||
-rw-r--r-- | libs/ardour/ardour/configuration_vars.h | 3 | ||||
-rw-r--r-- | libs/ardour/ardour/location.h | 3 | ||||
-rw-r--r-- | libs/ardour/audio_playlist.cc | 10 | ||||
-rw-r--r-- | libs/ardour/audioregion.cc | 16 | ||||
-rw-r--r-- | libs/ardour/location.cc | 74 | ||||
-rw-r--r-- | libs/ardour/utils.cc | 9 | ||||
-rw-r--r-- | libs/pbd3/SConscript | 2 | ||||
-rw-r--r-- | libs/pbd3/undo.cc | 2 | ||||
-rw-r--r-- | libs/surfaces/control_protocol/SConscript | 2 | ||||
-rw-r--r-- | libs/surfaces/generic_midi/SConscript | 2 | ||||
-rw-r--r-- | libs/surfaces/tranzport/SConscript | 2 |
22 files changed, 560 insertions, 253 deletions
diff --git a/SConstruct b/SConstruct index 6663674a3c..1403b69c8a 100644 --- a/SConstruct +++ b/SConstruct @@ -14,7 +14,7 @@ import SCons.Node.FS SConsignFile() EnsureSConsVersion(0, 96) -version = '2.0alpha2' +version = '2.0beta1' subst_dict = { } diff --git a/gtk2_ardour/SConscript b/gtk2_ardour/SConscript index db89dfa457..8ab1c0c19c 100644 --- a/gtk2_ardour/SConscript +++ b/gtk2_ardour/SConscript @@ -262,6 +262,7 @@ env.Alias('install', env.Install(os.path.join(install_prefix, 'share/ardour2/pix env.Alias ('tarball', env.Distribute (env['DISTTREE'], [ 'SConscript', 'i18n.h', 'gettext.h', + 'ardour.sh.in', 'ardour2_ui.rc', 'splash.ppm', 'ardour.menus', 'ardour.bindings', 'ardour.colors', 'editor_xpms' diff --git a/gtk2_ardour/audio_time_axis.cc b/gtk2_ardour/audio_time_axis.cc index b225e47c0d..84c7bf7e15 100644 --- a/gtk2_ardour/audio_time_axis.cc +++ b/gtk2_ardour/audio_time_axis.cc @@ -1048,7 +1048,7 @@ AudioTimeAxisView::get_selectables (jack_nframes_t start, jack_nframes_t end, do jack_nframes_t start_adjusted = session_frame_to_track_frame(start, speed); jack_nframes_t end_adjusted = session_frame_to_track_frame(end, speed); - if (view && touched (top, bot)) { + if (view && ((top < 0.0 && bot < 0.0)) || touched (top, bot)) { view->get_selectables (start_adjusted, end_adjusted, results); } diff --git a/gtk2_ardour/draginfo.h b/gtk2_ardour/draginfo.h index a86f7362cc..12458fdf34 100644 --- a/gtk2_ardour/draginfo.h +++ b/gtk2_ardour/draginfo.h @@ -38,7 +38,7 @@ struct DragInfo { bool copy; bool was_rolling; bool first_move; - bool move_threshold_passsed; + bool move_threshold_passed; bool want_move_threshold; bool brushing; ARDOUR::Location* copied_location; diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 5caef7fc19..6dc3b955f1 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -326,6 +326,7 @@ Editor::Editor (AudioEngine& eng) last_canvas_frame = 0; edit_cursor = 0; playhead_cursor = 0; + button_release_can_deselect = true; location_marker_color = color_map[cLocationMarker]; location_range_color = color_map[cLocationRange]; @@ -2981,31 +2982,31 @@ Editor::commit_reversible_command () } } -void -Editor::set_selected_track_from_click (Selection::Operation op, bool with_undo, bool no_remove) +bool +Editor::set_selected_track_from_click (bool press, Selection::Operation op, bool with_undo, bool no_remove) { + bool commit = false; + if (!clicked_trackview) { - return; + return false; } - 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); + commit = true; } } else { - selection->toggle (clicked_trackview); + selection->add (clicked_trackview); + commit = false; } break; + case Selection::Set: if (selection->selected (clicked_trackview) && selection->tracks.size() == 1) { /* no commit necessary */ - return; } selection->set (clicked_trackview); @@ -3015,27 +3016,19 @@ Editor::set_selected_track_from_click (Selection::Operation op, bool with_undo, /* not defined yet */ break; } - - if (with_undo) { - commit_reversible_command (); - } + + return commit; } -void -Editor::set_selected_control_point_from_click (Selection::Operation op, bool with_undo, bool no_remove) +bool +Editor::set_selected_control_point_from_click (bool press, Selection::Operation op, bool with_undo, bool no_remove) { if (!clicked_control_point) { - return; + return false; } /* select this point and any others that it represents */ - bool commit; - - if (with_undo) { - begin_reversible_command (_("select control points")); - } - double y1, y2; jack_nframes_t x1, x2; @@ -3044,18 +3037,12 @@ Editor::set_selected_control_point_from_click (Selection::Operation op, bool wit y1 = clicked_control_point->get_x() - 10; y2 = clicked_control_point->get_y() + 10; - commit = select_all_within (x1, x2, y1, y2, op); - - if (with_undo && commit) { - commit_reversible_command (); - } + return select_all_within (x1, x2, y1, y2, op); } void -Editor::mapover_audio_tracks (slot<void,AudioTimeAxisView&,uint32_t> sl) +Editor::get_relevant_audio_tracks (AudioTimeAxisView& base, set<AudioTimeAxisView*>& relevant_tracks) { - set<AudioTimeAxisView*> 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) { @@ -3088,12 +3075,22 @@ Editor::mapover_audio_tracks (slot<void,AudioTimeAxisView&,uint32_t> sl) /* no active group, or no group */ - relevant_tracks.insert (atv); + relevant_tracks.insert (&base); } } +} + +void +Editor::mapover_audio_tracks (slot<void,AudioTimeAxisView&,uint32_t> sl) +{ + set<AudioTimeAxisView*> relevant_tracks; + + if (!clicked_audio_trackview) { + return; + } - /* step two: apply operation to each track */ + get_relevant_audio_tracks (*clicked_audio_trackview, relevant_tracks); uint32_t sz = relevant_tracks.size(); @@ -3110,11 +3107,17 @@ Editor::mapped_set_selected_regionview_from_click (AudioTimeAxisView& atv, uint3 vector<AudioRegion*> results; AudioRegionView* marv; DiskStream* ds; - + if ((ds = atv.get_diskstream()) == 0) { /* bus */ return; } + + if (&atv == &basis->get_time_axis_view()) { + /* looking in same track as the original */ + return; + } + if ((pl = ds->playlist()) != 0) { pl->get_equivalent_regions (basis->region, results); @@ -3127,70 +3130,192 @@ Editor::mapped_set_selected_regionview_from_click (AudioTimeAxisView& atv, uint3 } } -void -Editor::set_selected_regionview_from_click (Selection::Operation op, bool no_track_remove) +bool +Editor::set_selected_regionview_from_click (bool press, Selection::Operation op, bool no_track_remove) { - cerr << "In SSRfC\n"; - vector<AudioRegionView*> all_equivalent_regions; + bool commit = false; - if (!clicked_regionview) { - return; + if (!clicked_regionview || !clicked_audio_trackview) { + return false; } - mapover_audio_tracks (bind (mem_fun (*this, &Editor::mapped_set_selected_regionview_from_click), - clicked_regionview, &all_equivalent_regions)); - + if (op == Selection::Toggle || op == Selection::Set) { + + mapover_audio_tracks (bind (mem_fun (*this, &Editor::mapped_set_selected_regionview_from_click), + clicked_regionview, &all_equivalent_regions)); + + + /* add clicked regionview since we skipped all other regions in the same track as the one it was in */ + + all_equivalent_regions.push_back (clicked_regionview); + + switch (op) { + case Selection::Toggle: + + if (clicked_regionview->get_selected()) { + if (press) { - cerr << "mapover done\n"; + /* whatever was clicked was selected already; do nothing here but allow + the button release to deselect it + */ - begin_reversible_command (_("set selected regionview")); + button_release_can_deselect = true; - 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 { + + if (button_release_can_deselect) { + + /* just remove this one region, but only on a permitted button release */ + + selection->remove (clicked_regionview); + commit = true; + + /* no more deselect action on button release till a new press + finds an already selected object. + */ + + button_release_can_deselect = false; + } + } + + } else { + + if (press) { + /* add all the equivalent regions, but only on button press */ + + if (!all_equivalent_regions.empty()) { + commit = true; + } + + for (vector<AudioRegionView*>::iterator i = all_equivalent_regions.begin(); i != all_equivalent_regions.end(); ++i) { + selection->add (*i); + } + } + } + break; + + case Selection::Set: + if (!clicked_regionview->get_selected()) { + selection->set (all_equivalent_regions); + commit = true; } else { - selection->remove (clicked_regionview); + /* no commit necessary: clicked on an already selected region */ + goto out; } - } else { - selection->add (all_equivalent_regions); + break; + + default: + /* silly compiler */ + break; } -#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 if (op == Selection::Extend) { - } else { - - selection->set (all_equivalent_regions); - set_selected_track_from_click (op, false, false); + list<Selectable*> results; + jack_nframes_t last_frame; + jack_nframes_t first_frame; + + /* 1. find the last selected regionview in the track that was clicked in */ + + last_frame = 0; + first_frame = max_frames; + + for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ++x) { + if (&(*x)->get_time_axis_view() == &clicked_regionview->get_time_axis_view()) { + + if ((*x)->region.last_frame() > last_frame) { + last_frame = (*x)->region.last_frame(); + } + + if ((*x)->region.first_frame() < first_frame) { + first_frame = (*x)->region.first_frame(); + } + } } - break; - case Selection::Extend: - /* not defined yet */ - break; + /* 2. figure out the boundaries for our search for new objects */ + + switch (clicked_regionview->region.coverage (first_frame, last_frame)) { + case OverlapNone: + cerr << "no overlap, first = " << first_frame << " last = " << last_frame << " region = " + << clicked_regionview->region.first_frame() << " .. " << clicked_regionview->region.last_frame() << endl; + + if (last_frame < clicked_regionview->region.first_frame()) { + first_frame = last_frame; + last_frame = clicked_regionview->region.last_frame(); + } else { + last_frame = first_frame; + first_frame = clicked_regionview->region.first_frame(); + } + break; + + case OverlapExternal: + cerr << "external overlap, first = " << first_frame << " last = " << last_frame << " region = " + << clicked_regionview->region.first_frame() << " .. " << clicked_regionview->region.last_frame() << endl; + + if (last_frame < clicked_regionview->region.first_frame()) { + first_frame = last_frame; + last_frame = clicked_regionview->region.last_frame(); + } else { + last_frame = first_frame; + first_frame = clicked_regionview->region.first_frame(); + } + break; + + case OverlapInternal: + cerr << "internal overlap, first = " << first_frame << " last = " << last_frame << " region = " + << clicked_regionview->region.first_frame() << " .. " << clicked_regionview->region.last_frame() << endl; + + if (last_frame < clicked_regionview->region.first_frame()) { + first_frame = last_frame; + last_frame = clicked_regionview->region.last_frame(); + } else { + last_frame = first_frame; + first_frame = clicked_regionview->region.first_frame(); + } + break; + + case OverlapStart: + case OverlapEnd: + /* nothing to do except add clicked region to selection, since it + overlaps with the existing selection in this track. + */ + break; + } + + /* 2. find all selectable objects (regionviews in this case) between that one and the end of the + one that was clicked. + */ + + set<AudioTimeAxisView*> relevant_tracks; + + get_relevant_audio_tracks (*clicked_audio_trackview, relevant_tracks); + + for (set<AudioTimeAxisView*>::iterator t = relevant_tracks.begin(); t != relevant_tracks.end(); ++t) { + (*t)->get_selectables (first_frame, last_frame, -1.0, -1.0, results); + } + + /* 3. convert to a vector of audio regions */ + + vector<AudioRegionView*> audio_regions; + + for (list<Selectable*>::iterator x = results.begin(); x != results.end(); ++x) { + AudioRegionView* arv; + + if ((arv = dynamic_cast<AudioRegionView*>(*x)) != 0) { + audio_regions.push_back (arv); + } + } + + if (!audio_regions.empty()) { + selection->add (audio_regions); + commit = true; + } } - cerr << "case done\n"; - commit_reversible_command () ; + out: + return commit; } void @@ -3237,13 +3362,13 @@ Editor::set_selected_regionview_from_region_list (Region& r, Selection::Operatio switch (op) { case Selection::Toggle: /* XXX this is not correct */ - selection->add (all_equivalent_regions); + selection->toggle (all_equivalent_regions); break; case Selection::Set: selection->set (all_equivalent_regions); break; case Selection::Extend: - /* not defined yet */ + selection->add (all_equivalent_regions); break; } diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 307cd71799..8b7b2af1d0 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -413,6 +413,7 @@ class Editor : public PublicEditor CrossfadeView* clicked_crossfadeview; ControlPoint* clicked_control_point; + void get_relevant_audio_tracks (AudioTimeAxisView& base, std::set<AudioTimeAxisView*>& relevant_tracks); void mapover_audio_tracks (sigc::slot<void,AudioTimeAxisView&,uint32_t> sl); /* functions to be passed to mapover_audio_tracks(), possibly with sigc::bind()-supplied arguments */ @@ -424,10 +425,15 @@ class Editor : public PublicEditor /* end */ + void button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type); + bool button_release_can_deselect; + void catch_vanishing_audio_regionview (AudioRegionView *); - void set_selected_control_point_from_click (Selection::Operation op = Selection::Set, bool with_undo = true, bool no_remove=false); - void set_selected_track_from_click (Selection::Operation op = Selection::Set, bool with_undo = true, bool no_remove=false); - void set_selected_regionview_from_click (Selection::Operation op = Selection::Set, bool no_track_remove=false); + + bool set_selected_control_point_from_click (bool press, Selection::Operation op = Selection::Set, bool with_undo = true, bool no_remove=false); + bool set_selected_track_from_click (bool press, Selection::Operation op = Selection::Set, bool with_undo = true, bool no_remove=false); + bool set_selected_regionview_from_click (bool press, Selection::Operation op = Selection::Set, bool no_track_remove=false); + void set_selected_regionview_from_region_list (ARDOUR::Region& region, Selection::Operation op = Selection::Set); bool set_selected_regionview_from_map_event (GdkEventAny*, StreamView*, ARDOUR::Region*); void collect_new_region_view (AudioRegionView *); @@ -1037,6 +1043,7 @@ class Editor : public PublicEditor void start_grab (GdkEvent*, Gdk::Cursor* cursor = 0); bool end_grab (ArdourCanvas::Item*, GdkEvent*); + void swap_grab (ArdourCanvas::Item*, Gdk::Cursor* cursor, uint32_t time); Gtk::Menu fade_context_menu; void popup_fade_context_menu (int, int, ArdourCanvas::Item*, ItemType); diff --git a/gtk2_ardour/editor_canvas.cc b/gtk2_ardour/editor_canvas.cc index 73aeef79b2..69aa6428a6 100644 --- a/gtk2_ardour/editor_canvas.cc +++ b/gtk2_ardour/editor_canvas.cc @@ -537,7 +537,6 @@ Editor::maybe_autoscroll (GdkEvent* event) } last_autoscroll_direction = autoscroll_direction; - drag_info.last_pointer_frame = drag_info.current_pointer_frame; } gint diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index 1409da77a9..249b1d781a 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -96,7 +96,6 @@ Editor::event_frame (GdkEvent* event, double* pcx, double* pcy) break; case GDK_KEY_PRESS: case GDK_KEY_RELEASE: - cerr << "here\n"; // track_canvas.w2c(event->key.x, event->key.y, *pcx, *pcy); break; default: @@ -284,66 +283,68 @@ Editor::step_mouse_mode (bool next) } } -bool -Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type) +void +Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type) { - jack_nframes_t where = event_frame (event, 0, 0); - - track_canvas.grab_focus(); - - if (session && session->actively_recording()) { - return true; - } + bool commit; + bool c1; + bool c2; /* in object/audition/timefx mode, any button press sets the selection if the object can be selected. this is a bit of hack, because we want to avoid this if the mouse operation is a region alignment. - */ - - if (((mouse_mode == MouseObject) || - (mouse_mode == MouseAudition && item_type == RegionItem) || - (mouse_mode == MouseTimeFX && item_type == RegionItem)) && - event->type == GDK_BUTTON_PRESS && - event->button.button <= 3) { - - AudioRegionView* rv; - ControlPoint* cp; - - /* not dbl-click or triple-click */ - switch (item_type) { - case RegionItem: - set_selected_regionview_from_click (Keyboard::selection_type (event->button.state), true); - break; - - case AudioRegionViewNameHighlight: - case AudioRegionViewName: - if ((rv = static_cast<AudioRegionView *> (item->get_data ("regionview"))) != 0) { - set_selected_regionview_from_click (Keyboard::selection_type (event->button.state), true); - } - break; - - case GainAutomationControlPointItem: - case PanAutomationControlPointItem: - case RedirectAutomationControlPointItem: - if ((cp = static_cast<ControlPoint *> (item->get_data ("control_point"))) != 0) { - set_selected_control_point_from_click (Keyboard::selection_type (event->button.state), false); - } - break; + note: not dbl-click or triple-click + */ - case StreamItem: - set_selected_track_from_click (Keyboard::selection_type (event->button.state), true, true); - break; + if (((mouse_mode != MouseObject) && + (mouse_mode != MouseAudition || item_type != RegionItem) && + (mouse_mode != MouseTimeFX || item_type != RegionItem)) || + (event->type != GDK_BUTTON_PRESS && event->type != GDK_BUTTON_RELEASE || event->button.button > 3)) { + + return; + } + + Selection::Operation op = Keyboard::selection_type (event->button.state); + bool press = (event->type == GDK_BUTTON_PRESS); - case AutomationTrackItem: - break; + begin_reversible_command (_("select on click")); - default: - break; - } + switch (item_type) { + case RegionItem: + c1 = set_selected_track_from_click (press, op, true, true); + c2 = set_selected_regionview_from_click (press, op, true); + commit = (c1 || c2); + break; + + case AudioRegionViewNameHighlight: + case AudioRegionViewName: + c1 = set_selected_track_from_click (press, op, true, true); + c2 = set_selected_regionview_from_click (press, op, true); + commit = (c1 || c2); + break; + + case GainAutomationControlPointItem: + case PanAutomationControlPointItem: + case RedirectAutomationControlPointItem: + c1 = set_selected_track_from_click (press, op, true, true); + c2 = set_selected_control_point_from_click (press, op, false); + commit = (c1 || c2); + break; + + case StreamItem: + commit = set_selected_track_from_click (press, op, true, true); + break; + + case AutomationTrackItem: + commit = set_selected_track_from_click (press, op, true, true); + break; + + default: + break; } - + #define SELECT_TRACK_FROM_CANVAS_IN_RANGE_MODE #ifdef SELECT_TRACK_FROM_CANVAS_IN_RANGE_MODE /* in range mode, button 1/2/3 press potentially selects a track */ @@ -352,24 +353,36 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp event->type == GDK_BUTTON_PRESS && event->button.button <= 3) { - AudioRegionView* rv; - switch (item_type) { case StreamItem: case RegionItem: case AutomationTrackItem: - set_selected_track_from_click (Keyboard::selection_type (event->button.state), true, true); + commit = set_selected_track_from_click (press, op, true, true); break; - case AudioRegionViewNameHighlight: - case AudioRegionViewName: - rv = reinterpret_cast<AudioRegionView *> (item->get_data ("regionview")); default: break; } } #endif + if (commit) { + commit_reversible_command (); + } +} + +bool +Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type) +{ + jack_nframes_t where = event_frame (event, 0, 0); + + track_canvas.grab_focus(); + if (session && session->actively_recording()) { + return true; + } + + button_selection (item, event, item_type); + if (drag_info.item == 0 && (Keyboard::is_delete_event (&event->button) || Keyboard::is_context_menu_event (&event->button) || @@ -435,6 +448,7 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp start_range_markerbar_op (item, event, CreateRangeMarker); return true; break; + case TransportMarkerBarItem: start_range_markerbar_op (item, event, CreateTransportMarker); return true; @@ -564,6 +578,10 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp break ; /* </CMT Additions> */ + case MarkerBarItem: + + break; + default: break; } @@ -816,6 +834,8 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT } } + button_selection (item, event, item_type); + /* edit events get handled here */ if (drag_info.item == 0 && Keyboard::is_edit_event (&event->button)) { @@ -1477,13 +1497,13 @@ Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item if (!from_autoscroll && drag_info.item) { /* item != 0 is the best test i can think of for dragging. */ - if (!drag_info.move_threshold_passsed) { + if (!drag_info.move_threshold_passed) { - drag_info.move_threshold_passsed = (abs ((int) (drag_info.current_pointer_x - drag_info.grab_x)) > 4); + drag_info.move_threshold_passed = (abs ((int) (drag_info.current_pointer_x - drag_info.grab_x)) > 4); // and change the initial grab loc/frame if this drag info wants us to - if (drag_info.want_move_threshold && drag_info.move_threshold_passsed) { + if (drag_info.want_move_threshold && drag_info.move_threshold_passed) { drag_info.grab_frame = drag_info.current_pointer_frame; drag_info.grab_x = drag_info.current_pointer_x; drag_info.grab_y = drag_info.current_pointer_y; @@ -1555,6 +1575,7 @@ Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item handled: track_canvas_motion (event); + // drag_info.last_pointer_frame = drag_info.current_pointer_frame; return true; not_handled: @@ -1597,7 +1618,7 @@ Editor::start_grab (GdkEvent* event, Gdk::Cursor *cursor) drag_info.cumulative_x_drag = 0; drag_info.cumulative_y_drag = 0; drag_info.first_move = true; - drag_info.move_threshold_passsed = false; + drag_info.move_threshold_passed = false; drag_info.want_move_threshold = false; drag_info.pointer_frame_offset = 0; drag_info.brushing = false; @@ -1625,6 +1646,19 @@ Editor::start_grab (GdkEvent* event, Gdk::Cursor *cursor) } } +void +Editor::swap_grab (ArdourCanvas::Item* new_item, Gdk::Cursor* cursor, uint32_t time) +{ + drag_info.item->ungrab (0); + drag_info.item = new_item; + + if (cursor == 0) { + cursor = grabber_cursor; + } + + drag_info.item->grab (Gdk::POINTER_MOTION_MASK|Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK, *cursor, time); +} + bool Editor::end_grab (ArdourCanvas::Item* item, GdkEvent* event) { @@ -2020,6 +2054,7 @@ Editor::marker_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) bool is_start; bool move_both = false; + jack_nframes_t newframe; if (drag_info.pointer_frame_offset <= (long) drag_info.current_pointer_frame) { newframe = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; @@ -2027,14 +2062,16 @@ Editor::marker_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) else { newframe = 0; } - + jack_nframes_t next = newframe; if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { snap_to (newframe, 0, true); } - if (drag_info.current_pointer_frame == drag_info.last_pointer_frame) return; + if (drag_info.current_pointer_frame == drag_info.last_pointer_frame) { + return; + } /* call this to find out if its the start or end */ @@ -2101,7 +2138,6 @@ Editor::marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event bool is_start; - begin_reversible_command ( _("move marker") ); session->add_undo( session->locations()->get_memento() ); @@ -2634,68 +2670,9 @@ Editor::start_region_copy_grab (ArdourCanvas::Item* item, GdkEvent* event) return; } - /* this is committed in the grab finished callback. */ - - begin_reversible_command (_("Drag region copy")); - - /* duplicate the region(s) */ - - vector<AudioRegionView*> new_regionviews; - - set<Playlist*> affected_playlists; - pair<set<Playlist*>::iterator,bool> insert_result; - - for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) { - AudioRegionView* rv; - - rv = (*i); - - Playlist* to_playlist = rv->region.playlist(); - AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&rv->get_time_axis_view()); - - insert_result = affected_playlists.insert (to_playlist); - if (insert_result.second) { - session->add_undo (to_playlist->get_memento ()); - } - - latest_regionview = 0; - - sigc::connection c = atv->view->AudioRegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view)); - - /* create a new region with the same name. - */ - - AudioRegion* newregion = new AudioRegion (rv->region); - - /* if the original region was locked, we don't care */ - - newregion->set_locked (false); - - to_playlist->add_region (*newregion, (jack_nframes_t) (rv->region.position() * atv->get_diskstream()->speed())); - - c.disconnect (); - - if (latest_regionview) { - new_regionviews.push_back (latest_regionview); - } - } - - if (new_regionviews.empty()) { - return; - } - - /* reset selection to new regionviews */ - - selection->set (new_regionviews); - - /* reset drag_info data to reflect the fact that we are dragging the copies */ - - drag_info.data = new_regionviews.front(); - drag_info.item = new_regionviews.front()->get_canvas_group (); - drag_info.copy = true; - drag_info.motion_callback = &Editor::region_drag_motion_callback; - drag_info.finished_callback = &Editor::region_drag_finished_callback; + drag_info.item = item; + drag_info.data = clicked_regionview; start_grab(event); @@ -2712,10 +2689,8 @@ Editor::start_region_copy_grab (ArdourCanvas::Item* item, GdkEvent* event) drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position; // we want a move threshold drag_info.want_move_threshold = true; - - show_verbose_time_cursor (drag_info.last_frame_position, 10); - - //begin_reversible_command (_("copy region(s)")); + drag_info.motion_callback = &Editor::region_drag_motion_callback; + drag_info.finished_callback = &Editor::region_drag_finished_callback; } void @@ -2764,6 +2739,72 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) vector<int32_t> height_list(512) ; vector<int32_t>::iterator j; + show_verbose_time_cursor (drag_info.last_frame_position, 10); + + if (drag_info.copy && drag_info.move_threshold_passed && drag_info.want_move_threshold) { + + drag_info.want_move_threshold = false; // don't copy again + + /* this is committed in the grab finished callback. */ + + begin_reversible_command (_("Drag region copy")); + + /* duplicate the region(s) */ + + vector<AudioRegionView*> new_regionviews; + + set<Playlist*> affected_playlists; + pair<set<Playlist*>::iterator,bool> insert_result; + + for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) { + AudioRegionView* rv; + + rv = (*i); + + Playlist* to_playlist = rv->region.playlist(); + AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&rv->get_time_axis_view()); + + insert_result = affected_playlists.insert (to_playlist); + if (insert_result.second) { + session->add_undo (to_playlist->get_memento ()); + } + + latest_regionview = 0; + + sigc::connection c = atv->view->AudioRegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view)); + + /* create a new region with the same name. + */ + + AudioRegion* newregion = new AudioRegion (rv->region); + + /* if the original region was locked, we don't care */ + + newregion->set_locked (false); + + to_playlist->add_region (*newregion, (jack_nframes_t) (rv->region.position() * atv->get_diskstream()->speed())); + + c.disconnect (); + + if (latest_regionview) { + new_regionviews.push_back (latest_regionview); + } + } + + if (new_regionviews.empty()) { + return; + } + + /* reset selection to new regionviews */ + + selection->set (new_regionviews); + + /* reset drag_info data to reflect the fact that we are dragging the copies */ + + drag_info.data = new_regionviews.front(); + swap_grab (new_regionviews.front()->get_canvas_group (), 0, event->motion.time); + } + /* Which trackview is this ? */ TimeAxisView* tvp = trackview_by_y_position (drag_info.current_pointer_y); @@ -2947,7 +2988,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) the region would be if we moved it by that much. */ - if (drag_info.move_threshold_passsed) { + if (drag_info.move_threshold_passed) { if ((int32_t)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { @@ -3507,7 +3548,7 @@ Editor::show_verbose_duration_cursor (jack_nframes_t start, jack_nframes_t end, /* XXX fix this to compute min/sec properly */ session->smpte_duration (end - start, smpte); secs = smpte.seconds + ((float) smpte.frames / session->smpte_frames_per_second); - snprintf (buf, sizeof (buf), "%02ld:%02ld:%.4f", smpte.hours, smpte.minutes, secs); + snprintf (buf, sizeof (buf), "%02" PRId32 ":%02" PRId32 ":%.4f", smpte.hours, smpte.minutes, secs); break; default: @@ -3629,7 +3670,6 @@ Editor::start_selection_op (ArdourCanvas::Item* item, GdkEvent* event, Selection switch (op) { case CreateSelection: - if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift)) { drag_info.copy = true; } else { @@ -3639,14 +3679,18 @@ Editor::start_selection_op (ArdourCanvas::Item* item, GdkEvent* event, Selection break; case SelectionStartTrim: - clicked_trackview->order_selection_trims (item, true); + if (clicked_trackview) { + clicked_trackview->order_selection_trims (item, true); + } start_grab (event, trimmer_cursor); start = selection->time[clicked_selection].start; drag_info.pointer_frame_offset = drag_info.grab_frame - start; break; case SelectionEndTrim: - clicked_trackview->order_selection_trims (item, false); + if (clicked_trackview) { + clicked_trackview->order_selection_trims (item, false); + } start_grab (event, trimmer_cursor); end = selection->time[clicked_selection].end; drag_info.pointer_frame_offset = drag_info.grab_frame - end; @@ -4239,7 +4283,6 @@ Editor::hide_marker (ArdourCanvas::Item* item, GdkEvent* event) void Editor::start_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event, RangeMarkerOp op) { - if (session == 0) { return; } @@ -4304,7 +4347,7 @@ Editor::drag_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event) } /* first drag: Either add to the selection - or create a new selection-> + or create a new selection. */ if (drag_info.first_move) { @@ -4371,12 +4414,39 @@ Editor::end_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event) break; } } else { - /* just a click, no pointer movement.*/ + /* just a click, no pointer movement. remember that context menu stuff was handled elsewhere */ if (Keyboard::no_modifier_keys_pressed (&event->button)) { - // nothing yet + jack_nframes_t start; + jack_nframes_t end; + start = session->locations()->first_mark_before (drag_info.grab_frame); + end = session->locations()->first_mark_after (drag_info.grab_frame); + + if (end == max_frames) { + end = session->current_end_frame (); + } + + if (start == 0) { + start = session->current_start_frame (); + } + + switch (mouse_mode) { + case MouseObject: + /* find the two markers on either side and then make the selection from it */ + cerr << "select between " << start << " .. " << end << endl; + select_all_within (start, end, 0.0f, FLT_MAX, Selection::Set); + break; + + case MouseRange: + /* find the two markers on either side of the click and make the range out of it */ + selection->set (0, start, end); + break; + + default: + break; + } } } diff --git a/gtk2_ardour/opts.cc b/gtk2_ardour/opts.cc index 4283756a71..2ea5805098 100644 --- a/gtk2_ardour/opts.cc +++ b/gtk2_ardour/opts.cc @@ -36,7 +36,7 @@ bool GTK_ARDOUR::just_version = false; bool GTK_ARDOUR::use_vst = true; bool GTK_ARDOUR::new_session = false; char* GTK_ARDOUR::curvetest_file = 0; -bool GTK_ARDOUR::try_hw_optimization = false; +bool GTK_ARDOUR::try_hw_optimization = true; using namespace GTK_ARDOUR; diff --git a/gtk2_ardour/selection.cc b/gtk2_ardour/selection.cc index 8424ff5378..3c1aea1ec8 100644 --- a/gtk2_ardour/selection.cc +++ b/gtk2_ardour/selection.cc @@ -199,18 +199,29 @@ Selection::toggle (AudioRegionView* r) { AudioRegionSelection::iterator i; - cerr << "about to toggle a regionview\n"; - if ((i = find (audio_regions.begin(), audio_regions.end(), r)) == audio_regions.end()) { audio_regions.add (r); - cerr << "\tadded\n"; } else { audio_regions.erase (i); - cerr << "\tremoved\n"; } RegionsChanged (); - cerr << "done\n"; +} + +void +Selection::toggle (vector<AudioRegionView*>& r) +{ + AudioRegionSelection::iterator i; + + for (vector<AudioRegionView*>::iterator x = r.begin(); x != r.end(); ++x) { + if ((i = find (audio_regions.begin(), audio_regions.end(), (*x))) == audio_regions.end()) { + audio_regions.add ((*x)); + } else { + audio_regions.erase (i); + } + } + + RegionsChanged (); } long @@ -633,8 +644,6 @@ Selection::add (list<Selectable*>& selectables) if (!autos.empty()) { add (autos); } - - cerr << "Selection @ " << this << " has " << points.size() << " points\n"; } void diff --git a/libs/ardour/ardour/audioregion.h b/libs/ardour/ardour/audioregion.h index a146a20417..f210fa595b 100644 --- a/libs/ardour/ardour/audioregion.h +++ b/libs/ardour/ardour/audioregion.h @@ -75,10 +75,11 @@ class AudioRegion : public Region AudioRegion (SourceList &, const XMLNode&); ~AudioRegion(); - bool region_list_equivalent (const AudioRegion&); - bool source_equivalent (const AudioRegion&); - bool equivalent (const AudioRegion&); - bool size_equivalent (const AudioRegion&); + bool region_list_equivalent (const AudioRegion&) const ; + bool source_equivalent (const AudioRegion&) const; + bool equivalent (const AudioRegion&) const; + bool size_equivalent (const AudioRegion&) const; + bool overlap_equivalent (const AudioRegion&) const; bool speed_mismatch (float) const; diff --git a/libs/ardour/ardour/configuration_vars.h b/libs/ardour/ardour/configuration_vars.h index 65ede9886b..85c7897026 100644 --- a/libs/ardour/ardour/configuration_vars.h +++ b/libs/ardour/ardour/configuration_vars.h @@ -42,12 +42,13 @@ CONFIG_VARIABLE(HeaderFormat, native_file_header_format, "native-file-header-fo CONFIG_VARIABLE(bool, use_tranzport, "use-tranzport", false) CONFIG_VARIABLE(uint32_t, osc_port, "osc-port", 3819) CONFIG_VARIABLE(bool, use_osc, "use-osc", true) +CONFIG_VARIABLE(bool, use_overlap_equivalency, "use-overlap-equivalency", true) CONFIG_VARIABLE(bool, meter_falloff_off, "meter-falloff-off", false) CONFIG_VARIABLE(bool, meter_falloff_slowest, "meter-falloff-slowest", false) CONFIG_VARIABLE(bool, meter_falloff_slower, "meter-falloff-slower", false) CONFIG_VARIABLE(bool, meter_falloff_slow, "meter-falloff-slow", false) CONFIG_VARIABLE(bool, meter_falloff_medium, "meter-falloff-medium", false) -CONFIG_VARIABLE(bool, meter_falloff_fast, "meter-falloff-fast", false) +CONFIG_VARIABLE(bool, meter_falloff_fast, "meter-falloff-fast", true) CONFIG_VARIABLE(bool, meter_falloff_faster, "meter-falloff-faster", false) CONFIG_VARIABLE(bool, meter_falloff_fastest, "meter-falloff-fastest", false) CONFIG_VARIABLE(bool, meter_hold_off, "meter-hold-off", false) diff --git a/libs/ardour/ardour/location.h b/libs/ardour/ardour/location.h index ee55adb600..bb744c95be 100644 --- a/libs/ardour/ardour/location.h +++ b/libs/ardour/ardour/location.h @@ -159,6 +159,9 @@ class Locations : public Stateful, public StateManager Location *first_location_before (jack_nframes_t); Location *first_location_after (jack_nframes_t); + jack_nframes_t first_mark_before (jack_nframes_t); + jack_nframes_t first_mark_after (jack_nframes_t); + sigc::signal<void,Location*> current_changed; sigc::signal<void> changed; sigc::signal<void,Location*> added; diff --git a/libs/ardour/audio_playlist.cc b/libs/ardour/audio_playlist.cc index 53aa173ffd..a0d43d5575 100644 --- a/libs/ardour/audio_playlist.cc +++ b/libs/ardour/audio_playlist.cc @@ -886,8 +886,14 @@ AudioPlaylist::get_equivalent_regions (const AudioRegion& other, vector<AudioReg AudioRegion* ar = dynamic_cast<AudioRegion*> (*i); - if (ar && ar->equivalent (other)) { - results.push_back (ar); + if (ar) { + if (Config->get_use_overlap_equivalency()) { + if (ar->overlap_equivalent (other)) { + results.push_back (ar); + } else if (ar->equivalent (other)) { + results.push_back (ar); + } + } } } } diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc index 95201ab6f7..eb8dfbc123 100644 --- a/libs/ardour/audioregion.cc +++ b/libs/ardour/audioregion.cc @@ -1139,15 +1139,15 @@ AudioRegion::master_source_names () } bool -AudioRegion::region_list_equivalent (const AudioRegion& other) +AudioRegion::region_list_equivalent (const AudioRegion& other) const { return size_equivalent (other) && source_equivalent (other) && _name == other._name; } bool -AudioRegion::source_equivalent (const AudioRegion& other) +AudioRegion::source_equivalent (const AudioRegion& other) const { - SourceList::iterator i; + SourceList::const_iterator i; SourceList::const_iterator io; for (i = sources.begin(), io = other.sources.begin(); i != sources.end() && io != other.sources.end(); ++i, ++io) { @@ -1166,7 +1166,13 @@ AudioRegion::source_equivalent (const AudioRegion& other) } bool -AudioRegion::equivalent (const AudioRegion& other) +AudioRegion::overlap_equivalent (const AudioRegion& other) const +{ + return coverage (other.first_frame(), other.last_frame()) != OverlapNone; +} + +bool +AudioRegion::equivalent (const AudioRegion& other) const { return _start == other._start && _position == other._position && @@ -1174,7 +1180,7 @@ AudioRegion::equivalent (const AudioRegion& other) } bool -AudioRegion::size_equivalent (const AudioRegion& other) +AudioRegion::size_equivalent (const AudioRegion& other) const { return _start == other._start && _length == other._length; diff --git a/libs/ardour/location.cc b/libs/ardour/location.cc index 87a27e5c3d..7d479637e3 100644 --- a/libs/ardour/location.cc +++ b/libs/ardour/location.cc @@ -656,6 +656,80 @@ Locations::first_location_after (jack_nframes_t frame) return 0; } +jack_nframes_t +Locations::first_mark_before (jack_nframes_t frame) +{ + LocationList locs; + + { + LockMonitor lm (lock, __LINE__, __FILE__); + locs = locations; + } + + LocationStartLaterComparison cmp; + locs.sort (cmp); + + /* locs is now sorted latest..earliest */ + + for (LocationList::iterator i = locs.begin(); i != locs.end(); ++i) { + if (!(*i)->is_hidden()) { + if ((*i)->is_mark()) { + /* MARK: start == end */ + if ((*i)->start() < frame) { + return (*i)->start(); + } + } else { + /* RANGE: start != end, compare start and end */ + if ((*i)->end() < frame) { + return (*i)->end(); + } + if ((*i)->start () < frame) { + return (*i)->start(); + } + } + } + } + + return 0; +} + +jack_nframes_t +Locations::first_mark_after (jack_nframes_t frame) +{ + LocationList locs; + + { + LockMonitor lm (lock, __LINE__, __FILE__); + locs = locations; + } + + LocationStartEarlierComparison cmp; + locs.sort (cmp); + + /* locs is now sorted earliest..latest */ + + for (LocationList::iterator i = locs.begin(); i != locs.end(); ++i) { + if (!(*i)->is_hidden()) { + if ((*i)->is_mark()) { + /* MARK, start == end so just compare start */ + if ((*i)->start() > frame) { + return (*i)->start(); + } + } else { + /* RANGE, start != end, compare start and end */ + if ((*i)->start() > frame ) { + return (*i)->start (); + } + if ((*i)->end() > frame) { + return (*i)->end (); + } + } + } + } + + return max_frames; +} + Location* Locations::end_location () const { diff --git a/libs/ardour/utils.cc b/libs/ardour/utils.cc index 8e9a36de59..15d0c6be81 100644 --- a/libs/ardour/utils.cc +++ b/libs/ardour/utils.cc @@ -175,10 +175,13 @@ tokenize_fullpath (string fullpath, string& path, string& name) } int -touch_file(string path) +touch_file (string path) { - FILE* file = fopen(path.c_str(), "a"); - fclose(file); + int fd = open (path.c_str(), O_RDONLY|O_CREAT); + if (fd >= 0) { + close (fd); + return 0; + } return 1; } diff --git a/libs/pbd3/SConscript b/libs/pbd3/SConscript index 4d1b2a8681..65264adcee 100644 --- a/libs/pbd3/SConscript +++ b/libs/pbd3/SConscript @@ -60,7 +60,7 @@ if env['NLS']: env.Alias('install', env.Install(os.path.join(install_prefix, 'lib/ardour2'), libpbd3)) env.Alias('tarball', env.Distribute (env['DISTTREE'], - [ 'SConscript', 'i18n.h' ] + + [ 'SConscript', 'i18n.h', 'gettext.h', 'pbd/abstract_ui.cc' ] + pbd3_files + glob.glob('po/*.po') + glob.glob('pbd/*.h'))) diff --git a/libs/pbd3/undo.cc b/libs/pbd3/undo.cc index 0af1cc2e7a..f2f11b1c5c 100644 --- a/libs/pbd3/undo.cc +++ b/libs/pbd3/undo.cc @@ -77,6 +77,7 @@ UndoCommand::clear () void UndoCommand::undo () { + cerr << "Undo " << _name << endl; for (list<UndoAction>::reverse_iterator i = undo_actions.rbegin(); i != undo_actions.rend(); ++i) { (*i)(); } @@ -85,6 +86,7 @@ UndoCommand::undo () void UndoCommand::redo () { + cerr << "Redo " << _name << endl; for (list<UndoAction>::iterator i = redo_actions.begin(); i != redo_actions.end(); ++i) { (*i)(); } diff --git a/libs/surfaces/control_protocol/SConscript b/libs/surfaces/control_protocol/SConscript index 904e6b3956..eeac7bed8b 100644 --- a/libs/surfaces/control_protocol/SConscript +++ b/libs/surfaces/control_protocol/SConscript @@ -49,6 +49,6 @@ if env['NLS']: env.Alias('install', env.Install(os.path.join(install_prefix, 'lib/ardour2'), libardour_cp)) env.Alias('tarball', env.Distribute (env['DISTTREE'], - [ 'SConscript', 'i18n.h', 'gettext.h' ] + + [ 'SConscript' ] + cp_files + glob.glob('po/*.po') + glob.glob('*.h'))) diff --git a/libs/surfaces/generic_midi/SConscript b/libs/surfaces/generic_midi/SConscript index 9edb76327a..97998f864f 100644 --- a/libs/surfaces/generic_midi/SConscript +++ b/libs/surfaces/generic_midi/SConscript @@ -50,6 +50,6 @@ if env['NLS']: env.Alias('install', env.Install(os.path.join(install_prefix, 'lib/ardour2/surfaces'), libardour_genericmidi)) env.Alias('tarball', env.Distribute (env['DISTTREE'], - [ 'SConscript', 'i18n.h', 'gettext.h' ] + + [ 'SConscript' ] + genericmidi_files + glob.glob('po/*.po') + glob.glob('*.h'))) diff --git a/libs/surfaces/tranzport/SConscript b/libs/surfaces/tranzport/SConscript index 98ecf09d41..55dae57cc1 100644 --- a/libs/surfaces/tranzport/SConscript +++ b/libs/surfaces/tranzport/SConscript @@ -50,6 +50,6 @@ if env['NLS']: env.Alias('install', env.Install(os.path.join(install_prefix, 'lib/ardour2/surfaces'), libardour_tranzport)) env.Alias('tarball', env.Distribute (env['DISTTREE'], - [ 'SConscript', 'i18n.h', 'gettext.h' ] + + [ 'SConscript' ] + tranzport_files + glob.glob('po/*.po') + glob.glob('*.h'))) |