mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-06 14:54:56 +01:00
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:
parent
27bfb0f9e2
commit
9884773eea
12 changed files with 69 additions and 59 deletions
|
|
@ -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 ();
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 ()
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,6 @@ class ExportDialog : public ArdourDialog {
|
||||||
|
|
||||||
PublicEditor & editor;
|
PublicEditor & editor;
|
||||||
StatusPtr status;
|
StatusPtr status;
|
||||||
PBD::ScopedConnection abort_connection;
|
|
||||||
|
|
||||||
/*** GUI components ***/
|
/*** GUI components ***/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue