I've been trying to get a simple audio conference application up using SFS2X and Redbox.
I followed the given instructions in setting up Red5 and SFS2X and also ran the examples to test the setup. Everything up till that step was fine.
But, when I tried to run the code I wrote following the overview steps given for the video conference example :
1)The user joins the room where the video conference takes place.
2)The list of currently available streams (or "live casts") is retrieved by means of the AVCastManager.getAvailableCasts method (in case the conference is already in progress).
3)Calling this method also enables the reception of the RedBoxCastEvent.LIVE_CAST_PUBLISHED and RedBoxCastEvent.LIVE_CAST_UNPUBLISHED events which notify if another user started or stopped his own stream respectively.
4)Each live cast is subscribed by means of the AVCastManager.subscribeLiveCast method and a Video object is displayedin the main panel to attach the stream to.
5)When a live cast is published (a new user joins the conference) or stopped (a user leaves the conference – see below), a notification is received by means of the events mentioned above: the stream is subscribed / unsubscribed and displayed on / removed from the stage.
6)The a/v stream of the current user is published using the AVCastManager.publishLiveCast method and an additional Video object showing his own camera stream is added to the stage; when the user publishes his own stream, the other users receive the mentioned events.
7)To make the user leave the conference and stop the a/v stream, the AVCastManager.unpublishLiveCast method is called. Also changing Roomor disconnecting from the server cause the user to leave the conference and the other users to be notified.
Code:
Code: Select all
package
{
//import base.*;
import com.smartfoxserver.v2.entities.data.ISFSObject;
import com.smartfoxserver.v2.redbox.AVCastManager;
import com.smartfoxserver.v2.redbox.AVChatManager;
import com.smartfoxserver.v2.redbox.data.LiveCast;
import com.smartfoxserver.v2.redbox.events.RedBoxConnectionEvent;
import com.smartfoxserver.v2.redbox.events.RedBoxCastEvent;
import com.smartfoxserver.v2.requests.ExtensionRequest;
import com.smartfoxserver.v2.requests.LoginRequest;
import com.smartfoxserver.v2.redbox.exceptions.*;
import fl.controls.Button;
import flare.basic.*;
import flare.core.*;
import flare.loaders.*;
import flare.system.*;
import flash.display.*;
import flash.events.*;
import flare.collisions.*;
import flash.geom.*;
import com.smartfoxserver.v2.SmartFox;
import com.smartfoxserver.v2.core.BaseEvent;
import com.smartfoxserver.v2.core.SFSEvent;
import flash.net.NetStream;
import flash.utils.Dictionary;
import INetworkManagerListener;
[SWF(frameRate=60,width=1024,height=576,backgroundColor=0x000000)]
public class NetworkManager
{
public var m_strIP:String = "127.0.0.1";
public var m_iPort:int = 9933;
public var m_strUserName:String = "";
public var m_strPwd:String = "";
public var m_strZoneName:String = "";
private var m_listener:INetworkManagerListener;
private var m_commandMappings:Dictionary = new Dictionary();
public function SetListener(a_listener:INetworkManagerListener):void
{
m_listener = a_listener;
}
private var m_connection:SmartFox;
public function NetworkManager()
{
m_connection = new SmartFox();
m_connection.addEventListener(SFSEvent.CONNECTION, OnCONNECTION);
m_connection.addEventListener(SFSEvent.CONNECTION_LOST, OnCONNECTIONLOST);
m_connection.addEventListener(SFSEvent.LOGIN, OnLOGIN);
m_connection.addEventListener(SFSEvent.LOGIN_ERROR, OnLOGINERROR);
m_connection.addEventListener(SFSEvent.EXTENSION_RESPONSE, OnEXTENSIONRESPONCE);
m_connection.addEventListener(SFSEvent.ROOM_JOIN, OnJoinRoom);
}
private function OnCONNECTION(evt:BaseEvent):void
{
trace("in OnCONNECTION");
var success:Boolean = evt.params["success"] as Boolean;
if (m_listener)
{
m_listener.OnConnection("", "", success);
}
}
private function OnCONNECTIONLOST(evt:BaseEvent):void
{
if (m_listener)
{
m_listener.OnConnectionLost();
}
}
private function OnLOGIN(evt:BaseEvent):void
{
if (m_listener)
{
m_listener.OnLogin();
}
initializeAV();
}
private var avCastMan:AVCastManager;
/**
* Initialize the AVChatManager instance.
*/
private function initializeAV():void
{
// Create AVChatmanager instance
trace( "Connecting AVcast manager to ip : " + m_connection.currentIp);
avCastMan = new AVCastManager(m_connection, m_connection.currentIp, true, true);
avCastMan.addEventListener(RedBoxConnectionEvent.AV_CONNECTION_INITIALIZED, onAVConnectionInited);
avCastMan.addEventListener(RedBoxConnectionEvent.AV_CONNECTION_ERROR, onAVConnectionError);
avCastMan.addEventListener(RedBoxCastEvent.LIVE_CAST_PUBLISHED, onLiveCastPublished);
avCastMan.addEventListener(RedBoxCastEvent.LIVE_CAST_UNPUBLISHED, onLiveCastUnpublished);
}
/**
* Handle A/V connection initialized.
*/
public function onAVConnectionInited(evt:RedBoxConnectionEvent):void
{
// Nothing to do. Usually we should wait this event before enabling the a/v chat related interface elements.
trace("AV Connection Initied...");
}
/**
* Handle A/V connection error.
*/
public function onAVConnectionError(evt:RedBoxConnectionEvent):void
{
var error:String = "The following error occurred while trying to establish an A/V connection: " + evt.params.errorCode;
// Show alert
//showAlert(error);
trace(error);
}
public function onLiveCastPublished(evt:RedBoxCastEvent):void
{
trace("New Live cast published Event..");
var liveCast:LiveCast = evt.params.liveCast;
// Subscribe live cast
var stream:NetStream = avCastMan.subscribeLiveCast(liveCast.id);
trace("Subscribed live cast from id." + liveCast.id);
//Play stream
if (stream != null)
{
stream.play();
}
}
public function onLiveCastUnpublished(evt:RedBoxCastEvent):void
{
trace("New Live cast unpublished Event..");
var liveCast:LiveCast = evt.params.liveCast;
avCastMan.unsubscribeLiveCast(liveCast.id);
trace("Unsubscribed live cast from id." + liveCast.id);
}
private function OnEXTENSIONRESPONCE(evt:BaseEvent):void
{
var cmd:String = evt.params.cmd;
var dt:ISFSObject = evt.params.params;
Main.GetInstance().OnExtensionResponce(cmd, dt);
/*
try
{
//ResetLastPacketTime();
//Debug.Log("Ext Resp------------------------------------------------> : " + cmd);
var dt:ISFSObject = evt.Params.params;
var functionToCall:Function = null;
ndo.SFSObject = dt;
m_commandMappings.TryGetValue(cmd, out functionToCall);
if (functionToCall != null)
{
functionToCall.Invoke(ndo);
}
}
catch (Exception e)
{
Debug.Log("Exception handling response: " + e.Message + " >>> " + e.StackTrace);
//Utility.Assert(false, "Exception handling response: " + e.Message + " : " + e.StackTrace);
//Debug.Log("Exception handling response: " + e.Message + " >>> " + e.StackTrace);
}*/
}
private function OnJoinRoom(evt:BaseEvent):void
{
trace("________Room joined successfully");
InitializeAVConference();
var selfstream:NetStream = avCastMan.publishLiveCast( true, true);
}
private function InitializeAVConference():void
{
var casts : Array = avCastMan.getAvailableCasts();
for each (var liveCast:LiveCast in avCastMan.getAvailableCasts())
{
var stream:NetStream = avCastMan.subscribeLiveCast(liveCast.id);
//stream.play();
trace(" Subscrbing to already existing livecasts id : " + liveCast.id);
}
}
public function RegisterCommand(a_strComandName:String, a_delFunction:Function):void
{
if (a_delFunction == null)
trace("Delegate is null");
var functionToCall:Function = null;
trace("Registered Command : " + a_strComandName);
}
private function OnLOGINERROR(evt:BaseEvent):void
{
if (m_listener)
{
m_listener.OnLoginError(evt.params.errorMessage,evt.params.errorCode);
}
}
private function Connect(a_strIP:String, a_iPort:int):void
{
m_strIP = a_strIP;
m_iPort = a_iPort;
Connect_();
}
public function Login():void
{
m_connection.send(new LoginRequest(m_strUserName, m_strPwd, m_strZoneName));
}
public function Connect_():void
{
m_connection.connect(m_strIP, m_iPort);
}
public function SendPacket(a_strName:String, a_data:ISFSObject):void
{
m_connection.send(new ExtensionRequest(a_strName, a_data));
}
}
}
Problems:
1)Firstly setting RTMPT to true when initing the AVCastManager gives a netconnection.connect.fail exception. If it is set to false the AVCastManager is inited successfully.
2)When the AVCastManager is inited succesfully following the RTMPT to false, when the local user is trying to publish his cast, the internal client side Redbox logs are such..
....
________Room joined successfully
[RedBox] User own live cast published; id: 6_2013014123822463_2
[RedBox] User own live cast unpublished
[RedBox] Initializing Live Casts list for current room...
Reg done fine
......
Why is the own live cast unpublished immediately?
3)Also this might be unrelated but I'm an AS3 noob. How do I simply play the audio returned in the NetStream's?
Thanks for such neat products. Hope to get this running soon!
Awaiting!