summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorSakari Bergen <sakari.bergen@beatwaves.net>2008-10-11 10:14:51 +0000
committerSakari Bergen <sakari.bergen@beatwaves.net>2008-10-11 10:14:51 +0000
commit98389f7da420ee205f6827b7df4db3ea0802f751 (patch)
tree28a28cf591b3d90a7eb60f422eee95e5ebfed6dc /libs
parent01b1790c98f9ee6739681f1dc8fe529c3ca7160a (diff)
Region export dialog: Make export channel and -selector polymorphic, add the region related classes and a dialog specialization
git-svn-id: svn://localhost/ardour2/branches/3.0@3915 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
-rw-r--r--libs/ardour/SConscript1
-rw-r--r--libs/ardour/ardour/export_channel.h144
-rw-r--r--libs/ardour/ardour/export_channel_configuration.h22
-rw-r--r--libs/ardour/ardour/export_profile_manager.h4
-rw-r--r--libs/ardour/ardour/export_timespan.h9
-rw-r--r--libs/ardour/export_channel.cc142
-rw-r--r--libs/ardour/export_channel_configuration.cc45
-rw-r--r--libs/ardour/export_profile_manager.cc20
-rw-r--r--libs/ardour/export_timespan.cc6
9 files changed, 333 insertions, 60 deletions
diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript
index 2abf18cd55..162994fc81 100644
--- a/libs/ardour/SConscript
+++ b/libs/ardour/SConscript
@@ -70,6 +70,7 @@ element_importer.cc
element_import_handler.cc
enums.cc
event_type_map.cc
+export_channel.cc
export_channel_configuration.cc
export_file_io.cc
export_filename.cc
diff --git a/libs/ardour/ardour/export_channel.h b/libs/ardour/ardour/export_channel.h
new file mode 100644
index 0000000000..dd351bfd70
--- /dev/null
+++ b/libs/ardour/ardour/export_channel.h
@@ -0,0 +1,144 @@
+/*
+ Copyright (C) 2008 Paul Davis
+ Author: Sakari Bergen
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __ardour_export_channel_h__
+#define __ardour_export_channel_h__
+
+#include <ardour/audioregion.h>
+#include <ardour/audio_track.h>
+#include <ardour/buffer_set.h>
+
+#include <set>
+
+#include <boost/shared_ptr.hpp>
+#include <sigc++/signal.h>
+
+namespace ARDOUR {
+
+class Session;
+
+/// Export channel base class interface for different source types
+class ExportChannel
+{
+ public:
+ virtual void read (Sample * data, nframes_t frames) const = 0;
+ virtual bool empty () const = 0;
+
+ /// Adds state to node passed
+ virtual void get_state (XMLNode * node) const = 0;
+
+ /// Sets state from node passed
+ virtual void set_state (XMLNode * node, Session & session) = 0;
+
+ // Operator< must be defined for usage in e.g. std::map or std::set to disallow duplicates when necessary
+ virtual bool operator< (ExportChannel const & other) const = 0;
+};
+
+/// Safe pointer for storing ExportChannels in ordered STL containers
+class ExportChannelPtr : public boost::shared_ptr<ExportChannel>
+{
+ public:
+ ExportChannelPtr () {}
+ template<typename Y> explicit ExportChannelPtr (Y * ptr) : boost::shared_ptr<ExportChannel> (ptr) {}
+
+ bool operator< (ExportChannelPtr const & other) const { return **this < *other; }
+};
+
+/// Basic export channel that reads from AudioPorts
+class PortExportChannel : public ExportChannel
+{
+ public:
+ typedef std::set<AudioPort *> PortSet;
+
+ PortExportChannel () {}
+
+ virtual void read (Sample * data, nframes_t frames) const;
+ virtual bool empty () const { return ports.empty(); }
+
+ virtual void get_state (XMLNode * node) const;
+ virtual void set_state (XMLNode * node, Session & session);
+
+ virtual bool operator< (ExportChannel const & other) const;
+
+ void add_port (AudioPort * port) { ports.insert (port); }
+ PortSet const & get_ports () { return ports; }
+
+ private:
+ PortSet ports;
+};
+
+/// Handles RegionExportChannels and does actual reading from region
+class RegionExportChannelFactory : public sigc::trackable
+{
+ public:
+ enum Type {
+ Raw,
+ Processed
+ };
+
+ RegionExportChannelFactory (Session * session, AudioRegion const & region, AudioTrack & track, Type type);
+
+ ExportChannelPtr create (uint32_t channel);
+ void read (uint32_t channel, Sample * data, nframes_t frames_to_read);
+
+ private:
+
+ int new_cycle_started () { buffers_up_to_date = false; return 0; }
+ void update_buffers (nframes_t frames);
+
+ AudioRegion const & region;
+ AudioTrack & track;
+ Type type;
+
+ nframes_t frames_per_cycle;
+ size_t n_channels;
+ BufferSet buffers;
+ bool buffers_up_to_date;
+ nframes_t region_start;
+ nframes_t position;
+};
+
+/// Export channel that reads from region channel
+class RegionExportChannel : public ExportChannel
+{
+ friend class RegionExportChannelFactory;
+
+ public:
+ virtual void read (Sample * data, nframes_t frames_to_read) const { factory.read (channel, data, frames_to_read); }
+ virtual void get_state (XMLNode * node) const {};
+ virtual void set_state (XMLNode * node, Session & session) {};
+ virtual bool empty () const { return false; }
+ // Region export should never have duplicate channels, so there need not be any semantics here
+ virtual bool operator< (ExportChannel const & other) const { return this < &other; }
+
+ private:
+
+ RegionExportChannel (RegionExportChannelFactory & factory, uint32_t channel) :
+ factory (factory),
+ channel (channel)
+ {}
+
+ RegionExportChannelFactory & factory;
+ uint32_t channel;
+};
+
+} // namespace ARDOUR
+
+#endif
diff --git a/libs/ardour/ardour/export_channel_configuration.h b/libs/ardour/ardour/export_channel_configuration.h
index 80ad29b435..7223e29110 100644
--- a/libs/ardour/ardour/export_channel_configuration.h
+++ b/libs/ardour/ardour/export_channel_configuration.h
@@ -21,12 +21,12 @@
#ifndef __ardour_export_channel_configuration_h__
#define __ardour_export_channel_configuration_h__
-#include <set>
#include <list>
#include <glibmm/ustring.h>
#include <sigc++/signal.h>
+#include <ardour/export_channel.h>
#include <ardour/export_status.h>
#include <ardour/ardour.h>
@@ -46,13 +46,6 @@ class ExportProcessor;
class ExportTimespan;
class Session;
-class ExportChannel : public std::set<AudioPort *>
-{
- public:
- void add_port (AudioPort * port) { if (port) { insert (port); } }
- void read_ports (float * data, nframes_t frames) const;
-};
-
class ExportChannelConfiguration
{
private:
@@ -86,20 +79,19 @@ class ExportChannelConfiguration
XMLNode & get_state ();
int set_state (const XMLNode &);
- typedef boost::shared_ptr<ExportChannel const> ChannelPtr;
- typedef std::list<ChannelPtr> ChannelList;
+ typedef std::list<ExportChannelPtr> ChannelList;
- ChannelList const & get_channels () { return channels; }
- bool all_channels_have_ports ();
+ ChannelList const & get_channels () const { return channels; }
+ bool all_channels_have_ports () const;
ustring name () const { return _name; }
void set_name (ustring name) { _name = name; }
void set_split (bool value) { split = value; }
- bool get_split () { return split; }
- uint32_t get_n_chans () { return channels.size(); }
+ bool get_split () const { return split; }
+ uint32_t get_n_chans () const { return channels.size(); }
- void register_channel (ChannelPtr channel) { channels.push_back (channel); }
+ void register_channel (ExportChannelPtr channel) { channels.push_back (channel); }
void register_file_config (FormatPtr format, FilenamePtr filename) { file_configs.push_back (FileConfig (format, filename)); }
void clear_channels () { channels.clear (); }
diff --git a/libs/ardour/ardour/export_profile_manager.h b/libs/ardour/ardour/export_profile_manager.h
index d2f1c162e0..74035572b0 100644
--- a/libs/ardour/ardour/export_profile_manager.h
+++ b/libs/ardour/ardour/export_profile_manager.h
@@ -144,6 +144,7 @@ class ExportProfileManager
typedef std::list<TimespanStatePtr> TimespanStateList;
void set_selection_range (nframes_t start = 0, nframes_t end = 0);
+ std::string set_single_range (nframes_t start, nframes_t end, Glib::ustring name);
TimespanStateList const & get_timespans () { return check_list (timespans); }
private:
@@ -162,6 +163,9 @@ class ExportProfileManager
boost::shared_ptr<Location> session_range;
boost::shared_ptr<Location> selection_range;
boost::shared_ptr<LocationList> ranges;
+
+ bool single_range_mode;
+ boost::shared_ptr<Location> single_range;
/* Channel Configs */
public:
diff --git a/libs/ardour/ardour/export_timespan.h b/libs/ardour/ardour/export_timespan.h
index e19013e822..38f449a1a5 100644
--- a/libs/ardour/ardour/export_timespan.h
+++ b/libs/ardour/ardour/export_timespan.h
@@ -27,6 +27,7 @@
#include <glibmm/ustring.h>
#include <ardour/export_status.h>
+#include <ardour/export_channel.h>
#include <ardour/ardour.h>
using Glib::ustring;
@@ -41,8 +42,8 @@ class ExportTimespan : public sigc::trackable
{
private:
typedef boost::shared_ptr<ExportTempFile> TempFilePtr;
- typedef std::pair<ExportChannel const, TempFilePtr> ChannelFilePair;
- typedef std::map<ExportChannel const, TempFilePtr> TempFileMap;
+ typedef std::pair<ExportChannelPtr, TempFilePtr> ChannelFilePair;
+ typedef std::map<ExportChannelPtr, TempFilePtr> TempFileMap;
typedef boost::shared_ptr<ExportStatus> ExportStatusPtr;
private:
@@ -59,13 +60,13 @@ class ExportTimespan : public sigc::trackable
void set_range_id (ustring range_id) { _range_id = range_id; }
/// Registers a channel to be read when export starts rolling
- void register_channel (ExportChannel const & channel);
+ void register_channel (ExportChannelPtr channel);
/// "Rewinds" the tempfiles to start reading the beginnings again
void rewind ();
/// Reads data from the tempfile belonging to channel into data
- nframes_t get_data (float * data, nframes_t frames, ExportChannel const & channel);
+ nframes_t get_data (float * data, nframes_t frames, ExportChannelPtr channel);
/// Reads data from each channel and writes to tempfile
int process (nframes_t frames);
diff --git a/libs/ardour/export_channel.cc b/libs/ardour/export_channel.cc
new file mode 100644
index 0000000000..e0242a9f52
--- /dev/null
+++ b/libs/ardour/export_channel.cc
@@ -0,0 +1,142 @@
+/*
+ Copyright (C) 2008 Paul Davis
+ Author: Sakari Bergen
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <ardour/export_channel.h>
+
+#include <ardour/export_failed.h>
+#include <ardour/audioengine.h>
+
+using namespace ARDOUR;
+
+bool
+PortExportChannel::operator< (ExportChannel const & other) const
+{
+ PortExportChannel const * pec;
+ if (!(pec = dynamic_cast<PortExportChannel const *> (&other))) {
+ return this < &other;
+ }
+ return ports < pec->ports;
+}
+
+void
+PortExportChannel::read (Sample * data, nframes_t frames) const
+{
+ memset (data, 0, frames * sizeof (float));
+
+ for (PortSet::const_iterator it = ports.begin(); it != ports.end(); ++it) {
+ if (*it != 0) {
+ Sample* port_buffer = (*it)->get_audio_buffer(frames, 0).data();
+
+ for (uint32_t i = 0; i < frames; ++i) {
+ data[i] += (float) port_buffer[i];
+ }
+ }
+ }
+}
+
+void
+PortExportChannel::get_state (XMLNode * node) const
+{
+ XMLNode * port_node;
+ for (PortSet::const_iterator it = ports.begin(); it != ports.end(); ++it) {
+ if ((port_node = node->add_child ("Port"))) {
+ port_node->add_property ("name", (*it)->name());
+ }
+ }
+}
+
+void
+PortExportChannel::set_state (XMLNode * node, Session & session)
+{
+ XMLProperty * prop;
+ XMLNodeList xml_ports = node->children ("Port");
+ for (XMLNodeList::iterator it = xml_ports.begin(); it != xml_ports.end(); ++it) {
+ if ((prop = (*it)->property ("name"))) {
+ ports.insert (dynamic_cast<AudioPort *> (session.engine().get_port_by_name (prop->value())));
+ }
+ }
+}
+
+RegionExportChannelFactory::RegionExportChannelFactory (Session * session, AudioRegion const & region, AudioTrack & track, Type type) :
+ region (region),
+ track (track),
+ type (type),
+ frames_per_cycle (session->engine().frames_per_cycle ()),
+ buffers_up_to_date (false),
+ region_start (region.position()),
+ position (region_start)
+{
+ switch (type) {
+ case Raw:
+ n_channels = region.n_channels();
+ break;
+ case Processed:
+ n_channels = track.n_outputs().n_audio();
+ break;
+ default:
+ throw ExportFailed ("Unhandled type in ExportChannelFactory constructor");
+ }
+
+ session->ProcessExport.connect (sigc::hide (sigc::mem_fun (*this, &RegionExportChannelFactory::new_cycle_started)));
+
+ buffers.set_count (ChanCount (DataType::AUDIO, n_channels));
+ buffers.ensure_buffers (DataType::AUDIO, n_channels, frames_per_cycle);
+}
+
+ExportChannelPtr
+RegionExportChannelFactory::create (uint32_t channel)
+{
+ assert (channel < n_channels);
+ return ExportChannelPtr (new RegionExportChannel (*this, channel));
+}
+
+void
+RegionExportChannelFactory::read (uint32_t channel, Sample * data, nframes_t frames_to_read)
+{
+ assert (channel < n_channels);
+ assert (frames_to_read <= frames_per_cycle);
+
+ if (!buffers_up_to_date) {
+ update_buffers(frames_to_read);
+ buffers_up_to_date = true;
+ }
+
+ memcpy (data, buffers.get_audio (channel).data(), frames_to_read * sizeof (Sample));
+}
+
+void
+RegionExportChannelFactory::update_buffers (nframes_t frames)
+{
+ switch (type) {
+ case Raw:
+ for (size_t channel = 0; channel < n_channels; ++channel) {
+ region.read (buffers.get_audio (channel).data(), position - region_start, frames, channel);
+ }
+ break;
+ case Processed:
+ std::cout << "exporting " << frames << " frames from position " << position << std::endl;
+ track.export_stuff (buffers, position, frames);
+ break;
+ default:
+ throw ExportFailed ("Unhandled type in ExportChannelFactory::update_buffers");
+ }
+
+ position += frames;
+}
diff --git a/libs/ardour/export_channel_configuration.cc b/libs/ardour/export_channel_configuration.cc
index a092af88c1..a2a289737c 100644
--- a/libs/ardour/export_channel_configuration.cc
+++ b/libs/ardour/export_channel_configuration.cc
@@ -37,24 +37,6 @@
namespace ARDOUR
{
-/* ExportChannel */
-
-void
-ExportChannel::read_ports (float * data, nframes_t frames) const
-{
- memset (data, 0, frames * sizeof (float));
-
- for (iterator it = begin(); it != end(); ++it) {
- if (*it != 0) {
- Sample* port_buffer = (*it)->get_audio_buffer( frames, 0).data();
-
- for (uint32_t i = 0; i < frames; ++i) {
- data[i] += (float) port_buffer[i];
- }
- }
- }
-}
-
/* ExportChannelConfiguration */
ExportChannelConfiguration::ExportChannelConfiguration (Session & session) :
@@ -73,7 +55,6 @@ ExportChannelConfiguration::get_state ()
{
XMLNode * root = new XMLNode ("ExportChannelConfiguration");
XMLNode * channel;
- XMLNode * port_node;
root->add_property ("split", get_split() ? "true" : "false");
root->add_property ("channels", to_string (get_n_chans(), std::dec));
@@ -84,12 +65,7 @@ ExportChannelConfiguration::get_state ()
if (!channel) { continue; }
channel->add_property ("number", to_string (i, std::dec));
-
- for (ExportChannel::const_iterator p_it = (*c_it)->begin(); p_it != (*c_it)->end(); ++p_it) {
- if ((port_node = channel->add_child ("Port"))) {
- port_node->add_property ("name", (*p_it)->name());
- }
- }
+ (*c_it)->get_state (channel);
++i;
}
@@ -108,15 +84,8 @@ ExportChannelConfiguration::set_state (const XMLNode & root)
XMLNodeList channels = root.children ("Channel");
for (XMLNodeList::iterator it = channels.begin(); it != channels.end(); ++it) {
- boost::shared_ptr<ExportChannel> channel (new ExportChannel ());
-
- XMLNodeList ports = (*it)->children ("Port");
- for (XMLNodeList::iterator p_it = ports.begin(); p_it != ports.end(); ++p_it) {
- if ((prop = (*p_it)->property ("name"))) {
- channel->add_port (dynamic_cast<AudioPort *> (session.engine().get_port_by_name (prop->value())));
- }
- }
-
+ ExportChannelPtr channel (new PortExportChannel ());
+ channel->set_state (*it, session);
register_channel (channel);
}
@@ -124,9 +93,9 @@ ExportChannelConfiguration::set_state (const XMLNode & root)
}
bool
-ExportChannelConfiguration::all_channels_have_ports ()
+ExportChannelConfiguration::all_channels_have_ports () const
{
- for (ChannelList::iterator it = channels.begin(); it != channels.end(); ++it) {
+ for (ChannelList::const_iterator it = channels.begin(); it != channels.end(); ++it) {
if ((*it)->empty ()) { return false; }
}
@@ -182,7 +151,7 @@ ExportChannelConfiguration::write_file ()
/* Get channel data */
- frames_read = timespan->get_data (channel_buffer, frames, **it);
+ frames_read = timespan->get_data (channel_buffer, frames, *it);
/* Interleave into file buffer */
@@ -238,7 +207,7 @@ ExportChannelConfiguration::register_with_timespan (TimespanPtr new_timespan)
timespan = new_timespan;
for (ChannelList::iterator it = channels.begin(); it != channels.end(); ++it) {
- timespan->register_channel (**it);
+ timespan->register_channel (*it);
}
}
diff --git a/libs/ardour/export_profile_manager.cc b/libs/ardour/export_profile_manager.cc
index dee9a9a991..86b586d8e0 100644
--- a/libs/ardour/export_profile_manager.cc
+++ b/libs/ardour/export_profile_manager.cc
@@ -53,6 +53,7 @@ ExportProfileManager::ExportProfileManager (Session & s) :
session_range (new Location ()),
ranges (new LocationList ()),
+ single_range_mode (false),
format_list (new FormatList ())
{
@@ -299,6 +300,20 @@ ExportProfileManager::set_selection_range (nframes_t start, nframes_t end)
}
}
+std::string
+ExportProfileManager::set_single_range (nframes_t start, nframes_t end, Glib::ustring name)
+{
+ single_range_mode = true;
+
+ single_range.reset (new Location());
+ single_range->set_name (name);
+ single_range->set (start, end);
+
+ update_ranges ();
+
+ return single_range->id().to_s();
+}
+
bool
ExportProfileManager::init_timespans (XMLNodeList nodes)
{
@@ -377,6 +392,11 @@ ExportProfileManager::serialize_timespan (TimespanStatePtr state)
void
ExportProfileManager::update_ranges () {
ranges->clear();
+
+ if (single_range_mode) {
+ ranges->push_back (single_range.get());
+ return;
+ }
/* Session */
diff --git a/libs/ardour/export_timespan.cc b/libs/ardour/export_timespan.cc
index d6996a5a48..4eb5b5a475 100644
--- a/libs/ardour/export_timespan.cc
+++ b/libs/ardour/export_timespan.cc
@@ -42,7 +42,7 @@ ExportTimespan::~ExportTimespan ()
}
void
-ExportTimespan::register_channel (ExportChannel const & channel)
+ExportTimespan::register_channel (ExportChannelPtr channel)
{
TempFilePtr ptr (new ExportTempFile (1, frame_rate));
ChannelFilePair pair (channel, ptr);
@@ -58,7 +58,7 @@ ExportTimespan::rewind ()
}
nframes_t
-ExportTimespan::get_data (float * data, nframes_t frames, ExportChannel const & channel)
+ExportTimespan::get_data (float * data, nframes_t frames, ExportChannelPtr channel)
{
TempFileMap::iterator it = filemap.find (channel);
if (it == filemap.end()) {
@@ -100,7 +100,7 @@ ExportTimespan::process (nframes_t frames)
float * data = new float[frames_to_read];
for (TempFileMap::iterator it = filemap.begin(); it != filemap.end(); ++it) {
- it->first.read_ports (data, frames_to_read);
+ it->first->read (data, frames_to_read);
it->second->write (data, frames_to_read);
}