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