package { import flash.display.*; import flash.net.*; import flash.events.*; import flash.desktop.*; import flash.errors.*; import flash.system.*; import flash.utils.*; import by.blooddy.crypto.*; public class Exporter extends MovieClip { public static var Instance:Exporter = null; public static var DefaultPort:int = 7890; private var driver:Socket = null; public function Exporter() { Instance = this; try { NativeApplication.nativeApplication.addEventListener("invoke", ApplicationInvoked); } catch (e) { // not an air runtime app ConnectDriver(DefaultPort); // try default port } } public function ApplicationInvoked(e) { if (e.arguments.length == 1) { ConnectDriver(parseInt(e.arguments[0])); } else { ConnectDriver(DefaultPort); } } private function ConnectDriver(port) { Trace("Attempting to connect to driver"); try { var s:Socket = new Socket(); s.addEventListener(IOErrorEvent.IO_ERROR, DriverError); s.addEventListener(Event.CONNECT, DriverConnected); s.addEventListener(Event.CLOSE, DriverClosed); s.connect("localhost", port); } catch (e) { Trace("Error establishing wrapper connection"); } } private function DriverClosed(e) { Quit(); } private function DriverError(e) { Trace(" Failed to connect"); } private function DriverConnected(e) { Trace(" Connected"); driver = e.target as Socket; driver.addEventListener(ProgressEvent.SOCKET_DATA, DriverRecv); } private function Quit() { fscommand("quit"); try { NativeApplication.nativeApplication.exit(); } catch (e) { } } private var jobQueue:Array = new Array(); private var activeJob:Job = null; private function QueueJob(jobParams) { if (!jobParams.hasOwnProperty("id")) { Print("Failure: job details didn't contain job id"); CheckNewJob(); return; } var id:int = parseInt(jobParams.id); if (!jobParams.hasOwnProperty("graphics") || getQualifiedClassName(jobParams.graphics) != "Array") { Print("Failure: job " + id + " details didn't contain graphics array"); JobFailed(id); return; } var graphicsDetails:Array = jobParams.graphics; delete jobParams.command; delete jobParams.id; delete jobParams.graphics; var job:Job = new Job(id, graphicsDetails); jobQueue.push(job); CheckNewJob(); } private function JobFailed(id:int) { DriverCommand("done", {id:id}); CheckNewJob(); } private function CheckNewJob() { if (activeJob == null && jobQueue.length > 0) { activeJob = jobQueue.shift(); activeJob.Go(JobComplete); } } private function JobComplete() { Trace("Done: " + activeJob.GetID()); DriverCommand("done", activeJob.GetCompletedData()); activeJob = null; CheckNewJob(); } private function DispatchCommand(cmdData) { try { if (cmdData.hasOwnProperty("command")) { var cmd = "" + cmdData.command; //Trace("cmd: " + cmd); switch (cmd) { case "trace": Trace(cmdData.string); break; case "exit": Quit(); break; case "job": QueueJob(cmdData); break; default: Trace("Recv unknown: " + JSON.stringify(cmdData)); break; } } } catch (e) { Print(e.getStackTrace()); } } private var buffer:ByteArray = new ByteArray(); private var swpBuffer:ByteArray = new ByteArray(); private function DriverRecv(e) { var oldPos = buffer.position; //Trace("recv"); try { driver.readBytes(buffer, buffer.length, driver.bytesAvailable); //Trace(buffer.length - buffer.position); var msg = buffer.readUTF(); buffer.readBytes(swpBuffer); buffer.clear(); var tmp = buffer; buffer = swpBuffer; swpBuffer = tmp; var cmdData = JSON.parse(msg); DispatchCommand(cmdData); } catch (eof:EOFError) { buffer.position = oldPos; //Trace("Waiting for more data... " + driver.bytesAvailable + " " + (buffer.length - buffer.position)); // wait for more data } catch (err:IOError) { Trace("Driver IO error"); } catch (err) { Trace("Problem reading from driver:\n" + err.toString()); } } private function DriverCommand(cmd:String, data = null) { var obj = {command:cmd}; if (data != null) { for (var k in data) { obj[k] = data[k]; } } DriverSend(JSON.stringify(obj)); } private function DriverSend(str:String) { if (driver != null) { Trace(str); driver.writeUTF(str); driver.flush(); } } public function Trace(str) { str = "" + str; traceText.x = 2; trace(str); traceText.width = stage.stageWidth - 4; traceText.height = stage.stageHeight - 4; if (traceText.text == "") { traceText.text = str; } else { traceText.appendText("\n" + str); } traceText.y = stage.height - traceText.textHeight - 2; } public function Print(str:String, localTrace:Boolean = true) { if (localTrace || driver == null) { Trace(str); } else { trace(str); } if (driver != null) { DriverCommand("print", {string:str + "\n"}); } } } }