static const char* track_mode_names[] = {
N_("Normal"),
+ N_("Non Layered"),
N_("Tape"),
0
};
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 {
<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'/>
}
switch (_trackview.audio_track()->mode()) {
+
+ case NonLayered:
case Normal:
if (recording) {
region_view = new AudioRegionView (canvas_group, _trackview, region,
switch (_trackview.audio_track()->mode()) {
case Normal:
+ case NonLayered:
xend = xstart;
fill_color = ARDOUR_UI::config()->canvasvar_RecordingRect.get();
break;
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());
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;
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);
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 */
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));
if (changed_tracks || drag_info.copy) {
boost::shared_ptr<Playlist> to_playlist = dest_rtv->playlist();
+
if (!to_playlist) {
++i;
continue;
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));
}
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();
}
/* 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));
}
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
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
(*i)->hide_selection ();
}
+
selection->clear ();
clicked_selection = 0;
}
{
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());
(*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();
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;
}
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;
}
}
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());
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());
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 {
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)
{
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())) {
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));
}
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 ()
commit_reversible_command ();
}
+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 ()
{
}
}
-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 */
no_redraw = false;
destructive_track_mode_item = 0;
normal_track_mode_item = 0;
+ non_layered_track_mode_item = 0;
ignore_toggle = false;
/* 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:
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:
case ARDOUR::Normal:
normal_track_mode_item->set_active ();
break;
+ case ARDOUR::NonLayered:
+ non_layered_track_mode_item->set_active ();
+ break;
}
}
}
}
-static bool __reset_item (RadioMenuItem* item)
+static bool __reset_item (RadioMenuItem* item, RadioMenuItem* item_2)
{
item->set_active ();
+ item_2->set_active ();
return false;
}
{
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;
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;
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";
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;
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
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;
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;
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;
double xend;
switch (_trackview.track()->mode()) {
+
+ case NonLayered:
case Normal:
rect.length = at - rect.start;
xstart = _trackview.editor().frame_to_pixel (rect.start);
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) {
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 */
enum Flag {
Recordable = 0x1,
Hidden = 0x2,
- Destructive = 0x4
+ Destructive = 0x4,
+ NonLayered = 0x8
};
Diskstream (Session &, const string& name, Flag f = Recordable);
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; }
/* 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> >&);
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);
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;
PBD::ID _orig_diskstream_id;
uint64_t layer_op_counter;
nframes_t freeze_length;
+ bool auto_partition;
void init (bool hide);
enum TrackMode {
Normal,
+ NonLayered,
Destructive
};
_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;
return 0;
}
+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)
{
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;
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));
if (_diskstream->set_destructive (m == Destructive)) {
return -1;
}
-
+
+ _diskstream->set_non_layered (m == NonLayered);
_mode = m;
TrackModeChanged (); /* EMIT SIGNAL */
AudioTrack::can_use_mode (TrackMode m, bool& bounce_required)
{
switch (m) {
+ case NonLayered:
case Normal:
bounce_required = false;
return true;
_diskstream = ds;
_diskstream->set_io (*this);
_diskstream->set_destructive (_mode == Destructive);
+ _diskstream->set_non_layered (_mode == NonLayered);
if (audio_diskstream()->deprecated_io_node) {
"ardour.rc", user_rc_file))
{
XMLTree tree;
-
+ found = true;
+
string rcfile = user_rc_file.to_string();
/* stupid XML parser hates empty files */
REGISTER (_MeterPoint);
REGISTER_ENUM (Normal);
+ REGISTER_ENUM (NonLayered);
REGISTER_ENUM (Destructive);
REGISTER (_TrackMode);
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;
its OK to block (for short intervals).
*/
- Glib::Mutex::Lock rm (region_lock);
+ Glib::RecMutex::Lock rm (region_lock);
set<Evoral::Parameter> ret;
*************************************************************/
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);
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);
add_region_internal (sub, pos);
}
-
possibly_splice_unlocked (position, (pos + length) - position, boost::shared_ptr<Region>());
}
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;
}
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");
{
RegionLock rlock (this);
+
boost::shared_ptr<Region> region;
boost::shared_ptr<Region> current;
string new_name;
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;
}
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.
*/
*/
if (!cutting) {
-
/* "middle" ++++++ */
_session.region_name (new_name, current->name(), false);
_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);
current->freeze ();
thawlist.push_back (current);
current->trim_end (pos2, this);
-
+
} else if (overlap == OverlapEnd) {
-
+
/*
start end
---------------*************************------------
*/
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);
}
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
*/
*/
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);
}
current->freeze ();
thawlist.push_back (current);
current->trim_front (pos3, this);
-
} else if (overlap == OverlapExternal) {
-
+
/* split: no split required.
cut: remove the region.
*/
if (cutting) {
remove_region_internal (current);
}
+
new_regions.push_back (current);
}
}
-
+
in_partition = false;
}
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;
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;
}
}
+
void
Playlist::mark_session_dirty ()
{
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)