Created
June 3, 2020 06:49
-
-
Save sxd1140/11117d36baf83f1f621a3661bbc6e5b2 to your computer and use it in GitHub Desktop.
Modify atem.js reference https://github.com/kasperskaarhoj/SKAARHOJ-Open-Engineering/tree/master/ArduinoLibs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
DEFAULT_PORT = 9910; | |
RECONNECT_INTERVAL = 5000; | |
COMMAND_CONNECT_HELLO = [0x10, 0x14, 0x53, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; | |
COMMAND_CONNECT_HELLO_ANSWER = [0x80, 0x0C, 0x53, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00]; | |
AUDIO_GAIN_RATE = 65381; | |
ATEM_maxInitPackageCount = 40; | |
ATEM.Model = { | |
'TVS': 0x01, | |
'1ME': 0x02, | |
'2ME': 0x03, | |
'PS4K': 0x04, | |
'1ME4K': 0x05, | |
'2ME4K': 0x06, | |
'2MEBS4K': 0x07 | |
}; | |
}; | |
ATEM.prototype.connectionState = ATEM.ConnectionState.Closed; | |
ATEM.prototype.localPackedId = 1; | |
ATEM.prototype.sessionId = []; | |
ATEM.prototype.remotePacketId = []; | |
ATEM.prototype.missedInitializationPackages = []; | |
ATEM.prototype.waitingForIncoming = false; | |
ATEM.prototype.initPayloadSent = false; | |
ATEM.prototype.hasInitialized = false; | |
ATEM.prototype.initPayloadSentAtPacketId = 0; | |
function ATEM(options) { | |
if (options == null) { | |
options = {}; | |
} | |
this._receivePacket = __bind(this._receivePacket, this); | |
this.forceOldStyle = options.forceOldStyle || false; | |
this.localPort = options.localPort || 1024 + Math.floor(Math.random() * 64511); | |
this.event = new EventEmitter; | |
this.commandEvent = new EventEmitter; | |
this.event.on('ping', (function(_this) { | |
return function(err) { | |
console.log('record lastconnectat') | |
return _this.lastConnectAt = new Date().getTime(); | |
}; | |
})(this)); | |
this.socket = dgram.createSocket('udp4'); | |
this.socket.on('message', this._receivePacket); | |
this.socket.bind(this.localPort); | |
setInterval((function(_this) { | |
return function() { | |
if (_this.lastConnectAt + RECONNECT_INTERVAL > new Date().getTime()) { | |
return; | |
} | |
if (_this.connectionState === ATEM.ConnectionState.Established) { | |
_this.connectionState = ATEM.ConnectionState.Closed; | |
_this.event.emit('disconnect', null, null); | |
} | |
// _this.localPackedId = 1; | |
// _this.sessionId = []; | |
return _this.connect(_this.address, _this.port); | |
}; | |
})(this), RECONNECT_INTERVAL); | |
} | |
ATEM.prototype.connect = function (address, port, local_port) { | |
this.address = address; | |
this.port = port != null ? port : DEFAULT_PORT; | |
if (local_port == null) { | |
local_port = 0; | |
} | |
this.localPackedId = 0; // Init localPacketIDCounter to 0; | |
this.iRemotePacketID = 0; | |
this.remotePacketId = []; | |
this.initPayloadSent = false; // Will be true after initial payload of data is delivered (regular 12-byte ping packages are transmitted.) | |
this.hasInitialized = false; // Will be true after initial payload of data is resent and received well | |
this.isConnected = false; // Will be true after the initial hello-package handshakes. | |
this.sessionId = [0x53, 0xAB]; // Temporary session ID - a new will be given back from ATEM. | |
this.lastConnectAt = new Date().getTime(); | |
for (var i = 0; i < ATEM_maxInitPackageCount + 7 / 8; i++) { | |
this.missedInitializationPackages[i] = 0xFF; | |
} | |
this.initPayloadSentAtPacketId = ATEM_maxInitPackageCount; | |
this._sendPacket(COMMAND_CONNECT_HELLO); | |
return this.connectionState = ATEM.ConnectionState.SynSent; | |
}; | |
ATEM.prototype.on = function (name, callback) { | |
return this.event.on(name, callback); | |
}; | |
buffer[1] = 0x0C; | |
buffer[2] = this.sessionId[0]; | |
buffer[3] = this.sessionId[1]; | |
buffer[4] = this.remotePacketId[0]; | |
buffer[5] = this.remotePacketId[1]; | |
buffer[9] = 0x41; | |
return this._sendPacket(buffer); | |
}; | |
ATEM.prototype._sendCommand = function (command, payload) { | |
if (!this.hasInitialized) return; | |
var buffer; | |
if (!Buffer.isBuffer(payload)) { | |
payload = new Buffer(payload); | |
} | |
buffer = new Buffer(20 + payload.length); | |
buffer.fill(0); | |
buffer[0] = (20 + payload.length) / 256 | 0x08; | |
buffer[1] = (20 + payload.length) % 256; | |
buffer[2] = this.sessionId[0]; | |
buffer[3] = this.sessionId[1]; | |
buffer[19] = command.charCodeAt(3); | |
payload.copy(buffer, 20); | |
this._sendPacket(buffer); | |
return this.localPackedId++; | |
}; | |
ATEM.prototype._sendPacket = function (buffer) { | |
if (!Buffer.isBuffer(buffer)) { | |
buffer = new Buffer(buffer); | |
} | |
// if (DEBUG) { | |
// console.log('SEND', buffer); | |
// } | |
// console.log('local id ' , buffer[10]<<8 |buffer[11]&255); | |
// console.log(String.fromCharCode(buffer[16],buffer[17],buffer[18],buffer[19])); | |
// if (this.connectionState == ATEM.ConnectionState.Closed) return; | |
return this.socket.send(buffer, 0, buffer.length, this.port, this.address); | |
}; | |
ATEM.prototype._receivePacket = function (message, remote) { | |
var flags, length; | |
length = ((message[0] & 0x07) << 8) | message[1]; | |
if (length !== remote.size) { | |
return; | |
} | |
// if (DEBUG) { | |
// console.log('RECV', message); | |
// } | |
flags = message[0] >> 3; | |
this.sessionId = [message[2], message[3]]; | |
this.remotePacketId[0] = message[10]; | |
this.remotePacketId[1] = message[11]; | |
this.iRemotePacketID = message[10] << 8 | message[11]; | |
this.lastConnectAt = new Date().getTime(); | |
this.waitingForIncoming = false; | |
if (this.iRemotePacketID < ATEM_maxInitPackageCount) { | |
this.missedInitializationPackages[this.iRemotePacketID >> 3] &= ~(1 << (this.iRemotePacketID & 0x07)); | |
} | |
if (flags & 0x2 && !(flags & 0x4)) { | |
this.isConnected = true; | |
COMMAND_CONNECT_HELLO_ANSWER[2] = this.sessionId[0]; | |
COMMAND_CONNECT_HELLO_ANSWER[3] = this.sessionId[1]; | |
this._sendPacket(COMMAND_CONNECT_HELLO_ANSWER); | |
} | |
if (!this.initPayloadSent && length == 12 && this.iRemotePacketID > 0) { | |
this.initPayloadSent = true; | |
this.initPayloadSentAtPacketId = this.iRemotePacketID; | |
} | |
if (this.initPayloadSent && (flags & 0x1) && (this.hasInitialized || !(flags & 0x4))) { | |
var buffer; | |
buffer = new Buffer(12); | |
buffer.fill(0); | |
buffer[0] = 0x10 << 3 | 12 >> 8 & 0x7; | |
buffer[1] = 12 & 0xFF; | |
buffer[2] = this.sessionId[0]; | |
buffer[3] = this.sessionId[1]; | |
buffer[4] = this.remotePacketId[0]; | |
buffer[5] = this.remotePacketId[1]; | |
// this.localPackedId++; | |
buffer[10] = this.localPackedId >> 8; | |
buffer[11] = this.localPackedId & 0xFF; | |
this._sendPacket(buffer); | |
// this._sendAck(); | |
} | |
else if (this.initPayloadSent && (flags & 0x8) && this.hasInitialized) { | |
var b1 = message[6]; | |
var b2 = message[7]; | |
var buffer; | |
buffer = new Buffer(12); | |
buffer.fill(0); | |
buffer[0] = 0x1 << 3 | 12 >> 8 & 0x7; | |
buffer[1] = 12 & 0xFF; | |
buffer[2] = this.sessionId[0]; | |
buffer[3] = this.sessionId[1]; | |
buffer[4] = this.remotePacketId[0]; | |
buffer[5] = this.remotePacketId[1]; | |
buffer[10] = b1; | |
buffer[11] = b2; | |
this._sendPacket(buffer); | |
} | |
if ((flags & 0x1) && length > 12) { | |
this._parseCommand(message.slice(12)); | |
this.event.emit('stateChanged', null, this.state); | |
} | |
if (!this.hasInitialized && this.initPayloadSent && !this.waitingForIncoming) { | |
for (var i = 1; i < this.initPayloadSentAtPacketId; i++) { | |
if (i <= ATEM_maxInitPackageCount) { | |
if (this.missedInitializationPackages[i >> 3] & (1 << (i & 0x7))) { | |
var buffer; | |
buffer = new Buffer(12); | |
buffer.fill(0); | |
buffer[0] = 0x8 << 3 | 12 >> 8 & 0x7; | |
buffer[1] = 12 & 0xFF; | |
buffer[2] = this.sessionId[0]; | |
buffer[3] = this.sessionId[1]; | |
buffer[4] = this.remotePacketId[0]; | |
buffer[5] = this.remotePacketId[1]; | |
buffer[6] = (i - 1) >> 8; | |
buffer[7] = (i - 1) & 0xFF; | |
buffer[8] = 1; | |
// buffer[10] = this.localPackedId >> 8; | |
// buffer[11] = this.localPackedId & 0xFF; | |
this._sendPacket(buffer); | |
this.waitingForIncoming = true; | |
break; | |
} | |
} else { | |
break; | |
} | |
} | |
if (!this.waitingForIncoming) { | |
this.hasInitialized = true; | |
this.event.emit('connect', null, null); | |
} | |
} | |
/* | |
if (flags & ATEM.PacketFlag.Connect && !(flags & ATEM.PacketFlag.Repeat)) { | |
console.log('hello ack'); | |
console.log('new sessionid', this.sessionId) | |
this._sendPacket(COMMAND_CONNECT_HELLO_ANSWER); | |
} | |
if (flags & ATEM.PacketFlag.Sync && length > 12) { | |
this._parseCommand(message.slice(12)); | |
this.event.emit('stateChanged', null, this.state); | |
} | |
if (flags & ATEM.PacketFlag.Sync && length === 12 && this.connectionState === ATEM.ConnectionState.SynSent) { | |
this.connectionState = ATEM.ConnectionState.Established; | |
console.log('connect first'); | |
this.event.emit('connect', null, null); | |
} | |
if (flags & ATEM.PacketFlag.Sync && this.connectionState === ATEM.ConnectionState.Established) { | |
// if (a) { | |
this._sendAck(); | |
// a = false; | |
// setTimeout(()=>{ | |
// b = true; | |
// },10000) | |
// } | |
console.log('get ping'); | |
return this.event.emit('ping', null, null); | |
} | |
*/ | |
}; | |
ATEM.prototype._parseCommand = function(buffer) { | |
var key, length, name, value, _ref, _results; | |
length = this._parseNumber(buffer.slice(0, 2)); | |
name = this._parseString(buffer.slice(4, 8)); | |
if (DEBUG) { | |
console.log('COMMAND', "" + name + "(" + length + ")", buffer.slice(0, length)); | |
} | |
this._setStatus(name, buffer.slice(0, length).slice(8)); | |
if (me == null) { | |
me = 0; | |
} | |
return this._sendCommand('DCut', [me, 0xef, 0xbf, 0x5f]); | |
}; | |
ATEM.prototype.changeTransitionPosition = function(position, me) { | |
if (me == null) { | |
me = 0; | |
} | |
return this._sendCommand('CTPs', [me, 0x00, position / 256, position % 256]); | |
if (position >= 10000) { | |
return this._sendCommand('CTPs', [me, 0x00, 0x00, 0x00]); | |
} | |
}; | |
ATEM.prototype.changeTransitionPreview = function(state, me) { | |
if (me == null) { | |
me = 0; | |
} | |
return this._sendCommand('CTPr', [me, state, 0x00, 0x00]); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment