2 Copyright (C) 2008 Paul Davis
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.
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.
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.
21 #include "ardour/export_format_specification.h"
25 #include "ardour/export_format_compatibility.h"
26 #include "ardour/export_formats.h"
27 #include "ardour/session.h"
29 #include "pbd/error.h"
30 #include "pbd/xml++.h"
31 #include "pbd/enumwriter.h"
32 #include "pbd/convert.h"
42 ExportFormatSpecification::Time
&
43 ExportFormatSpecification::Time::operator= (AnyTime
const & other
)
46 timecode
= other
.timecode
;
50 frames
= other
.frames
;
52 seconds
= other
.seconds
;
59 ExportFormatSpecification::Time::get_frames (nframes_t target_rate
) const
62 nframes_t duration
= session
.convert_to_frames_at (0, *this);
64 return ((double) target_rate
/ session
.frame_rate()) * duration
+ 0.5;
68 ExportFormatSpecification::Time::get_state ()
71 XMLNode
* node
= new XMLNode ("Duration");
73 node
->add_property ("format", enum_2_string (type
));
77 node
->add_property ("hours", to_string (timecode
.hours
, std::dec
));
78 node
->add_property ("minutes", to_string (timecode
.minutes
, std::dec
));
79 node
->add_property ("seconds", to_string (timecode
.seconds
, std::dec
));
80 node
->add_property ("frames", to_string (timecode
.frames
, std::dec
));
83 node
->add_property ("bars", to_string (bbt
.bars
, std::dec
));
84 node
->add_property ("beats", to_string (bbt
.beats
, std::dec
));
85 node
->add_property ("ticks", to_string (bbt
.ticks
, std::dec
));
88 node
->add_property ("frames", to_string (frames
, std::dec
));
91 node
->add_property ("seconds", to_string (seconds
, std::dec
));
99 ExportFormatSpecification::Time::set_state (const XMLNode
& node
)
101 XMLProperty
const * prop
;
103 prop
= node
.property ("format");
105 if (!prop
) { return -1; }
107 type
= (Type
) string_2_enum (prop
->value(), Type
);
111 if ((prop
= node
.property ("hours"))) {
112 timecode
.hours
= atoi (prop
->value());
115 if ((prop
= node
.property ("minutes"))) {
116 timecode
.minutes
= atoi (prop
->value());
119 if ((prop
= node
.property ("seconds"))) {
120 timecode
.seconds
= atoi (prop
->value());
123 if ((prop
= node
.property ("frames"))) {
124 timecode
.frames
= atoi (prop
->value());
130 if ((prop
= node
.property ("bars"))) {
131 bbt
.bars
= atoi (prop
->value());
134 if ((prop
= node
.property ("beats"))) {
135 bbt
.beats
= atoi (prop
->value());
138 if ((prop
= node
.property ("ticks"))) {
139 bbt
.ticks
= atoi (prop
->value());
145 if ((prop
= node
.property ("frames"))) {
146 std::istringstream
iss (prop
->value());
153 if ((prop
= node
.property ("seconds"))) {
154 seconds
= atof (prop
->value());
163 ExportFormatSpecification::ExportFormatSpecification (Session
& s
)
166 , has_sample_format (false)
167 , supports_tagging (false)
168 , _has_broadcast_info (false)
170 , _dither_type (D_None
)
171 , _src_quality (SRC_SincBest
)
174 , _trim_beginning (false)
175 , _silence_beginning (s
)
180 , _normalize_target (1.0)
182 format_ids
.insert (F_None
);
183 endiannesses
.insert (E_FileDefault
);
184 sample_formats
.insert (SF_None
);
185 sample_rates
.insert (SR_None
);
186 qualities
.insert (Q_None
);
189 ExportFormatSpecification::ExportFormatSpecification (Session
& s
, XMLNode
const & state
)
191 , _silence_beginning (s
)
194 _silence_beginning
.type
= Time::Timecode
;
195 _silence_end
.type
= Time::Timecode
;
200 ExportFormatSpecification::ExportFormatSpecification (ExportFormatSpecification
const & other
)
201 : ExportFormatBase(other
)
202 , session (other
.session
)
203 , _silence_beginning (other
.session
)
204 , _silence_end (other
.session
)
206 set_name (other
.name() + " (copy)");
208 _format_name
= other
._format_name
;
209 has_sample_format
= other
.has_sample_format
;
211 supports_tagging
= other
.supports_tagging
;
212 _has_broadcast_info
= other
._has_broadcast_info
;
213 _channel_limit
= other
._channel_limit
;
215 set_type (other
.type());
216 set_format_id (other
.format_id());
217 set_endianness (other
.endianness());
218 set_sample_format (other
.sample_format());
219 set_sample_rate (other
.sample_rate());
220 set_quality (other
.quality());
222 set_dither_type (other
.dither_type());
223 set_src_quality (other
.src_quality());
224 set_trim_beginning (other
.trim_beginning());
225 set_trim_end (other
.trim_end());
226 set_normalize (other
.normalize());
227 set_normalize_target (other
.normalize_target());
229 set_tag (other
.tag());
231 set_silence_beginning (other
.silence_beginning_time());
232 set_silence_end (other
.silence_end_time());
235 ExportFormatSpecification::~ExportFormatSpecification ()
240 ExportFormatSpecification::get_state ()
243 XMLNode
* root
= new XMLNode ("ExportFormatSpecification");
245 root
->add_property ("name", _name
);
246 root
->add_property ("id", _id
.to_s());
248 node
= root
->add_child ("Encoding");
249 node
->add_property ("id", enum_2_string (format_id()));
250 node
->add_property ("type", enum_2_string (type()));
251 node
->add_property ("extension", extension());
252 node
->add_property ("name", _format_name
);
253 node
->add_property ("has-sample-format", has_sample_format
? "true" : "false");
254 node
->add_property ("channel-limit", to_string (_channel_limit
, std::dec
));
256 node
= root
->add_child ("SampleRate");
257 node
->add_property ("rate", to_string (sample_rate(), std::dec
));
259 node
= root
->add_child ("SRCQuality");
260 node
->add_property ("quality", enum_2_string (src_quality()));
262 XMLNode
* enc_opts
= root
->add_child ("EncodingOptions");
264 add_option (enc_opts
, "sample-format", enum_2_string (sample_format()));
265 add_option (enc_opts
, "dithering", enum_2_string (dither_type()));
266 add_option (enc_opts
, "tag-metadata", _tag
? "true" : "false");
267 add_option (enc_opts
, "tag-support", supports_tagging
? "true" : "false");
268 add_option (enc_opts
, "broadcast-info", _has_broadcast_info
? "true" : "false");
270 XMLNode
* processing
= root
->add_child ("Processing");
272 node
= processing
->add_child ("Normalize");
273 node
->add_property ("enabled", normalize() ? "true" : "false");
274 node
->add_property ("target", to_string (normalize_target(), std::dec
));
276 XMLNode
* silence
= processing
->add_child ("Silence");
277 XMLNode
* start
= silence
->add_child ("Start");
278 XMLNode
* end
= silence
->add_child ("End");
280 node
= start
->add_child ("Trim");
281 node
->add_property ("enabled", trim_beginning() ? "true" : "false");
283 node
= start
->add_child ("Add");
284 node
->add_property ("enabled", silence_beginning() > 0 ? "true" : "false");
285 node
->add_child_nocopy (_silence_beginning
.get_state());
287 node
= end
->add_child ("Trim");
288 node
->add_property ("enabled", trim_end() ? "true" : "false");
290 node
= end
->add_child ("Add");
291 node
->add_property ("enabled", silence_end() > 0 ? "true" : "false");
292 node
->add_child_nocopy (_silence_end
.get_state());
298 ExportFormatSpecification::set_state (const XMLNode
& root
)
300 XMLProperty
const * prop
;
301 XMLNode
const * child
;
304 if ((prop
= root
.property ("name"))) {
305 _name
= prop
->value();
308 if ((prop
= root
.property ("id"))) {
312 /* Encoding and SRC */
314 if ((child
= root
.child ("Encoding"))) {
315 if ((prop
= child
->property ("id"))) {
316 set_format_id ((FormatId
) string_2_enum (prop
->value(), FormatId
));
319 if ((prop
= child
->property ("type"))) {
320 set_type ((Type
) string_2_enum (prop
->value(), Type
));
323 if ((prop
= child
->property ("extension"))) {
324 set_extension (prop
->value());
327 if ((prop
= child
->property ("name"))) {
328 _format_name
= prop
->value();
331 if ((prop
= child
->property ("has-sample-format"))) {
332 has_sample_format
= !prop
->value().compare ("true");
335 if ((prop
= child
->property ("channel-limit"))) {
336 _channel_limit
= atoi (prop
->value());
340 if ((child
= root
.child ("SampleRate"))) {
341 if ((prop
= child
->property ("rate"))) {
342 set_sample_rate ( (SampleRate
) string_2_enum (prop
->value(), SampleRate
));
346 if ((child
= root
.child ("SRCQuality"))) {
347 if ((prop
= child
->property ("quality"))) {
348 _src_quality
= (SRCQuality
) string_2_enum (prop
->value(), SRCQuality
);
352 /* Encoding options */
354 if ((child
= root
.child ("EncodingOptions"))) {
355 set_sample_format ((SampleFormat
) string_2_enum (get_option (child
, "sample-format"), SampleFormat
));
356 set_dither_type ((DitherType
) string_2_enum (get_option (child
, "dithering"), DitherType
));
357 set_tag (!(get_option (child
, "tag-metadata").compare ("true")));
358 supports_tagging
= (!(get_option (child
, "tag-support").compare ("true")));
359 _has_broadcast_info
= (!(get_option (child
, "broadcast-info").compare ("true")));
364 XMLNode
const * proc
= root
.child ("Processing");
365 if (!proc
) { std::cerr
<< X_("Could not load processing for export format") << std::endl
; return -1; }
367 if ((child
= proc
->child ("Normalize"))) {
368 if ((prop
= child
->property ("enabled"))) {
369 _normalize
= (!prop
->value().compare ("true"));
372 if ((prop
= child
->property ("target"))) {
373 _normalize_target
= atof (prop
->value());
377 XMLNode
const * silence
= proc
->child ("Silence");
378 if (!silence
) { std::cerr
<< X_("Could not load silence for export format") << std::endl
; return -1; }
380 XMLNode
const * start
= silence
->child ("Start");
381 XMLNode
const * end
= silence
->child ("End");
382 if (!start
|| !end
) { std::cerr
<< X_("Could not load end or start silence for export format") << std::endl
; return -1; }
386 if ((child
= start
->child ("Trim"))) {
387 if ((prop
= child
->property ("enabled"))) {
388 _trim_beginning
= (!prop
->value().compare ("true"));
392 if ((child
= start
->child ("Add"))) {
393 if ((prop
= child
->property ("enabled"))) {
394 if (!prop
->value().compare ("true")) {
395 if ((child
= child
->child ("Duration"))) {
396 _silence_beginning
.set_state (*child
);
399 _silence_beginning
.type
= Time::Timecode
;
406 if ((child
= end
->child ("Trim"))) {
407 if ((prop
= child
->property ("enabled"))) {
408 _trim_end
= (!prop
->value().compare ("true"));
412 if ((child
= end
->child ("Add"))) {
413 if ((prop
= child
->property ("enabled"))) {
414 if (!prop
->value().compare ("true")) {
415 if ((child
= child
->child ("Duration"))) {
416 _silence_end
.set_state (*child
);
419 _silence_end
.type
= Time::Timecode
;
428 ExportFormatSpecification::is_compatible_with (ExportFormatCompatibility
const & compatibility
) const
430 boost::shared_ptr
<ExportFormatBase
> intersection
= get_intersection (compatibility
);
432 if (intersection
->formats_empty() && format_id() != 0) {
436 if (intersection
->endiannesses_empty() && endianness() != E_FileDefault
) {
440 if (intersection
->sample_rates_empty() && sample_rate() != SR_None
) {
444 if (intersection
->sample_formats_empty() && sample_format() != SF_None
) {
448 if (intersection
->qualities_empty() && quality() != Q_None
) {
456 ExportFormatSpecification::is_complete () const
458 if (type() == T_None
) {
466 if (!sample_rate()) {
470 if (has_sample_format
) {
471 if (sample_format() == SF_None
) {
480 ExportFormatSpecification::set_format (boost::shared_ptr
<ExportFormat
> format
)
483 set_format_id (format
->get_format_id ());
484 set_type (format
->get_type());
485 set_extension (format
->extension());
487 if (format
->get_explicit_sample_format()) {
488 set_sample_format (format
->get_explicit_sample_format());
491 if (format
->has_sample_format()) {
492 has_sample_format
= true;
495 if (format
->has_broadcast_info()) {
496 _has_broadcast_info
= true;
499 supports_tagging
= format
->supports_tagging ();
500 _channel_limit
= format
->get_channel_limit();
502 _format_name
= format
->name();
504 set_format_id (F_None
);
507 _has_broadcast_info
= false;
508 has_sample_format
= false;
509 supports_tagging
= false;
516 ExportFormatSpecification::description ()
523 desc
+= _("normalize, ");
526 if (_trim_beginning
&& _trim_end
) {
528 } else if (_trim_beginning
) {
529 desc
+= _("trim start, ");
530 } else if (_trim_end
) {
531 desc
+= "trim end, ";
534 desc
+= _format_name
+ ", ";
536 if (has_sample_format
) {
537 desc
+= HasSampleFormat::get_sample_format_name (sample_format()) + ", ";
540 switch (sample_rate()) {
567 ExportFormatSpecification::add_option (XMLNode
* node
, std::string
const & name
, std::string
const & value
)
569 node
= node
->add_child ("Option");
570 node
->add_property ("name", name
);
571 node
->add_property ("value", value
);
575 ExportFormatSpecification::get_option (XMLNode
const * node
, std::string
const & name
)
577 XMLNodeList
list (node
->children ("Option"));
579 for (XMLNodeList::iterator it
= list
.begin(); it
!= list
.end(); ++it
) {
580 XMLProperty
* prop
= (*it
)->property ("name");
581 if (prop
&& !name
.compare (prop
->value())) {
582 prop
= (*it
)->property ("value");
584 return prop
->value();
589 std::cerr
<< "Could not load encoding option \"" << name
<< "\" for export format" << std::endl
;
594 }; // namespace ARDOUR