From 98389f7da420ee205f6827b7df4db3ea0802f751 Mon Sep 17 00:00:00 2001 From: Sakari Bergen Date: Sat, 11 Oct 2008 10:14:51 +0000 Subject: 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 --- gtk2_ardour/editor_export_audio.cc | 30 +++-- gtk2_ardour/export_channel_selector.cc | 115 +++++++++++++---- gtk2_ardour/export_channel_selector.h | 61 +++++++-- gtk2_ardour/export_dialog.cc | 31 ++++- gtk2_ardour/export_dialog.h | 22 +++- libs/ardour/SConscript | 1 + libs/ardour/ardour/export_channel.h | 144 ++++++++++++++++++++++ libs/ardour/ardour/export_channel_configuration.h | 22 ++-- libs/ardour/ardour/export_profile_manager.h | 4 + libs/ardour/ardour/export_timespan.h | 9 +- libs/ardour/export_channel.cc | 142 +++++++++++++++++++++ libs/ardour/export_channel_configuration.cc | 45 ++----- libs/ardour/export_profile_manager.cc | 20 +++ libs/ardour/export_timespan.cc | 6 +- 14 files changed, 537 insertions(+), 115 deletions(-) create mode 100644 libs/ardour/ardour/export_channel.h create mode 100644 libs/ardour/export_channel.cc diff --git a/gtk2_ardour/editor_export_audio.cc b/gtk2_ardour/editor_export_audio.cc index b382200d38..621482f0f1 100644 --- a/gtk2_ardour/editor_export_audio.cc +++ b/gtk2_ardour/editor_export_audio.cc @@ -91,17 +91,25 @@ Editor::export_range () void Editor::export_region () { -// if (selection->regions.empty()) { -// return; -// } -// -// boost::shared_ptr r = selection->regions.front()->region(); -// -// ExportDialog* dialog = new ExportRegionDialog (*this, r); -// -// dialog->connect_to_session (session); -// dialog->set_range (clicked_regionview->region()->first_frame(), clicked_regionview->region()->last_frame()); -// dialog->start_export(); + if (selection->regions.empty()) { + return; + } + + try { + boost::shared_ptr r = selection->regions.front()->region(); + AudioRegion & region (dynamic_cast (*r)); + + RouteTimeAxisView & rtv (dynamic_cast (selection->regions.front()->get_time_axis_view())); + AudioTrack & track (dynamic_cast (*rtv.route())); + + ExportRegionDialog dialog (*this, region, track); + dialog.set_session (session); + dialog.run(); + + } catch (std::bad_cast & e) { + error << "Exporting Region failed!" << endmsg; + return; + } } int diff --git a/gtk2_ardour/export_channel_selector.cc b/gtk2_ardour/export_channel_selector.cc index 41ecec9094..e26d05d7c8 100644 --- a/gtk2_ardour/export_channel_selector.cc +++ b/gtk2_ardour/export_channel_selector.cc @@ -39,7 +39,7 @@ using namespace ARDOUR; using namespace PBD; -ExportChannelSelector::ExportChannelSelector () : +PortExportChannelSelector::PortExportChannelSelector () : channels_label (_("Channels:"), Gtk::ALIGN_LEFT), split_checkbox (_("Split to mono files")), max_channels (20), @@ -68,11 +68,11 @@ ExportChannelSelector::ExportChannelSelector () : channels_spinbutton.set_range (1, max_channels); channels_spinbutton.set_value (2); - channels_spinbutton.signal_value_changed().connect (sigc::mem_fun (*this, &ExportChannelSelector::update_channel_count)); + channels_spinbutton.signal_value_changed().connect (sigc::mem_fun (*this, &PortExportChannelSelector::update_channel_count)); /* Other signals */ - split_checkbox.signal_toggled().connect (sigc::mem_fun (*this, &ExportChannelSelector::update_split_state)); + split_checkbox.signal_toggled().connect (sigc::mem_fun (*this, &PortExportChannelSelector::update_split_state)); channel_view.CriticalSelectionChanged.connect (CriticalSelectionChanged.make_slot()); /* Finalize */ @@ -81,7 +81,7 @@ ExportChannelSelector::ExportChannelSelector () : } -ExportChannelSelector::~ExportChannelSelector () +PortExportChannelSelector::~PortExportChannelSelector () { // if (session) { // session->add_instant_xml (get_state(), false); @@ -89,7 +89,7 @@ ExportChannelSelector::~ExportChannelSelector () } void -ExportChannelSelector::set_state (ARDOUR::ExportProfileManager::ChannelConfigStatePtr const state_, ARDOUR::Session * session_) +PortExportChannelSelector::set_state (ARDOUR::ExportProfileManager::ChannelConfigStatePtr const state_, ARDOUR::Session * session_) { state = state_; session = session_; @@ -102,7 +102,7 @@ ExportChannelSelector::set_state (ARDOUR::ExportProfileManager::ChannelConfigSta } void -ExportChannelSelector::fill_route_list () +PortExportChannelSelector::fill_route_list () { channel_view.clear_routes (); Session::RouteList routes = *session->get_routes(); @@ -123,7 +123,7 @@ ExportChannelSelector::fill_route_list () } void -ExportChannelSelector::update_channel_count () +PortExportChannelSelector::update_channel_count () { uint32_t chans = static_cast (channels_spinbutton.get_value()); channel_view.set_channel_count (chans); @@ -131,14 +131,14 @@ ExportChannelSelector::update_channel_count () } void -ExportChannelSelector::update_split_state () +PortExportChannelSelector::update_split_state () { state->config->set_split (split_checkbox.get_active()); CriticalSelectionChanged(); } void -ExportChannelSelector::RouteCols::add_channels (uint32_t chans) +PortExportChannelSelector::RouteCols::add_channels (uint32_t chans) { while (chans > 0) { channels.push_back (Channel (*this)); @@ -147,8 +147,8 @@ ExportChannelSelector::RouteCols::add_channels (uint32_t chans) } } -ExportChannelSelector::RouteCols::Channel & -ExportChannelSelector::RouteCols::get_channel (uint32_t channel) +PortExportChannelSelector::RouteCols::Channel & +PortExportChannelSelector::RouteCols::get_channel (uint32_t channel) { if (channel > n_channels) { std::cout << "Invalid channel cout for get_channel!" << std::endl; @@ -164,7 +164,7 @@ ExportChannelSelector::RouteCols::get_channel (uint32_t channel) return *it; } -ExportChannelSelector::ChannelTreeView::ChannelTreeView (uint32_t max_channels) : +PortExportChannelSelector::ChannelTreeView::ChannelTreeView (uint32_t max_channels) : n_channels (0) { /* Main columns */ @@ -186,13 +186,13 @@ ExportChannelSelector::ChannelTreeView::ChannelTreeView (uint32_t max_channels) column->add_attribute (text_renderer->property_text(), route_cols.name); Gtk::CellRendererToggle *toggle = dynamic_cast(get_column_cell_renderer (0)); - toggle->signal_toggled().connect (mem_fun (*this, &ExportChannelSelector::ChannelTreeView::update_toggle_selection)); + toggle->signal_toggled().connect (mem_fun (*this, &PortExportChannelSelector::ChannelTreeView::update_toggle_selection)); static_columns = get_columns().size(); } void -ExportChannelSelector::ChannelTreeView::set_config (ChannelConfigPtr c) +PortExportChannelSelector::ChannelTreeView::set_config (ChannelConfigPtr c) { /* TODO Without the following line, the state might get reset. * Pointing to the same address does not mean the state of the configuration hasn't changed. @@ -208,6 +208,11 @@ ExportChannelSelector::ChannelTreeView::set_config (ChannelConfigPtr c) for (Gtk::ListStore::Children::iterator r_it = route_list->children().begin(); r_it != route_list->children().end(); ++r_it) { + ARDOUR::PortExportChannel * pec; + if (!(pec = dynamic_cast (c_it->get()))) { + continue; + } + Glib::RefPtr port_list = r_it->get_value (route_cols.port_list_col); std::set route_ports; std::set intersection; @@ -219,7 +224,7 @@ ExportChannelSelector::ChannelTreeView::set_config (ChannelConfigPtr c) (*p_it)->get_value (route_cols.port_cols.label))); } - std::set_intersection ((*c_it)->begin(), (*c_it)->end(), + std::set_intersection (pec->get_ports().begin(), pec->get_ports().end(), route_ports.begin(), route_ports.end(), std::insert_iterator > (intersection, intersection.begin())); @@ -253,7 +258,7 @@ ExportChannelSelector::ChannelTreeView::set_config (ChannelConfigPtr c) } void -ExportChannelSelector::ChannelTreeView::add_route (ARDOUR::IO * route) +PortExportChannelSelector::ChannelTreeView::add_route (ARDOUR::IO * route) { Gtk::TreeModel::iterator iter = route_list->append(); Gtk::TreeModel::Row row = *iter; @@ -291,7 +296,7 @@ ExportChannelSelector::ChannelTreeView::add_route (ARDOUR::IO * route) } void -ExportChannelSelector::ChannelTreeView::set_channel_count (uint32_t channels) +PortExportChannelSelector::ChannelTreeView::set_channel_count (uint32_t channels) { int offset = channels - n_channels; @@ -315,7 +320,7 @@ ExportChannelSelector::ChannelTreeView::set_channel_count (uint32_t channels) column->add_attribute (combo_renderer->property_model(), route_cols.port_list_col); column->add_attribute (combo_renderer->property_editable(), route_cols.selected); - combo_renderer->signal_edited().connect (sigc::bind (sigc::mem_fun (*this, &ExportChannelSelector::ChannelTreeView::update_selection_text), n_channels)); + combo_renderer->signal_edited().connect (sigc::bind (sigc::mem_fun (*this, &PortExportChannelSelector::ChannelTreeView::update_selection_text), n_channels)); /* put data into view */ @@ -344,7 +349,7 @@ ExportChannelSelector::ChannelTreeView::set_channel_count (uint32_t channels) } void -ExportChannelSelector::ChannelTreeView::update_config () +PortExportChannelSelector::ChannelTreeView::update_config () { if (!config) { return; } @@ -353,7 +358,8 @@ ExportChannelSelector::ChannelTreeView::update_config () for (uint32_t i = 1; i <= n_channels; ++i) { - boost::shared_ptr channel (new ExportChannel ()); + ExportChannelPtr channel (new PortExportChannel ()); + PortExportChannel * pec = static_cast (channel.get()); for (Gtk::ListStore::Children::iterator it = route_list->children().begin(); it != route_list->children().end(); ++it) { Gtk::TreeModel::Row row = *it; @@ -364,7 +370,7 @@ ExportChannelSelector::ChannelTreeView::update_config () AudioPort * port = row[route_cols.get_channel (i).port]; if (port) { - channel->add_port (port); + pec->add_port (port); } } @@ -375,7 +381,7 @@ ExportChannelSelector::ChannelTreeView::update_config () } void -ExportChannelSelector::ChannelTreeView::update_toggle_selection (Glib::ustring const & path) +PortExportChannelSelector::ChannelTreeView::update_toggle_selection (Glib::ustring const & path) { Gtk::TreeModel::iterator iter = get_model ()->get_iter (path); bool selected = iter->get_value (route_cols.selected); @@ -408,7 +414,7 @@ ExportChannelSelector::ChannelTreeView::update_toggle_selection (Glib::ustring c } void -ExportChannelSelector::ChannelTreeView::update_selection_text (Glib::ustring const & path, Glib::ustring const & new_text, uint32_t channel) +PortExportChannelSelector::ChannelTreeView::update_selection_text (Glib::ustring const & path, Glib::ustring const & new_text, uint32_t channel) { Gtk::TreeModel::iterator iter = get_model ()->get_iter (path); iter->set_value (route_cols.get_channel (channel).label, new_text); @@ -425,3 +431,66 @@ ExportChannelSelector::ChannelTreeView::update_selection_text (Glib::ustring con update_config (); } + +RegionExportChannelSelector::RegionExportChannelSelector (ARDOUR::AudioRegion const & region, ARDOUR::AudioTrack & track) : + session (0), + region (region), + track (track), + region_chans (region.n_channels()), + track_chans (track.n_outputs().n_audio()), + + raw_button (type_group), + processed_button (type_group) +{ + pack_start (vbox); + + raw_button.set_label (string_compose (_("Raw region export, no fades or plugins (%1 channels)"), region_chans)); + raw_button.signal_toggled ().connect (sigc::mem_fun (*this, &RegionExportChannelSelector::handle_selection)); + vbox.pack_start (raw_button); + + processed_button.set_label (string_compose (_("Processed region export with fades and plugins applied (%1 channels)"), track_chans)); + processed_button.signal_toggled ().connect (sigc::mem_fun (*this, &RegionExportChannelSelector::handle_selection)); + vbox.pack_start (processed_button); + + vbox.show_all_children (); + show_all_children (); +} + +void +RegionExportChannelSelector::set_state (ARDOUR::ExportProfileManager::ChannelConfigStatePtr const state_, ARDOUR::Session * session_) +{ + state = state_; + session = session_; + + handle_selection (); +} + +void +RegionExportChannelSelector::handle_selection () +{ + if (!state) { + return; + } + + state->config->clear_channels (); + + if (raw_button.get_active ()) { + + factory.reset (new RegionExportChannelFactory (session, region, track, RegionExportChannelFactory::Raw)); + + for (size_t chan = 0; chan < region_chans; ++chan) { + state->config->register_channel (factory->create (chan)); + } + + } else if (processed_button.get_active ()) { + + factory.reset (new RegionExportChannelFactory(session, region, track, RegionExportChannelFactory::Processed)); + + for (size_t chan = 0; chan < region_chans; ++chan) { + state->config->register_channel (factory->create (chan)); + } + + } + + CriticalSelectionChanged (); +} diff --git a/gtk2_ardour/export_channel_selector.h b/gtk2_ardour/export_channel_selector.h index 0faf652bd8..c2e99940aa 100644 --- a/gtk2_ardour/export_channel_selector.h +++ b/gtk2_ardour/export_channel_selector.h @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -31,31 +32,39 @@ namespace ARDOUR { class Session; - class ExportChannel; class ExportChannelConfiguration; + class RegionExportChannelFactory; class ExportHandler; class AudioPort; class IO; + class AudioRegion; + class AudioTrack; } class XMLNode; -/// -class ExportChannelSelector : public Gtk::HBox { - private: - +class ExportChannelSelector : public Gtk::HBox +{ + protected: typedef boost::shared_ptr ChannelConfigPtr; - typedef boost::shared_ptr HandlerPtr; public: + virtual ~ExportChannelSelector () {} + + virtual void set_state (ARDOUR::ExportProfileManager::ChannelConfigStatePtr const state_, ARDOUR::Session * session_) = 0; + sigc::signal CriticalSelectionChanged; +}; + +class PortExportChannelSelector : public ExportChannelSelector +{ - ExportChannelSelector (); - ~ExportChannelSelector (); + public: + + PortExportChannelSelector (); + ~PortExportChannelSelector (); void set_state (ARDOUR::ExportProfileManager::ChannelConfigStatePtr const state_, ARDOUR::Session * session_); - - sigc::signal CriticalSelectionChanged; private: @@ -63,8 +72,7 @@ class ExportChannelSelector : public Gtk::HBox { void update_channel_count (); void update_split_state (); - typedef boost::shared_ptr ChannelPtr; - typedef std::list CahnnelList; + typedef std::list CahnnelList; ARDOUR::Session * session; ARDOUR::ExportProfileManager::ChannelConfigStatePtr state; @@ -178,4 +186,33 @@ class ExportChannelSelector : public Gtk::HBox { }; +class RegionExportChannelSelector : public ExportChannelSelector +{ + public: + RegionExportChannelSelector (ARDOUR::AudioRegion const & region, ARDOUR::AudioTrack & track); + + virtual void set_state (ARDOUR::ExportProfileManager::ChannelConfigStatePtr const state_, ARDOUR::Session * session_); + + private: + + void handle_selection (); + + ARDOUR::Session * session; + ARDOUR::ExportProfileManager::ChannelConfigStatePtr state; + boost::shared_ptr factory; + ARDOUR::AudioRegion const & region; + ARDOUR::AudioTrack & track; + + uint32_t region_chans; + uint32_t track_chans; + + /*** GUI components ***/ + + Gtk::VBox vbox; + + Gtk::RadioButtonGroup type_group; + Gtk::RadioButton raw_button; + Gtk::RadioButton processed_button; +}; + #endif /* __export_channel_selector_h__ */ diff --git a/gtk2_ardour/export_dialog.cc b/gtk2_ardour/export_dialog.cc index 7ae81a016a..86263c8d3f 100644 --- a/gtk2_ardour/export_dialog.cc +++ b/gtk2_ardour/export_dialog.cc @@ -45,8 +45,6 @@ ExportDialog::~ExportDialog () void ExportDialog::set_session (ARDOUR::Session* s) { - init (); - session = s; /* Init handler and profile manager */ @@ -55,6 +53,12 @@ ExportDialog::set_session (ARDOUR::Session* s) status = session->get_export_status (); profile_manager.reset (new ExportProfileManager (*session)); + /* Possibly init stuff in derived classes */ + + init (); + + /* Rest of session related initialization */ + preset_selector->set_manager (profile_manager); file_notebook->set_session_and_manager (session, profile_manager); @@ -163,7 +167,7 @@ ExportDialog::init_components () { preset_selector.reset (new ExportPresetSelector ()); timespan_selector.reset (new ExportTimespanSelectorMultiple ()); - channel_selector.reset (new ExportChannelSelector ()); + channel_selector.reset (new PortExportChannelSelector ()); file_notebook.reset (new ExportFileNotebook ()); } @@ -358,7 +362,7 @@ ExportRangeDialog::init_components () { preset_selector.reset (new ExportPresetSelector ()); timespan_selector.reset (new ExportTimespanSelectorSingle (range_id)); - channel_selector.reset (new ExportChannelSelector ()); + channel_selector.reset (new PortExportChannelSelector ()); file_notebook.reset (new ExportFileNotebook ()); } @@ -371,6 +375,23 @@ ExportSelectionDialog::init_components () { preset_selector.reset (new ExportPresetSelector ()); timespan_selector.reset (new ExportTimespanSelectorSingle (X_("selection"))); - channel_selector.reset (new ExportChannelSelector ()); + channel_selector.reset (new PortExportChannelSelector ()); + file_notebook.reset (new ExportFileNotebook ()); +} + +ExportRegionDialog::ExportRegionDialog (PublicEditor & editor, ARDOUR::AudioRegion const & region, ARDOUR::AudioTrack & track) : + ExportDialog (editor, _("Export Region")), + region (region), + track (track) +{} + +void +ExportRegionDialog::init_components () +{ + Glib::ustring loc_id = profile_manager->set_single_range (region.position(), region.position() + region.length(), region.name()); + + preset_selector.reset (new ExportPresetSelector ()); + timespan_selector.reset (new ExportTimespanSelectorSingle (loc_id)); + channel_selector.reset (new RegionExportChannelSelector (region, track)); file_notebook.reset (new ExportFileNotebook ()); } diff --git a/gtk2_ardour/export_dialog.h b/gtk2_ardour/export_dialog.h index c0c5a24b20..0de6c6ffac 100644 --- a/gtk2_ardour/export_dialog.h +++ b/gtk2_ardour/export_dialog.h @@ -63,6 +63,12 @@ class ExportDialog : public ArdourDialog { protected: + typedef boost::shared_ptr HandlerPtr; + typedef boost::shared_ptr ManagerPtr; + + HandlerPtr handler; + ManagerPtr profile_manager; + // initializes GUI layout virtual void init_gui (); @@ -94,13 +100,9 @@ class ExportDialog : public ArdourDialog { void show_progress (); gint progress_timeout (); - typedef boost::shared_ptr HandlerPtr; - typedef boost::shared_ptr ManagerPtr; typedef boost::shared_ptr StatusPtr; PublicEditor & editor; - HandlerPtr handler; - ManagerPtr profile_manager; StatusPtr status; /*** GUI components ***/ @@ -153,4 +155,16 @@ class ExportSelectionDialog : public ExportDialog void init_components (); }; +class ExportRegionDialog : public ExportDialog +{ + public: + ExportRegionDialog (PublicEditor & editor, ARDOUR::AudioRegion const & region, ARDOUR::AudioTrack & track); + + private: + void init_components (); + + ARDOUR::AudioRegion const & region; + ARDOUR::AudioTrack & track; +}; + #endif /* __ardour_export_dialog_h__ */ 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 +#include +#include + +#include + +#include +#include + +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 +{ + public: + ExportChannelPtr () {} + template explicit ExportChannelPtr (Y * ptr) : boost::shared_ptr (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 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 #include #include #include +#include #include #include @@ -46,13 +46,6 @@ class ExportProcessor; class ExportTimespan; class Session; -class ExportChannel : public std::set -{ - 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 ChannelPtr; - typedef std::list ChannelList; + typedef std::list 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 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 session_range; boost::shared_ptr selection_range; boost::shared_ptr ranges; + + bool single_range_mode; + boost::shared_ptr 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 #include +#include #include using Glib::ustring; @@ -41,8 +42,8 @@ class ExportTimespan : public sigc::trackable { private: typedef boost::shared_ptr TempFilePtr; - typedef std::pair ChannelFilePair; - typedef std::map TempFileMap; + typedef std::pair ChannelFilePair; + typedef std::map TempFileMap; typedef boost::shared_ptr 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 + +#include +#include + +using namespace ARDOUR; + +bool +PortExportChannel::operator< (ExportChannel const & other) const +{ + PortExportChannel const * pec; + if (!(pec = dynamic_cast (&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 (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 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 (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); } -- cgit v1.2.3