summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/export_main_dialog.cc46
-rw-r--r--gtk2_ardour/export_main_dialog.h8
-rw-r--r--libs/ardour/ardour/export_channel_configuration.h6
-rw-r--r--libs/ardour/ardour/export_failed.h8
-rw-r--r--libs/ardour/ardour/export_file_io.h52
-rw-r--r--libs/ardour/ardour/export_formats.h4
-rw-r--r--libs/ardour/ardour/export_handler.h2
-rw-r--r--libs/ardour/ardour/export_processor.h13
-rw-r--r--libs/ardour/ardour/export_status.h10
-rw-r--r--libs/ardour/ardour/export_timespan.h5
-rw-r--r--libs/ardour/ardour/session.h33
-rw-r--r--libs/ardour/export_channel_configuration.cc28
-rw-r--r--libs/ardour/export_file_io.cc94
-rw-r--r--libs/ardour/export_format_manager.cc12
-rw-r--r--libs/ardour/export_formats.cc22
-rw-r--r--libs/ardour/export_handler.cc27
-rw-r--r--libs/ardour/export_multiplication.cc20
-rw-r--r--libs/ardour/export_processor.cc82
-rw-r--r--libs/ardour/export_profile_manager.cc3
-rw-r--r--libs/ardour/export_status.cc18
-rw-r--r--libs/ardour/export_timespan.cc10
-rw-r--r--libs/ardour/export_utilities.cc6
-rw-r--r--libs/ardour/session_export.cc50
23 files changed, 343 insertions, 216 deletions
diff --git a/gtk2_ardour/export_main_dialog.cc b/gtk2_ardour/export_main_dialog.cc
index 16a2b9e6e1..e653a48bf0 100644
--- a/gtk2_ardour/export_main_dialog.cc
+++ b/gtk2_ardour/export_main_dialog.cc
@@ -143,9 +143,6 @@ ExportMainDialog::ExportMainDialog (PublicEditor & editor) :
ExportMainDialog::~ExportMainDialog ()
{
- if (session) {
- session->release_export_handler();
- }
}
void
@@ -156,6 +153,7 @@ ExportMainDialog::set_session (ARDOUR::Session* s)
/* Init handler and profile manager */
handler = session->get_export_handler ();
+ status = session->get_export_status ();
profile_manager.reset (new ExportProfileManager (*session));
/* Selection range */
@@ -190,6 +188,7 @@ ExportMainDialog::set_session (ARDOUR::Session* s)
timespan_selector.CriticalSelectionChanged.connect (sigc::mem_fun (*this, &ExportMainDialog::update_warnings));
channel_selector.CriticalSelectionChanged.connect (sigc::mem_fun (*this, &ExportMainDialog::update_warnings));
+ status->Aborting.connect (sigc::mem_fun (*this, &ExportMainDialog::notify_errors));
update_warnings ();
}
@@ -202,12 +201,20 @@ ExportMainDialog::select_timespan (Glib::ustring id)
}
void
-ExportMainDialog::close_dialog ()
+ExportMainDialog::notify_errors ()
{
- ExportStatus & status = session->export_status;
+ if (status->errors()) {
+ Glib::ustring txt = _("Export has been aborted due to an error!\nSee the Log for details.");
+ Gtk::MessageDialog msg (txt, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
+ msg.run();
+ }
+}
- if (status.running) {
- status.abort();
+void
+ExportMainDialog::close_dialog ()
+{
+ if (status->running) {
+ status->abort();
}
hide_all ();
@@ -341,8 +348,7 @@ ExportMainDialog::export_fw ()
void
ExportMainDialog::show_progress ()
{
- ARDOUR::ExportStatus & status = session->export_status;
- status.running = true;
+ status->running = true;
cancel_button->set_label (_("Stop Export"));
rt_export_button->set_sensitive (false);
@@ -355,7 +361,7 @@ ExportMainDialog::show_progress ()
progress_connection = Glib::signal_timeout().connect (mem_fun(*this, &ExportMainDialog::progress_timeout), 100);
gtk_main_iteration ();
- while (status.running) {
+ while (status->running) {
if (gtk_events_pending()) {
gtk_main_iteration ();
} else {
@@ -377,30 +383,28 @@ ExportMainDialog::get_nth_format_name (uint32_t n)
gint
ExportMainDialog::progress_timeout ()
{
- ARDOUR::ExportStatus & status = session->export_status;
-
- switch (status.stage) {
+ switch (status->stage) {
case export_None:
progress_label.set_text ("");
break;
case export_ReadTimespan:
- progress_label.set_text (string_compose (_("Reading timespan %1 of %2"), status.timespan, status.total_timespans));
+ progress_label.set_text (string_compose (_("Reading timespan %1 of %2"), status->timespan, status->total_timespans));
break;
case export_PostProcess:
progress_label.set_text (string_compose (_("Processing file %2 of %3 (%1) from timespan %4 of %5"),
- get_nth_format_name (status.format),
- status.format, status.total_formats,
- status.timespan, status.total_timespans));
+ get_nth_format_name (status->format),
+ status->format, status->total_formats,
+ status->timespan, status->total_timespans));
break;
case export_Write:
progress_label.set_text (string_compose (_("Encoding file %2 of %3 (%1) from timespan %4 of %5"),
- get_nth_format_name (status.format),
- status.format, status.total_formats,
- status.timespan, status.total_timespans));
+ get_nth_format_name (status->format),
+ status->format, status->total_formats,
+ status->timespan, status->total_timespans));
break;
}
- progress_bar.set_fraction (status.progress);
+ progress_bar.set_fraction (status->progress);
return TRUE;
}
diff --git a/gtk2_ardour/export_main_dialog.h b/gtk2_ardour/export_main_dialog.h
index 9c4429856d..e578833515 100644
--- a/gtk2_ardour/export_main_dialog.h
+++ b/gtk2_ardour/export_main_dialog.h
@@ -21,6 +21,8 @@
#ifndef __export_main_dialog_h__
#define __export_main_dialog_h__
+#include <boost/shared_ptr.hpp>
+
#include <ardour/export_handler.h>
#include <ardour/export_profile_manager.h>
@@ -37,6 +39,7 @@ namespace ARDOUR {
class ExportFilename;
class ExportFormatSpecification;
class ExportChannelConfiguration;
+ class ExportStatus;
}
class ExportTimespanSelector;
@@ -64,7 +67,8 @@ class ExportMainDialog : public ArdourDialog {
};
private:
-
+
+ void notify_errors ();
void close_dialog ();
void sync_with_manager ();
@@ -82,6 +86,7 @@ class ExportMainDialog : public ArdourDialog {
typedef boost::shared_ptr<ARDOUR::ExportHandler> HandlerPtr;
typedef boost::shared_ptr<ARDOUR::ExportFormatSpecification> FormatPtr;
typedef boost::shared_ptr<ARDOUR::ExportProfileManager> ManagerPtr;
+ typedef boost::shared_ptr<ARDOUR::ExportStatus> StatusPtr;
void export_rt ();
void export_fw ();
@@ -95,6 +100,7 @@ class ExportMainDialog : public ArdourDialog {
PublicEditor & editor;
HandlerPtr handler;
ManagerPtr profile_manager;
+ StatusPtr status;
/*** GUI components ***/
diff --git a/libs/ardour/ardour/export_channel_configuration.h b/libs/ardour/ardour/export_channel_configuration.h
index 234cd5d127..80ad29b435 100644
--- a/libs/ardour/ardour/export_channel_configuration.h
+++ b/libs/ardour/ardour/export_channel_configuration.h
@@ -80,7 +80,7 @@ class ExportChannelConfiguration
private:
friend class ExportElementFactory;
- ExportChannelConfiguration (ExportStatus & status, Session & session);
+ ExportChannelConfiguration (Session & session);
public:
XMLNode & get_state ();
@@ -115,6 +115,8 @@ class ExportChannelConfiguration
private:
+ typedef boost::shared_ptr<ExportStatus> ExportStatusPtr;
+
Session & session;
// processor has to be prepared before doing this.
@@ -124,7 +126,7 @@ class ExportChannelConfiguration
static void * _write_files (void *arg);
WriterThread writer_thread;
ProcessorPtr processor;
- ExportStatus & status;
+ ExportStatusPtr status;
bool files_written;
diff --git a/libs/ardour/ardour/export_failed.h b/libs/ardour/ardour/export_failed.h
index de00fba87e..1b375f3cb8 100644
--- a/libs/ardour/ardour/export_failed.h
+++ b/libs/ardour/ardour/export_failed.h
@@ -35,9 +35,8 @@ namespace ARDOUR
class ExportFailed : public std::exception
{
public:
- ExportFailed (std::string const & reason, std::string const & description) :
- reason (reason.c_str()),
- description (description.c_str())
+ ExportFailed (std::string const & reason) :
+ reason (reason.c_str())
{
error << string_compose (_("Export failed: %1"), reason) << endmsg;
}
@@ -46,13 +45,12 @@ class ExportFailed : public std::exception
const char* what() const throw()
{
- return description;
+ return reason;
}
private:
const char * reason;
- const char * description;
};
diff --git a/libs/ardour/ardour/export_file_io.h b/libs/ardour/ardour/export_file_io.h
index e0b1c95323..6705b7736a 100644
--- a/libs/ardour/ardour/export_file_io.h
+++ b/libs/ardour/ardour/export_file_io.h
@@ -21,11 +21,20 @@
#ifndef __ardour_export_file_io_h__
#define __ardour_export_file_io_h__
-#include <sndfile.h>
+#include <stdint.h>
+#include <utility>
+
+#include <boost/shared_ptr.hpp>
+#include <glibmm/ustring.h>
+#include <ardour/sndfile_helpers.h>
#include <ardour/graph.h>
#include <ardour/types.h>
#include <ardour/ardour.h>
+#include <ardour/export_format_specification.h>
+#include <ardour/export_utilities.h>
+
+using Glib::ustring;
namespace ARDOUR
{
@@ -34,15 +43,16 @@ namespace ARDOUR
class ExportFileWriter
{
public:
- ExportFileWriter (string filename) : _filename (filename) {}
virtual ~ExportFileWriter () {}
-
+
string filename () const { return _filename; }
nframes_t position () const { return _position; }
void set_position (nframes_t position) { _position = position; }
protected:
+ ExportFileWriter (string filename) : _filename (filename) {}
+
string _filename;
nframes_t _position;
};
@@ -51,12 +61,13 @@ class ExportFileWriter
class SndfileWriterBase : public ExportFileWriter
{
public:
- SndfileWriterBase (int channels, nframes_t samplerate, int format, string const & path);
- virtual ~SndfileWriterBase ();
SNDFILE * get_sndfile () const { return sndfile; }
protected:
+ SndfileWriterBase (int channels, nframes_t samplerate, int format, string const & path);
+ virtual ~SndfileWriterBase ();
+
SF_INFO sf_info;
SNDFILE * sndfile;
};
@@ -66,13 +77,17 @@ class SndfileWriterBase : public ExportFileWriter
template <typename T>
class SndfileWriter : public SndfileWriterBase, public GraphSink<T>
{
- public:
+ protected:
+ // Should only be created vie ExportFileFactory and derived classes
+ friend class ExportFileFactory;
SndfileWriter (int channels, nframes_t samplerate, int format, string const & path);
- virtual ~SndfileWriter () {}
-
+
+ public:
nframes_t write (T * data, nframes_t frames);
-
+ virtual ~SndfileWriter () {}
+
protected:
+
sf_count_t (*write_func)(SNDFILE *, const T *, sf_count_t);
private:
@@ -139,6 +154,25 @@ class ExportTempFile : public SndfileWriter<float>, public GraphSource<float>
};
+class ExportFileFactory
+{
+ public:
+ typedef boost::shared_ptr<ExportFormatSpecification const> FormatPtr;
+ typedef GraphSink<float> FloatSink;
+ typedef boost::shared_ptr<FloatSink> FloatSinkPtr;
+ typedef boost::shared_ptr<ExportFileWriter> FileWriterPtr;
+
+ typedef std::pair<FloatSinkPtr, FileWriterPtr> FilePair;
+
+ static FilePair create (FormatPtr format, uint32_t channels, ustring const & filename);
+ static bool check (FormatPtr format, uint32_t channels);
+
+ private:
+
+ static FilePair create_sndfile (FormatPtr format, unsigned int channels, ustring const & filename);
+ static bool check_sndfile (FormatPtr format, unsigned int channels);
+};
+
} // namespace ARDOUR
#endif /* __ardour_export_file_io_h__ */
diff --git a/libs/ardour/ardour/export_formats.h b/libs/ardour/ardour/export_formats.h
index 558223d75a..34227526fc 100644
--- a/libs/ardour/ardour/export_formats.h
+++ b/libs/ardour/ardour/export_formats.h
@@ -170,6 +170,8 @@ class ExportFormatOggVorbis : public ExportFormat {
ExportFormatOggVorbis ();
~ExportFormatOggVorbis () {};
+ static bool check_system_compatibility ();
+
bool set_compatibility_state (ExportFormatCompatibility const & compatibility);
Type get_type () const { return T_Sndfile; }
SampleFormat get_explicit_sample_format () const { return SF_Vorbis; }
@@ -181,6 +183,8 @@ class ExportFormatFLAC : public ExportFormat, public HasSampleFormat {
ExportFormatFLAC ();
~ExportFormatFLAC () {};
+ static bool check_system_compatibility ();
+
bool set_compatibility_state (ExportFormatCompatibility const & compatibility);
Type get_type () const { return T_Sndfile; }
diff --git a/libs/ardour/ardour/export_handler.h b/libs/ardour/ardour/export_handler.h
index 99de563fa9..6142869fe0 100644
--- a/libs/ardour/ardour/export_handler.h
+++ b/libs/ardour/ardour/export_handler.h
@@ -93,6 +93,7 @@ class ExportHandler : public ExportElementFactory, public sigc::trackable
typedef std::multimap<TimespanPtr, FileSpec> ConfigMap;
typedef boost::shared_ptr<ExportProcessor> ProcessorPtr;
+ typedef boost::shared_ptr<ExportStatus> StatusPtr;
private:
/* Session::get_export_handler() should be used to obtain an export handler
@@ -112,6 +113,7 @@ class ExportHandler : public ExportElementFactory, public sigc::trackable
Session & session;
ProcessorPtr processor;
+ StatusPtr export_status;
ConfigMap config_map;
bool realtime;
diff --git a/libs/ardour/ardour/export_processor.h b/libs/ardour/ardour/export_processor.h
index fdb8213c68..5034831da4 100644
--- a/libs/ardour/ardour/export_processor.h
+++ b/libs/ardour/ardour/export_processor.h
@@ -52,14 +52,6 @@ class ExportProcessor
typedef boost::shared_ptr<Normalizer> NormalizerPtr;
typedef boost::shared_ptr<ExportTempFile> TempFilePtr;
- typedef boost::shared_ptr<SampleFormatConverter<short> > ShortConverterPtr;
- typedef boost::shared_ptr<SampleFormatConverter<int> > IntConverterPtr;
- typedef boost::shared_ptr<SampleFormatConverter<float> > FloatConverterPtr;
-
- typedef boost::shared_ptr<SndfileWriter<short> > ShortWriterPtr;
- typedef boost::shared_ptr<SndfileWriter<int> > IntWriterPtr;
- typedef boost::shared_ptr<SndfileWriter<float> > FloatWriterPtr;
-
typedef GraphSink<float> FloatSink;
typedef boost::shared_ptr<FloatSink> FloatSinkPtr;
typedef std::vector<FloatSinkPtr> FloatSinkVect;
@@ -96,10 +88,9 @@ class ExportProcessor
private:
void reset ();
- FloatSinkPtr prepare_sndfile_writer (FormatPtr format, uint32_t channels, ustring const & filename);
- Session & session;
- ExportStatus & status;
+ Session & session;
+ boost::shared_ptr<ExportStatus> status;
/* these are initalized in prepare() */
diff --git a/libs/ardour/ardour/export_status.h b/libs/ardour/ardour/export_status.h
index 3ca5905a22..88c2feb493 100644
--- a/libs/ardour/ardour/export_status.h
+++ b/libs/ardour/ardour/export_status.h
@@ -47,8 +47,13 @@ struct ExportStatus {
volatile bool running;
sigc::signal<void> Aborting;
- void abort () { _aborted = true; Aborting(); }
+ void abort (bool error_occurred = false);
bool aborted () const { return _aborted; }
+ bool errors () const { return _errors; }
+
+ sigc::signal<void> Finished;
+ void finish ();
+ bool finished () const { return _aborted; }
/* Progress info */
@@ -66,6 +71,9 @@ struct ExportStatus {
private:
volatile bool _aborted;
+ volatile bool _errors;
+ volatile bool _finished;
+
};
} // namespace ARDOUR
diff --git a/libs/ardour/ardour/export_timespan.h b/libs/ardour/ardour/export_timespan.h
index 7995da36d2..e19013e822 100644
--- a/libs/ardour/ardour/export_timespan.h
+++ b/libs/ardour/ardour/export_timespan.h
@@ -43,10 +43,11 @@ class ExportTimespan : public sigc::trackable
typedef boost::shared_ptr<ExportTempFile> TempFilePtr;
typedef std::pair<ExportChannel const, TempFilePtr> ChannelFilePair;
typedef std::map<ExportChannel const, TempFilePtr> TempFileMap;
+ typedef boost::shared_ptr<ExportStatus> ExportStatusPtr;
private:
friend class ExportElementFactory;
- ExportTimespan (ExportStatus & status, nframes_t frame_rate);
+ ExportTimespan (ExportStatusPtr status, nframes_t frame_rate);
public:
~ExportTimespan ();
@@ -78,7 +79,7 @@ class ExportTimespan : public sigc::trackable
private:
- ExportStatus & status;
+ ExportStatusPtr status;
nframes_t start_frame;
nframes_t end_frame;
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index b6d8f15101..eef953ac2c 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -51,7 +51,6 @@
#include <ardour/ardour.h>
#include <ardour/configuration.h>
-#include <ardour/export_status.h>
#include <ardour/location.h>
#include <ardour/gain.h>
#include <ardour/io.h>
@@ -111,6 +110,7 @@ class SMFSource;
class SessionDirectory;
class SessionMetadata;
class ExportHandler;
+class ExportStatus;
struct RouteGroup;
@@ -618,27 +618,14 @@ class Session : public PBD::StatefulDestructible
bool sample_rate_convert (import_status&, string infile, string& outfile);
string build_tmp_convert_name (string file);
- /* Export stuff */
-
- SlaveSource post_export_slave;
- nframes_t post_export_position;
-
- ExportStatus export_status;
-
boost::shared_ptr<ExportHandler> get_export_handler ();
- void release_export_handler ();
+ boost::shared_ptr<ExportStatus> get_export_status ();
- int pre_export ();
- int start_audio_export (nframes_t position, bool realtime);
- int stop_audio_export ();
- void finalize_audio_export ();
- void abort_audio_export ();
+ int start_audio_export (nframes_t position, bool realtime);
sigc::signal<int, nframes_t> ProcessExport;
- sigc::signal<void> ExportFinished;
+ sigc::signal<void> ExportReadFinished;
static sigc::signal<void, std::string, std::string> Exported;
- sigc::connection export_freewheel_connection;
- sigc::connection export_abort_connection;
void add_source (boost::shared_ptr<Source>);
void remove_source (boost::weak_ptr<Source>);
@@ -1080,9 +1067,21 @@ class Session : public PBD::StatefulDestructible
bool follow_slave (nframes_t, nframes_t);
void set_slave_source (SlaveSource);
+ SlaveSource post_export_slave;
+ nframes_t post_export_position;
+
bool _exporting;
bool _exporting_realtime;
+
boost::shared_ptr<ExportHandler> export_handler;
+ boost::shared_ptr<ExportStatus> export_status;
+
+ int pre_export ();
+ int stop_audio_export ();
+ void finalize_audio_export ();
+
+ sigc::connection export_freewheel_connection;
+ sigc::connection export_abort_connection;
void prepare_diskstreams ();
void commit_diskstreams (nframes_t, bool& session_requires_butler);
diff --git a/libs/ardour/export_channel_configuration.cc b/libs/ardour/export_channel_configuration.cc
index 97b05c2f1e..e6eb84be06 100644
--- a/libs/ardour/export_channel_configuration.cc
+++ b/libs/ardour/export_channel_configuration.cc
@@ -57,10 +57,10 @@ ExportChannel::read_ports (float * data, nframes_t frames) const
/* ExportChannelConfiguration */
-ExportChannelConfiguration::ExportChannelConfiguration (ExportStatus & status, Session & session) :
+ExportChannelConfiguration::ExportChannelConfiguration (Session & session) :
session (session),
writer_thread (*this),
- status (status),
+ status (session.get_export_status ()),
files_written (false),
split (false)
{
@@ -143,7 +143,7 @@ ExportChannelConfiguration::write_files (boost::shared_ptr<ExportProcessor> new_
files_written = true;
if (!timespan) {
- throw ExportFailed (_("Export failed due to a programming error"), _("No timespan registered to channel configuration when requesting files to be written"));
+ throw ExportFailed (X_("Programming error: No timespan registered to channel configuration when requesting files to be written"));
}
/* Take a local copy of the processor to be used in the thread that is created below */
@@ -175,7 +175,7 @@ ExportChannelConfiguration::write_file ()
uint32_t channel;
do {
- if (status.aborted()) { break; }
+ if (status->aborted()) { break; }
channel = 0;
for (ChannelList::iterator it = channels.begin(); it != channels.end(); ++it) {
@@ -194,7 +194,7 @@ ExportChannelConfiguration::write_file ()
}
progress += frames_read;
- status.progress = (float) progress / timespan_length;
+ status->progress = (float) progress / timespan_length;
} while (processor->process (file_buffer, frames_read) > 0);
@@ -211,14 +211,18 @@ ExportChannelConfiguration::_write_files (void *arg)
// cc can be trated like 'this'
WriterThread & cc (*((WriterThread *) arg));
- for (FileConfigList::iterator it = cc->file_configs.begin(); it != cc->file_configs.end(); ++it) {
- if (cc->status.aborted()) {
- break;
+ try {
+ for (FileConfigList::iterator it = cc->file_configs.begin(); it != cc->file_configs.end(); ++it) {
+ if (cc->status->aborted()) {
+ break;
+ }
+ cc->processor->prepare (it->first, it->second, cc->channels.size(), cc->split, cc->timespan->get_start());
+ cc->write_file (); // Writes tempfile
+ cc->processor->prepare_post_processors ();
+ cc->processor->write_files();
}
- cc->processor->prepare (it->first, it->second, cc->channels.size(), cc->split, cc->timespan->get_start());
- cc->write_file (); // Writes tempfile
- cc->processor->prepare_post_processors ();
- cc->processor->write_files();
+ } catch (ExportFailed & e) {
+ cc->status->abort (true);
}
cc.running = false;
diff --git a/libs/ardour/export_file_io.cc b/libs/ardour/export_file_io.cc
index 7da6e8a60c..d4aa1870ba 100644
--- a/libs/ardour/export_file_io.cc
+++ b/libs/ardour/export_file_io.cc
@@ -21,6 +21,7 @@
#include <string.h>
#include <ardour/export_file_io.h>
+
#include <ardour/export_failed.h>
#include <pbd/failed_constructor.h>
@@ -43,11 +44,11 @@ SndfileWriterBase::SndfileWriterBase (int channels, nframes_t samplerate, int fo
sf_info.format = format;
if (!sf_format_check (&sf_info)) {
- throw ExportFailed (_("Export failed due to a programming error"), "Invalid format given for SndfileWriter!");
+ throw ExportFailed (X_("Invalid format given for SndfileWriter!"));
}
if (path.length() == 0) {
- throw ExportFailed (_("Export failed due to a programming error"), "No output file specified for SndFileWriter");
+ throw ExportFailed (X_("No output file specified for SndFileWriter"));
}
/* TODO add checks that the directory path exists, and also
@@ -58,13 +59,12 @@ SndfileWriterBase::SndfileWriterBase (int channels, nframes_t samplerate, int fo
if (path.compare ("temp")) {
if ((sndfile = sf_open (path.c_str(), SFM_WRITE, &sf_info)) == 0) {
sf_error_str (0, errbuf, sizeof (errbuf) - 1);
- throw ExportFailed (string_compose(_("Export: cannot open output file \"%1\""), path),
- string_compose(_("Export: cannot open output file \"%1\" for SndFileWriter (%2)"), path, errbuf));
+ throw ExportFailed (string_compose(X_("Cannot open output file \"%1\" for SndFileWriter (%2)"), path, errbuf));
}
} else {
FILE * file;
if (!(file = tmpfile ())) {
- throw ExportFailed (_("Export failed due to a programming error"), "Cannot open tempfile");
+ throw ExportFailed (X_("Cannot open tempfile"));
}
sndfile = sf_open_fd (fileno(file), SFM_RDWR, &sf_info, true);
}
@@ -114,7 +114,7 @@ SndfileWriter<T>::write (T * data, nframes_t frames)
nframes_t written = (*write_func) (sndfile, data, frames);
if (written != frames) {
sf_error_str (sndfile, errbuf, sizeof (errbuf) - 1);
- throw ExportFailed (_("Writing export file failed"), string_compose(_("Could not write data to output file (%1)"), errbuf));
+ throw ExportFailed (string_compose(_("Could not write data to output file (%1)"), errbuf));
}
if (GraphSink<T>::end_of_input) {
@@ -198,7 +198,7 @@ ExportTempFile::read (float * data, nframes_t frames)
/* Check for errors */
if (read_status != to_read) {
- throw ExportFailed (_("Reading export file failed"), _("Error reading temporary export file, export might not be complete!"));
+ throw ExportFailed (X_("Error reading temporary export file, export might not be complete!"));
}
/* Add silence at end */
@@ -365,4 +365,82 @@ ExportTempFile::_read (float * data, nframes_t frames)
return sf_readf_float (sndfile, data, frames);
}
-};
+ExportFileFactory::FilePair
+ExportFileFactory::create (FormatPtr format, uint32_t channels, ustring const & filename)
+{
+ switch (format->type()) {
+ case ExportFormatBase::T_Sndfile:
+ return create_sndfile (format, channels, filename);
+
+ default:
+ throw ExportFailed (X_("Invalid format given for ExportFileFactory::create!"));
+ }
+}
+
+bool
+ExportFileFactory::check (FormatPtr format, uint32_t channels)
+{
+ switch (format->type()) {
+ case ExportFormatBase::T_Sndfile:
+ return check_sndfile (format, channels);
+
+ default:
+ throw ExportFailed (X_("Invalid format given for ExportFileFactory::check!"));
+ }
+}
+
+ExportFileFactory::FilePair
+ExportFileFactory::create_sndfile (FormatPtr format, unsigned int channels, ustring const & filename)
+{
+ typedef boost::shared_ptr<SampleFormatConverter<short> > ShortConverterPtr;
+ typedef boost::shared_ptr<SampleFormatConverter<int> > IntConverterPtr;
+ typedef boost::shared_ptr<SampleFormatConverter<float> > FloatConverterPtr;
+
+ typedef boost::shared_ptr<SndfileWriter<short> > ShortWriterPtr;
+ typedef boost::shared_ptr<SndfileWriter<int> > IntWriterPtr;
+ typedef boost::shared_ptr<SndfileWriter<float> > FloatWriterPtr;
+
+ FilePair ret;
+
+ int real_format = format->format_id() | format->sample_format() | format->endianness();
+
+ uint32_t data_width = sndfile_data_width (real_format);
+
+ if (data_width == 8 || data_width == 16) {
+
+ ShortConverterPtr sfc = ShortConverterPtr (new SampleFormatConverter<short> (channels, format->dither_type(), data_width));
+ ShortWriterPtr sfw = ShortWriterPtr (new SndfileWriter<short> (channels, format->sample_rate(), real_format, filename));
+ sfc->pipe_to (sfw);
+
+ return std::make_pair (boost::static_pointer_cast<FloatSink> (sfc), boost::static_pointer_cast<ExportFileWriter> (sfw));
+
+ } else if (data_width == 24 || data_width == 32) {
+
+ IntConverterPtr sfc = IntConverterPtr (new SampleFormatConverter<int> (channels, format->dither_type(), data_width));
+ IntWriterPtr sfw = IntWriterPtr (new SndfileWriter<int> (channels, format->sample_rate(), real_format, filename));
+ sfc->pipe_to (sfw);
+
+ return std::make_pair (boost::static_pointer_cast<FloatSink> (sfc), boost::static_pointer_cast<ExportFileWriter> (sfw));
+
+ } else {
+
+ FloatConverterPtr sfc = FloatConverterPtr (new SampleFormatConverter<float> (channels, format->dither_type(), data_width));
+ FloatWriterPtr sfw = FloatWriterPtr (new SndfileWriter<float> (channels, format->sample_rate(), real_format, filename));
+ sfc->pipe_to (sfw);
+
+ return std::make_pair (boost::static_pointer_cast<FloatSink> (sfc), boost::static_pointer_cast<ExportFileWriter> (sfw));;
+ }
+}
+
+bool
+ExportFileFactory::check_sndfile (FormatPtr format, unsigned int channels)
+{
+ SF_INFO sf_info;
+ sf_info.channels = channels;
+ sf_info.samplerate = format->sample_rate ();
+ sf_info.format = format->format_id () | format->sample_format ();
+
+ return (sf_format_check (&sf_info) == SF_TRUE ? true : false);
+}
+
+} // namespace ARDOUR
diff --git a/libs/ardour/export_format_manager.cc b/libs/ardour/export_format_manager.cc
index e9e722dfec..a1d1b72629 100644
--- a/libs/ardour/export_format_manager.cc
+++ b/libs/ardour/export_format_manager.cc
@@ -185,11 +185,15 @@ ExportFormatManager::init_formats ()
fl_ptr->set_extension ("raw");
add_format (f_ptr);
- f_ptr.reset (new ExportFormatOggVorbis ());
- add_format (f_ptr);
+ if (ExportFormatOggVorbis::check_system_compatibility()) {
+ f_ptr.reset (new ExportFormatOggVorbis ());
+ add_format (f_ptr);
+ }
- f_ptr.reset (new ExportFormatFLAC ());
- add_format (f_ptr);
+ if (ExportFormatFLAC::check_system_compatibility()) {
+ f_ptr.reset (new ExportFormatFLAC ());
+ add_format (f_ptr);
+ }
}
void
diff --git a/libs/ardour/export_formats.cc b/libs/ardour/export_formats.cc
index 7df54bad1c..f3c8f7197c 100644
--- a/libs/ardour/export_formats.cc
+++ b/libs/ardour/export_formats.cc
@@ -252,6 +252,17 @@ ExportFormatOggVorbis::ExportFormatOggVorbis ()
}
bool
+ExportFormatOggVorbis::check_system_compatibility ()
+{
+ SF_INFO sf_info;
+ sf_info.channels = 2;
+ sf_info.samplerate = SR_44_1;
+ sf_info.format = F_Ogg | SF_Vorbis;
+
+ return (sf_format_check (&sf_info) == SF_TRUE ? true : false);
+}
+
+bool
ExportFormatOggVorbis::set_compatibility_state (ExportFormatCompatibility const & compatibility)
{
bool compatible = compatibility.has_format (F_Ogg);
@@ -285,6 +296,17 @@ ExportFormatFLAC::ExportFormatFLAC () :
}
bool
+ExportFormatFLAC::check_system_compatibility ()
+{
+ SF_INFO sf_info;
+ sf_info.channels = 2;
+ sf_info.samplerate = SR_44_1;
+ sf_info.format = F_FLAC | SF_16;
+
+ return (sf_format_check (&sf_info) == SF_TRUE ? true : false);
+}
+
+bool
ExportFormatFLAC::set_compatibility_state (ExportFormatCompatibility const & compatibility)
{
bool compatible = compatibility.has_format (F_FLAC);
diff --git a/libs/ardour/export_handler.cc b/libs/ardour/export_handler.cc
index 0e22fdad27..ba26821a5b 100644
--- a/libs/ardour/export_handler.cc
+++ b/libs/ardour/export_handler.cc
@@ -55,13 +55,13 @@ ExportElementFactory::~ExportElementFactory ()
ExportElementFactory::TimespanPtr
ExportElementFactory::add_timespan ()
{
- return TimespanPtr (new ExportTimespan (session.export_status, session.frame_rate()));
+ return TimespanPtr (new ExportTimespan (session.get_export_status(), session.frame_rate()));
}
ExportElementFactory::ChannelConfigPtr
ExportElementFactory::add_channel_config ()
{
- return ChannelConfigPtr (new ExportChannelConfiguration (session.export_status, session));
+ return ChannelConfigPtr (new ExportChannelConfiguration (session));
}
ExportElementFactory::FormatPtr
@@ -99,6 +99,7 @@ ExportElementFactory::add_filename_copy (FilenamePtr other)
ExportHandler::ExportHandler (Session & session) :
ExportElementFactory (session),
session (session),
+ export_status (session.get_export_status ()),
realtime (false)
{
processor.reset (new ExportProcessor (session));
@@ -108,7 +109,7 @@ ExportHandler::ExportHandler (Session & session) :
ExportHandler::~ExportHandler ()
{
- if (session.export_status.aborted()) {
+ if (export_status->aborted()) {
for (std::list<Glib::ustring>::iterator it = files_written.begin(); it != files_written.end(); ++it) {
sys::remove (sys::path (*it));
}
@@ -133,7 +134,7 @@ ExportHandler::add_export_config (TimespanPtr timespan, ChannelConfigPtr channel
* 1. Session is prepared in do_export
* 2. start_timespan is called, which then registers all necessary channel configs to a timespan
* 3. The timespan reads each unique channel into a tempfile and calls Session::stop_export when the end is reached
- * 4. stop_export emits ExportFinished after stopping the transport, this ends up calling finish_timespan
+ * 4. stop_export emits ExportReadFinished after stopping the transport, this ends up calling finish_timespan
* 5. finish_timespan registers all the relevant formats and filenames to relevant channel configurations
* 6. finish_timespan does a manual call to timespan_thread_finished, which gets the next channel configuration
* for the current timespan, calling write_files for it
@@ -148,20 +149,18 @@ ExportHandler::do_export (bool rt)
{
/* Count timespans */
- ExportStatus & status = session.export_status;
- status.init();
+ export_status->init();
std::set<TimespanPtr> timespan_set;
for (ConfigMap::iterator it = config_map.begin(); it != config_map.end(); ++it) {
timespan_set.insert (it->first);
}
- status.total_timespans = timespan_set.size();
+ export_status->total_timespans = timespan_set.size();
/* Start export */
realtime = rt;
- session.ExportFinished.connect (sigc::mem_fun (*this, &ExportHandler::finish_timespan));
- session.pre_export ();
+ session.ExportReadFinished.connect (sigc::mem_fun (*this, &ExportHandler::finish_timespan));
start_timespan ();
}
@@ -442,10 +441,10 @@ ExportHandler::frames_to_cd_frames_string (char* buf, nframes_t when)
void
ExportHandler::start_timespan ()
{
- session.export_status.timespan++;
+ export_status->timespan++;
if (config_map.empty()) {
- session.finalize_audio_export();
+ export_status->finish ();
return;
}
@@ -472,12 +471,12 @@ ExportHandler::finish_timespan ()
/* Register formats and filenames to relevant channel configs */
- session.export_status.total_formats = 0;
- session.export_status.format = 0;
+ export_status->total_formats = 0;
+ export_status->format = 0;
for (ConfigMap::iterator it = timespan_bounds.first; it != timespan_bounds.second; ++it) {
- session.export_status.total_formats++;
+ export_status->total_formats++;
/* Setup filename */
diff --git a/libs/ardour/export_multiplication.cc b/libs/ardour/export_multiplication.cc
index da10d54eaa..943ca5a172 100644
--- a/libs/ardour/export_multiplication.cc
+++ b/libs/ardour/export_multiplication.cc
@@ -19,7 +19,7 @@ ExportProfileManager::register_all_configs ()
TimespanNodePtr ts_node;
if (!(ts_node = boost::dynamic_pointer_cast<TimespanNode> (*tsl_it))) {
- throw ExportFailed (_("Export failed due to a programming error"), "Invalid pointer cast in ExportProfileManager");
+ throw ExportFailed (X_("Programming error, Invalid pointer cast in ExportProfileManager"));
}
TimespanListPtr ts_list = ts_node->data()->timespans;
@@ -30,19 +30,19 @@ ExportProfileManager::register_all_configs ()
ChannelConfigNode * cc_node;
if (!(cc_node = dynamic_cast<ChannelConfigNode *> (*cc_it))) {
- throw ExportFailed (_("Export failed due to a programming error"), "Invalid pointer cast in ExportProfileManager");
+ throw ExportFailed (X_("Programming error, Invalid pointer cast in ExportProfileManager"));
}
ChannelConfigPtr channel_config = cc_node->data()->config;
FormatNode * f_node;
if (!(f_node = dynamic_cast<FormatNode *> (*f_it))) {
- throw ExportFailed (_("Export failed due to a programming error"), "Invalid pointer cast in ExportProfileManager");
+ throw ExportFailed (X_("Programming error, Invalid pointer cast in ExportProfileManager"));
}
FormatPtr format = f_node->data()->format;
FilenameNode * fn_node;
if (!(fn_node = dynamic_cast<FilenameNode *> (*fn_it))) {
- throw ExportFailed (_("Export failed due to a programming error"), "Invalid pointer cast in ExportProfileManager");
+ throw ExportFailed (X_("Programming error, Invalid pointer cast in ExportProfileManager"));
}
FilenamePtr filename = fn_node->data()->filename;
@@ -443,7 +443,7 @@ ExportProfileManager::duplicate_timespan_children (TimespanNodePtr source, Times
ChannelConfigNode * node_insertion_ptr;
if (!insertion_point) { insertion_point = source->last_child(); }
if (!(node_insertion_ptr = dynamic_cast<ChannelConfigNode *> (insertion_point))) {
- throw ExportFailed (_("Export failed due to a programming error"), "Invalid pointer cast in ExportProfileManager");
+ throw ExportFailed (X_("Programming error, Invalid pointer cast in ExportProfileManager"));
}
node_insertion_point = node_insertion_ptr->self_ptr();
@@ -460,7 +460,7 @@ ExportProfileManager::duplicate_timespan_children (TimespanNodePtr source, Times
ChannelConfigNodePtr new_node;
if (!(node = dynamic_cast<ChannelConfigNode *> (*it))) {
- throw ExportFailed (_("Export failed due to a programming error"), "Invalid pointer cast in ExportProfileManager");
+ throw ExportFailed (X_("Programming error, Invalid pointer cast in ExportProfileManager"));
}
new_node = duplicate_channel_config_node (node->self_ptr());
@@ -509,7 +509,7 @@ ExportProfileManager::duplicate_channel_config_children (ChannelConfigNodePtr so
FormatNode * node_insertion_ptr;
if (!insertion_point) { insertion_point = source->last_child(); }
if (!(node_insertion_ptr = dynamic_cast<FormatNode *> (insertion_point))) {
- throw ExportFailed (_("Export failed due to a programming error"), "Invalid pointer cast in ExportProfileManager");
+ throw ExportFailed (X_("Programming error, Invalid pointer cast in ExportProfileManager"));
}
node_insertion_point = node_insertion_ptr->self_ptr();
@@ -526,7 +526,7 @@ ExportProfileManager::duplicate_channel_config_children (ChannelConfigNodePtr so
FormatNodePtr new_node;
if (!(node = dynamic_cast<FormatNode *> (*it))) {
- throw ExportFailed (_("Export failed due to a programming error"), "Invalid pointer cast in ExportProfileManager");
+ throw ExportFailed (X_("Programming error, Invalid pointer cast in ExportProfileManager"));
}
new_node = duplicate_format_node (node->self_ptr());
@@ -573,7 +573,7 @@ ExportProfileManager::duplicate_format_children (FormatNodePtr source, FormatNod
FilenameNode * node_insertion_ptr;
if (!insertion_point) { insertion_point = source->last_child(); }
if (!(node_insertion_ptr = dynamic_cast<FilenameNode *> (insertion_point))) {
- throw ExportFailed (_("Export failed due to a programming error"), "Invalid pointer cast in ExportProfileManager");
+ throw ExportFailed (X_("Programming error, Invalid pointer cast in ExportProfileManager"));
}
node_insertion_point = node_insertion_ptr->self_ptr();
@@ -584,7 +584,7 @@ ExportProfileManager::duplicate_format_children (FormatNodePtr source, FormatNod
FilenameNodePtr new_node;
if (!(node = dynamic_cast<FilenameNode *> (*it))) {
- throw ExportFailed (_("Export failed due to a programming error"), "Invalid pointer cast in ExportProfileManager");
+ throw ExportFailed (X_("Programming error, Invalid pointer cast in ExportProfileManager"));
}
new_node = duplicate_filename_node (node->self_ptr());
diff --git a/libs/ardour/export_processor.cc b/libs/ardour/export_processor.cc
index 87f1772c90..8659514dbf 100644
--- a/libs/ardour/export_processor.cc
+++ b/libs/ardour/export_processor.cc
@@ -30,7 +30,6 @@
#include <ardour/export_filename.h>
#include <ardour/export_status.h>
#include <ardour/export_format_specification.h>
-#include <ardour/sndfile_helpers.h>
#include "i18n.h"
@@ -43,7 +42,7 @@ sigc::signal<void, Glib::ustring> ExportProcessor::WritingFile;
ExportProcessor::ExportProcessor (Session & session) :
session (session),
- status (session.export_status),
+ status (session.get_export_status()),
blocksize (session.get_block_size()),
frame_rate (session.frame_rate())
{
@@ -70,7 +69,7 @@ ExportProcessor::reset ()
int
ExportProcessor::prepare (FormatPtr format, FilenamePtr fname, uint32_t chans, bool split, nframes_t start)
{
- session.export_status.format++;
+ status->format++;
temp_file_length = 0;
/* Reset just to be sure all references are dropped */
@@ -96,7 +95,7 @@ ExportProcessor::prepare (FormatPtr format, FilenamePtr fname, uint32_t chans, b
/* Construct export pipe to temp file */
- status.stage = export_PostProcess;
+ status->stage = export_PostProcess;
if (normalize) {
/* Normalizing => we need a normalizer, peak reader and tempfile */
@@ -122,27 +121,12 @@ ExportProcessor::prepare (FormatPtr format, FilenamePtr fname, uint32_t chans, b
src->pipe_to (temp_file);
}
- /* File writer(s) */
-
- FloatSinkPtr (ExportProcessor::*prep_function) (FormatPtr, uint32_t, ustring const &);
-
- switch (format->type()) {
- case ExportFormatBase::T_Sndfile:
- prep_function = &ExportProcessor::prepare_sndfile_writer;
- break;
-
- default:
- throw ExportFailed (_("Export failed due to a programming error"), "Invalid format given for ExportProcessor::prepare!");
- break;
-
- }
-
/* Ensure directory exists */
sys::path folder (filename->get_folder());
if (!sys::exists (folder)) {
if (!sys::create_directory (folder)) {
- throw ExportFailed ("Export could not create the directory you requested for", "sys::create_directory failed for export dir");
+ throw ExportFailed (X_("sys::create_directory failed for export dir"));
}
}
@@ -152,12 +136,16 @@ ExportProcessor::prepare (FormatPtr format, FilenamePtr fname, uint32_t chans, b
filename->include_channel = true;
for (uint32_t chn = 1; chn <= channels; ++chn) {
filename->set_channel (chn);
- file_sinks.push_back ((this->*prep_function) (format, 1, filename->get_path (format)));
+ ExportFileFactory::FilePair pair = ExportFileFactory::create (format, 1, filename->get_path (format));
+ file_sinks.push_back (pair.first);
+ writer_list.push_back (pair.second);
WritingFile (filename->get_path (format));
}
} else {
- file_sinks.push_back ((this->*prep_function) (format, channels, filename->get_path (format)));
+ ExportFileFactory::FilePair pair = ExportFileFactory::create (format, channels, filename->get_path (format));
+ file_sinks.push_back (pair.first);
+ writer_list.push_back (pair.second);
WritingFile (filename->get_path (format));
}
@@ -229,7 +217,7 @@ ExportProcessor::write_files ()
{
/* Write to disk */
- status.stage = export_Write;
+ status->stage = export_Write;
temp_file_position = 0;
uint32_t buffer_size = 4096; // TODO adjust buffer size?
@@ -270,9 +258,9 @@ ExportProcessor::write_files ()
disk_sink->write (chan_bufs[channel], frames_read);
}
- if (status.aborted()) { break; }
+ if (status->aborted()) { break; }
temp_file_position += frames_read;
- status.progress = (float) temp_file_position / temp_file_length;
+ status->progress = (float) temp_file_position / temp_file_length;
}
/* Clean up */
@@ -285,9 +273,9 @@ ExportProcessor::write_files ()
while ((frames_read = temp_file->read (buf, buffer_size)) > 0) {
disk_sink->write (buf, frames_read);
- if (status.aborted()) { break; }
+ if (status->aborted()) { break; }
temp_file_position += frames_read;
- status.progress = (float) temp_file_position / temp_file_length;
+ status->progress = (float) temp_file_position / temp_file_length;
}
}
@@ -304,44 +292,4 @@ ExportProcessor::write_files ()
}
}
-ExportProcessor::FloatSinkPtr
-ExportProcessor::prepare_sndfile_writer (FormatPtr format, uint32_t channels, ustring const & filename)
-{
- int real_format = format->format_id() | format->sample_format() | format->endianness();
-
- uint32_t data_width = sndfile_data_width (real_format);
-
- if (data_width == 8 || data_width == 16) {
-
- ShortConverterPtr sfc = ShortConverterPtr (new SampleFormatConverter<short> (channels, format->dither_type(), data_width));
- ShortWriterPtr sfw = ShortWriterPtr (new SndfileWriter<short> (channels, format->sample_rate(), real_format, filename));
-
- writer_list.push_back (boost::static_pointer_cast<ExportFileWriter> (sfw));
-
- sfc->pipe_to (sfw);
- return boost::static_pointer_cast<FloatSink> (sfc);
-
- } else if (data_width == 24 || data_width == 32) {
-
- IntConverterPtr sfc = IntConverterPtr (new SampleFormatConverter<int> (channels, format->dither_type(), data_width));
- IntWriterPtr sfw = IntWriterPtr (new SndfileWriter<int> (channels, format->sample_rate(), real_format, filename));
-
- writer_list.push_back (boost::static_pointer_cast<ExportFileWriter> (sfw));
-
- sfc->pipe_to (sfw);
- return boost::static_pointer_cast<FloatSink> (sfc);
-
- } else {
-
- FloatConverterPtr sfc = FloatConverterPtr (new SampleFormatConverter<float> (channels, format->dither_type(), data_width));
- FloatWriterPtr sfw = FloatWriterPtr (new SndfileWriter<float> (channels, format->sample_rate(), real_format, filename));
-
- writer_list.push_back (boost::static_pointer_cast<ExportFileWriter> (sfw));
-
- sfc->pipe_to (sfw);
- return boost::static_pointer_cast<FloatSink> (sfc);
- }
-
-}
-
}; // namespace ARDOUR
diff --git a/libs/ardour/export_profile_manager.cc b/libs/ardour/export_profile_manager.cc
index e9edf5feef..dee9a9a991 100644
--- a/libs/ardour/export_profile_manager.cc
+++ b/libs/ardour/export_profile_manager.cc
@@ -30,6 +30,7 @@
#include <pbd/convert.h>
#include <ardour/export_failed.h>
+#include <ardour/export_file_io.h>
#include <ardour/export_format_specification.h>
#include <ardour/export_timespan.h>
#include <ardour/export_channel_configuration.h>
@@ -691,6 +692,8 @@ ExportProfileManager::check_config (boost::shared_ptr<Warnings> warnings,
/* Check format and maximum channel count */
if (!format || !format->type()) {
warnings->errors.push_back (_("No format selected!"));
+ } else if (!ExportFileFactory::check (format, channel_config->get_n_chans())) {
+ warnings->errors.push_back (_("One or more of the selected formats is not compatible with this system!"));
} else if (format->channel_limit() < channel_config->get_n_chans()) {
warnings->errors.push_back
(string_compose (_("%1 supports only %2 channels, but you have %3 channels in your channel configuration"),
diff --git a/libs/ardour/export_status.cc b/libs/ardour/export_status.cc
index c64a03fe23..a31e66dc39 100644
--- a/libs/ardour/export_status.cc
+++ b/libs/ardour/export_status.cc
@@ -34,6 +34,8 @@ ExportStatus::init ()
stop = false;
running = false;
_aborted = false;
+ _finished = false;
+ _errors = false;
stage = export_None;
progress = 0.0;
@@ -48,4 +50,20 @@ ExportStatus::init ()
format = 0;
}
+void
+ExportStatus::abort (bool error_occurred)
+{
+ _aborted = true;
+ _finished = true;
+ _errors = _errors || error_occurred;
+ Aborting ();
+}
+
+void
+ExportStatus::finish ()
+{
+ _finished = true;
+ Finished();
+}
+
} // namespace ARDOUR
diff --git a/libs/ardour/export_timespan.cc b/libs/ardour/export_timespan.cc
index 14273d835f..d6996a5a48 100644
--- a/libs/ardour/export_timespan.cc
+++ b/libs/ardour/export_timespan.cc
@@ -28,7 +28,7 @@
namespace ARDOUR
{
-ExportTimespan::ExportTimespan (ExportStatus & status, nframes_t frame_rate) :
+ExportTimespan::ExportTimespan (ExportStatusPtr status, nframes_t frame_rate) :
status (status),
start_frame (0),
end_frame (0),
@@ -62,7 +62,7 @@ ExportTimespan::get_data (float * data, nframes_t frames, ExportChannel const &
{
TempFileMap::iterator it = filemap.find (channel);
if (it == filemap.end()) {
- throw ExportFailed (_("Export failed due to programming error"), _("Trying to get data from ExportTimespan for channel that was never registered!"));
+ throw ExportFailed (X_("Trying to get data from ExportTimespan for channel that was never registered!"));
}
return it->second->read (data, frames);
@@ -79,7 +79,7 @@ ExportTimespan::set_range (nframes_t start, nframes_t end)
int
ExportTimespan::process (nframes_t frames)
{
- status.stage = export_ReadTimespan;
+ status->stage = export_ReadTimespan;
/* update position */
@@ -89,11 +89,11 @@ ExportTimespan::process (nframes_t frames)
frames_to_read = frames;
} else {
frames_to_read = end_frame - position;
- status.stop = true;
+ status->stop = true;
}
position += frames_to_read;
- status.progress = (float) (position - start_frame) / (end_frame - start_frame);
+ status->progress = (float) (position - start_frame) / (end_frame - start_frame);
/* Read channels from ports and save to tempfiles */
diff --git a/libs/ardour/export_utilities.cc b/libs/ardour/export_utilities.cc
index 64fa62ded5..a9223e2e1b 100644
--- a/libs/ardour/export_utilities.cc
+++ b/libs/ardour/export_utilities.cc
@@ -70,7 +70,7 @@ SampleRateConverter::SampleRateConverter (uint32_t channels, nframes_t in_rate,
int err;
if ((src_state = src_new (quality, channels, &err)) == 0) {
- throw ExportFailed (string_compose (_("cannot initialize sample rate conversion: %1"), src_strerror (err)), "Cannot initialize sample rate conversion");
+ throw ExportFailed (string_compose (X_("Cannot initialize sample rate conversion: %1"), src_strerror (err)));
}
src_data.src_ratio = out_rate / (double) in_rate;
@@ -109,7 +109,7 @@ SampleRateConverter::process (float * data, nframes_t frames)
max_leftover_frames = 4 * frames;
leftover_data = (float *) realloc (leftover_data, max_leftover_frames * channels * sizeof (float));
if (!leftover_data) {
- throw ExportFailed (_("A memory allocation error occured during sample rate conversion"), "Samplerate conversion failed");
+ throw ExportFailed (X_("A memory allocation error occured during sample rate conversion"));
}
data_out_size = out_samples_max;
@@ -161,7 +161,7 @@ SampleRateConverter::process (float * data, nframes_t frames)
++cnt;
if ((err = src_process (src_state, &src_data)) != 0) {
- throw ExportFailed (_("an error occured during sample rate conversion"), string_compose ("an error occured during sample rate conversion: %1", src_strerror (err)));
+ throw ExportFailed (string_compose ("An error occured during sample rate conversion: %1", src_strerror (err)));
}
frames_out = src_data.output_frames_gen;
diff --git a/libs/ardour/session_export.cc b/libs/ardour/session_export.cc
index aed32e278b..3ddceb6b00 100644
--- a/libs/ardour/session_export.cc
+++ b/libs/ardour/session_export.cc
@@ -26,6 +26,7 @@
#include <ardour/export_file_io.h>
#include <ardour/export_utilities.h>
#include <ardour/export_handler.h>
+#include <ardour/export_status.h>
#include <ardour/timestamps.h>
#include <ardour/ardour.h>
#include <ardour/session.h>
@@ -49,17 +50,20 @@ Session::get_export_handler ()
return export_handler;
}
-void
-Session::release_export_handler ()
+boost::shared_ptr<ExportStatus>
+Session::get_export_status ()
{
- if (!_exporting) {
- export_handler.reset();
+ if (!export_status) {
+ export_status.reset (new ExportStatus ());
}
+
+ return export_status;
}
int
Session::pre_export ()
{
+ get_export_status (); // Init export_status
wait_till_butler_finished ();
@@ -87,8 +91,8 @@ Session::pre_export ()
Config->set_slave_source (None);
_exporting = true;
- export_status.running = true;
- export_abort_connection = export_status.Aborting.connect (sigc::mem_fun (*this, &Session::abort_audio_export));
+ export_status->running = true;
+ export_abort_connection = export_status->Aborting.connect (sigc::hide_return (sigc::mem_fun (*this, &Session::stop_audio_export)));
return 0;
}
@@ -96,6 +100,10 @@ Session::pre_export ()
int
Session::start_audio_export (nframes_t position, bool realtime)
{
+ if (!_exporting) {
+ pre_export ();
+ }
+
/* get everyone to the right position */
{
@@ -119,7 +127,7 @@ Session::start_audio_export (nframes_t position, bool realtime)
_transport_frame = position;
_exporting_realtime = realtime;
- export_status.stop = false;
+ export_status->stop = false;
/* get transport ready. note how this is calling butler functions
from a non-butler thread. we waited for the butler to stop
@@ -154,7 +162,7 @@ Session::process_export (nframes_t nframes)
{
try {
- if (export_status.stop) {
+ if (export_status->stop) {
stop_audio_export ();
return;
}
@@ -176,11 +184,7 @@ Session::process_export (nframes_t nframes)
ProcessExport (nframes);
} catch (ExportFailed e) {
-
- std::cerr << e.what() << std::endl;
- stop_audio_export();
- finalize_audio_export();
-
+ export_status->abort (true);
}
}
@@ -208,8 +212,12 @@ Session::stop_audio_export ()
realtime_stop (true);
schedule_butler_transport_work ();
- if (!export_status.aborted()) {
- ExportFinished ();
+ if (!export_status->aborted()) {
+ ExportReadFinished ();
+ }
+
+ if (export_status->finished()) {
+ finalize_audio_export ();
}
return 0;
@@ -220,7 +228,7 @@ void
Session::finalize_audio_export ()
{
_exporting = false;
- export_status.running = false;
+ export_status->running = false;
if (!_exporting_realtime) {
_engine.freewheel (false);
@@ -230,10 +238,11 @@ Session::finalize_audio_export ()
/* Clean up */
ProcessExport.clear();
- ExportFinished.clear();
+ ExportReadFinished.clear();
export_freewheel_connection.disconnect();
export_abort_connection.disconnect();
export_handler.reset();
+ export_status.reset();
/* restart slaving */
@@ -243,10 +252,3 @@ Session::finalize_audio_export ()
locate (post_export_position, false, false, false);
}
}
-
-void
-Session::abort_audio_export ()
-{
- stop_audio_export ();
- finalize_audio_export ();
-}