diff --git a/gtk2_ardour/ardour.bindings.in b/gtk2_ardour/ardour.bindings.in index 368d7294d5..2adcd116a3 100644 --- a/gtk2_ardour/ardour.bindings.in +++ b/gtk2_ardour/ardour.bindings.in @@ -322,3 +322,12 @@ (gtk_accel_path "/Editor/set-fade-out-length" "backslash") (gtk_accel_path "/Editor/trim-from-start" "braceleft") (gtk_accel_path "/Editor/trim-to-end" "braceright") +(gtk_accel_path "/Editor/goto-mark-1" "KP_1") +(gtk_accel_path "/Editor/goto-mark-2" "KP_2") +(gtk_accel_path "/Editor/goto-mark-3" "KP_3") +(gtk_accel_path "/Editor/goto-mark-4" "KP_4") +(gtk_accel_path "/Editor/goto-mark-5" "KP_5") +(gtk_accel_path "/Editor/goto-mark-6" "KP_6") +(gtk_accel_path "/Editor/goto-mark-7" "KP_7") +(gtk_accel_path "/Editor/goto-mark-8" "KP_8") +(gtk_accel_path "/Editor/goto-mark-9" "KP_9") diff --git a/gtk2_ardour/ardour.menus b/gtk2_ardour/ardour.menus index 9a98659d65..07d902321e 100644 --- a/gtk2_ardour/ardour.menus +++ b/gtk2_ardour/ardour.menus @@ -59,6 +59,16 @@ + + + + + + + + + + diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index e8eebe5060..6b8432f324 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -4167,6 +4167,48 @@ Editor::get_regions_at (nframes64_t where, const TrackSelection& ts) const return rs; } + +RegionSelection +Editor::get_regions_after (nframes64_t where, const TrackSelection& ts) const +{ + RegionSelection rs; + const TrackSelection* tracks; + + if (ts.empty()) { + tracks = &track_views; + } else { + tracks = &ts; + } + + for (TrackSelection::const_iterator t = tracks->begin(); t != tracks->end(); ++t) { + + AudioTimeAxisView* atv = dynamic_cast(*t); + + if (atv) { + boost::shared_ptr ds; + boost::shared_ptr pl; + + if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) { + + Playlist::RegionList* regions = pl->regions_touched ((nframes_t) floor ( (double)where * ds->speed()), max_frames); + + for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) { + + RegionView* rv = atv->audio_view()->find_view (*i); + + if (rv) { + rs.push_back (rv); + } + } + + delete regions; + } + } + } + + return rs; +} + RegionSelection& Editor::get_regions_for_action () { diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 1c17ad4220..8588dcd2ef 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -1145,6 +1145,7 @@ class Editor : public PublicEditor void set_fade_out_active (bool); std::set > motion_frozen_playlists; + RegionSelection pre_drag_region_selection; void region_drag_motion_callback (ArdourCanvas::Item*, GdkEvent*); void region_drag_finished_callback (ArdourCanvas::Item*, GdkEvent*); @@ -1941,6 +1942,7 @@ class Editor : public PublicEditor bool get_edit_op_range (nframes64_t& start, nframes64_t& end) const; RegionSelection get_regions_at (nframes64_t where, const TrackSelection& ts) const; + RegionSelection get_regions_after (nframes64_t where, const TrackSelection& ts) const; RegionSelection tmp_regions; diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc index 36dba0c43f..02ad04f377 100644 --- a/gtk2_ardour/editor_actions.cc +++ b/gtk2_ardour/editor_actions.cc @@ -150,6 +150,25 @@ Editor::register_actions () act = ActionManager::register_action (editor_actions, "select-all-in-loop-range", _("Select All in Loop Range"), mem_fun(*this, &Editor::select_all_selectables_using_loop)); ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "goto-mark-1", _("Locate to Mark 1"), bind (mem_fun (*this, &Editor::goto_nth_marker), 0)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "goto-mark-2", _("Locate to Mark 2"), bind (mem_fun (*this, &Editor::goto_nth_marker), 1)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "goto-mark-3", _("Locate to Mark 3"), bind (mem_fun (*this, &Editor::goto_nth_marker), 2)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "goto-mark-4", _("Locate to Mark 4"), bind (mem_fun (*this, &Editor::goto_nth_marker), 3)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "goto-mark-5", _("Locate to Mark 5"), bind (mem_fun (*this, &Editor::goto_nth_marker), 4)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "goto-mark-6", _("Locate to Mark 6"), bind (mem_fun (*this, &Editor::goto_nth_marker), 5)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "goto-mark-7", _("Locate to Mark 7"), bind (mem_fun (*this, &Editor::goto_nth_marker), 6)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "goto-mark-8", _("Locate to Mark 8"), bind (mem_fun (*this, &Editor::goto_nth_marker), 7)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "goto-mark-9", _("Locate to Mark 9"), bind (mem_fun (*this, &Editor::goto_nth_marker), 8)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "jump-forward-to-mark", _("Jump Forward to Mark"), mem_fun(*this, &Editor::jump_forward_to_mark)); ActionManager::session_sensitive_actions.push_back (act); act = ActionManager::register_action (editor_actions, "jump-backward-to-mark", _("Jump Backward to Mark"), mem_fun(*this, &Editor::jump_backward_to_mark)); diff --git a/gtk2_ardour/editor_markers.cc b/gtk2_ardour/editor_markers.cc index 294aaa1746..6876e4f59a 100644 --- a/gtk2_ardour/editor_markers.cc +++ b/gtk2_ardour/editor_markers.cc @@ -1109,22 +1109,32 @@ Editor::selected_marker_moved (Location* loc) edit_point_clock.set (loc->start()); } +struct SortLocationsByPosition { + bool operator() (Location* a, Location* b) { + return a->start() < b->start(); + } +}; + void Editor::goto_nth_marker (int n) { -#if 0 if (!session) { return; } const Locations::LocationList& l (session->locations()->list()); - LocationList ordered; + Locations::LocationList ordered; ordered = l; + + SortLocationsByPosition cmp; + ordered.sort (cmp); - for (Locations::LocationList::iterator i = locations.begin(); n > 0 && i != ordered.end(); ++i) { - if (loc->is_mark() && !loc->is_hidden() && !loc->is_start()) { - session->request_locate ((*i)->start(), session->transport_rolling()); - break; + for (Locations::LocationList::iterator i = ordered.begin(); n >= 0 && i != ordered.end(); ++i) { + if ((*i)->is_mark() && !(*i)->is_hidden() && !(*i)->is_start()) { + if (n == 0) { + session->request_locate ((*i)->start(), session->transport_rolling()); + break; + } + --n; } } -#endif } diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index 10b170d46a..3d853d0cef 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -2948,6 +2948,14 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) vector height_list(512) ; vector::iterator j; + if (drag_info.first_move && drag_info.move_threshold_passed && pre_drag_region_selection.empty()) { + pre_drag_region_selection = selection->regions; + if (Config->get_edit_mode() == Splice) { + RegionSelection all_after = get_regions_after (clicked_regionview->region()->position(), selection->tracks); + selection->set (all_after); + } + } + if (drag_info.copy && drag_info.move_threshold_passed && drag_info.want_move_threshold) { drag_info.want_move_threshold = false; // don't copy again @@ -3439,6 +3447,11 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event region_drag_motion_callback (item, event); + if (Config->get_edit_mode() == Splice && !pre_drag_region_selection.empty()) { + selection->set (pre_drag_region_selection); + pre_drag_region_selection.clear (); + } + if (drag_info.brushing) { /* all changes were made during motion event handlers */ diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h index f09afc2f54..fab29b0c20 100644 --- a/libs/ardour/ardour/playlist.h +++ b/libs/ardour/ardour/playlist.h @@ -231,12 +231,12 @@ class Playlist : public PBD::StatefulDestructible, public boost::enable_shared_f void sort_regions (); - void possibly_splice (nframes_t at, nframes64_t distance); - void possibly_splice_unlocked(nframes_t at, nframes64_t distance); - void core_splice (nframes_t at, nframes64_t distance); - void splice_locked (nframes_t at, nframes64_t distance); - void splice_unlocked (nframes_t at, nframes64_t distance); + void possibly_splice (nframes_t at, nframes64_t distance, boost::shared_ptr exclude = boost::shared_ptr()); + void possibly_splice_unlocked(nframes_t at, nframes64_t distance, boost::shared_ptr exclude = boost::shared_ptr()); + void core_splice (nframes_t at, nframes64_t distance, boost::shared_ptr exclude); + void splice_locked (nframes_t at, nframes64_t distance, boost::shared_ptr exclude); + void splice_unlocked (nframes_t at, nframes64_t distance, boost::shared_ptr exclude); virtual void finalize_split_region (boost::shared_ptr original, boost::shared_ptr left, boost::shared_ptr right) {} diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h index 7c99cf9d1d..ca8c5855a9 100644 --- a/libs/ardour/ardour/region.h +++ b/libs/ardour/ardour/region.h @@ -90,6 +90,11 @@ class Region : public PBD::StatefulDestructible, public boost::enable_shared_fro nframes_t length() const { return _length; } layer_t layer () const { return _layer; } + /* these two are valid ONLY during a StateChanged signal handler */ + + nframes_t last_position() const { return _last_position; } + nframes_t last_length() const { return _last_length; } + nframes64_t ancestral_start () const { return _ancestral_start; } nframes64_t ancestral_length () const { return _ancestral_length; } float stretch() const { return _stretch; } @@ -142,7 +147,7 @@ class Region : public PBD::StatefulDestructible, public boost::enable_shared_fro void set_position (nframes_t, void *src); void set_position_on_top (nframes_t, void *src); void special_set_position (nframes_t); - void nudge_position (long, void *src); + void nudge_position (nframes64_t, void *src); bool at_natural_position () const; void move_to_natural_position (void *src); @@ -213,7 +218,9 @@ class Region : public PBD::StatefulDestructible, public boost::enable_shared_fro nframes_t _start; nframes_t _length; + nframes_t _last_length; nframes_t _position; + nframes_t _last_position; Flag _flags; nframes_t _sync_position; layer_t _layer; diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc index f53283a98e..afcbdc93be 100644 --- a/libs/ardour/playlist.cc +++ b/libs/ardour/playlist.cc @@ -487,7 +487,7 @@ Playlist::add_region (boost::shared_ptr region, nframes_t position, floa } - possibly_splice_unlocked (position, (pos + length) - position); + possibly_splice_unlocked (position, (pos + length) - position, boost::shared_ptr()); } void @@ -524,6 +524,8 @@ Playlist::add_region_internal (boost::shared_ptr region, nframes_t posit regions.insert (upper_bound (regions.begin(), regions.end(), region, cmp), region); all_regions.insert (region); + possibly_splice_unlocked (position, region->length(), region); + if (!holding_state () && !in_set_state) { /* layers get assigned from XML state */ relayer (); @@ -564,7 +566,6 @@ void Playlist::remove_region (boost::shared_ptr region) { RegionLock rlock (this); - nframes_t pos = region->position(); remove_region_internal (region); } @@ -1048,7 +1049,7 @@ Playlist::split_region (boost::shared_ptr region, nframes_t playlist_pos } void -Playlist::possibly_splice (nframes_t at, nframes64_t distance) +Playlist::possibly_splice (nframes_t at, nframes64_t distance, boost::shared_ptr exclude) { if (_splicing || in_set_state) { /* don't respond to splicing moves or state setting */ @@ -1056,12 +1057,12 @@ Playlist::possibly_splice (nframes_t at, nframes64_t distance) } if (_edit_mode == Splice) { - splice_locked (at, distance); + splice_locked (at, distance, exclude); } } void -Playlist::possibly_splice_unlocked (nframes_t at, nframes64_t distance) +Playlist::possibly_splice_unlocked (nframes_t at, nframes64_t distance, boost::shared_ptr exclude) { if (_splicing || in_set_state) { /* don't respond to splicing moves or state setting */ @@ -1069,38 +1070,36 @@ Playlist::possibly_splice_unlocked (nframes_t at, nframes64_t distance) } if (_edit_mode == Splice) { - splice_unlocked (at, distance); + splice_unlocked (at, distance, exclude); } } void -Playlist::splice_locked (nframes_t at, nframes64_t distance) +Playlist::splice_locked (nframes_t at, nframes64_t distance, boost::shared_ptr exclude) { { RegionLock rl (this); - core_splice (at, distance); + core_splice (at, distance, exclude); } - - notify_length_changed (); } void -Playlist::splice_unlocked (nframes_t at, nframes64_t distance) +Playlist::splice_unlocked (nframes_t at, nframes64_t distance, boost::shared_ptr exclude) { - core_splice (at, distance); - notify_length_changed (); + core_splice (at, distance, exclude); } void -Playlist::core_splice (nframes_t at, nframes64_t distance) +Playlist::core_splice (nframes_t at, nframes64_t distance, boost::shared_ptr exclude) { - stacktrace (cerr, 12); - _splicing = true; - cerr << "core splice, move everything >= " << at << " by " << distance << endl; - for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) { + + if (exclude && (*i) == exclude) { + continue; + } + if ((*i)->position() >= at) { nframes64_t new_pos = (*i)->position() + distance; if (new_pos < 0) { @@ -1109,13 +1108,13 @@ Playlist::core_splice (nframes_t at, nframes64_t distance) new_pos = max_frames - (*i)->length(); } - cerr << "\tmove " << (*i)->name() << " to " << new_pos << endl; (*i)->set_position (new_pos, this); } } - _splicing = false; + + notify_length_changed (); } void @@ -1144,10 +1143,25 @@ Playlist::region_bounds_changed (Change what_changed, boost::shared_ptr regions.erase (i); regions.insert (upper_bound (regions.begin(), regions.end(), region, cmp), region); - } if (what_changed & Change (ARDOUR::PositionChanged|ARDOUR::LengthChanged)) { + + nframes64_t delta = 0; + + if (what_changed & ARDOUR::PositionChanged) { + delta = (nframes64_t) region->position() - (nframes64_t) region->last_position(); + } + + if (what_changed & ARDOUR::LengthChanged) { + delta += (nframes64_t) region->length() - (nframes64_t) region->last_length(); + + } + + if (delta) { + possibly_splice (region->last_position(), delta, region); + } + if (holding_state ()) { pending_bounds.push_back (region); } else { @@ -1155,9 +1169,7 @@ Playlist::region_bounds_changed (Change what_changed, boost::shared_ptr /* it moved or changed length, so change the timestamp */ timestamp_layer_op (region); } - - // XXX NEED TO SPLICE HERE ... HOW TO GET DISTANCE ? - + notify_length_changed (); relayer (); check_dependents (region, false); diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc index cd91772a3b..7956f65bd9 100644 --- a/libs/ardour/region.cc +++ b/libs/ardour/region.cc @@ -61,9 +61,11 @@ Region::Region (nframes_t start, nframes_t length, const string& name, layer_t l _start = start; _sync_position = _start; _length = length; + _last_length = length; _ancestral_start = start; _ancestral_length = length; _stretch = 1.0; + _last_position = 0; _position = 0; _layer = layer; _read_data_count = 0; @@ -86,10 +88,12 @@ Region::Region (boost::shared_ptr other, nframes_t offset, nframes _sync_position = _start; } _length = length; + _last_length = length; _ancestral_start = other->_ancestral_start + offset; _ancestral_length = length; _stretch = 1.0; _name = name; + _last_position = 0; _position = 0; _layer = layer; _flags = Flag (flags & ~(Locked|WholeFile|Hidden)); @@ -117,10 +121,12 @@ Region::Region (boost::shared_ptr other) _start = other->_start; _sync_position = other->_sync_position; _length = other->_length; + _last_length = other->_length; _ancestral_start = _start; _ancestral_length = _length; _stretch = 1.0; _name = other->_name; + _last_position = other->_position; _position = other->_position; _layer = other->_layer; _flags = Flag (other->_flags & ~Locked); @@ -135,7 +141,9 @@ Region::Region (const XMLNode& node) _start = 0; _sync_position = _start; _length = 0; + _last_length = 0; _name = X_("error: XML did not reset this"); + _last_position = 0; _position = 0; _layer = 0; _flags = Flag (0); @@ -187,6 +195,8 @@ Region::set_length (nframes_t len, void *src) return; } + + _last_length = _length; _length = len; _flags = Region::Flag (_flags & ~WholeFile); @@ -265,6 +275,7 @@ Region::special_set_position (nframes_t pos) a way to store its "natural" or "captured" position. */ + _position = _position; _position = pos; } @@ -276,6 +287,7 @@ Region::set_position (nframes_t pos, void *src) } if (_position != pos) { + _last_position = _position; _position = pos; /* check that the new _position wouldn't make the current @@ -285,6 +297,7 @@ Region::set_position (nframes_t pos, void *src) */ if (max_frames - _length < _position) { + _last_length = _length; _length = max_frames - _position; } } @@ -304,6 +317,7 @@ Region::set_position_on_top (nframes_t pos, void *src) } if (_position != pos) { + _last_position = _position; _position = pos; } @@ -321,7 +335,7 @@ Region::set_position_on_top (nframes_t pos, void *src) } void -Region::nudge_position (long n, void *src) +Region::nudge_position (nframes64_t n, void *src) { if (_flags & Locked) { return; @@ -331,6 +345,8 @@ Region::nudge_position (long n, void *src) return; } + _last_position = _position; + if (n > 0) { if (_position > max_frames - n) { _position = max_frames; @@ -545,10 +561,16 @@ Region::trim_to_internal (nframes_t position, nframes_t length, void *src) what_changed = Change (what_changed|StartChanged); } if (_length != length) { + if (!_frozen) { + _last_length = _length; + } _length = length; what_changed = Change (what_changed|LengthChanged); } if (_position != position) { + if (!_frozen) { + _last_position = _position; + } _position = position; what_changed = Change (what_changed|PositionChanged); } @@ -783,7 +805,6 @@ Region::state (bool full_state) fe = X_("id"); break; default: /* should be unreachable but makes g++ happy */ - cerr << "Odd region property found\n"; fe = X_("nothing"); break; } @@ -838,9 +859,11 @@ Region::set_live_state (const XMLNode& node, Change& what_changed, bool send) sscanf (prop->value().c_str(), "%" PRIu32, &val); if (val != _length) { what_changed = Change (what_changed|LengthChanged); + _last_length = _length; _length = val; } } else { + _last_length = _length; _length = 1; } @@ -848,9 +871,11 @@ Region::set_live_state (const XMLNode& node, Change& what_changed, bool send) sscanf (prop->value().c_str(), "%" PRIu32, &val); if (val != _position) { what_changed = Change (what_changed|PositionChanged); + _last_position = _position; _position = val; } } else { + _last_position = _position; _position = 0; } @@ -949,6 +974,8 @@ void Region::freeze () { _frozen++; + _last_length = _length; + _last_position = _position; } void