Add a missing #define to our MSVC project (portaudio_backend)
[ardour.git] / libs / ardour / export_format_specification.cc
index e1e6776a1b8f84979e4f52ef319c25bad3dc8396..7ed52a80e8c2b83ef2bb0972dc50fb892006f304 100644 (file)
 #include "pbd/enumwriter.h"
 #include "pbd/convert.h"
 
-#include "i18n.h"
+#include "pbd/i18n.h"
 
 namespace ARDOUR
 {
 
 using namespace PBD;
 using std::string;
+using std::list;
 
 ExportFormatSpecification::Time &
 ExportFormatSpecification::Time::operator= (AnyTime const & other)
 {
-       type = other.type;
-       timecode = other.timecode;
-       bbt = other.bbt;
-
-       if (type == Frames) {
-               frames = other.frames;
-       } else {
-               seconds = other.seconds;
-       }
-
+       static_cast<AnyTime &>(*this) = other;
        return *this;
 }
 
-nframes_t
-ExportFormatSpecification::Time::get_frames (nframes_t target_rate) const
+framecnt_t
+ExportFormatSpecification::Time::get_frames_at (framepos_t position, framecnt_t target_rate) const
 {
-       //TODO position
-       nframes_t duration = session.convert_to_frames_at (0, *this);
-
+       framecnt_t duration = session.any_duration_to_frames (position, *this);
        return ((double) target_rate / session.frame_rate()) * duration + 0.5;
 }
 
@@ -177,7 +167,16 @@ ExportFormatSpecification::ExportFormatSpecification (Session & s)
        , _silence_end (s)
 
        , _normalize (false)
-       , _normalize_target (1.0)
+       , _normalize_loudness (false)
+       , _normalize_dbfs (GAIN_COEFF_UNITY)
+       , _normalize_lufs (-23)
+       , _normalize_dbtp (-1)
+       , _with_toc (false)
+       , _with_cue (false)
+       , _with_mp4chaps (false)
+       , _soundcloud_upload (false)
+       , _command ("")
+       , _analyse (true)
 {
        format_ids.insert (F_None);
        endiannesses.insert (E_FileDefault);
@@ -188,8 +187,31 @@ ExportFormatSpecification::ExportFormatSpecification (Session & s)
 
 ExportFormatSpecification::ExportFormatSpecification (Session & s, XMLNode const & state)
        : session (s)
+
+       , has_sample_format (false)
+       , supports_tagging (false)
+       , _has_broadcast_info (false)
+       , _channel_limit (0)
+       , _dither_type (D_None)
+       , _src_quality (SRC_SincBest)
+       , _tag (true)
+
+       , _trim_beginning (false)
        , _silence_beginning (s)
+       , _trim_end (false)
        , _silence_end (s)
+
+       , _normalize (false)
+       , _normalize_loudness (false)
+       , _normalize_dbfs (GAIN_COEFF_UNITY)
+       , _normalize_lufs (-23)
+       , _normalize_dbtp (-1)
+       , _with_toc (false)
+       , _with_cue (false)
+       , _with_mp4chaps (false)
+       , _soundcloud_upload (false)
+       , _command ("")
+       , _analyse (true)
 {
        _silence_beginning.type = Time::Timecode;
        _silence_end.type = Time::Timecode;
@@ -197,13 +219,19 @@ ExportFormatSpecification::ExportFormatSpecification (Session & s, XMLNode const
        set_state (state);
 }
 
-ExportFormatSpecification::ExportFormatSpecification (ExportFormatSpecification const & other)
+ExportFormatSpecification::ExportFormatSpecification (ExportFormatSpecification const & other, bool modify_name)
        : ExportFormatBase(other)
        , session (other.session)
        , _silence_beginning (other.session)
        , _silence_end (other.session)
+       , _soundcloud_upload (false)
+       , _analyse (other._analyse)
 {
-       set_name (other.name() + " (copy)");
+       if (modify_name) {
+               set_name (other.name() + " (copy)");
+       } else {
+               set_name (other.name());
+       }
 
        _format_name = other._format_name;
        has_sample_format = other.has_sample_format;
@@ -224,12 +252,17 @@ ExportFormatSpecification::ExportFormatSpecification (ExportFormatSpecification
        set_trim_beginning (other.trim_beginning());
        set_trim_end (other.trim_end());
        set_normalize (other.normalize());
-       set_normalize_target (other.normalize_target());
+       set_normalize_loudness (other.normalize_loudness());
+       set_normalize_dbfs (other.normalize_dbfs());
+       set_normalize_lufs (other.normalize_lufs());
+       set_normalize_dbtp (other.normalize_dbtp());
 
        set_tag (other.tag());
 
        set_silence_beginning (other.silence_beginning_time());
        set_silence_end (other.silence_end_time());
+
+       set_extension(other.extension());
 }
 
 ExportFormatSpecification::~ExportFormatSpecification ()
@@ -239,11 +272,18 @@ ExportFormatSpecification::~ExportFormatSpecification ()
 XMLNode &
 ExportFormatSpecification::get_state ()
 {
+       LocaleGuard lg;
        XMLNode * node;
        XMLNode * root = new XMLNode ("ExportFormatSpecification");
 
        root->add_property ("name", _name);
        root->add_property ("id", _id.to_s());
+       root->add_property ("with-cue", _with_cue ? "true" : "false");
+       root->add_property ("with-toc", _with_toc ? "true" : "false");
+       root->add_property ("with-mp4chaps", _with_mp4chaps ? "true" : "false");
+       root->add_property ("command", _command);
+       root->add_property ("analyse", _analyse ? "true" : "false");
+       root->add_property ("soundcloud-upload", _soundcloud_upload ? "true" : "false");
 
        node = root->add_child ("Encoding");
        node->add_property ("id", enum_2_string (format_id()));
@@ -271,7 +311,10 @@ ExportFormatSpecification::get_state ()
 
        node = processing->add_child ("Normalize");
        node->add_property ("enabled", normalize() ? "true" : "false");
-       node->add_property ("target", to_string (normalize_target(), std::dec));
+       node->add_property ("loudness", normalize_loudness() ? "yes" : "no");
+       node->add_property ("dbfs", to_string (normalize_dbfs(), std::dec));
+       node->add_property ("lufs", to_string (normalize_lufs(), std::dec));
+       node->add_property ("dbtp", to_string (normalize_dbtp(), std::dec));
 
        XMLNode * silence = processing->add_child ("Silence");
        XMLNode * start = silence->add_child ("Start");
@@ -281,14 +324,14 @@ ExportFormatSpecification::get_state ()
        node->add_property ("enabled", trim_beginning() ? "true" : "false");
 
        node = start->add_child ("Add");
-       node->add_property ("enabled", silence_beginning() > 0 ? "true" : "false");
+       node->add_property ("enabled", _silence_beginning.not_zero() ? "true" : "false");
        node->add_child_nocopy (_silence_beginning.get_state());
 
        node = end->add_child ("Trim");
        node->add_property ("enabled", trim_end() ? "true" : "false");
 
        node = end->add_child ("Add");
-       node->add_property ("enabled", silence_end() > 0 ? "true" : "false");
+       node->add_property ("enabled", _silence_end.not_zero() ? "true" : "false");
        node->add_child_nocopy (_silence_end.get_state());
 
        return *root;
@@ -300,6 +343,7 @@ ExportFormatSpecification::set_state (const XMLNode & root)
        XMLProperty const * prop;
        XMLNode const * child;
        string value;
+       LocaleGuard lg;
 
        if ((prop = root.property ("name"))) {
                _name = prop->value();
@@ -309,6 +353,42 @@ ExportFormatSpecification::set_state (const XMLNode & root)
                _id = prop->value();
        }
 
+       if ((prop = root.property ("with-cue"))) {
+               _with_cue = string_is_affirmative (prop->value());
+       } else {
+               _with_cue = false;
+       }
+
+       if ((prop = root.property ("with-toc"))) {
+               _with_toc = string_is_affirmative (prop->value());
+       } else {
+               _with_toc = false;
+       }
+
+       if ((prop = root.property ("with-mp4chaps"))) {
+               _with_mp4chaps = string_is_affirmative (prop->value());
+       } else {
+               _with_mp4chaps = false;
+       }
+
+       if ((prop = root.property ("command"))) {
+               _command = prop->value();
+       } else {
+               _command = "";
+       }
+
+       if ((prop = root.property ("analyse"))) {
+               _analyse = string_is_affirmative (prop->value());
+       } else {
+               _analyse = false;
+       }
+
+       if ((prop = root.property ("soundcloud-upload"))) {
+               _soundcloud_upload = string_is_affirmative (prop->value());
+       } else {
+               _soundcloud_upload = false;
+       }
+
        /* Encoding and SRC */
 
        if ((child = root.child ("Encoding"))) {
@@ -329,7 +409,11 @@ ExportFormatSpecification::set_state (const XMLNode & root)
                }
 
                if ((prop = child->property ("has-sample-format"))) {
-                       has_sample_format = !prop->value().compare ("true");
+                       has_sample_format = string_is_affirmative (prop->value());
+               }
+
+               if ((prop = child->property ("has-sample-format"))) {
+                       has_sample_format = string_is_affirmative (prop->value());
                }
 
                if ((prop = child->property ("channel-limit"))) {
@@ -369,8 +453,25 @@ ExportFormatSpecification::set_state (const XMLNode & root)
                        _normalize = (!prop->value().compare ("true"));
                }
 
+               // old formats before ~ 4.7-930ish
                if ((prop = child->property ("target"))) {
-                       _normalize_target = atof (prop->value());
+                       _normalize_dbfs = atof (prop->value());
+               }
+
+               if ((prop = child->property ("loudness"))) {
+                       _normalize_loudness = string_is_affirmative (prop->value());
+               }
+
+               if ((prop = child->property ("dbfs"))) {
+                       _normalize_dbfs = atof (prop->value());
+               }
+
+               if ((prop = child->property ("lufs"))) {
+                       _normalize_lufs = atof (prop->value());
+               }
+
+               if ((prop = child->property ("dbtp"))) {
+                       _normalize_dbtp = atof (prop->value());
                }
        }
 
@@ -512,54 +613,92 @@ ExportFormatSpecification::set_format (boost::shared_ptr<ExportFormat> format)
        }
 }
 
-Glib::ustring
-ExportFormatSpecification::description ()
+string
+ExportFormatSpecification::description (bool include_name)
 {
-       Glib::ustring desc;
-
-       desc = _name + ": ";
+       list<string> components;
 
        if (_normalize) {
-               desc += _("normalize, ");
+               if (_normalize_loudness) {
+                       components.push_back (_("normalize loudness"));
+               } else {
+                       components.push_back (_("normalize peak"));
+               }
        }
 
        if (_trim_beginning && _trim_end) {
-               desc += _("trim, ");
+               components.push_back ( _("trim"));
        } else if (_trim_beginning) {
-               desc += _("trim start, ");
+               components.push_back (_("trim start"));
        } else if (_trim_end) {
-               desc += "trim end, ";
+               components.push_back (_("trim end"));
        }
 
-       desc += _format_name + ", ";
+       if (_format_name != "") {
+               components.push_back (_format_name);
+       }
 
        if (has_sample_format) {
-               desc += HasSampleFormat::get_sample_format_name (sample_format())  + ", ";
+               components.push_back (HasSampleFormat::get_sample_format_name (sample_format()));
        }
 
        switch (sample_rate()) {
-         case SR_22_05:
-               desc += "22,5 kHz";
+       case SR_8:
+               components.push_back ("8 kHz");
+               break;
+       case SR_22_05:
+               components.push_back ("22,5 kHz");
+               break;
+       case SR_44_1:
+               components.push_back ("44,1 kHz");
                break;
-         case SR_44_1:
-               desc += "44,1 kHz";
+       case SR_48:
+               components.push_back ("48 kHz");
                break;
-         case SR_48:
-               desc += "48 kHz";
+       case SR_88_2:
+               components.push_back ("88,2 kHz");
                break;
-         case SR_88_2:
-               desc += "88,2 kHz";
+       case SR_96:
+               components.push_back ("96 kHz");
                break;
-         case SR_96:
-               desc += "96 kHz";
+       case SR_176_4:
+               components.push_back ("176.4 kHz");
                break;
-         case SR_192:
-               desc += "192 kHz";
+       case SR_192:
+               components.push_back ("192 kHz");
                break;
-         case SR_None:
+       case SR_Session:
+               components.push_back (_("Session rate"));
                break;
+       case SR_None:
+               break;
+       }
+
+       if (_with_toc) {
+               components.push_back ("TOC");
+       }
+
+       if (_with_cue) {
+               components.push_back ("CUE");
+       }
+
+       if (_with_mp4chaps) {
+               components.push_back ("MP4ch");
+       }
+
+       if (!_command.empty()) {
+               components.push_back ("+");
+       }
+
+       string desc;
+       if (include_name) {
+               desc = _name + ": ";
        }
 
+       for (list<string>::const_iterator it = components.begin(); it != components.end(); ++it) {
+               if (it != components.begin()) { desc += ", "; }
+               desc += *it;
+       }
        return desc;
 }
 
@@ -577,7 +716,7 @@ ExportFormatSpecification::get_option (XMLNode const * node, std::string const &
        XMLNodeList list (node->children ("Option"));
 
        for (XMLNodeList::iterator it = list.begin(); it != list.end(); ++it) {
-               XMLProperty * prop = (*it)->property ("name");
+               XMLProperty const * prop = (*it)->property ("name");
                if (prop && !name.compare (prop->value())) {
                        prop = (*it)->property ("value");
                        if (prop) {