#include "ardour/transient_detector.h"
#include "ardour/dB.h"
#include "ardour/quantize.h"
+#include "ardour/strip_silence.h"
#include "ardour_ui.h"
#include "editor.h"
#include "gui_thread.h"
#include "keyboard.h"
#include "utils.h"
+#include "strip_silence_dialog.h"
#include "i18n.h"
_new_regionviews_show_envelope = false;
}
-
-/** Remove `clicked_regionview' */
-void
-Editor::remove_clicked_region ()
-{
- if (clicked_routeview == 0 || clicked_regionview == 0) {
- return;
- }
-
- boost::shared_ptr<Playlist> playlist = clicked_routeview->playlist();
-
- begin_reversible_command (_("remove region"));
- XMLNode &before = playlist->get_state();
- playlist->remove_region (clicked_regionview->region());
- XMLNode &after = playlist->get_state();
- session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
- commit_reversible_command ();
-}
-
-
-/** Remove the selected regions */
-void
-Editor::remove_selected_regions ()
-{
- RegionSelection rs;
- get_regions_for_action (rs);
-
- if (!session) {
- return;
- }
-
- if (rs.empty()) {
- return;
- }
-
- begin_reversible_command (_("remove region"));
-
- list<boost::shared_ptr<Region> > regions_to_remove;
-
- for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
- // we can't just remove the region(s) in this loop because
- // this removes them from the RegionSelection, and they thus
- // disappear from underneath the iterator, and the ++i above
- // SEGVs in a puzzling fashion.
-
- // so, first iterate over the regions to be removed from rs and
- // add them to the regions_to_remove list, and then
- // iterate over the list to actually remove them.
-
- regions_to_remove.push_back ((*i)->region());
- }
-
- for (list<boost::shared_ptr<Region> >::iterator rl = regions_to_remove.begin(); rl != regions_to_remove.end(); ++rl) {
- boost::shared_ptr<Playlist> playlist = (*rl)->playlist();
- if (!playlist) {
- // is this check necessary?
- continue;
- }
-
- XMLNode &before = playlist->get_state();
- playlist->remove_region (*rl);
- XMLNode &after = playlist->get_state();
- session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
- }
-
- commit_reversible_command ();
-}
-
boost::shared_ptr<Region>
Editor::select_region_for_operation (int dir, TimeAxisView **tv)
{
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 ()
{
PlaylistMapping (TimeAxisView* tvp) : tv (tvp) {}
};
+/** Remove `clicked_regionview' */
+void
+Editor::remove_clicked_region ()
+{
+ if (clicked_routeview == 0 || clicked_regionview == 0) {
+ return;
+ }
+
+ boost::shared_ptr<Playlist> playlist = clicked_routeview->playlist();
+
+ begin_reversible_command (_("remove region"));
+ XMLNode &before = playlist->get_state();
+ playlist->remove_region (clicked_regionview->region());
+ XMLNode &after = playlist->get_state();
+ session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
+ commit_reversible_command ();
+}
+
+
+/** Remove the selected regions */
+void
+Editor::remove_selected_regions ()
+{
+ RegionSelection rs;
+ get_regions_for_action (rs);
+
+ if (!session) {
+ return;
+ }
+
+ if (rs.empty()) {
+ return;
+ }
+
+ begin_reversible_command (_("remove region"));
+
+ list<boost::shared_ptr<Region> > regions_to_remove;
+
+ for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
+ // we can't just remove the region(s) in this loop because
+ // this removes them from the RegionSelection, and they thus
+ // disappear from underneath the iterator, and the ++i above
+ // SEGVs in a puzzling fashion.
+
+ // so, first iterate over the regions to be removed from rs and
+ // add them to the regions_to_remove list, and then
+ // iterate over the list to actually remove them.
+
+ regions_to_remove.push_back ((*i)->region());
+ }
+
+ vector<PlaylistState> playlists;
+
+ for (list<boost::shared_ptr<Region> >::iterator rl = regions_to_remove.begin(); rl != regions_to_remove.end(); ++rl) {
+
+ boost::shared_ptr<Playlist> playlist = (*rl)->playlist();
+
+ if (!playlist) {
+ // is this check necessary?
+ continue;
+ }
+
+ vector<PlaylistState>::iterator i;
+
+ //only take state if this is a new playlist.
+ for (i = playlists.begin(); i != playlists.end(); ++i) {
+ if ((*i).playlist == playlist) {
+ break;
+ }
+ }
+
+ if (i == playlists.end()) {
+
+ PlaylistState before;
+ before.playlist = playlist;
+ before.before = &playlist->get_state();
+
+ playlist->freeze ();
+ playlists.push_back(before);
+ }
+
+ playlist->remove_region (*rl);
+ }
+
+ vector<PlaylistState>::iterator pl;
+
+ for (pl = playlists.begin(); pl != playlists.end(); ++pl) {
+ (*pl).playlist->thaw ();
+ session->add_command(new MementoCommand<Playlist>(*(*pl).playlist, (*pl).before, &(*pl).playlist->get_state()));
+ }
+
+ commit_reversible_command ();
+}
/** Cut, copy or clear selected regions.
* @param op Operation (Cut, Copy or Clear)
*/
void
Editor::cut_copy_regions (CutCopyOp op, RegionSelection& rs)
-{
+{
/* 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.
*/
boost::shared_ptr<Playlist> pl = (*x)->region()->playlist();
if (pl) {
+ set<PlaylistState, lt_playlist>::iterator fl;
- PlaylistState before;
- before.playlist = pl;
- before.before = &pl->get_state();
-
- insert_result = freezelist.insert (before);
-
- if (insert_result.second) {
+ //only take state if this is a new playlist.
+ for (fl = freezelist.begin(); fl != freezelist.end(); ++fl) {
+ if ((*fl).playlist == pl) {
+ break;
+ }
+ }
+
+ if (fl == freezelist.end()) {
+ PlaylistState before;
+ before.playlist = pl;
+ before.before = &pl->get_state();
pl->freeze ();
+ insert_result = freezelist.insert (before);
}
}
}
apply_filter (rev, _("reverse regions"));
}
+void
+Editor::strip_region_silence ()
+{
+ if (!session) {
+ return;
+ }
+
+ RegionSelection rs;
+ get_regions_for_action (rs);
+
+ if (rs.empty()) {
+ return;
+ }
+
+ std::list<boost::shared_ptr<AudioRegion> > ar;
+
+ for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
+ AudioRegionView* const arv = dynamic_cast<AudioRegionView*> (*i);
+ if (arv) {
+ ar.push_back (arv->audio_region ());
+ }
+ }
+
+ StripSilenceDialog d (ar);
+ int const r = d.run ();
+
+ if (r == Gtk::RESPONSE_OK) {
+ StripSilence s (*session, d.threshold (), d.minimum_length (), d.fade_length ());
+ apply_filter (s, _("strip silence"));
+ }
+}
+
void
Editor::quantize_region ()
if (arv->audio_region()->apply (filter) == 0) {
XMLNode &before = playlist->get_state();
- playlist->replace_region (arv->region(), filter.results.front(), arv->region()->position());
+
+ if (filter.results.empty ()) {
+
+ /* no regions returned; remove the old one */
+ playlist->remove_region (arv->region ());
+
+ } else {
+
+ std::vector<boost::shared_ptr<Region> >::iterator res = filter.results.begin ();
+
+ /* first region replaces the old one */
+ playlist->replace_region (arv->region(), *res, (*res)->position());
+ ++res;
+
+ /* add the rest */
+ while (res != filter.results.end()) {
+ playlist->add_region (*res, (*res)->position());
+ ++res;
+ }
+
+ }
+
XMLNode &after = playlist->get_state();
session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
} else {
void
Editor::update_region_fade_visibility ()
{
- bool _fade_visibility = Config->get_show_region_fades ();
+ bool _fade_visibility = session->config.get_show_region_fades ();
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
AudioTimeAxisView* v = dynamic_cast<AudioTimeAxisView*>(*i);
void
Editor::update_xfade_visibility ()
{
- _xfade_visibility = Config->get_xfades_visible ();
+ _xfade_visibility = session->config.get_xfades_visible ();
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
AudioTimeAxisView* v = dynamic_cast<AudioTimeAxisView*>(*i);
}
}
-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 */