Background
The same touch-screen kiosk I previously wrote about requires phone dialing capabilities since the purpose it serves is a Building Directory in the lobby of a government office building.I used MDM Zinc because I can retain all source code in Actionscript (Flash), yet utilize the computer's modem to dial phone numbers via the Zinc COMPort API (whose phone numbers are retrieved from an MS SQL database via Zinc's ODBC API).
At the start of this project while evaluating Zinc as an option, the first thing I did was create a phone dialer prototype using Flash and Zinc to prove it would work. It worked perfectly. But when integrating it into the system at the tail end of the project and adding some robustness to it, I ran into a hitch that caused the Zinc-compiled application to crash.
Problem
In order to gracefully recover should the modem throw a "No Carrier" or "No Dialtone" error, I wanted to hang-up the line then alert the user of this error. However, when invoking the hang-up immediately when Flash is asynchronously notified, the Zinc-compiled application freezes indefinitely.Example
Part of the constructor of my PhoneDialer AS3 class
mdm.COMPort.onCOMPortData = function(e:Object)
{
var data:String = StringUtil.trim(e.data);
logger.logLine("onCOMPortData() - timeCode: " +
e.timeCode + ", data: " + data + ".");
if (data == "NO CARRIER")
{
hangUp(); //freezes here
dispatchEvent(new PhoneDialerEvent(
PhoneDialerEvent.NO_CARRIER));
}
else if (data == "NO DIALTONE")
{
hangUp(); //freezes here
dispatchEvent(new PhoneDialerEvent(
PhoneDialerEvent.NO_DIALTONE));
}
else if (data == "OK")
{
//Dial was successful!
dispatchEvent(new PhoneDialerEvent(
PhoneDialerEvent.OK));
}
};
{
var data:String = StringUtil.trim(e.data);
logger.logLine("onCOMPortData() - timeCode: " +
e.timeCode + ", data: " + data + ".");
if (data == "NO CARRIER")
{
hangUp(); //freezes here
dispatchEvent(new PhoneDialerEvent(
PhoneDialerEvent.NO_CARRIER));
}
else if (data == "NO DIALTONE")
{
hangUp(); //freezes here
dispatchEvent(new PhoneDialerEvent(
PhoneDialerEvent.NO_DIALTONE));
}
else if (data == "OK")
{
//Dial was successful!
dispatchEvent(new PhoneDialerEvent(
PhoneDialerEvent.OK));
}
};
Method in my PhoneDialer class:
public function hangUp()
{
if (!pickedUp)
throw new AlreadyHungUpException();
logger.logLine("Closing COMPort.");
mdm.COMPort.close(); //actually freezes here
pickedUp = false;
}
{
if (!pickedUp)
throw new AlreadyHungUpException();
logger.logLine("Closing COMPort.");
mdm.COMPort.close(); //actually freezes here
pickedUp = false;
}
Solution
The solution was to not invoke mdm.COMPort.close() within the onCOMPortData handler. Instead, I alert the user of the error which also instructs him/her to click the Cancel button on the Dialing screen. Then the cancel button invokes hangUp(), which works without a hitch.Also one other item of interest: even though Zinc was designed to support Actionscirpt 3, the first line of code above, mdm.COMPort.onCOMPortData = fuction(... triggers a warning when compiling to SWF - "Warning: 1072: Migration issue: Class is not a dynamic class. Instances cannot have members added to them dynamically." Since this is just a warning, it does not cause any problems during run-time, but it's interesting that they did not switch to use the standard addEventListener method of event-handling that has been implemented as a standard across AS3 components.