diff options
-rw-r--r-- | gtk2_ardour/add_route_dialog.cc | 3 | ||||
-rw-r--r-- | gtk2_ardour/ardour.menus.in | 2 | ||||
-rw-r--r-- | gtk2_ardour/audio_streamview.cc | 3 | ||||
-rw-r--r-- | gtk2_ardour/audio_time_axis.cc | 9 | ||||
-rw-r--r-- | gtk2_ardour/editor.h | 8 | ||||
-rw-r--r-- | gtk2_ardour/editor_actions.cc | 7 | ||||
-rw-r--r-- | gtk2_ardour/editor_mouse.cc | 99 | ||||
-rw-r--r-- | gtk2_ardour/editor_ops.cc | 165 | ||||
-rw-r--r-- | gtk2_ardour/route_time_axis.cc | 41 | ||||
-rw-r--r-- | gtk2_ardour/route_time_axis.h | 3 | ||||
-rw-r--r-- | gtk2_ardour/streamview.cc | 2 | ||||
-rw-r--r-- | libs/ardour/ardour/audio_diskstream.h | 1 | ||||
-rw-r--r-- | libs/ardour/ardour/configuration_vars.h | 1 | ||||
-rw-r--r-- | libs/ardour/ardour/diskstream.h | 5 | ||||
-rw-r--r-- | libs/ardour/ardour/playlist.h | 7 | ||||
-rw-r--r-- | libs/ardour/ardour/types.h | 1 | ||||
-rw-r--r-- | libs/ardour/audio_diskstream.cc | 17 | ||||
-rw-r--r-- | libs/ardour/audio_playlist.cc | 2 | ||||
-rw-r--r-- | libs/ardour/audio_track.cc | 8 | ||||
-rw-r--r-- | libs/ardour/configuration.cc | 3 | ||||
-rw-r--r-- | libs/ardour/enums.cc | 1 | ||||
-rw-r--r-- | libs/ardour/midi_playlist.cc | 4 | ||||
-rw-r--r-- | libs/ardour/playlist.cc | 57 | ||||
-rw-r--r-- | wscript | 2 |
24 files changed, 353 insertions, 98 deletions
diff --git a/gtk2_ardour/add_route_dialog.cc b/gtk2_ardour/add_route_dialog.cc index d5856fa4e6..9baa8f3cd2 100644 --- a/gtk2_ardour/add_route_dialog.cc +++ b/gtk2_ardour/add_route_dialog.cc @@ -56,6 +56,7 @@ static const char* channel_setup_names[] = { static const char* track_mode_names[] = { N_("Normal"), + N_("Non Layered"), N_("Tape"), 0 }; @@ -273,6 +274,8 @@ AddRouteDialog::mode () Glib::ustring str = track_mode_combo.get_active_text(); if (str == _("Normal")) { return ARDOUR::Normal; + } else if (str == _("Non Layered")){ + return ARDOUR::NonLayered; } else if (str == _("Tape")) { return ARDOUR::Destructive; } else { diff --git a/gtk2_ardour/ardour.menus.in b/gtk2_ardour/ardour.menus.in index eb0968da4a..c754590102 100644 --- a/gtk2_ardour/ardour.menus.in +++ b/gtk2_ardour/ardour.menus.in @@ -185,6 +185,8 @@ <menuitem action='crop'/> <menuitem action='trim-region-to-loop'/> <menuitem action='trim-region-to-punch'/> + <menuitem action='trim-to-previous-region'/> + <menuitem action='trim-to-next-region'/> </menu> <menu action="FadeMenu"> <menuitem action='set-fade-in-length'/> diff --git a/gtk2_ardour/audio_streamview.cc b/gtk2_ardour/audio_streamview.cc index ed56651e5f..8dcee5aaab 100644 --- a/gtk2_ardour/audio_streamview.cc +++ b/gtk2_ardour/audio_streamview.cc @@ -134,6 +134,8 @@ AudioStreamView::add_region_view_internal (boost::shared_ptr<Region> r, bool wai } switch (_trackview.audio_track()->mode()) { + + case NonLayered: case Normal: if (recording) { region_view = new AudioRegionView (canvas_group, _trackview, region, @@ -519,6 +521,7 @@ AudioStreamView::setup_rec_box () switch (_trackview.audio_track()->mode()) { case Normal: + case NonLayered: xend = xstart; fill_color = ARDOUR_UI::config()->canvasvar_RecordingRect.get(); break; diff --git a/gtk2_ardour/audio_time_axis.cc b/gtk2_ardour/audio_time_axis.cc index 609d7b7d6c..b774182a88 100644 --- a/gtk2_ardour/audio_time_axis.cc +++ b/gtk2_ardour/audio_time_axis.cc @@ -245,9 +245,15 @@ AudioTimeAxisView::build_mode_menu() mode_menu->set_name ("ArdourContextMenu"); RadioMenuItem::Group mode_group; + items.push_back (RadioMenuElem (mode_group, _("Normal"), bind (mem_fun (*this, &AudioTimeAxisView::set_track_mode), ARDOUR::Normal))); normal_track_mode_item = dynamic_cast<RadioMenuItem*>(&items.back()); + + items.push_back (RadioMenuElem (mode_group, _("Non Overlapping"), + bind (mem_fun (*this, &AudioTimeAxisView::set_track_mode), ARDOUR::NonLayered))); + non_layered_track_mode_item = dynamic_cast<RadioMenuItem*>(&items.back()); + items.push_back (RadioMenuElem (mode_group, _("Tape"), bind (mem_fun (*this, &AudioTimeAxisView::set_track_mode), ARDOUR::Destructive))); destructive_track_mode_item = dynamic_cast<RadioMenuItem*>(&items.back()); @@ -256,6 +262,9 @@ AudioTimeAxisView::build_mode_menu() case ARDOUR::Destructive: destructive_track_mode_item->set_active (); break; + case ARDOUR::NonLayered: + non_layered_track_mode_item->set_active (); + break; case ARDOUR::Normal: normal_track_mode_item->set_active (); break; diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 1c04c76504..82f63792fc 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -1997,8 +1997,8 @@ public: void point_trim (GdkEvent*); void trim_motion_callback (ArdourCanvas::Item*, GdkEvent*); void single_contents_trim (RegionView&, nframes64_t, bool, bool, bool); - void single_start_trim (RegionView&, nframes64_t, bool, bool); - void single_end_trim (RegionView&, nframes64_t, bool, bool); + void single_start_trim (RegionView&, nframes64_t, bool, bool, bool); + void single_end_trim (RegionView&, nframes64_t, bool, bool, bool); void trim_finished_callback (ArdourCanvas::Item*, GdkEvent*); void thaw_region_after_trim (RegionView& rv); @@ -2013,6 +2013,10 @@ public: void trim_region_to_punch (); void trim_region_to_location (const ARDOUR::Location&, const char* cmd); + void trim_to_region(bool forward); + void trim_region_to_previous_region_end(); + void trim_region_to_next_region_start(); + bool show_gain_after_trim; /* Drag-n-Drop */ diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc index 9606540b6e..f1c4e4b184 100644 --- a/gtk2_ardour/editor_actions.cc +++ b/gtk2_ardour/editor_actions.cc @@ -386,6 +386,13 @@ Editor::register_actions () ActionManager::session_sensitive_actions.push_back (act); ActionManager::region_selection_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "trim-to-previous-region", _("Trim to Previous"), mem_fun(*this, &Editor::trim_region_to_previous_region_end)); + ActionManager::session_sensitive_actions.push_back (act); + ActionManager::region_selection_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "trim-to-next-region", _("Trim to Next"), mem_fun(*this, &Editor::trim_region_to_next_region_start)); + ActionManager::session_sensitive_actions.push_back (act); + ActionManager::region_selection_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "set-loop-from-edit-range", _("Set Loop from Edit Range"), bind (mem_fun(*this, &Editor::set_loop_from_edit_range), false)); ActionManager::session_sensitive_actions.push_back (act); act = ActionManager::register_action (editor_actions, "set-loop-from-region", _("Set Loop from Region"), bind (mem_fun(*this, &Editor::set_loop_from_region), false)); diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index 7db90c1ac7..6cc92a2f74 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -4340,6 +4340,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event if (changed_tracks || drag_info.copy) { boost::shared_ptr<Playlist> to_playlist = dest_rtv->playlist(); + if (!to_playlist) { ++i; continue; @@ -4350,6 +4351,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event sigc::connection c = dest_rtv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view)); insert_result = modified_playlists.insert (to_playlist); + if (insert_result.second) { session->add_command (new MementoCommand<Playlist>(*to_playlist, &to_playlist->get_state(), 0)); } @@ -4380,11 +4382,13 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event boost::shared_ptr<Playlist> playlist = dest_rtv->playlist(); insert_result = modified_playlists.insert (playlist); + if (insert_result.second) { session->add_command (new MementoCommand<Playlist>(*playlist, &playlist->get_state(), 0)); } /* freeze to avoid lots of relayering in the case of a multi-region drag */ frozen_insert_result = frozen_playlists.insert(playlist); + if (frozen_insert_result.second) { playlist->freeze(); } @@ -4416,6 +4420,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event /* remove the region from the old playlist */ insert_result = modified_playlists.insert (from_playlist); + if (insert_result.second) { session->add_command (new MementoCommand<Playlist>(*from_playlist, &from_playlist->get_state(), 0)); } @@ -4478,13 +4483,13 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event for (set<boost::shared_ptr<Playlist> >::iterator p = modified_playlists.begin(); p != modified_playlists.end(); ++p) { session->add_command (new MementoCommand<Playlist>(*(*p), 0, &(*p)->get_state())); } + commit_reversible_command (); } for (vector<RegionView*>::iterator x = copies.begin(); x != copies.end(); ++x) { delete *x; } - } void @@ -4807,6 +4812,7 @@ Editor::cancel_selection () for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { (*i)->hide_selection (); } + selection->clear (); clicked_selection = 0; } @@ -5075,6 +5081,7 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) { RegionView* rv = clicked_regionview; nframes64_t frame_delta = 0; + bool left_direction; bool obey_snap = !Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier()); @@ -5129,11 +5136,14 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) (*i)->region()->freeze (); AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i); - if (arv) + + if (arv){ arv->temporarily_hide_envelope (); + } boost::shared_ptr<Playlist> pl = (*i)->region()->playlist(); insert_result = motion_frozen_playlists.insert (pl); + if (insert_result.second) { session->add_command(new MementoCommand<Playlist>(*pl, &pl->get_state(), 0)); pl->freeze(); @@ -5147,13 +5157,20 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) frame_delta = (drag_info.current_pointer_frame - drag_info.last_pointer_frame); } + bool non_overlap_trim = false; + + if (Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier)) { + non_overlap_trim = true; + } + switch (trim_op) { case StartTrim: if ((left_direction == false) && (drag_info.current_pointer_frame <= rv->region()->first_frame()/speed)) { break; } else { + for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) { - single_start_trim (**i, frame_delta, left_direction, obey_snap); + single_start_trim (**i, frame_delta, left_direction, obey_snap, non_overlap_trim); } break; } @@ -5162,8 +5179,9 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) if ((left_direction == true) && (drag_info.current_pointer_frame > (nframes64_t) (rv->region()->last_frame()/speed))) { break; } else { + for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) { - single_end_trim (**i, frame_delta, left_direction, obey_snap); + single_end_trim (**i, frame_delta, left_direction, obey_snap, non_overlap_trim); } break; } @@ -5242,7 +5260,7 @@ Editor::single_contents_trim (RegionView& rv, nframes64_t frame_delta, bool left } void -Editor::single_start_trim (RegionView& rv, nframes64_t frame_delta, bool left_direction, bool obey_snap) +Editor::single_start_trim (RegionView& rv, nframes64_t frame_delta, bool left_direction, bool obey_snap, bool no_overlap) { boost::shared_ptr<Region> region (rv.region()); @@ -5269,14 +5287,37 @@ Editor::single_start_trim (RegionView& rv, nframes64_t frame_delta, bool left_di if (obey_snap) { snap_to (new_bound, (left_direction ? 0 : 1)); } + + nframes64_t pre_trim_first_frame = region->first_frame(); region->trim_front ((nframes64_t) (new_bound * speed), this); + + if (no_overlap) { + //Get the next region on the left of this region and shrink/expand it. + boost::shared_ptr<Playlist> playlist (region->playlist()); + boost::shared_ptr<Region> region_left = playlist->find_next_region (pre_trim_first_frame, End, 0); + + bool regions_touching = false; + + if (region_left != 0 && (pre_trim_first_frame == region_left->last_frame() + 1)){ + regions_touching = true; + } + + //Only trim region on the left if the first frame has gone beyond the left region's last frame. + if (region_left != 0 && + (region_left->last_frame() > region->first_frame() || regions_touching)) + { + region_left->trim_end(region->first_frame(), this); + } + } + + rv.region_changed (Change (LengthChanged|PositionChanged|StartChanged)); } void -Editor::single_end_trim (RegionView& rv, nframes64_t frame_delta, bool left_direction, bool obey_snap) +Editor::single_end_trim (RegionView& rv, nframes64_t frame_delta, bool left_direction, bool obey_snap, bool no_overlap) { boost::shared_ptr<Region> region (rv.region()); @@ -5293,7 +5334,7 @@ Editor::single_end_trim (RegionView& rv, nframes64_t frame_delta, bool left_dire if (tv && tv->is_track()) { speed = tv->get_diskstream()->speed(); } - + if (left_direction) { new_bound = (nframes64_t) ((region->last_frame() + 1)/speed) - frame_delta; } else { @@ -5303,10 +5344,37 @@ Editor::single_end_trim (RegionView& rv, nframes64_t frame_delta, bool left_dire if (obey_snap) { snap_to (new_bound); } + + nframes64_t pre_trim_last_frame = region->last_frame(); + region->trim_end ((nframes64_t) (new_bound * speed), this); - rv.region_changed (LengthChanged); + + if (no_overlap) { + //Get the next region on the right of this region and shrink/expand it. + boost::shared_ptr<Playlist> playlist (region->playlist()); + boost::shared_ptr<Region> region_right = playlist->find_next_region (pre_trim_last_frame, Start, 1); + + bool regions_touching = false; + + if (region_right != 0 && (pre_trim_last_frame == region_right->first_frame() - 1)){ + regions_touching = true; + } + + //Only trim region on the right if the last frame has gone beyond the right region's first frame. + if (region_right != 0 && + (region_right->first_frame() < region->last_frame() || regions_touching)) + { + region_right->trim_front(region->last_frame() + 1, this); + } + + rv.region_changed (Change (LengthChanged|PositionChanged|StartChanged)); + } + else { + rv.region_changed (LengthChanged); + } } - + + void Editor::trim_finished_callback (ArdourCanvas::Item* item, GdkEvent* event) { @@ -5343,6 +5411,7 @@ void Editor::point_trim (GdkEvent* event) { RegionView* rv = clicked_regionview; + nframes64_t new_bound = drag_info.current_pointer_frame; if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { @@ -5356,25 +5425,29 @@ Editor::point_trim (GdkEvent* event) begin_reversible_command (_("Start point trim")); if (selection->selected (rv)) { - for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) { + if ( (*i) == NULL){ + cerr << "region view contains null region" << endl; + } + if (!(*i)->region()->locked()) { boost::shared_ptr<Playlist> pl = (*i)->region()->playlist(); XMLNode &before = pl->get_state(); - (*i)->region()->trim_front (new_bound, this); + + (*i)->region()->trim_front (new_bound, this); + XMLNode &after = pl->get_state(); session->add_command(new MementoCommand<Playlist>(*pl.get(), &before, &after)); } } } else { - if (!rv->region()->locked()) { boost::shared_ptr<Playlist> pl = rv->region()->playlist(); XMLNode &before = pl->get_state(); - rv->region()->trim_front (new_bound, this); + rv->region()->trim_front (new_bound, this); XMLNode &after = pl->get_state(); session->add_command(new MementoCommand<Playlist>(*pl.get(), &before, &after)); } diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index 1b5067e2ac..5826033072 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -3476,6 +3476,49 @@ Editor::align_region_internal (boost::shared_ptr<Region> region, RegionPoint poi session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after)); } +void +Editor::trim_region_front () +{ + trim_region (true); +} + +void +Editor::trim_region_back () +{ + trim_region (false); +} + +void +Editor::trim_region (bool front) +{ + nframes64_t where = get_preferred_edit_position(); + RegionSelection rs; + + get_regions_for_action (rs); + + if (rs.empty()) { + return; + } + + begin_reversible_command (front ? _("trim front") : _("trim back")); + + for (list<RegionView*>::const_iterator i = rs.by_layer().begin(); i != rs.by_layer().end(); ++i) { + if (!(*i)->region()->locked()) { + boost::shared_ptr<Playlist> pl = (*i)->region()->playlist(); + XMLNode &before = pl->get_state(); + if (front) { + (*i)->region()->trim_front (where, this); + } else { + (*i)->region()->trim_end (where, this); + } + XMLNode &after = pl->get_state(); + session->add_command(new MementoCommand<Playlist>(*pl.get(), &before, &after)); + } + } + + commit_reversible_command (); +} + /** Trim the end of the selected regions to the position of the edit cursor */ void Editor::trim_region_to_loop () @@ -3623,6 +3666,85 @@ Editor::trim_region_from_edit_point () } void +Editor::trim_region_to_previous_region_end () +{ + return trim_to_region(false); +} + +void +Editor::trim_region_to_next_region_start () +{ + return trim_to_region(true); +} + +void +Editor::trim_to_region(bool forward) +{ + RegionSelection rs; + + get_regions_for_action (rs); + + begin_reversible_command (_("trim to region")); + + boost::shared_ptr<Region> next_region; + + for (RegionSelection::iterator x = rs.begin(); x != rs.end(); ++x) { + + AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*x); + + if (!arv) { + continue; + } + + AudioTimeAxisView* atav = dynamic_cast<AudioTimeAxisView*> (&arv->get_time_axis_view()); + + if (!atav) { + return; + } + + float speed = 1.0; + + if (atav->get_diskstream() != 0) { + speed = atav->get_diskstream()->speed(); + } + + + boost::shared_ptr<Region> region = arv->region(); + boost::shared_ptr<Playlist> playlist (region->playlist()); + + XMLNode &before = playlist->get_state(); + + if(forward){ + + next_region = playlist->find_next_region (region->first_frame(), Start, 1); + + if(!next_region){ + continue; + } + + region->trim_end((nframes64_t) (next_region->first_frame() * speed), this); + arv->region_changed (Change (LengthChanged)); + } + else { + + next_region = playlist->find_next_region (region->first_frame(), Start, 0); + + if(!next_region){ + continue; + } + + region->trim_front((nframes64_t) ((next_region->last_frame() + 1) * speed), this); + arv->region_changed (Change (LengthChanged|PositionChanged|StartChanged)); + } + + XMLNode &after = playlist->get_state(); + session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after)); + } + + commit_reversible_command (); +} + +void Editor::unfreeze_route () { if (clicked_routeview == 0 || !clicked_routeview->is_track()) { @@ -5207,49 +5329,6 @@ Editor::ensure_entered_track_selected (bool op_really_wants_one_track_if_none_ar } } -void -Editor::trim_region_front () -{ - trim_region (true); -} - -void -Editor::trim_region_back () -{ - trim_region (false); -} - -void -Editor::trim_region (bool front) -{ - nframes64_t where = get_preferred_edit_position(); - RegionSelection rs; - - get_regions_for_action (rs); - - if (rs.empty()) { - return; - } - - begin_reversible_command (front ? _("trim front") : _("trim back")); - - for (list<RegionView*>::const_iterator i = rs.by_layer().begin(); i != rs.by_layer().end(); ++i) { - if (!(*i)->region()->locked()) { - boost::shared_ptr<Playlist> pl = (*i)->region()->playlist(); - XMLNode &before = pl->get_state(); - if (front) { - (*i)->region()->trim_front (where, this); - } else { - (*i)->region()->trim_end (where, this); - } - XMLNode &after = pl->get_state(); - session->add_command(new MementoCommand<Playlist>(*pl.get(), &before, &after)); - } - } - - commit_reversible_command (); -} - struct EditorOrderRouteSorter { bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) { /* use of ">" forces the correct sort order */ diff --git a/gtk2_ardour/route_time_axis.cc b/gtk2_ardour/route_time_axis.cc index a1f41adf6e..2b622bda28 100644 --- a/gtk2_ardour/route_time_axis.cc +++ b/gtk2_ardour/route_time_axis.cc @@ -128,6 +128,7 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh no_redraw = false; destructive_track_mode_item = 0; normal_track_mode_item = 0; + non_layered_track_mode_item = 0; ignore_toggle = false; @@ -165,8 +166,10 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh /* use icon */ rec_enable_button->remove (); + switch (track()->mode()) { case ARDOUR::Normal: + case ARDOUR::NonLayered: rec_enable_button->add (*(manage (new Image (::get_icon (X_("record_normal_red")))))); break; case ARDOUR::Destructive: @@ -554,10 +557,17 @@ RouteTimeAxisView::build_display_menu () mem_fun (*this, &RouteTimeAxisView::set_track_mode), ARDOUR::Normal))); normal_track_mode_item = dynamic_cast<RadioMenuItem*>(&items.back()); + items.push_back (RadioMenuElem (mode_group, _("Tape mode"), bind ( mem_fun (*this, &RouteTimeAxisView::set_track_mode), ARDOUR::Destructive))); destructive_track_mode_item = dynamic_cast<RadioMenuItem*>(&items.back()); + + items.push_back (RadioMenuElem (mode_group, _("No layering mode"), + bind (mem_fun (*this, &RouteTimeAxisView::set_track_mode), ARDOUR::NonLayered))); + non_layered_track_mode_item = dynamic_cast<RadioMenuItem*>(&items.back()); + + switch (track()->mode()) { case ARDOUR::Destructive: @@ -566,6 +576,9 @@ RouteTimeAxisView::build_display_menu () case ARDOUR::Normal: normal_track_mode_item->set_active (); break; + case ARDOUR::NonLayered: + non_layered_track_mode_item->set_active (); + break; } } @@ -597,9 +610,10 @@ RouteTimeAxisView::build_display_menu () } } -static bool __reset_item (RadioMenuItem* item) +static bool __reset_item (RadioMenuItem* item, RadioMenuItem* item_2) { item->set_active (); + item_2->set_active (); return false; } @@ -608,15 +622,23 @@ RouteTimeAxisView::set_track_mode (TrackMode mode) { RadioMenuItem* item; RadioMenuItem* other_item; + RadioMenuItem* other_item_2; switch (mode) { case ARDOUR::Normal: item = normal_track_mode_item; - other_item = destructive_track_mode_item; + other_item = non_layered_track_mode_item; + other_item_2 = destructive_track_mode_item; + break; + case ARDOUR::NonLayered: + item = non_layered_track_mode_item; + other_item = normal_track_mode_item; + other_item_2 = destructive_track_mode_item; break; case ARDOUR::Destructive: item = destructive_track_mode_item; other_item = normal_track_mode_item; + other_item_2 = non_layered_track_mode_item; break; default: fatal << string_compose (_("programming error: %1 %2"), "illegal track mode in RouteTimeAxisView::set_track_mode", mode) << endmsg; @@ -624,13 +646,13 @@ RouteTimeAxisView::set_track_mode (TrackMode mode) return; } - if (item && other_item && item->get_active () && track()->mode() != mode) { - _set_track_mode (track().get(), mode, other_item); + if (item && other_item && other_item_2 && item->get_active() && track()->mode() != mode) { + _set_track_mode (track().get(), mode, other_item, other_item_2); } } void -RouteTimeAxisView::_set_track_mode (Track* track, TrackMode mode, RadioMenuItem* reset_item) +RouteTimeAxisView::_set_track_mode (Track* track, TrackMode mode, RadioMenuItem* reset_item, RadioMenuItem* reset_item_2) { bool needs_bounce; @@ -638,7 +660,7 @@ RouteTimeAxisView::_set_track_mode (Track* track, TrackMode mode, RadioMenuItem* if (!needs_bounce) { /* cannot be done */ - Glib::signal_idle().connect (bind (sigc::ptr_fun (__reset_item), reset_item)); + Glib::signal_idle().connect (bind (sigc::ptr_fun (__reset_item), reset_item, reset_item_2)); return; } else { cerr << "would bounce this one\n"; @@ -649,7 +671,9 @@ RouteTimeAxisView::_set_track_mode (Track* track, TrackMode mode, RadioMenuItem* track->set_mode (mode); rec_enable_button->remove (); + switch (mode) { + case ARDOUR::NonLayered: case ARDOUR::Normal: rec_enable_button->add (*(manage (new Image (::get_icon (X_("record_normal_red")))))); break; @@ -657,8 +681,8 @@ RouteTimeAxisView::_set_track_mode (Track* track, TrackMode mode, RadioMenuItem* rec_enable_button->add (*(manage (new Image (::get_icon (X_("record_tape_red")))))); break; } - rec_enable_button->show_all (); + rec_enable_button->show_all (); } void @@ -670,6 +694,9 @@ RouteTimeAxisView::track_mode_changed () case ARDOUR::Normal: item = normal_track_mode_item; break; + case ARDOUR::NonLayered: + item = non_layered_track_mode_item; + break; case ARDOUR::Destructive: item = destructive_track_mode_item; break; diff --git a/gtk2_ardour/route_time_axis.h b/gtk2_ardour/route_time_axis.h index cf1e86c0b4..9c386bafa3 100644 --- a/gtk2_ardour/route_time_axis.h +++ b/gtk2_ardour/route_time_axis.h @@ -283,6 +283,7 @@ protected: Gtk::RadioMenuItem* align_existing_item; Gtk::RadioMenuItem* align_capture_item; Gtk::RadioMenuItem* normal_track_mode_item; + Gtk::RadioMenuItem* non_layered_track_mode_item; Gtk::RadioMenuItem* destructive_track_mode_item; Gtk::Menu* playlist_menu; Gtk::Menu* playlist_action_menu; @@ -298,7 +299,7 @@ protected: ArdourCanvas::SimpleRect* timestretch_rect; void set_track_mode (ARDOUR::TrackMode); - void _set_track_mode (ARDOUR::Track* track, ARDOUR::TrackMode mode, Gtk::RadioMenuItem* reset_item); + void _set_track_mode (ARDOUR::Track* track, ARDOUR::TrackMode mode, Gtk::RadioMenuItem* reset_item, Gtk::RadioMenuItem* reset_item_2); void track_mode_changed (); list<ProcessorAutomationInfo*> processor_automation; diff --git a/gtk2_ardour/streamview.cc b/gtk2_ardour/streamview.cc index 8d36427a0b..27131fa3e3 100644 --- a/gtk2_ardour/streamview.cc +++ b/gtk2_ardour/streamview.cc @@ -424,6 +424,8 @@ StreamView::update_rec_box () double xend; switch (_trackview.track()->mode()) { + + case NonLayered: case Normal: rect.length = at - rect.start; xstart = _trackview.editor().frame_to_pixel (rect.start); diff --git a/libs/ardour/ardour/audio_diskstream.h b/libs/ardour/ardour/audio_diskstream.h index 8acb3e2806..4f22efd535 100644 --- a/libs/ardour/ardour/audio_diskstream.h +++ b/libs/ardour/ardour/audio_diskstream.h @@ -78,6 +78,7 @@ class AudioDiskstream : public Diskstream void set_record_enabled (bool yn); int set_destructive (bool yn); + int set_non_layered (bool yn); bool can_become_destructive (bool& requires_bounce) const; float peak_power(uint32_t n = 0) { diff --git a/libs/ardour/ardour/configuration_vars.h b/libs/ardour/ardour/configuration_vars.h index 81985ff77a..c91306d6dd 100644 --- a/libs/ardour/ardour/configuration_vars.h +++ b/libs/ardour/ardour/configuration_vars.h @@ -172,6 +172,7 @@ CONFIG_VARIABLE (bool, default_narrow_ms, "default-narrow_ms", false) CONFIG_VARIABLE (bool, name_new_markers, "name-new-markers", false) CONFIG_VARIABLE (bool, rubberbanding_snaps_to_grid, "rubberbanding-snaps-to-grid", false) CONFIG_VARIABLE (long, font_scale, "font-scale", 102400) +CONFIG_VARIABLE (std::string, default_session_parent_dir, "default-session-parent-dir", "~") /* denormal management */ diff --git a/libs/ardour/ardour/diskstream.h b/libs/ardour/ardour/diskstream.h index a835e4b571..a5a98338da 100644 --- a/libs/ardour/ardour/diskstream.h +++ b/libs/ardour/ardour/diskstream.h @@ -64,7 +64,8 @@ class Diskstream : public SessionObject, public boost::noncopyable enum Flag { Recordable = 0x1, Hidden = 0x2, - Destructive = 0x4 + Destructive = 0x4, + NonLayered = 0x8 }; Diskstream (Session &, const string& name, Flag f = Recordable); @@ -94,10 +95,12 @@ class Diskstream : public SessionObject, public boost::noncopyable bool destructive() const { return _flags & Destructive; } virtual int set_destructive (bool yn) { return -1; } + virtual int set_non_layered (bool yn) { return -1; } virtual bool can_become_destructive (bool& requires_bounce) const { return false; } bool hidden() const { return _flags & Hidden; } bool recordable() const { return _flags & Recordable; } + bool non_layered() const { return _flags & NonLayered; } bool reversed() const { return _actual_speed < 0.0f; } double speed() const { return _visible_speed; } diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h index a88687cbbb..63edad8805 100644 --- a/libs/ardour/ardour/playlist.h +++ b/libs/ardour/ardour/playlist.h @@ -91,7 +91,7 @@ class Playlist : public SessionObject, /* Editing operations */ - void add_region (boost::shared_ptr<Region>, nframes_t position, float times = 1); + void add_region (boost::shared_ptr<Region>, nframes_t position, float times = 1, bool auto_partition = false); void remove_region (boost::shared_ptr<Region>); void get_equivalent_regions (boost::shared_ptr<Region>, std::vector<boost::shared_ptr<Region> >&); void get_region_list_equivalent_regions (boost::shared_ptr<Region>, std::vector<boost::shared_ptr<Region> >&); @@ -99,7 +99,7 @@ class Playlist : public SessionObject, void split_region (boost::shared_ptr<Region>, nframes_t position); void split (nframes64_t at); void shift (nframes64_t at, nframes64_t distance, bool move_intersected, bool ignore_music_glue); - void partition (nframes_t start, nframes_t end, bool just_top_level); + void partition (nframes_t start, nframes_t end, bool cut = false); void duplicate (boost::shared_ptr<Region>, nframes_t position, float times); void nudge_after (nframes_t start, nframes_t distance, bool forwards); void shuffle (boost::shared_ptr<Region>, int dir); @@ -187,7 +187,7 @@ class Playlist : public SessionObject, DataType _type; mutable gint block_notifications; mutable gint ignore_state_changes; - mutable Glib::Mutex region_lock; + mutable Glib::RecMutex region_lock; std::set<boost::shared_ptr<Region> > pending_adds; std::set<boost::shared_ptr<Region> > pending_removes; RegionList pending_bounds; @@ -212,6 +212,7 @@ class Playlist : public SessionObject, PBD::ID _orig_diskstream_id; uint64_t layer_op_counter; nframes_t freeze_length; + bool auto_partition; void init (bool hide); diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h index b6b6321d4f..2ed5e0e365 100644 --- a/libs/ardour/ardour/types.h +++ b/libs/ardour/ardour/types.h @@ -135,6 +135,7 @@ namespace ARDOUR { enum TrackMode { Normal, + NonLayered, Destructive }; diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index 4c36100c82..94c52c5976 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -1687,7 +1687,7 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca _last_capture_regions.push_back (region); i_am_the_modifier++; - _playlist->add_region (region, (*ci)->start); + _playlist->add_region (region, (*ci)->start, 1, non_layered()); i_am_the_modifier--; buffer_position += (*ci)->frames; @@ -2407,6 +2407,21 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node) } int +AudioDiskstream::set_non_layered (bool yn) +{ + if (yn != non_layered()) { + + if (yn) { + _flags = Flag (_flags | NonLayered); + } else { + _flags = Flag (_flags & ~NonLayered); + } + } + + return 0; +} + +int AudioDiskstream::set_destructive (bool yn) { bool bounce_ignored; diff --git a/libs/ardour/audio_playlist.cc b/libs/ardour/audio_playlist.cc index 4953cdf702..ef2cf281ef 100644 --- a/libs/ardour/audio_playlist.cc +++ b/libs/ardour/audio_playlist.cc @@ -147,7 +147,7 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nf its OK to block (for short intervals). */ - Glib::Mutex::Lock rm (region_lock); + Glib::RecMutex::Lock rm (region_lock); end = start + cnt - 1; read_frames = 0; diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc index 8f37ea2239..25161ea249 100644 --- a/libs/ardour/audio_track.cc +++ b/libs/ardour/audio_track.cc @@ -77,7 +77,10 @@ AudioTrack::use_new_diskstream () if (_mode == Destructive) { dflags = AudioDiskstream::Flag (dflags | AudioDiskstream::Destructive); + } else if (_mode == NonLayered){ + dflags = AudioDiskstream::Flag(dflags | AudioDiskstream::NonLayered); } + boost::shared_ptr<AudioDiskstream> ds (new AudioDiskstream (_session, name(), dflags)); @@ -94,7 +97,8 @@ AudioTrack::set_mode (TrackMode m) if (_diskstream->set_destructive (m == Destructive)) { return -1; } - + + _diskstream->set_non_layered (m == NonLayered); _mode = m; TrackModeChanged (); /* EMIT SIGNAL */ @@ -107,6 +111,7 @@ bool AudioTrack::can_use_mode (TrackMode m, bool& bounce_required) { switch (m) { + case NonLayered: case Normal: bounce_required = false; return true; @@ -177,6 +182,7 @@ AudioTrack::set_diskstream (boost::shared_ptr<AudioDiskstream> ds, void *src) _diskstream = ds; _diskstream->set_io (*this); _diskstream->set_destructive (_mode == Destructive); + _diskstream->set_non_layered (_mode == NonLayered); if (audio_diskstream()->deprecated_io_node) { diff --git a/libs/ardour/configuration.cc b/libs/ardour/configuration.cc index bf8facd1a4..611ebddb59 100644 --- a/libs/ardour/configuration.cc +++ b/libs/ardour/configuration.cc @@ -129,7 +129,8 @@ Configuration::load_state () "ardour.rc", user_rc_file)) { XMLTree tree; - + found = true; + string rcfile = user_rc_file.to_string(); /* stupid XML parser hates empty files */ diff --git a/libs/ardour/enums.cc b/libs/ardour/enums.cc index c61f38c922..841b2ad185 100644 --- a/libs/ardour/enums.cc +++ b/libs/ardour/enums.cc @@ -152,6 +152,7 @@ setup_enum_writer () REGISTER (_MeterPoint); REGISTER_ENUM (Normal); + REGISTER_ENUM (NonLayered); REGISTER_ENUM (Destructive); REGISTER (_TrackMode); diff --git a/libs/ardour/midi_playlist.cc b/libs/ardour/midi_playlist.cc index 0e4c65ce3f..bb3603b8a8 100644 --- a/libs/ardour/midi_playlist.cc +++ b/libs/ardour/midi_playlist.cc @@ -130,7 +130,7 @@ MidiPlaylist::read (MidiRingBuffer<nframes_t>& dst, nframes_t start, nframes_t d its OK to block (for short intervals). */ - Glib::Mutex::Lock rm (region_lock); + Glib::RecMutex::Lock rm (region_lock); nframes_t end = start + dur - 1; @@ -271,7 +271,7 @@ MidiPlaylist::contained_automation() its OK to block (for short intervals). */ - Glib::Mutex::Lock rm (region_lock); + Glib::RecMutex::Lock rm (region_lock); set<Evoral::Parameter> ret; diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc index f34e47b9da..a4a0a62e98 100644 --- a/libs/ardour/playlist.cc +++ b/libs/ardour/playlist.cc @@ -474,7 +474,7 @@ Playlist::flush_notifications () *************************************************************/ void -Playlist::add_region (boost::shared_ptr<Region> region, nframes_t position, float times) +Playlist::add_region (boost::shared_ptr<Region> region, nframes_t position, float times, bool auto_partition) { RegionLock rlock (this); times = fabs (times); @@ -482,6 +482,10 @@ Playlist::add_region (boost::shared_ptr<Region> region, nframes_t position, floa int itimes = (int) floor (times); nframes_t pos = position; + + if(times == 1 && auto_partition){ + partition(pos, (nframes_t) (pos + region->length()), true); + } if (itimes >= 1) { add_region_internal (region, pos); @@ -510,7 +514,6 @@ Playlist::add_region (boost::shared_ptr<Region> region, nframes_t position, floa add_region_internal (sub, pos); } - possibly_splice_unlocked (position, (pos + length) - position, boost::shared_ptr<Region>()); } @@ -529,8 +532,9 @@ Playlist::set_region_ownership () bool Playlist::add_region_internal (boost::shared_ptr<Region> region, nframes_t position) { - if (region->data_type() != _type) + if (region->data_type() != _type){ return false; + } RegionSortByPosition cmp; nframes_t old_length = 0; @@ -674,11 +678,11 @@ Playlist::get_region_list_equivalent_regions (boost::shared_ptr<Region> other, v } void -Playlist::partition (nframes_t start, nframes_t end, bool just_top_level) +Playlist::partition (nframes_t start, nframes_t end, bool cut) { RegionList thawlist; - partition_internal (start, end, false, thawlist); + partition_internal (start, end, cut, thawlist); for (RegionList::iterator i = thawlist.begin(); i != thawlist.end(); ++i) { (*i)->thaw ("separation"); @@ -692,6 +696,7 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi { RegionLock rlock (this); + boost::shared_ptr<Region> region; boost::shared_ptr<Region> current; string new_name; @@ -708,16 +713,18 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi RegionList copy = regions; for (RegionList::iterator i = copy.begin(); i != copy.end(); i = tmp) { - + tmp = i; ++tmp; current = *i; if (current->first_frame() >= start && current->last_frame() < end) { + if (cutting) { remove_region_internal (current); } + continue; } @@ -740,7 +747,6 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi pos4 = current->last_frame(); if (overlap == OverlapInternal) { - /* split: we need 3 new regions, the front, middle and end. cut: we need 2 regions, the front and end. */ @@ -757,7 +763,6 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi */ if (!cutting) { - /* "middle" ++++++ */ _session.region_name (new_name, current->name(), false); @@ -772,7 +777,7 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi _session.region_name (new_name, current->name(), false); region = RegionFactory::create (current, pos3 - pos1, pos4 - pos3, new_name, regions.size(), Region::Flag(current->flags()|Region::Automatic|Region::RightOfSplit)); - + add_region_internal (region, end); new_regions.push_back (region); @@ -781,9 +786,9 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi current->freeze (); thawlist.push_back (current); current->trim_end (pos2, this); - + } else if (overlap == OverlapEnd) { - + /* start end ---------------*************************------------ @@ -795,12 +800,13 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi */ if (!cutting) { - + /* end +++++ */ _session.region_name (new_name, current->name(), false); region = RegionFactory::create (current, pos2 - pos1, pos4 - pos2, new_name, (layer_t) regions.size(), Region::Flag(current->flags()|Region::Automatic|Region::LeftOfSplit)); + add_region_internal (region, start); new_regions.push_back (region); } @@ -810,9 +816,9 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi current->freeze (); thawlist.push_back (current); current->trim_end (pos2, this); - + } else if (overlap == OverlapStart) { - + /* split: we need 2 regions: the front and the end. cut: just trim current to skip the cut area */ @@ -830,11 +836,11 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi */ if (!cutting) { - /* front **** */ _session.region_name (new_name, current->name(), false); region = RegionFactory::create (current, 0, pos3 - pos1, new_name, regions.size(), Region::Flag(current->flags()|Region::Automatic|Region::RightOfSplit)); + add_region_internal (region, pos1); new_regions.push_back (region); } @@ -844,9 +850,8 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi current->freeze (); thawlist.push_back (current); current->trim_front (pos3, this); - } else if (overlap == OverlapExternal) { - + /* split: no split required. cut: remove the region. */ @@ -866,10 +871,11 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi if (cutting) { remove_region_internal (current); } + new_regions.push_back (current); } } - + in_partition = false; } @@ -1591,9 +1597,12 @@ Playlist::find_next_region (nframes_t frame, RegionPoint point, int dir) boost::shared_ptr<Region> ret; nframes_t closest = max_frames; + bool end_iter = false; for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) { + if(end_iter) break; + nframes_t distance; boost::shared_ptr<Region> r = (*i); nframes_t pos = 0; @@ -1614,23 +1623,28 @@ Playlist::find_next_region (nframes_t frame, RegionPoint point, int dir) switch (dir) { case 1: /* forwards */ - if (pos >= frame) { + if (pos > frame) { if ((distance = pos - frame) < closest) { closest = distance; ret = r; + end_iter = true; } } break; default: /* backwards */ - - if (pos <= frame) { + + if (pos < frame) { if ((distance = frame - pos) < closest) { closest = distance; ret = r; } } + else { + end_iter = true; + } + break; } } @@ -1710,6 +1724,7 @@ Playlist::find_next_region_boundary (nframes64_t frame, int dir) + void Playlist::mark_session_dirty () { @@ -110,7 +110,7 @@ def set_options(opt): opt.add_option('--wiimote', action='store_true', default=False, dest='wiimote', help='Build the wiimote control surface') opt.add_option('--windows-key', type='string', dest='windows_key', - help='Set X Modifier (Mod1,Mod2,Mod3,Mod4,Mod5) for "Windows" key [Default: Mod4]') + help='Set X Modifier (Mod1,Mod2,Mod3,Mod4,Mod5) for "Windows" key [Default: Mod4]', default='Mod4><Super') for i in children: opt.sub_options(i) |