diff options
author | Robin Gareus <robin@gareus.org> | 2015-12-16 00:25:07 +0100 |
---|---|---|
committer | Robin Gareus <robin@gareus.org> | 2015-12-16 00:25:07 +0100 |
commit | b228c1131187f3822ece3bd6ed26869a68fb0dff (patch) | |
tree | cea750878ac04fc188f68c1fb761ff9422c8dab8 /session_utils/export.cc | |
parent | f05afd973b538a2e1543423f42d6859c0254f7ca (diff) |
commandline session utilities
Diffstat (limited to 'session_utils/export.cc')
-rw-r--r-- | session_utils/export.cc | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/session_utils/export.cc b/session_utils/export.cc new file mode 100644 index 0000000000..e7d169a0d3 --- /dev/null +++ b/session_utils/export.cc @@ -0,0 +1,235 @@ +#include <iostream> +#include <cstdlib> +#include <getopt.h> +#include <glibmm.h> + +#include "common.h" + +#include "pbd/basename.h" + +#include "ardour/export_handler.h" +#include "ardour/export_status.h" +#include "ardour/export_timespan.h" +#include "ardour/export_channel_configuration.h" +#include "ardour/export_format_specification.h" +#include "ardour/export_filename.h" +#include "ardour/route.h" +#include "ardour/session_metadata.h" +#include "ardour/broadcast_info.h" + +using namespace std; +using namespace ARDOUR; +using namespace SessionUtils; + +static int export_session (Session *session, + std::string outfile, + std::string samplerate, + bool normalize) +{ + ExportTimespanPtr tsp = session->get_export_handler()->add_timespan(); + boost::shared_ptr<ExportChannelConfiguration> ccp = session->get_export_handler()->add_channel_config(); + boost::shared_ptr<ARDOUR::ExportFilename> fnp = session->get_export_handler()->add_filename(); + boost::shared_ptr<AudioGrapher::BroadcastInfo> b; + + XMLTree tree; + + tree.read_buffer(std::string( +"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +"<ExportFormatSpecification name=\"UTIL-WAV-16\" id=\"14792644-44ab-4209-a4f9-7ce6c2910cac\">" +" <Encoding id=\"F_WAV\" type=\"T_Sndfile\" extension=\"wav\" name=\"WAV\" has-sample-format=\"true\" channel-limit=\"256\"/>" +" <SampleRate rate=\""+ samplerate +"\"/>" +" <SRCQuality quality=\"SRC_SincBest\"/>" +" <EncodingOptions>" +" <Option name=\"sample-format\" value=\"SF_16\"/>" +" <Option name=\"dithering\" value=\"D_None\"/>" +" <Option name=\"tag-metadata\" value=\"true\"/>" +" <Option name=\"tag-support\" value=\"false\"/>" +" <Option name=\"broadcast-info\" value=\"false\"/>" +" </EncodingOptions>" +" <Processing>" +" <Normalize enabled=\""+ (normalize ? "true" : "false") +"\" target=\"0\"/>" +" <Silence>" +" <Start>" +" <Trim enabled=\"false\"/>" +" <Add enabled=\"false\">" +" <Duration format=\"Timecode\" hours=\"0\" minutes=\"0\" seconds=\"0\" frames=\"0\"/>" +" </Add>" +" </Start>" +" <End>" +" <Trim enabled=\"false\"/>" +" <Add enabled=\"false\">" +" <Duration format=\"Timecode\" hours=\"0\" minutes=\"0\" seconds=\"0\" frames=\"0\"/>" +" </Add>" +" </End>" +" </Silence>" +" </Processing>" +"</ExportFormatSpecification>" +)); + + boost::shared_ptr<ExportFormatSpecification> fmp = session->get_export_handler()->add_format(*tree.root()); + + /* set up range */ + framepos_t start, end; + start = session->current_start_frame(); + end = session->current_end_frame(); + tsp->set_range (start, end); + tsp->set_range_id ("session"); + + /* add master outs as default */ + IO* master_out = session->master_out()->output().get(); + if (!master_out) { + PBD::warning << _("Export Util: No Master Out Ports to Connect for Audio Export") << endmsg; + return -1; + } + + for (uint32_t n = 0; n < master_out->n_ports().n_audio(); ++n) { + PortExportChannel * channel = new PortExportChannel (); + channel->add_port (master_out->audio (n)); + ExportChannelPtr chan_ptr (channel); + ccp->register_channel (chan_ptr); + } + + /* output filename */ + if (outfile.empty ()) { + tsp->set_name ("session"); + } else { + std::string dirname = Glib::path_get_dirname (outfile); + std::string basename = Glib::path_get_basename (outfile); + + if (basename.size() > 4 && !basename.compare (basename.size() - 4, 4, ".wav")) { + basename = PBD::basename_nosuffix (basename); + } + + fnp->set_folder(dirname); + tsp->set_name (basename); + } + + cout << "* Writing " << Glib::build_filename (fnp->get_folder(), tsp->name() + ".wav") << endl; + + + /* output */ + fnp->set_timespan(tsp); + fnp->include_label = false; + + /* do audio export */ + fmp->set_soundcloud_upload(false); + session->get_export_handler()->add_export_config (tsp, ccp, fmp, fnp, b); + session->get_export_handler()->do_export(); + + boost::shared_ptr<ARDOUR::ExportStatus> status = session->get_export_status (); + + // TODO trap SIGINT -> status->abort(); + + while (status->running) { + if (status->normalizing) { + double progress = ((float) status->current_normalize_cycle) / status->total_normalize_cycles; + printf ("* Normalizing %.1f%% \r", 100. * progress); fflush (stdout); + } else { + double progress = ((float) status->processed_frames_current_timespan) / status->total_frames_current_timespan; + printf ("* Exporting Audio %.1f%% \r", 100. * progress); fflush (stdout); + } + Glib::usleep (1000000); + } + printf("\n"); + + status->finish (); + + printf ("* Done.\n"); + return 0; +} + +static void usage (int status) { + // help2man compatible format (standard GNU help-text) + printf ("export - export an ardour session from the commandline.\n\n"); + printf ("Usage: export [ OPTIONS ] <session-dir> <session-name>\n\n"); + printf ("Options:\n\ + -h, --help display this help and exit\n\ + -n, --normalize normalize signal level (to 0dBFS)\n\ + -o, --output <file> set expected [initial] framerate\n\ + -s, --samplerate <rate> samplerate to use (default: 48000)\n\ + -V, --version print version information and exit\n\ +\n"); + printf ("\n\ +The session is exported as 16bit wav.\n\ +If the no output file is given, the session's export dir is used.\n\ +\n"); + + printf ("Report bugs to <http://tracker.ardour.org/>\n" + "Website: <http://ardour.org/>\n"); + ::exit (status); +} + +int main (int argc, char* argv[]) +{ + std::string rate = "48000"; + std::string outfile; + bool normalize = false; + + const char *optstring = "hno:r:V"; + + const struct option longopts[] = { + { "help", 0, 0, 'h' }, + { "normalize", 0, 0, 'n' }, + { "output", 1, 0, 'o' }, + { "samplerate", 1, 0, 'r' }, + { "version", 0, 0, 'V' }, + }; + + int c = 0; + while (EOF != (c = getopt_long (argc, argv, + optstring, longopts, (int *) 0))) { + switch (c) { + + case 'n': + normalize = true; + break; + + case 'o': + outfile = optarg; + break; + + case 's': + { + const int sr = atoi (optarg); + if (sr >= 8000 && sr <= 192000) { + stringstream ss; + ss << sr; + rate = ss.str(); + } else { + fprintf(stderr, "Invalid Samplerate\n"); + } + } + break; + + case 'V': + printf ("ardour-utils version %s\n\n", VERSIONSTRING); + printf ("Copyright (C) GPL 2015 Robin Gareus <robin@gareus.org>\n"); + exit (0); + break; + + case 'h': + usage (0); + break; + + default: + usage (EXIT_FAILURE); + break; + } + } + + if (optind + 2 > argc) { + usage (EXIT_FAILURE); + } + + SessionUtils::init(); + Session* s = 0; + + s = SessionUtils::load_session (argv[optind], argv[optind+1]); + + export_session (s, outfile, rate, normalize); + + SessionUtils::unload_session(s); + SessionUtils::cleanup(); + + return 0; +} |