package { import flash.display.*; import flash.net.*; import flash.events.*; import flash.desktop.*; import flash.errors.*; import flash.system.*; 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.connect("localhost", port); } catch (e) { Trace("Error establishing wrapper connection"); } } 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) { var job:Job = new Job(jobParams); jobQueue.push(job); 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 { Trace("recv: " + typeof(cmdData) + " " + cmdData + " " + cmdData.hasOwnProperty("command")); 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: " + JSON.stringify(cmdData)); break; } } } catch (e) { Print(e.toString()); } } private function DriverRecv(e) { Trace("recv"); try { Trace(e.target.bytesAvailable); var msg = driver.readUTF(); Trace("msg: " + msg); Trace("avail: " + e.target.bytesAvailable); var cmdData = JSON.parse(msg); Trace("cmdData: " + cmdData + " " + typeof(cmdData)); DispatchCommand(cmdData); } catch (eof:EOFError) { Trace("Waiting for more data... " + e.target.bytesAvailable); // wait for more data } catch (err:IOError) { Trace("Driver IO error"); } catch (err) { Trace("Problem reading from driver"); } } 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:String) { 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}); } } } }