mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-16 19:56:31 +01:00
* Improved export error handling, streamlined ExportFailed
* Cleaned out export related visibility in Session, and simpified Session <--> export component communication in general * Removed export_status.h header dependency from session.h * Added check for libsndfile FLAC and Ogg Vorbis compatibility * Added ExportFileFactory, leading in cleaner code in ExportProcessor, and better extensibility for possible future non-libsndfile formats git-svn-id: svn://localhost/ardour2/branches/3.0@3818 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
909995338c
commit
6b50ba341d
23 changed files with 345 additions and 218 deletions
|
|
@ -143,9 +143,6 @@ ExportMainDialog::ExportMainDialog (PublicEditor & editor) :
|
||||||
|
|
||||||
ExportMainDialog::~ExportMainDialog ()
|
ExportMainDialog::~ExportMainDialog ()
|
||||||
{
|
{
|
||||||
if (session) {
|
|
||||||
session->release_export_handler();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -156,6 +153,7 @@ ExportMainDialog::set_session (ARDOUR::Session* s)
|
||||||
/* Init handler and profile manager */
|
/* Init handler and profile manager */
|
||||||
|
|
||||||
handler = session->get_export_handler ();
|
handler = session->get_export_handler ();
|
||||||
|
status = session->get_export_status ();
|
||||||
profile_manager.reset (new ExportProfileManager (*session));
|
profile_manager.reset (new ExportProfileManager (*session));
|
||||||
|
|
||||||
/* Selection range */
|
/* Selection range */
|
||||||
|
|
@ -190,6 +188,7 @@ ExportMainDialog::set_session (ARDOUR::Session* s)
|
||||||
|
|
||||||
timespan_selector.CriticalSelectionChanged.connect (sigc::mem_fun (*this, &ExportMainDialog::update_warnings));
|
timespan_selector.CriticalSelectionChanged.connect (sigc::mem_fun (*this, &ExportMainDialog::update_warnings));
|
||||||
channel_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 ();
|
update_warnings ();
|
||||||
}
|
}
|
||||||
|
|
@ -201,13 +200,21 @@ ExportMainDialog::select_timespan (Glib::ustring id)
|
||||||
timespan_selector.select_one_range (id);
|
timespan_selector.select_one_range (id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ExportMainDialog::notify_errors ()
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ExportMainDialog::close_dialog ()
|
ExportMainDialog::close_dialog ()
|
||||||
{
|
{
|
||||||
ExportStatus & status = session->export_status;
|
if (status->running) {
|
||||||
|
status->abort();
|
||||||
if (status.running) {
|
|
||||||
status.abort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hide_all ();
|
hide_all ();
|
||||||
|
|
@ -341,8 +348,7 @@ ExportMainDialog::export_fw ()
|
||||||
void
|
void
|
||||||
ExportMainDialog::show_progress ()
|
ExportMainDialog::show_progress ()
|
||||||
{
|
{
|
||||||
ARDOUR::ExportStatus & status = session->export_status;
|
status->running = true;
|
||||||
status.running = true;
|
|
||||||
|
|
||||||
cancel_button->set_label (_("Stop Export"));
|
cancel_button->set_label (_("Stop Export"));
|
||||||
rt_export_button->set_sensitive (false);
|
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);
|
progress_connection = Glib::signal_timeout().connect (mem_fun(*this, &ExportMainDialog::progress_timeout), 100);
|
||||||
|
|
||||||
gtk_main_iteration ();
|
gtk_main_iteration ();
|
||||||
while (status.running) {
|
while (status->running) {
|
||||||
if (gtk_events_pending()) {
|
if (gtk_events_pending()) {
|
||||||
gtk_main_iteration ();
|
gtk_main_iteration ();
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -377,30 +383,28 @@ ExportMainDialog::get_nth_format_name (uint32_t n)
|
||||||
gint
|
gint
|
||||||
ExportMainDialog::progress_timeout ()
|
ExportMainDialog::progress_timeout ()
|
||||||
{
|
{
|
||||||
ARDOUR::ExportStatus & status = session->export_status;
|
switch (status->stage) {
|
||||||
|
|
||||||
switch (status.stage) {
|
|
||||||
case export_None:
|
case export_None:
|
||||||
progress_label.set_text ("");
|
progress_label.set_text ("");
|
||||||
break;
|
break;
|
||||||
case export_ReadTimespan:
|
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;
|
break;
|
||||||
case export_PostProcess:
|
case export_PostProcess:
|
||||||
progress_label.set_text (string_compose (_("Processing file %2 of %3 (%1) from timespan %4 of %5"),
|
progress_label.set_text (string_compose (_("Processing file %2 of %3 (%1) from timespan %4 of %5"),
|
||||||
get_nth_format_name (status.format),
|
get_nth_format_name (status->format),
|
||||||
status.format, status.total_formats,
|
status->format, status->total_formats,
|
||||||
status.timespan, status.total_timespans));
|
status->timespan, status->total_timespans));
|
||||||
break;
|
break;
|
||||||
case export_Write:
|
case export_Write:
|
||||||
progress_label.set_text (string_compose (_("Encoding file %2 of %3 (%1) from timespan %4 of %5"),
|
progress_label.set_text (string_compose (_("Encoding file %2 of %3 (%1) from timespan %4 of %5"),
|
||||||
get_nth_format_name (status.format),
|
get_nth_format_name (status->format),
|
||||||
status.format, status.total_formats,
|
status->format, status->total_formats,
|
||||||
status.timespan, status.total_timespans));
|
status->timespan, status->total_timespans));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
progress_bar.set_fraction (status.progress);
|
progress_bar.set_fraction (status->progress);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,8 @@
|
||||||
#ifndef __export_main_dialog_h__
|
#ifndef __export_main_dialog_h__
|
||||||
#define __export_main_dialog_h__
|
#define __export_main_dialog_h__
|
||||||
|
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
#include <ardour/export_handler.h>
|
#include <ardour/export_handler.h>
|
||||||
#include <ardour/export_profile_manager.h>
|
#include <ardour/export_profile_manager.h>
|
||||||
|
|
||||||
|
|
@ -37,6 +39,7 @@ namespace ARDOUR {
|
||||||
class ExportFilename;
|
class ExportFilename;
|
||||||
class ExportFormatSpecification;
|
class ExportFormatSpecification;
|
||||||
class ExportChannelConfiguration;
|
class ExportChannelConfiguration;
|
||||||
|
class ExportStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ExportTimespanSelector;
|
class ExportTimespanSelector;
|
||||||
|
|
@ -65,6 +68,7 @@ class ExportMainDialog : public ArdourDialog {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
void notify_errors ();
|
||||||
void close_dialog ();
|
void close_dialog ();
|
||||||
|
|
||||||
void sync_with_manager ();
|
void sync_with_manager ();
|
||||||
|
|
@ -82,6 +86,7 @@ class ExportMainDialog : public ArdourDialog {
|
||||||
typedef boost::shared_ptr<ARDOUR::ExportHandler> HandlerPtr;
|
typedef boost::shared_ptr<ARDOUR::ExportHandler> HandlerPtr;
|
||||||
typedef boost::shared_ptr<ARDOUR::ExportFormatSpecification> FormatPtr;
|
typedef boost::shared_ptr<ARDOUR::ExportFormatSpecification> FormatPtr;
|
||||||
typedef boost::shared_ptr<ARDOUR::ExportProfileManager> ManagerPtr;
|
typedef boost::shared_ptr<ARDOUR::ExportProfileManager> ManagerPtr;
|
||||||
|
typedef boost::shared_ptr<ARDOUR::ExportStatus> StatusPtr;
|
||||||
|
|
||||||
void export_rt ();
|
void export_rt ();
|
||||||
void export_fw ();
|
void export_fw ();
|
||||||
|
|
@ -95,6 +100,7 @@ class ExportMainDialog : public ArdourDialog {
|
||||||
PublicEditor & editor;
|
PublicEditor & editor;
|
||||||
HandlerPtr handler;
|
HandlerPtr handler;
|
||||||
ManagerPtr profile_manager;
|
ManagerPtr profile_manager;
|
||||||
|
StatusPtr status;
|
||||||
|
|
||||||
/*** GUI components ***/
|
/*** GUI components ***/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ class ExportChannelConfiguration
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class ExportElementFactory;
|
friend class ExportElementFactory;
|
||||||
ExportChannelConfiguration (ExportStatus & status, Session & session);
|
ExportChannelConfiguration (Session & session);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
XMLNode & get_state ();
|
XMLNode & get_state ();
|
||||||
|
|
@ -115,6 +115,8 @@ class ExportChannelConfiguration
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
typedef boost::shared_ptr<ExportStatus> ExportStatusPtr;
|
||||||
|
|
||||||
Session & session;
|
Session & session;
|
||||||
|
|
||||||
// processor has to be prepared before doing this.
|
// processor has to be prepared before doing this.
|
||||||
|
|
@ -124,7 +126,7 @@ class ExportChannelConfiguration
|
||||||
static void * _write_files (void *arg);
|
static void * _write_files (void *arg);
|
||||||
WriterThread writer_thread;
|
WriterThread writer_thread;
|
||||||
ProcessorPtr processor;
|
ProcessorPtr processor;
|
||||||
ExportStatus & status;
|
ExportStatusPtr status;
|
||||||
|
|
||||||
bool files_written;
|
bool files_written;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,9 +35,8 @@ namespace ARDOUR
|
||||||
class ExportFailed : public std::exception
|
class ExportFailed : public std::exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ExportFailed (std::string const & reason, std::string const & description) :
|
ExportFailed (std::string const & reason) :
|
||||||
reason (reason.c_str()),
|
reason (reason.c_str())
|
||||||
description (description.c_str())
|
|
||||||
{
|
{
|
||||||
error << string_compose (_("Export failed: %1"), reason) << endmsg;
|
error << string_compose (_("Export failed: %1"), reason) << endmsg;
|
||||||
}
|
}
|
||||||
|
|
@ -46,13 +45,12 @@ class ExportFailed : public std::exception
|
||||||
|
|
||||||
const char* what() const throw()
|
const char* what() const throw()
|
||||||
{
|
{
|
||||||
return description;
|
return reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
const char * reason;
|
const char * reason;
|
||||||
const char * description;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,11 +21,20 @@
|
||||||
#ifndef __ardour_export_file_io_h__
|
#ifndef __ardour_export_file_io_h__
|
||||||
#define __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/graph.h>
|
||||||
#include <ardour/types.h>
|
#include <ardour/types.h>
|
||||||
#include <ardour/ardour.h>
|
#include <ardour/ardour.h>
|
||||||
|
#include <ardour/export_format_specification.h>
|
||||||
|
#include <ardour/export_utilities.h>
|
||||||
|
|
||||||
|
using Glib::ustring;
|
||||||
|
|
||||||
namespace ARDOUR
|
namespace ARDOUR
|
||||||
{
|
{
|
||||||
|
|
@ -34,7 +43,6 @@ namespace ARDOUR
|
||||||
class ExportFileWriter
|
class ExportFileWriter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ExportFileWriter (string filename) : _filename (filename) {}
|
|
||||||
virtual ~ExportFileWriter () {}
|
virtual ~ExportFileWriter () {}
|
||||||
|
|
||||||
string filename () const { return _filename; }
|
string filename () const { return _filename; }
|
||||||
|
|
@ -43,6 +51,8 @@ class ExportFileWriter
|
||||||
void set_position (nframes_t position) { _position = position; }
|
void set_position (nframes_t position) { _position = position; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
ExportFileWriter (string filename) : _filename (filename) {}
|
||||||
|
|
||||||
string _filename;
|
string _filename;
|
||||||
nframes_t _position;
|
nframes_t _position;
|
||||||
};
|
};
|
||||||
|
|
@ -51,12 +61,13 @@ class ExportFileWriter
|
||||||
class SndfileWriterBase : public ExportFileWriter
|
class SndfileWriterBase : public ExportFileWriter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SndfileWriterBase (int channels, nframes_t samplerate, int format, string const & path);
|
|
||||||
virtual ~SndfileWriterBase ();
|
|
||||||
|
|
||||||
SNDFILE * get_sndfile () const { return sndfile; }
|
SNDFILE * get_sndfile () const { return sndfile; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
SndfileWriterBase (int channels, nframes_t samplerate, int format, string const & path);
|
||||||
|
virtual ~SndfileWriterBase ();
|
||||||
|
|
||||||
SF_INFO sf_info;
|
SF_INFO sf_info;
|
||||||
SNDFILE * sndfile;
|
SNDFILE * sndfile;
|
||||||
};
|
};
|
||||||
|
|
@ -66,13 +77,17 @@ class SndfileWriterBase : public ExportFileWriter
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class SndfileWriter : public SndfileWriterBase, public GraphSink<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);
|
SndfileWriter (int channels, nframes_t samplerate, int format, string const & path);
|
||||||
|
|
||||||
|
public:
|
||||||
|
nframes_t write (T * data, nframes_t frames);
|
||||||
virtual ~SndfileWriter () {}
|
virtual ~SndfileWriter () {}
|
||||||
|
|
||||||
nframes_t write (T * data, nframes_t frames);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
sf_count_t (*write_func)(SNDFILE *, const T *, sf_count_t);
|
sf_count_t (*write_func)(SNDFILE *, const T *, sf_count_t);
|
||||||
|
|
||||||
private:
|
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
|
} // namespace ARDOUR
|
||||||
|
|
||||||
#endif /* __ardour_export_file_io_h__ */
|
#endif /* __ardour_export_file_io_h__ */
|
||||||
|
|
|
||||||
|
|
@ -170,6 +170,8 @@ class ExportFormatOggVorbis : public ExportFormat {
|
||||||
ExportFormatOggVorbis ();
|
ExportFormatOggVorbis ();
|
||||||
~ExportFormatOggVorbis () {};
|
~ExportFormatOggVorbis () {};
|
||||||
|
|
||||||
|
static bool check_system_compatibility ();
|
||||||
|
|
||||||
bool set_compatibility_state (ExportFormatCompatibility const & compatibility);
|
bool set_compatibility_state (ExportFormatCompatibility const & compatibility);
|
||||||
Type get_type () const { return T_Sndfile; }
|
Type get_type () const { return T_Sndfile; }
|
||||||
SampleFormat get_explicit_sample_format () const { return SF_Vorbis; }
|
SampleFormat get_explicit_sample_format () const { return SF_Vorbis; }
|
||||||
|
|
@ -181,6 +183,8 @@ class ExportFormatFLAC : public ExportFormat, public HasSampleFormat {
|
||||||
ExportFormatFLAC ();
|
ExportFormatFLAC ();
|
||||||
~ExportFormatFLAC () {};
|
~ExportFormatFLAC () {};
|
||||||
|
|
||||||
|
static bool check_system_compatibility ();
|
||||||
|
|
||||||
bool set_compatibility_state (ExportFormatCompatibility const & compatibility);
|
bool set_compatibility_state (ExportFormatCompatibility const & compatibility);
|
||||||
Type get_type () const { return T_Sndfile; }
|
Type get_type () const { return T_Sndfile; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,7 @@ class ExportHandler : public ExportElementFactory, public sigc::trackable
|
||||||
typedef std::multimap<TimespanPtr, FileSpec> ConfigMap;
|
typedef std::multimap<TimespanPtr, FileSpec> ConfigMap;
|
||||||
|
|
||||||
typedef boost::shared_ptr<ExportProcessor> ProcessorPtr;
|
typedef boost::shared_ptr<ExportProcessor> ProcessorPtr;
|
||||||
|
typedef boost::shared_ptr<ExportStatus> StatusPtr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/* Session::get_export_handler() should be used to obtain an export handler
|
/* 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;
|
Session & session;
|
||||||
ProcessorPtr processor;
|
ProcessorPtr processor;
|
||||||
|
StatusPtr export_status;
|
||||||
ConfigMap config_map;
|
ConfigMap config_map;
|
||||||
|
|
||||||
bool realtime;
|
bool realtime;
|
||||||
|
|
|
||||||
|
|
@ -52,14 +52,6 @@ class ExportProcessor
|
||||||
typedef boost::shared_ptr<Normalizer> NormalizerPtr;
|
typedef boost::shared_ptr<Normalizer> NormalizerPtr;
|
||||||
typedef boost::shared_ptr<ExportTempFile> TempFilePtr;
|
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 GraphSink<float> FloatSink;
|
||||||
typedef boost::shared_ptr<FloatSink> FloatSinkPtr;
|
typedef boost::shared_ptr<FloatSink> FloatSinkPtr;
|
||||||
typedef std::vector<FloatSinkPtr> FloatSinkVect;
|
typedef std::vector<FloatSinkPtr> FloatSinkVect;
|
||||||
|
|
@ -96,10 +88,9 @@ class ExportProcessor
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void reset ();
|
void reset ();
|
||||||
FloatSinkPtr prepare_sndfile_writer (FormatPtr format, uint32_t channels, ustring const & filename);
|
|
||||||
|
|
||||||
Session & session;
|
Session & session;
|
||||||
ExportStatus & status;
|
boost::shared_ptr<ExportStatus> status;
|
||||||
|
|
||||||
/* these are initalized in prepare() */
|
/* these are initalized in prepare() */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,8 +47,13 @@ struct ExportStatus {
|
||||||
volatile bool running;
|
volatile bool running;
|
||||||
|
|
||||||
sigc::signal<void> Aborting;
|
sigc::signal<void> Aborting;
|
||||||
void abort () { _aborted = true; Aborting(); }
|
void abort (bool error_occurred = false);
|
||||||
bool aborted () const { return _aborted; }
|
bool aborted () const { return _aborted; }
|
||||||
|
bool errors () const { return _errors; }
|
||||||
|
|
||||||
|
sigc::signal<void> Finished;
|
||||||
|
void finish ();
|
||||||
|
bool finished () const { return _aborted; }
|
||||||
|
|
||||||
/* Progress info */
|
/* Progress info */
|
||||||
|
|
||||||
|
|
@ -66,6 +71,9 @@ struct ExportStatus {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
volatile bool _aborted;
|
volatile bool _aborted;
|
||||||
|
volatile bool _errors;
|
||||||
|
volatile bool _finished;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ARDOUR
|
} // namespace ARDOUR
|
||||||
|
|
|
||||||
|
|
@ -43,10 +43,11 @@ class ExportTimespan : public sigc::trackable
|
||||||
typedef boost::shared_ptr<ExportTempFile> TempFilePtr;
|
typedef boost::shared_ptr<ExportTempFile> TempFilePtr;
|
||||||
typedef std::pair<ExportChannel const, TempFilePtr> ChannelFilePair;
|
typedef std::pair<ExportChannel const, TempFilePtr> ChannelFilePair;
|
||||||
typedef std::map<ExportChannel const, TempFilePtr> TempFileMap;
|
typedef std::map<ExportChannel const, TempFilePtr> TempFileMap;
|
||||||
|
typedef boost::shared_ptr<ExportStatus> ExportStatusPtr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class ExportElementFactory;
|
friend class ExportElementFactory;
|
||||||
ExportTimespan (ExportStatus & status, nframes_t frame_rate);
|
ExportTimespan (ExportStatusPtr status, nframes_t frame_rate);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~ExportTimespan ();
|
~ExportTimespan ();
|
||||||
|
|
@ -78,7 +79,7 @@ class ExportTimespan : public sigc::trackable
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
ExportStatus & status;
|
ExportStatusPtr status;
|
||||||
|
|
||||||
nframes_t start_frame;
|
nframes_t start_frame;
|
||||||
nframes_t end_frame;
|
nframes_t end_frame;
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,6 @@
|
||||||
|
|
||||||
#include <ardour/ardour.h>
|
#include <ardour/ardour.h>
|
||||||
#include <ardour/configuration.h>
|
#include <ardour/configuration.h>
|
||||||
#include <ardour/export_status.h>
|
|
||||||
#include <ardour/location.h>
|
#include <ardour/location.h>
|
||||||
#include <ardour/gain.h>
|
#include <ardour/gain.h>
|
||||||
#include <ardour/io.h>
|
#include <ardour/io.h>
|
||||||
|
|
@ -111,6 +110,7 @@ class SMFSource;
|
||||||
class SessionDirectory;
|
class SessionDirectory;
|
||||||
class SessionMetadata;
|
class SessionMetadata;
|
||||||
class ExportHandler;
|
class ExportHandler;
|
||||||
|
class ExportStatus;
|
||||||
|
|
||||||
struct RouteGroup;
|
struct RouteGroup;
|
||||||
|
|
||||||
|
|
@ -618,27 +618,14 @@ class Session : public PBD::StatefulDestructible
|
||||||
bool sample_rate_convert (import_status&, string infile, string& outfile);
|
bool sample_rate_convert (import_status&, string infile, string& outfile);
|
||||||
string build_tmp_convert_name (string file);
|
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 ();
|
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 start_audio_export (nframes_t position, bool realtime);
|
||||||
int stop_audio_export ();
|
|
||||||
void finalize_audio_export ();
|
|
||||||
void abort_audio_export ();
|
|
||||||
|
|
||||||
sigc::signal<int, nframes_t> ProcessExport;
|
sigc::signal<int, nframes_t> ProcessExport;
|
||||||
sigc::signal<void> ExportFinished;
|
sigc::signal<void> ExportReadFinished;
|
||||||
static sigc::signal<void, std::string, std::string> Exported;
|
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 add_source (boost::shared_ptr<Source>);
|
||||||
void remove_source (boost::weak_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);
|
bool follow_slave (nframes_t, nframes_t);
|
||||||
void set_slave_source (SlaveSource);
|
void set_slave_source (SlaveSource);
|
||||||
|
|
||||||
|
SlaveSource post_export_slave;
|
||||||
|
nframes_t post_export_position;
|
||||||
|
|
||||||
bool _exporting;
|
bool _exporting;
|
||||||
bool _exporting_realtime;
|
bool _exporting_realtime;
|
||||||
|
|
||||||
boost::shared_ptr<ExportHandler> export_handler;
|
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 prepare_diskstreams ();
|
||||||
void commit_diskstreams (nframes_t, bool& session_requires_butler);
|
void commit_diskstreams (nframes_t, bool& session_requires_butler);
|
||||||
|
|
|
||||||
|
|
@ -57,10 +57,10 @@ ExportChannel::read_ports (float * data, nframes_t frames) const
|
||||||
|
|
||||||
/* ExportChannelConfiguration */
|
/* ExportChannelConfiguration */
|
||||||
|
|
||||||
ExportChannelConfiguration::ExportChannelConfiguration (ExportStatus & status, Session & session) :
|
ExportChannelConfiguration::ExportChannelConfiguration (Session & session) :
|
||||||
session (session),
|
session (session),
|
||||||
writer_thread (*this),
|
writer_thread (*this),
|
||||||
status (status),
|
status (session.get_export_status ()),
|
||||||
files_written (false),
|
files_written (false),
|
||||||
split (false)
|
split (false)
|
||||||
{
|
{
|
||||||
|
|
@ -143,7 +143,7 @@ ExportChannelConfiguration::write_files (boost::shared_ptr<ExportProcessor> new_
|
||||||
files_written = true;
|
files_written = true;
|
||||||
|
|
||||||
if (!timespan) {
|
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 */
|
/* 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;
|
uint32_t channel;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (status.aborted()) { break; }
|
if (status->aborted()) { break; }
|
||||||
|
|
||||||
channel = 0;
|
channel = 0;
|
||||||
for (ChannelList::iterator it = channels.begin(); it != channels.end(); ++it) {
|
for (ChannelList::iterator it = channels.begin(); it != channels.end(); ++it) {
|
||||||
|
|
@ -194,7 +194,7 @@ ExportChannelConfiguration::write_file ()
|
||||||
}
|
}
|
||||||
|
|
||||||
progress += frames_read;
|
progress += frames_read;
|
||||||
status.progress = (float) progress / timespan_length;
|
status->progress = (float) progress / timespan_length;
|
||||||
|
|
||||||
} while (processor->process (file_buffer, frames_read) > 0);
|
} while (processor->process (file_buffer, frames_read) > 0);
|
||||||
|
|
||||||
|
|
@ -211,8 +211,9 @@ ExportChannelConfiguration::_write_files (void *arg)
|
||||||
// cc can be trated like 'this'
|
// cc can be trated like 'this'
|
||||||
WriterThread & cc (*((WriterThread *) arg));
|
WriterThread & cc (*((WriterThread *) arg));
|
||||||
|
|
||||||
|
try {
|
||||||
for (FileConfigList::iterator it = cc->file_configs.begin(); it != cc->file_configs.end(); ++it) {
|
for (FileConfigList::iterator it = cc->file_configs.begin(); it != cc->file_configs.end(); ++it) {
|
||||||
if (cc->status.aborted()) {
|
if (cc->status->aborted()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cc->processor->prepare (it->first, it->second, cc->channels.size(), cc->split, cc->timespan->get_start());
|
cc->processor->prepare (it->first, it->second, cc->channels.size(), cc->split, cc->timespan->get_start());
|
||||||
|
|
@ -220,6 +221,9 @@ ExportChannelConfiguration::_write_files (void *arg)
|
||||||
cc->processor->prepare_post_processors ();
|
cc->processor->prepare_post_processors ();
|
||||||
cc->processor->write_files();
|
cc->processor->write_files();
|
||||||
}
|
}
|
||||||
|
} catch (ExportFailed & e) {
|
||||||
|
cc->status->abort (true);
|
||||||
|
}
|
||||||
|
|
||||||
cc.running = false;
|
cc.running = false;
|
||||||
cc->files_written = true;
|
cc->files_written = true;
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <ardour/export_file_io.h>
|
#include <ardour/export_file_io.h>
|
||||||
|
|
||||||
#include <ardour/export_failed.h>
|
#include <ardour/export_failed.h>
|
||||||
#include <pbd/failed_constructor.h>
|
#include <pbd/failed_constructor.h>
|
||||||
|
|
||||||
|
|
@ -43,11 +44,11 @@ SndfileWriterBase::SndfileWriterBase (int channels, nframes_t samplerate, int fo
|
||||||
sf_info.format = format;
|
sf_info.format = format;
|
||||||
|
|
||||||
if (!sf_format_check (&sf_info)) {
|
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) {
|
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
|
/* 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 (path.compare ("temp")) {
|
||||||
if ((sndfile = sf_open (path.c_str(), SFM_WRITE, &sf_info)) == 0) {
|
if ((sndfile = sf_open (path.c_str(), SFM_WRITE, &sf_info)) == 0) {
|
||||||
sf_error_str (0, errbuf, sizeof (errbuf) - 1);
|
sf_error_str (0, errbuf, sizeof (errbuf) - 1);
|
||||||
throw ExportFailed (string_compose(_("Export: cannot open output file \"%1\""), path),
|
throw ExportFailed (string_compose(X_("Cannot open output file \"%1\" for SndFileWriter (%2)"), path, errbuf));
|
||||||
string_compose(_("Export: cannot open output file \"%1\" for SndFileWriter (%2)"), path, errbuf));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
FILE * file;
|
FILE * file;
|
||||||
if (!(file = tmpfile ())) {
|
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);
|
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);
|
nframes_t written = (*write_func) (sndfile, data, frames);
|
||||||
if (written != frames) {
|
if (written != frames) {
|
||||||
sf_error_str (sndfile, errbuf, sizeof (errbuf) - 1);
|
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) {
|
if (GraphSink<T>::end_of_input) {
|
||||||
|
|
@ -198,7 +198,7 @@ ExportTempFile::read (float * data, nframes_t frames)
|
||||||
/* Check for errors */
|
/* Check for errors */
|
||||||
|
|
||||||
if (read_status != to_read) {
|
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 */
|
/* Add silence at end */
|
||||||
|
|
@ -365,4 +365,82 @@ ExportTempFile::_read (float * data, nframes_t frames)
|
||||||
return sf_readf_float (sndfile, data, 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
|
||||||
|
|
|
||||||
|
|
@ -185,11 +185,15 @@ ExportFormatManager::init_formats ()
|
||||||
fl_ptr->set_extension ("raw");
|
fl_ptr->set_extension ("raw");
|
||||||
add_format (f_ptr);
|
add_format (f_ptr);
|
||||||
|
|
||||||
|
if (ExportFormatOggVorbis::check_system_compatibility()) {
|
||||||
f_ptr.reset (new ExportFormatOggVorbis ());
|
f_ptr.reset (new ExportFormatOggVorbis ());
|
||||||
add_format (f_ptr);
|
add_format (f_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ExportFormatFLAC::check_system_compatibility()) {
|
||||||
f_ptr.reset (new ExportFormatFLAC ());
|
f_ptr.reset (new ExportFormatFLAC ());
|
||||||
add_format (f_ptr);
|
add_format (f_ptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -251,6 +251,17 @@ ExportFormatOggVorbis::ExportFormatOggVorbis ()
|
||||||
set_quality (Q_LossyCompression);
|
set_quality (Q_LossyCompression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
bool
|
||||||
ExportFormatOggVorbis::set_compatibility_state (ExportFormatCompatibility const & compatibility)
|
ExportFormatOggVorbis::set_compatibility_state (ExportFormatCompatibility const & compatibility)
|
||||||
{
|
{
|
||||||
|
|
@ -284,6 +295,17 @@ ExportFormatFLAC::ExportFormatFLAC () :
|
||||||
set_quality (Q_LosslessCompression);
|
set_quality (Q_LosslessCompression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
bool
|
||||||
ExportFormatFLAC::set_compatibility_state (ExportFormatCompatibility const & compatibility)
|
ExportFormatFLAC::set_compatibility_state (ExportFormatCompatibility const & compatibility)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -55,13 +55,13 @@ ExportElementFactory::~ExportElementFactory ()
|
||||||
ExportElementFactory::TimespanPtr
|
ExportElementFactory::TimespanPtr
|
||||||
ExportElementFactory::add_timespan ()
|
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::ChannelConfigPtr
|
||||||
ExportElementFactory::add_channel_config ()
|
ExportElementFactory::add_channel_config ()
|
||||||
{
|
{
|
||||||
return ChannelConfigPtr (new ExportChannelConfiguration (session.export_status, session));
|
return ChannelConfigPtr (new ExportChannelConfiguration (session));
|
||||||
}
|
}
|
||||||
|
|
||||||
ExportElementFactory::FormatPtr
|
ExportElementFactory::FormatPtr
|
||||||
|
|
@ -99,6 +99,7 @@ ExportElementFactory::add_filename_copy (FilenamePtr other)
|
||||||
ExportHandler::ExportHandler (Session & session) :
|
ExportHandler::ExportHandler (Session & session) :
|
||||||
ExportElementFactory (session),
|
ExportElementFactory (session),
|
||||||
session (session),
|
session (session),
|
||||||
|
export_status (session.get_export_status ()),
|
||||||
realtime (false)
|
realtime (false)
|
||||||
{
|
{
|
||||||
processor.reset (new ExportProcessor (session));
|
processor.reset (new ExportProcessor (session));
|
||||||
|
|
@ -108,7 +109,7 @@ ExportHandler::ExportHandler (Session & session) :
|
||||||
|
|
||||||
ExportHandler::~ExportHandler ()
|
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) {
|
for (std::list<Glib::ustring>::iterator it = files_written.begin(); it != files_written.end(); ++it) {
|
||||||
sys::remove (sys::path (*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
|
* 1. Session is prepared in do_export
|
||||||
* 2. start_timespan is called, which then registers all necessary channel configs to a timespan
|
* 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
|
* 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
|
* 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
|
* 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
|
* for the current timespan, calling write_files for it
|
||||||
|
|
@ -148,20 +149,18 @@ ExportHandler::do_export (bool rt)
|
||||||
{
|
{
|
||||||
/* Count timespans */
|
/* Count timespans */
|
||||||
|
|
||||||
ExportStatus & status = session.export_status;
|
export_status->init();
|
||||||
status.init();
|
|
||||||
std::set<TimespanPtr> timespan_set;
|
std::set<TimespanPtr> timespan_set;
|
||||||
for (ConfigMap::iterator it = config_map.begin(); it != config_map.end(); ++it) {
|
for (ConfigMap::iterator it = config_map.begin(); it != config_map.end(); ++it) {
|
||||||
timespan_set.insert (it->first);
|
timespan_set.insert (it->first);
|
||||||
}
|
}
|
||||||
status.total_timespans = timespan_set.size();
|
export_status->total_timespans = timespan_set.size();
|
||||||
|
|
||||||
/* Start export */
|
/* Start export */
|
||||||
|
|
||||||
realtime = rt;
|
realtime = rt;
|
||||||
|
|
||||||
session.ExportFinished.connect (sigc::mem_fun (*this, &ExportHandler::finish_timespan));
|
session.ExportReadFinished.connect (sigc::mem_fun (*this, &ExportHandler::finish_timespan));
|
||||||
session.pre_export ();
|
|
||||||
start_timespan ();
|
start_timespan ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -442,10 +441,10 @@ ExportHandler::frames_to_cd_frames_string (char* buf, nframes_t when)
|
||||||
void
|
void
|
||||||
ExportHandler::start_timespan ()
|
ExportHandler::start_timespan ()
|
||||||
{
|
{
|
||||||
session.export_status.timespan++;
|
export_status->timespan++;
|
||||||
|
|
||||||
if (config_map.empty()) {
|
if (config_map.empty()) {
|
||||||
session.finalize_audio_export();
|
export_status->finish ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -472,12 +471,12 @@ ExportHandler::finish_timespan ()
|
||||||
|
|
||||||
/* Register formats and filenames to relevant channel configs */
|
/* Register formats and filenames to relevant channel configs */
|
||||||
|
|
||||||
session.export_status.total_formats = 0;
|
export_status->total_formats = 0;
|
||||||
session.export_status.format = 0;
|
export_status->format = 0;
|
||||||
|
|
||||||
for (ConfigMap::iterator it = timespan_bounds.first; it != timespan_bounds.second; ++it) {
|
for (ConfigMap::iterator it = timespan_bounds.first; it != timespan_bounds.second; ++it) {
|
||||||
|
|
||||||
session.export_status.total_formats++;
|
export_status->total_formats++;
|
||||||
|
|
||||||
/* Setup filename */
|
/* Setup filename */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ ExportProfileManager::register_all_configs ()
|
||||||
|
|
||||||
TimespanNodePtr ts_node;
|
TimespanNodePtr ts_node;
|
||||||
if (!(ts_node = boost::dynamic_pointer_cast<TimespanNode> (*tsl_it))) {
|
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;
|
TimespanListPtr ts_list = ts_node->data()->timespans;
|
||||||
|
|
@ -30,19 +30,19 @@ ExportProfileManager::register_all_configs ()
|
||||||
|
|
||||||
ChannelConfigNode * cc_node;
|
ChannelConfigNode * cc_node;
|
||||||
if (!(cc_node = dynamic_cast<ChannelConfigNode *> (*cc_it))) {
|
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;
|
ChannelConfigPtr channel_config = cc_node->data()->config;
|
||||||
|
|
||||||
FormatNode * f_node;
|
FormatNode * f_node;
|
||||||
if (!(f_node = dynamic_cast<FormatNode *> (*f_it))) {
|
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;
|
FormatPtr format = f_node->data()->format;
|
||||||
|
|
||||||
FilenameNode * fn_node;
|
FilenameNode * fn_node;
|
||||||
if (!(fn_node = dynamic_cast<FilenameNode *> (*fn_it))) {
|
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;
|
FilenamePtr filename = fn_node->data()->filename;
|
||||||
|
|
||||||
|
|
@ -443,7 +443,7 @@ ExportProfileManager::duplicate_timespan_children (TimespanNodePtr source, Times
|
||||||
ChannelConfigNode * node_insertion_ptr;
|
ChannelConfigNode * node_insertion_ptr;
|
||||||
if (!insertion_point) { insertion_point = source->last_child(); }
|
if (!insertion_point) { insertion_point = source->last_child(); }
|
||||||
if (!(node_insertion_ptr = dynamic_cast<ChannelConfigNode *> (insertion_point))) {
|
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();
|
node_insertion_point = node_insertion_ptr->self_ptr();
|
||||||
|
|
||||||
|
|
@ -460,7 +460,7 @@ ExportProfileManager::duplicate_timespan_children (TimespanNodePtr source, Times
|
||||||
ChannelConfigNodePtr new_node;
|
ChannelConfigNodePtr new_node;
|
||||||
|
|
||||||
if (!(node = dynamic_cast<ChannelConfigNode *> (*it))) {
|
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());
|
new_node = duplicate_channel_config_node (node->self_ptr());
|
||||||
|
|
@ -509,7 +509,7 @@ ExportProfileManager::duplicate_channel_config_children (ChannelConfigNodePtr so
|
||||||
FormatNode * node_insertion_ptr;
|
FormatNode * node_insertion_ptr;
|
||||||
if (!insertion_point) { insertion_point = source->last_child(); }
|
if (!insertion_point) { insertion_point = source->last_child(); }
|
||||||
if (!(node_insertion_ptr = dynamic_cast<FormatNode *> (insertion_point))) {
|
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();
|
node_insertion_point = node_insertion_ptr->self_ptr();
|
||||||
|
|
||||||
|
|
@ -526,7 +526,7 @@ ExportProfileManager::duplicate_channel_config_children (ChannelConfigNodePtr so
|
||||||
FormatNodePtr new_node;
|
FormatNodePtr new_node;
|
||||||
|
|
||||||
if (!(node = dynamic_cast<FormatNode *> (*it))) {
|
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());
|
new_node = duplicate_format_node (node->self_ptr());
|
||||||
|
|
@ -573,7 +573,7 @@ ExportProfileManager::duplicate_format_children (FormatNodePtr source, FormatNod
|
||||||
FilenameNode * node_insertion_ptr;
|
FilenameNode * node_insertion_ptr;
|
||||||
if (!insertion_point) { insertion_point = source->last_child(); }
|
if (!insertion_point) { insertion_point = source->last_child(); }
|
||||||
if (!(node_insertion_ptr = dynamic_cast<FilenameNode *> (insertion_point))) {
|
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();
|
node_insertion_point = node_insertion_ptr->self_ptr();
|
||||||
|
|
||||||
|
|
@ -584,7 +584,7 @@ ExportProfileManager::duplicate_format_children (FormatNodePtr source, FormatNod
|
||||||
FilenameNodePtr new_node;
|
FilenameNodePtr new_node;
|
||||||
|
|
||||||
if (!(node = dynamic_cast<FilenameNode *> (*it))) {
|
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());
|
new_node = duplicate_filename_node (node->self_ptr());
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@
|
||||||
#include <ardour/export_filename.h>
|
#include <ardour/export_filename.h>
|
||||||
#include <ardour/export_status.h>
|
#include <ardour/export_status.h>
|
||||||
#include <ardour/export_format_specification.h>
|
#include <ardour/export_format_specification.h>
|
||||||
#include <ardour/sndfile_helpers.h>
|
|
||||||
|
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
|
|
@ -43,7 +42,7 @@ sigc::signal<void, Glib::ustring> ExportProcessor::WritingFile;
|
||||||
|
|
||||||
ExportProcessor::ExportProcessor (Session & session) :
|
ExportProcessor::ExportProcessor (Session & session) :
|
||||||
session (session),
|
session (session),
|
||||||
status (session.export_status),
|
status (session.get_export_status()),
|
||||||
blocksize (session.get_block_size()),
|
blocksize (session.get_block_size()),
|
||||||
frame_rate (session.frame_rate())
|
frame_rate (session.frame_rate())
|
||||||
{
|
{
|
||||||
|
|
@ -70,7 +69,7 @@ ExportProcessor::reset ()
|
||||||
int
|
int
|
||||||
ExportProcessor::prepare (FormatPtr format, FilenamePtr fname, uint32_t chans, bool split, nframes_t start)
|
ExportProcessor::prepare (FormatPtr format, FilenamePtr fname, uint32_t chans, bool split, nframes_t start)
|
||||||
{
|
{
|
||||||
session.export_status.format++;
|
status->format++;
|
||||||
temp_file_length = 0;
|
temp_file_length = 0;
|
||||||
|
|
||||||
/* Reset just to be sure all references are dropped */
|
/* 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 */
|
/* Construct export pipe to temp file */
|
||||||
|
|
||||||
status.stage = export_PostProcess;
|
status->stage = export_PostProcess;
|
||||||
|
|
||||||
if (normalize) {
|
if (normalize) {
|
||||||
/* Normalizing => we need a normalizer, peak reader and tempfile */
|
/* 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);
|
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 */
|
/* Ensure directory exists */
|
||||||
|
|
||||||
sys::path folder (filename->get_folder());
|
sys::path folder (filename->get_folder());
|
||||||
if (!sys::exists (folder)) {
|
if (!sys::exists (folder)) {
|
||||||
if (!sys::create_directory (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;
|
filename->include_channel = true;
|
||||||
for (uint32_t chn = 1; chn <= channels; ++chn) {
|
for (uint32_t chn = 1; chn <= channels; ++chn) {
|
||||||
filename->set_channel (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));
|
WritingFile (filename->get_path (format));
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} 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));
|
WritingFile (filename->get_path (format));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -229,7 +217,7 @@ ExportProcessor::write_files ()
|
||||||
{
|
{
|
||||||
/* Write to disk */
|
/* Write to disk */
|
||||||
|
|
||||||
status.stage = export_Write;
|
status->stage = export_Write;
|
||||||
temp_file_position = 0;
|
temp_file_position = 0;
|
||||||
|
|
||||||
uint32_t buffer_size = 4096; // TODO adjust buffer size?
|
uint32_t buffer_size = 4096; // TODO adjust buffer size?
|
||||||
|
|
@ -270,9 +258,9 @@ ExportProcessor::write_files ()
|
||||||
disk_sink->write (chan_bufs[channel], frames_read);
|
disk_sink->write (chan_bufs[channel], frames_read);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status.aborted()) { break; }
|
if (status->aborted()) { break; }
|
||||||
temp_file_position += frames_read;
|
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 */
|
/* Clean up */
|
||||||
|
|
@ -285,9 +273,9 @@ ExportProcessor::write_files ()
|
||||||
while ((frames_read = temp_file->read (buf, buffer_size)) > 0) {
|
while ((frames_read = temp_file->read (buf, buffer_size)) > 0) {
|
||||||
disk_sink->write (buf, frames_read);
|
disk_sink->write (buf, frames_read);
|
||||||
|
|
||||||
if (status.aborted()) { break; }
|
if (status->aborted()) { break; }
|
||||||
temp_file_position += frames_read;
|
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
|
}; // namespace ARDOUR
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
#include <pbd/convert.h>
|
#include <pbd/convert.h>
|
||||||
|
|
||||||
#include <ardour/export_failed.h>
|
#include <ardour/export_failed.h>
|
||||||
|
#include <ardour/export_file_io.h>
|
||||||
#include <ardour/export_format_specification.h>
|
#include <ardour/export_format_specification.h>
|
||||||
#include <ardour/export_timespan.h>
|
#include <ardour/export_timespan.h>
|
||||||
#include <ardour/export_channel_configuration.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 */
|
/* Check format and maximum channel count */
|
||||||
if (!format || !format->type()) {
|
if (!format || !format->type()) {
|
||||||
warnings->errors.push_back (_("No format selected!"));
|
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()) {
|
} else if (format->channel_limit() < channel_config->get_n_chans()) {
|
||||||
warnings->errors.push_back
|
warnings->errors.push_back
|
||||||
(string_compose (_("%1 supports only %2 channels, but you have %3 channels in your channel configuration"),
|
(string_compose (_("%1 supports only %2 channels, but you have %3 channels in your channel configuration"),
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,8 @@ ExportStatus::init ()
|
||||||
stop = false;
|
stop = false;
|
||||||
running = false;
|
running = false;
|
||||||
_aborted = false;
|
_aborted = false;
|
||||||
|
_finished = false;
|
||||||
|
_errors = false;
|
||||||
|
|
||||||
stage = export_None;
|
stage = export_None;
|
||||||
progress = 0.0;
|
progress = 0.0;
|
||||||
|
|
@ -48,4 +50,20 @@ ExportStatus::init ()
|
||||||
format = 0;
|
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
|
} // namespace ARDOUR
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
namespace ARDOUR
|
namespace ARDOUR
|
||||||
{
|
{
|
||||||
|
|
||||||
ExportTimespan::ExportTimespan (ExportStatus & status, nframes_t frame_rate) :
|
ExportTimespan::ExportTimespan (ExportStatusPtr status, nframes_t frame_rate) :
|
||||||
status (status),
|
status (status),
|
||||||
start_frame (0),
|
start_frame (0),
|
||||||
end_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);
|
TempFileMap::iterator it = filemap.find (channel);
|
||||||
if (it == filemap.end()) {
|
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);
|
return it->second->read (data, frames);
|
||||||
|
|
@ -79,7 +79,7 @@ ExportTimespan::set_range (nframes_t start, nframes_t end)
|
||||||
int
|
int
|
||||||
ExportTimespan::process (nframes_t frames)
|
ExportTimespan::process (nframes_t frames)
|
||||||
{
|
{
|
||||||
status.stage = export_ReadTimespan;
|
status->stage = export_ReadTimespan;
|
||||||
|
|
||||||
/* update position */
|
/* update position */
|
||||||
|
|
||||||
|
|
@ -89,11 +89,11 @@ ExportTimespan::process (nframes_t frames)
|
||||||
frames_to_read = frames;
|
frames_to_read = frames;
|
||||||
} else {
|
} else {
|
||||||
frames_to_read = end_frame - position;
|
frames_to_read = end_frame - position;
|
||||||
status.stop = true;
|
status->stop = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
position += frames_to_read;
|
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 */
|
/* Read channels from ports and save to tempfiles */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ SampleRateConverter::SampleRateConverter (uint32_t channels, nframes_t in_rate,
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if ((src_state = src_new (quality, channels, &err)) == 0) {
|
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;
|
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;
|
max_leftover_frames = 4 * frames;
|
||||||
leftover_data = (float *) realloc (leftover_data, max_leftover_frames * channels * sizeof (float));
|
leftover_data = (float *) realloc (leftover_data, max_leftover_frames * channels * sizeof (float));
|
||||||
if (!leftover_data) {
|
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;
|
data_out_size = out_samples_max;
|
||||||
|
|
@ -161,7 +161,7 @@ SampleRateConverter::process (float * data, nframes_t frames)
|
||||||
++cnt;
|
++cnt;
|
||||||
|
|
||||||
if ((err = src_process (src_state, &src_data)) != 0) {
|
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;
|
frames_out = src_data.output_frames_gen;
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
#include <ardour/export_file_io.h>
|
#include <ardour/export_file_io.h>
|
||||||
#include <ardour/export_utilities.h>
|
#include <ardour/export_utilities.h>
|
||||||
#include <ardour/export_handler.h>
|
#include <ardour/export_handler.h>
|
||||||
|
#include <ardour/export_status.h>
|
||||||
#include <ardour/timestamps.h>
|
#include <ardour/timestamps.h>
|
||||||
#include <ardour/ardour.h>
|
#include <ardour/ardour.h>
|
||||||
#include <ardour/session.h>
|
#include <ardour/session.h>
|
||||||
|
|
@ -49,17 +50,20 @@ Session::get_export_handler ()
|
||||||
return export_handler;
|
return export_handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
boost::shared_ptr<ExportStatus>
|
||||||
Session::release_export_handler ()
|
Session::get_export_status ()
|
||||||
{
|
{
|
||||||
if (!_exporting) {
|
if (!export_status) {
|
||||||
export_handler.reset();
|
export_status.reset (new ExportStatus ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return export_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
Session::pre_export ()
|
Session::pre_export ()
|
||||||
{
|
{
|
||||||
|
get_export_status (); // Init export_status
|
||||||
|
|
||||||
wait_till_butler_finished ();
|
wait_till_butler_finished ();
|
||||||
|
|
||||||
|
|
@ -87,8 +91,8 @@ Session::pre_export ()
|
||||||
Config->set_slave_source (None);
|
Config->set_slave_source (None);
|
||||||
|
|
||||||
_exporting = true;
|
_exporting = true;
|
||||||
export_status.running = true;
|
export_status->running = true;
|
||||||
export_abort_connection = export_status.Aborting.connect (sigc::mem_fun (*this, &Session::abort_audio_export));
|
export_abort_connection = export_status->Aborting.connect (sigc::hide_return (sigc::mem_fun (*this, &Session::stop_audio_export)));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -96,6 +100,10 @@ Session::pre_export ()
|
||||||
int
|
int
|
||||||
Session::start_audio_export (nframes_t position, bool realtime)
|
Session::start_audio_export (nframes_t position, bool realtime)
|
||||||
{
|
{
|
||||||
|
if (!_exporting) {
|
||||||
|
pre_export ();
|
||||||
|
}
|
||||||
|
|
||||||
/* get everyone to the right position */
|
/* get everyone to the right position */
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
@ -119,7 +127,7 @@ Session::start_audio_export (nframes_t position, bool realtime)
|
||||||
_transport_frame = position;
|
_transport_frame = position;
|
||||||
|
|
||||||
_exporting_realtime = realtime;
|
_exporting_realtime = realtime;
|
||||||
export_status.stop = false;
|
export_status->stop = false;
|
||||||
|
|
||||||
/* get transport ready. note how this is calling butler functions
|
/* get transport ready. note how this is calling butler functions
|
||||||
from a non-butler thread. we waited for the butler to stop
|
from a non-butler thread. we waited for the butler to stop
|
||||||
|
|
@ -154,7 +162,7 @@ Session::process_export (nframes_t nframes)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if (export_status.stop) {
|
if (export_status->stop) {
|
||||||
stop_audio_export ();
|
stop_audio_export ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -176,11 +184,7 @@ Session::process_export (nframes_t nframes)
|
||||||
ProcessExport (nframes);
|
ProcessExport (nframes);
|
||||||
|
|
||||||
} catch (ExportFailed e) {
|
} catch (ExportFailed e) {
|
||||||
|
export_status->abort (true);
|
||||||
std::cerr << e.what() << std::endl;
|
|
||||||
stop_audio_export();
|
|
||||||
finalize_audio_export();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -208,8 +212,12 @@ Session::stop_audio_export ()
|
||||||
realtime_stop (true);
|
realtime_stop (true);
|
||||||
schedule_butler_transport_work ();
|
schedule_butler_transport_work ();
|
||||||
|
|
||||||
if (!export_status.aborted()) {
|
if (!export_status->aborted()) {
|
||||||
ExportFinished ();
|
ExportReadFinished ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (export_status->finished()) {
|
||||||
|
finalize_audio_export ();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -220,7 +228,7 @@ void
|
||||||
Session::finalize_audio_export ()
|
Session::finalize_audio_export ()
|
||||||
{
|
{
|
||||||
_exporting = false;
|
_exporting = false;
|
||||||
export_status.running = false;
|
export_status->running = false;
|
||||||
|
|
||||||
if (!_exporting_realtime) {
|
if (!_exporting_realtime) {
|
||||||
_engine.freewheel (false);
|
_engine.freewheel (false);
|
||||||
|
|
@ -230,10 +238,11 @@ Session::finalize_audio_export ()
|
||||||
/* Clean up */
|
/* Clean up */
|
||||||
|
|
||||||
ProcessExport.clear();
|
ProcessExport.clear();
|
||||||
ExportFinished.clear();
|
ExportReadFinished.clear();
|
||||||
export_freewheel_connection.disconnect();
|
export_freewheel_connection.disconnect();
|
||||||
export_abort_connection.disconnect();
|
export_abort_connection.disconnect();
|
||||||
export_handler.reset();
|
export_handler.reset();
|
||||||
|
export_status.reset();
|
||||||
|
|
||||||
/* restart slaving */
|
/* restart slaving */
|
||||||
|
|
||||||
|
|
@ -243,10 +252,3 @@ Session::finalize_audio_export ()
|
||||||
locate (post_export_position, false, false, false);
|
locate (post_export_position, false, false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
Session::abort_audio_export ()
|
|
||||||
{
|
|
||||||
stop_audio_export ();
|
|
||||||
finalize_audio_export ();
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue