various fixes for exporting, including correct handling of errors during export which previously would hang when using jack1 because jack_set_freewheel() was called from inside a process() callback; use shared_ptr<Route> in parts of export code that weren't using them before; fix up generation of export filenames so that Glib::build_filename() is used and non-existent folders are ignored

git-svn-id: svn://localhost/ardour2/branches/3.0@13610 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2012-12-06 19:56:33 +00:00
parent 27bfb0f9e2
commit 9884773eea
12 changed files with 69 additions and 59 deletions

View file

@ -570,34 +570,31 @@ TrackExportChannelSelector::fill_list()
RouteList routes = *_session->get_routes(); RouteList routes = *_session->get_routes();
for (RouteList::iterator it = routes.begin(); it != routes.end(); ++it) { for (RouteList::iterator it = routes.begin(); it != routes.end(); ++it) {
Route * route = it->get(); if (!boost::dynamic_pointer_cast<Track>(*it)) {
if(!dynamic_cast<Track *>(route)) {
// not a track, must be a bus // not a track, must be a bus
if ((*it)->is_master () || (*it)->is_monitor ()) { if ((*it)->is_master () || (*it)->is_monitor ()) {
continue; continue;
} }
// not monitor or master bus // not monitor or master bus
add_track (*it);
add_track(route);
} }
} }
for (RouteList::iterator it = routes.begin(); it != routes.end(); ++it) { for (RouteList::iterator it = routes.begin(); it != routes.end(); ++it) {
Route * route = it->get(); if (boost::dynamic_pointer_cast<AudioTrack>(*it)) {
if(dynamic_cast<AudioTrack *>(route)) { add_track (*it);
add_track(route);
} }
} }
} }
void void
TrackExportChannelSelector::add_track(Route * route) TrackExportChannelSelector::add_track (boost::shared_ptr<Route> route)
{ {
Gtk::TreeModel::iterator iter = track_list->append(); Gtk::TreeModel::iterator iter = track_list->append();
Gtk::TreeModel::Row row = *iter; Gtk::TreeModel::Row row = *iter;
row[track_cols.selected] = true; row[track_cols.selected] = true;
row[track_cols.label] = route->name(); row[track_cols.label] = route->name();
row[track_cols.track] = route; row[track_cols.route] = route;
} }
void void
@ -614,12 +611,12 @@ TrackExportChannelSelector::update_config()
ExportProfileManager::ChannelConfigStatePtr state = manager->add_channel_config(); ExportProfileManager::ChannelConfigStatePtr state = manager->add_channel_config();
Route * track = row[track_cols.track]; boost::shared_ptr<Route> route = row[track_cols.route];
/* Output of track code. TODO make this an option also /* Output of track code. TODO make this an option also
uint32_t outs = track->n_ports().n_audio(); uint32_t outs = route->n_ports().n_audio();
for (uint32_t i = 0; i < outs; ++i) { for (uint32_t i = 0; i < outs; ++i) {
AudioPort * port = track->audio (i); AudioPort * port = route->audio (i);
if (port) { if (port) {
ExportChannelPtr channel (new PortExportChannel ()); ExportChannelPtr channel (new PortExportChannel ());
PortExportChannel * pec = static_cast<PortExportChannel *> (channel.get()); PortExportChannel * pec = static_cast<PortExportChannel *> (channel.get());
@ -630,9 +627,9 @@ TrackExportChannelSelector::update_config()
*/ */
std::list<ExportChannelPtr> list; std::list<ExportChannelPtr> list;
RouteExportChannel::create_from_route (list, *track); RouteExportChannel::create_from_route (list, route);
state->config->register_channels (list); state->config->register_channels (list);
state->config->set_name(track->name()); state->config->set_name (route->name());
} }
CriticalSelectionChanged (); CriticalSelectionChanged ();

View file

@ -235,7 +235,7 @@ class TrackExportChannelSelector : public ExportChannelSelector
private: private:
void fill_list(); void fill_list();
void add_track(ARDOUR::Route * route); void add_track (boost::shared_ptr<ARDOUR::Route> route);
void update_config(); void update_config();
ChannelConfigList configs; ChannelConfigList configs;
@ -243,11 +243,11 @@ class TrackExportChannelSelector : public ExportChannelSelector
struct TrackCols : public Gtk::TreeModelColumnRecord struct TrackCols : public Gtk::TreeModelColumnRecord
{ {
public: public:
Gtk::TreeModelColumn<ARDOUR::Route *> track; Gtk::TreeModelColumn<boost::shared_ptr<ARDOUR::Route> > route;
Gtk::TreeModelColumn<std::string> label; Gtk::TreeModelColumn<std::string> label;
Gtk::TreeModelColumn<bool> selected; Gtk::TreeModelColumn<bool> selected;
TrackCols () { add (track); add(label); add(selected); } TrackCols () { add (route); add(label); add(selected); }
}; };
TrackCols track_cols; TrackCols track_cols;

View file

@ -21,6 +21,8 @@
#include <sigc++/signal.h> #include <sigc++/signal.h>
#include <gtkmm/messagedialog.h>
#include "ardour/audioregion.h" #include "ardour/audioregion.h"
#include "ardour/export_status.h" #include "ardour/export_status.h"
#include "ardour/export_handler.h" #include "ardour/export_handler.h"
@ -94,8 +96,6 @@ ExportDialog::set_session (ARDOUR::Session* s)
channel_selector->CriticalSelectionChanged.connect (sigc::mem_fun (*this, &ExportDialog::update_warnings_and_example_filename)); channel_selector->CriticalSelectionChanged.connect (sigc::mem_fun (*this, &ExportDialog::update_warnings_and_example_filename));
file_notebook->CriticalSelectionChanged.connect (sigc::mem_fun (*this, &ExportDialog::update_warnings_and_example_filename)); file_notebook->CriticalSelectionChanged.connect (sigc::mem_fun (*this, &ExportDialog::update_warnings_and_example_filename));
status->Aborting.connect (abort_connection, invalidator (*this), boost::bind (&ExportDialog::notify_errors, this), gui_context());
update_warnings_and_example_filename (); update_warnings_and_example_filename ();
} }
@ -323,6 +323,7 @@ ExportDialog::show_progress ()
progress_connection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &ExportDialog::progress_timeout), 100); progress_connection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &ExportDialog::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 ();
@ -339,10 +340,12 @@ ExportDialog::show_progress ()
ns->nag (); ns->nag ();
delete ns; delete ns;
} }
} else {
notify_errors ();
}
status->finish (); status->finish ();
} }
}
gint gint
ExportDialog::progress_timeout () ExportDialog::progress_timeout ()

View file

@ -111,7 +111,6 @@ class ExportDialog : public ArdourDialog {
PublicEditor & editor; PublicEditor & editor;
StatusPtr status; StatusPtr status;
PBD::ScopedConnection abort_connection;
/*** GUI components ***/ /*** GUI components ***/

View file

@ -161,7 +161,7 @@ class RouteExportChannel : public ExportChannel
boost::shared_ptr<ProcessorRemover> remover); boost::shared_ptr<ProcessorRemover> remover);
~RouteExportChannel(); ~RouteExportChannel();
static void create_from_route(std::list<ExportChannelPtr> & result, Route & route); static void create_from_route(std::list<ExportChannelPtr> & result, boost::shared_ptr<Route> route);
public: // ExportChannel interface public: // ExportChannel interface
void set_max_buffer_size(framecnt_t frames); void set_max_buffer_size(framecnt_t frames);
@ -179,11 +179,11 @@ class RouteExportChannel : public ExportChannel
// Removes the processor from the track when deleted // Removes the processor from the track when deleted
class ProcessorRemover { class ProcessorRemover {
public: public:
ProcessorRemover (Route & route, boost::shared_ptr<CapturingProcessor> processor) ProcessorRemover (boost::shared_ptr<Route> route, boost::shared_ptr<CapturingProcessor> processor)
: route (route), processor (processor) {} : route (route), processor (processor) {}
~ProcessorRemover(); ~ProcessorRemover();
private: private:
Route & route; boost::shared_ptr<Route> route;
boost::shared_ptr<CapturingProcessor> processor; boost::shared_ptr<CapturingProcessor> processor;
}; };

View file

@ -40,7 +40,6 @@ class ExportStatus {
volatile bool stop; volatile bool stop;
volatile bool running; volatile bool running;
PBD::Signal0<void> Aborting;
void abort (bool error_occurred = false); void abort (bool error_occurred = false);
bool aborted () const { return _aborted; } bool aborted () const { return _aborted; }
bool errors () const { return _errors; } bool errors () const { return _errors; }
@ -49,6 +48,8 @@ class ExportStatus {
void finish (); void finish ();
bool finished () const { return _finished; } bool finished () const { return _finished; }
void cleanup ();
/* Progress info */ /* Progress info */
volatile bool normalizing; volatile bool normalizing;

View file

@ -941,7 +941,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
void process_without_events (pframes_t); void process_without_events (pframes_t);
void process_with_events (pframes_t); void process_with_events (pframes_t);
void process_audition (pframes_t); void process_audition (pframes_t);
void process_export (pframes_t); int process_export (pframes_t);
int process_export_fw (pframes_t); int process_export_fw (pframes_t);
void block_processing() { g_atomic_int_set (&processing_prohibited, 1); } void block_processing() { g_atomic_int_set (&processing_prohibited, 1); }
@ -983,6 +983,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
int pre_export (); int pre_export ();
int stop_audio_export (); int stop_audio_export ();
void finalize_audio_export (); void finalize_audio_export ();
void finalize_export_internal (bool stop_freewheel);
bool _pre_export_mmc_enabled; bool _pre_export_mmc_enabled;
PBD::ScopedConnection export_freewheel_connection; PBD::ScopedConnection export_freewheel_connection;

View file

@ -547,16 +547,13 @@ AudioEngine::process_callback (pframes_t nframes)
} }
/* test if we are freewheeling and there are freewheel signals connected. /* test if we are freewheeling and there are freewheel signals connected.
ardour should act normally even when freewheeling unless /it/ is exporting */ ardour should act normally even when freewheeling unless /it/ is
exporting
*/
if (_freewheeling && !Freewheel.empty()) { if (_freewheeling && !Freewheel.empty()) {
/* emit the Freewheel signal and stop freewheeling in the event of trouble
*/ Freewheel (nframes);
boost::optional<int> r = Freewheel (nframes);
if (r.get_value_or (0)) {
jack_set_freewheel (_priv_jack, false);
}
} else { } else {
MIDI::Manager::instance()->cycle_start(nframes); MIDI::Manager::instance()->cycle_start(nframes);

View file

@ -214,9 +214,9 @@ RouteExportChannel::~RouteExportChannel()
} }
void void
RouteExportChannel::create_from_route(std::list<ExportChannelPtr> & result, Route & route) RouteExportChannel::create_from_route(std::list<ExportChannelPtr> & result, boost::shared_ptr<Route> route)
{ {
boost::shared_ptr<CapturingProcessor> processor = route.add_export_point(); boost::shared_ptr<CapturingProcessor> processor = route->add_export_point();
uint32_t channels = processor->input_streams().n_audio(); uint32_t channels = processor->input_streams().n_audio();
boost::shared_ptr<ProcessorRemover> remover (new ProcessorRemover (route, processor)); boost::shared_ptr<ProcessorRemover> remover (new ProcessorRemover (route, processor));
@ -271,5 +271,5 @@ RouteExportChannel::operator< (ExportChannel const & other) const
RouteExportChannel::ProcessorRemover::~ProcessorRemover() RouteExportChannel::ProcessorRemover::~ProcessorRemover()
{ {
route.remove_processor (processor); route->remove_processor (processor);
} }

View file

@ -21,6 +21,9 @@
#include <string> #include <string>
#include "ardour/export_filename.h" #include "ardour/export_filename.h"
#include <glibmm/miscutils.h>
#include <glibmm/fileutils.h>
#include "pbd/xml++.h" #include "pbd/xml++.h"
#include "pbd/convert.h" #include "pbd/convert.h"
#include "pbd/enumwriter.h" #include "pbd/enumwriter.h"
@ -101,15 +104,24 @@ ExportFilename::set_state (const XMLNode & node)
folder = ""; folder = "";
if ((prop = child->property ("relative"))) { if ((prop = child->property ("relative"))) {
if (!prop->value().compare ("true")) { if (string_is_affirmative (prop->value())) {
folder = session.session_directory().root_path(); folder = session.session_directory().root_path();
} }
} }
if ((prop = child->property ("path"))) { if ((prop = child->property ("path"))) {
folder += prop->value(); std::string tmp;
tmp = Glib::build_filename (folder, prop->value());
if (!Glib::file_test (tmp, Glib::FILE_TEST_EXISTS)) {
warning << string_compose (_("Existing export folder for this session (%1) does not exist - ignored"), tmp) << endmsg;
} else {
folder = tmp;
}
} }
if (folder.empty()) {
folder = session.session_directory().export_path();
}
pair = get_field (node, "label"); pair = get_field (node, "label");
include_label = pair.first; include_label = pair.first;
@ -140,11 +152,9 @@ ExportFilename::set_state (const XMLNode & node)
string string
ExportFilename::get_path (ExportFormatSpecPtr format) const ExportFilename::get_path (ExportFormatSpecPtr format) const
{ {
string path = folder; string path;
bool filename_empty = true; bool filename_empty = true;
path += "/";
if (include_session) { if (include_session) {
path += filename_empty ? "" : "_"; path += filename_empty ? "" : "_";
path += session.name(); path += session.name();
@ -198,7 +208,7 @@ ExportFilename::get_path (ExportFormatSpecPtr format) const
path += "."; path += ".";
path += format->extension (); path += format->extension ();
return path; return Glib::build_filename (folder, path);
} }
string string

View file

@ -18,6 +18,8 @@
*/ */
#include <pbd/stacktrace.h>
#include "ardour/export_status.h" #include "ardour/export_status.h"
namespace ARDOUR namespace ARDOUR
@ -59,7 +61,6 @@ ExportStatus::abort (bool error_occurred)
_finished = true; _finished = true;
_errors = _errors || error_occurred; _errors = _errors || error_occurred;
running = false; running = false;
Aborting ();
} }
void void
@ -67,7 +68,7 @@ ExportStatus::finish ()
{ {
_finished = true; _finished = true;
running = false; running = false;
Finished(); Finished(); /* EMIT SIGNAL */
} }
} // namespace ARDOUR } // namespace ARDOUR

View file

@ -89,7 +89,6 @@ Session::pre_export ()
_exporting = true; _exporting = true;
export_status->running = true; export_status->running = true;
export_status->Aborting.connect_same_thread (*this, boost::bind (&Session::stop_audio_export, this));
export_status->Finished.connect_same_thread (*this, boost::bind (&Session::finalize_audio_export, this)); export_status->Finished.connect_same_thread (*this, boost::bind (&Session::finalize_audio_export, this));
/* disable MMC output early */ /* disable MMC output early */
@ -157,7 +156,7 @@ Session::start_audio_export (framepos_t position)
return _engine.freewheel (true); return _engine.freewheel (true);
} }
void int
Session::process_export (pframes_t nframes) Session::process_export (pframes_t nframes)
{ {
if (_export_rolling && export_status->stop) { if (_export_rolling && export_status->stop) {
@ -183,13 +182,15 @@ Session::process_export (pframes_t nframes)
} catch (std::exception & e) { } catch (std::exception & e) {
error << string_compose (_("Export ended unexpectedly: %1"), e.what()) << endmsg; error << string_compose (_("Export ended unexpectedly: %1"), e.what()) << endmsg;
export_status->abort (true); export_status->abort (true);
return -1;
} }
return 0;
} }
int int
Session::process_export_fw (pframes_t nframes) Session::process_export_fw (pframes_t nframes)
{ {
if (!_export_started) { if (!_export_started) {
_export_started = true; _export_started = true;
set_transport_speed (1.0, false); set_transport_speed (1.0, false);
@ -202,6 +203,7 @@ Session::process_export_fw (pframes_t nframes)
_engine.main_thread()->get_buffers (); _engine.main_thread()->get_buffers ();
process_export (nframes); process_export (nframes);
_engine.main_thread()->drop_buffers (); _engine.main_thread()->drop_buffers ();
return 0; return 0;
} }
@ -217,23 +219,22 @@ Session::stop_audio_export ()
_export_rolling = false; _export_rolling = false;
_butler->schedule_transport_work (); _butler->schedule_transport_work ();
if (export_status->aborted()) {
finalize_audio_export ();
}
return 0; return 0;
} }
void void
Session::finalize_audio_export () Session::finalize_audio_export ()
{ {
_exporting = false; _exporting = false;
_export_rolling = false;
if (_export_rolling) {
stop_audio_export ();
}
/* Clean up */ /* Clean up */
_engine.freewheel (false); _engine.freewheel (false);
export_freewheel_connection.disconnect(); export_freewheel_connection.disconnect();
MIDI::Manager::instance()->mmc()->enable_send (_pre_export_mmc_enabled); MIDI::Manager::instance()->mmc()->enable_send (_pre_export_mmc_enabled);