@vidispine/vdt-js 22.3.0-pre.5 → 22.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -259,7 +259,7 @@ var roles = /*#__PURE__*/Object.freeze({
259
259
  VXA_READ: VXA_READ
260
260
  });
261
261
 
262
- var _excluded$4 = ["value"],
262
+ var _excluded$8 = ["value"],
263
263
  _excluded2$2 = ["start", "end"];
264
264
 
265
265
  function ownKeys$7(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
@@ -271,7 +271,7 @@ var GROUP_PROPERTY_KEYS = [].concat(COMBINED_PROPERTY_KEYS, ['cycle']);
271
271
  var FIELD_PROPERTY_KEYS = [].concat(COMBINED_PROPERTY_KEYS, ['value', 'reference', 'type', 'track']);
272
272
  var FIELD_VALUE_PROPERTY_KEYS = [].concat(COMBINED_PROPERTY_KEYS, ['value', 'lang']);
273
273
 
274
- var isObject = function isObject(o) {
274
+ var isObject$1 = function isObject(o) {
275
275
  return Object.prototype.toString.call(o) === '[object Object]';
276
276
  };
277
277
 
@@ -287,7 +287,7 @@ var isField = function isField(value) {
287
287
  };
288
288
 
289
289
  var isFieldObject = function isFieldObject(v) {
290
- return isObject(v) && (v.value === null || isObject(v.value) || isFieldType(v.value));
290
+ return isObject$1(v) && (v.value === null || isObject$1(v.value) || isFieldType(v.value));
291
291
  };
292
292
 
293
293
  if (value === null) {
@@ -303,7 +303,7 @@ var isField = function isField(value) {
303
303
 
304
304
  var isGroup = function isGroup(value) {
305
305
  var isGroupObject = function isGroupObject(v) {
306
- return isObject(v) && v.value === undefined && Object.entries(value);
306
+ return isObject$1(v) && v.value === undefined && Object.entries(value);
307
307
  };
308
308
 
309
309
  if (Array.isArray(value)) {
@@ -355,7 +355,7 @@ var parseValueObject = function parseValueObject(valueObject) {
355
355
  var parseFieldValue = function parseFieldValue(value) {
356
356
  if ([undefined, null].includes(value)) return undefined;
357
357
  if (Array.isArray(value)) return value.map(parseFieldValue);
358
- if (isObject(value)) return parseValueObject(value);
358
+ if (isObject$1(value)) return parseValueObject(value);
359
359
  return parseValue(value);
360
360
  };
361
361
 
@@ -365,7 +365,7 @@ var parseFieldObject = function parseFieldObject(fieldObject) {
365
365
 
366
366
  if (parsedFieldValue === undefined) {
367
367
  fieldObject.value;
368
- var fieldObjectWithoutValue = _objectWithoutProperties__default["default"](fieldObject, _excluded$4);
368
+ var fieldObjectWithoutValue = _objectWithoutProperties__default["default"](fieldObject, _excluded$8);
369
369
 
370
370
  return fieldObjectWithoutValue;
371
371
  }
@@ -376,7 +376,7 @@ var parseFieldObject = function parseFieldObject(fieldObject) {
376
376
  };
377
377
 
378
378
  var parseField$1 = function parseField(field) {
379
- if (isObject(field)) {
379
+ if (isObject$1(field)) {
380
380
  return parseFieldObject(field);
381
381
  }
382
382
 
@@ -451,10 +451,10 @@ var parseTimespan$1 = function parseTimespan() {
451
451
  });
452
452
  };
453
453
  /**
454
- * Create a MetadataType object from a metadata object
454
+ * Create a VidiCore MetadataType from a simplified object structure
455
455
  *
456
- * @param {Object} metadata - object with metadata to create MetadataType object of
457
- * @returns {Object} MetadataType
456
+ * @param {object} metadata - object to create MetadataType from
457
+ * @returns {object} a MetadataType object
458
458
  */
459
459
 
460
460
 
@@ -490,7 +490,7 @@ var sortTimespanList = function sortTimespanList(timespan1, timespan2) {
490
490
  return 0;
491
491
  };
492
492
 
493
- var _excluded$3 = ["value"],
493
+ var _excluded$7 = ["value"],
494
494
  _excluded2$1 = ["field", "group"],
495
495
  _excluded3 = ["field", "group"];
496
496
 
@@ -535,7 +535,7 @@ var parseField = function parseField() {
535
535
 
536
536
  var _field$value = field.value,
537
537
  value = _field$value === void 0 ? [] : _field$value,
538
- attributes = _objectWithoutProperties__default["default"](field, _excluded$3);
538
+ attributes = _objectWithoutProperties__default["default"](field, _excluded$7);
539
539
 
540
540
  var parsedValueList = parseValueList(value, options);
541
541
  if (includeAttributes || includeFieldAttributes) return _objectSpread$6(_objectSpread$6({}, attributes), {}, {
@@ -684,21 +684,21 @@ var parseGroupList = function parseGroupList() {
684
684
  /**
685
685
  * Parses timespan according to specified options.
686
686
  * The attributes can be targeted for each sub-type.
687
- * @param {Object} timespan={} - The timespan response from the API.
688
- * @param {Object} options={} - Options which change how the metadataType is parsed.
689
- * @param {string} options.joinValue=undefined - String to join the values, eg ','.
690
- * @param {boolean} options.includeAttributes=false - Include attributes on all objects.
691
- * @param {boolean} options.includeTimespanAttributes=false - Include attributes on timespans.
692
- * @param {boolean} options.includeGroupAttributes=false - Include attributes on groups.
693
- * @param {boolean} options.includeFieldAttributes=false - Include attributes on fields.
694
- * @param {boolean} options.includeValueAttributes=false - Include attributes on values.
695
- * @param {boolean} options.flat=false - Flatten to key/value (Note: keys may be overwritten).
696
- * @param {boolean} options.flatTimespan=false - Flatten timespan.
697
- * @param {boolean} options.flatGroup=false - Flatten group.
698
- * @param {boolean} options.groupAsList=false - Return groups as list.
699
- * @param {boolean} options.fieldAsList=false - Return fields as list.
700
- * @param {boolean} options.arrayOnSingle=true - Return fields as array even if single field.
701
- * @param {boolean} options.arrayOnSingleValue=true - Return fields as array even if single field value.
687
+ * @param {Object} [timespan={}] - A timespan from VidiCore.
688
+ * @param {Object} [options={}] - Options which change how the metadataType is parsed.
689
+ * @param {string} [options.joinValue=undefined] - String to join the values, eg ','.
690
+ * @param {boolean} [options.includeAttributes=false] - Include attributes on all objects.
691
+ * @param {boolean} [options.includeTimespanAttributes=false] - Include attributes on timespans.
692
+ * @param {boolean} [options.includeGroupAttributes=false] - Include attributes on groups.
693
+ * @param {boolean} [options.includeFieldAttributes=false] - Include attributes on fields.
694
+ * @param {boolean} [options.includeValueAttributes=false] - Include attributes on values.
695
+ * @param {boolean} [options.flat=false] - Flatten to key/value (Note: keys may be overwritten).
696
+ * @param {boolean} [options.flatTimespan=false] - Flatten timespan.
697
+ * @param {boolean} [options.flatGroup=false] - Flatten group.
698
+ * @param {boolean} [options.groupAsList=false] - Return groups as list.
699
+ * @param {boolean} [options.fieldAsList=false] - Return fields as list.
700
+ * @param {boolean} [options.arrayOnSingle=true] - Return fields as array even if single field.
701
+ * @param {boolean} [options.arrayOnSingleValue=true] - Return fields as array even if single field value.
702
702
  * @returns {Object} Metadata object parsed according to options.
703
703
  */
704
704
 
@@ -763,7 +763,8 @@ function _objectSpread$5(target) { for (var i = 1; i < arguments.length; i++) {
763
763
  /**
764
764
  * Parses timespanList according to specified options.
765
765
  * The attributes can be targeted for each sub-type.
766
- * @param {Object[]} timespanList - The timespanList response from the API.
766
+ *
767
+ * @param {Object[]} timespanList - A timespanList from VidiCore.
767
768
  * @param {Object} options - Options which change how the metadataType is parsed.
768
769
  * @param {string} options.joinValue - String to join the values, eg ','.
769
770
  * @param {boolean} options.includeAttributes - Include attributes on all objects.
@@ -779,8 +780,8 @@ function _objectSpread$5(target) { for (var i = 1; i < arguments.length; i++) {
779
780
  * @param {boolean} options.timespanAsList - Return timespans as list.
780
781
  * @param {boolean} options.groupAsList - Return groups as list.
781
782
  * @param {boolean} options.fieldAsList - Return fields as list.
782
- * @param {boolean} options.arrayOnSingle=true - Return fields as array even if single field.
783
- * @param {boolean} options.arrayOnSingleValue=true - Return fields as array even if single field value.
783
+ * @param {boolean} [options.arrayOnSingle=true] - Return fields as array even if single field.
784
+ * @param {boolean} [options.arrayOnSingleValue=true] - Return fields as array even if single field value.
784
785
  * @returns {Object} Metadata object parsed according to options.
785
786
  */
786
787
 
@@ -823,11 +824,11 @@ var parseTimespanList = function parseTimespanList() {
823
824
  return output;
824
825
  };
825
826
 
826
- var _excluded$2 = ["timespan"];
827
+ var _excluded$6 = ["timespan"];
827
828
  /**
828
829
  * Parses MetadataType according to specified options.
829
830
  * The attributes can be targeted for each sub-type.
830
- * @param {Object} metadataType - The MetadataType response from the API.
831
+ * @param {Object} metadataType - A MetadataType from VidiCore.
831
832
  * @param {Object} options - Options which change how the metadataType is parsed.
832
833
  * @param {string} options.joinValue - String to join the values, eg ','.
833
834
  * @param {boolean} options.includeAttributes - Include attributes on all objects.
@@ -843,8 +844,8 @@ var _excluded$2 = ["timespan"];
843
844
  * @param {boolean} options.timespanAsList - Return timespans as list.
844
845
  * @param {boolean} options.groupAsList - Return groups as list.
845
846
  * @param {boolean} options.fieldAsList - Return fields as list.
846
- * @param {boolean} options.arrayOnSingle=true - Return fields as array even if single field.
847
- * @param {boolean} options.arrayOnSingleValue=true - Return fields as array even if single field value.
847
+ * @param {boolean} [options.arrayOnSingle=true] - Return fields as array even if single field.
848
+ * @param {boolean} [options.arrayOnSingleValue=true] - Return fields as array even if single field value.
848
849
  * @returns {Object} Metadata object parsed according to options.
849
850
  */
850
851
 
@@ -860,7 +861,7 @@ var parseMetadataType = function parseMetadataType() {
860
861
  var _ref2 = metadataType || {},
861
862
  _ref2$timespan = _ref2.timespan,
862
863
  timespanList = _ref2$timespan === void 0 ? [] : _ref2$timespan,
863
- attributes = _objectWithoutProperties__default["default"](_ref2, _excluded$2);
864
+ attributes = _objectWithoutProperties__default["default"](_ref2, _excluded$6);
864
865
 
865
866
  if (sortTimespan) timespanList.sort(sortTimespanList);
866
867
  var timespan = parseTimespanList(timespanList, options);
@@ -885,12 +886,12 @@ function ownKeys$4(object, enumerableOnly) { var keys = Object.keys(object); if
885
886
  function _objectSpread$4(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys$4(Object(source), !0).forEach(function (key) { _defineProperty__default["default"](target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys$4(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
886
887
 
887
888
  /**
888
- * Parses highlight timespan responses from the api into key/value object.
889
+ * Parses highlight timespan in VidiCore into key/value object.
889
890
  * The attributes can be targeted for each sub-type.
890
- * @param {Object[]} highlightTimespan - A timespan object from the api response.
891
+ * @param {Object[]} highlightTimespan - A VidiCore timespan object.
891
892
  * @param {Object} options - Options which change how the timespans are parsed.
892
- * @param {boolean} options.arrayOnSingle=true - Return an array if there is a single value.
893
- * @param {boolean} options.timespanAsList=false - Return timespans as list.
893
+ * @param {boolean} [options.arrayOnSingle=true] - Return an array if there is a single value.
894
+ * @param {boolean} [options.timespanAsList=false] - Return timespans as list.
894
895
  * @param {string} options.joinValue - String to join the values, eg ','.
895
896
  */
896
897
  var parseHighlightTimespan = function parseHighlightTimespan() {
@@ -933,38 +934,38 @@ function ownKeys$3(object, enumerableOnly) { var keys = Object.keys(object); if
933
934
 
934
935
  function _objectSpread$3(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys$3(Object(source), !0).forEach(function (key) { _defineProperty__default["default"](target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys$3(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
935
936
  /**
936
- * Parses highlight timespans responses from the api into key/value object.
937
+ * Parses highlight timespans from VidiCore into key/value object.
937
938
  * The attributes can be targeted for each sub-type.
938
- * @param {Object} highlightTimespanList - A list of timespans from the api response.
939
+ * @param {Object} highlightTimespanList - A list of timespans from VidiCore.
939
940
  * @param {Object} options - Options which change how the timespans are parsed.
940
- * @param {boolean} options.arrayOnSingle=true - Return an array if there is a single value.
941
+ * @param {boolean} [options.arrayOnSingle=true] - Return an array if there is a single value.
941
942
  * @param {string} options.joinValue - String to join the values, eg ','.
942
- * @param {boolean} options.timespanAsList=false - Return timespans as list.
943
- * @param {boolean} options.flat=false - Flatten to field-name/field-value (Note: field-values may be overwritten).
944
- * @param {boolean} options.flatTimespan=false - Flatten timespan to object with start/end as key.
945
- * @param {string} options.joinTimespan=_ - Character to join the start/end timecodes.
943
+ * @param {boolean} [options.timespanAsList=false] - Return timespans as list.
944
+ * @param {boolean} [options.flat=false] - Flatten to field-name/field-value (Note: field-values may be overwritten).
945
+ * @param {boolean} [options.flatTimespan=false] - Flatten timespan to object with start/end as key.
946
+ * @param {string} [options.joinTimespan=_] - Character to join the start/end timecodes.
946
947
  */
947
948
 
948
949
  var parseHighlightTimespanList = function parseHighlightTimespanList() {
949
950
  var highlightTimespanList = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
950
- var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
951
- var flat = opts.flat,
952
- timespanAsList = opts.timespanAsList,
953
- _opts$joinTimespan = opts.joinTimespan,
954
- joinTimespan = _opts$joinTimespan === void 0 ? '_' : _opts$joinTimespan,
955
- flatTimespan = opts.flatTimespan;
951
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
952
+ var flat = options.flat,
953
+ timespanAsList = options.timespanAsList,
954
+ _options$joinTimespan = options.joinTimespan,
955
+ joinTimespan = _options$joinTimespan === void 0 ? '_' : _options$joinTimespan,
956
+ flatTimespan = options.flatTimespan;
956
957
  if (timespanAsList === true) return highlightTimespanList.map(function (timespan) {
957
- return parseHighlightTimespan(timespan, opts);
958
+ return parseHighlightTimespan(timespan, options);
958
959
  });
959
960
  if (flat === true || flatTimespan === true) return highlightTimespanList.reduce(function (a, timespan) {
960
- return _objectSpread$3(_objectSpread$3({}, a), parseHighlightTimespan(timespan, opts));
961
+ return _objectSpread$3(_objectSpread$3({}, a), parseHighlightTimespan(timespan, options));
961
962
  }, {});
962
963
  return highlightTimespanList.reduce(function (a, timespan) {
963
- return _objectSpread$3(_objectSpread$3({}, a), {}, _defineProperty__default["default"]({}, [timespan.start, timespan.end].join(joinTimespan), parseHighlightTimespan(timespan, opts)));
964
+ return _objectSpread$3(_objectSpread$3({}, a), {}, _defineProperty__default["default"]({}, [timespan.start, timespan.end].join(joinTimespan), parseHighlightTimespan(timespan, options)));
964
965
  }, {});
965
966
  };
966
967
 
967
- var CONSTANT_TIMEBASES = {
968
+ var MAP_CONSTANT_TO_DEN_NUM = {
968
969
  PAL: {
969
970
  denominator: 25,
970
971
  numerator: 1
@@ -984,59 +985,61 @@ var CONSTANT_TIMEBASES = {
984
985
  59.94: {
985
986
  denominator: 60000,
986
987
  numerator: 1001
987
- }
988
- };
989
- var FRAME_SEPARATORS = {
990
- ':': {
991
- dropFrame: false,
992
- field: 2
993
- },
994
- ';': {
995
- dropFrame: true,
996
- field: 2
997
988
  },
998
- '.': {
999
- dropFrame: false,
1000
- field: 1
989
+ 23.976: {
990
+ denominator: 48000,
991
+ numerator: 2002
1001
992
  },
1002
- ',': {
1003
- dropFrame: true,
1004
- field: 1
993
+ 23.98: {
994
+ denominator: 48000,
995
+ numerator: 2002
1005
996
  }
1006
997
  };
998
+ var TIME_BASE_CONSTANTS = Object.keys(MAP_CONSTANT_TO_DEN_NUM);
999
+
1000
+ /**
1001
+ * TimeBase class representing the TimeBaseType in VidiCore
1002
+ *
1003
+ * For more info, see the [Time bases section in VidiCore API Docs](https://apidoc.vidispine.com/latest/time.html#time-bases)
1004
+ */
1007
1005
 
1008
1006
  var TimeBase = /*#__PURE__*/function () {
1009
- function TimeBase() {
1010
- var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
1007
+ /**
1008
+ * Constructor for TimeBase
1009
+ *
1010
+ * @param {object} [timeCodeType={}] A time base type object
1011
+ * @param {number} [timeCodeType.numerator=1] The numerator for the TimeBase
1012
+ * @param {number} [timeCodeType.denominator=1] The denominator for the TimeBase
1013
+ */
1014
+ function TimeBase(timeCodeType) {
1015
+ _classCallCheck__default["default"](this, TimeBase);
1016
+
1017
+ var _ref = timeCodeType || {},
1011
1018
  _ref$numerator = _ref.numerator,
1012
1019
  numerator = _ref$numerator === void 0 ? 1 : _ref$numerator,
1013
1020
  _ref$denominator = _ref.denominator,
1014
1021
  denominator = _ref$denominator === void 0 ? 1 : _ref$denominator;
1015
1022
 
1016
- _classCallCheck__default["default"](this, TimeBase);
1017
-
1018
1023
  this.numerator = Number(numerator);
1019
1024
  this.denominator = Number(denominator);
1020
1025
  }
1026
+ /**
1027
+ * Get TimeBase in a constant representation (e.g. "PAL") if possible, otherwise undefined
1028
+ * @returns {string} Constant representation of the TimeBase
1029
+ */
1030
+
1021
1031
 
1022
1032
  _createClass__default["default"](TimeBase, [{
1023
- key: "toJSON",
1024
- value: function toJSON() {
1025
- return {
1026
- denominator: this.denominator,
1027
- numerator: this.numerator
1028
- };
1029
- }
1030
- }, {
1031
1033
  key: "toConstant",
1032
1034
  value: function toConstant() {
1033
1035
  var _this = this;
1034
1036
 
1035
- var constant;
1036
- Object.entries(CONSTANT_TIMEBASES).find(function (thisTimeBase) {
1037
- var _thisTimeBase = _slicedToArray__default["default"](thisTimeBase, 2),
1038
- thisTimeBaseText = _thisTimeBase[0],
1039
- thisTimeBaseType = _thisTimeBase[1];
1037
+ var constant; // If multiple equal den/num, it selects first in MAP_CONSTANT_TO_DEN_NUM
1038
+
1039
+ Object.entries(MAP_CONSTANT_TO_DEN_NUM).find(function (timeBaseConstant) {
1040
+ var _timeBaseConstant = _slicedToArray__default["default"](timeBaseConstant, 2),
1041
+ thisTimeBaseText = _timeBaseConstant[0],
1042
+ thisTimeBaseType = _timeBaseConstant[1];
1040
1043
 
1041
1044
  var numerator = thisTimeBaseType.numerator,
1042
1045
  denominator = thisTimeBaseType.denominator;
@@ -1050,18 +1053,36 @@ var TimeBase = /*#__PURE__*/function () {
1050
1053
  });
1051
1054
  return constant;
1052
1055
  }
1056
+ /**
1057
+ * Get TimeBase as a VidiCore TimeBaseType string
1058
+ *
1059
+ * Default format: denominator(:numerator if > 1)
1060
+ * `constant` has precedence over `fraction` if both are true (e.g. NTSC > 30000:1001)
1061
+ *
1062
+ * @param {object} [options={}] For how to display it as text
1063
+ * @param {boolean} [options.constant=false] Show time base as constant (e.g. PAL)
1064
+ * @param {boolean} [options.fraction=false] Show time base as fraction (25:1) even when numerator is 1
1065
+ * @returns {string} Text representation of the TimeBase
1066
+ */
1067
+
1053
1068
  }, {
1054
1069
  key: "toText",
1055
1070
  value: function toText() {
1056
- var useConstant = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
1071
+ var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1072
+
1073
+ var _ref2 = options || {},
1074
+ _ref2$constant = _ref2.constant,
1075
+ constant = _ref2$constant === void 0 ? false : _ref2$constant,
1076
+ _ref2$fraction = _ref2.fraction,
1077
+ fraction = _ref2$fraction === void 0 ? false : _ref2$fraction;
1057
1078
 
1058
- if (useConstant) {
1079
+ if (constant) {
1059
1080
  var _timeBaseText = this.toConstant();
1060
1081
 
1061
1082
  if (_timeBaseText) return _timeBaseText;
1062
1083
  }
1063
1084
 
1064
- if (this.numerator > 1) {
1085
+ if (fraction || this.numerator > 1) {
1065
1086
  var _timeBaseText2 = [this.denominator, this.numerator].join(':');
1066
1087
 
1067
1088
  return _timeBaseText2;
@@ -1070,13 +1091,40 @@ var TimeBase = /*#__PURE__*/function () {
1070
1091
  var timeBaseText = String(this.denominator);
1071
1092
  return timeBaseText;
1072
1093
  }
1094
+ /**
1095
+ * Output TimeBase as frame rate (by default max 16 decimal places)
1096
+ *
1097
+ *
1098
+ * For `options.fixed`:
1099
+ * - `true` gives two decimal places
1100
+ * - `false` gives max amount of decimal places
1101
+ * - `number` gives that amount of decimal places
1102
+ *
1103
+ * Default format: rate with two decimals if needed (i.e. decimals are > 0)
1104
+ * Option precedence (when all true): `constant` > `rounded` > `fixed`
1105
+ *
1106
+ * @param {object} [options={}] For how to display it as rate
1107
+ * @param {boolean|number} [options.fixed=true] Amount of decimal places (true gives 2 decimal places)
1108
+ * @param {boolean} [options.constant=false] Use constant representation (if applicable)
1109
+ * @param {boolean} [options.rounded=false] Rounded to nearest integer
1110
+ *
1111
+ * @returns {number} Rate of the TimeBase
1112
+ */
1113
+
1073
1114
  }, {
1074
1115
  key: "toRate",
1075
1116
  value: function toRate() {
1076
- var useConstant = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
1077
- var round = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
1117
+ var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1118
+
1119
+ var _ref3 = options || {},
1120
+ _ref3$constant = _ref3.constant,
1121
+ constant = _ref3$constant === void 0 ? false : _ref3$constant,
1122
+ _ref3$rounded = _ref3.rounded,
1123
+ rounded = _ref3$rounded === void 0 ? false : _ref3$rounded,
1124
+ _ref3$fixed = _ref3.fixed,
1125
+ fixed = _ref3$fixed === void 0 ? true : _ref3$fixed;
1078
1126
 
1079
- if (useConstant) {
1127
+ if (constant) {
1080
1128
  var _rate = this.toConstant();
1081
1129
 
1082
1130
  if (_rate) return _rate;
@@ -1088,56 +1136,110 @@ var TimeBase = /*#__PURE__*/function () {
1088
1136
  return rate;
1089
1137
  }
1090
1138
 
1091
- return round ? rate.toFixed(2) : rate;
1139
+ if (rounded) {
1140
+ return Math.round(rate);
1141
+ }
1142
+
1143
+ if (fixed === true || typeof fixed === 'number') {
1144
+ return Number(rate.toFixed(fixed === true ? 2 : fixed));
1145
+ }
1146
+
1147
+ return rate;
1148
+ }
1149
+ /**
1150
+ * Get TimeBase in a object representation
1151
+ *
1152
+ * @returns {object} TimeBase as `{denominator, numerator}` object
1153
+ */
1154
+
1155
+ }, {
1156
+ key: "toObject",
1157
+ value: function toObject() {
1158
+ return {
1159
+ denominator: this.denominator,
1160
+ numerator: this.numerator
1161
+ };
1162
+ }
1163
+ /**
1164
+ * @deprecated Use {@link TimeBase#toObject|toObject} instead
1165
+ *
1166
+ * @returns {object} TimeBase as `{denominator, numerator}` object
1167
+ */
1168
+
1169
+ }, {
1170
+ key: "toJson",
1171
+ value: function toJson() {
1172
+ // eslint-disable-next-line no-console
1173
+ console.warn('Deprecated - use toObject instead');
1174
+ return this.toObject();
1092
1175
  }
1093
1176
  }]);
1094
1177
 
1095
1178
  return TimeBase;
1096
1179
  }();
1097
1180
 
1098
- var formatTimeBaseType = function formatTimeBaseType(timeBase) {
1099
- return new TimeBase(timeBase);
1100
- };
1181
+ /**
1182
+ * Format a string representation of a time base to a TimeBase Instance
1183
+ *
1184
+ * @param {string} timeBaseText The string to format to a TimeBase instance
1185
+ * @returns {TimeBase} A TimeBase Instance
1186
+ */
1101
1187
 
1102
1188
  var formatTimeBaseText = function formatTimeBaseText(timeBaseText) {
1103
1189
  if (timeBaseText === undefined) {
1104
- return formatTimeBaseType();
1190
+ return new TimeBase();
1105
1191
  }
1106
1192
 
1107
1193
  if (typeof timeBaseText === 'number') {
1108
- return formatTimeBaseType({
1194
+ return new TimeBase({
1109
1195
  denominator: timeBaseText
1110
1196
  });
1111
1197
  }
1112
1198
 
1113
- if (timeBaseText.includes(':')) {
1199
+ if (typeof timeBaseText === 'string' && timeBaseText.includes(':')) {
1114
1200
  var _timeBaseText$split = timeBaseText.split(':'),
1115
1201
  _timeBaseText$split2 = _slicedToArray__default["default"](_timeBaseText$split, 2),
1116
- _denominator = _timeBaseText$split2[0],
1202
+ denominator = _timeBaseText$split2[0],
1117
1203
  numerator = _timeBaseText$split2[1];
1118
1204
 
1119
- return formatTimeBaseType({
1120
- denominator: _denominator,
1205
+ return new TimeBase({
1206
+ denominator: denominator,
1121
1207
  numerator: numerator
1122
1208
  });
1123
1209
  }
1124
1210
 
1125
- if (Object.keys(CONSTANT_TIMEBASES).includes(timeBaseText)) {
1126
- return formatTimeBaseType(CONSTANT_TIMEBASES[timeBaseText]);
1211
+ if (TIME_BASE_CONSTANTS.includes(timeBaseText)) {
1212
+ return new TimeBase(MAP_CONSTANT_TO_DEN_NUM[timeBaseText]);
1127
1213
  }
1128
1214
 
1129
- var denominator = Number(timeBaseText);
1130
-
1131
- if (Number.isNaN(denominator)) {
1132
- throw new Error("timeBaseText must be a number or ".concat(Object.keys(CONSTANT_TIMEBASES).join(','), " - is ").concat(timeBaseText));
1215
+ if (!['string', 'number'].includes(_typeof__default["default"](timeBaseText)) || Number.isNaN(Number(timeBaseText))) {
1216
+ throw new Error("timeBaseText must be a number or ".concat(TIME_BASE_CONSTANTS.join(','), " - is ").concat(JSON.stringify(timeBaseText)));
1133
1217
  }
1134
1218
 
1135
- return formatTimeBaseType({
1136
- denominator: denominator
1219
+ return new TimeBase({
1220
+ denominator: Number(timeBaseText)
1137
1221
  });
1138
1222
  };
1139
1223
 
1140
- var formatTimeBase = function formatTimeBase(timeBase) {
1224
+ /**
1225
+ * Create a TimeBase instance of an object
1226
+ *
1227
+ * @param {object} timeBase A TimeBase object ({ numerator, denominator })
1228
+ * @returns {TimeBase} A TimeBase instance
1229
+ */
1230
+
1231
+ var formatTimeBaseType = function formatTimeBaseType(timeBase) {
1232
+ return new TimeBase(timeBase);
1233
+ };
1234
+
1235
+ /**
1236
+ * Create a TimeBase Instance from a string or object representation of a time base
1237
+ *
1238
+ * @param {string|object} timeBase Expressed as "denominator:numerator" or { numerator, denominator }
1239
+ * @returns {TimeBase} A TimeBase instance
1240
+ */
1241
+
1242
+ var createTimeBase = function createTimeBase(timeBase) {
1141
1243
  if (_typeof__default["default"](timeBase) === 'object') {
1142
1244
  return formatTimeBaseType(timeBase);
1143
1245
  }
@@ -1145,47 +1247,86 @@ var formatTimeBase = function formatTimeBase(timeBase) {
1145
1247
  return formatTimeBaseText(timeBase);
1146
1248
  };
1147
1249
 
1148
- var getDropFrames$1 = function getDropFrames(roundedFrameRate) {
1149
- return roundedFrameRate === 60 ? 4 : 2;
1250
+ /**
1251
+ * @private
1252
+ *
1253
+ * Drops 4 frames (0-3) for 59.97 and 2 frames (0-1) for 29.97/NTSC
1254
+ *
1255
+ * @param {TimeBase} timeBase to check
1256
+ * @returns {number} amount of frame drops for specified timeBase
1257
+ */
1258
+ var getAmountOfFrameDrops = function getAmountOfFrameDrops(timeBase) {
1259
+ var timeBaseConstant = timeBase.toRate({
1260
+ constant: true
1261
+ });
1262
+ return timeBaseConstant === '59.94' && 4 || ['NTSC', '29.97'].includes(timeBaseConstant) && 2 || 0;
1150
1263
  };
1151
1264
 
1152
- var getRoundedFrameRate$1 = function getRoundedFrameRate(timeBase) {
1153
- return Math.round(timeBase.denominator / timeBase.numerator);
1265
+ /**
1266
+ * @private
1267
+ *
1268
+ * Check if TimeBase drops frames
1269
+ *
1270
+ * @param {object} timeBase TimeBase Instance to check
1271
+ * @returns {boolean} true if time base drops frames, false otherwise
1272
+ */
1273
+
1274
+ var isDropFrameTimeBase = function isDropFrameTimeBase(timeBase) {
1275
+ return getAmountOfFrameDrops(timeBase) > 0;
1154
1276
  };
1155
1277
 
1156
- function countDroppedFrames(frames, roundedFrameRate) {
1157
- var dropFrames = getDropFrames$1(roundedFrameRate);
1158
- var oneMinuteUndroppedFrames = 60 * roundedFrameRate;
1159
- var oneMinuteDroppedFrames = 60 * roundedFrameRate - dropFrames;
1160
- var tenMinuteFrames = 10 * (oneMinuteUndroppedFrames - dropFrames) + dropFrames;
1161
- var tenMinuteChunks = Math.floor(frames / tenMinuteFrames);
1162
- var minuteRemainder = Math.max(0, frames % tenMinuteFrames - oneMinuteUndroppedFrames);
1163
- var oneMinuteChunks = Math.floor(minuteRemainder / oneMinuteDroppedFrames);
1164
- var frameRemainder = minuteRemainder % oneMinuteDroppedFrames;
1165
- var frameChunks = frameRemainder > 0 ? dropFrames : 0;
1166
- return tenMinuteChunks * 9 * dropFrames + oneMinuteChunks * dropFrames + frameChunks;
1167
- }
1278
+ var _excluded$5 = ["hours"];
1168
1279
 
1169
- var isDropFrameTimeBase = function isDropFrameTimeBase(_ref) {
1170
- var numerator = _ref.numerator,
1171
- denominator = _ref.denominator;
1172
- return numerator === 1001 && (denominator === 60000 || denominator === 30000);
1280
+ var getDroppedFramesFromSamples = function getDroppedFramesFromSamples(_ref) {
1281
+ var samples = _ref.samples,
1282
+ timeBase = _ref.timeBase;
1283
+ var amountOfFrameDrops = getAmountOfFrameDrops(timeBase);
1284
+ if (amountOfFrameDrops === 0) return 0;
1285
+ var roundedFrameRate = timeBase.toRate({
1286
+ rounded: true
1287
+ });
1288
+ var oneMinuteNotDroppedFrames = 60 * roundedFrameRate;
1289
+ var amountOfFramesToDropPerMinute = 60 * roundedFrameRate - amountOfFrameDrops;
1290
+ var tenMinuteFrames = 10 * (oneMinuteNotDroppedFrames - amountOfFrameDrops) + amountOfFrameDrops;
1291
+ var amountOfTenMinuteChunks = Math.floor((samples + 1) / tenMinuteFrames);
1292
+ var minuteRemainder = Math.max(0, (samples + 1) % tenMinuteFrames - oneMinuteNotDroppedFrames);
1293
+ var amountOfOneMinuteReminderChunks = Math.floor(minuteRemainder / amountOfFramesToDropPerMinute);
1294
+ var frameRemainder = minuteRemainder % amountOfFramesToDropPerMinute;
1295
+ var amountOfFrameRemainderChunks = frameRemainder > 0 ? amountOfFrameDrops : 0;
1296
+ return amountOfTenMinuteChunks * 9 * amountOfFrameDrops + amountOfOneMinuteReminderChunks * amountOfFrameDrops + amountOfFrameRemainderChunks;
1173
1297
  };
1298
+ /**
1299
+ * TimeCode class representing the TimeCodeType in VidiCore
1300
+ *
1301
+ * For more info, see the [Time Codes section of VidiCore API Docs](https://apidoc.vidispine.com/latest/time.html#time-codes)
1302
+ */
1303
+
1174
1304
 
1175
1305
  var TimeCode = /*#__PURE__*/function () {
1306
+ /**
1307
+ * Constructor for TimeCode
1308
+ *
1309
+ * @param {object} [timeCodeType={}] Object to create TimeCode of
1310
+ * @param {number} [timeCodeType.samples=0] Amount of samples for the time code
1311
+ * @param {object|string|number} [timeCodeType.timeBase={numerator: 1, denominator: 1}] The time base it should have
1312
+ * @param {object} [options={}] Options for the timeCode
1313
+ * @param {boolean} options.dropFrame If time code should be dropFrame or not (by default checks timeBase)
1314
+ * @param {string} options.frameSeparator Separator to use for frame smpte output (default ":" for non-drop-frame and ";" for dropFrame)
1315
+ */
1176
1316
  function TimeCode() {
1177
- var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
1178
- _ref2$samples = _ref2.samples,
1179
- samples = _ref2$samples === void 0 ? 0 : _ref2$samples,
1180
- timeBase = _ref2.timeBase;
1317
+ var _options$dropFrame, _options$frameSeparat;
1181
1318
 
1182
- var _ref3 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
1183
- dropFrame = _ref3.dropFrame,
1184
- _ref3$field = _ref3.field,
1185
- field = _ref3$field === void 0 ? 2 : _ref3$field;
1319
+ var timeCodeType = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1320
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1186
1321
 
1187
1322
  _classCallCheck__default["default"](this, TimeCode);
1188
1323
 
1324
+ var _ref2 = timeCodeType || {},
1325
+ _ref2$samples = _ref2.samples,
1326
+ samples = _ref2$samples === void 0 ? 0 : _ref2$samples,
1327
+ _ref2$timeBase = _ref2.timeBase,
1328
+ timeBase = _ref2$timeBase === void 0 ? new TimeBase() : _ref2$timeBase;
1329
+
1189
1330
  if (typeof samples === 'number') {
1190
1331
  this.samples = samples;
1191
1332
  } else if (typeof samples === 'string') {
@@ -1200,21 +1341,39 @@ var TimeCode = /*#__PURE__*/function () {
1200
1341
  throw new Error("samples is not number/string/-Inf/+Inf is: ".concat(samples));
1201
1342
  }
1202
1343
 
1203
- this.timeBase = new TimeBase(timeBase);
1204
- this.dropFrame = dropFrame === undefined ? isDropFrameTimeBase(this.timeBase) : dropFrame;
1205
- this.field = field;
1344
+ this.timeBase = createTimeBase(timeBase);
1345
+ this.dropFrame = (_options$dropFrame = options === null || options === void 0 ? void 0 : options.dropFrame) !== null && _options$dropFrame !== void 0 ? _options$dropFrame : isDropFrameTimeBase(this.timeBase);
1346
+ this.frameSeparator = (_options$frameSeparat = options === null || options === void 0 ? void 0 : options.frameSeparator) !== null && _options$frameSeparat !== void 0 ? _options$frameSeparat : this.dropFrame ? ';' : ':';
1206
1347
  }
1348
+ /**
1349
+ * Return this TimeCode added with the supplied timeCodeType
1350
+ * If time bases differ, it will retain the time base of this TimeCode instance
1351
+ * If supplied time code has a more granular time base - it will round down exceeding samples (hasn't reached that sample yet)
1352
+ *
1353
+ * Note: This might make you "lose" frames depending on granularity of time bases, e.g.
1354
+ * "51@50".add("25@25") => "101@50"
1355
+ * while "25@25".add("51@50") => "50@25" (not "101@50")
1356
+ *
1357
+ * @param {TimeCode} timeCodeType A TimeCode instance you want to add with
1358
+ * @returns A new TimeCode instance with the addition applied
1359
+ */
1360
+
1207
1361
 
1208
1362
  _createClass__default["default"](TimeCode, [{
1209
1363
  key: "add",
1210
- value: function add(val) {
1211
- var _val$timeBase = val.timeBase,
1212
- numerator = _val$timeBase.numerator,
1213
- denominator = _val$timeBase.denominator;
1214
- var conformedTimeCode = val;
1364
+ value: function add(timeCodeType) {
1365
+ if (!(timeCodeType !== null && timeCodeType !== void 0 && timeCodeType.timeBase) || (timeCodeType === null || timeCodeType === void 0 ? void 0 : timeCodeType.samples) === undefined) {
1366
+ throw Error('Invalid timeCodeType, cannot be added');
1367
+ }
1368
+
1369
+ var _timeCodeType$timeBas = timeCodeType.timeBase;
1370
+ _timeCodeType$timeBas = _timeCodeType$timeBas === void 0 ? {} : _timeCodeType$timeBas;
1371
+ var numerator = _timeCodeType$timeBas.numerator,
1372
+ denominator = _timeCodeType$timeBas.denominator;
1373
+ var conformedTimeCode = timeCodeType;
1215
1374
 
1216
1375
  if (numerator !== this.timeBase.numerator || denominator !== this.timeBase.denominator) {
1217
- conformedTimeCode = val.conformTimeBase(this.timeBase);
1376
+ conformedTimeCode = timeCodeType.conformTimeBase(this.timeBase);
1218
1377
  }
1219
1378
 
1220
1379
  var _conformedTimeCode = conformedTimeCode,
@@ -1224,16 +1383,34 @@ var TimeCode = /*#__PURE__*/function () {
1224
1383
  timeBase: this.timeBase
1225
1384
  });
1226
1385
  }
1386
+ /**
1387
+ * Return this TimeCode subtracted with the supplied timeCodeType
1388
+ * If time bases differ, it will retain the time base of the instance time code
1389
+ * If supplied time code has a more granular time base - it will round down exceeding samples (hasn't reached that sample yet)
1390
+ *
1391
+ * Note: This might make you "lose" frames depending on granularity of time bases, e.g.
1392
+ * "101@50".subtract("25@25") => "51@50"
1393
+ * while "50@25".subtract("51@50") => "25@25" (not "49@50")
1394
+ *
1395
+ * @param {TimeCode} timeCodeType A TimeCode instance you want to subtract with
1396
+ * @returns A new TimeCode instance with the subtraction applied
1397
+ */
1398
+
1227
1399
  }, {
1228
1400
  key: "subtract",
1229
- value: function subtract(val) {
1230
- var _val$timeBase2 = val.timeBase,
1231
- numerator = _val$timeBase2.numerator,
1232
- denominator = _val$timeBase2.denominator;
1233
- var conformedTimeCode = val;
1401
+ value: function subtract(timeCodeType) {
1402
+ if (!(timeCodeType !== null && timeCodeType !== void 0 && timeCodeType.timeBase) || (timeCodeType === null || timeCodeType === void 0 ? void 0 : timeCodeType.samples) === undefined) {
1403
+ throw Error('Invalid timeCodeType, cannot be subtracted');
1404
+ }
1405
+
1406
+ var _timeCodeType$timeBas2 = timeCodeType.timeBase;
1407
+ _timeCodeType$timeBas2 = _timeCodeType$timeBas2 === void 0 ? {} : _timeCodeType$timeBas2;
1408
+ var numerator = _timeCodeType$timeBas2.numerator,
1409
+ denominator = _timeCodeType$timeBas2.denominator;
1410
+ var conformedTimeCode = timeCodeType;
1234
1411
 
1235
1412
  if (numerator !== this.timeBase.numerator || denominator !== this.timeBase.denominator) {
1236
- conformedTimeCode = val.conformTimeBase(this.timeBase);
1413
+ conformedTimeCode = timeCodeType.conformTimeBase(this.timeBase);
1237
1414
  }
1238
1415
 
1239
1416
  var _conformedTimeCode2 = conformedTimeCode,
@@ -1243,361 +1420,765 @@ var TimeCode = /*#__PURE__*/function () {
1243
1420
  timeBase: this.timeBase
1244
1421
  });
1245
1422
  }
1423
+ /**
1424
+ * Creates a new TimeCode instance with specified timeBase and samples adjusted to that.
1425
+ *
1426
+ * If it conforms to a less granular time base - it will floor samples (hasn't reached that sample yet)
1427
+ * - e.g. "51@50".conformTo("PAL") => "25@PAL" (not "26@PAL")
1428
+ *
1429
+ * @param {string|object} conformTo The TimeBase it should conform the TimeCode to
1430
+ * @returns A new TimeCode instance with the conformTo timeBase applied
1431
+ */
1432
+
1246
1433
  }, {
1247
1434
  key: "conformTimeBase",
1248
1435
  value: function conformTimeBase(conformTo) {
1249
- var timeBase = conformTo;
1436
+ var conformToTimeBase = conformTo;
1250
1437
 
1251
- if (conformTo instanceof TimeCode === false) {
1252
- timeBase = new TimeBase(conformTo);
1438
+ if (!(conformTo instanceof TimeBase)) {
1439
+ conformToTimeBase = createTimeBase(conformTo);
1253
1440
  }
1254
1441
 
1255
- var samples = Math.round(this.samples / (this.timeBase.toRate(false, false) / timeBase.toRate(false, false)));
1442
+ var samples = Math.floor(this.samples / (this.timeBase.toRate({
1443
+ fixed: false
1444
+ }) / conformToTimeBase.toRate({
1445
+ fixed: false
1446
+ })));
1256
1447
  var timeCode = {
1257
1448
  samples: samples,
1258
- timeBase: timeBase
1449
+ timeBase: conformToTimeBase
1259
1450
  };
1260
1451
  return new TimeCode(timeCode);
1261
1452
  }
1262
- }, {
1263
- key: "toJSON",
1264
- value: function toJSON() {
1265
- return {
1266
- samples: this.samples,
1267
- timeBase: this.timeBase
1268
- };
1269
- }
1453
+ /**
1454
+ * Get TimeCode as a text representation
1455
+ *
1456
+ * Default format: samples@denominator(:numerator if > 1)
1457
+ * `constant` has precedence over `fraction` if both are true
1458
+ *
1459
+ * @param {object} [options={}] TimeBase toText options
1460
+ * @param {boolean} [options.includeTimeBaseForSeconds=false] include time base even if seconds
1461
+ * @param {boolean} [options.constant=false] show as constant (e.g. @PAL)
1462
+ * @param {boolean} [options.fraction=false] show as fraction (@25:1)
1463
+ * @returns Text representation of TimeCode
1464
+ */
1465
+
1270
1466
  }, {
1271
1467
  key: "toText",
1272
1468
  value: function toText() {
1273
- var timeCodeText = String(this.samples);
1274
- var timeBaseText = this.timeBase.toText();
1469
+ var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1470
+ var timeCodeText = "".concat(this.samples);
1471
+ var timeBaseText = this.timeBase.toText(options);
1275
1472
 
1276
- if (timeBaseText !== '1') {
1473
+ if (options !== null && options !== void 0 && options.includeTimeBaseForSeconds || !['1', '1:1'].includes(timeBaseText)) {
1277
1474
  timeCodeText = [this.samples, timeBaseText].join('@');
1278
1475
  }
1279
1476
 
1280
1477
  return timeCodeText;
1281
1478
  }
1479
+ /**
1480
+ * Get TimeCode in a units object representation
1481
+ *
1482
+ * @returns {object} in the format { hours, minutes, seconds, frames }
1483
+ */
1484
+
1282
1485
  }, {
1283
- key: "toSeconds",
1284
- value: function toSeconds() {
1285
- var _this$timeBase = this.timeBase,
1286
- numerator = _this$timeBase.numerator,
1287
- denominator = _this$timeBase.denominator;
1288
- return this.samples * (numerator / denominator);
1486
+ key: "toUnits",
1487
+ value: function toUnits() {
1488
+ var totalSamples = this.samples + (this.dropFrame ? getDroppedFramesFromSamples(this) : 0);
1489
+ var roundedFrameRate = this.timeBase.toRate({
1490
+ rounded: true
1491
+ }); // Calculated without drop-frame but with 2 decimal places
1492
+
1493
+ if (['23.976', '23.98'].includes(this.timeBase.toConstant())) {
1494
+ roundedFrameRate = this.timeBase.toRate({
1495
+ fixed: true
1496
+ });
1497
+ }
1498
+
1499
+ var hours = Math.floor(totalSamples / (3600 * roundedFrameRate));
1500
+ var minutes = Math.floor(totalSamples / (60 * roundedFrameRate)) % 60;
1501
+ var seconds = Math.floor(totalSamples / roundedFrameRate) % 60;
1502
+ var frames = Math.floor(totalSamples % roundedFrameRate);
1503
+ return {
1504
+ hours: hours,
1505
+ minutes: minutes,
1506
+ seconds: seconds,
1507
+ frames: frames
1508
+ };
1289
1509
  }
1510
+ /**
1511
+ * Get TimeCode in a time object representation
1512
+ * "milliseconds" is rounded down, if you want another representation use "partialSeconds"
1513
+ *
1514
+ * @returns {object} in the format { hours, minutes, seconds, milliseconds, partialSeconds }
1515
+ */
1516
+
1290
1517
  }, {
1291
1518
  key: "toTime",
1292
1519
  value: function toTime() {
1293
- var roundedFrameRate = getRoundedFrameRate$1(this.timeBase);
1294
- var totalSamples = this.samples + (this.dropFrame ? countDroppedFrames(this.samples + 1, roundedFrameRate) : 0);
1295
- var hours = Math.floor(totalSamples / (3600 * roundedFrameRate));
1296
- var minutes = Math.floor(totalSamples / (60 * roundedFrameRate)) % 60;
1297
- var seconds = Math.floor(totalSamples / roundedFrameRate) % 60;
1298
- var frames = totalSamples % roundedFrameRate;
1299
- var partialSeconds = frames / roundedFrameRate;
1520
+ var totalSamples = this.samples + getDroppedFramesFromSamples(this);
1521
+
1522
+ var _this$toUnits = this.toUnits(),
1523
+ hours = _this$toUnits.hours,
1524
+ minutes = _this$toUnits.minutes,
1525
+ seconds = _this$toUnits.seconds;
1526
+
1527
+ var roundedFrameRate = this.timeBase.toRate({
1528
+ rounded: true
1529
+ });
1530
+ var framesPrecise = totalSamples % roundedFrameRate;
1531
+ var milliseconds = Math.floor(1000 * framesPrecise / roundedFrameRate);
1532
+ var partialSeconds = framesPrecise / roundedFrameRate;
1300
1533
  return {
1301
1534
  hours: hours,
1302
1535
  minutes: minutes,
1303
1536
  seconds: seconds,
1304
- frames: frames,
1537
+ milliseconds: milliseconds,
1305
1538
  partialSeconds: partialSeconds
1306
1539
  };
1307
1540
  }
1541
+ /**
1542
+ * Get TimeCode in a seconds representation
1543
+ *
1544
+ * @returns {number} the seconds
1545
+ */
1546
+
1547
+ }, {
1548
+ key: "toSeconds",
1549
+ value: function toSeconds() {
1550
+ var _this$timeBase = this.timeBase,
1551
+ numerator = _this$timeBase.numerator,
1552
+ denominator = _this$timeBase.denominator;
1553
+ return Math.round(1000 * +(this.samples * numerator / denominator)) / 1000;
1554
+ }
1555
+ /**
1556
+ * Get TimeCode in a duration representation
1557
+ * The time unit char keys for the format string are:
1558
+ * - "h" for hour
1559
+ * - "m" for minute
1560
+ * - "s" for seconds
1561
+ * - "S" for milliseconds
1562
+ * Any other char will be kept in the duration output string.
1563
+ *
1564
+ * Add consecutive chars for zero padding.
1565
+ *
1566
+ * By default it:
1567
+ * - uses colon delimiter (e.g. for format "hhmmss")
1568
+ * - shows "m:ss" or "h:mm:ss" if format is undefined
1569
+ *
1570
+ * @param {object} [options={}]
1571
+ * @param {string} options.format specify format of duration string, e.g. hh:mm:ss.S for 01:23:04.5
1572
+ * @returns {string} Duration representation of the TimeCode
1573
+ */
1574
+
1308
1575
  }, {
1309
1576
  key: "toDuration",
1310
1577
  value: function toDuration() {
1311
- var _ref4 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
1312
- format = _ref4.format;
1578
+ var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1579
+ var format = options.format;
1313
1580
 
1314
1581
  var _this$toTime = this.toTime(),
1315
1582
  hours = _this$toTime.hours,
1316
- minutes = _this$toTime.minutes,
1317
- seconds = _this$toTime.seconds;
1583
+ rest = _objectWithoutProperties__default["default"](_this$toTime, _excluded$5);
1318
1584
 
1319
- if (typeof format === 'string') {
1320
- if (format.toLowerCase() === 'hhmmss') {
1321
- return [hours.toFixed().padStart(2, '0'), minutes.toFixed().padStart(2, '0'), seconds.toFixed().padStart(2, '0')].join(':');
1322
- }
1585
+ var minutes = rest.minutes,
1586
+ seconds = rest.seconds,
1587
+ milliseconds = rest.milliseconds;
1588
+
1589
+ if (!!format && typeof format !== 'string') {
1590
+ throw Error('format has to be a string');
1323
1591
  }
1324
1592
 
1325
- if (hours) {
1326
- return [hours.toFixed(), minutes.toFixed().padStart(2, '0'), seconds.toFixed().padStart(2, '0')].join(':');
1593
+ var isBefore = function isBefore(unit, units) {
1594
+ return !format.includes(unit) || !units.some(function (u) {
1595
+ return format.includes(u) && format.lastIndexOf(unit) > format.indexOf(u);
1596
+ });
1597
+ };
1598
+
1599
+ if (!!format && !(isBefore('h', ['m', 's', 'S']) && isBefore('m', ['s', 'S']) && isBefore('s', ['S']))) {
1600
+ throw Error('format order is unsupported (has to be h, m, s then S)');
1327
1601
  }
1328
1602
 
1329
- if (minutes >= 10) {
1330
- return [minutes.toFixed().padStart(2, '0'), seconds.toFixed().padStart(2, '0')].join(':');
1603
+ if (!format) {
1604
+ return "".concat(hours > 0 ? "".concat(hours, ":").concat("".concat(minutes).padStart(2, '0')) : minutes, ":").concat("".concat(seconds).padStart(2, '0'));
1331
1605
  }
1332
1606
 
1333
- return [minutes.toFixed(), seconds.toFixed().padStart(2, '0')].join(':');
1607
+ var countConsecutiveChars = function countConsecutiveChars(i, arr) {
1608
+ var j = i;
1609
+
1610
+ while (arr[j] === arr[j + 1]) {
1611
+ j += 1;
1612
+ }
1613
+
1614
+ return j - i + 1;
1615
+ };
1616
+
1617
+ var timeUnitKeys = ['h', 'm', 's', 'S'];
1618
+ var output = [];
1619
+
1620
+ _toConsumableArray__default["default"](format).forEach(function (c, i, arr) {
1621
+ switch (c) {
1622
+ case 'h':
1623
+ {
1624
+ if (arr[i - 1] === 'h') {
1625
+ break;
1626
+ }
1627
+
1628
+ var amount = countConsecutiveChars(i, arr);
1629
+ output.push("".concat(hours).padStart(amount, '0'));
1630
+
1631
+ if (timeUnitKeys.includes(arr[i + amount])) {
1632
+ output.push(':');
1633
+ }
1634
+
1635
+ break;
1636
+ }
1637
+
1638
+ case 'm':
1639
+ {
1640
+ if (arr[i - 1] === 'm') {
1641
+ break;
1642
+ }
1643
+
1644
+ var _amount = countConsecutiveChars(i, arr);
1645
+
1646
+ if (!format.includes('h')) {
1647
+ minutes *= hours * 60;
1648
+ }
1649
+
1650
+ output.push("".concat(minutes).padStart(_amount, '0'));
1651
+
1652
+ if (timeUnitKeys.includes(arr[i + _amount])) {
1653
+ output.push(':');
1654
+ }
1655
+
1656
+ break;
1657
+ }
1658
+
1659
+ case 's':
1660
+ {
1661
+ if (arr[i - 1] === 's') {
1662
+ break;
1663
+ }
1664
+
1665
+ var _amount2 = countConsecutiveChars(i, arr);
1666
+
1667
+ if (!format.includes('m')) {
1668
+ seconds *= minutes * 60;
1669
+ }
1670
+
1671
+ output.push("".concat(seconds).padStart(_amount2, '0'));
1672
+
1673
+ if (timeUnitKeys.includes(arr[i + _amount2])) {
1674
+ output.push('.');
1675
+ }
1676
+
1677
+ break;
1678
+ }
1679
+
1680
+ case 'S':
1681
+ {
1682
+ if (arr[i - 1] === 'S') {
1683
+ break;
1684
+ }
1685
+
1686
+ var _amount3 = countConsecutiveChars(i, arr);
1687
+
1688
+ if (!format.includes('s')) {
1689
+ milliseconds *= seconds * 1000;
1690
+ }
1691
+
1692
+ output.push("".concat(Math.round(milliseconds / Math.pow(10, 3 - _amount3))).padStart(_amount3, '0'));
1693
+ break;
1694
+ }
1695
+
1696
+ default:
1697
+ output.push(c);
1698
+ }
1699
+ });
1700
+
1701
+ return output.join('');
1334
1702
  }
1703
+ /**
1704
+ * Get TimeCode in a smpte representation
1705
+ *
1706
+ * @returns {string} Smpte representation of the TimeCode
1707
+ */
1708
+
1335
1709
  }, {
1336
1710
  key: "toSmpte",
1337
1711
  value: function toSmpte() {
1338
- var _this = this;
1339
-
1340
1712
  if (this.samples === -Infinity) return '00:00:00:00';
1341
1713
 
1342
- var _this$toTime2 = this.toTime(),
1343
- hours = _this$toTime2.hours,
1344
- minutes = _this$toTime2.minutes,
1345
- seconds = _this$toTime2.seconds,
1346
- frames = _this$toTime2.frames;
1714
+ var _this$toUnits2 = this.toUnits(),
1715
+ hours = _this$toUnits2.hours,
1716
+ minutes = _this$toUnits2.minutes,
1717
+ seconds = _this$toUnits2.seconds,
1718
+ frames = _this$toUnits2.frames;
1347
1719
 
1348
1720
  var hhmmss = [hours.toFixed().padStart(2, '0'), minutes.toFixed().padStart(2, '0'), seconds.toFixed().padStart(2, '0')].join(':');
1721
+ return [hhmmss, "".concat(frames).padStart(2, '0')].join(this.frameSeparator);
1722
+ }
1723
+ /**
1724
+ * Get TimeCode as a VidiCore TimeCodeType object
1725
+ *
1726
+ * @returns {object} TimeCode as `{ samples, timeBase }`
1727
+ */
1349
1728
 
1350
- var _Object$entries$find = Object.entries(FRAME_SEPARATORS).find(function (thisSeparator) {
1351
- var _thisSeparator = _slicedToArray__default["default"](thisSeparator, 2),
1352
- _thisSeparator$ = _thisSeparator[1],
1353
- dropFrame = _thisSeparator$.dropFrame,
1354
- field = _thisSeparator$.field;
1355
-
1356
- return dropFrame === _this.dropFrame && field === _this.field;
1357
- }),
1358
- _Object$entries$find2 = _slicedToArray__default["default"](_Object$entries$find, 1),
1359
- _Object$entries$find3 = _Object$entries$find2[0],
1360
- frameSeparator = _Object$entries$find3 === void 0 ? ':' : _Object$entries$find3;
1361
-
1362
- return [hhmmss, frames.toFixed().padStart(2, '0')].join(frameSeparator);
1729
+ }, {
1730
+ key: "toObject",
1731
+ value: function toObject() {
1732
+ return {
1733
+ samples: this.samples,
1734
+ timeBase: this.timeBase.toObject()
1735
+ };
1363
1736
  }
1737
+ /**
1738
+ * @deprecated Use {@link TimeCode#toObject|toObject} instead
1739
+ *
1740
+ * @returns {object} TimeCode as `{ samples, timeBase }`
1741
+ */
1742
+
1364
1743
  }, {
1365
- key: "toFraction",
1366
- value: function toFraction() {
1367
- return "".concat(this.samples, "@").concat(this.timeBase.denominator, ":").concat(this.timeBase.numerator);
1744
+ key: "toJson",
1745
+ value: function toJson() {
1746
+ // eslint-disable-next-line no-console
1747
+ console.warn('Deprecated - use toObject instead');
1748
+ return this.toObject();
1368
1749
  }
1369
1750
  }]);
1370
1751
 
1371
1752
  return TimeCode;
1372
1753
  }();
1373
1754
 
1374
- var formatTimeCodeType = function formatTimeCodeType(timeCode, options) {
1375
- return new TimeCode(timeCode, options);
1376
- };
1377
-
1378
- var formatTimeCodeText = function formatTimeCodeText(timeCodeText, options) {
1379
- if (timeCodeText === undefined) {
1380
- var _timeCode = {
1381
- samples: 0
1382
- };
1383
- return formatTimeCodeType(_timeCode, options);
1384
- }
1755
+ /* eslint-disable no-self-assign */
1385
1756
 
1386
- if (typeof timeCodeText === 'number') {
1387
- var _timeCode2 = {
1388
- samples: timeCodeText
1389
- };
1390
- return formatTimeCodeType(_timeCode2, options);
1757
+ /**
1758
+ * @private
1759
+ *
1760
+ * Using Euclid's algorithm
1761
+ *
1762
+ * @param {number} num1 a number
1763
+ * @param {number} num2 another number
1764
+ * @returns {number} the greatest common divisor as a number
1765
+ */
1766
+ var getGreatestCommonDivisor = function getGreatestCommonDivisor(num1, num2) {
1767
+ var a = Math.abs(num1);
1768
+ var b = Math.abs(num2);
1769
+
1770
+ while (a && b && a !== b) {
1771
+ if (a > b) {
1772
+ var _ref = [a - b, b];
1773
+ a = _ref[0];
1774
+ b = _ref[1];
1775
+ } else {
1776
+ var _ref2 = [a, b - a];
1777
+ a = _ref2[0];
1778
+ b = _ref2[1];
1779
+ }
1391
1780
  }
1392
1781
 
1393
- if (timeCodeText.includes('@')) {
1394
- var _timeCodeText$split = timeCodeText.split('@'),
1395
- _timeCodeText$split2 = _slicedToArray__default["default"](_timeCodeText$split, 2),
1396
- samplesString = _timeCodeText$split2[0],
1397
- timeBaseText = _timeCodeText$split2[1];
1398
-
1399
- var _samples = Number(samplesString);
1400
-
1401
- var timeBase = formatTimeBaseText(timeBaseText);
1402
- var _timeCode3 = {
1403
- samples: _samples,
1404
- timeBase: timeBase
1405
- };
1406
- return formatTimeCodeType(_timeCode3, options);
1407
- }
1782
+ return a || b;
1783
+ };
1408
1784
 
1409
- if (timeCodeText === '-INF') {
1410
- var _samples2 = -Infinity;
1785
+ var _excluded$4 = ["timeBase", "useGCD"];
1786
+ /**
1787
+ * Format seconds to TimeCode object
1788
+ * Input time base is always 1:1 since it expects seconds as input
1789
+ *
1790
+ * Note: Max 15 digits accuracy (double precision float64), e.g.
1791
+ * - 10^6 seconds can have 10^9 decimals (nanosecond) precision
1792
+ * - 10^9 seconds can have 10^6 decimals (microsecond) precision
1793
+ * - 10^12 seconds can have 10^3 decimals (millisecond) precision
1794
+ *
1795
+ * @param {string|number} seconds With or without decimals ("." and "," are both interpreted as decimal)
1796
+ * @param {object} [options={}] Options for how to format the seconds to a TimeCode
1797
+ * @param {object|string} options.timeBase What TimeBase the resulting TimeCode should have (if unset and useGCD=false, denominator will be 10^<amount-of-decimals>)
1798
+ * @param {boolean} [options.useGCD=false] Samples and denominator are divided with GCD (ignored if timeBase is set) (e.g. 1.04 => 104@100 => 26@25)
1799
+ * @returns {TimeCode} A TimeCode instance
1800
+ */
1411
1801
 
1412
- var _timeCode4 = {
1413
- samples: _samples2
1414
- };
1415
- return formatTimeCodeType(_timeCode4, options);
1416
- }
1802
+ var formatTimeCodeSeconds = function formatTimeCodeSeconds(seconds) {
1803
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1417
1804
 
1418
- if (timeCodeText === '+INF') {
1419
- var _samples3 = Infinity;
1420
- var _timeCode5 = {
1421
- samples: _samples3
1422
- };
1423
- return formatTimeCodeType(_timeCode5, options);
1424
- }
1805
+ var timeBase = options.timeBase,
1806
+ _options$useGCD = options.useGCD,
1807
+ useGCD = _options$useGCD === void 0 ? false : _options$useGCD,
1808
+ timeCodeOptions = _objectWithoutProperties__default["default"](options, _excluded$4);
1425
1809
 
1426
- var samples = Number(timeCodeText);
1810
+ var secondsWithDot = "".concat(seconds).replace(/,/g, '.');
1811
+ var amountOfDigits = secondsWithDot.replace('.', '').length;
1427
1812
 
1428
- if (Number.isNaN(samples)) {
1429
- throw new Error("timeBaseText must be a number or sample@timeBase - is ".concat(timeCodeText));
1813
+ if (amountOfDigits > 16) {
1814
+ throw new Error("Amount of second digits cannot be more than 16, is ".concat(amountOfDigits));
1430
1815
  }
1431
1816
 
1432
- var timeCode = {
1433
- samples: samples
1434
- };
1435
- return formatTimeCodeType(timeCode, options);
1436
- };
1437
-
1438
- var formatSeconds = function formatSeconds(seconds, timeBase, options) {
1439
- if (Number.isNaN(Number(seconds))) {
1817
+ if (Number.isNaN(+secondsWithDot)) {
1440
1818
  throw new Error("seconds must be digits, is ".concat(seconds));
1441
1819
  }
1442
1820
 
1443
- var _ref = timeBase || {},
1444
- _ref$denominator = _ref.denominator,
1445
- denominator = _ref$denominator === void 0 ? 1 : _ref$denominator,
1446
- _ref$numerator = _ref.numerator,
1447
- numerator = _ref$numerator === void 0 ? 1 : _ref$numerator;
1821
+ var denominator = 1;
1822
+ var samples;
1448
1823
 
1449
- var samples = seconds * (denominator / numerator);
1450
- var timeCode = {
1451
- samples: samples,
1452
- timeBase: timeBase || {}
1453
- };
1454
- return new TimeCode(timeCode, options);
1455
- };
1456
-
1457
- var formatSecondsPrecise = function formatSecondsPrecise(seconds, timeBase, options) {
1458
- if (Number.isNaN(Number(seconds))) {
1459
- throw new Error("seconds must be digits, is ".concat(seconds));
1460
- }
1461
-
1462
- var _ref = timeBase || {},
1463
- _ref$numerator = _ref.numerator,
1464
- numerator = _ref$numerator === void 0 ? 1 : _ref$numerator;
1824
+ if (Number.isInteger(+secondsWithDot)) {
1825
+ samples = +secondsWithDot * denominator;
1826
+ } else {
1827
+ var _ms$length;
1465
1828
 
1466
- var _ref2 = timeBase || {},
1467
- _ref2$denominator = _ref2.denominator,
1468
- denominator = _ref2$denominator === void 0 ? 1 : _ref2$denominator;
1829
+ var _secondsWithDot$split = secondsWithDot.split('.'),
1830
+ _secondsWithDot$split2 = _slicedToArray__default["default"](_secondsWithDot$split, 2),
1831
+ ms = _secondsWithDot$split2[1];
1469
1832
 
1470
- if (!Number.isInteger(seconds)) {
1471
- var decimalPlaces = String(seconds).split('.')[1].length;
1833
+ var decimalPlaces = Math.min((_ms$length = ms === null || ms === void 0 ? void 0 : ms.length) !== null && _ms$length !== void 0 ? _ms$length : 0, 16);
1472
1834
  denominator *= Math.pow(10, decimalPlaces);
1835
+ samples = Math.round(secondsWithDot * denominator);
1473
1836
  }
1474
1837
 
1475
- var samples = (seconds * (denominator / numerator)).toFixed();
1476
- var timeCode = {
1838
+ if (!timeBase && useGCD) {
1839
+ var gcd = getGreatestCommonDivisor(denominator, samples);
1840
+ samples /= gcd;
1841
+ denominator /= gcd;
1842
+ }
1843
+
1844
+ var timeCode = new TimeCode({
1477
1845
  samples: samples,
1478
1846
  timeBase: {
1479
1847
  denominator: denominator,
1480
- numerator: numerator
1848
+ numerator: 1
1481
1849
  }
1482
- };
1483
- return new TimeCode(timeCode, options);
1850
+ }, timeCodeOptions);
1851
+ return timeBase ? timeCode.conformTimeBase(createTimeBase(timeBase === true ? 1 : timeBase)) : timeCode;
1484
1852
  };
1485
1853
 
1854
+ var _excluded$3 = ["exceedingMode", "timeBase"];
1855
+
1486
1856
  function ownKeys$2(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
1487
1857
 
1488
1858
  function _objectSpread$2(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys$2(Object(source), !0).forEach(function (key) { _defineProperty__default["default"](target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys$2(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
1489
-
1490
- var getDropFrames = function getDropFrames(roundedFrameRate) {
1491
- return roundedFrameRate === 60 ? 4 : 2;
1859
+ var MAP_SEPARATOR_TO_OPTIONS = {
1860
+ ':': {
1861
+ dropFrame: false,
1862
+ frameSeparator: ':'
1863
+ },
1864
+ '.': {
1865
+ dropFrame: false,
1866
+ frameSeparator: '.'
1867
+ },
1868
+ ';': {
1869
+ dropFrame: true,
1870
+ frameSeparator: ';'
1871
+ },
1872
+ ',': {
1873
+ dropFrame: true,
1874
+ frameSeparator: ','
1875
+ }
1492
1876
  };
1877
+ var getDroppedFramesFromSmpte = function getDroppedFramesFromSmpte(_ref, samples, timeBase) {
1878
+ var _ref2 = _slicedToArray__default["default"](_ref, 4),
1879
+ hh = _ref2[0],
1880
+ mm = _ref2[1],
1881
+ ss = _ref2[2],
1882
+ ff = _ref2[3];
1883
+
1884
+ var roundedFrameRate = timeBase.toRate({
1885
+ rounded: true
1886
+ });
1887
+ var dropFrames = getAmountOfFrameDrops(timeBase);
1888
+
1889
+ if (samples === 0 || dropFrames === 0) {
1890
+ return 0;
1891
+ }
1493
1892
 
1494
- var getRoundedFrameRate = function getRoundedFrameRate(timeBase) {
1495
- return Math.round(timeBase.denominator / timeBase.numerator);
1893
+ var shouldDropMinute = mm % 10 !== 0;
1894
+ var shouldDropSecond = shouldDropMinute && ss === 0;
1895
+ var hourFrames = hh * (3600 * roundedFrameRate - 54 * dropFrames);
1896
+ var minuteFrames = mm * 60 * roundedFrameRate - (mm - Math.ceil(mm / 10)) * dropFrames;
1897
+ var secondFrames = ss * roundedFrameRate - (shouldDropMinute && ss > 1 ? dropFrames : 0);
1898
+
1899
+ if (shouldDropSecond && ff < dropFrames) {
1900
+ throw new Error("Frame does not exist for ".concat(timeBase.toRate({
1901
+ constant: true
1902
+ }), " drop-frame"));
1903
+ }
1904
+
1905
+ var frameFrames = shouldDropSecond ? ff - dropFrames : ff;
1906
+ var samplesWithoutDroppedFrames = hourFrames + minuteFrames + secondFrames + frameFrames;
1907
+ return samples - samplesWithoutDroppedFrames;
1496
1908
  };
1497
1909
 
1498
- var splitSmpte = function splitSmpte(smpteText) {
1499
- var hasDropFrameSeparator = smpteText.match(/[^0-9:\-_]/);
1500
- var hhmmssff;
1501
- var frameOptions = {};
1910
+ var splitSmpte = function splitSmpte(smpte) {
1911
+ var _ref3 = (smpte === null || smpte === void 0 ? void 0 : smpte.match(/[^0-9:\-_]/)) || [],
1912
+ _ref4 = _slicedToArray__default["default"](_ref3, 1),
1913
+ nonColonFrameSeparator = _ref4[0];
1502
1914
 
1503
- if (hasDropFrameSeparator) {
1504
- var _hasDropFrameSeparato = _slicedToArray__default["default"](hasDropFrameSeparator, 1),
1505
- frameSeparator = _hasDropFrameSeparato[0];
1915
+ var smpteValues = [];
1916
+ var options = {
1917
+ frameSeparator: ':',
1918
+ dropFrame: false
1919
+ };
1506
1920
 
1507
- var _smpteText$split = smpteText.split(frameSeparator),
1508
- _smpteText$split2 = _slicedToArray__default["default"](_smpteText$split, 2),
1509
- hhmmss = _smpteText$split2[0],
1510
- splitFrames = _smpteText$split2[1];
1921
+ if (nonColonFrameSeparator) {
1922
+ var _smpte$split = smpte.split(nonColonFrameSeparator),
1923
+ _smpte$split2 = _slicedToArray__default["default"](_smpte$split, 2),
1924
+ hhmmss = _smpte$split2[0],
1925
+ ff = _smpte$split2[1];
1511
1926
 
1512
- hhmmssff = [].concat(_toConsumableArray__default["default"](hhmmss.split(':')), [splitFrames]);
1513
- frameOptions = FRAME_SEPARATORS[frameSeparator] || {};
1927
+ smpteValues = [].concat(_toConsumableArray__default["default"](hhmmss.split(':')), [ff]);
1928
+ options = MAP_SEPARATOR_TO_OPTIONS[nonColonFrameSeparator] || {};
1514
1929
  } else {
1515
- hhmmssff = smpteText.split(':');
1930
+ smpteValues = smpte.split(':');
1516
1931
  }
1517
1932
 
1518
- hhmmssff = hhmmssff.map(Number);
1933
+ smpteValues = smpteValues.map(Number);
1519
1934
 
1520
- if (hhmmssff.length > 4 || hhmmssff.some(function (n) {
1935
+ if (smpteValues.length !== 4) {
1936
+ throw new Error('Invalid format, must be "##:##:##:##');
1937
+ }
1938
+
1939
+ if (smpteValues.some(function (n) {
1521
1940
  return Number.isNaN(n);
1522
1941
  })) {
1523
- throw new Error('Invalid SMPTE timecode');
1942
+ throw new Error('Invalid format, values must be numbers');
1524
1943
  }
1525
1944
 
1526
- return [hhmmssff, frameOptions];
1945
+ return [smpteValues, options];
1527
1946
  };
1528
1947
 
1529
- var countSamples = function countSamples(hh, mm, ss, ff, _ref) {
1530
- var dropFrame = _ref.dropFrame,
1531
- roundedFrameRate = _ref.roundedFrameRate;
1948
+ var getSamplesFromSmpte = function getSamplesFromSmpte(smpteValues, timeBase, dropFrame) {
1949
+ var _smpteValues = _slicedToArray__default["default"](smpteValues, 4),
1950
+ hh = _smpteValues[0],
1951
+ mm = _smpteValues[1],
1952
+ ss = _smpteValues[2],
1953
+ ff = _smpteValues[3];
1954
+
1955
+ var roundedFrameRate = timeBase.toRate({
1956
+ rounded: true
1957
+ });
1958
+ var samples = hh * 3600 * roundedFrameRate + mm * 60 * roundedFrameRate + ss * roundedFrameRate + ff;
1959
+ return samples - (dropFrame ? getDroppedFramesFromSmpte(smpteValues, samples, timeBase) : 0);
1960
+ }; // Better naming than "useValueExcess" and "useValueTruncate" must exist
1961
+
1962
+
1963
+ var EXCEEDING_OPTIONS = ['error', 'add', 'ignore'];
1964
+ /**
1965
+ * Format smpte text to a TimeCode Instance
1966
+ *
1967
+ * exceedingMode:
1968
+ * - "overflow" exceeding values will be kept (e.g. PAL and 00:00:00:25 => 00:00:01:00)
1969
+ * - "truncate" exceeding values will be truncated (e.g. PAL and 00:00:00:25 => 00:00:00:24)
1970
+ * - "error" exceeding values will throw error (e.g. PAL and 00:00:00:25 => Error)
1971
+ *
1972
+ * @param {string} smpte String representation of smpte
1973
+ * @param {object} [options={}] What options to use for creating the time code from smpte (all not specified below are passed to the TimeCode constructor)
1974
+ * @param {object|string|number} options.timeBase TimeBase of smpte (and consequently TimeBase of output TimeCode)
1975
+ * @param {string} [options.exceedingMode=error] How to handle exceeding values (`overflow|truncate|error`)
1976
+ * @param {boolean} options.dropFrame If it should parse and create time code using dropFrame
1977
+ * @param {string} options.frameSeparator What frame separator the TimeCode should store (defaults to what the smpte has)
1978
+ * @returns {TimeCode} A TimeCode instance
1979
+ */
1980
+
1981
+ var formatTimeCodeSmpte = function formatTimeCodeSmpte(smpte) {
1982
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1532
1983
 
1533
- if (!dropFrame) {
1534
- return hh * 3600 * roundedFrameRate + mm * 60 * roundedFrameRate + ss * roundedFrameRate + ff;
1984
+ var _options$exceedingMod = options.exceedingMode,
1985
+ exceedingMode = _options$exceedingMod === void 0 ? 'error' : _options$exceedingMod,
1986
+ timeBase = options.timeBase,
1987
+ timeCodeOptions = _objectWithoutProperties__default["default"](options, _excluded$3);
1988
+
1989
+ if ([null, undefined].includes(smpte)) {
1990
+ throw new Error("smpte cannot be undefined or null");
1535
1991
  }
1536
1992
 
1537
- if (![30, 60].includes(roundedFrameRate)) {
1538
- throw new Error('Cannot use dropframe with non NTSC timebase');
1993
+ if (typeof smpte !== 'string') {
1994
+ throw new Error("smpte must be a string, is ".concat(JSON.stringify(smpte)));
1539
1995
  }
1540
1996
 
1541
- var dropFrames = getDropFrames(roundedFrameRate);
1542
- var shouldDropMinute = mm % 10 !== 0;
1543
- var shouldDropSecond = shouldDropMinute && ss === 0;
1544
- var hourFrames = hh * (3600 * roundedFrameRate - 54 * dropFrames);
1545
- var minuteFrames = mm * 60 * roundedFrameRate - (mm - Math.ceil(mm / 10)) * dropFrames;
1546
- var secondFrames = ss * roundedFrameRate - (shouldDropMinute && ss > 1 ? dropFrames : 0);
1997
+ var _splitSmpte = splitSmpte(smpte),
1998
+ _splitSmpte2 = _slicedToArray__default["default"](_splitSmpte, 2),
1999
+ smpteValues = _splitSmpte2[0],
2000
+ timeCodeOptionsFromSmpte = _splitSmpte2[1];
1547
2001
 
1548
- if (shouldDropSecond && ff < dropFrames) {
1549
- throw new Error('Invalid ff');
2002
+ var timeBaseInstance = createTimeBase(timeBase);
2003
+
2004
+ var mergedOptions = _objectSpread$2(_objectSpread$2({}, timeCodeOptionsFromSmpte), {}, {
2005
+ dropFrame: isDropFrameTimeBase(timeBaseInstance)
2006
+ }, timeCodeOptions);
2007
+
2008
+ var roundedFrameRate = timeBaseInstance.toRate({
2009
+ rounded: true
2010
+ });
2011
+ var maxFrame = Math.max(0, roundedFrameRate - 1);
2012
+
2013
+ if (smpteValues.some(function (v) {
2014
+ return v < 0;
2015
+ })) {
2016
+ throw new Error('Negative values are not supported');
1550
2017
  }
1551
2018
 
1552
- var frameFrames = shouldDropSecond ? ff - dropFrames : ff;
1553
- return hourFrames + minuteFrames + secondFrames + frameFrames;
2019
+ var samples;
2020
+
2021
+ switch (exceedingMode) {
2022
+ case 'error':
2023
+ {
2024
+ var _smpteValues2 = _slicedToArray__default["default"](smpteValues, 4),
2025
+ hours = _smpteValues2[0],
2026
+ minutes = _smpteValues2[1],
2027
+ seconds = _smpteValues2[2],
2028
+ frames = _smpteValues2[3];
2029
+
2030
+ if (hours >= 100) {
2031
+ throw Error('Minutes has to be less than 60');
2032
+ }
2033
+
2034
+ if (minutes >= 60) {
2035
+ throw Error('Minutes has to be less than 60');
2036
+ }
2037
+
2038
+ if (seconds >= 60) {
2039
+ throw Error('Seconds has to be less than 60');
2040
+ }
2041
+
2042
+ if (frames > maxFrame) {
2043
+ throw Error("Frames has to be less or equal to ".concat(maxFrame));
2044
+ }
2045
+
2046
+ samples = getSamplesFromSmpte(smpteValues, timeBaseInstance, mergedOptions === null || mergedOptions === void 0 ? void 0 : mergedOptions.dropFrame);
2047
+ break;
2048
+ }
2049
+
2050
+ case 'ignore':
2051
+ {
2052
+ var _smpteValues3 = _slicedToArray__default["default"](smpteValues, 4),
2053
+ _hours = _smpteValues3[0],
2054
+ _minutes = _smpteValues3[1],
2055
+ _seconds = _smpteValues3[2],
2056
+ _frames = _smpteValues3[3];
2057
+
2058
+ var truncatedSmpteValues = [Math.min(100, _hours), Math.min(59, _minutes), Math.min(59, _seconds), Math.min(maxFrame, _frames)];
2059
+ samples = getSamplesFromSmpte(truncatedSmpteValues, timeBaseInstance, mergedOptions === null || mergedOptions === void 0 ? void 0 : mergedOptions.dropFrame);
2060
+ break;
2061
+ }
2062
+
2063
+ case 'add':
2064
+ {
2065
+ samples = getSamplesFromSmpte(smpteValues, timeBaseInstance, mergedOptions === null || mergedOptions === void 0 ? void 0 : mergedOptions.dropFrame);
2066
+ break;
2067
+ }
2068
+
2069
+ default:
2070
+ {
2071
+ throw new Error("Invalid exceedingMode, options are ".concat(JSON.stringify(EXCEEDING_OPTIONS)));
2072
+ }
2073
+ }
2074
+
2075
+ return new TimeCode({
2076
+ samples: samples,
2077
+ timeBase: timeBaseInstance
2078
+ }, mergedOptions);
1554
2079
  };
1555
2080
 
1556
- var formatSmpte = function formatSmpte(smpteText, timeBaseText) {
1557
- var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
2081
+ var _excluded$2 = ["timeBase"];
2082
+ /**
2083
+ * Format text to a TimeCode instance
2084
+ *
2085
+ * @param {string} timeCodeText A time code text (e.g. "25@PAL")
2086
+ * @param {object} [options={}] Options for how to format
2087
+ * @param {object|string} options.timeBase The time base the returned TimeCode should have
2088
+ * @returns {TimeCode} A TimeCode instance
2089
+ */
1558
2090
 
1559
- if (smpteText === undefined) {
1560
- var _timeBase = formatTimeBase(timeBaseText);
2091
+ var formatTimeCodeText = function formatTimeCodeText(timeCodeText, options) {
2092
+ var _timeCodeObject;
2093
+
2094
+ var _ref = options || {},
2095
+ timeBase = _ref.timeBase,
2096
+ timeCodeOptions = _objectWithoutProperties__default["default"](_ref, _excluded$2);
1561
2097
 
1562
- var _timeCode = {
1563
- samples: 0,
1564
- timeBase: _timeBase
2098
+ var timeCodeObject;
2099
+
2100
+ if (timeCodeText === undefined) {
2101
+ timeCodeObject = {
2102
+ samples: 0
2103
+ };
2104
+ } else if (typeof timeCodeText === 'number') {
2105
+ timeCodeObject = {
2106
+ samples: timeCodeText
2107
+ };
2108
+ } else if (timeCodeText.includes('@')) {
2109
+ var _timeCodeText$split = timeCodeText.split('@'),
2110
+ _timeCodeText$split2 = _slicedToArray__default["default"](_timeCodeText$split, 2),
2111
+ samplesString = _timeCodeText$split2[0],
2112
+ timeBaseText = _timeCodeText$split2[1];
2113
+
2114
+ var samples = Number(samplesString);
2115
+ timeCodeObject = {
2116
+ samples: samples,
2117
+ timeBase: formatTimeBaseText(timeBaseText)
2118
+ };
2119
+ } else if (timeCodeText === '-INF') {
2120
+ timeCodeObject = {
2121
+ samples: -Infinity
2122
+ };
2123
+ } else if (timeCodeText === '+INF') {
2124
+ timeCodeObject = {
2125
+ samples: Infinity
2126
+ };
2127
+ } else {
2128
+ timeCodeObject = {
2129
+ samples: Number(timeCodeText)
1565
2130
  };
1566
- return formatTimeCodeType(_timeCode);
1567
2131
  }
1568
2132
 
1569
- if (typeof smpteText !== 'string') {
1570
- throw new Error("smpteText must be a string, is ".concat(smpteText));
2133
+ if (Number.isNaN((_timeCodeObject = timeCodeObject) === null || _timeCodeObject === void 0 ? void 0 : _timeCodeObject.samples) || timeCodeObject.timeBase && !(timeCodeObject.timeBase instanceof TimeBase)) {
2134
+ throw new Error("timeCodeText must be a number or sample@timeBase - is ".concat(timeCodeText));
1571
2135
  }
1572
2136
 
1573
- var _splitSmpte = splitSmpte(smpteText),
1574
- _splitSmpte2 = _slicedToArray__default["default"](_splitSmpte, 2),
1575
- _splitSmpte2$ = _slicedToArray__default["default"](_splitSmpte2[0], 4),
1576
- hh = _splitSmpte2$[0],
1577
- mm = _splitSmpte2$[1],
1578
- ss = _splitSmpte2$[2],
1579
- _splitSmpte2$$ = _splitSmpte2$[3],
1580
- ff = _splitSmpte2$$ === void 0 ? 0 : _splitSmpte2$$,
1581
- frameOptions = _splitSmpte2[1];
1582
-
1583
- var _frameOptions$dropFra = frameOptions.dropFrame,
1584
- dropFrame = _frameOptions$dropFra === void 0 ? false : _frameOptions$dropFra;
1585
- var timeBase = formatTimeBase(timeBaseText);
1586
- var roundedFrameRate = getRoundedFrameRate(timeBase);
1587
-
1588
- if (mm >= 60 || mm < 0 || ss >= 60 || ss < 0 || ff >= roundedFrameRate || ff < 0) {
1589
- throw new Error('Invalid mm, ss or ff');
1590
- }
1591
-
1592
- var samples = countSamples(hh, mm, ss, ff, {
1593
- dropFrame: dropFrame,
1594
- roundedFrameRate: roundedFrameRate
1595
- });
1596
- var timeCode = {
1597
- samples: samples,
1598
- timeBase: timeBase
1599
- };
1600
- return formatTimeCodeType(timeCode, _objectSpread$2(_objectSpread$2({}, frameOptions), options));
2137
+ var timeCode = new TimeCode(timeCodeObject, timeCodeOptions);
2138
+ return timeBase ? timeCode.conformTimeBase(createTimeBase(timeBase)) : timeCode;
2139
+ };
2140
+
2141
+ /**
2142
+ * Format an object to a TimeCode instance
2143
+ *
2144
+ * @param {object} timeCode To create TimeCode instance of
2145
+ * @param {object} options For the TimeCode constructor
2146
+ * @returns {TimeCode} A TimeCode instance
2147
+ */
2148
+
2149
+ var formatTimeCodeType = function formatTimeCodeType(timeCode, options) {
2150
+ return new TimeCode(timeCode, options);
2151
+ };
2152
+
2153
+ var isObject = function isObject(o) {
2154
+ return Object.prototype.toString.call(o) === '[object Object]';
2155
+ };
2156
+
2157
+ var isString = function isString(s) {
2158
+ return typeof s === 'string';
2159
+ };
2160
+
2161
+ var hasSmpteFormat = function hasSmpteFormat(s) {
2162
+ return isString(s) && !!s.match(/^(\d\d+):(\d\d+):(\d\d+)(:|;|\.|,)(\d\d+)$/);
2163
+ };
2164
+
2165
+ var isNumber = function isNumber(s) {
2166
+ return !Number.isNaN(Number(s));
2167
+ };
2168
+ /**
2169
+ * Create a TimeCode instance from smpte, seconds/samples, timeCode object or string
2170
+ *
2171
+ * @param {object|string|number} timeCode Smpte, seconds/samples, timeCode object or string
2172
+ * @param {object} [options={}] For the format functions
2173
+ * @returns {TimeCode} A TimeCode instance
2174
+ */
2175
+
2176
+
2177
+ var createTimeCode = function createTimeCode(timeCode, options) {
2178
+ if (isObject(timeCode)) return formatTimeCodeType(timeCode, options);
2179
+ if (hasSmpteFormat(timeCode)) return formatTimeCodeSmpte(timeCode, options);
2180
+ if (isNumber(timeCode)) return formatTimeCodeSeconds(timeCode, options);
2181
+ return formatTimeCodeText(timeCode, options);
1601
2182
  };
1602
2183
 
1603
2184
  function timeToCueTime(_ref) {
@@ -1617,10 +2198,10 @@ function timeToCueTime(_ref) {
1617
2198
  }
1618
2199
  /**
1619
2200
  * Convert subtitle groups to WebVtt subtitle format
1620
- * @param {Object} input={}
2201
+ * @param {Object} [input={}]
1621
2202
  * @param {Object} input.metadataType - MetadataType response from API.
1622
- * @param {string} input.subtitleGroup=stl_subtitle - Name of group containing subtitle field/text.
1623
- * @param {string} input.subtitleField=stl_text - Name of field (text) to use for the subtitles.
2203
+ * @param {string} [input.subtitleGroup=stl_subtitle] - Name of group containing subtitle field/text.
2204
+ * @param {string} [input.subtitleField=stl_text] - Name of field (text) to use for the subtitles.
1624
2205
  * @returns {string} WebVtt subtitles
1625
2206
  */
1626
2207
 
@@ -1815,12 +2396,13 @@ var parseContainerComponent = function parseContainerComponent(containerComponen
1815
2396
  }
1816
2397
 
1817
2398
  if (durationTimeCode !== undefined && durationTimeCode.samples !== 0) {
1818
- parsedContainerComponent.durationTimeCode = formatTimeCodeType(durationTimeCode);
1819
- parsedContainerComponent.duration = parsedContainerComponent.durationTimeCode.toDuration();
2399
+ var timeCode = formatTimeCodeType(durationTimeCode);
2400
+ parsedContainerComponent.durationTimeCode = timeCode.toObject();
2401
+ parsedContainerComponent.duration = timeCode.toDuration();
1820
2402
  }
1821
2403
 
1822
2404
  if (startTimestamp) {
1823
- parsedContainerComponent.startTimestamp = formatTimeCodeType(startTimestamp);
2405
+ parsedContainerComponent.startTimestamp = formatTimeCodeType(startTimestamp).toObject();
1824
2406
  }
1825
2407
 
1826
2408
  if (startTimecode !== undefined && timeCodeTimeBase) {
@@ -1892,8 +2474,10 @@ var parseVideoComponent = function parseVideoComponent(videoComponent) {
1892
2474
  samples: samples,
1893
2475
  timeBase: timeBase
1894
2476
  });
1895
- frameRate = timeCode.timeBase.toRate(true);
1896
- smpte = timeCode.toSmpte(true);
2477
+ frameRate = timeCode.timeBase.toRate({
2478
+ constant: true
2479
+ });
2480
+ smpte = timeCode.toSmpte();
1897
2481
  }
1898
2482
 
1899
2483
  var height = resolution.height,
@@ -2274,7 +2858,9 @@ var parseMediaConvertPreset = function parseMediaConvertPreset(transcodePresetTy
2274
2858
  numerator: numerator
2275
2859
  });
2276
2860
  output.timeBase = timeBase;
2277
- output.frameRate = timeBase.toRate(true);
2861
+ output.frameRate = timeBase.toRate({
2862
+ constant: true
2863
+ });
2278
2864
  }
2279
2865
  }
2280
2866
 
@@ -2319,7 +2905,9 @@ var parseTranscodePreset = function parseTranscodePreset(transcodePresetType) {
2319
2905
  if (video.framerate) {
2320
2906
  var timeBase = formatTimeBaseType(video.framerate);
2321
2907
  output.timeBase = timeBase;
2322
- output.frameRate = timeBase.toRate(true);
2908
+ output.frameRate = timeBase.toRate({
2909
+ constant: true
2910
+ });
2323
2911
  }
2324
2912
 
2325
2913
  if (video.scaling) {
@@ -2372,14 +2960,14 @@ exports.TimeBase = TimeBase;
2372
2960
  exports.TimeCode = TimeCode;
2373
2961
  exports.createFacetType = createFacetType;
2374
2962
  exports.createMetadataType = createMetadataType;
2963
+ exports.createTimeBase = createTimeBase;
2964
+ exports.createTimeCode = createTimeCode;
2375
2965
  exports.filterShapeSource = filterShapeSource;
2376
2966
  exports.findNearestThumbnail = findNearestThumbnail;
2377
- exports.formatSeconds = formatSeconds;
2378
- exports.formatSecondsPrecise = formatSecondsPrecise;
2379
- exports.formatSmpte = formatSmpte;
2380
- exports.formatTimeBase = formatTimeBase;
2381
2967
  exports.formatTimeBaseText = formatTimeBaseText;
2382
2968
  exports.formatTimeBaseType = formatTimeBaseType;
2969
+ exports.formatTimeCodeSeconds = formatTimeCodeSeconds;
2970
+ exports.formatTimeCodeSmpte = formatTimeCodeSmpte;
2383
2971
  exports.formatTimeCodeText = formatTimeCodeText;
2384
2972
  exports.formatTimeCodeType = formatTimeCodeType;
2385
2973
  exports.getDocumentType = getDocumentType;