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
This commit is contained in:
Sakari Bergen 2008-10-11 10:14:51 +00:00
parent 01b1790c98
commit 98389f7da4
14 changed files with 537 additions and 115 deletions

View file

@ -91,17 +91,25 @@ Editor::export_range ()
void void
Editor::export_region () Editor::export_region ()
{ {
// if (selection->regions.empty()) { if (selection->regions.empty()) {
// return; return;
// } }
//
// boost::shared_ptr<Region> r = selection->regions.front()->region(); try {
// boost::shared_ptr<Region> r = selection->regions.front()->region();
// ExportDialog* dialog = new ExportRegionDialog (*this, r); AudioRegion & region (dynamic_cast<AudioRegion &> (*r));
//
// dialog->connect_to_session (session); RouteTimeAxisView & rtv (dynamic_cast<RouteTimeAxisView &> (selection->regions.front()->get_time_axis_view()));
// dialog->set_range (clicked_regionview->region()->first_frame(), clicked_regionview->region()->last_frame()); AudioTrack & track (dynamic_cast<AudioTrack &> (*rtv.route()));
// dialog->start_export();
ExportRegionDialog dialog (*this, region, track);
dialog.set_session (session);
dialog.run();
} catch (std::bad_cast & e) {
error << "Exporting Region failed!" << endmsg;
return;
}
} }
int int

View file

@ -39,7 +39,7 @@
using namespace ARDOUR; using namespace ARDOUR;
using namespace PBD; using namespace PBD;
ExportChannelSelector::ExportChannelSelector () : PortExportChannelSelector::PortExportChannelSelector () :
channels_label (_("Channels:"), Gtk::ALIGN_LEFT), channels_label (_("Channels:"), Gtk::ALIGN_LEFT),
split_checkbox (_("Split to mono files")), split_checkbox (_("Split to mono files")),
max_channels (20), max_channels (20),
@ -68,11 +68,11 @@ ExportChannelSelector::ExportChannelSelector () :
channels_spinbutton.set_range (1, max_channels); channels_spinbutton.set_range (1, max_channels);
channels_spinbutton.set_value (2); 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 */ /* 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()); channel_view.CriticalSelectionChanged.connect (CriticalSelectionChanged.make_slot());
/* Finalize */ /* Finalize */
@ -81,7 +81,7 @@ ExportChannelSelector::ExportChannelSelector () :
} }
ExportChannelSelector::~ExportChannelSelector () PortExportChannelSelector::~PortExportChannelSelector ()
{ {
// if (session) { // if (session) {
// session->add_instant_xml (get_state(), false); // session->add_instant_xml (get_state(), false);
@ -89,7 +89,7 @@ ExportChannelSelector::~ExportChannelSelector ()
} }
void 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_; state = state_;
session = session_; session = session_;
@ -102,7 +102,7 @@ ExportChannelSelector::set_state (ARDOUR::ExportProfileManager::ChannelConfigSta
} }
void void
ExportChannelSelector::fill_route_list () PortExportChannelSelector::fill_route_list ()
{ {
channel_view.clear_routes (); channel_view.clear_routes ();
Session::RouteList routes = *session->get_routes(); Session::RouteList routes = *session->get_routes();
@ -123,7 +123,7 @@ ExportChannelSelector::fill_route_list ()
} }
void void
ExportChannelSelector::update_channel_count () PortExportChannelSelector::update_channel_count ()
{ {
uint32_t chans = static_cast<uint32_t> (channels_spinbutton.get_value()); uint32_t chans = static_cast<uint32_t> (channels_spinbutton.get_value());
channel_view.set_channel_count (chans); channel_view.set_channel_count (chans);
@ -131,14 +131,14 @@ ExportChannelSelector::update_channel_count ()
} }
void void
ExportChannelSelector::update_split_state () PortExportChannelSelector::update_split_state ()
{ {
state->config->set_split (split_checkbox.get_active()); state->config->set_split (split_checkbox.get_active());
CriticalSelectionChanged(); CriticalSelectionChanged();
} }
void void
ExportChannelSelector::RouteCols::add_channels (uint32_t chans) PortExportChannelSelector::RouteCols::add_channels (uint32_t chans)
{ {
while (chans > 0) { while (chans > 0) {
channels.push_back (Channel (*this)); channels.push_back (Channel (*this));
@ -147,8 +147,8 @@ ExportChannelSelector::RouteCols::add_channels (uint32_t chans)
} }
} }
ExportChannelSelector::RouteCols::Channel & PortExportChannelSelector::RouteCols::Channel &
ExportChannelSelector::RouteCols::get_channel (uint32_t channel) PortExportChannelSelector::RouteCols::get_channel (uint32_t channel)
{ {
if (channel > n_channels) { if (channel > n_channels) {
std::cout << "Invalid channel cout for get_channel!" << std::endl; std::cout << "Invalid channel cout for get_channel!" << std::endl;
@ -164,7 +164,7 @@ ExportChannelSelector::RouteCols::get_channel (uint32_t channel)
return *it; return *it;
} }
ExportChannelSelector::ChannelTreeView::ChannelTreeView (uint32_t max_channels) : PortExportChannelSelector::ChannelTreeView::ChannelTreeView (uint32_t max_channels) :
n_channels (0) n_channels (0)
{ {
/* Main columns */ /* Main columns */
@ -186,13 +186,13 @@ ExportChannelSelector::ChannelTreeView::ChannelTreeView (uint32_t max_channels)
column->add_attribute (text_renderer->property_text(), route_cols.name); column->add_attribute (text_renderer->property_text(), route_cols.name);
Gtk::CellRendererToggle *toggle = dynamic_cast<Gtk::CellRendererToggle *>(get_column_cell_renderer (0)); Gtk::CellRendererToggle *toggle = dynamic_cast<Gtk::CellRendererToggle *>(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(); static_columns = get_columns().size();
} }
void void
ExportChannelSelector::ChannelTreeView::set_config (ChannelConfigPtr c) PortExportChannelSelector::ChannelTreeView::set_config (ChannelConfigPtr c)
{ {
/* TODO Without the following line, the state might get reset. /* 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. * 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) { 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<ARDOUR::PortExportChannel *> (c_it->get()))) {
continue;
}
Glib::RefPtr<Gtk::ListStore> port_list = r_it->get_value (route_cols.port_list_col); Glib::RefPtr<Gtk::ListStore> port_list = r_it->get_value (route_cols.port_list_col);
std::set<AudioPort *> route_ports; std::set<AudioPort *> route_ports;
std::set<AudioPort *> intersection; std::set<AudioPort *> intersection;
@ -219,7 +224,7 @@ ExportChannelSelector::ChannelTreeView::set_config (ChannelConfigPtr c)
(*p_it)->get_value (route_cols.port_cols.label))); (*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(), route_ports.begin(), route_ports.end(),
std::insert_iterator<std::set<AudioPort *> > (intersection, intersection.begin())); std::insert_iterator<std::set<AudioPort *> > (intersection, intersection.begin()));
@ -253,7 +258,7 @@ ExportChannelSelector::ChannelTreeView::set_config (ChannelConfigPtr c)
} }
void void
ExportChannelSelector::ChannelTreeView::add_route (ARDOUR::IO * route) PortExportChannelSelector::ChannelTreeView::add_route (ARDOUR::IO * route)
{ {
Gtk::TreeModel::iterator iter = route_list->append(); Gtk::TreeModel::iterator iter = route_list->append();
Gtk::TreeModel::Row row = *iter; Gtk::TreeModel::Row row = *iter;
@ -291,7 +296,7 @@ ExportChannelSelector::ChannelTreeView::add_route (ARDOUR::IO * route)
} }
void void
ExportChannelSelector::ChannelTreeView::set_channel_count (uint32_t channels) PortExportChannelSelector::ChannelTreeView::set_channel_count (uint32_t channels)
{ {
int offset = channels - n_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_model(), route_cols.port_list_col);
column->add_attribute (combo_renderer->property_editable(), route_cols.selected); 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 */ /* put data into view */
@ -344,7 +349,7 @@ ExportChannelSelector::ChannelTreeView::set_channel_count (uint32_t channels)
} }
void void
ExportChannelSelector::ChannelTreeView::update_config () PortExportChannelSelector::ChannelTreeView::update_config ()
{ {
if (!config) { return; } if (!config) { return; }
@ -353,7 +358,8 @@ ExportChannelSelector::ChannelTreeView::update_config ()
for (uint32_t i = 1; i <= n_channels; ++i) { for (uint32_t i = 1; i <= n_channels; ++i) {
boost::shared_ptr<ExportChannel> channel (new ExportChannel ()); ExportChannelPtr channel (new PortExportChannel ());
PortExportChannel * pec = static_cast<PortExportChannel *> (channel.get());
for (Gtk::ListStore::Children::iterator it = route_list->children().begin(); it != route_list->children().end(); ++it) { for (Gtk::ListStore::Children::iterator it = route_list->children().begin(); it != route_list->children().end(); ++it) {
Gtk::TreeModel::Row row = *it; Gtk::TreeModel::Row row = *it;
@ -364,7 +370,7 @@ ExportChannelSelector::ChannelTreeView::update_config ()
AudioPort * port = row[route_cols.get_channel (i).port]; AudioPort * port = row[route_cols.get_channel (i).port];
if (port) { if (port) {
channel->add_port (port); pec->add_port (port);
} }
} }
@ -375,7 +381,7 @@ ExportChannelSelector::ChannelTreeView::update_config ()
} }
void 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); Gtk::TreeModel::iterator iter = get_model ()->get_iter (path);
bool selected = iter->get_value (route_cols.selected); bool selected = iter->get_value (route_cols.selected);
@ -408,7 +414,7 @@ ExportChannelSelector::ChannelTreeView::update_toggle_selection (Glib::ustring c
} }
void 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); Gtk::TreeModel::iterator iter = get_model ()->get_iter (path);
iter->set_value (route_cols.get_channel (channel).label, new_text); 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 (); 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 ();
}

View file

@ -24,6 +24,7 @@
#include <list> #include <list>
#include <ardour/export_profile_manager.h> #include <ardour/export_profile_manager.h>
#include <ardour/export_channel.h>
#include <gtkmm.h> #include <gtkmm.h>
#include <sigc++/signal.h> #include <sigc++/signal.h>
@ -31,40 +32,47 @@
namespace ARDOUR { namespace ARDOUR {
class Session; class Session;
class ExportChannel;
class ExportChannelConfiguration; class ExportChannelConfiguration;
class RegionExportChannelFactory;
class ExportHandler; class ExportHandler;
class AudioPort; class AudioPort;
class IO; class IO;
class AudioRegion;
class AudioTrack;
} }
class XMLNode; class XMLNode;
/// class ExportChannelSelector : public Gtk::HBox
class ExportChannelSelector : public Gtk::HBox { {
private: protected:
typedef boost::shared_ptr<ARDOUR::ExportChannelConfiguration> ChannelConfigPtr; typedef boost::shared_ptr<ARDOUR::ExportChannelConfiguration> ChannelConfigPtr;
typedef boost::shared_ptr<ARDOUR::ExportHandler> HandlerPtr; typedef boost::shared_ptr<ARDOUR::ExportHandler> HandlerPtr;
public: public:
virtual ~ExportChannelSelector () {}
ExportChannelSelector (); virtual void set_state (ARDOUR::ExportProfileManager::ChannelConfigStatePtr const state_, ARDOUR::Session * session_) = 0;
~ExportChannelSelector (); sigc::signal<void> CriticalSelectionChanged;
};
class PortExportChannelSelector : public ExportChannelSelector
{
public:
PortExportChannelSelector ();
~PortExportChannelSelector ();
void set_state (ARDOUR::ExportProfileManager::ChannelConfigStatePtr const state_, ARDOUR::Session * session_); void set_state (ARDOUR::ExportProfileManager::ChannelConfigStatePtr const state_, ARDOUR::Session * session_);
sigc::signal<void> CriticalSelectionChanged;
private: private:
void fill_route_list (); void fill_route_list ();
void update_channel_count (); void update_channel_count ();
void update_split_state (); void update_split_state ();
typedef boost::shared_ptr<ARDOUR::ExportChannel> ChannelPtr; typedef std::list<ARDOUR::ExportChannelPtr> CahnnelList;
typedef std::list<ChannelPtr> CahnnelList;
ARDOUR::Session * session; ARDOUR::Session * session;
ARDOUR::ExportProfileManager::ChannelConfigStatePtr state; 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<ARDOUR::RegionExportChannelFactory> 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__ */ #endif /* __export_channel_selector_h__ */

View file

@ -45,8 +45,6 @@ ExportDialog::~ExportDialog ()
void void
ExportDialog::set_session (ARDOUR::Session* s) ExportDialog::set_session (ARDOUR::Session* s)
{ {
init ();
session = s; session = s;
/* Init handler and profile manager */ /* Init handler and profile manager */
@ -55,6 +53,12 @@ ExportDialog::set_session (ARDOUR::Session* s)
status = session->get_export_status (); status = session->get_export_status ();
profile_manager.reset (new ExportProfileManager (*session)); profile_manager.reset (new ExportProfileManager (*session));
/* Possibly init stuff in derived classes */
init ();
/* Rest of session related initialization */
preset_selector->set_manager (profile_manager); preset_selector->set_manager (profile_manager);
file_notebook->set_session_and_manager (session, profile_manager); file_notebook->set_session_and_manager (session, profile_manager);
@ -163,7 +167,7 @@ ExportDialog::init_components ()
{ {
preset_selector.reset (new ExportPresetSelector ()); preset_selector.reset (new ExportPresetSelector ());
timespan_selector.reset (new ExportTimespanSelectorMultiple ()); timespan_selector.reset (new ExportTimespanSelectorMultiple ());
channel_selector.reset (new ExportChannelSelector ()); channel_selector.reset (new PortExportChannelSelector ());
file_notebook.reset (new ExportFileNotebook ()); file_notebook.reset (new ExportFileNotebook ());
} }
@ -358,7 +362,7 @@ ExportRangeDialog::init_components ()
{ {
preset_selector.reset (new ExportPresetSelector ()); preset_selector.reset (new ExportPresetSelector ());
timespan_selector.reset (new ExportTimespanSelectorSingle (range_id)); timespan_selector.reset (new ExportTimespanSelectorSingle (range_id));
channel_selector.reset (new ExportChannelSelector ()); channel_selector.reset (new PortExportChannelSelector ());
file_notebook.reset (new ExportFileNotebook ()); file_notebook.reset (new ExportFileNotebook ());
} }
@ -371,6 +375,23 @@ ExportSelectionDialog::init_components ()
{ {
preset_selector.reset (new ExportPresetSelector ()); preset_selector.reset (new ExportPresetSelector ());
timespan_selector.reset (new ExportTimespanSelectorSingle (X_("selection"))); 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 ()); file_notebook.reset (new ExportFileNotebook ());
} }

View file

@ -63,6 +63,12 @@ class ExportDialog : public ArdourDialog {
protected: protected:
typedef boost::shared_ptr<ARDOUR::ExportHandler> HandlerPtr;
typedef boost::shared_ptr<ARDOUR::ExportProfileManager> ManagerPtr;
HandlerPtr handler;
ManagerPtr profile_manager;
// initializes GUI layout // initializes GUI layout
virtual void init_gui (); virtual void init_gui ();
@ -94,13 +100,9 @@ class ExportDialog : public ArdourDialog {
void show_progress (); void show_progress ();
gint progress_timeout (); gint progress_timeout ();
typedef boost::shared_ptr<ARDOUR::ExportHandler> HandlerPtr;
typedef boost::shared_ptr<ARDOUR::ExportProfileManager> ManagerPtr;
typedef boost::shared_ptr<ARDOUR::ExportStatus> StatusPtr; typedef boost::shared_ptr<ARDOUR::ExportStatus> StatusPtr;
PublicEditor & editor; PublicEditor & editor;
HandlerPtr handler;
ManagerPtr profile_manager;
StatusPtr status; StatusPtr status;
/*** GUI components ***/ /*** GUI components ***/
@ -153,4 +155,16 @@ class ExportSelectionDialog : public ExportDialog
void init_components (); 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__ */ #endif /* __ardour_export_dialog_h__ */

View file

@ -70,6 +70,7 @@ element_importer.cc
element_import_handler.cc element_import_handler.cc
enums.cc enums.cc
event_type_map.cc event_type_map.cc
export_channel.cc
export_channel_configuration.cc export_channel_configuration.cc
export_file_io.cc export_file_io.cc
export_filename.cc export_filename.cc

View file

@ -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

View file

@ -21,12 +21,12 @@
#ifndef __ardour_export_channel_configuration_h__ #ifndef __ardour_export_channel_configuration_h__
#define __ardour_export_channel_configuration_h__ #define __ardour_export_channel_configuration_h__
#include <set>
#include <list> #include <list>
#include <glibmm/ustring.h> #include <glibmm/ustring.h>
#include <sigc++/signal.h> #include <sigc++/signal.h>
#include <ardour/export_channel.h>
#include <ardour/export_status.h> #include <ardour/export_status.h>
#include <ardour/ardour.h> #include <ardour/ardour.h>
@ -46,13 +46,6 @@ class ExportProcessor;
class ExportTimespan; class ExportTimespan;
class Session; 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 class ExportChannelConfiguration
{ {
private: private:
@ -86,20 +79,19 @@ class ExportChannelConfiguration
XMLNode & get_state (); XMLNode & get_state ();
int set_state (const XMLNode &); int set_state (const XMLNode &);
typedef boost::shared_ptr<ExportChannel const> ChannelPtr; typedef std::list<ExportChannelPtr> ChannelList;
typedef std::list<ChannelPtr> ChannelList;
ChannelList const & get_channels () { return channels; } ChannelList const & get_channels () const { return channels; }
bool all_channels_have_ports (); bool all_channels_have_ports () const;
ustring name () const { return _name; } ustring name () const { return _name; }
void set_name (ustring name) { _name = name; } void set_name (ustring name) { _name = name; }
void set_split (bool value) { split = value; } void set_split (bool value) { split = value; }
bool get_split () { return split; } bool get_split () const { return split; }
uint32_t get_n_chans () { return channels.size(); } 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 register_file_config (FormatPtr format, FilenamePtr filename) { file_configs.push_back (FileConfig (format, filename)); }
void clear_channels () { channels.clear (); } void clear_channels () { channels.clear (); }

View file

@ -144,6 +144,7 @@ class ExportProfileManager
typedef std::list<TimespanStatePtr> TimespanStateList; typedef std::list<TimespanStatePtr> TimespanStateList;
void set_selection_range (nframes_t start = 0, nframes_t end = 0); 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); } TimespanStateList const & get_timespans () { return check_list (timespans); }
private: private:
@ -163,6 +164,9 @@ class ExportProfileManager
boost::shared_ptr<Location> selection_range; boost::shared_ptr<Location> selection_range;
boost::shared_ptr<LocationList> ranges; boost::shared_ptr<LocationList> ranges;
bool single_range_mode;
boost::shared_ptr<Location> single_range;
/* Channel Configs */ /* Channel Configs */
public: public:

View file

@ -27,6 +27,7 @@
#include <glibmm/ustring.h> #include <glibmm/ustring.h>
#include <ardour/export_status.h> #include <ardour/export_status.h>
#include <ardour/export_channel.h>
#include <ardour/ardour.h> #include <ardour/ardour.h>
using Glib::ustring; using Glib::ustring;
@ -41,8 +42,8 @@ class ExportTimespan : public sigc::trackable
{ {
private: private:
typedef boost::shared_ptr<ExportTempFile> TempFilePtr; typedef boost::shared_ptr<ExportTempFile> TempFilePtr;
typedef std::pair<ExportChannel const, TempFilePtr> ChannelFilePair; typedef std::pair<ExportChannelPtr, TempFilePtr> ChannelFilePair;
typedef std::map<ExportChannel const, TempFilePtr> TempFileMap; typedef std::map<ExportChannelPtr, TempFilePtr> TempFileMap;
typedef boost::shared_ptr<ExportStatus> ExportStatusPtr; typedef boost::shared_ptr<ExportStatus> ExportStatusPtr;
private: private:
@ -59,13 +60,13 @@ class ExportTimespan : public sigc::trackable
void set_range_id (ustring range_id) { _range_id = range_id; } void set_range_id (ustring range_id) { _range_id = range_id; }
/// Registers a channel to be read when export starts rolling /// 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 /// "Rewinds" the tempfiles to start reading the beginnings again
void rewind (); void rewind ();
/// Reads data from the tempfile belonging to channel into data /// 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 /// Reads data from each channel and writes to tempfile
int process (nframes_t frames); int process (nframes_t frames);

View file

@ -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;
}

View file

@ -37,24 +37,6 @@
namespace ARDOUR 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::ExportChannelConfiguration (Session & session) : ExportChannelConfiguration::ExportChannelConfiguration (Session & session) :
@ -73,7 +55,6 @@ ExportChannelConfiguration::get_state ()
{ {
XMLNode * root = new XMLNode ("ExportChannelConfiguration"); XMLNode * root = new XMLNode ("ExportChannelConfiguration");
XMLNode * channel; XMLNode * channel;
XMLNode * port_node;
root->add_property ("split", get_split() ? "true" : "false"); root->add_property ("split", get_split() ? "true" : "false");
root->add_property ("channels", to_string (get_n_chans(), std::dec)); root->add_property ("channels", to_string (get_n_chans(), std::dec));
@ -84,12 +65,7 @@ ExportChannelConfiguration::get_state ()
if (!channel) { continue; } if (!channel) { continue; }
channel->add_property ("number", to_string (i, std::dec)); channel->add_property ("number", to_string (i, std::dec));
(*c_it)->get_state (channel);
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());
}
}
++i; ++i;
} }
@ -108,15 +84,8 @@ ExportChannelConfiguration::set_state (const XMLNode & root)
XMLNodeList channels = root.children ("Channel"); XMLNodeList channels = root.children ("Channel");
for (XMLNodeList::iterator it = channels.begin(); it != channels.end(); ++it) { for (XMLNodeList::iterator it = channels.begin(); it != channels.end(); ++it) {
boost::shared_ptr<ExportChannel> channel (new ExportChannel ()); ExportChannelPtr channel (new PortExportChannel ());
channel->set_state (*it, session);
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())));
}
}
register_channel (channel); register_channel (channel);
} }
@ -124,9 +93,9 @@ ExportChannelConfiguration::set_state (const XMLNode & root)
} }
bool 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; } if ((*it)->empty ()) { return false; }
} }
@ -182,7 +151,7 @@ ExportChannelConfiguration::write_file ()
/* Get channel data */ /* 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 */ /* Interleave into file buffer */
@ -238,7 +207,7 @@ ExportChannelConfiguration::register_with_timespan (TimespanPtr new_timespan)
timespan = new_timespan; timespan = new_timespan;
for (ChannelList::iterator it = channels.begin(); it != channels.end(); ++it) { for (ChannelList::iterator it = channels.begin(); it != channels.end(); ++it) {
timespan->register_channel (**it); timespan->register_channel (*it);
} }
} }

View file

@ -53,6 +53,7 @@ ExportProfileManager::ExportProfileManager (Session & s) :
session_range (new Location ()), session_range (new Location ()),
ranges (new LocationList ()), ranges (new LocationList ()),
single_range_mode (false),
format_list (new FormatList ()) 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 bool
ExportProfileManager::init_timespans (XMLNodeList nodes) ExportProfileManager::init_timespans (XMLNodeList nodes)
{ {
@ -378,6 +393,11 @@ void
ExportProfileManager::update_ranges () { ExportProfileManager::update_ranges () {
ranges->clear(); ranges->clear();
if (single_range_mode) {
ranges->push_back (single_range.get());
return;
}
/* Session */ /* Session */
session_range->set_name (_("Session")); session_range->set_name (_("Session"));

View file

@ -42,7 +42,7 @@ ExportTimespan::~ExportTimespan ()
} }
void void
ExportTimespan::register_channel (ExportChannel const & channel) ExportTimespan::register_channel (ExportChannelPtr channel)
{ {
TempFilePtr ptr (new ExportTempFile (1, frame_rate)); TempFilePtr ptr (new ExportTempFile (1, frame_rate));
ChannelFilePair pair (channel, ptr); ChannelFilePair pair (channel, ptr);
@ -58,7 +58,7 @@ ExportTimespan::rewind ()
} }
nframes_t 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); TempFileMap::iterator it = filemap.find (channel);
if (it == filemap.end()) { if (it == filemap.end()) {
@ -100,7 +100,7 @@ ExportTimespan::process (nframes_t frames)
float * data = new float[frames_to_read]; float * data = new float[frames_to_read];
for (TempFileMap::iterator it = filemap.begin(); it != filemap.end(); ++it) { 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); it->second->write (data, frames_to_read);
} }