summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/ardour.menus.in2
-rw-r--r--gtk2_ardour/editor.h3
-rw-r--r--gtk2_ardour/editor_actions.cc2
-rw-r--r--gtk2_ardour/editor_ops.cc12
-rw-r--r--gtk2_ardour/editor_selection.cc3
-rw-r--r--gtk2_ardour/route_time_axis.cc13
-rw-r--r--gtk2_ardour/route_time_axis.h2
-rw-r--r--libs/ardour/ardour/playlist.h1
-rw-r--r--libs/ardour/audio_playlist_source.cc29
-rw-r--r--libs/ardour/playlist.cc60
-rw-r--r--libs/ardour/playlist_source.cc21
-rw-r--r--libs/ardour/session_state.cc11
-rw-r--r--libs/ardour/source_factory.cc80
13 files changed, 165 insertions, 74 deletions
diff --git a/gtk2_ardour/ardour.menus.in b/gtk2_ardour/ardour.menus.in
index 62d637058b..d59fcc8f38 100644
--- a/gtk2_ardour/ardour.menus.in
+++ b/gtk2_ardour/ardour.menus.in
@@ -228,7 +228,7 @@
<menuitem action='play-selected-regions'/>
<menuitem action='export-region'/>
<menuitem action='bounce-region'/>
- <menuitem action='join-regions'/>
+ <menuitem action='combine-regions'/>
<menuitem action='analyze-region'/>
<menuitem action='toggle-region-lock'/>
<menuitem action='toggle-region-lock-style'/>
diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
index 83d8b394c3..140235e890 100644
--- a/gtk2_ardour/editor.h
+++ b/gtk2_ardour/editor.h
@@ -1099,7 +1099,8 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
void duplicate_some_regions (RegionSelection&, float times);
void duplicate_selection (float times);
void region_fill_selection ();
- void join_regions ();
+ void combine_regions ();
+ void uncombine_regions ();
void region_fill_track ();
void audition_playlist_region_standalone (boost::shared_ptr<ARDOUR::Region>);
diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc
index 0081a806aa..a45279b6bb 100644
--- a/gtk2_ardour/editor_actions.cc
+++ b/gtk2_ardour/editor_actions.cc
@@ -1372,7 +1372,7 @@ Editor::register_region_actions ()
reg_sens (_region_actions, "play-selected-regions", _("Play"), sigc::mem_fun(*this, &Editor::play_selected_region));
reg_sens (_region_actions, "bounce-region", _("Bounce"), sigc::mem_fun (*this, &Editor::bounce_region_selection));
- reg_sens (_region_actions, "join-regions", _("Join"), sigc::mem_fun (*this, &Editor::join_regions));
+ reg_sens (_region_actions, "combine-regions", _("Combine"), sigc::mem_fun (*this, &Editor::combine_regions));
reg_sens (_region_actions, "analyze-region", _("Spectral Analysis..."), sigc::mem_fun (*this, &Editor::analyze_region_selection));
diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc
index 07e68faf3d..a6bba7d76c 100644
--- a/gtk2_ardour/editor_ops.cc
+++ b/gtk2_ardour/editor_ops.cc
@@ -6403,7 +6403,7 @@ Editor::toggle_region_mute ()
}
void
-Editor::join_regions ()
+Editor::combine_regions ()
{
/* foreach track with selected regions, take all selected regions
and join them into a new region containing the subregions (as a
@@ -6413,6 +6413,10 @@ Editor::join_regions ()
typedef set<RouteTimeAxisView*> RTVS;
RTVS tracks;
+ if (selection->regions.empty()) {
+ return;
+ }
+
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(&(*i)->get_time_axis_view());
@@ -6421,8 +6425,12 @@ Editor::join_regions ()
}
}
+ begin_reversible_command (_("combine regions"));
+
for (RTVS::iterator i = tracks.begin(); i != tracks.end(); ++i) {
- (*i)->join_regions ();
+ (*i)->combine_regions ();
}
+
+ commit_reversible_command ();
}
diff --git a/gtk2_ardour/editor_selection.cc b/gtk2_ardour/editor_selection.cc
index 7998a4bfa6..3ec11ea410 100644
--- a/gtk2_ardour/editor_selection.cc
+++ b/gtk2_ardour/editor_selection.cc
@@ -957,7 +957,6 @@ Editor::sensitize_the_right_region_actions ()
if (!selection->time.empty()) {
_region_actions->get_action("split-region")->set_sensitive (true);
}
-
return;
} else if (mouse_mode != MouseObject) {
@@ -1063,9 +1062,11 @@ Editor::sensitize_the_right_region_actions ()
_region_actions->get_action("show-region-list-editor")->set_sensitive (false);
_region_actions->get_action("show-region-properties")->set_sensitive (false);
_region_actions->get_action("rename-region")->set_sensitive (false);
+ _region_actions->get_action("combine-regions")->set_sensitive (true);
} else if (rs.size() == 1) {
_region_actions->get_action("add-range-markers-from-region")->set_sensitive (false);
_region_actions->get_action("close-region-gaps")->set_sensitive (false);
+ _region_actions->get_action("combine-regions")->set_sensitive (false);
}
if (!have_midi) {
diff --git a/gtk2_ardour/route_time_axis.cc b/gtk2_ardour/route_time_axis.cc
index 81dbefcd29..119f1814d3 100644
--- a/gtk2_ardour/route_time_axis.cc
+++ b/gtk2_ardour/route_time_axis.cc
@@ -2486,7 +2486,7 @@ void add_region_to_list (RegionView* rv, Playlist::RegionList* l, uint32_t* max_
}
void
-RouteTimeAxisView::join_regions ()
+RouteTimeAxisView::combine_regions ()
{
assert (is_track());
@@ -2495,11 +2495,16 @@ RouteTimeAxisView::join_regions ()
}
Playlist::RegionList selected_regions;
+ boost::shared_ptr<Playlist> playlist = track()->playlist();
uint32_t max_level = 0;
_view->foreach_selected_regionview (sigc::bind (sigc::ptr_fun (add_region_to_list), &selected_regions, &max_level));
- uint32_t num_joined_regions = track()->playlist()->count_joined_regions();
- string name = string_compose (_("%1 combine-%2 (%3)"), track()->playlist()->name(), num_joined_regions+1, max_level+1);
- track()->playlist()->join (selected_regions, name);
+ uint32_t num_joined_regions = playlist->count_joined_regions();
+ string name = string_compose (_("%1 compound-%2 (%3)"), playlist->name(), num_joined_regions+1, max_level+1);
+
+
+ playlist->clear_changes ();
+ playlist->join (selected_regions, name);
+ _session->add_command (new StatefulDiffCommand (playlist));
}
diff --git a/gtk2_ardour/route_time_axis.h b/gtk2_ardour/route_time_axis.h
index d596de3df7..b06b56fc67 100644
--- a/gtk2_ardour/route_time_axis.h
+++ b/gtk2_ardour/route_time_axis.h
@@ -94,7 +94,7 @@ public:
/* Editing operations */
void cut_copy_clear (Selection&, Editing::CutCopyOp);
bool paste (ARDOUR::framepos_t, float times, Selection&, size_t nth);
- void join_regions ();
+ void combine_regions ();
void toggle_automation_track (const Evoral::Parameter& param);
/* The editor calls these when mapping an operation across multiple tracks */
diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h
index 3234e4c108..72155d9981 100644
--- a/libs/ardour/ardour/playlist.h
+++ b/libs/ardour/ardour/playlist.h
@@ -376,6 +376,7 @@ public:
void timestamp_layer_op (boost::shared_ptr<Region>);
void _split_region (boost::shared_ptr<Region>, framepos_t position);
+ void load_nested_sources (const XMLNode& node);
};
} /* namespace ARDOUR */
diff --git a/libs/ardour/audio_playlist_source.cc b/libs/ardour/audio_playlist_source.cc
index 2160b9bd3a..882a1710e7 100644
--- a/libs/ardour/audio_playlist_source.cc
+++ b/libs/ardour/audio_playlist_source.cc
@@ -34,6 +34,7 @@
#include "ardour/audio_playlist_source.h"
#include "ardour/audioregion.h"
#include "ardour/debug.h"
+#include "ardour/filename_extensions.h"
#include "ardour/session.h"
#include "ardour/session_directory.h"
#include "ardour/session_playlists.h"
@@ -52,14 +53,12 @@ AudioPlaylistSource::AudioPlaylistSource (Session& s, const std::string& name, b
, PlaylistSource (s, name, p, DataType::AUDIO, begin, len, flags)
, _playlist_channel (chn)
{
- _peak_path = Glib::build_filename (_session.session_directory().peak_path().to_string(), name);
-
AudioSource::_length = len;
ensure_buffers_for_level (_level);
}
AudioPlaylistSource::AudioPlaylistSource (Session& s, const XMLNode& node)
- : Source (s, DataType::AUDIO, "toBeRenamed")
+ : Source (s, node)
, AudioSource (s, node)
, PlaylistSource (s, node)
{
@@ -91,7 +90,6 @@ AudioPlaylistSource::get_state ()
snprintf (buf, sizeof (buf), "%" PRIu32, _playlist_channel);
node.add_property ("channel", buf);
- node.add_property ("peak-path", _peak_path);
return node;
}
@@ -124,12 +122,6 @@ AudioPlaylistSource::set_state (const XMLNode& node, int version, bool with_desc
sscanf (prop->value().c_str(), "%" PRIu32, &_playlist_channel);
- if ((prop = node.property (X_("peak-path"))) == 0) {
- throw failed_constructor ();
- }
-
- _peak_path = prop->value ();
-
ensure_buffers_for_level (_level);
return 0;
@@ -224,23 +216,12 @@ AudioPlaylistSource::sample_rate () const
int
AudioPlaylistSource::setup_peakfile ()
{
- /* the peak data is setup once and once only
- */
-
- if (!Glib::file_test (_peak_path, Glib::FILE_TEST_EXISTS)) {
- /* the 2nd argument here will be passed
- in to ::peak_path, and is irrelevant
- since our peak file path is fixed and
- not dependent on anything.
- */
- return initialize_peakfile (false, string());
- }
-
- return 0;
+ _peak_path = Glib::build_filename (_session.session_directory().peak_path().to_string(), name() + ARDOUR::peakfile_suffix);
+ return initialize_peakfile (false, string());
}
string
-AudioPlaylistSource::peak_path (string /*audio_path*/)
+AudioPlaylistSource::peak_path (string /*audio_path_IGNORED*/)
{
return _peak_path;
}
diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc
index fd9af56e80..9ceb11fe51 100644
--- a/libs/ardour/playlist.cc
+++ b/libs/ardour/playlist.cc
@@ -2221,6 +2221,26 @@ Playlist::update (const RegionListProperty::ChangeRecord& change)
thaw ();
}
+void
+Playlist::load_nested_sources (const XMLNode& node)
+{
+ XMLNodeList nlist;
+ XMLNodeConstIterator niter;
+
+ nlist = node.children();
+
+ for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
+ if ((*niter)->name() == "Source") {
+ try {
+ SourceFactory::create (_session, **niter, true);
+ }
+ catch (failed_constructor& err) {
+ error << string_compose (_("Cannot reconstruct nested source for playlist %1"), name()) << endmsg;
+ }
+ }
+ }
+}
+
int
Playlist::set_state (const XMLNode& node, int version)
{
@@ -2264,6 +2284,19 @@ Playlist::set_state (const XMLNode& node, int version)
nlist = node.children();
+ /* find the "Nested" node, if any, and recreate the PlaylistSources
+ listed there
+ */
+
+ for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
+ child = *niter;
+
+ if (child->name() == "Nested") {
+ load_nested_sources (*child);
+ break;
+ }
+ }
+
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
child = *niter;
@@ -2292,7 +2325,7 @@ Playlist::set_state (const XMLNode& node, int version)
error << _("Playlist: cannot create region from XML") << endmsg;
continue;
}
-
+
add_region (region, region->position(), 1.0);
@@ -2348,6 +2381,31 @@ Playlist::state (bool full_state)
if (full_state) {
RegionLock rlock (this, false);
+ XMLNode* nested_node = 0;
+
+ for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
+ if ((*i)->max_source_level() > 0) {
+
+ if (!nested_node) {
+ nested_node = new XMLNode (X_("Nested"));
+ }
+
+ /* region is compound - get its playlist and
+ store that before we list the region that
+ needs it ...
+ */
+
+ const SourceList& sl ((*i)->sources());
+
+ for (SourceList::const_iterator s = sl.begin(); s != sl.end(); ++s) {
+ nested_node->add_child_nocopy ((*s)->get_state ());
+ }
+ }
+ }
+
+ if (nested_node) {
+ node->add_child_nocopy (*nested_node);
+ }
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
node->add_child_nocopy ((*i)->get_state());
diff --git a/libs/ardour/playlist_source.cc b/libs/ardour/playlist_source.cc
index 7ac175959c..a1597a76d2 100644
--- a/libs/ardour/playlist_source.cc
+++ b/libs/ardour/playlist_source.cc
@@ -32,6 +32,7 @@
#include "ardour/playlist.h"
#include "ardour/playlist_source.h"
+#include "ardour/playlist_factory.h"
#include "ardour/session.h"
#include "ardour/session_playlists.h"
#include "ardour/source_factory.h"
@@ -84,26 +85,38 @@ PlaylistSource::add_state (XMLNode& node)
node.add_property ("offset", buf);
snprintf (buf, sizeof (buf), "%" PRIu64, _playlist_length);
node.add_property ("length", buf);
+
+ node.add_child_nocopy (_playlist->get_state());
}
int
PlaylistSource::set_state (const XMLNode& node, int version)
{
- /* get playlist ID */
+ /* check that we have a playlist ID */
const XMLProperty *prop = node.property (X_("playlist"));
if (!prop) {
+ error << _("No playlist ID in PlaylistSource XML!") << endmsg;
throw failed_constructor ();
}
- PBD::ID id (prop->value());
+ /* create playlist from child node */
+
+ XMLNodeList nlist;
+ XMLNodeConstIterator niter;
- /* get playlist */
+ nlist = node.children();
- boost::shared_ptr<Playlist> p = _session.playlists->by_id (id);
+ for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
+ if ((*niter)->name() == "Playlist") {
+ _playlist = PlaylistFactory::create (_session, **niter, true, false);
+ break;
+ }
+ }
if (!_playlist) {
+ error << _("No playlist node in PlaylistSource XML!") << endmsg;
throw failed_constructor ();
}
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index 604fc4bc52..82c2d5a31c 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -1056,20 +1056,23 @@ Session::state(bool full_state)
for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
- /* Don't save information about non-destructive file sources that are empty
- and unused by any regions.
+ /* Don't save information about non-file Sources, or
+ * about non-destructive file sources that are empty
+ * and unused by any regions.
*/
boost::shared_ptr<FileSource> fs;
+
if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
+
if (!fs->destructive()) {
if (fs->empty() && !fs->used()) {
continue;
}
}
+
+ child->add_child_nocopy (siter->second->get_state());
}
-
- child->add_child_nocopy (siter->second->get_state());
}
}
diff --git a/libs/ardour/source_factory.cc b/libs/ardour/source_factory.cc
index 4d3f02b1dc..57f0fdc1ec 100644
--- a/libs/ardour/source_factory.cc
+++ b/libs/ardour/source_factory.cc
@@ -147,44 +147,66 @@ SourceFactory::create (Session& s, const XMLNode& node, bool defer_peaks)
if (type == DataType::AUDIO) {
- try {
- Source* src = new SndFileSource (s, node);
-#ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
- // boost_debug_shared_ptr_mark_interesting (src, "Source");
-#endif
- boost::shared_ptr<Source> ret (src);
- if (setup_peakfile (ret, defer_peaks)) {
- return boost::shared_ptr<Source>();
- }
- ret->check_for_analysis_data_on_disk ();
- SourceCreated (ret);
- return ret;
- }
+ /* it could be nested */
- catch (failed_constructor& err) {
+ if (node.property ("playlist") != 0) {
-#ifdef USE_COREAUDIO_FOR_FILES
+ try {
+ boost::shared_ptr<AudioPlaylistSource> ap (new AudioPlaylistSource (s, node));
+
+ if (setup_peakfile (ap, true)) {
+ return boost::shared_ptr<Source>();
+ }
- /* this is allowed to throw */
+ ap->check_for_analysis_data_on_disk ();
+ SourceCreated (ap);
+ return ap;
- Source *src = new CoreAudioSource (s, node);
+ } catch (failed_constructor&) {
+ /* oh well, so much for that then ... */
+ }
+
+ } else {
+
+
+ try {
+ Source* src = new SndFileSource (s, node);
#ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
- // boost_debug_shared_ptr_mark_interesting (src, "Source");
+ // boost_debug_shared_ptr_mark_interesting (src, "Source");
#endif
- boost::shared_ptr<Source> ret (src);
-
- if (setup_peakfile (ret, defer_peaks)) {
- return boost::shared_ptr<Source>();
+ boost::shared_ptr<Source> ret (src);
+ if (setup_peakfile (ret, defer_peaks)) {
+ return boost::shared_ptr<Source>();
+ }
+ ret->check_for_analysis_data_on_disk ();
+ SourceCreated (ret);
+ return ret;
}
- ret->check_for_analysis_data_on_disk ();
- SourceCreated (ret);
- return ret;
+ catch (failed_constructor& err) {
+
+#ifdef USE_COREAUDIO_FOR_FILES
+
+ /* this is allowed to throw */
+
+ Source *src = new CoreAudioSource (s, node);
+#ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
+ // boost_debug_shared_ptr_mark_interesting (src, "Source");
+#endif
+ boost::shared_ptr<Source> ret (src);
+
+ if (setup_peakfile (ret, defer_peaks)) {
+ return boost::shared_ptr<Source>();
+ }
+
+ ret->check_for_analysis_data_on_disk ();
+ SourceCreated (ret);
+ return ret;
#else
- throw; // rethrow
+ throw; // rethrow
#endif
+ }
}
-
} else if (type == DataType::MIDI) {
boost::shared_ptr<SMFSource> src (new SMFSource (s, node));
src->load_model (true, true);
@@ -348,9 +370,7 @@ SourceFactory::createFromPlaylist (DataType type, Session& s, boost::shared_ptr<
}
ret->check_for_analysis_data_on_disk ();
-
- /* we never announce these sources */
-
+ SourceCreated (ret);
return ret;
}
}