Normalize API rename part 2
[ardour.git] / session_utils / export.cc
1 #include <iostream>
2 #include <cstdlib>
3 #include <getopt.h>
4 #include <glibmm.h>
5
6 #include "common.h"
7
8 #include "pbd/basename.h"
9
10 #include "ardour/export_handler.h"
11 #include "ardour/export_status.h"
12 #include "ardour/export_timespan.h"
13 #include "ardour/export_channel_configuration.h"
14 #include "ardour/export_format_specification.h"
15 #include "ardour/export_filename.h"
16 #include "ardour/route.h"
17 #include "ardour/session_metadata.h"
18 #include "ardour/broadcast_info.h"
19
20 using namespace std;
21 using namespace ARDOUR;
22 using namespace SessionUtils;
23
24 static int export_session (Session *session,
25                 std::string outfile,
26                 std::string samplerate,
27                 bool normalize)
28 {
29         ExportTimespanPtr tsp = session->get_export_handler()->add_timespan();
30         boost::shared_ptr<ExportChannelConfiguration> ccp = session->get_export_handler()->add_channel_config();
31         boost::shared_ptr<ARDOUR::ExportFilename> fnp = session->get_export_handler()->add_filename();
32         boost::shared_ptr<AudioGrapher::BroadcastInfo> b;
33
34         XMLTree tree;
35
36         tree.read_buffer(std::string(
37 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
38 "<ExportFormatSpecification name=\"UTIL-WAV-16\" id=\"14792644-44ab-4209-a4f9-7ce6c2910cac\">"
39 "  <Encoding id=\"F_WAV\" type=\"T_Sndfile\" extension=\"wav\" name=\"WAV\" has-sample-format=\"true\" channel-limit=\"256\"/>"
40 "  <SampleRate rate=\""+ samplerate +"\"/>"
41 "  <SRCQuality quality=\"SRC_SincBest\"/>"
42 "  <EncodingOptions>"
43 "    <Option name=\"sample-format\" value=\"SF_16\"/>"
44 "    <Option name=\"dithering\" value=\"D_None\"/>"
45 "    <Option name=\"tag-metadata\" value=\"true\"/>"
46 "    <Option name=\"tag-support\" value=\"false\"/>"
47 "    <Option name=\"broadcast-info\" value=\"false\"/>"
48 "  </EncodingOptions>"
49 "  <Processing>"
50 "    <Normalize enabled=\""+ (normalize ? "true" : "false") +"\" target=\"0\"/>"
51 "    <Silence>"
52 "      <Start>"
53 "        <Trim enabled=\"false\"/>"
54 "        <Add enabled=\"false\">"
55 "          <Duration format=\"Timecode\" hours=\"0\" minutes=\"0\" seconds=\"0\" frames=\"0\"/>"
56 "        </Add>"
57 "      </Start>"
58 "      <End>"
59 "        <Trim enabled=\"false\"/>"
60 "        <Add enabled=\"false\">"
61 "          <Duration format=\"Timecode\" hours=\"0\" minutes=\"0\" seconds=\"0\" frames=\"0\"/>"
62 "        </Add>"
63 "      </End>"
64 "    </Silence>"
65 "  </Processing>"
66 "</ExportFormatSpecification>"
67 ));
68
69         boost::shared_ptr<ExportFormatSpecification> fmp = session->get_export_handler()->add_format(*tree.root());
70
71         /* set up range */
72         framepos_t start, end;
73         start = session->current_start_frame();
74         end   = session->current_end_frame();
75         tsp->set_range (start, end);
76         tsp->set_range_id ("session");
77
78         /* add master outs as default */
79         IO* master_out = session->master_out()->output().get();
80         if (!master_out) {
81                 PBD::warning << _("Export Util: No Master Out Ports to Connect for Audio Export") << endmsg;
82                 return -1;
83         }
84
85         for (uint32_t n = 0; n < master_out->n_ports().n_audio(); ++n) {
86                 PortExportChannel * channel = new PortExportChannel ();
87                 channel->add_port (master_out->audio (n));
88                 ExportChannelPtr chan_ptr (channel);
89                 ccp->register_channel (chan_ptr);
90         }
91
92         /* output filename */
93         if (outfile.empty ()) {
94                 tsp->set_name ("session");
95         } else {
96                 std::string dirname = Glib::path_get_dirname (outfile);
97                 std::string basename = Glib::path_get_basename (outfile);
98
99                 if (basename.size() > 4 && !basename.compare (basename.size() - 4, 4, ".wav")) {
100                         basename = PBD::basename_nosuffix (basename);
101                 }
102
103                 fnp->set_folder(dirname);
104                 tsp->set_name (basename);
105         }
106
107         cout << "* Writing " << Glib::build_filename (fnp->get_folder(), tsp->name() + ".wav") << endl;
108
109
110         /* output */
111         fnp->set_timespan(tsp);
112         fnp->include_label = false;
113
114         /* do audio export */
115         fmp->set_soundcloud_upload(false);
116         session->get_export_handler()->add_export_config (tsp, ccp, fmp, fnp, b);
117         session->get_export_handler()->do_export();
118
119         boost::shared_ptr<ARDOUR::ExportStatus> status = session->get_export_status ();
120
121         // TODO trap SIGINT -> status->abort();
122
123         while (status->running ()) {
124                 double progress = 0.0;
125                 switch (status->active_job) {
126                 case ExportStatus::Normalizing:
127                         progress = ((float) status->current_postprocessing_cycle) / status->total_postprocessing_cycles;
128                         printf ("* Normalizing %.1f%%      \r", 100. * progress); fflush (stdout);
129                         break;
130                 case ExportStatus::Exporting:
131                         progress = ((float) status->processed_frames_current_timespan) / status->total_frames_current_timespan;
132                         printf ("* Exporting Audio %.1f%%  \r", 100. * progress); fflush (stdout);
133                         break;
134                 default:
135                         printf ("* Exporting...            \r");
136                         break;
137                 }
138                 Glib::usleep (1000000);
139         }
140         printf("\n");
141
142         status->finish ();
143
144         printf ("* Done.\n");
145         return 0;
146 }
147
148 static void usage (int status) {
149         // help2man compatible format (standard GNU help-text)
150         printf (UTILNAME " - export an ardour session from the commandline.\n\n");
151         printf ("Usage: " UTILNAME " [ OPTIONS ] <session-dir> <session/snapshot-name>\n\n");
152         printf ("Options:\n\
153   -h, --help                 display this help and exit\n\
154   -n, --normalize            normalize signal level (to 0dBFS)\n\
155   -o, --output  <file>       export output file name\n\
156   -s, --samplerate <rate>    samplerate to use (default: 48000)\n\
157   -V, --version              print version information and exit\n\
158 \n");
159         printf ("\n\
160 The session is exported as 16bit wav.\n\
161 If the no output file is given, the session's export dir is used.\n\
162 \n");
163
164         printf ("Report bugs to <http://tracker.ardour.org/>\n"
165                 "Website: <http://ardour.org/>\n");
166         ::exit (status);
167 }
168
169 int main (int argc, char* argv[])
170 {
171         std::string rate = "48000";
172         std::string outfile;
173         bool normalize = false;
174
175         const char *optstring = "hno:r:V";
176
177         const struct option longopts[] = {
178                 { "help",       0, 0, 'h' },
179                 { "normalize",  0, 0, 'n' },
180                 { "output",     1, 0, 'o' },
181                 { "samplerate", 1, 0, 'r' },
182                 { "version",    0, 0, 'V' },
183         };
184
185         int c = 0;
186         while (EOF != (c = getopt_long (argc, argv,
187                                         optstring, longopts, (int *) 0))) {
188                 switch (c) {
189
190                         case 'n':
191                                 normalize = true;
192                                 break;
193
194                         case 'o':
195                                 outfile = optarg;
196                                 break;
197
198                         case 's':
199                                 {
200                                         const int sr = atoi (optarg);
201                                         if (sr >= 8000 && sr <= 192000) {
202                                                 stringstream ss;
203                                                 ss << sr;
204                                                 rate = ss.str();
205                                         } else {
206                                                 fprintf(stderr, "Invalid Samplerate\n");
207                                         }
208                                 }
209                                 break;
210
211                         case 'V':
212                                 printf ("ardour-utils version %s\n\n", VERSIONSTRING);
213                                 printf ("Copyright (C) GPL 2015 Robin Gareus <robin@gareus.org>\n");
214                                 exit (0);
215                                 break;
216
217                         case 'h':
218                                 usage (0);
219                                 break;
220
221                         default:
222                                         usage (EXIT_FAILURE);
223                                         break;
224                 }
225         }
226
227         if (optind + 2 > argc) {
228                 usage (EXIT_FAILURE);
229         }
230
231         SessionUtils::init();
232         Session* s = 0;
233
234         s = SessionUtils::load_session (argv[optind], argv[optind+1]);
235
236         export_session (s, outfile, rate, normalize);
237
238         SessionUtils::unload_session(s);
239         SessionUtils::cleanup();
240
241         return 0;
242 }