13
0
livetrax/gtk2_ardour/simple_export_dialog.cc
Robin Gareus f807ea6ea2
Check if format is valid before starting export
This can happen if e.g. mp3 export is n/a, but a mp3
preset is present.
2022-11-04 21:57:53 +01:00

307 lines
8.8 KiB
C++

/*
* Copyright (C) 2022 Robin Gareus <robin@gareus.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <gtkmm/messagedialog.h>
#include <gtkmm/stock.h>
#include <glib.h>
#include "pbd/openuri.h"
#include "ardour/export_channel_configuration.h"
#include "ardour/export_filename.h"
#include "ardour/export_preset.h"
#include "ardour/export_profile_manager.h"
#include "ardour/export_status.h"
#include "ardour/export_timespan.h"
#include "ardour/profile.h"
#include "ardour/session_directory.h"
#include "nag.h"
#include "simple_export_dialog.h"
#include "pbd/i18n.h"
using namespace std;
using namespace ARDOUR;
using namespace PBD;
using namespace Gtk;
SimpleExportDialog::SimpleExportDialog (PublicEditor& editor)
: ARDOUR::SimpleExport ()
, ArdourDialog (_("Quick Audio Export"), true, false)
, _editor (editor)
, _eps (true)
{
if (_eps.the_combo ().get_parent ()) {
_eps.the_combo ().get_parent ()->remove (_eps.the_combo ());
}
Table* t = manage (new Table);
int r = 0;
t->set_spacings (4);
#define LBL(TXT) *manage (new Label (_(TXT), ALIGN_END))
/* clang-format off */
t->attach (LBL ("Format preset:"), 0, 1, r, r + 1, FILL, SHRINK, 0, 0);
t->attach (_eps.the_combo (), 1, 2, r, r + 1, EXPAND, SHRINK, 0, 0);
++r;
t->attach (LBL ("Export range:"), 0, 1, r, r + 1, FILL, SHRINK, 0, 0);
t->attach (_range_combo, 1, 2, r, r + 1, EXPAND | FILL, SHRINK, 0, 0);
++r;
t->attach (LBL ("After export:"), 0, 1, r, r + 1, FILL, SHRINK, 0, 0);
t->attach (_post_export_combo, 1, 2, r, r + 1, EXPAND | FILL, SHRINK, 0, 0);
++r;
t->attach (_error_label, 0, 2, r, r + 1, EXPAND | FILL, SHRINK, 0, 0);
++r;
t->attach (_progress_bar, 0, 2, r, r + 1, EXPAND | FILL, SHRINK, 0, 0);
/* clang-format on */
#undef LBL
_post_export_combo.append (_("Open the folder where files are exported"));
_post_export_combo.append (_("Do nothing"));
_post_export_combo.set_active (0);
get_vbox ()->pack_start (*t, false, false);
_cancel_button = add_button (Gtk::Stock::CANCEL, RESPONSE_CANCEL);
_export_button = add_button (_("_Export"), RESPONSE_OK);
_cancel_button->signal_clicked ().connect (sigc::mem_fun (*this, &SimpleExportDialog::close_dialog));
_export_button->signal_clicked ().connect (sigc::mem_fun (*this, &SimpleExportDialog::start_export));
_progress_bar.set_no_show_all (true);
_error_label.set_no_show_all (true);
_export_button->set_sensitive (false);
_range_combo.set_sensitive (false);
t->show_all ();
}
XMLNode&
SimpleExportDialog::get_state () const
{
XMLNode* node = new XMLNode (X_("QuickExport"));
node->set_property (X_("PresetUUID"), preset_uuid ());
node->set_property (X_("PostExport"), _post_export_combo.get_active_row_number ());
return *node;
}
void
SimpleExportDialog::set_state (XMLNode const& node)
{
int post_export;
std::string pset_uuid;
if (node.get_property (X_("PresetUUID"), pset_uuid)) {
set_preset (pset_uuid);
}
if (node.get_property (X_("PostExport"), post_export)) {
_post_export_combo.set_active (post_export);
}
}
void
SimpleExportDialog::set_session (ARDOUR::Session* s)
{
SimpleExport::set_session (s);
ArdourDialog::set_session (s);
_range_combo.remove_all ();
_preset_cfg_connection.disconnect ();
if (!s) {
_export_button->set_sensitive (false);
_range_combo.set_sensitive (false);
return;
}
XMLNode* node = s->extra_xml (X_("QuickExport"));
if (node) {
set_state (*node);
}
_eps.set_manager (_manager);
if (!check_outputs ()) {
set_error ("Error: Session has no master bus");
return;
}
/* check range */
Location* srl (s->locations ()->session_range_location ());
TimeSelection const& tsel (_editor.get_selection ().time);
bool ok = false;
if (!tsel.empty ()) {
ok = true;
_range_combo.append (_("Using time selection"));
}
if (srl) {
ok = true;
_range_combo.append (_("Session start to session end")); // same text as ExportVideoDialog::apply_state
}
if (!ok) {
set_error ("Error: No valid range to export. Select a range or create session start/end markers");
return;
}
_range_combo.set_active (0);
_range_combo.set_sensitive (true);
_export_button->set_sensitive (true);
_preset_cfg_connection = _eps.CriticalSelectionChanged.connect (sigc::mem_fun (*this, &SimpleExportDialog::check_manager));
}
void
SimpleExportDialog::check_manager ()
{
bool ok = _manager && _manager->preset ();
if (ok && _manager->get_formats ().empty ()) {
ok = false;
}
if (ok) {
/* check for NULL ExportFormatSpecPtr */
auto fms = _manager->get_formats ();
for (auto const& fm : fms) {
if (!fm->format) {
ok = false;
break;
}
}
}
_export_button->set_sensitive (ok);
}
void
SimpleExportDialog::set_error (std::string const& err)
{
_export_button->set_sensitive (false);
_range_combo.set_sensitive (false);
_error_label.set_text (err);
_error_label.show ();
}
void
SimpleExportDialog::close_dialog ()
{
if (_status->running ()) {
_status->abort ();
}
}
void
SimpleExportDialog::start_export ()
{
Location* srl = SimpleExport::_session->locations ()->session_range_location ();
TimeSelection const& tsel (_editor.get_selection ().time);
std::string range = _range_combo.get_active_text ();
if (!tsel.empty () && range == _("Using time selection")) {
set_range (tsel.start_sample (), tsel.end_sample ());
SimpleExport::set_name (string_compose (_("%1 (selection)"), SimpleExport::_session->snap_name ()));
} else {
set_range (srl->start_sample (), srl->end_sample ());
SimpleExport::set_name (SimpleExport::_session->snap_name ());
}
SimpleExport::_session->add_extra_xml (get_state ());
_cancel_button->set_label (_("_Abort"));
_export_button->set_sensitive (false);
_progress_bar.set_fraction (0.0);
_progress_bar.show ();
#if 0
_eps.hide ();
_range_combo.hide ();
_post_export_combo,.hide ();
#endif
_progress_connection = Glib::signal_timeout ().connect (sigc::mem_fun (*this, &SimpleExportDialog::progress_timeout), 100);
if (run_export ()) {
hide ();
if (_post_export_combo.get_active_row_number () == 0) {
PBD::open_folder (folder ());
}
if (!ARDOUR::Profile->get_mixbus ()) {
NagScreen* ns = NagScreen::maybe_nag (_("Export"));
if (ns) {
ns->nag ();
delete ns;
}
}
} else if (!_status->aborted ()) {
hide ();
std::string txt = _("Export has been aborted due to an error!\nSee the Log window for details.");
Gtk::MessageDialog msg (txt, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
msg.run ();
}
}
bool
SimpleExportDialog::progress_timeout ()
{
std::string status_text;
float progress = -1;
switch (_status->active_job) {
case ExportStatus::Exporting:
status_text = string_compose (_("Exporting '%3' (timespan %1 of %2)"),
_status->timespan, _status->total_timespans, _status->timespan_name);
progress = ((float)_status->processed_samples_current_timespan) / _status->total_samples_current_timespan;
break;
case ExportStatus::Normalizing:
status_text = string_compose (_("Normalizing '%3' (timespan %1 of %2)"),
_status->timespan, _status->total_timespans, _status->timespan_name);
progress = ((float)_status->current_postprocessing_cycle) / _status->total_postprocessing_cycles;
break;
case ExportStatus::Encoding:
status_text = string_compose (_("Encoding '%3' (timespan %1 of %2)"),
_status->timespan, _status->total_timespans, _status->timespan_name);
progress = ((float)_status->current_postprocessing_cycle) / _status->total_postprocessing_cycles;
break;
case ExportStatus::Tagging:
status_text = string_compose (_("Tagging '%3' (timespan %1 of %2)"),
_status->timespan, _status->total_timespans, _status->timespan_name);
case ExportStatus::Uploading:
break;
case ExportStatus::Command:
status_text = string_compose (_("Running Post-Export Command for '%1'"), _status->timespan_name);
break;
}
_progress_bar.set_text (status_text);
if (progress >= 0) {
_progress_bar.set_fraction (progress);
} else {
_progress_bar.set_pulse_step (.1);
_progress_bar.pulse ();
}
return true;
}