diff options
author | Sakari Bergen <sakari.bergen@beatwaves.net> | 2008-10-11 10:14:51 +0000 |
---|---|---|
committer | Sakari Bergen <sakari.bergen@beatwaves.net> | 2008-10-11 10:14:51 +0000 |
commit | 98389f7da420ee205f6827b7df4db3ea0802f751 (patch) | |
tree | 28a28cf591b3d90a7eb60f422eee95e5ebfed6dc /libs | |
parent | 01b1790c98f9ee6739681f1dc8fe529c3ca7160a (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/SConscript | 1 | ||||
-rw-r--r-- | libs/ardour/ardour/export_channel.h | 144 | ||||
-rw-r--r-- | libs/ardour/ardour/export_channel_configuration.h | 22 | ||||
-rw-r--r-- | libs/ardour/ardour/export_profile_manager.h | 4 | ||||
-rw-r--r-- | libs/ardour/ardour/export_timespan.h | 9 | ||||
-rw-r--r-- | libs/ardour/export_channel.cc | 142 | ||||
-rw-r--r-- | libs/ardour/export_channel_configuration.cc | 45 | ||||
-rw-r--r-- | libs/ardour/export_profile_manager.cc | 20 | ||||
-rw-r--r-- | libs/ardour/export_timespan.cc | 6 |
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); } |