mirror of
https://github.com/Ylianst/MeshCommander
synced 2025-12-06 06:03:20 +00:00
Started adding support for mid-stream AMTKVM recording.
This commit is contained in:
@@ -75,6 +75,11 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
function strToArr(str) { var arr = new Uint8Array(str.length); for (var i = 0, j = str.length; i < j; ++i) { arr[i] = str.charCodeAt(i); } return arr }
|
||||
|
||||
obj.ProcessBinaryData = function (data) {
|
||||
// ###BEGIN###{DesktopRecorder}
|
||||
// Record the data if needed
|
||||
if ((obj.recordedData != null) && (obj.recordedHolding !== true)) { obj.recordedData.push(recordingEntry(2, 1, String.fromCharCode.apply(null, new Uint8Array(data)))); }
|
||||
// ###END###{DesktopRecorder}
|
||||
|
||||
// Append to accumulator
|
||||
if (obj.acc == null) {
|
||||
obj.acc = new Uint8Array(data);
|
||||
@@ -121,6 +126,10 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
obj.canvas.canvas.width = obj.rwidth = obj.width = obj.ScreenWidth = accview.getUint16(0);
|
||||
obj.canvas.canvas.height = obj.rheight = obj.height = obj.ScreenHeight = accview.getUint16(2);
|
||||
|
||||
// ###BEGIN###{DesktopRecorder}
|
||||
obj.DeskRecordServerInit = String.fromCharCode.apply(null, new Uint8Array(obj.acc.buffer.slice(0, 24 + namelen)));
|
||||
// ###END###{DesktopRecorder}
|
||||
|
||||
// These are all values we don't really need, we are going to only run in RGB565 or RGB332 and not use the flexibility provided by these settings.
|
||||
// Makes the javascript code smaller and maybe a bit faster.
|
||||
/*
|
||||
@@ -178,6 +187,12 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
if (obj.acc.byteLength < 4) return;
|
||||
obj.state = 100 + accview.getUint16(2); // Read the number of tiles that are going to be sent, add 100 and use that as our protocol state.
|
||||
cmdsize = 4;
|
||||
|
||||
// ###BEGIN###{DesktopRecorder}
|
||||
// This is the start of a new frame, start recording now if needed.
|
||||
if (obj.recordedHolding === true) { delete obj.recordedHolding; obj.recordedData.push(recordingEntry(2, 1, String.fromCharCode.apply(null, obj.acc))); }
|
||||
// ###END###{DesktopRecorder}
|
||||
|
||||
break;
|
||||
case 2: // This is the bell, do nothing.
|
||||
cmdsize = 1;
|
||||
@@ -889,5 +904,61 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
|
||||
return Position;
|
||||
}
|
||||
|
||||
// ###BEGIN###{DesktopRecorder}
|
||||
obj.StartRecording = function () {
|
||||
if ((obj.recordedData != null) && (obj.DeskRecordServerInit != null)) return false;
|
||||
|
||||
// Take a screen shot and save it to file
|
||||
var b64image = obj.CanvasId.toDataURL('image/png').split(',')[1];
|
||||
|
||||
// This is an ArrayBuffer, convert it to a string array
|
||||
//var binary = '', bytes = new Uint8Array(fileReader.result), length = bytes.byteLength;
|
||||
//for (var i = 0; i < length; i++) { binary += String.fromCharCode(bytes[i]); }
|
||||
obj.recordedHolding = true;
|
||||
obj.recordedData = [];
|
||||
obj.recordedStart = Date.now();
|
||||
obj.recordedSize = 0;
|
||||
obj.recordedData.push(recordingEntry(1, 0, JSON.stringify({ magic: 'MeshCentralRelaySession', ver: 1, time: new Date().toLocaleString(), protocol: 200, bpp: obj.bpp }))); // Metadata, 200 = Midstream Intel AMT KVM
|
||||
obj.recordedData.push(recordingEntry(2, 1, obj.DeskRecordServerInit));
|
||||
|
||||
/*
|
||||
// Save a screenshot
|
||||
var cmdlen = (8 + binary.length);
|
||||
if (cmdlen > 65000) {
|
||||
// Jumbo Packet
|
||||
obj.recordedData.push(recordingEntry(2, 1, ShortToStr(27) + ShortToStr(8) + IntToStr(cmdlen) + ShortToStr(3) + ShortToStr(0) + ShortToStr(0) + ShortToStr(0) + binary));
|
||||
} else {
|
||||
// Normal packet
|
||||
obj.recordedData.push(recordingEntry(2, 1, ShortToStr(3) + ShortToStr(cmdlen) + ShortToStr(0) + ShortToStr(0) + binary));
|
||||
}
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
obj.StopRecording = function () {
|
||||
if (obj.recordedData == null) return;
|
||||
var r = obj.recordedData;
|
||||
r.push(recordingEntry(3, 0, 'MeshCentralMCREC'));
|
||||
delete obj.recordedData;
|
||||
delete obj.recordedStart;
|
||||
delete obj.recordedSize;
|
||||
return r;
|
||||
}
|
||||
|
||||
function recordingEntry(type, flags, data) {
|
||||
//console.log('recordingEntry', type, flags, (typeof data == 'number')?data:data.length);
|
||||
// Header: Type (2) + Flags (2) + Size(4) + Time(8)
|
||||
// Type (1 = Header, 2 = Network Data), Flags (1 = Binary, 2 = User), Size (4 bytes), Time (8 bytes)
|
||||
var now = Date.now();
|
||||
if (typeof data == 'number') {
|
||||
obj.recordedSize += data;
|
||||
return ShortToStr(type) + ShortToStr(flags) + IntToStr(data) + IntToStr(now >> 32) + IntToStr(now & 32);
|
||||
} else {
|
||||
obj.recordedSize += data.length;
|
||||
return ShortToStr(type) + ShortToStr(flags) + IntToStr(data.length) + IntToStr(now >> 32) + IntToStr(now & 32) + data;
|
||||
}
|
||||
}
|
||||
// ###END###{DesktopRecorder}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
function CreateIMRSDKWrapper() {
|
||||
var obj = {};
|
||||
|
||||
var _IMRSDK;
|
||||
var _ImrSdkVersion;
|
||||
var _ref = require('ref');
|
||||
@@ -22,23 +21,28 @@ function CreateIMRSDKWrapper() {
|
||||
|
||||
// Callback from the native lib back into js (StdCall)
|
||||
var uintPtr = _ref.refType('uint');
|
||||
var OpenHandlerCallBack = _ffi.Callback('int', ['uint', 'uint'], _ffi.FFI_STDCALL, function (clientID, conID) { obj.pendingData[conID] = ''; return 0; });
|
||||
var CloseHandlerCallBack = _ffi.Callback('int', ['uint'], _ffi.FFI_STDCALL, function (conID) { obj.pendingData[conID] = ''; return 0; });
|
||||
var OpenHandlerCallBack = _ffi.Callback('int', ['uint', 'uint'], _ffi.FFI_STDCALL, function (clientID, conID) { obj.conID = conID; obj.pendingData[conID] = ''; return 0; });
|
||||
var CloseHandlerCallBack = _ffi.Callback('int', ['uint'], _ffi.FFI_STDCALL, function (conID) { obj.pendingData[conID] = null; return 0; });
|
||||
var ReceiveHandlerCallBack = _ffi.Callback('int', ['pointer', uintPtr, 'uint'], _ffi.FFI_STDCALL, function (bufferPtr, lengthPtr, conID) {
|
||||
try {
|
||||
var bufferLen = lengthPtr.readUInt32LE(0), buffer = _ref.reinterpret(bufferPtr, bufferLen);
|
||||
lengthPtr.writeUInt32LE(obj.pendingData[conID].length, 0);
|
||||
for (var i = 0; i < obj.pendingData[conID].length; i++) { buffer[i] = obj.pendingData[conID].charCodeAt(i); }
|
||||
// ###BEGIN###{IDERDebug}
|
||||
//console.log('ReceiveHandlerCallBack(conID: ' + conID + ', Len: ' + obj.pendingData[conID].length + ')');
|
||||
if (logFile != null) { logFile.write('IDERRECV: ' + rstr2hex(obj.pendingData[conID]) + '\r\n'); }
|
||||
// ###END###{IDERDebug}
|
||||
obj.pendingData[conID] = '';
|
||||
if (obj.pendingData[conID] == null) {
|
||||
lengthPtr.writeUInt32LE(0, 0); // Send a close
|
||||
} else {
|
||||
var bufferLen = lengthPtr.readUInt32LE(0), buffer = _ref.reinterpret(bufferPtr, bufferLen);
|
||||
lengthPtr.writeUInt32LE(obj.pendingData[conID].length, 0);
|
||||
for (var i = 0; i < obj.pendingData[conID].length; i++) { buffer[i] = obj.pendingData[conID].charCodeAt(i); }
|
||||
// ###BEGIN###{IDERDebug}
|
||||
//console.log('ReceiveHandlerCallBack(conID: ' + conID + ', Len: ' + obj.pendingData[conID].length + ')');
|
||||
if (logFile != null) { logFile.write('IDERRECV: ' + rstr2hex(obj.pendingData[conID]) + '\r\n'); }
|
||||
// ###END###{IDERDebug}
|
||||
obj.pendingData[conID] = '';
|
||||
}
|
||||
} catch (e) { console.log(e); }
|
||||
return 0;
|
||||
});
|
||||
var SendHandlerCallBack = _ffi.Callback('int', ['pointer', 'uint', 'uint'], _ffi.FFI_STDCALL, function (ptr, length, conID) {
|
||||
try {
|
||||
if (obj.client == null) return;
|
||||
var buffer = _ref.reinterpret(ptr, length), str = '';
|
||||
for (var i = 0; i < length; i++) { str += String.fromCharCode(buffer[i]); }
|
||||
// ###BEGIN###{IDERDebug}
|
||||
@@ -123,7 +127,7 @@ function CreateIMRSDKWrapper() {
|
||||
if (_Setup('imrsdk') == false) { if (_Setup('imrsdk_x64') == false) { return null; } }
|
||||
|
||||
// IMR_Init
|
||||
obj.Init = function() {
|
||||
obj.Init = function () {
|
||||
var version = new _IMRVersion();
|
||||
var error = _IMRSDK.IMR_Init(version.ref(), 'imrsdk.ini');
|
||||
if (error == 4) return _ImrSdkVersion; // If already initialized, return previous version information.
|
||||
@@ -133,7 +137,7 @@ function CreateIMRSDKWrapper() {
|
||||
}
|
||||
|
||||
// IMR_InitEx
|
||||
obj.InitEx = function(client) {
|
||||
obj.InitEx = function (client) {
|
||||
var version = new _IMRVersion();
|
||||
var callbacks = new _SockCallBacks();
|
||||
callbacks.OpenHandler = OpenHandlerCallBack;
|
||||
@@ -247,7 +251,10 @@ function CreateIMRSDKWrapper() {
|
||||
}
|
||||
|
||||
// IMR_IDERCloseSession
|
||||
obj.IDERCloseSessionAsync = function (client_id, func) { _IMRSDK.IMR_IDERCloseSession.async(client_id, func); }
|
||||
obj.IDERCloseSessionAsync = function (client_id, func) {
|
||||
//console.log('IDERCloseSessionAsync', client_id);
|
||||
_IMRSDK.IMR_IDERCloseSession.async(client_id, func);
|
||||
}
|
||||
|
||||
// IMR_IDERClientFeatureSupported
|
||||
obj.IDERClientFeatureSupported = function (client_id) {
|
||||
@@ -306,10 +313,12 @@ function CreateIMRSDKWrapper() {
|
||||
}
|
||||
|
||||
globalIderPendingCalls = 0;
|
||||
globalIderWrapper = null;
|
||||
globalIderClientId = null;
|
||||
|
||||
// Construct a Intel AMT IDER object
|
||||
var CreateAmtRemoteIderIMR = function () {
|
||||
if (globalIderPendingCalls != 0) { console.log('Incomplete IDER cleanup (' + globalIderPendingCalls + ').'); return null; } // IDER is not ready.
|
||||
if (globalIderPendingCalls != 0) { console.log('Incomplete IDER cleanup (A, ' + globalIderPendingCalls + ').'); return null; } // IDER is not ready.
|
||||
var _net = require('net');
|
||||
var _tls = require('tls');
|
||||
|
||||
@@ -360,10 +369,11 @@ var CreateAmtRemoteIderIMR = function () {
|
||||
try
|
||||
{
|
||||
if (obj.m.clientid !== undefined) {
|
||||
try { obj.m.imrsdk.IDERCloseSessionAsync(obj.m.clientid, function (error) { }); } catch (e) { }
|
||||
delete obj.m.clientid;
|
||||
try { obj.m.imrsdk.IDERCloseSessionAsync(obj.m.clientid, function (error) { console.log('IDERCloseSessionAsync-Response', error); }); } catch (e) { console.log(e); }
|
||||
//try { obj.m.imrsdk.RemoveClient(obj.m.clientid); } catch (e) { console.log(e); }
|
||||
//delete obj.m.clientid;
|
||||
}
|
||||
obj.m.imrsdk.Close(function (error) { });
|
||||
//obj.m.imrsdk.Close(function (error) { });
|
||||
} catch (e) { }
|
||||
delete obj.m.imrsdk;
|
||||
}
|
||||
@@ -414,7 +424,7 @@ var CreateAmtRemoteIderIMR = function () {
|
||||
}
|
||||
|
||||
function startIderSession(userConsentFunc) {
|
||||
if (globalIderPendingCalls != 0) { console.log('Incomplete IDER cleanup (' + globalIderPendingCalls + ').'); return; }
|
||||
if (globalIderPendingCalls != 0) { console.log('Incomplete IDER cleanup (B, ' + globalIderPendingCalls + ').'); return; }
|
||||
try {
|
||||
//console.log('IDER-Start');
|
||||
if (obj.m.xtlsoptions && obj.m.xtlsoptions.meshServerConnect) {
|
||||
@@ -452,18 +462,17 @@ var CreateAmtRemoteIderIMR = function () {
|
||||
|
||||
obj.m.client.on('data', function (data) {
|
||||
//console.log('IDER-RECV(' + data.length + ', ' + obj.receivedCount + '): ' + rstr2hex(data));
|
||||
|
||||
if (obj.m.imrsdk == null) { return; }
|
||||
if ((obj.m.imrsdk == null) || (obj.m.imrsdk.pendingData[obj.m.imrsdk.conID] == null)) { return; }
|
||||
|
||||
if ((obj.receivedCount == 0) && (data.charCodeAt(0) == 0x11) && (data.charCodeAt(1) == 0x05)) {
|
||||
// We got a user consent error, handle it now before IMRSDK.dll can get it.
|
||||
console.log('IDER user consent required.');
|
||||
obj.m.imrsdk.pendingData[obj.m.clientid] = String.fromCharCode(0x11, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); // Try to cause a fault.
|
||||
obj.m.imrsdk.ReadyReadSock(0, function (x, error) { });
|
||||
obj.m.imrsdk.pendingData[obj.m.imrsdk.conID] = String.fromCharCode(0x11, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); // Try to cause a fault.
|
||||
obj.m.imrsdk.ReadyReadSock(obj.m.imrsdk.conID, function (x, error) { });
|
||||
setTimeout(function () { obj.m.userConsentFunc(startIderSession); }, 500);
|
||||
} else {
|
||||
if (obj.m.imrsdk.pendingData[obj.m.clientid] == null) { obj.m.imrsdk.pendingData[obj.m.clientid] = data; } else { obj.m.imrsdk.pendingData[obj.m.clientid] += data; }
|
||||
obj.m.imrsdk.ReadyReadSock(0, function (x, error) { });
|
||||
obj.m.imrsdk.pendingData[obj.m.imrsdk.conID] += data;
|
||||
obj.m.imrsdk.ReadyReadSock(obj.m.imrsdk.conID, function (x, error) { });
|
||||
}
|
||||
obj.receivedCount += data.length;
|
||||
});
|
||||
@@ -483,15 +492,19 @@ var CreateAmtRemoteIderIMR = function () {
|
||||
try {
|
||||
//console.log('IDER-StartEx');
|
||||
obj.m.userConsentFunc = userConsentFunc;
|
||||
obj.m.imrsdk = CreateIMRSDKWrapper();
|
||||
obj.m.imrsdk.InitEx(obj.m.client);
|
||||
obj.m.imrsdk.RemoveAllClients();
|
||||
if (obj.m.amtcertpath) { obj.m.imrsdk.SetCertificateInfo(obj.m.amtcertpath, null, null); }
|
||||
obj.m.clientid = obj.m.imrsdk.AddClient(obj.m.tls + 1, obj.m.host);
|
||||
if (globalIderWrapper == null) {
|
||||
obj.m.imrsdk = globalIderWrapper = CreateIMRSDKWrapper();
|
||||
obj.m.imrsdk.InitEx(obj.m.client);
|
||||
if (obj.m.amtcertpath) { obj.m.imrsdk.SetCertificateInfo(obj.m.amtcertpath, null, null); }
|
||||
} else {
|
||||
obj.m.imrsdk = globalIderWrapper;
|
||||
obj.m.imrsdk.client = obj.m.client;
|
||||
}
|
||||
obj.m.clientid = globalIderClientId = obj.m.imrsdk.AddClient(obj.m.tls + 1, 'HOST' + Math.random());
|
||||
obj.m.imrsdk.pendingData[obj.m.clientid] = '';
|
||||
|
||||
globalIderPendingCalls++;
|
||||
//console.log('IDEROpenTCPSessionAsync-call');
|
||||
var error = obj.m.imrsdk.IDEROpenTCPSessionAsync(obj.m.clientid, obj.m.user, obj.m.pass, obj.m.imgpath, obj.m.isopath, function (error) {
|
||||
//console.log('IDEROpenTCPSessionAsync-callback(' + error + ')');
|
||||
globalIderPendingCalls--;
|
||||
if (obj.m.imrsdk == null) return; // We closed already, exit now.
|
||||
if ((error == 38) && (userConsentFunc != undefined)) { obj.m.Stop(); userConsentFunc(startIderSession); return; }
|
||||
@@ -510,7 +523,7 @@ var CreateAmtRemoteIderIMR = function () {
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
//console.log(e);
|
||||
console.log(e);
|
||||
obj.m.Stop();
|
||||
obj.m.onDialogPrompt(obj.m, { 'html': e }, 1);
|
||||
}
|
||||
|
||||
66
index.html
66
index.html
@@ -961,7 +961,9 @@
|
||||
<input id="idx_deskFocusBtn" type="button" title="Toggle focus mode, when active only the region around the mouse is updated" onkeypress="return false" onkeydown="return false" value="Focus All" onclick="deskToggleFocus()" style="margin-right:3px">
|
||||
<!-- ###END###{DesktopFocus} -->
|
||||
<!-- ###BEGIN###{FileSaver} -->
|
||||
<!-- ###BEGIN###{!DesktopRecorder} -->
|
||||
<input id="idx_deskSaveBtn" type="button" title="Save a screenshot of the remote desktop" onkeypress="return false" onkeydown="return false" value="Save..." onclick="deskSaveImage()" style="margin-right:3px">
|
||||
<!-- ###END###{!DesktopRecorder} -->
|
||||
<!-- ###END###{FileSaver} -->
|
||||
<input type="button" value="Settings..." title="Edit remote desktop settings" onkeypress="return false" onkeydown="return false" onclick="showDesktopSettings()" style="margin-right:3px">
|
||||
<!-- ###BEGIN###{IDER} -->
|
||||
@@ -1002,6 +1004,14 @@
|
||||
<input id="specialkeylistinput" type="button" onkeypress="return false" class="bottombutton" value="Send" onclick="sendSpecialKey()">
|
||||
</div>
|
||||
-->
|
||||
<!-- ###BEGIN###{FileSaver} -->
|
||||
<!-- ###BEGIN###{DesktopRecorder} -->
|
||||
<div id="id_DeskRecorderTools" style=float:right>
|
||||
<span id=DeskSaveImageButton title="Save a screenshot of the remote desktop"><img src='images-commander/icon-camera.png' onclick=deskSaveImage() height=16 width=16 style=padding-top:2px;padding-right:4px;cursor:pointer /></span>
|
||||
<span id=DeskRecordButton title="Record remote desktop session to file" style="padding-right:8px"><img id=DeskRecordButtonImage src='images-commander/icon-film.png' onclick=deskRecordSession() height=16 width=16 style=padding-top:2px;cursor:pointer /></span>
|
||||
</div>
|
||||
<!-- ###END###{DesktopRecorder} -->
|
||||
<!-- ###END###{FileSaver} -->
|
||||
<!-- ###BEGIN###{Desktop-Multi} -->
|
||||
<div id="id_DeskScreenSelector" style=float:right></div>
|
||||
<!-- ###END###{Desktop-Multi} -->
|
||||
@@ -1837,9 +1847,9 @@
|
||||
|
||||
// ###BEGIN###{FileSaver}
|
||||
// ###BEGIN###{Desktop}
|
||||
if (!Q('Desk')['toBlob']) { // On some browsers like IE, we can't save screen shots. Hide the scheenshot/capture buttons.
|
||||
QV('idx_deskSaveBtn', false);
|
||||
}
|
||||
// ###BEGIN###{!Mode-NodeWebkit}
|
||||
if (!Q('Desk')['toBlob']) { QV('idx_deskSaveBtn', false); }// On some browsers like IE, we can't save screen shots. Hide the sceeenshot/capture buttons.
|
||||
// ###END###{!Mode-NodeWebkit}
|
||||
// ###END###{Desktop}
|
||||
// ###END###{FileSaver}
|
||||
|
||||
@@ -1998,9 +2008,7 @@
|
||||
haltEvent(e);
|
||||
// ###BEGIN###{IDER}
|
||||
var diskimages = true;
|
||||
console.log(e.dataTransfer.files);
|
||||
for (var i = 0; i < e.dataTransfer.files.length; i++) {
|
||||
console.log(i, e.dataTransfer.files[i]);
|
||||
if ((e.dataTransfer.files[i].name.toLowerCase().endsWith('.img') == false) && (e.dataTransfer.files[i].name.toLowerCase().endsWith('.iso') == false)) { diskimages = false; }
|
||||
}
|
||||
if ((diskimages == true) && (e.dataTransfer != null) && (currentView > 0) && (currentView < 100) && ((e.dataTransfer.files.length == 1) || (e.dataTransfer.files.length == 2))) {
|
||||
@@ -8062,6 +8070,9 @@
|
||||
// ###END###{DesktopType}
|
||||
switch (state) {
|
||||
case 0:
|
||||
// ###BEGIN###{DesktopRecorder}
|
||||
if (desktop.m.recordedData != null) { deskRecordSession(); }
|
||||
// ###END###{DesktopRecorder}
|
||||
// desktop.m.ResetScreen();
|
||||
// ###BEGIN###{DesktopInband}
|
||||
webRtcDesktopReset();
|
||||
@@ -8287,27 +8298,42 @@
|
||||
}
|
||||
}
|
||||
|
||||
// ###BEGIN###{FileSaver}
|
||||
// ###BEGIN###{DesktopRecorder}
|
||||
// Toggle desktop session recording
|
||||
function deskRecordSession() {
|
||||
if (desktop == null) return;
|
||||
if (desktop.m.recordedData == null) {
|
||||
// Start recording
|
||||
if ((desktop.State === 3) && (desktop.m.StartRecording())) { Q('DeskRecordButtonImage').src = 'images-commander/icon-film-red.png'; }
|
||||
} else {
|
||||
// Stop recording
|
||||
Q('DeskRecordButtonImage').src = 'images-commander/icon-film.png';
|
||||
var d = new Date(), n = 'AmtDesktopSesion-' + currentcomputer['name'] + '-' + d.getFullYear() + '-' + ('0' + (d.getMonth() + 1)).slice(-2) + '-' + ('0' + d.getDate()).slice(-2) + '-' + ('0' + d.getHours()).slice(-2) + '-' + ('0' + d.getMinutes()).slice(-2);
|
||||
saveAs(data2blob(desktop.m.StopRecording().join('')), n + '.mcrec');
|
||||
}
|
||||
}
|
||||
// ###END###{DesktopRecorder}
|
||||
// ###END###{FileSaver}
|
||||
|
||||
// ###BEGIN###{FileSaver}
|
||||
// Save the desktop image to file
|
||||
function deskSaveImage() {
|
||||
if (xxdialogMode || desktop.State != 3) return;
|
||||
var n = 'Desktop', d = new Date();
|
||||
if (amtsysstate) { n += '-' + amtsysstate['AMT_GeneralSettings'].response['HostName']; }
|
||||
n += '-' + d.getFullYear() + '-' + ('0'+(d.getMonth()+1)).slice(-2) + '-' + ('0' + d.getDate()).slice(-2) + '-' + ('0' + d.getHours()).slice(-2) + '-' + ('0' + d.getMinutes()).slice(-2);
|
||||
Q('Desk')['toBlob'](
|
||||
function(blob) {
|
||||
// ###BEGIN###{!Mode-NodeWebkit}
|
||||
saveAs(blob, n + '.jpg');
|
||||
// ###END###{!Mode-NodeWebkit}
|
||||
// ###BEGIN###{Mode-NodeWebkit}
|
||||
var chooser = document.createElement('input');
|
||||
chooser.setAttribute('type', 'file');
|
||||
chooser.setAttribute('nwsaveas', n + '.jpg');
|
||||
chooser.addEventListener('change', function () { require('fs').writeFile(this.value, blob, function () { }); }, false);
|
||||
chooser.click();
|
||||
// ###END###{Mode-NodeWebkit}
|
||||
}
|
||||
);
|
||||
n += '-' + d.getFullYear() + '-' + ('0' + (d.getMonth() + 1)).slice(-2) + '-' + ('0' + d.getDate()).slice(-2) + '-' + ('0' + d.getHours()).slice(-2) + '-' + ('0' + d.getMinutes()).slice(-2);
|
||||
// ###BEGIN###{!Mode-NodeWebkit}
|
||||
Q('Desk')['toBlob']( function (blob) { saveAs(blob, n + '.jpg'); } );
|
||||
// ###END###{!Mode-NodeWebkit}
|
||||
// ###BEGIN###{Mode-NodeWebkit}
|
||||
var b64image = document.getElementById('Desk').toDataURL('image/png').split(',')[1];
|
||||
var chooser = document.createElement('input');
|
||||
chooser.setAttribute('type', 'file');
|
||||
chooser.setAttribute('nwsaveas', n + '.png');
|
||||
chooser.addEventListener('change', function () { console.log('cc'); require('fs').writeFile(this.value, b64image, 'base64', function () { }); }, false);
|
||||
chooser.click();
|
||||
// ###END###{Mode-NodeWebkit}
|
||||
}
|
||||
// ###END###{FileSaver}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user