diff --git a/.gitignore b/.gitignore index 50cc40b..c377d21 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,5 @@ typings/ .env dist/ + +.DS_Store diff --git a/src/index.js b/src/index.js index b073115..0b3a33b 100644 --- a/src/index.js +++ b/src/index.js @@ -76,6 +76,39 @@ SMPTE.fromParts = function ( return new SMPTE({hours, minutes, seconds, frames}, fr, df); }; +/** + * Creates a SMPTE object given an array of parts of the timecode + * @param {Array} timecode Array containing parts of the timecode + * @param {Number} fr Frame rate number + * @param {Boolean} df Boolean indicating if timecode is drop frame + */ +SMPTE.fromArray = function ( + timecode, + fr = SMPTE.defaults.frameRate, + df = SMPTE.defaults.dropFrame +) { + if (! Array.isArray(timecode)) { + throw new Error('First argument must be an array'); + } + + const strTimecode = timecode + .map(part => part.toString().padStart(2, '0')) + .join(df ? ';' : ':'); + + if (! SMPTE.isTimecodeFormatValid(strTimecode)) { + throw new Error('Invalid timecode'); + } + + const [ + hours, + minutes, + seconds, + frames, + ] = timecode; + + return new SMPTE({hours, minutes, seconds, frames}, fr, df); +}; + /** * Checks if a timecode string is in a valid format * @param {String} timecode Timecode string to be evaluated diff --git a/test/unit/timecode.static.js b/test/unit/timecode.static.js index a4a8cf8..60be869 100644 --- a/test/unit/timecode.static.js +++ b/test/unit/timecode.static.js @@ -193,4 +193,69 @@ describe('SMPTE', function () { expect(fromSeconds(600, FrameRate.FR_60).frameCount).to.equal(36000); }); }); + + describe('.fromArray()', function () { + const fromArray = SMPTE.fromArray; + + it('should accept an array', function () { + expect(() => fromArray('00:00:00:00')).to.throw(Error); + expect(() => fromArray(0)).to.throw(Error); + expect(() => fromArray([ + 0, + 0, + 0, + 0, + ])).to.not.throw(Error); + }); + + it('should accept an valid timecode array', function () { + expect(() => fromArray([ + 0, + ])).to.throw(Error); + + expect(() => fromArray([ + 25, + 60, + 60, + 60, + ])).to.throw(Error); + + expect(() => fromArray([ + 23, + 59, + 59, + 23, + ])).to.not.throw(Error); + }); + + it('should properly return frame count', function () { + const timecode = '02:30:10:15'; + + const splitted = timecode.split(':').map(part => parseInt(part)); + + expect(fromArray(splitted, FrameRate.FR_23_976).frameCount) + .to.equal(new SMPTE(timecode, FrameRate.FR_23_976).frameCount); + + expect(fromArray(splitted, FrameRate.FR_24).frameCount) + .to.equal(new SMPTE(timecode, FrameRate.FR_24).frameCount); + + expect(fromArray(splitted, FrameRate.FR_25).frameCount) + .to.equal(new SMPTE(timecode, FrameRate.FR_25).frameCount); + + expect(fromArray(splitted, FrameRate.FR_29_97).frameCount) + .to.equal(new SMPTE(timecode, FrameRate.FR_29_97).frameCount); + + expect(fromArray(splitted, FrameRate.FR_30).frameCount) + .to.equal(new SMPTE(timecode, FrameRate.FR_30).frameCount); + + expect(fromArray(splitted, FrameRate.FR_50).frameCount) + .to.equal(new SMPTE(timecode, FrameRate.FR_50).frameCount); + + expect(fromArray(splitted, FrameRate.FR_59_94).frameCount) + .to.equal(new SMPTE(timecode, FrameRate.FR_59_94).frameCount); + + expect(fromArray(splitted, FrameRate.FR_60).frameCount) + .to.equal(new SMPTE(timecode, FrameRate.FR_60).frameCount); + }); + }); });