Issue
Code backup
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,508 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()"
|
||||
preinitialize="presetup()"
|
||||
width="250" height="150"
|
||||
xmlns:local="*">
|
||||
<mx:Script>
|
||||
<![CDATA[
|
||||
|
||||
import flash.external.*;
|
||||
import flash.net.NetConnection;
|
||||
import flash.net.NetStream;
|
||||
import mx.utils.ObjectUtil;
|
||||
import mx.core.FlexGlobals;
|
||||
import flash.system.Security;
|
||||
import flash.system.SecurityPanel;
|
||||
import flash.media.*;
|
||||
import com.adobe.crypto.MD5;
|
||||
import com.adobe.serialization.json.JSON;
|
||||
|
||||
[Bindable]
|
||||
public var netConnection:NetConnection = null;
|
||||
private var incomingNetStream:NetStream = null;
|
||||
private var outgoingNetStream:NetStream = null;
|
||||
private var mic:Microphone = null;
|
||||
[Bindable] private var microphoneList:Array;
|
||||
private var sessionid:String;
|
||||
private var auth_user:String;
|
||||
private var auth_domain:String;
|
||||
private var mic_index:int = -1;
|
||||
|
||||
private var attachedUUID:String = "";
|
||||
|
||||
[Embed(source="Sound_of_phone_ringing2.mp3")]
|
||||
[Bindable]
|
||||
private var soundOfPhoneRinging_MP3:Class;
|
||||
private var ringChannel:SoundChannel = null;
|
||||
private var ringUUID:String = "";
|
||||
private var soundOfPhoneRinging:Sound;
|
||||
|
||||
|
||||
public function presetup():void
|
||||
{
|
||||
/* Load config here */
|
||||
soundOfPhoneRinging = new soundOfPhoneRinging_MP3();
|
||||
}
|
||||
|
||||
/********* JavaScript functions *********/
|
||||
public function makeCall(number:String, account:String, evt:Object):void {
|
||||
if (netConnection != null) {
|
||||
if (incomingNetStream == null) {
|
||||
setupStreams();
|
||||
}
|
||||
netConnection.call("makeCall", null, number, account, evt);
|
||||
}
|
||||
}
|
||||
|
||||
public function sendDTMF(digits:String, duration:int):void {
|
||||
if (netConnection != null) {
|
||||
netConnection.call("sendDTMF", null, digits, duration);
|
||||
}
|
||||
}
|
||||
|
||||
public function answer(uuid:String):void {
|
||||
if (ringChannel != null) {
|
||||
ringChannel.stop();
|
||||
ringChannel = null;
|
||||
}
|
||||
if (incomingNetStream == null) {
|
||||
setupStreams();
|
||||
}
|
||||
if (netConnection != null) {
|
||||
netConnection.call("answer", null, uuid);
|
||||
}
|
||||
}
|
||||
|
||||
public function hangup(uuid:String):void {
|
||||
if (uuid == attachedUUID) {
|
||||
destroyStreams();
|
||||
}
|
||||
if (netConnection != null) {
|
||||
netConnection.call("hangup", null, uuid);
|
||||
}
|
||||
}
|
||||
|
||||
public function register(account:String, nickname:String):void {
|
||||
if (netConnection != null) {
|
||||
netConnection.call("register", null, account, nickname);
|
||||
}
|
||||
}
|
||||
|
||||
public function unregister(account:String, nickname:String):void {
|
||||
if (netConnection != null) {
|
||||
netConnection.call("unregister", null, account, nickname);
|
||||
}
|
||||
}
|
||||
|
||||
public function attach(uuid:String):void {
|
||||
if (netConnection != null) {
|
||||
netConnection.call("attach", null, uuid);
|
||||
}
|
||||
}
|
||||
|
||||
public function transfer(uuid:String, number:String):void {
|
||||
if (netConnection != null) {
|
||||
netConnection.call("transfer", null, uuid, number);
|
||||
}
|
||||
}
|
||||
|
||||
public function three_way(uuid1:String, uuid2:String):void {
|
||||
if (netConnection != null) {
|
||||
netConnection.call("three_way", null, uuid1, uuid2);
|
||||
}
|
||||
}
|
||||
|
||||
public function join(uuid1:String, uuid2:String):void {
|
||||
if (netConnection != null) {
|
||||
netConnection.call("join", null, uuid1, uuid2);
|
||||
}
|
||||
}
|
||||
|
||||
public function sendevent(data:Object):void {
|
||||
if (netConnection != null) {
|
||||
netConnection.call("sendevent", null, data);
|
||||
}
|
||||
}
|
||||
|
||||
public function getMic():int {
|
||||
return mic_index;
|
||||
}
|
||||
|
||||
public function micList():Object {
|
||||
return JSON.encode(microphoneList);
|
||||
}
|
||||
|
||||
public function setMic(index:int):void {
|
||||
mic_index = index;
|
||||
setupMic();
|
||||
}
|
||||
|
||||
public function isMuted():Boolean {
|
||||
if (mic != null) {
|
||||
return mic.muted;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function showPrivacy():void {
|
||||
Security.showSettings(SecurityPanel.PRIVACY);
|
||||
}
|
||||
|
||||
public function login(username:String, password:String):void {
|
||||
if (netConnection != null) {
|
||||
netConnection.call("login", null, username, MD5.hash(sessionid + ":" + username + ":" + password));
|
||||
}
|
||||
}
|
||||
|
||||
public function logout(account:String):void {
|
||||
if (netConnection != null) {
|
||||
netConnection.call("logout", null, account);
|
||||
}
|
||||
}
|
||||
|
||||
public function setVolume(value:Number):void {
|
||||
if (incomingNetStream != null) {
|
||||
var st:SoundTransform = new SoundTransform(value);
|
||||
incomingNetStream.soundTransform = st;
|
||||
}
|
||||
}
|
||||
|
||||
public function setMicVolume(value:Number):void {
|
||||
if (outgoingNetStream != null) {
|
||||
var st:SoundTransform = new SoundTransform(value);
|
||||
outgoingNetStream.soundTransform = st;
|
||||
}
|
||||
}
|
||||
|
||||
/********* FreeSWITCH functions *********/
|
||||
/* XXX: TODO: Move those in a separate object so a malicious server can't setup streams and spy on the user */
|
||||
public function connected(sid:String):void{
|
||||
sessionid = sid;
|
||||
|
||||
if (ExternalInterface.available) {
|
||||
ExternalInterface.call("onConnected", sid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function onHangup(uuid:String, cause:String):void {
|
||||
if (ringUUID == uuid && ringChannel != null) {
|
||||
ringChannel.stop();
|
||||
ringChannel = null;
|
||||
}
|
||||
if (ExternalInterface.available) {
|
||||
ExternalInterface.call("onHangup", uuid, cause);
|
||||
}
|
||||
}
|
||||
|
||||
public function onLogin(result:String, user:String, domain:String):void {
|
||||
if (result == "success") {
|
||||
auth_user = user;
|
||||
auth_domain = domain;
|
||||
}
|
||||
if (ExternalInterface.available) {
|
||||
ExternalInterface.call("onLogin", result, user, domain);
|
||||
}
|
||||
}
|
||||
|
||||
public function onLogout(user:String, domain:String):void {
|
||||
if (ExternalInterface.available) {
|
||||
ExternalInterface.call("onLogout", user, domain);
|
||||
}
|
||||
}
|
||||
|
||||
public function onAttach(uuid:String):void {
|
||||
attachedUUID = uuid;
|
||||
|
||||
if (ringChannel != null && uuid != "") {
|
||||
ringChannel.stop();
|
||||
ringChannel = null;
|
||||
}
|
||||
|
||||
if (attachedUUID == "") {
|
||||
destroyStreams();
|
||||
} else if (incomingNetStream == null || outgoingNetStream == null) {
|
||||
setupStreams();
|
||||
}
|
||||
if (ExternalInterface.available) {
|
||||
ExternalInterface.call("onAttach", uuid);
|
||||
}
|
||||
}
|
||||
|
||||
public function onMakeCall(uuid:String, number:String, account:String):void {
|
||||
if (ExternalInterface.available) {
|
||||
ExternalInterface.call("onMakeCall", uuid, number, account);
|
||||
}
|
||||
}
|
||||
|
||||
public function callState(uuid:String, state:String):void {
|
||||
if (ExternalInterface.available) {
|
||||
ExternalInterface.call("onCallState", uuid, state);
|
||||
}
|
||||
}
|
||||
|
||||
public function displayUpdate(uuid:String, name:String, number:String):void {
|
||||
if (ExternalInterface.available) {
|
||||
ExternalInterface.call("onDisplayUpdate", uuid, name, number);
|
||||
}
|
||||
}
|
||||
|
||||
public function incomingCall(uuid:String, name:String, number:String, account:String, evt:Object):void {
|
||||
if (attachedUUID == "" && ringChannel == null) {
|
||||
ringUUID = uuid;
|
||||
ringChannel = soundOfPhoneRinging.play(0, 3);
|
||||
}
|
||||
|
||||
if (evt != null) {
|
||||
if (evt.hasOwnProperty("rtmp_auto_answer")) {
|
||||
if (evt.rtmp_auto_answer == "true") {
|
||||
answer(uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ExternalInterface.available) {
|
||||
ExternalInterface.call("onIncomingCall", uuid, name, number, account, evt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function event(event:Object):void {
|
||||
if (ExternalInterface.available) {
|
||||
ExternalInterface.call("onEvent", JSON.encode(event));
|
||||
}
|
||||
}
|
||||
|
||||
/********* Internal functions *********/
|
||||
private function onDebug(message:String):void {
|
||||
//statusTxt.text = (statusTxt.text != "") ? statusTxt.text + "\n" + message : message;
|
||||
if (ExternalInterface.available) {
|
||||
ExternalInterface.call("onDebug", message);
|
||||
}
|
||||
}
|
||||
|
||||
private function init():void
|
||||
{
|
||||
NetConnection.defaultObjectEncoding = ObjectEncoding.AMF0;
|
||||
|
||||
try {
|
||||
Security.allowDomain("*");
|
||||
} catch(e:Error) {
|
||||
onDebug("Exception: " + e.toString());
|
||||
}
|
||||
|
||||
if (ExternalInterface.available) {
|
||||
try {
|
||||
ExternalInterface.marshallExceptions = true;
|
||||
ExternalInterface.addCallback("login", this.login);
|
||||
ExternalInterface.addCallback("logout", this.logout);
|
||||
ExternalInterface.addCallback("makeCall", this.makeCall);
|
||||
ExternalInterface.addCallback("attach", this.attach);
|
||||
ExternalInterface.addCallback("answer", this.answer);
|
||||
ExternalInterface.addCallback("hangup", this.hangup);
|
||||
ExternalInterface.addCallback("sendDTMF", this.sendDTMF);
|
||||
ExternalInterface.addCallback("register", this.register);
|
||||
ExternalInterface.addCallback("unregister", this.unregister);
|
||||
ExternalInterface.addCallback("transfer", this.transfer);
|
||||
ExternalInterface.addCallback("three_way", this.three_way);
|
||||
ExternalInterface.addCallback("getMic", this.getMic);
|
||||
ExternalInterface.addCallback("micList", this.micList);
|
||||
ExternalInterface.addCallback("setMic", this.setMic);
|
||||
ExternalInterface.addCallback("isMuted", this.isMuted);
|
||||
ExternalInterface.addCallback("showPrivacy", this.showPrivacy);
|
||||
ExternalInterface.addCallback("connect", this.connect);
|
||||
ExternalInterface.addCallback("disconnect", this.disconnect);
|
||||
ExternalInterface.addCallback("join", this.join);
|
||||
ExternalInterface.addCallback("sendevent", this.sendevent);
|
||||
ExternalInterface.addCallback("setVolume", this.setVolume);
|
||||
ExternalInterface.addCallback("setMicVolume", this.setMicVolume);
|
||||
//txtStatus.text = "Connecting...";
|
||||
} catch(e:Error) {
|
||||
//txtStatus.text = e.toString();
|
||||
onDebug("Exception: " + e.toString());
|
||||
}
|
||||
} else {
|
||||
onDebug("ExternalInterface is disabled");
|
||||
}
|
||||
|
||||
try {
|
||||
microphoneList = Microphone.names;
|
||||
setupMic();
|
||||
connect();
|
||||
} catch(e:Error) {
|
||||
onDebug("Exception: " + e.toString());
|
||||
}
|
||||
|
||||
if (ExternalInterface.available) {
|
||||
ExternalInterface.call("onInit");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function connect():void{
|
||||
if (netConnection != null) {
|
||||
disconnect();
|
||||
}
|
||||
|
||||
netConnection = new NetConnection();
|
||||
netConnection.client = this;
|
||||
netConnection.addEventListener( NetStatusEvent.NET_STATUS , netStatus );
|
||||
netConnection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
|
||||
netConnection.connect(FlexGlobals.topLevelApplication.parameters.rtmp_url);
|
||||
}
|
||||
|
||||
public function disconnect():void {
|
||||
if (netConnection != null) {
|
||||
netConnection.close();
|
||||
netConnection = null;
|
||||
incomingNetStream = null;
|
||||
outgoingNetStream = null;
|
||||
}
|
||||
}
|
||||
|
||||
private function destroyStreams():void {
|
||||
if (outgoingNetStream != null) {
|
||||
onDebug("Closing media streams")
|
||||
outgoingNetStream.close();
|
||||
outgoingNetStream = null;
|
||||
}
|
||||
if (incomingNetStream != null) {
|
||||
incomingNetStream.close();
|
||||
incomingNetStream = null;
|
||||
}
|
||||
}
|
||||
|
||||
private function setupMic():void {
|
||||
try {
|
||||
mic = Microphone.getMicrophone(mic_index);
|
||||
mic.addEventListener(ActivityEvent.ACTIVITY, activityHandler);
|
||||
mic.addEventListener(StatusEvent.STATUS, statusHandler);
|
||||
mic.codec = SoundCodec.SPEEX;
|
||||
mic.setUseEchoSuppression(true);
|
||||
mic.setLoopBack(false);
|
||||
mic.setSilenceLevel(0,20000);
|
||||
mic.framesPerPacket = 1;
|
||||
mic.gain = 55;
|
||||
mic.rate = 16;
|
||||
mic_index = mic.index;
|
||||
|
||||
if (outgoingNetStream != null) {
|
||||
outgoingNetStream.close();
|
||||
outgoingNetStream = new NetStream(netConnection);
|
||||
outgoingNetStream.addEventListener(NetStatusEvent.NET_STATUS, netStatus);
|
||||
outgoingNetStream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
|
||||
outgoingNetStream.attachAudio(mic);
|
||||
outgoingNetStream.publish("publish", "live");
|
||||
}
|
||||
} catch(e:Error) {
|
||||
onDebug("Couldn't setup microphone: " + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
private function setupStreams():void {
|
||||
onDebug("Setup media streams");
|
||||
|
||||
if (mic == null || mic.index != mic_index) {
|
||||
setupMic();
|
||||
}
|
||||
|
||||
incomingNetStream = new NetStream(netConnection);
|
||||
incomingNetStream.addEventListener(NetStatusEvent.NET_STATUS, netStatus);
|
||||
incomingNetStream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
|
||||
incomingNetStream.client = this;
|
||||
incomingNetStream.bufferTime = 0.2;
|
||||
incomingNetStream.play("play");
|
||||
incomingNetStream.receiveAudio(true);
|
||||
|
||||
outgoingNetStream = new NetStream(netConnection);
|
||||
outgoingNetStream.addEventListener(NetStatusEvent.NET_STATUS, netStatus);
|
||||
outgoingNetStream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
|
||||
outgoingNetStream.attachAudio(mic);
|
||||
outgoingNetStream.publish("publish", "live");
|
||||
}
|
||||
|
||||
private function onDisconnected():void {
|
||||
if (ExternalInterface.available) {
|
||||
ExternalInterface.call("onDisconnected");
|
||||
}
|
||||
}
|
||||
|
||||
private function securityErrorHandler(event:SecurityErrorEvent):void {
|
||||
onDebug("securityErrorHandler: " + event.text);
|
||||
}
|
||||
|
||||
private function asyncErrorHandler(event:AsyncErrorEvent):void {
|
||||
onDebug("asyncErrorHandler: " + event.text);
|
||||
}
|
||||
|
||||
private function activityHandler(event:ActivityEvent):void {
|
||||
onDebug("activityHandler: " + event);
|
||||
}
|
||||
|
||||
private function statusHandler(event:StatusEvent):void {
|
||||
onDebug("statusHandler: " + event);
|
||||
}
|
||||
|
||||
private function netStatus (evt:NetStatusEvent ):void {
|
||||
|
||||
onDebug("netStatus: " + evt.info.code);
|
||||
|
||||
switch(evt.info.code) {
|
||||
|
||||
case "NetConnection.Connect.Success":
|
||||
//txtStatus.text = "Connected";
|
||||
break;
|
||||
|
||||
case "NetConnection.Connect.Failed":
|
||||
netConnection = null;
|
||||
incomingNetStream = null;
|
||||
outgoingNetStream = null;
|
||||
//btnCall.label = "Connect";
|
||||
//txtStatus.text = "Failed";
|
||||
onDisconnected();
|
||||
break;
|
||||
|
||||
case "NetConnection.Connect.Closed":
|
||||
netConnection = null;
|
||||
incomingNetStream = null;
|
||||
outgoingNetStream = null;
|
||||
//btnCall.label = "Connect";
|
||||
//txtStatus.text = "Disconnected";
|
||||
onDisconnected();
|
||||
break;
|
||||
|
||||
case "NetConnection.Connect.Rejected":
|
||||
netConnection = null;
|
||||
incomingNetStream = null;
|
||||
outgoingNetStream = null;
|
||||
//btnCall.label = "Connect";
|
||||
//txtStatus.text = "Rejected";
|
||||
onDisconnected();
|
||||
break;
|
||||
|
||||
case "NetStream.Play.StreamNotFound":
|
||||
break;
|
||||
|
||||
case "NetStream.Play.Failed":
|
||||
break;
|
||||
|
||||
case "NetStream.Play.Start":
|
||||
break;
|
||||
|
||||
case "NetStream.Play.Stop":
|
||||
break;
|
||||
|
||||
case "NetStream.Buffer.Full":
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
}
|
||||
}
|
||||
]]>
|
||||
</mx:Script>
|
||||
<!--<mx:Panel id="reader" title="Test" width="500">
|
||||
<mx:TextArea width="500" color="#FF0000" id="statusTxt"/>
|
||||
</mx:Panel>-->
|
||||
</mx:Application>
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,31 @@
|
||||
|
||||
These are optional modules for the webphone and java SDK.
|
||||
Just copy these files near the jar (so extract the files from this mediaench directory and copy them near the webphone.jar or JVoIP.jar)
|
||||
|
||||
|
||||
DETAILS:
|
||||
|
||||
The webphone/JVoIP will work fine also without these files, but having them accessible might increase the voice quality and will add some more audio codec (but most codec's are implemented in pure java).
|
||||
The files should be stored near the main jar file (on local file system or on your web server) and you might have to enable the dll, so and dylib mime type on your web server if used in a web project (or set the "mediaenchext" applet parameter to "jar" and rename dll with jar in file name extensions). If the files cannot be found or loaded than the webphone will just not use these features or will failback to pure java code and it will remain fully functional.
|
||||
When served from a webserver, the webphone will download one of these libraries only at the first usage. Subsequent usage will be served from the browser local cache.
|
||||
|
||||
|
||||
TODO:
|
||||
|
||||
1. Deploy
|
||||
Unpack the mediaench.zip and copy the files near your webphone.jar or JVoIP.jar
|
||||
|
||||
2. Enable mime types
|
||||
Make sure that your web server allows the download of these resource types by allowing/adding the following mime types to your webserver configuration if not already added/allowed:
|
||||
• extension: .dll MIME type: application/x-msdownload (or application/x-msdownload)
|
||||
• extension: .jar MIME type: application/java-archive
|
||||
• extension: .jnilib MIME type: application/java-archive
|
||||
• extension: .so MIME type: application/octet-stream
|
||||
• extension: .dylib MIME type: application/octet-stream
|
||||
|
||||
3. Test
|
||||
In case if you are using the webphone, test the files availability by trying to download the files from your browsers.
|
||||
For example you should be able to download the mediaench.dll by entering it's exact URL in your browser:
|
||||
http:\\yourdomain.com\path_to_webphone\mediaench.dll
|
||||
If the browser doesn't initiate the file download (or displays an error) then you either typed the url incorrectly or your web server doesn't allow the .dll mime type.
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user