#include <ardour/audio_track.h>
#include <ardour/audioplaylist.h>
#include <ardour/region_factory.h>
+#include <ardour/playlist_factory.h>
#include <ardour/reverse.h>
#include "ardour_ui.h"
#include "rgb_macros.h"
#include "selection_templates.h"
#include "selection.h"
-#include "sfdb_ui.h"
#include "editing.h"
#include "gtk-custom-hruler.h"
#include "gui_thread.h"
tmp = a;
++tmp;
- Playlist* pl = (*a)->region()->playlist();
+ boost::shared_ptr<Playlist> pl = (*a)->region()->playlist();
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*a);
if (arv)
return;
}
- Playlist* playlist = clicked_audio_trackview->playlist();
+ boost::shared_ptr<Playlist> playlist = clicked_audio_trackview->playlist();
begin_reversible_command (_("remove region"));
XMLNode &before = playlist->get_state();
RouteTimeAxisView* rtv;
if ((rtv = dynamic_cast<RouteTimeAxisView*> (*tv)) != 0) {
- Playlist *pl;
+ boost::shared_ptr<Playlist> pl;
if ((pl = rtv->playlist()) == 0) {
return region;
}
}
+void
+Editor::scroll_playhead (bool forward)
+{
+ nframes_t pos = playhead_cursor->current_frame;
+ nframes_t delta = (nframes_t) floor (current_page_frames() / 0.8);
+
+ if (forward) {
+ if (pos == max_frames) {
+ return;
+ }
+
+ if (pos < max_frames - delta) {
+ pos += delta ;
+ } else {
+ pos = max_frames;
+ }
+
+ } else {
+
+ if (pos == 0) {
+ return;
+ }
+
+ if (pos > delta) {
+ pos -= delta;
+ } else {
+ pos = 0;
+ }
+ }
+
+ session->request_locate (pos);
+}
+
void
Editor::playhead_backward ()
{
frame = leftmost_frame - cnt;
}
- reposition_x_origin (frame);
+ reset_x_origin (frame);
}
void
frame = leftmost_frame + cnt;
}
- reposition_x_origin (frame);
+ reset_x_origin (frame);
}
void
void
Editor::add_location_from_selection ()
{
+ string rangename;
+
if (selection->time.empty()) {
return;
}
nframes_t start = selection->time[clicked_selection].start;
nframes_t end = selection->time[clicked_selection].end;
- Location *location = new Location (start, end, "selection");
+ session->locations()->next_available_name(rangename,"selection");
+ Location *location = new Location (start, end, rangename, Location::IsRangeMarker);
session->begin_reversible_command (_("add marker"));
XMLNode &before = session->locations()->get_state();
void
Editor::add_location_from_playhead_cursor ()
{
+ string markername;
+
nframes_t where = session->audible_frame();
- Location *location = new Location (where, where, "mark", Location::IsMark);
+ session->locations()->next_available_name(markername,"mark");
+ Location *location = new Location (where, where, markername, Location::IsMark);
session->begin_reversible_command (_("add marker"));
XMLNode &before = session->locations()->get_state();
session->locations()->add (location, true);
RegionView* rv = *(selection->regions.begin());
boost::shared_ptr<Region> region = rv->region();
- Location *location = new Location (region->position(), region->last_frame(), region->name());
+ Location *location = new Location (region->position(), region->last_frame(), region->name(), Location::IsRangeMarker);
session->begin_reversible_command (_("add marker"));
XMLNode &before = session->locations()->get_state();
session->locations()->add (location, true);
begin_reversible_command (_("select all"));
switch (op) {
case Selection::Add:
+ selection->add (touched);
+ break;
case Selection::Toggle:
selection->add (touched);
break;
bool
Editor::select_all_within (nframes_t start, nframes_t end, double top, double bot, Selection::Operation op)
{
- list<Selectable *> touched;
-
+ list<Selectable*> touched;
+ list<Selectable*>::size_type n = 0;
+ TrackViewList touched_tracks;
+
for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
if ((*iter)->hidden()) {
continue;
}
+
+ n = touched.size();
+
(*iter)->get_selectables (start, end, top, bot, touched);
- }
- cerr << "select all within found " << touched.size() << endl;
+ if (n != touched.size()) {
+ touched_tracks.push_back (*iter);
+ }
+ }
+ if (!touched_tracks.empty()) {
+ switch (op) {
+ case Selection::Add:
+ selection->add (touched_tracks);
+ break;
+ case Selection::Toggle:
+ selection->toggle (touched_tracks);
+ break;
+ case Selection::Set:
+ selection->set (touched_tracks);
+ break;
+ case Selection::Extend:
+ /* not defined yet */
+ break;
+ }
+ }
+
begin_reversible_command (_("select all within"));
switch (op) {
case Selection::Add:
- case Selection::Toggle:
- cerr << "toggle\n";
selection->add (touched);
break;
+ case Selection::Toggle:
+ selection->toggle (touched);
+ break;
case Selection::Set:
- cerr << "set\n";
selection->set (touched);
break;
case Selection::Extend:
- cerr << "extend\n";
/* not defined yet */
break;
}
- cerr << "selection now has " << selection->points.size() << endl;
-
commit_reversible_command ();
return !touched.empty();
}
nframes_t pos;
float prefix;
bool was_floating;
+ string markername;
if (get_prefix (prefix, was_floating)) {
pos = session->audible_frame ();
}
}
- session->locations()->add (new Location (pos, 0, "mark", Location::IsMark), true);
+ session->locations()->next_available_name(markername,"mark");
+ session->locations()->add (new Location (pos, 0, markername, Location::IsMark), true);
}
void
session->locations()->clear ();
}
+void
+Editor::unhide_markers ()
+{
+ for (LocationMarkerMap::iterator i = location_markers.begin(); i != location_markers.end(); ++i) {
+ Location *l = (*i).first;
+ if (l->is_hidden() && l->is_mark()) {
+ l->set_hidden(false, this);
+ }
+ }
+}
+
+void
+Editor::unhide_ranges ()
+{
+ for (LocationMarkerMap::iterator i = location_markers.begin(); i != location_markers.end(); ++i) {
+ Location *l = (*i).first;
+ if (l->is_hidden() && l->is_range_marker()) {
+ l->set_hidden(false, this);
+ }
+ }
+}
+
/* INSERT/REPLACE */
void
TimeAxisView *tv;
nframes_t where;
AudioTimeAxisView *atv = 0;
- Playlist *playlist;
+ boost::shared_ptr<Playlist> playlist;
track_canvas.window_to_world (x, y, wx, wy);
wx += horizontal_adjustment.get_value();
return;
}
+ cerr << "drop target playlist, UC = " << playlist.use_count() << endl;
+
snap_to (where);
begin_reversible_command (_("insert dragged region"));
XMLNode &before = playlist->get_state();
+ cerr << "pre add target playlist, UC = " << playlist.use_count() << endl;
playlist->add_region (RegionFactory::create (region), where, 1.0);
+ cerr << "post add target playlist, UC = " << playlist.use_count() << endl;
session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
commit_reversible_command ();
+
+ cerr << "post drop target playlist, UC = " << playlist.use_count() << endl;
}
void
Editor::insert_region_list_selection (float times)
{
RouteTimeAxisView *tv = 0;
- Playlist *playlist;
+ boost::shared_ptr<Playlist> playlist;
if (clicked_audio_trackview != 0) {
tv = clicked_audio_trackview;
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
boost::shared_ptr<AudioRegion> current;
boost::shared_ptr<Region> current_r;
- Playlist *pl;
+ boost::shared_ptr<Playlist> pl;
nframes_t internal_start;
string new_name;
nframes_t start = selection->time[clicked_selection].start;
nframes_t end = selection->time[clicked_selection].end;
+ sort_track_selection ();
+
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
boost::shared_ptr<AudioRegion> current;
boost::shared_ptr<Region> current_r;
- Playlist* playlist;
+ boost::shared_ptr<Playlist> playlist;
nframes_t internal_start;
string new_name;
return;
}
- Playlist *playlist;
+ boost::shared_ptr<Playlist> playlist;
+ sort_track_selection ();
+
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
AudioTimeAxisView* atv;
return;
}
- Playlist *playlist;
+ boost::shared_ptr<Playlist> playlist;
/* XXX i'm unsure as to whether this should operate on selected tracks only
or the entire enchillada. uncomment the below line to correct the behaviour
return;
}
- vector<Playlist*> playlists;
- Playlist *playlist;
+ vector<boost::shared_ptr<Playlist> > playlists;
+ boost::shared_ptr<Playlist> playlist;
if (clicked_trackview != 0) {
} else {
+ sort_track_selection ();
+
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
AudioTimeAxisView* atv;
begin_reversible_command (_("trim to selection"));
- for (vector<Playlist*>::iterator i = playlists.begin(); i != playlists.end(); ++i) {
+ for (vector<boost::shared_ptr<Playlist> >::iterator i = playlists.begin(); i != playlists.end(); ++i) {
boost::shared_ptr<Region> region;
if (!ar)
continue;
- Playlist* pl = region->playlist();
+ boost::shared_ptr<Playlist> pl = region->playlist();
if (end <= region->last_frame()) {
return;
nframes_t start = selection->time[clicked_selection].start;
nframes_t end = selection->time[clicked_selection].end;
- Playlist *playlist;
+ boost::shared_ptr<Playlist> playlist;
if (selection->tracks.empty()) {
return;
itt.done = false;
itt.cancel = false;
itt.progress = 0.0f;
+
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setstacksize(&attr, 500000);
+
+ pthread_create (&itt.thread, &attr, _freeze_thread, this);
- pthread_create (&itt.thread, 0, _freeze_thread, this);
+ pthread_attr_destroy(&attr);
track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH));
continue;
}
- Playlist* playlist;
+ boost::shared_ptr<Playlist> playlist;
if ((playlist = atv->playlist()) == 0) {
return;
}
struct PlaylistState {
- Playlist* playlist;
+ boost::shared_ptr<Playlist> playlist;
XMLNode* before;
};
}
};
+struct PlaylistMapping {
+ TimeAxisView* tv;
+ boost::shared_ptr<AudioPlaylist> pl;
+
+ PlaylistMapping (TimeAxisView* tvp) : tv (tvp) {}
+};
+
void
Editor::cut_copy_regions (CutCopyOp op)
{
- typedef std::map<AudioPlaylist*,AudioPlaylist*> PlaylistMapping;
- PlaylistMapping pmap;
- nframes_t first_position = max_frames;
+ /* we can't use a std::map here because the ordering is important, and we can't trivially sort
+ a map when we want ordered access to both elements. i think.
+ */
+
+ vector<PlaylistMapping> pmap;
+ nframes_t first_position = max_frames;
+
set<PlaylistState, lt_playlist> freezelist;
pair<set<PlaylistState, lt_playlist>::iterator,bool> insert_result;
+
+ /* get ordering correct before we cut/copy */
+
+ selection->regions.sort_by_position_and_track ();
for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
+
first_position = min ((*x)->region()->position(), first_position);
if (op == Cut || op == Clear) {
- AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region()->playlist());
+ boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist>((*x)->region()->playlist());
+
if (pl) {
PlaylistState before;
before.before = &pl->get_state();
insert_result = freezelist.insert (before);
-
+
if (insert_result.second) {
pl->freeze ();
}
}
}
+
+ TimeAxisView* tv = &(*x)->get_trackview();
+ vector<PlaylistMapping>::iterator z;
+
+ for (z = pmap.begin(); z != pmap.end(); ++z) {
+ if ((*z).tv == tv) {
+ break;
+ }
+ }
+
+ if (z == pmap.end()) {
+ pmap.push_back (PlaylistMapping (tv));
+ }
}
for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ) {
- AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region()->playlist());
- AudioPlaylist* npl;
+ boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist>((*x)->region()->playlist());
+
+ if (!pl) {
+ /* impossible, but this handles it for the future */
+ continue;
+ }
+
+ TimeAxisView& tv = (*x)->get_trackview();
+ boost::shared_ptr<AudioPlaylist> npl;
RegionSelection::iterator tmp;
tmp = x;
++tmp;
- if (pl) {
-
- PlaylistMapping::iterator pi = pmap.find (pl);
-
- if (pi == pmap.end()) {
- npl = new AudioPlaylist (*session, "cutlist", true);
- npl->freeze();
- pmap[pl] = npl;
- } else {
- npl = pi->second;
- }
-
- // FIXME
- boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>((*x)->region());
- switch (op) {
- case Cut:
- if (!ar) break;
-
- npl->add_region (RegionFactory::create (ar), (*x)->region()->position() - first_position);
- pl->remove_region (((*x)->region()));
- break;
-
- case Copy:
- if (!ar) break;
-
- npl->add_region (RegionFactory::create (ar), (*x)->region()->position() - first_position);
- break;
-
- case Clear:
- pl->remove_region (((*x)->region()));
+ vector<PlaylistMapping>::iterator z;
+
+ for (z = pmap.begin(); z != pmap.end(); ++z) {
+ if ((*z).tv == &tv) {
break;
}
}
+
+ assert (z != pmap.end());
+
+ if (!(*z).pl) {
+ npl = boost::dynamic_pointer_cast<AudioPlaylist> (PlaylistFactory::create (*session, "cutlist", true));
+ npl->freeze();
+ (*z).pl = npl;
+ } else {
+ npl = (*z).pl;
+ }
+
+ boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>((*x)->region());
+
+ switch (op) {
+ case Cut:
+ if (!ar) break;
+
+ npl->add_region (RegionFactory::create (ar), (*x)->region()->position() - first_position);
+ pl->remove_region (((*x)->region()));
+ break;
+
+ case Copy:
+ if (!ar) break;
+
+ npl->add_region (RegionFactory::create (ar), (*x)->region()->position() - first_position);
+ break;
+
+ case Clear:
+ pl->remove_region (((*x)->region()));
+ break;
+ }
x = tmp;
}
-
- list<Playlist*> foo;
-
- for (PlaylistMapping::iterator i = pmap.begin(); i != pmap.end(); ++i) {
- foo.push_back (i->second);
+
+ list<boost::shared_ptr<Playlist> > foo;
+
+ /* the pmap is in the same order as the tracks in which selected regions occured */
+
+ for (vector<PlaylistMapping>::iterator i = pmap.begin(); i != pmap.end(); ++i) {
+ (*i).pl->thaw();
+ foo.push_back ((*i).pl);
}
-
+
if (!foo.empty()) {
cut_buffer->set (foo);
}
TrackSelection::iterator i;
size_t nth;
+ /* get everything in the correct order */
+
+ sort_track_selection ();
+
for (nth = 0, i = selection->tracks.begin(); i != selection->tracks.end(); ++i, ++nth) {
-
+
/* undo/redo is handled by individual tracks */
if ((*i)->paste (position, times, *cut_buffer, nth)) {
commit = true;
}
}
-
+
if (commit) {
commit_reversible_command ();
}
TreeModel::iterator i = selected->get_selected();
NamedSelection* ns = (*i)[named_selection_columns.selection];
- list<Playlist*>::iterator chunk;
- list<Playlist*>::iterator tmp;
+ list<boost::shared_ptr<Playlist> >::iterator chunk;
+ list<boost::shared_ptr<Playlist> >::iterator tmp;
chunk = ns->playlists.begin();
begin_reversible_command (_("paste chunk"));
+
+ sort_track_selection ();
for (t = selection->tracks.begin(); t != selection->tracks.end(); ++t) {
AudioTimeAxisView* atv;
- Playlist* pl;
- AudioPlaylist* apl;
+ boost::shared_ptr<Playlist> pl;
+ boost::shared_ptr<AudioPlaylist> apl;
if ((atv = dynamic_cast<AudioTimeAxisView*> (*t)) == 0) {
continue;
if ((pl = atv->playlist()) == 0) {
continue;
}
-
- if ((apl = dynamic_cast<AudioPlaylist*> (pl)) == 0) {
+
+ if ((apl = boost::dynamic_pointer_cast<AudioPlaylist> (pl)) == 0) {
continue;
}
++tmp;
XMLNode &before = apl->get_state();
- apl->paste (**chunk, edit_cursor->current_frame, times);
+ apl->paste (*chunk, edit_cursor->current_frame, times);
session->add_command(new MementoCommand<AudioPlaylist>(*apl, &before, &apl->get_state()));
if (tmp != ns->playlists.end()) {
void
Editor::duplicate_some_regions (RegionSelection& regions, float times)
{
- Playlist *playlist;
+ boost::shared_ptr<Playlist> playlist;
RegionSelection sel = regions; // clear (below) will clear the argument list
begin_reversible_command (_("duplicate region"));
return;
}
- Playlist *playlist;
+ boost::shared_ptr<Playlist> playlist;
vector<boost::shared_ptr<AudioRegion> > new_regions;
vector<boost::shared_ptr<AudioRegion> >::iterator ri;
{
/* reset all selected points to the relevant default value */
- cerr << "point selection has " << selection->points.size() << " entries\n";
-
for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
}
void
-Editor::clear_playlist (Playlist& playlist)
+Editor::clear_playlist (boost::shared_ptr<Playlist> playlist)
{
begin_reversible_command (_("clear playlist"));
- XMLNode &before = playlist.get_state();
- playlist.clear ();
- XMLNode &after = playlist.get_state();
- session->add_command (new MementoCommand<Playlist>(playlist, &before, &after));
+ XMLNode &before = playlist->get_state();
+ playlist->clear ();
+ XMLNode &after = playlist->get_state();
+ session->add_command (new MementoCommand<Playlist>(*playlist.get(), &before, &after));
commit_reversible_command ();
}
void
Editor::nudge_track (bool use_edit_cursor, bool forwards)
{
- Playlist *playlist;
+ boost::shared_ptr<Playlist> playlist;
nframes_t distance;
nframes_t next_distance;
nframes_t start;
if (!arv)
continue;
- Playlist* playlist = arv->region()->playlist();
+ boost::shared_ptr<Playlist> playlist = arv->region()->playlist();
RegionSelection::iterator tmp;
}
}
}
+
+void
+Editor::set_fade_in_shape (AudioRegion::FadeShape shape)
+{
+ begin_reversible_command (_("set fade in shape"));
+
+ for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
+ AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
+
+ if (!tmp) {
+ return;
+ }
+
+ AutomationList& alist = tmp->audio_region()->fade_in();
+ XMLNode &before = alist.get_state();
+
+ tmp->audio_region()->set_fade_in_shape (shape);
+
+ XMLNode &after = alist.get_state();
+ session->add_command(new MementoCommand<AutomationList>(alist, &before, &after));
+ }
+
+ commit_reversible_command ();
+}
+
+void
+Editor::set_fade_out_shape (AudioRegion::FadeShape shape)
+{
+ begin_reversible_command (_("set fade out shape"));
+
+ for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
+ AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
+
+ if (!tmp) {
+ return;
+ }
+
+ AutomationList& alist = tmp->audio_region()->fade_out();
+ XMLNode &before = alist.get_state();
+
+ tmp->audio_region()->set_fade_out_shape (shape);
+
+ XMLNode &after = alist.get_state();
+ session->add_command(new MementoCommand<AutomationList>(alist, &before, &after));
+ }
+
+ commit_reversible_command ();
+}
+
+void
+Editor::set_fade_in_active (bool yn)
+{
+ begin_reversible_command (_("set fade in active"));
+
+ for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
+ AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
+
+ if (!tmp) {
+ return;
+ }
+
+
+ boost::shared_ptr<AudioRegion> ar (tmp->audio_region());
+
+ XMLNode &before = ar->get_state();
+
+ ar->set_fade_in_active (yn);
+
+ XMLNode &after = ar->get_state();
+ session->add_command(new MementoCommand<AudioRegion>(*ar, &before, &after));
+ }
+}
+
+void
+Editor::set_fade_out_active (bool yn)
+{
+ begin_reversible_command (_("set fade out active"));
+
+ for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
+ AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
+
+ if (!tmp) {
+ return;
+ }
+
+ boost::shared_ptr<AudioRegion> ar (tmp->audio_region());
+
+ XMLNode &before = ar->get_state();
+
+ ar->set_fade_out_active (yn);
+
+ XMLNode &after = ar->get_state();
+ session->add_command(new MementoCommand<AudioRegion>(*ar, &before, &after));
+ }
+}
+