Fix relative grouped + VCA slaved gain
[ardour.git] / libs / ardour / export_format_specification.cc
1 /*
2     Copyright (C) 2008 Paul Davis
3     Author: Sakari Bergen
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19 */
20
21 #include "ardour/export_format_specification.h"
22
23 #include "ardour/export_format_compatibility.h"
24 #include "ardour/export_formats.h"
25 #include "ardour/session.h"
26 #include "ardour/types_convert.h"
27
28 #include "pbd/error.h"
29 #include "pbd/xml++.h"
30 #include "pbd/enumwriter.h"
31 #include "pbd/enum_convert.h"
32 #include "pbd/string_convert.h"
33 #include "pbd/types_convert.h"
34
35 #include "pbd/i18n.h"
36
37 namespace PBD {
38         DEFINE_ENUM_CONVERT (ARDOUR::ExportFormatBase::FormatId)
39         DEFINE_ENUM_CONVERT (ARDOUR::ExportFormatBase::SampleRate)
40         DEFINE_ENUM_CONVERT (ARDOUR::ExportFormatBase::SampleFormat)
41         DEFINE_ENUM_CONVERT (ARDOUR::ExportFormatBase::DitherType)
42         DEFINE_ENUM_CONVERT (ARDOUR::ExportFormatBase::SRCQuality)
43         DEFINE_ENUM_CONVERT (ARDOUR::ExportFormatBase::Type)
44 }
45
46 namespace ARDOUR
47 {
48
49 using namespace PBD;
50 using std::string;
51 using std::list;
52
53 ExportFormatSpecification::Time &
54 ExportFormatSpecification::Time::operator= (AnyTime const & other)
55 {
56         static_cast<AnyTime &>(*this) = other;
57         return *this;
58 }
59
60 framecnt_t
61 ExportFormatSpecification::Time::get_frames_at (framepos_t position, framecnt_t target_rate) const
62 {
63         framecnt_t duration = session.any_duration_to_frames (position, *this);
64         return ((double) target_rate / session.frame_rate()) * duration + 0.5;
65 }
66
67 XMLNode &
68 ExportFormatSpecification::Time::get_state ()
69 {
70
71         XMLNode * node = new XMLNode ("Duration");
72
73         node->set_property ("format", type);
74
75         switch (type) {
76           case Timecode:
77                 node->set_property ("hours", timecode.hours);
78                 node->set_property ("minutes", timecode.minutes);
79                 node->set_property ("seconds", timecode.seconds);
80                 node->set_property ("frames", timecode.frames);
81                 break;
82           case BBT:
83                 node->set_property ("bars", bbt.bars);
84                 node->set_property ("beats", bbt.beats);
85                 node->set_property ("ticks", bbt.ticks);
86                 break;
87           case Frames:
88                 node->set_property ("frames", frames);
89                 break;
90           case Seconds:
91                 node->set_property ("seconds", seconds);
92                 break;
93         }
94
95         return *node;
96 }
97
98 int
99 ExportFormatSpecification::Time::set_state (const XMLNode & node)
100 {
101         if (!node.get_property ("format", type)) {
102                 return -1;
103         }
104
105         switch (type) {
106         case Timecode:
107                 node.get_property ("hours", timecode.hours);
108                 node.get_property ("minutes", timecode.minutes);
109                 node.get_property ("seconds", timecode.seconds);
110                 node.get_property ("frames", timecode.frames);
111                 break;
112
113         case BBT:
114                 node.get_property ("bars", bbt.bars);
115                 node.get_property ("beats", bbt.beats);
116                 node.get_property ("ticks", bbt.ticks);
117                 break;
118
119         case Frames:
120                 node.get_property ("frames", frames);
121                 break;
122
123         case Seconds:
124                 node.get_property ("seconds", seconds);
125                 break;
126
127         }
128
129         return 0;
130 }
131
132 ExportFormatSpecification::ExportFormatSpecification (Session & s)
133         : session (s)
134
135         , has_sample_format (false)
136         , supports_tagging (false)
137         , _has_broadcast_info (false)
138         , _channel_limit (0)
139         , _dither_type (D_None)
140         , _src_quality (SRC_SincBest)
141         , _tag (true)
142
143         , _trim_beginning (false)
144         , _silence_beginning (s)
145         , _trim_end (false)
146         , _silence_end (s)
147
148         , _normalize (false)
149         , _normalize_loudness (false)
150         , _normalize_dbfs (GAIN_COEFF_UNITY)
151         , _normalize_lufs (-23)
152         , _normalize_dbtp (-1)
153         , _with_toc (false)
154         , _with_cue (false)
155         , _with_mp4chaps (false)
156         , _soundcloud_upload (false)
157         , _command ("")
158         , _analyse (true)
159 {
160         format_ids.insert (F_None);
161         endiannesses.insert (E_FileDefault);
162         sample_formats.insert (SF_None);
163         sample_rates.insert (SR_None);
164         qualities.insert (Q_None);
165 }
166
167 ExportFormatSpecification::ExportFormatSpecification (Session & s, XMLNode const & state)
168         : session (s)
169
170         , has_sample_format (false)
171         , supports_tagging (false)
172         , _has_broadcast_info (false)
173         , _channel_limit (0)
174         , _dither_type (D_None)
175         , _src_quality (SRC_SincBest)
176         , _tag (true)
177
178         , _trim_beginning (false)
179         , _silence_beginning (s)
180         , _trim_end (false)
181         , _silence_end (s)
182
183         , _normalize (false)
184         , _normalize_loudness (false)
185         , _normalize_dbfs (GAIN_COEFF_UNITY)
186         , _normalize_lufs (-23)
187         , _normalize_dbtp (-1)
188         , _with_toc (false)
189         , _with_cue (false)
190         , _with_mp4chaps (false)
191         , _soundcloud_upload (false)
192         , _command ("")
193         , _analyse (true)
194 {
195         _silence_beginning.type = Time::Timecode;
196         _silence_end.type = Time::Timecode;
197
198         set_state (state);
199 }
200
201 ExportFormatSpecification::ExportFormatSpecification (ExportFormatSpecification const & other, bool modify_name)
202         : ExportFormatBase(other)
203         , session (other.session)
204         , _silence_beginning (other.session)
205         , _silence_end (other.session)
206         , _soundcloud_upload (false)
207         , _analyse (other._analyse)
208 {
209         if (modify_name) {
210                 set_name (other.name() + " (copy)");
211         } else {
212                 set_name (other.name());
213         }
214
215         _format_name = other._format_name;
216         has_sample_format = other.has_sample_format;
217
218         supports_tagging = other.supports_tagging;
219         _has_broadcast_info = other._has_broadcast_info;
220         _channel_limit = other._channel_limit;
221
222         set_type (other.type());
223         set_format_id (other.format_id());
224         set_endianness (other.endianness());
225         set_sample_format (other.sample_format());
226         set_sample_rate (other.sample_rate());
227         set_quality (other.quality());
228
229         set_dither_type (other.dither_type());
230         set_src_quality (other.src_quality());
231         set_trim_beginning (other.trim_beginning());
232         set_trim_end (other.trim_end());
233         set_normalize (other.normalize());
234         set_normalize_loudness (other.normalize_loudness());
235         set_normalize_dbfs (other.normalize_dbfs());
236         set_normalize_lufs (other.normalize_lufs());
237         set_normalize_dbtp (other.normalize_dbtp());
238
239         set_tag (other.tag());
240
241         set_silence_beginning (other.silence_beginning_time());
242         set_silence_end (other.silence_end_time());
243
244         set_extension(other.extension());
245 }
246
247 ExportFormatSpecification::~ExportFormatSpecification ()
248 {
249 }
250
251 XMLNode &
252 ExportFormatSpecification::get_state ()
253 {
254         LocaleGuard lg;
255         XMLNode * node;
256         XMLNode * root = new XMLNode ("ExportFormatSpecification");
257
258         root->set_property ("name", _name);
259         root->set_property ("id", _id.to_s());
260         root->set_property ("with-cue", _with_cue);
261         root->set_property ("with-toc", _with_toc);
262         root->set_property ("with-mp4chaps", _with_mp4chaps);
263         root->set_property ("command", _command);
264         root->set_property ("analyse", _analyse);
265         root->set_property ("soundcloud-upload", _soundcloud_upload);
266
267         node = root->add_child ("Encoding");
268         node->set_property ("id", format_id());
269         node->set_property ("type", type());
270         node->set_property ("extension", extension());
271         node->set_property ("name", _format_name);
272         node->set_property ("has-sample-format", has_sample_format);
273         node->set_property ("channel-limit", _channel_limit);
274
275         node = root->add_child ("SampleRate");
276         node->set_property ("rate", sample_rate());
277
278         node = root->add_child ("SRCQuality");
279         node->set_property ("quality", src_quality());
280
281         XMLNode * enc_opts = root->add_child ("EncodingOptions");
282
283         add_option (enc_opts, "sample-format", to_string(sample_format()));
284         add_option (enc_opts, "dithering", to_string (dither_type()));
285         add_option (enc_opts, "tag-metadata", to_string (_tag));
286         add_option (enc_opts, "tag-support", to_string (supports_tagging));
287         add_option (enc_opts, "broadcast-info", to_string (_has_broadcast_info));
288
289         XMLNode * processing = root->add_child ("Processing");
290
291         node = processing->add_child ("Normalize");
292         node->set_property ("enabled", normalize());
293         node->set_property ("loudness", normalize_loudness());
294         node->set_property ("dbfs", normalize_dbfs());
295         node->set_property ("lufs", normalize_lufs());
296         node->set_property ("dbtp", normalize_dbtp());
297
298         XMLNode * silence = processing->add_child ("Silence");
299         XMLNode * start = silence->add_child ("Start");
300         XMLNode * end = silence->add_child ("End");
301
302         node = start->add_child ("Trim");
303         node->set_property ("enabled", trim_beginning());
304
305         node = start->add_child ("Add");
306         node->set_property ("enabled", _silence_beginning.not_zero());
307         node->add_child_nocopy (_silence_beginning.get_state());
308
309         node = end->add_child ("Trim");
310         node->set_property ("enabled", trim_end());
311
312         node = end->add_child ("Add");
313         node->set_property ("enabled", _silence_end.not_zero());
314         node->add_child_nocopy (_silence_end.get_state());
315
316         return *root;
317 }
318
319 int
320 ExportFormatSpecification::set_state (const XMLNode & root)
321 {
322         XMLNode const * child;
323         string str;
324         LocaleGuard lg;
325
326         root.get_property ("name", _name);
327
328         if (root.get_property ("id", str)) {
329                 _id = str;
330         }
331
332         if (!root.get_property ("with-cue", _with_cue)) {
333                 _with_cue = false;
334         }
335
336         if (!root.get_property ("with-toc", _with_toc)) {
337                 _with_toc = false;
338         }
339
340         if (!root.get_property ("with-mp4chaps", _with_mp4chaps)) {
341                 _with_mp4chaps = false;
342         }
343
344         if (!root.get_property ("command", _command)) {
345                 _command = "";
346         }
347
348         if (!root.get_property ("analyse", _analyse)) {
349                 _analyse = false;
350         }
351
352         if (!root.get_property ("soundcloud-upload", _soundcloud_upload)) {
353                 _soundcloud_upload = false;
354         }
355
356         /* Encoding and SRC */
357
358         if ((child = root.child ("Encoding"))) {
359                 FormatId fid;
360                 if (child->get_property ("id", fid)) {
361                         set_format_id (fid);
362                 }
363
364                 ExportFormatBase::Type type;
365                 if (child->get_property ("type", type)) {
366                         set_type (type);
367                 }
368
369                 if (child->get_property ("extension", str)) {
370                         set_extension (str);
371                 }
372
373                 child->get_property ("name", _format_name);
374                 child->get_property ("has-sample-format", has_sample_format);
375                 child->get_property ("channel-limit", _channel_limit);
376         }
377
378         if ((child = root.child ("SampleRate"))) {
379                 SampleRate rate;
380                 if (child->get_property ("rate", rate)) {
381                         set_sample_rate (rate);
382                 }
383         }
384
385         if ((child = root.child ("SRCQuality"))) {
386                 child->get_property ("quality", _src_quality);
387         }
388
389         /* Encoding options */
390
391         if ((child = root.child ("EncodingOptions"))) {
392                 set_sample_format ((SampleFormat) string_2_enum (get_option (child, "sample-format"), SampleFormat));
393                 set_dither_type ((DitherType) string_2_enum (get_option (child, "dithering"), DitherType));
394                 set_tag (string_to<bool>(get_option (child, "tag-metadata")));
395                 supports_tagging = string_to<bool>(get_option (child, "tag-support"));
396                 _has_broadcast_info = string_to<bool>(get_option (child, "broadcast-info"));
397         }
398
399         /* Processing */
400
401         XMLNode const * proc = root.child ("Processing");
402         if (!proc) { std::cerr << X_("Could not load processing for export format") << std::endl; return -1; }
403
404         if ((child = proc->child ("Normalize"))) {
405                 child->get_property ("enabled", _normalize);
406                 // old formats before ~ 4.7-930ish
407                 child->get_property ("target", _normalize_dbfs);
408                 child->get_property ("loudness", _normalize_loudness);
409                 child->get_property ("dbfs", _normalize_dbfs);
410                 child->get_property ("lufs", _normalize_lufs);
411                 child->get_property ("dbtp", _normalize_dbtp);
412         }
413
414         XMLNode const * silence = proc->child ("Silence");
415         if (!silence) { std::cerr << X_("Could not load silence for export format") << std::endl; return -1; }
416
417         XMLNode const * start = silence->child ("Start");
418         XMLNode const * end = silence->child ("End");
419         if (!start || !end) { std::cerr << X_("Could not load end or start silence for export format") << std::endl; return -1; }
420
421         /* Silence start */
422
423         if ((child = start->child ("Trim"))) {
424                 child->get_property ("enabled", _trim_beginning);
425         }
426
427         bool enabled;
428         if ((child = start->child ("Add"))) {
429                 if (child->get_property ("enabled", enabled) && enabled) {
430                         if ((child = child->child ("Duration"))) {
431                                 _silence_beginning.set_state (*child);
432                         }
433                 } else {
434                         _silence_beginning.type = Time::Timecode;
435                 }
436         }
437
438         /* Silence end */
439
440         if ((child = end->child ("Trim"))) {
441                 child->get_property ("enabled", _trim_end);
442         }
443
444         if ((child = end->child ("Add"))) {
445                 if (child->get_property ("enabled", enabled) && enabled) {
446                         if ((child = child->child ("Duration"))) {
447                                 _silence_end.set_state (*child);
448                         }
449                 } else {
450                                 _silence_end.type = Time::Timecode;
451                 }
452         }
453
454         return 0;
455 }
456
457 bool
458 ExportFormatSpecification::is_compatible_with (ExportFormatCompatibility const & compatibility) const
459 {
460         boost::shared_ptr<ExportFormatBase> intersection = get_intersection (compatibility);
461
462         if (intersection->formats_empty() && format_id() != 0) {
463                 return false;
464         }
465
466         if (intersection->endiannesses_empty() && endianness() != E_FileDefault) {
467                 return false;
468         }
469
470         if (intersection->sample_rates_empty() && sample_rate() != SR_None) {
471                 return false;
472         }
473
474         if (intersection->sample_formats_empty() && sample_format() != SF_None) {
475                 return false;
476         }
477
478         if (intersection->qualities_empty() && quality() != Q_None) {
479                 return false;
480         }
481
482         return true;
483 }
484
485 bool
486 ExportFormatSpecification::is_complete () const
487 {
488         if (type() == T_None) {
489                 return false;
490         }
491
492         if (!format_id()) {
493                 return false;
494         }
495
496         if (!sample_rate()) {
497                 return false;
498         }
499
500         if (has_sample_format) {
501                 if (sample_format() == SF_None) {
502                         return false;
503                 }
504         }
505
506         return true;
507 }
508
509 void
510 ExportFormatSpecification::set_format (boost::shared_ptr<ExportFormat> format)
511 {
512         if (format) {
513                 set_format_id (format->get_format_id ());
514                 set_type (format->get_type());
515                 set_extension (format->extension());
516
517                 if (format->get_explicit_sample_format()) {
518                         set_sample_format (format->get_explicit_sample_format());
519                 }
520
521                 if (format->has_sample_format()) {
522                         has_sample_format = true;
523                 }
524
525                 if (format->has_broadcast_info()) {
526                         _has_broadcast_info = true;
527                 }
528
529                 supports_tagging = format->supports_tagging ();
530                 _channel_limit = format->get_channel_limit();
531
532                 _format_name = format->name();
533         } else {
534                 set_format_id (F_None);
535                 set_type (T_None);
536                 set_extension ("");
537                 _has_broadcast_info = false;
538                 has_sample_format = false;
539                 supports_tagging = false;
540                 _channel_limit = 0;
541                 _format_name = "";
542         }
543 }
544
545 string
546 ExportFormatSpecification::description (bool include_name)
547 {
548         list<string> components;
549
550         if (_normalize) {
551                 if (_normalize_loudness) {
552                         components.push_back (_("normalize loudness"));
553                 } else {
554                         components.push_back (_("normalize peak"));
555                 }
556         }
557
558         if (_trim_beginning && _trim_end) {
559                 components.push_back ( _("trim"));
560         } else if (_trim_beginning) {
561                 components.push_back (_("trim start"));
562         } else if (_trim_end) {
563                 components.push_back (_("trim end"));
564         }
565
566         if (_format_name != "") {
567                 components.push_back (_format_name);
568         }
569
570         if (has_sample_format) {
571                 components.push_back (HasSampleFormat::get_sample_format_name (sample_format()));
572         }
573
574         switch (sample_rate()) {
575         case SR_8:
576                 components.push_back ("8 kHz");
577                 break;
578         case SR_22_05:
579                 components.push_back ("22,5 kHz");
580                 break;
581         case SR_44_1:
582                 components.push_back ("44,1 kHz");
583                 break;
584         case SR_48:
585                 components.push_back ("48 kHz");
586                 break;
587         case SR_88_2:
588                 components.push_back ("88,2 kHz");
589                 break;
590         case SR_96:
591                 components.push_back ("96 kHz");
592                 break;
593         case SR_176_4:
594                 components.push_back ("176.4 kHz");
595                 break;
596         case SR_192:
597                 components.push_back ("192 kHz");
598                 break;
599         case SR_Session:
600                 components.push_back (_("Session rate"));
601                 break;
602         case SR_None:
603                 break;
604         }
605
606         if (_with_toc) {
607                 components.push_back ("TOC");
608         }
609
610         if (_with_cue) {
611                 components.push_back ("CUE");
612         }
613
614         if (_with_mp4chaps) {
615                 components.push_back ("MP4ch");
616         }
617
618         if (!_command.empty()) {
619                 components.push_back ("+");
620         }
621
622         string desc;
623         if (include_name) {
624                 desc = _name + ": ";
625         }
626
627         for (list<string>::const_iterator it = components.begin(); it != components.end(); ++it) {
628                 if (it != components.begin()) { desc += ", "; }
629                 desc += *it;
630         }
631         return desc;
632 }
633
634 void
635 ExportFormatSpecification::add_option (XMLNode * node, std::string const & name, std::string const & value)
636 {
637         node = node->add_child ("Option");
638         node->set_property ("name", name);
639         node->set_property ("value", value);
640 }
641
642 std::string
643 ExportFormatSpecification::get_option (XMLNode const * node, std::string const & name)
644 {
645         XMLNodeList list (node->children ("Option"));
646
647         for (XMLNodeList::iterator it = list.begin(); it != list.end(); ++it) {
648                 std::string str;
649                 if ((*it)->get_property ("name", str) && name == str) {
650                         if ((*it)->get_property ("value", str)) {
651                                 return str;
652                         }
653                 }
654         }
655
656         std::cerr << "Could not load encoding option \"" << name << "\" for export format" << std::endl;
657
658         return "";
659 }
660
661 }; // namespace ARDOUR