diff --git a/lib/atem.coffee b/lib/atem.coffee index 1cbfa57..820a71f 100644 --- a/lib/atem.coffee +++ b/lib/atem.coffee @@ -51,7 +51,7 @@ class ATEM Ack: 0x10 state: - tallys : [] + tallys: [] channels: {} video: upstreamKeyNextState: [] @@ -277,6 +277,19 @@ class ATEM arr.push(buffer) arr + _numberToBytes: (number, numberOfBytes) -> + bytes = [] + for i in [0...numberOfBytes] + shift = numberOfBytes - i - 1 + bytes.push((number >> (8 * shift)) & 0xFF) + bytes + + _stringToBytes: (str) -> + bytes = [] + for i in [0...str.length] + bytes.push(str.charCodeAt(i)) + bytes + _merge: (obj1, obj2) -> obj2 = {} unless obj2? for key2 of obj2 @@ -352,4 +365,24 @@ class ATEM sendAudioLevelNumber: (enable = true) -> @_sendCommand('SALN', [enable, 0x00, 0x00, 0x00]) + startRecordMacro: (number, name, description) -> # ATEM response with "MRcS" + nameLength = name?.length || 0 + descriptionLength = description?.length || 0 + bytes = [0x00, number] + bytes = bytes.concat(@_numberToBytes(nameLength, 2)) + bytes = bytes.concat(@_numberToBytes(descriptionLength, 2)) + bytes = bytes.concat(@_stringToBytes(name)) if nameLength > 0 + bytes = bytes.concat(@_stringToBytes(description)) if descriptionLength > 0 + + @_sendCommand('MSRc', bytes) + + stopRecordMacro: -> # ATEM response with "MRcS" + @_sendCommand('MAct', [0xFF, 0xFF, 0x02, 0x81]) # Filling number field with 0xFF means special action + + runMacro: (number) -> # ATEM response with "MRPr" + @_sendCommand('MAct', [0x00, number, 0x00, 0x7d]) + + deleteMacro: (number) -> # ATEM response with "MPrp" + @_sendCommand('MAct', [0x00, number, 0x05, 0x00]) + module.exports = ATEM diff --git a/test/test-atem.coffee b/test/test-atem.coffee index 6b230e8..4d8aa4b 100644 --- a/test/test-atem.coffee +++ b/test/test-atem.coffee @@ -371,6 +371,27 @@ describe 'Atem', -> after initialize + describe 'runMacro', -> + before (done) -> + sw.changeProgramInput(1) + setTimeout(done, 100) + + it 'expects run macro', (done) -> + sw.startRecordMacro(99, 'Test Macro', 'Hey! This is macro.') + sw.changeProgramInput(2) + sw.stopRecordMacro() + sw.changeProgramInput(1) + sw.runMacro(99) + setTimeout( -> + expect(sw.state.video.programInput).be.eq(2) + done null, null + , 500) + + after (done) -> + sw.deleteMacro(99) + sw.changeProgramInput(1) + setTimeout(done, 100) + after -> console.log """\n-------- ATEM Information -------- ATEM Model: #{sw.state._pin}(#{sw.state.model})