summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/add_route_dialog.cc3
-rw-r--r--gtk2_ardour/ardour.menus.in2
-rw-r--r--gtk2_ardour/audio_streamview.cc3
-rw-r--r--gtk2_ardour/audio_time_axis.cc9
-rw-r--r--gtk2_ardour/editor.h8
-rw-r--r--gtk2_ardour/editor_actions.cc7
-rw-r--r--gtk2_ardour/editor_mouse.cc99
-rw-r--r--gtk2_ardour/editor_ops.cc165
-rw-r--r--gtk2_ardour/route_time_axis.cc41
-rw-r--r--gtk2_ardour/route_time_axis.h3
-rw-r--r--gtk2_ardour/streamview.cc2
-rw-r--r--libs/ardour/ardour/audio_diskstream.h1
-rw-r--r--libs/ardour/ardour/configuration_vars.h1
-rw-r--r--libs/ardour/ardour/diskstream.h5
-rw-r--r--libs/ardour/ardour/playlist.h7
-rw-r--r--libs/ardour/ardour/types.h1
-rw-r--r--libs/ardour/audio_diskstream.cc17
-rw-r--r--libs/ardour/audio_playlist.cc2
-rw-r--r--libs/ardour/audio_track.cc8
-rw-r--r--libs/ardour/configuration.cc3
-rw-r--r--libs/ardour/enums.cc1
-rw-r--r--libs/ardour/midi_playlist.cc4
-rw-r--r--libs/ardour/playlist.cc57
-rw-r--r--wscript2
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 ()
{
diff --git a/wscript b/wscript
index f8001ca58e..e42dbbea31 100644
--- a/wscript
+++ b/wscript
@@ -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)