I need help for your videoconference

Post your questions and bug-reports about the audio/video streaming add-on based on Red5 Media Server.

Moderators: Lapo, Bax

User avatar
rjgtav
Posts: 2813
Joined: 19 Apr 2009, 11:31
Location: Lisbon, Portugal

Re: I need help for your videoconference

Postby rjgtav » 19 Nov 2012, 22:30

Here's the updated AVCastManager.as file.

Now the publishLiveCast() accepts a 3rd parameter, which is the amount of seconds (default=5s) that the client waits for the user click either "Allow" or "Deny", before checking whether or not the camera was allowed. If the camera was allowed, it publishes the stream, if it isn't, it doesn't publish anything, nor does it update any UV.

I've also added a new property called isCasting, which is true when it successfully started casting the webcam and false, when it isn't casting, because the user denied it. This property is used internally by the RedBox API but maybe it can find some other use.

The parts that I added/edited are tagged with rjgtav.

AVCastManager.as - ActionScript 2.0

Code: Select all

import com.smartfoxserver.redbox.utils.Logger;
import com.smartfoxserver.redbox.utils.Constants;
import com.smartfoxserver.redbox.events.RedBoxCastEvent;
import com.smartfoxserver.redbox.data.LiveCast;
import com.smartfoxserver.redbox.exceptions.*;

import it.gotoandplay.smartfoxbits.bits.Connector;
import it.gotoandplay.smartfoxbits.events.SFSEvent;
import it.gotoandplay.smartfoxbits.events.EventDispatcher;

import it.gotoandplay.smartfoxserver.SmartFoxClient;
import it.gotoandplay.smartfoxserver.Room;
import it.gotoandplay.smartfoxserver.User;

import mx.utils.Delegate
import flash.display.BitmapData;


/**
 * SmartFoxServer's RedBox Audio/Video Broadcast Manager.
 * This class is responsible for managing audio/video live casts inside the room joined by the user, making it possible to create live web events or a/v conferences.
 * The AVCastManager handles the live cast publishing/playing to/from the Red5 server.
 * Unlike the other RedBox classes, the AVCastManager works on a room basis to leverage the access control and moderation features of SmartFoxServer rooms.
 *
 * <b>NOTE</b>: in the provided examples, {@code avCastMan} always indicates an AVCastManager instance.
 *
 * @usage   The most common usages for the <b>AVCastManager</b> class are video conference applications and live webcast applications (for example live online seminars).
 *          
 *          <i>Video conference</i>
 *          In this kind of application, each user publishes his own live stream and subscribes the streams coming from the other users in the same room (in the SmartFoxServer meaning). The following workflow is suggested.
 *          <ol>
 *             <li>The current user joins the room where the video conference takes place.</li>
 *             <li>The list of currently available streams (or "live casts") is retrieved by means of the {@link #getAvailableCasts} method (in case the conference is already in progress).
 *             Calling this method also enables the reception of the {@link RedBoxCastEvent#onLiveCastPublished} and {@link RedBoxCastEvent#onLiveCastUnpublished} events which notify that another user started or stopped his own stream.</li>
 *             <li>Each live cast is subscribed by means of the {@link #subscribeLiveCast} method and a Video object is displayed on the stage to attach the stream to.
 *             When a live cast is published (a new user joins the conference) or stopped (a user leaves the conference), a notification is received by means of the above mentioned events: the stream is subscribed / unsubscribed and displayed on / removed from the stage.</li>
 *             <li>The a/v stream for the current user is published by means of the {@link #publishLiveCast} method and an additional Video object showing the user own camera stream is added on the stage; when the current user publishes his own stream, the other users receive the above mentioned events.</li>
 *             <li>To make the current user leave the conference, the {@link #unpublishLiveCast} method is called. Also changing SmartFoxServer room causes the user to leave the conference and the other users to be notified.</li>
 *          </ol>
 *          <hr />
 *          <i>Live webcast</i>
 *          In this kind of application, a single user publishes his own live stream and all the other users in the same room subscribe it. The following workflow is suggested.
 *          <ol>
 *             <li>The publisher joins the room where the live webcast takes place.</li>
 *             <li>The a/v stream for the user is published by means of the {@link #publishLiveCast} method and a Video object showing the user own camera stream is added on the stage; when the current user publishes his own stream, the other users already in the room receive the {@link RedBoxCastEvent#onLiveCastPublished} event and the stream can be subscribed (see step 4).</li>
 *             <li>The webcast spectators join the room and retrieve the list of available streams (one item only if the publisher is already streaming, otherwise the list will be empty).</li>
 *             <li>If the live webcast is already started, it can be subscribed by means of the {@link #subscribeLiveCast} method; otherwise the {@link RedBoxCastEvent#onLiveCastPublished} event must be waited for before calling this method.</li>
 *             <li>On all the subscribers clients a Video object is displayed on the stage to attach the stream to.</li>
 *          </ol>
 *
 * @version   1.0.0
 *
 * @author   The gotoAndPlay() Team
 *          {@link http://www.smartfoxserver.com}
 *          {@link http://www.gotoandplay.it}
 */
class com.smartfoxserver.redbox.AVCastManager
{
   //--------------------------------------
   // CLASS CONSTANTS
   //--------------------------------------
   
   private var CAST_USER_VAR:String = "$RB_castId"
   
   //--------------------------------------
   //  PRIVATE VARIABLES
   //--------------------------------------
   
   private var connector:Connector
   private var dispatcher:EventDispatcher
   private var smartFox:SmartFoxClient
   private var red5IpAddress:String
   private var netConn:NetConnection
   private var castList:Array = null
   private var castListByUser:Array
   private var myLiveCast:NetStream
   private var castListRequested:Boolean
   
   //Added by rjgtav
   private var _isCasting:Boolean = false;
   private var camera:Camera = null;
   private var microphone:Microphone = null;
   private var enableCamera:Boolean = false;
   private var enableMicrophone:Boolean = false;
   private var waitForAllowInterval = null;
   //rjgtav ends here
   
   //--------------------------------------
   //  GETTERS/SETTERS
   //--------------------------------------
   
   /**
    * The status of the connection to the Red5 server.
    * If {@code true}, the connection to Red5 is currently available.
    */
   public function get isConnected():Boolean
   {
      return netConn.isConnected
   }
   
   //Added by rjgtav
   public function get isCasting():Boolean
   {
      return _isCasting
   }
   //rjgtav ends here
   
   //--------------------------------------
   //  COSTRUCTOR
   //--------------------------------------
   
   /**
    * AVCastManager contructor.
     * The RedBox classes make an extensive use of the SmartFoxBits Connector's s event handler in order to communicate with SmartFoxServer.
    * To achieve this you should place the Connector on a frame before you use RedBox classes on the following frame(s) or to make sure that the Connector is on the lowest layer of the timeline, and set the "Load order" option in the Flash Publish Settings to "Bottom up".
    *
    * @param   sfs:   the SmartFoxClient instance.
    * @param   red5Ip:   the Red5 server IP address.
    * @param   debug:   turn on the debug messages (optional, default is {@code false}).
    *
    * @throws   ConnectorNotFoundException if the SmartFoxBits Connector is not placed on the Stage.
    * @throws   MyUserPropsNotSetException if the <i>SmartFoxClient.myUserId</i> or <i>SmartFoxClient.myUserName</i> properties are not set.
    * @throws  InvalidParamsException if the {@code red5Ip} is not well formated IP address.
    *
    * @example   The following example shows how to instantiate the AVCastManager class.
    *          <code>
    *          var red5IpAddress:String = "127.0.0.1"
    *          
    *          var avCastMan:AVCastManager = new AVCastManager(red5IpAddress)
    *          </code>
    *
    * see      MyUserPropsNotSetException
    */
   function AVCastManager(red5Ip:String, debug:Boolean)
   {
      //Gets the SmartFoxBits Connector instance
      connector = _global.__$F$SmartFoxBitsConnector__
      //Shows error if doesn't found an Connector instance
      if(connector == undefined || connector == null)
      {
         throw new ConnectorNotFoundException()
      }
      
      //Creates new event dispatcher instanse
      dispatcher = new EventDispatcher()
      // Set reference to SmartFoxClient instance
      smartFox = connector.connection
      
      // Check if "myUser" properties are set
      if (!myUserIsValid())
         throw new MyUserPropsNotSetException()
      
      //------------------------------
      
      // Initialize properties
      red5IpAddress = red5Ip
      debug = Boolean(debug)
      Logger.enableLog = debug
      netConn = new NetConnection()
      
      // Initialize casts list for the current room
      if (smartFox.getActiveRoom() != null)
         initCastList()
      
      // Add Red5 connection event listener
      netConn.onStatus = Delegate.create(this, onRed5ConnectionStatus)
      
      // Add SmartFoxServer event listeners
      connector.addEventListener(SFSEvent.onJoinRoom, Delegate.create(this, onJoinRoom))
      connector.addEventListener(SFSEvent.onUserVariablesUpdate, Delegate.create(this, onUserVariablesUpdate))
      connector.addEventListener(SFSEvent.onUserLeaveRoom, Delegate.create(this, onUserLeaveRoom))
      connector.addEventListener(SFSEvent.onConnectionLost, Delegate.create(this, onUserDisconnection))
      connector.addEventListener(SFSEvent.onLogout, Delegate.create(this, onUserDisconnection))
      
      // Establish connection to Red5
      initAVConnection()
   }
   
   // -------------------------------------------------------
   // PUBLIC METHODS
   // -------------------------------------------------------
   
   /**
    * Initialize the audio/video connection.
    * Calling this method causes the connection to Red5 to be established and the {@link RedBoxCastEvent#onAVConnectionInited} event to be fired in response.
    * If the connection can't be established, the {@link RedBoxCastEvent#onAVConnectionError} event is fired in response.
    * <b>NOTE</b>: this method is called automatically when the AVCastManager is instantiated.
    *
    * @throws  InvalidParamsException if the {@code red5IpAddress} is not well formated IP address.
    *   
    * @sends   RedBoxCastEvent#onAVConnectionInited
    * @sends   RedBoxCastEvent#onAVConnectionError
    *
    * @example   The following example shows how to initialize the Red5 connection for the AVCastManager instance.
    *          <code>
    *          avCastMan.initAVConnection()
    *          </code>
    *
    * @see      #isConnected
    * @see      RedBoxCastEvent#onAVConnectionInited
    * @see      RedBoxCastEvent#onAVConnectionError
    */
   public function initAVConnection():Void
   {
      // Connect to Red5 if a connection is not yet available
      if (!netConn.isConnected)
      {
         if(!netConn.connect("rtmp://" + red5IpAddress + "/" + Constants.RED5_APPLICATION))
         {
            throw new InvalidParamsException("Bad URI")
         }
      }
      else
      {
         // Dispatch "onAVConnectionInited" event
         dispatchAVCastEvent(RedBoxCastEvent.onAVConnectionInited)
         
         Logger.log("Red5 connection initialized")
      }
   }
   
   /**
    * Destroy the AVCastManager instance.
    * Calling this method causes the interruption of all the playing streams (if any) and the disconnection from Red5.
    * This method should always be called before deleting the AVCastManager instance.
    *
    * @example   The following example shows how to destroy the AVCastManager instance.
    *          <code>
    *          avCastMan.destroy()
    *          avCastMan = null
    *          </code>
    */
   public function destroy():Void
   {
      // Remove Red5 connection event listener
      netConn.onStatus = null
      
      // Remove SmartFoxServer event listeners
      connector.removeEventListener(SFSEvent.onJoinRoom, onJoinRoom)
      connector.removeEventListener(SFSEvent.onUserVariablesUpdate, onUserVariablesUpdate)
      connector.removeEventListener(SFSEvent.onUserLeaveRoom, onUserLeaveRoom)
      connector.removeEventListener(SFSEvent.onConnectionLost, onUserDisconnection)
      connector.removeEventListener(SFSEvent.onLogout, onUserDisconnection)
      
      // Unpublish outgoing stream
      unpublishLiveCast()
      
      // Unsubscribe all incoming streams
      unsubscribeAllLiveCasts()
      
      castListRequested = false
      castList = null
      castListByUser = null
      
      waitForAllowInterval = null;//Added by rjgtav
      
      // Disconnect from Red5 server
      if (netConn.isConnected)
         netConn.close()
      
      Logger.log("AVCastManager instance destroyed")
   }
   
   /**
    * Retrieve the list of available live broadcasts for the current room.
    * The list is populated by the {@link AVCastManager} class as soon as it is instantiated and each time a new room is joined.
    * When this method is called, the {@link RedBoxCastEvent#onLiveCastPublished} and {@link RedBoxCastEvent#onLiveCastUnpublished} events dispatching is enabled, in order to be notified when users in the current room start/stop streaming.
    * In order to turn off events notification, the {@link #stopPublishNotification} method should be called.
    *
    * @return   An array of {@link LiveCast} objects.
    *
    * @example   The following example shows how to loop through the list of live casts available for the current room.
    *          <code>
    *          var liveCasts:Array = avCastMan.getAvailableCasts()
    *          for(var i in avCastMan.getAvailableCasts())
    *          {
    *              var liveCast:LiveCast = liveCasts[i]
    *             // Subscribe live cast
    *             var stream:NetStream = avCastMan.subscribeLiveCast(liveCast.id)
    *             
    *             // Display a/v stream on stage
    *             ...
    *          }
    *          </code>
    *
    * @see      LiveCast
    * @see      #stopPublishNotification
    */
   public function getAvailableCasts():Array
   {
      castListRequested = true
      
      return castList
   }
   
   /**
    * Stop receiving live cast published/unpublished events.
    *
    * @see      #getAvailableCasts
    */
   public function stopPublishNotification():Void
   {
      castListRequested = false
   }
   
   /**
    * Subscribe a live cast to receive its audio/video stream.
    *
    * @param   castId:   (<b>String</b>) the id of the {@link LiveCast} object to be subscribed.
    *
    * @return   A NetStream object.
    *
    * @throws   NoAVConnectionException if the connection to Red5 is not available.
    *
    * @example   The following example shows how to subscribe a live cast when a publishing notification is received.
    *          <code>
    *          avCastMan.addEventListener(RedBoxCastEvent.onLiveCastPublished, Delegate.create(this, onLiveCastPublished))
    *          
    *          // A user publishes his own live cast...
    *          
    *          function onLiveCastPublished(evt:RedBoxCastEvent):Void
    *          {
    *             var liveCast:LiveCast = evt.params.liveCast
    *             
    *             // Subscribe live cast
    *             var stream:NetStream = avCastMan.subscribeLiveCast(liveCast.id)
    *             
    *             // Display a/v stream on stage
    *             ...
    *          }
    *          </code>
    *
    * @see      #unsubscribeLiveCast
    * @see      NoAVConnectionException
    * @see      NetStream
    */
   public function subscribeLiveCast(castId:String):NetStream
   {
      // Check Red5 connection availability
      if (!netConn.isConnected)
         throw new NoAVConnectionException(Constants.ERROR_NO_CONNECTION + " [subscribeLiveCast method]")
      
      //------------------------------
      
      if (castList != null && !(castList[castId] == null || castList[castId] == undefined))
      {
         var liveCast:LiveCast = castList[castId]
         
         var stream:NetStream = new NetStream(netConn)
         stream.play(liveCast.id)
         
         liveCast.setStream(stream)
         
         return liveCast.stream
      }
      
      return null
   }
   
   /**
    * Unsubscribe a live cast to stop receiving its audio/video stream.
    * <b>NOTE</b>: when a user stops his own stream or leaves the current room / disconnects from SmartFoxServer while his stream is in progress, the {@link AVCastManager} class automatically unsubscribes the live cast before dispatching the {@link RedBoxCastEvent#onLiveCastUnpublished} event.
    *
    * @param   castId:   (<b>String</b>) the id of the {@link LiveCast} object to be unsubscribed.
    *
    * @example   The following example shows how to unsubscribe a live cast.
    *          <code>
    *          avCastMan.unsubscribeLiveCast(liveCast.id)
    *          </code>
    *
    * @see      #subscribeLiveCast
    */
   public function unsubscribeLiveCast(castId:String):Void
   {
      if (castList != null && !(castList[castId] == null || castList[castId] == undefined))
      {
         var liveCast:LiveCast = castList[castId]
         
         // Close incoming stream
         if (liveCast.stream != null && liveCast.stream != undefined)
         {
            liveCast.stream.close()
            liveCast.setStream(null)
         }
      }
   }
   
   /**
    * Unsubscribe all currently subscribed live casts.
    *
    * @see      #unsubscribeLiveCast
    */
   public function unsubscribeAllLiveCasts():Void
   {
      if (castList != null)
      {
         for(var i in castList)
            unsubscribeLiveCast(castList[i].id)
      }
   }
   
   /**
    * Start broadcasting the current user's live stream.
    * Calling this method causes the {@link RedBoxCastEvent#onLiveCastPublished} event to be fired on the other users clients.
    * Audio and video recording mode/quality should be set before calling this method. In order to alter these settings, please refer to the Microphone and Camera classes documentation.
    *
    * @param   enableCamera:      enable video live streaming; default value is {@code true}.
    * @param   enableMicrophone:   enable audio live streaming; default value is {@code true}.
    *
    * @return   The NetStream object representing the user's outgoing stream.
    *
    * @sends   RedBoxCastEvent#onLiveCastPublished
    *
    * @throws   NoAVConnectionException if the connection to Red5 is not available.
    * @throws   InvalidParamsException if both <i>enableCamera</i> and <i>enableMicrophone</i> parameters are set to {@code false}.
    *
    * @example   The following example shows how to publish the current user's live stream.
    *          <code>
    *          avCastman.publishLiveCast(true, true)
    *          </code>
    *
    * @see      #unpublishLiveCast
    * @see      RedBoxCastEvent#onLiveCastPublished
    * @see      NoAVConnectionException
    * @see      InvalidParamsException
    * @see      Camera
    * @see      Microphone
    * @see      NetStream
    */
   public function publishLiveCast(enableCamera:Boolean, enableMicrophone:Boolean, waitSeconds:Number):NetStream
   {
      if(enableCamera == undefined)
      {
         enableCamera = true;
      }
      if(enableMicrophone == undefined)
      {
         enableMicrophone = true;
      }
      if(waitSeconds == undefined)
      {
         waitSeconds = 5;
      }
      
      // If cam & mic are both null, why sending this type of request?
      if (!enableCamera && !enableMicrophone)
         throw new InvalidParamsException(Constants.ERROR_INVALID_PARAMS)
      
      // Check Red5 connection availability
      if (!netConn.isConnected)
         throw new NoAVConnectionException(Constants.ERROR_NO_CONNECTION + " [publishLiveCast method]")
      
      //------------------------------
      
      if (myLiveCast == null || myLiveCast == undefined)
      {
         myLiveCast = new NetStream(netConn)
         
         //Get camera and microphone and attach them to the stream
         if (enableCamera)
            camera = Camera.get();//added by rjgtav
            myLiveCast.attachVideo(camera)
         
         if (enableMicrophone)
            microphone = Microphone.get();//added by rjgtav
            myLiveCast.attachAudio(microphone)
         
         //added by rjgtav
         this.enableCamera = enableCamera;
         this.enableMicrophone = enableMicrophone;
         
         if((enableCamera && !camera.muted) || (enableMicrophone && !microphone.muted)){
            //The user has already allowed the app to use the mic or the cam or both.
            //We can publish the stream
            publishMyLiveCast();
         }else{
            //The user hasn't allowed yet the app to use the mic and the cam
            //We'll wait some seconds for the user to click the "Allow" button,
            //before we publish the stream and update the UV's
            waitForAllowInterval = setInterval(this, "publishMyLiveCast", waitSeconds*1000);
         }
         //rjgtav ends here
         
         return myLiveCast
      }
      
      return null
   }
   
   /**
    * Stop broadcasting the current user's live stream.
    * Calling this method causes the {@link RedBoxCastEvent#onLiveCastUnpublished} event to be fired on the other users clients.
    *
    * @sends   RedBoxCastEvent#onLiveCastUnpublished
    *
    * @example   The following example shows how to unpublish a live cast.
    *          <code>
    *          avCastMan.unpublishLiveCast()
    *          </code>
    *
    * @see      #publishLiveCast
    * @see      RedBoxCastEvent#onLiveCastUnpublished
    */
   public function unpublishLiveCast():Void//Edited by rjgtav
   {
      // Stop outgoing stream
      if (myLiveCast != null && myLiveCast != undefined)
      {
         myLiveCast.close()
         myLiveCast = null
      }
      
      // Reset user variable
      if (smartFox.connected() && _isCasting)
      {
         _isCasting = false;
         
         var userVar:Object = {}
         userVar[CAST_USER_VAR] = null
         
         smartFox.setUserVariables(userVar)
      }
      
      //Added by rjgtav
      //Clears the interval, in case the user unpublishes the stream earlier than expected
      clearInterval(waitForAllowInterval)
   }

   /**
    * Register a listener function in order to receive notification of a RedBox event.
    *
    * If you no longer need an event listener, remove it by calling the removeEventListener method.
    *
    * <b>NOTE</b>: use the Delegate.create() method when registering a listener, to keep right scope in your application.
    *
    * @usage   To register to an event:
    *         <code>
     *         import com.smartfoxserver.redbox.events.*
    *         import mx.utils.Delegate
    *
    *         avCastMan.addEventListener(RedBoxCastEvent.onLiveCastPublished, Delegate.create(this, myListener))
    *
    *         private function myListener(evt:RedBoxCastEvent):Void
    *         {
    *            trace("Got the event!")
    *            trace("Event type: " + evt.type)
    *            trace("Event target: " + evt.target)
    *            trace("Additional parameters:")
     *
    *            for (var i in evt.params)
    *               trace("\t" + i + " -> " + evt.params[i])
    *         }
    *         </code>
    *
    * @param   type      The event type you want to be notified of.
    * @param   listener   The listener function in your application that processes the event. This function must accept an RedBoxCastEvent object as its only parameter and must return nothing, as in the example above.
    *
    * @see      #removeEventListener
    * @see      RedBoxCastEvent
    */
   public function addEventListener(type:String, listener:Function):Void
   {
      dispatcher.addListener(type, listener)
   }
   
   /**
    * Remove a listener from the event dispatcher, to stop receiving notification of an event.
    *
    * @usage   To remove a listener:
    *         <code>
    *         avCastMan.removeEventListener(RedBoxCastEvent.onLiveCastPublished, myListener)
    *         </code>
    *         <b>NOTE</b>: the Delegate.create() is not required to remove a listener.
    *
    * @param   type      The event type you registered your listener to.
    * @param   listener   The listener function to remove.
    *
    * @see    #addEventListener
    * @see      RedBoxCastEvent
    */
   public function removeEventListener(type:String, listener:Function):Void
   {
      dispatcher.removeListener(type, listener)
   }
   
   // -------------------------------------------------------
   // SMARTFOXSERVER & RED5 EVENT HANDLERS
   // -------------------------------------------------------
   
   /**
    * Handle room joined event.
    *
    * @exclude
    */
   public function onJoinRoom(evt:SFSEvent):Void
   {
      // Unpublish outgoing stream
      unpublishLiveCast()
      
      // Unsubscribe all incoming streams
      unsubscribeAllLiveCasts()
      
      // Re-initialize live casts list
      initCastList()
   }
   
   /**
    * Handle user variables update event.
    *
    * @exclude
    */
   public function onUserVariablesUpdate(evt:SFSEvent):Void
   {
      // Check if the proper variable has changed
      if (evt.params.changedVars[CAST_USER_VAR] != null && castList != null)
       {
          var castId:String = evt.params.user.getVariable(CAST_USER_VAR)
          var userId:Number = evt.params.user.getId()
          var userName:String = evt.params.user.getName()
          
          if (castId != null)
          {
             Logger.log("User '" + userName + "' published his live cast:", castId)
             
             // Add new live cast to list
             addLiveCast(castId, userId, userName, true)
          }
          else
          {
             Logger.log("User '" + userName + "' unpublished his live cast")
             
             // Remove live cast from list
             removeLiveCast(userId)
          }
       }
   }
   
   /**
    * Handle user leaving current room.
    *
    * @exclude
    */
   public function onUserLeaveRoom(evt:SFSEvent):Void
   {
      var userId:Number = evt.params.userId
      
      // Remove live cast from list
       var removed:Boolean = removeLiveCast(userId)
      
       if (removed)
          Logger.log("User '" + evt.params.userName + "' left the room; live cast removed")
   }
   
   /**
    * Handle user logout and disconnection events.
    *
    * @exclude
    */
   public function onUserDisconnection(evt:SFSEvent):Void
   {
      // Reset AVCastManager instance
      destroy()
   }
   
   /**
    * Handle Red5 connection status events.
    *
    * @exclude
    */
   public function onRed5ConnectionStatus(info:Object):Void
   {
      var code:String = info.code
      var level:String = info.level
      
      Logger.log("NetStatusEvent response received")
      Logger.log("Level: " + level, "| Code:" + code)
      
      switch (code)
      {
         case "NetConnection.Connect.Success":
            
            Logger.log("NetConnection successful")
            
            // Call the "initialize" method which will dispatch the "onAVConnectionInited" event
            initAVConnection()
            
            break
         
         case "NetConnection.Connect.Closed":
         case "NetConnection.Connect.Failed":
         case "NetConnection.Connect.Rejected":
         case "NetConnection.Connect.AppShutDown":
         case "NetConnection.Connect.InvalidApp":
            
            Logger.log("NetConnection error, dispatching event...")
            
            // Unpublish outgoing stream
            unpublishLiveCast()
            
            // Unsubscribe all incoming streams
            unsubscribeAllLiveCasts()
            
            // Dispatch connection error event
            var params:Object = {}
            params.errorCode = code
            
            dispatchAVCastEvent(RedBoxCastEvent.onAVConnectionError, params)
            
            break
      }
   }
   
   // -------------------------------------------------------
   // PRIVATE METHODS
   // -------------------------------------------------------
   
   /**
    * Dispatch AVCastManager events.
    */
   private function dispatchAVCastEvent(type:String, params:Object):Void
   {
      if(params == undefined)
      {
         params = null
      }
      var event:RedBoxCastEvent = new RedBoxCastEvent(this, type, params)
      dispatcher.dispatchEvent(event)
   }
   
   /**
    * Check if SmartFoxClient.myUserId and SmartFoxClient.myUserName are set.
    */
   private function myUserIsValid():Boolean
   {
      return (smartFox.myUserId >= 0 && smartFox.myUserName != undefined && smartFox.myUserName != "" && smartFox.myUserName != null)
   }

   
   /**
    * Initialize the available live casts list for the current room.
    */
   private function initCastList():Void
   {
      Logger.log("Initializing Live Casts list for current room...")
      
      castListRequested = false
      
      castList = new Array()
      castListByUser = new Array()
      
      var currRoom:Room = smartFox.getActiveRoom()
      var userList = currRoom.getUserList()
      for (var i in userList)
      {
         var user:User = userList[i]
         // Exclude my own cast
         if (user.getId() != smartFox.myUserId)
         {
            var castId:String = (user.getVariable(CAST_USER_VAR) != undefined ? user.getVariable(CAST_USER_VAR) : "")
            
            if (castId != null && castId != "")
            {
               Logger.log("Live cast found for user", user.getName())
               
               // Add live cast to list
               addLiveCast(castId, user.getId(), user.getName(), false)
            }
         }
      }
   }
   
   /**
    * Add live cast to list.
    */
   private function addLiveCast(id:String, userId:Number, userName:String, fireEvent:Boolean):Void
   {
      if(fireEvent == undefined)
      {
         fireEvent = true
      }
      // Create new live cast
      var params:Object = {}
      params.id = id
      params.uId = userId
      params.uName = userName
      
      var liveCast:LiveCast = new LiveCast(params)
      
      // Add cast to list
      castList[id] = liveCast
      castListByUser[userId] = liveCast
      
      // Dispatch event (only if the cast list has already been requested)
         if (fireEvent && castListRequested)
         {
          params = {}
         params.liveCast = liveCast
         
         dispatchAVCastEvent(RedBoxCastEvent.onLiveCastPublished, params)
      }
   }
   
   /**
    * Remove live cast from list.
    */
   private function removeLiveCast(userId:Number):Boolean
   {
      if (castListByUser != undefined && castListByUser != null && castListByUser[userId] != undefined && castListByUser[userId] != null)
      {
         var liveCast:LiveCast = castListByUser[userId]
         
         // Unsubscribe live cast
          unsubscribeLiveCast(liveCast.id)
          
          // Dispatch event (only if the cast list has already been requested)
          if (castListRequested)
          {
             var params:Object = {}
            params.liveCast = liveCast
            
            dispatchAVCastEvent(RedBoxCastEvent.onLiveCastUnpublished, params)
          }
          
          // Remove cast from casts list
         delete castList[liveCast.id]
         delete castListByUser[userId]
         
         return true
        }
        
        return false
   }
   
   //Added by rjgtav
   /**
    * Publishes the Live Cast and updates the user's UV
    */
   private function publishMyLiveCast():Void
   {
      //We only publish the stream if the user allowed the application
      if((enableCamera && !camera.muted) || (enableMicrophone && !microphone.muted)){
         // Generate stream id
         var now:Date = new Date()
         var month:Number = now.getUTCMonth() + 1
         var dateString:String = now.getUTCFullYear().toString() + (month < 10 ? "0" : "") + month.toString() + now.getUTCDate().toString()
         var timeString:String = now.getUTCHours().toString() + now.getUTCMinutes().toString() + now.getUTCSeconds().toString() + now.getUTCMilliseconds().toString()
         var roomId:Number = smartFox.activeRoomId
         var userId:Number = smartFox.myUserId
         
         var liveCastId:String = roomId + "_" + dateString + timeString + "_" + userId
         
         // Publish live stream
         myLiveCast.publish(liveCastId, Constants.BROADCAST_TYPE_LIVE)
         
         // Set user variable
         var userVar:Object = {}
         userVar[CAST_USER_VAR] = liveCastId
         smartFox.setUserVariables(userVar)
         
         _isCasting = true;
         
         Logger.log("User own live cast published; id:", liveCastId)
      }else{
         Logger.log("User didn't allow the app to use the cam and/or mic. No cast is going to be published.")
         unpublishLiveCast()
      }
      
      //Clear the interval
      clearInterval(waitForAllowInterval)
   }
   //rjgtav ends here
}


AVCastManager.as - ActionScript 3.0

Code: Select all

package com.smartfoxserver.redbox
{
   import com.smartfoxserver.redbox.utils.Logger;
   import com.smartfoxserver.redbox.utils.Constants;
   import com.smartfoxserver.redbox.events.RedBoxCastEvent;
   import com.smartfoxserver.redbox.data.LiveCast;
   import com.smartfoxserver.redbox.exceptions.*;
   
   import it.gotoandplay.smartfoxserver.SmartFoxClient;
   import it.gotoandplay.smartfoxserver.SFSEvent;
   import it.gotoandplay.smartfoxserver.data.Room;
   import it.gotoandplay.smartfoxserver.data.User;
   
   import flash.events.EventDispatcher;
   import flash.media.Camera;
   import flash.media.Microphone;
   import flash.net.NetConnection;
   import flash.net.NetStream;
   import flash.events.NetStatusEvent;
   import flash.events.TimerEvent;
   import flash.utils.Timer;

   /**
    * SmartFoxServer's RedBox Audio/Video Broadcast Manager.
    * This class is responsible for managing audio/video live casts inside the room joined by the user, making it possible to create live web events or a/v conferences.
    * The AVCastManager handles the live cast publishing/playing to/from the Red5 server.
    * Unlike the other RedBox classes, the AVCastManager works on a room basis to leverage the access control and moderation features of SmartFoxServer rooms.
    *
    * <b>NOTE</b>: in the provided examples, {@code avCastMan} always indicates an AVCastManager instance.
    *
    * @usage   The most common usages for the <b>AVCastManager</b> class are video conference applications and live webcast applications (for example live online seminars).
    *          
    *          <i>Video conference</i>
    *          In this kind of application, each user publishes his own live stream and subscribes the streams coming from the other users in the same room (in the SmartFoxServer meaning). The following workflow is suggested.
    *          <ol>
    *             <li>The current user joins the room where the video conference takes place.</li>
    *             <li>The list of currently available streams (or "live casts") is retrieved by means of the {@link #getAvailableCasts} method (in case the conference is already in progress).
    *             Calling this method also enables the reception of the {@link RedBoxCastEvent#onLiveCastPublished} and {@link RedBoxCastEvent#onLiveCastUnpublished} events which notify that another user started or stopped his own stream.</li>
    *             <li>Each live cast is subscribed by means of the {@link #subscribeLiveCast} method and a Video object is displayed on the stage to attach the stream to.
    *             When a live cast is published (a new user joins the conference) or stopped (a user leaves the conference), a notification is received by means of the above mentioned events: the stream is subscribed / unsubscribed and displayed on / removed from the stage.</li>
    *             <li>The a/v stream for the current user is published by means of the {@link #publishLiveCast} method and an additional Video object showing the user own camera stream is added on the stage; when the current user publishes his own stream, the other users receive the above mentioned events.</li>
    *             <li>To make the current user leave the conference, the {@link #unpublishLiveCast} method is called. Also changing SmartFoxServer room causes the user to leave the conference and the other users to be notified.</li>
    *          </ol>
    *          <hr />
    *          <i>Live webcast</i>
    *          In this kind of application, a single user publishes his own live stream and all the other users in the same room subscribe it. The following workflow is suggested.
    *          <ol>
    *             <li>The publisher joins the room where the live webcast takes place.</li>
    *             <li>The a/v stream for the user is published by means of the {@link #publishLiveCast} method and a Video object showing the user own camera stream is added on the stage; when the current user publishes his own stream, the other users already in the room receive the {@link RedBoxCastEvent#onLiveCastPublished} event and the stream can be subscribed (see step 4).</li>
    *             <li>The webcast spectators join the room and retrieve the list of available streams (one item only if the publisher is already streaming, otherwise the list will be empty).</li>
    *             <li>If the live webcast is already started, it can be subscribed by means of the {@link #subscribeLiveCast} method; otherwise the {@link RedBoxCastEvent#onLiveCastPublished} event must be waited for before calling this method.</li>
    *             <li>On all the subscribers clients a Video object is displayed on the stage to attach the stream to.</li>
    *          </ol>
    *
    * @version   1.0.0
    *
    * @author   The gotoAndPlay() Team
    *          {@link http://www.smartfoxserver.com}
    *          {@link http://www.gotoandplay.it}
    */
   public class AVCastManager extends EventDispatcher
   {
      //--------------------------------------
      // CLASS CONSTANTS
      //--------------------------------------
      
      private const CAST_USER_VAR:String = "$RB_castId"
      
      //--------------------------------------
      //  PRIVATE VARIABLES
      //--------------------------------------
      
      private var smartFox:SmartFoxClient
      private var red5IpAddress:String
      private var netConn:NetConnection
      private var castList:Array
      private var castListByUser:Array
      private var myLiveCast:NetStream
      private var castListRequested:Boolean
      
      //Added by rjgtav
      private var _isCasting:Boolean = false;
      private var camera:Camera = null;
      private var microphone:Microphone = null;
      private var enableCamera:Boolean = false;
      private var enableMicrophone:Boolean = false;
      private var waitForAllowInterval:Timer = new Timer(0);
      //rjgtav ends here
      
      //--------------------------------------
      //  GETTERS/SETTERS
      //--------------------------------------
      
      /**
       * The status of the connection to the Red5 server.
       * If {@code true}, the connection to Red5 is currently available.
       */
      public function get isConnected():Boolean
      {
         return netConn.connected
      }
      
      //Added by rjgtav
      public function get isCasting():Boolean
      {
         return _isCasting
      }
      //rjgtav ends here
      
      //--------------------------------------
      //  COSTRUCTOR
      //--------------------------------------
      
      /**
       * AVCastManager contructor.
       *
       * @param   sfs:   the SmartFoxClient instance.
       * @param   red5Ip:   the Red5 server IP address.
       * @param   debug:   turn on the debug messages (optional, default is {@code false}).
       *
       * @throws   MyUserPropsNotSetException if the <i>SmartFoxClient.myUserId</i> or <i>SmartFoxClient.myUserName</i> properties are not set.
       *
       * @example   The following example shows how to instantiate the AVCastManager class.
       *          <code>
       *          var smartFox:SmartFoxServer = new SmartFoxServer(true)
       *          var red5IpAddress:String = "127.0.0.1"
       *          
       *          var avCastMan:AVCastManager = new AVCastManager(smartFox, red5IpAddress)
       *          </code>
       *
       * see      MyUserPropsNotSetException
       */
      function AVCastManager(sfs:SmartFoxClient, red5Ip:String, debug:Boolean = false)
      {
         // Set reference to SmartFoxCLient instance
         smartFox = sfs
         
         // Check if "myUser" properties are set
         if (!myUserIsValid())
            throw new MyUserPropsNotSetException()
         
         //------------------------------
         
         // Initialize properties
         red5IpAddress = red5Ip
         Logger.enableLog = debug
         netConn = new NetConnection()
         
         // Initialize casts list for the current room
         if (smartFox.getActiveRoom() != null)
            initCastList()
         
         // Add Red5 connection event listener
         netConn.addEventListener(NetStatusEvent.NET_STATUS, onRed5ConnectionStatus)
         
         // Add SmartFoxServer event listeners
         smartFox.addEventListener(SFSEvent.onJoinRoom, onJoinRoom)
         smartFox.addEventListener(SFSEvent.onUserVariablesUpdate, onUserVariablesUpdate)
         smartFox.addEventListener(SFSEvent.onUserLeaveRoom, onUserLeaveRoom)
         smartFox.addEventListener(SFSEvent.onConnectionLost, onUserDisconnection)
         smartFox.addEventListener(SFSEvent.onLogout, onUserDisconnection)
         
         // Establish connection to Red5
         initAVConnection()
      }
      
      // -------------------------------------------------------
      // PUBLIC METHODS
      // -------------------------------------------------------
      
      /**
       * Initialize the audio/video connection.
       * Calling this method causes the connection to Red5 to be established and the {@link RedBoxCastEvent#onAVConnectionInited} event to be fired in response.
       * If the connection can't be established, the {@link RedBoxCastEvent#onAVConnectionError} event is fired in response.
       * <b>NOTE</b>: this method is called automatically when the AVCastManager is instantiated.
       *
       * @sends   RedBoxCastEvent#onAVConnectionInited
       * @sends   RedBoxCastEvent#onAVConnectionError
       *
       * @example   The following example shows how to initialize the Red5 connection for the AVCastManager instance.
       *          <code>
       *          avCastMan.initAVConnection()
       *          </code>
       *
       * @see      #isConnected
       * @see      RedBoxCastEvent#onAVConnectionInited
       * @see      RedBoxCastEvent#onAVConnectionError
       */
      public function initAVConnection():void
      {
         // Connect to Red5 if a connection is not yet available
         if (!netConn.connected)
         {
            netConn.connect("rtmp://" + red5IpAddress + "/" + Constants.RED5_APPLICATION)
         }
         else
         {
            // Dispatch "onAVConnectionInited" event
            dispatchAVCastEvent(RedBoxCastEvent.onAVConnectionInited)
            
            Logger.log("Red5 connection initialized")
         }
      }
      
      /**
       * Destroy the AVCastManager instance.
       * Calling this method causes the interruption of all the playing streams (if any) and the disconnection from Red5.
       * This method should always be called before deleting the AVCastManager instance.
       *
       * @example   The following example shows how to destroy the AVCastManager instance.
       *          <code>
       *          avCastMan.destroy()
       *          avCastMan = null
       *          </code>
       */
      public function destroy():void
      {
         // Remove Red5 connection event listener
         netConn.removeEventListener(NetStatusEvent.NET_STATUS, onRed5ConnectionStatus)
         
         // Remove SmartFoxServer event listeners
         smartFox.removeEventListener(SFSEvent.onJoinRoom, onJoinRoom)
         smartFox.removeEventListener(SFSEvent.onUserVariablesUpdate, onUserVariablesUpdate)
         smartFox.removeEventListener(SFSEvent.onUserLeaveRoom, onUserLeaveRoom)
         smartFox.removeEventListener(SFSEvent.onConnectionLost, onUserDisconnection)
         smartFox.removeEventListener(SFSEvent.onLogout, onUserDisconnection)
         
         // Unpublish outgoing stream
         unpublishLiveCast()
         
         // Unsubscribe all incoming streams
         unsubscribeAllLiveCasts()
         
         castListRequested = false
         castList = null
         castListByUser = null
         
         waitForAllowInterval = null;//Added by rjgtav
         
         // Disconnect from Red5 server
         if (netConn.connected)
            netConn.close()
         
         Logger.log("AVCastManager instance destroyed")
      }
      
      /**
       * Retrieve the list of available live broadcasts for the current room.
       * The list is populated by the {@link AVCastManager} class as soon as it is instantiated and each time a new room is joined.
       * When this method is called, the {@link RedBoxCastEvent#onLiveCastPublished} and {@link RedBoxCastEvent#onLiveCastUnpublished} events dispatching is enabled, in order to be notified when users in the current room start/stop streaming.
       * In order to turn off events notification, the {@link #stopPublishNotification} method should be called.
       *
       * @return   An array of {@link LiveCast} objects.
       *
       * @example   The following example shows how to loop through the list of live casts available for the current room.
       *          <code>
       *          for each (var liveCast:LiveCast in avCastMan.getAvailableCasts())
       *          {
       *             // Subscribe live cast
       *             var stream:NetStream = avCastMan.subscribeLiveCast(liveCast.id)
       *             
       *             // Display a/v stream on stage
       *             ...
       *          }
       *          </code>
       *
       * @see      LiveCast
       * @see      #stopPublishNotification
       */
      public function getAvailableCasts():Array
      {
         castListRequested = true
         
         return castList
      }
      
      /**
       * Stop receiving live cast published/unpublished events.
       *
       * @see      #getAvailableCasts
       */
      public function stopPublishNotification():void
      {
         castListRequested = false
      }
      
      /**
       * Subscribe a live cast to receive its audio/video stream.
       *
       * @param   castId:   (<b>String</b>) the id of the {@link LiveCast} object to be subscribed.
       *
       * @return   A flash.net.NetStream object.
       *
       * @throws   NoAVConnectionException if the connection to Red5 is not available.
       *
       * @example   The following example shows how to subscribe a live cast when a publishing notification is received.
       *          <code>
       *          avCastMan.addEventListener(RedBoxCastEvent.onLiveCastPublished, onLiveCastPublished)
       *          
       *          // A user publishes his own live cast...
       *          
       *          function onLiveCastPublished(evt:RedBoxCastEvent):void
       *          {
       *             var liveCast:LiveCast = evt.params.liveCast
       *             
       *             // Subscribe live cast
       *             var stream:NetStream = avCastMan.subscribeLiveCast(liveCast.id)
       *             
       *             // Display a/v stream on stage
       *             ...
       *          }
       *          </code>
       *
       * @see      #unsubscribeLiveCast
       * @see      NoAVConnectionException
       * @see      flash.net.NetStream
       */
      public function subscribeLiveCast(castId:String):NetStream
      {
         // Check Red5 connection availability
         if (!netConn.connected)
            throw new NoAVConnectionException(Constants.ERROR_NO_CONNECTION + " [subscribeLiveCast method]")
         
         //------------------------------
         
         if (castList != null && castList[castId] != null)
         {
            var liveCast:LiveCast = castList[castId]
            
            var stream:NetStream = new NetStream(netConn)
            stream.play(liveCast.id)
            
            liveCast.setStream(stream)
            
            return liveCast.stream
         }
         
         return null
      }
      
      /**
       * Unsubscribe a live cast to stop receiving its audio/video stream.
       * <b>NOTE</b>: when a user stops his own stream or leaves the current room / disconnects from SmartFoxServer while his stream is in progress, the {@link AVCastManager} class automatically unsubscribes the live cast before dispatching the {@link RedBoxCastEvent#onLiveCastUnpublished} event.
       *
       * @param   castId:   (<b>String</b>) the id of the {@link LiveCast} object to be unsubscribed.
       *
       * @example   The following example shows how to unsubscribe a live cast.
       *          <code>
       *          avCastMan.unsubscribeLiveCast(liveCast.id)
       *          </code>
       *
       * @see      #subscribeLiveCast
       */
      public function unsubscribeLiveCast(castId:String):void
      {
         if (castList != null && castList[castId] != null)
         {
            var liveCast:LiveCast = castList[castId]
            
            // Close incoming stream
            if (liveCast.stream != null)
            {
               liveCast.stream.close()
               liveCast.setStream(null)
            }
         }
      }
      
      /**
       * Unsubscribe all currently subscribed live casts.
       *
       * @see      #unsubscribeLiveCast
       */
      public function unsubscribeAllLiveCasts():void
      {
         if (castList != null)
         {
            for each (var liveCast:LiveCast in castList)
               unsubscribeLiveCast(liveCast.id)
         }
      }
      
      /**
       * Start broadcasting the current user's live stream.
       * Calling this method causes the {@link RedBoxCastEvent#onLiveCastPublished} event to be fired on the other users clients.
       * Audio and video recording mode/quality should be set before calling this method. In order to alter these settings, please refer to the flash.media.Microphone and flash.media.Camera classes documentation.
       *
       * @param   enableCamera:      enable video live streaming; default value is {@code true}.
       * @param   enableMicrophone:   enable audio live streaming; default value is {@code true}.
       *
       * @return   The flash.net.NetStream object representing the user's outgoing stream.
       *
       * @sends   RedBoxCastEvent#onLiveCastPublished
       *
       * @throws   NoAVConnectionException if the connection to Red5 is not available.
       * @throws   InvalidParamsException if both <i>enableCamera</i> and <i>enableMicrophone</i> parameters are set to {@code false}.
       *
       * @example   The following example shows how to publish the current user's live stream.
       *          <code>
       *          avCastman.publishLiveCast(true, true)
       *          </code>
       *
       * @see      #unpublishLiveCast
       * @see      RedBoxCastEvent#onLiveCastPublished
       * @see      NoAVConnectionException
       * @see      InvalidParamsException
       * @see      flash.media.Camera
       * @see      flash.media.Microphone
       * @see      flash.net.NetStream
       */
      public function publishLiveCast(enableCamera:Boolean = true, enableMicrophone:Boolean = true, waitSeconds:Number = 5):NetStream
      {
         // If cam & mic are both null, why sending this type of request?
         if (!enableCamera && !enableMicrophone)
            throw new InvalidParamsException(Constants.ERROR_INVALID_PARAMS)
         
         // Check Red5 connection availability
         if (!netConn.connected)
            throw new NoAVConnectionException(Constants.ERROR_NO_CONNECTION + " [publishLiveCast method]")
         
         //------------------------------
         
         if (myLiveCast == null)
         {
            myLiveCast = new NetStream(netConn)
            
            // Attach cam and mic to the stream
            if (enableCamera)
               camera = Camera.getCamera();//added by rjgtav
               myLiveCast.attachCamera(camera)
            
            if (enableMicrophone)
               microphone = Microphone.getMicrophone();//added by rjgtav
               myLiveCast.attachAudio(microphone)
               
            //added by rjgtav
            this.enableCamera = enableCamera;
            this.enableMicrophone = enableMicrophone;
            
            if((enableCamera && !camera.muted) || (enableMicrophone && !microphone.muted)){
               //The user has already allowed the app to use the mic or the cam or both.
               //We can publish the stream
               publishMyLiveCast();
            }else{
               //The user hasn't allowed yet the app to use the mic and the cam
               //We'll wait some seconds for the user to click the "Allow" button,
               //before we publish the stream and update the UV's
               this.waitForAllowInterval.delay = waitSeconds*1000;
               this.waitForAllowInterval.addEventListener(TimerEvent.TIMER, publishMyLiveCast, false, 0, true);
               this.waitForAllowInterval.start();
            }
            //rjgtav ends here
            
            return myLiveCast
         }
         
         return null
      }
      
      /**
       * Stop broadcasting the current user's live stream.
       * Calling this method causes the {@link RedBoxCastEvent#onLiveCastUnpublished} event to be fired on the other users clients.
       *
       * @sends   RedBoxCastEvent#onLiveCastUnpublished
       *
       * @example   The following example shows how to unpublish a live cast.
       *          <code>
       *          avCastMan.unpublishLiveCast()
       *          </code>
       *
       * @see      #publishLiveCast
       * @see      RedBoxCastEvent#onLiveCastUnpublished
       */
      public function unpublishLiveCast():void//Edited by rjgtav
      {
         // Stop outgoing stream
         if (myLiveCast != null)
         {
            myLiveCast.close()
            myLiveCast = null
         }
         
         // Reset user variable
         if (smartFox.isConnected && _isCasting)
         {
            _isCasting = false;
            
            var userVar:Object = {}
            userVar[CAST_USER_VAR] = null
            
            smartFox.setUserVariables(userVar)
         }
         
         //Added by rjgtav
         //Stops the timer, in case the user unpublishes the stream earlier than expected
         this.waitForAllowInterval.stop();
         this.waitForAllowInterval.removeEventListener(TimerEvent.TIMER, publishMyLiveCast);
      }
      
      // -------------------------------------------------------
      // SMARTFOXSERVER & RED5 EVENT HANDLERS
      // -------------------------------------------------------
      
      /**
       * Handle room joined event.
       *
       * @exclude
       */
      public function onJoinRoom(evt:SFSEvent):void
      {
         // Unpublish outgoing stream
         unpublishLiveCast()
         
         // Unsubscribe all incoming streams
         unsubscribeAllLiveCasts()
         
         // Re-initialize live casts list
         initCastList()
      }
      
      /**
       * Handle user variables update event.
       *
       * @exclude
       */
      public function onUserVariablesUpdate(evt:SFSEvent):void
      {
         // Check if the proper variable has changed
         if (evt.params.changedVars[CAST_USER_VAR] != null && castList != null)
          {
             var castId:String = evt.params.user.getVariable(CAST_USER_VAR)
             var userId:int = evt.params.user.getId()
             var userName:String = evt.params.user.getName()
             
             if (castId != null)
             {
                Logger.log("User '" + userName + "' published his live cast:", castId)
                
                // Add new live cast to list
                addLiveCast(castId, userId, userName, true)
             }
             else
             {
                Logger.log("User '" + userName + "' unpublished his live cast")
                
                // Remove live cast from list
                removeLiveCast(userId)
             }
          }
      }
      
      /**
       * Handle user leaving current room.
       *
       * @exclude
       */
      public function onUserLeaveRoom(evt:SFSEvent):void
      {
         var userId:int = evt.params.userId
         
         // Remove live cast from list
          var removed:Boolean = removeLiveCast(userId)
         
          if (removed)
             Logger.log("User '" + evt.params.userName + "' left the room; live cast removed")
      }
      
      /**
       * Handle user logout and disconnection events.
       *
       * @exclude
       */
      public function onUserDisconnection(evt:SFSEvent):void
      {
         // Reset AVCastManager instance
         destroy()
      }
      
      /**
       * Handle Red5 connection status events.
       *
       * @exclude
       */
      public function onRed5ConnectionStatus(evt:NetStatusEvent):void
      {
         var code:String = evt.info.code
         var level:String = evt.info.level
         
         Logger.log("NetStatusEvent response received")
         Logger.log("Level: " + level, "| Code:" + code)
         
         switch (code)
         {
            case "NetConnection.Connect.Success":
               
               Logger.log("NetConnection successful")
               
               // Call the "initialize" method which will dispatch the "onAVConnectionInited" event
               initAVConnection()
               
               break
            
            case "NetConnection.Connect.Closed":
            case "NetConnection.Connect.Failed":
            case "NetConnection.Connect.Rejected":
            case "NetConnection.Connect.AppShutDown":
            case "NetConnection.Connect.InvalidApp":
               
               Logger.log("NetConnection error, dispatching event...")
               
               // Unpublish outgoing stream
               unpublishLiveCast()
               
               // Unsubscribe all incoming streams
               unsubscribeAllLiveCasts()
               
               // Dispatch connection error event
               var params:Object = {}
               params.errorCode = code
               
               dispatchAVCastEvent(RedBoxCastEvent.onAVConnectionError, params)
               
               break
         }
      }
      
      // -------------------------------------------------------
      // PRIVATE METHODS
      // -------------------------------------------------------
      
      /**
       * Dispatch AVCastManager events.
       */
      private function dispatchAVCastEvent(type:String, params:Object = null):void
      {
         var event:RedBoxCastEvent = new RedBoxCastEvent(type, params)
         dispatchEvent(event)
      }
      
      /**
       * Check if SmartFoxClient.myUserId and SmartFoxClient.myUserName are set.
       */
      private function myUserIsValid():Boolean
      {
         return (smartFox.myUserId >= 0 && smartFox.myUserName != "" && smartFox.myUserName != null)
      }
      
      /**
       * Initialize the available live casts list for the current room.
       */
      private function initCastList():void
      {
         Logger.log("Initializing Live Casts list for current room...")
         
         castListRequested = false
         
         castList = new Array()
         castListByUser = new Array()
         
         var currRoom:Room = smartFox.getActiveRoom()
         
         for each (var user:User in currRoom.getUserList())
         {
            // Exclude my own cast
            if (user.getId() != smartFox.myUserId)
            {
               var castId:String = (user.getVariable(CAST_USER_VAR) != undefined ? user.getVariable(CAST_USER_VAR) : "")
               
               if (castId != null && castId != "")
               {
                  Logger.log("Live cast found for user", user.getName())
                  
                  // Add live cast to list
                  addLiveCast(castId, user.getId(), user.getName(), false)
               }
            }
         }
      }
      
      /**
       * Add live cast to list.
       */
      private function addLiveCast(id:String, userId:int, userName:String, fireEvent:Boolean = true):void
      {
         // Create new live cast
         var params:Object = {}
         params.id = id
         params.uId = userId
         params.uName = userName
         
         var liveCast:LiveCast = new LiveCast(params)
         
         // Add cast to list
         castList[id] = liveCast
         castListByUser[userId] = liveCast
         
         // Dispatch event (only if the cast list has already been requested)
          if (fireEvent && castListRequested)
          {
             params = {}
            params.liveCast = liveCast
            
            dispatchAVCastEvent(RedBoxCastEvent.onLiveCastPublished, params)
         }
      }
      
      /**
       * Remove live cast from list.
       */
      private function removeLiveCast(userId:int):Boolean
      {
         if (castListByUser != null && castListByUser[userId] != null)
         {
            var liveCast:LiveCast = castListByUser[userId]
            
            // Unsubscribe live cast
             unsubscribeLiveCast(liveCast.id)
             
             // Dispatch event (only if the cast list has already been requested)
             if (castListRequested)
             {
                var params:Object = {}
               params.liveCast = liveCast
               
               dispatchAVCastEvent(RedBoxCastEvent.onLiveCastUnpublished, params)
             }
             
             // Remove cast from casts list
            delete castList[liveCast.id]
            delete castListByUser[userId]
            
            return true
           }
           
           return false
      }
      
      //Added by rjgtav
      /**
       * Publishes the Live Cast and updates the user's UV
       */
      private function publishMyLiveCast():Void
      {
         //We only publish the stream if the user allowed the application
         if((enableCamera && !camera.muted) || (enableMicrophone && !microphone.muted)){
            // Generate stream id
            var now:Date = new Date()
            var month:int = now.getUTCMonth() + 1
            var dateString:String = now.getUTCFullYear().toString() + (month < 10 ? "0" : "") + month.toString() + now.getUTCDate().toString()
            var timeString:String = now.getUTCHours().toString() + now.getUTCMinutes().toString() + now.getUTCSeconds().toString() + now.getUTCMilliseconds().toString()
            var roomId:int = smartFox.activeRoomId
            var userId:int = smartFox.myUserId
            
            var liveCastId:String = roomId + "_" + dateString + timeString + "_" + userId
            
            // Publish live stream
            myLiveCast.publish(liveCastId, Constants.BROADCAST_TYPE_LIVE)
            
            // Set user variable
            var userVar:Object = {}
            userVar[CAST_USER_VAR] = liveCastId
            smartFox.setUserVariables(userVar)
            
            _isCasting = true;
            
            Logger.log("User own live cast published; id:", liveCastId)
         }else{
            Logger.log("User didn't allow the app to use the cam and/or mic. No cast is going to be published.")
            unpublishLiveCast()
         }
         
         //Clear the interval
         waitForAllowInterval.stop();
         waitForAllowInterval.removeEventListener(TimerEvent.TIMER, publishMyLiveCast)
      }
      //rjgtav ends here
   }
}


Hope this works. Any issue or doubt, feel free to report.
Skills: SFS Pro, SFS2X, AS2.0/AS3.0, Java, HTML5/CSS3/JS, C#
Portfolio: https://rjgtav.wordpress.com/
SFS Tutorials: http://sfs-tutor.blogspot.com/ - Discontinued. Some examples may be bugged.
supermk88
Posts: 239
Joined: 18 Mar 2011, 12:30

Re: I need help for your videoconference

Postby supermk88 » 21 Nov 2012, 00:51

Hi very thx for the help ^^ but i have a problem i'm using smartfox server pro 1.6.9 and i have see that in your av cast manager you have import something from smartfoxbits.. When i try to build there are some error, if you can help me this is the avcastmanager that i use:

Code: Select all

package com.smartfoxserver.redbox
{
   import com.smartfoxserver.redbox.data.LiveCast;
   import com.smartfoxserver.redbox.events.RedBoxCastEvent;
   import com.smartfoxserver.redbox.exceptions.*;
   import com.smartfoxserver.redbox.utils.Constants;
   import com.smartfoxserver.redbox.utils.Logger;
   
   import flash.events.EventDispatcher;
   import flash.events.NetStatusEvent;
   import flash.media.Camera;
   import flash.media.Microphone;
   import flash.media.SoundCodec;
   import flash.net.NetConnection;
   import flash.net.NetStream;
   
   import it.gotoandplay.smartfoxserver.SFSEvent;
   import it.gotoandplay.smartfoxserver.SmartFoxClient;
   import it.gotoandplay.smartfoxserver.data.Room;
   import it.gotoandplay.smartfoxserver.data.User;

   /**
    * SmartFoxServer's RedBox Audio/Video Broadcast Manager.
    * This class is responsible for managing audio/video live casts inside the room joined by the user, making it possible to create live web events or a/v conferences.
    * The AVCastManager handles the live cast publishing/playing to/from the Red5 server.
    * Unlike the other RedBox classes, the AVCastManager works on a room basis to leverage the access control and moderation features of SmartFoxServer rooms.
    *
    * <b>NOTE</b>: in the provided examples, {@code avCastMan} always indicates an AVCastManager instance.
    *
    * @usage   The most common usages for the <b>AVCastManager</b> class are video conference applications and live webcast applications (for example live online seminars).
    *          
    *          <i>Video conference</i>
    *          In this kind of application, each user publishes his own live stream and subscribes the streams coming from the other users in the same room (in the SmartFoxServer meaning). The following workflow is suggested.
    *          <ol>
    *             <li>The current user joins the room where the video conference takes place.</li>
    *             <li>The list of currently available streams (or "live casts") is retrieved by means of the {@link #getAvailableCasts} method (in case the conference is already in progress).
    *             Calling this method also enables the reception of the {@link RedBoxCastEvent#onLiveCastPublished} and {@link RedBoxCastEvent#onLiveCastUnpublished} events which notify that another user started or stopped his own stream.</li>
    *             <li>Each live cast is subscribed by means of the {@link #subscribeLiveCast} method and a Video object is displayed on the stage to attach the stream to.
    *             When a live cast is published (a new user joins the conference) or stopped (a user leaves the conference), a notification is received by means of the above mentioned events: the stream is subscribed / unsubscribed and displayed on / removed from the stage.</li>
    *             <li>The a/v stream for the current user is published by means of the {@link #publishLiveCast} method and an additional Video object showing the user own camera stream is added on the stage; when the current user publishes his own stream, the other users receive the above mentioned events.</li>
    *             <li>To make the current user leave the conference, the {@link #unpublishLiveCast} method is called. Also changing SmartFoxServer room causes the user to leave the conference and the other users to be notified.</li>
    *          </ol>
    *          <hr />
    *          <i>Live webcast</i>
    *          In this kind of application, a single user publishes his own live stream and all the other users in the same room subscribe it. The following workflow is suggested.
    *          <ol>
    *             <li>The publisher joins the room where the live webcast takes place.</li>
    *             <li>The a/v stream for the user is published by means of the {@link #publishLiveCast} method and a Video object showing the user own camera stream is added on the stage; when the current user publishes his own stream, the other users already in the room receive the {@link RedBoxCastEvent#onLiveCastPublished} event and the stream can be subscribed (see step 4).</li>
    *             <li>The webcast spectators join the room and retrieve the list of available streams (one item only if the publisher is already streaming, otherwise the list will be empty).</li>
    *             <li>If the live webcast is already started, it can be subscribed by means of the {@link #subscribeLiveCast} method; otherwise the {@link RedBoxCastEvent#onLiveCastPublished} event must be waited for before calling this method.</li>
    *             <li>On all the subscribers clients a Video object is displayed on the stage to attach the stream to.</li>
    *          </ol>
    *
    * @version   1.0.0
    *
    * @author   The gotoAndPlay() Team
    *          {@link http://www.smartfoxserver.com}
    *          {@link http://www.gotoandplay.it}
    */
   public class AVCastManager extends EventDispatcher
   {
      //--------------------------------------
      // CLASS CONSTANTS
      //--------------------------------------
      
      private const CAST_USER_VAR:String = "$RB_castId"
      
      //--------------------------------------
      //  PRIVATE VARIABLES
      //--------------------------------------
      
      private var smartFox:SmartFoxClient
      private var red5IpAddress:String
      private var netConn:NetConnection
      private var castList:Array
      private var castListByUser:Array
      private var myLiveCast:NetStream
      private var castListRequested:Boolean
      
      //--------------------------------------
      //  GETTERS/SETTERS
      //--------------------------------------
      
      /**
       * The status of the connection to the Red5 server.
       * If {@code true}, the connection to Red5 is currently available.
       */
      public function get isConnected():Boolean
      {
         return netConn.connected
      }
      
      //--------------------------------------
      //  COSTRUCTOR
      //--------------------------------------
      
      /**
       * AVCastManager contructor.
       *
       * @param   sfs:   the SmartFoxClient instance.
       * @param   red5Ip:   the Red5 server IP address.
       * @param   debug:   turn on the debug messages (optional, default is {@code false}).
       *
       * @throws   MyUserPropsNotSetException if the <i>SmartFoxClient.myUserId</i> or <i>SmartFoxClient.myUserName</i> properties are not set.
       *
       * @example   The following example shows how to instantiate the AVCastManager class.
       *          <code>
       *          var smartFox:SmartFoxServer = new SmartFoxServer(true)
       *          var red5IpAddress:String = "127.0.0.1"
       *          
       *          var avCastMan:AVCastManager = new AVCastManager(smartFox, red5IpAddress)
       *          </code>
       *
       * see      MyUserPropsNotSetException
       */
      function AVCastManager(sfs:SmartFoxClient, red5Ip:String, debug:Boolean = false)
      {
         // Set reference to SmartFoxCLient instance
         smartFox = sfs
         
         // Check if "myUser" properties are set
         if (!myUserIsValid())
            throw new MyUserPropsNotSetException()
         
         //------------------------------
         
         // Initialize properties
         red5IpAddress = red5Ip
         Logger.enableLog = debug
         netConn = new NetConnection()
         
         // Initialize casts list for the current room
         if (smartFox.getActiveRoom() != null)
            initCastList()
         
         // Add Red5 connection event listener
         netConn.addEventListener(NetStatusEvent.NET_STATUS, onRed5ConnectionStatus)
         
         // Add SmartFoxServer event listeners
         smartFox.addEventListener(SFSEvent.onJoinRoom, onJoinRoom)
         smartFox.addEventListener(SFSEvent.onUserVariablesUpdate, onUserVariablesUpdate)
         smartFox.addEventListener(SFSEvent.onUserLeaveRoom, onUserLeaveRoom)
         smartFox.addEventListener(SFSEvent.onConnectionLost, onUserDisconnection)
         smartFox.addEventListener(SFSEvent.onLogout, onUserDisconnection)
         
         // Establish connection to Red5
         initAVConnection()
      }
      
      // -------------------------------------------------------
      // PUBLIC METHODS
      // -------------------------------------------------------
      
      /**
       * Initialize the audio/video connection.
       * Calling this method causes the connection to Red5 to be established and the {@link RedBoxCastEvent#onAVConnectionInited} event to be fired in response.
       * If the connection can't be established, the {@link RedBoxCastEvent#onAVConnectionError} event is fired in response.
       * <b>NOTE</b>: this method is called automatically when the AVCastManager is instantiated.
       *
       * @sends   RedBoxCastEvent#onAVConnectionInited
       * @sends   RedBoxCastEvent#onAVConnectionError
       *
       * @example   The following example shows how to initialize the Red5 connection for the AVCastManager instance.
       *          <code>
       *          avCastMan.initAVConnection()
       *          </code>
       *
       * @see      #isConnected
       * @see      RedBoxCastEvent#onAVConnectionInited
       * @see      RedBoxCastEvent#onAVConnectionError
       */
      public function initAVConnection():void
      {
         // Connect to Red5 if a connection is not yet available
         if (!netConn.connected)
         {
            netConn.connect("rtmp://" + red5IpAddress + "/" + Constants.RED5_APPLICATION)
         }
         else
         {
            // Dispatch "onAVConnectionInited" event
            dispatchAVCastEvent(RedBoxCastEvent.onAVConnectionInited)
            
            Logger.log("Red5 connection initialized")
         }
      }
      
      /**
       * Destroy the AVCastManager instance.
       * Calling this method causes the interruption of all the playing streams (if any) and the disconnection from Red5.
       * This method should always be called before deleting the AVCastManager instance.
       *
       * @example   The following example shows how to destroy the AVCastManager instance.
       *          <code>
       *          avCastMan.destroy()
       *          avCastMan = null
       *          </code>
       */
      public function destroy():void
      {
         // Remove Red5 connection event listener
         netConn.removeEventListener(NetStatusEvent.NET_STATUS, onRed5ConnectionStatus)
         
         // Remove SmartFoxServer event listeners
         smartFox.removeEventListener(SFSEvent.onJoinRoom, onJoinRoom)
         smartFox.removeEventListener(SFSEvent.onUserVariablesUpdate, onUserVariablesUpdate)
         smartFox.removeEventListener(SFSEvent.onUserLeaveRoom, onUserLeaveRoom)
         smartFox.removeEventListener(SFSEvent.onConnectionLost, onUserDisconnection)
         smartFox.removeEventListener(SFSEvent.onLogout, onUserDisconnection)
         
         // Unpublish outgoing stream
         unpublishLiveCast()
         
         // Unsubscribe all incoming streams
         unsubscribeAllLiveCasts()
         
         castListRequested = false
         castList = null
         castListByUser = null
         
         // Disconnect from Red5 server
         if (netConn.connected)
            netConn.close()
         
         Logger.log("AVCastManager instance destroyed")
      }
      
      /**
       * Retrieve the list of available live broadcasts for the current room.
       * The list is populated by the {@link AVCastManager} class as soon as it is instantiated and each time a new room is joined.
       * When this method is called, the {@link RedBoxCastEvent#onLiveCastPublished} and {@link RedBoxCastEvent#onLiveCastUnpublished} events dispatching is enabled, in order to be notified when users in the current room start/stop streaming.
       * In order to turn off events notification, the {@link #stopPublishNotification} method should be called.
       *
       * @return   An array of {@link LiveCast} objects.
       *
       * @example   The following example shows how to loop through the list of live casts available for the current room.
       *          <code>
       *          for each (var liveCast:LiveCast in avCastMan.getAvailableCasts())
       *          {
       *             // Subscribe live cast
       *             var stream:NetStream = avCastMan.subscribeLiveCast(liveCast.id)
       *             
       *             // Display a/v stream on stage
       *             ...
       *          }
       *          </code>
       *
       * @see      LiveCast
       * @see      #stopPublishNotification
       */
      public function getAvailableCasts():Array
      {
         castListRequested = true
         
         return castList
      }
      
      /**
       * Stop receiving live cast published/unpublished events.
       *
       * @see      #getAvailableCasts
       */
      public function stopPublishNotification():void
      {
         castListRequested = false
      }
      
      /**
       * Subscribe a live cast to receive its audio/video stream.
       *
       * @param   castId:   (<b>String</b>) the id of the {@link LiveCast} object to be subscribed.
       *
       * @return   A flash.net.NetStream object.
       *
       * @throws   NoAVConnectionException if the connection to Red5 is not available.
       *
       * @example   The following example shows how to subscribe a live cast when a publishing notification is received.
       *          <code>
       *          avCastMan.addEventListener(RedBoxCastEvent.onLiveCastPublished, onLiveCastPublished)
       *          
       *          // A user publishes his own live cast...
       *          
       *          function onLiveCastPublished(evt:RedBoxCastEvent):void
       *          {
       *             var liveCast:LiveCast = evt.params.liveCast
       *             
       *             // Subscribe live cast
       *             var stream:NetStream = avCastMan.subscribeLiveCast(liveCast.id)
       *             
       *             // Display a/v stream on stage
       *             ...
       *          }
       *          </code>
       *
       * @see      #unsubscribeLiveCast
       * @see      NoAVConnectionException
       * @see      flash.net.NetStream
       */
      public function subscribeLiveCast(castId:String):NetStream
      {
         // Check Red5 connection availability
         if (!netConn.connected)
            throw new NoAVConnectionException(Constants.ERROR_NO_CONNECTION + " [subscribeLiveCast method]")
         
         //------------------------------
         
         if (castList != null && castList[castId] != null)
         {
            var liveCast:LiveCast = castList[castId]
            
            var stream:NetStream = new NetStream(netConn)
            stream.play(liveCast.id)
            
            liveCast.setStream(stream)
            
            return liveCast.stream
         }
         
         return null
      }
      
      /**
       * Unsubscribe a live cast to stop receiving its audio/video stream.
       * <b>NOTE</b>: when a user stops his own stream or leaves the current room / disconnects from SmartFoxServer while his stream is in progress, the {@link AVCastManager} class automatically unsubscribes the live cast before dispatching the {@link RedBoxCastEvent#onLiveCastUnpublished} event.
       *
       * @param   castId:   (<b>String</b>) the id of the {@link LiveCast} object to be unsubscribed.
       *
       * @example   The following example shows how to unsubscribe a live cast.
       *          <code>
       *          avCastMan.unsubscribeLiveCast(liveCast.id)
       *          </code>
       *
       * @see      #subscribeLiveCast
       */
      public function unsubscribeLiveCast(castId:String):void
      {
         if (castList != null && castList[castId] != null)
         {
            var liveCast:LiveCast = castList[castId]
            
            // Close incoming stream
            if (liveCast.stream != null)
            {
               liveCast.stream.close()
               liveCast.setStream(null)
            }
         }
      }
      
      /**
       * Unsubscribe all currently subscribed live casts.
       *
       * @see      #unsubscribeLiveCast
       */
      public function unsubscribeAllLiveCasts():void
      {
         if (castList != null)
         {
            for each (var liveCast:LiveCast in castList)
               unsubscribeLiveCast(liveCast.id)
         }
      }
      
      /**
       * Start broadcasting the current user's live stream.
       * Calling this method causes the {@link RedBoxCastEvent#onLiveCastPublished} event to be fired on the other users clients.
       * Audio and video recording mode/quality should be set before calling this method. In order to alter these settings, please refer to the flash.media.Microphone and flash.media.Camera classes documentation.
       *
       * @param   enableCamera:      enable video live streaming; default value is {@code true}.
       * @param   enableMicrophone:   enable audio live streaming; default value is {@code true}.
       *
       * @return   The flash.net.NetStream object representing the user's outgoing stream.
       *
       * @sends   RedBoxCastEvent#onLiveCastPublished
       *
       * @throws   NoAVConnectionException if the connection to Red5 is not available.
       * @throws   InvalidParamsException if both <i>enableCamera</i> and <i>enableMicrophone</i> parameters are set to {@code false}.
       *
       * @example   The following example shows how to publish the current user's live stream.
       *          <code>
       *          avCastman.publishLiveCast(true, true)
       *          </code>
       *
       * @see      #unpublishLiveCast
       * @see      RedBoxCastEvent#onLiveCastPublished
       * @see      NoAVConnectionException
       * @see      InvalidParamsException
       * @see      flash.media.Camera
       * @see      flash.media.Microphone
       * @see      flash.net.NetStream
       */
      public function publishLiveCast(enableCamera:Boolean = true, enableMicrophone:Boolean = true):NetStream
      {
         // If cam & mic are both null, why sending this type of request?
         if (!enableCamera && !enableMicrophone)
            throw new InvalidParamsException(Constants.ERROR_INVALID_PARAMS)
         
         // Check Red5 connection availability
         if (!netConn.connected)
            throw new NoAVConnectionException(Constants.ERROR_NO_CONNECTION + " [publishLiveCast method]")
         
         //------------------------------
         
         if (myLiveCast == null)
         {
            myLiveCast = new NetStream(netConn)
            
            // Attach cam and mic to the stream
            if (enableCamera)
               myLiveCast.attachCamera(Camera.getCamera())
            
            if (enableMicrophone){

var _microphone:Microphone = Microphone.getMicrophone();
if (_microphone) {
   
_microphone.setSilenceLevel(0);
_microphone.codec = SoundCodec.SPEEX;
_microphone.encodeQuality = 10;
_microphone.rate = 16;
_microphone.framesPerPacket = 1;
_microphone.gain = 80;
_microphone.setUseEchoSuppression(false);
   
   
    myLiveCast.attachAudio(_microphone);
} else {
   
}


}
               
            
            // Generate stream id
            var now:Date = new Date()
            var month:int = now.getUTCMonth() + 1
            var dateString:String = now.getUTCFullYear().toString() + (month < 10 ? "0" : "") + month.toString() + now.getUTCDate().toString()
            var timeString:String = now.getUTCHours().toString() + now.getUTCMinutes().toString() + now.getUTCSeconds().toString() + now.getUTCMilliseconds().toString()
            var roomId:int = smartFox.activeRoomId
            var userId:int = smartFox.myUserId
            
            var liveCastId:String = roomId + "_" + dateString + timeString + "_" + userId
            
            // Publish live stream
            myLiveCast.publish(liveCastId, Constants.BROADCAST_TYPE_LIVE)
            
            // Set user variable
            var userVar:Object = {}
            userVar[CAST_USER_VAR] = liveCastId
            smartFox.setUserVariables(userVar)
            
            Logger.log("User own live cast published; id:", liveCastId)
            
            return myLiveCast
         }
         
         return null
      }
      
      /**
       * Stop broadcasting the current user's live stream.
       * Calling this method causes the {@link RedBoxCastEvent#onLiveCastUnpublished} event to be fired on the other users clients.
       *
       * @sends   RedBoxCastEvent#onLiveCastUnpublished
       *
       * @example   The following example shows how to unpublish a live cast.
       *          <code>
       *          avCastMan.unpublishLiveCast()
       *          </code>
       *
       * @see      #publishLiveCast
       * @see      RedBoxCastEvent#onLiveCastUnpublished
       */
      public function unpublishLiveCast():void
      {
         // Stop outgoing stream
         if (myLiveCast != null)
         {
            myLiveCast.close()
            myLiveCast = null
            
            // Reset user variable
            if (smartFox.isConnected)
            {
               var userVar:Object = {}
               userVar[CAST_USER_VAR] = null
               
               smartFox.setUserVariables(userVar)
            }
         }
      }
      
      // -------------------------------------------------------
      // SMARTFOXSERVER & RED5 EVENT HANDLERS
      // -------------------------------------------------------
      
      /**
       * Handle room joined event.
       *
       * @exclude
       */
      public function onJoinRoom(evt:SFSEvent):void
      {
         // Unpublish outgoing stream
         unpublishLiveCast()
         
         // Unsubscribe all incoming streams
         unsubscribeAllLiveCasts()
         
         // Re-initialize live casts list
         initCastList()
      }
      
      /**
       * Handle user variables update event.
       *
       * @exclude
       */
      public function onUserVariablesUpdate(evt:SFSEvent):void
      {
         // Check if the proper variable has changed
         if (evt.params.changedVars[CAST_USER_VAR] != null && castList != null)
          {
             var castId:String = evt.params.user.getVariable(CAST_USER_VAR)
             var userId:int = evt.params.user.getId()
             var userName:String = evt.params.user.getName()
             
             if (castId != null)
             {
                Logger.log("User '" + userName + "' published his live cast:", castId)
                
                // Add new live cast to list
                addLiveCast(castId, userId, userName, true)
             }
             else
             {
                Logger.log("User '" + userName + "' unpublished his live cast")
                
                // Remove live cast from list
                removeLiveCast(userId)
             }
          }
      }
      
      /**
       * Handle user leaving current room.
       *
       * @exclude
       */
      public function onUserLeaveRoom(evt:SFSEvent):void
      {
         var userId:int = evt.params.userId
         
         // Remove live cast from list
          var removed:Boolean = removeLiveCast(userId)
         
          if (removed)
             Logger.log("User '" + evt.params.userName + "' left the room; live cast removed")
      }
      
      /**
       * Handle user logout and disconnection events.
       *
       * @exclude
       */
      public function onUserDisconnection(evt:SFSEvent):void
      {
         // Reset AVCastManager instance
         destroy()
      }
      
      /**
       * Handle Red5 connection status events.
       *
       * @exclude
       */
      public function onRed5ConnectionStatus(evt:NetStatusEvent):void
      {
         var code:String = evt.info.code
         var level:String = evt.info.level
         
         Logger.log("NetStatusEvent response received")
         Logger.log("Level: " + level, "| Code:" + code)
         
         switch (code)
         {
            case "NetConnection.Connect.Success":
               
               Logger.log("NetConnection successful")
               
               // Call the "initialize" method which will dispatch the "onAVConnectionInited" event
               initAVConnection()
               
               break
            
            case "NetConnection.Connect.Closed":
            case "NetConnection.Connect.Failed":
            case "NetConnection.Connect.Rejected":
            case "NetConnection.Connect.AppShutDown":
            case "NetConnection.Connect.InvalidApp":
               
               Logger.log("NetConnection error, dispatching event...")
               
               // Unpublish outgoing stream
               unpublishLiveCast()
               
               // Unsubscribe all incoming streams
               unsubscribeAllLiveCasts()
               
               // Dispatch connection error event
               var params:Object = {}
               params.errorCode = code
               
               dispatchAVCastEvent(RedBoxCastEvent.onAVConnectionError, params)
               
               break
         }
      }
      
      // -------------------------------------------------------
      // PRIVATE METHODS
      // -------------------------------------------------------
      
      /**
       * Dispatch AVCastManager events.
       */
      private function dispatchAVCastEvent(type:String, params:Object = null):void
      {
         var event:RedBoxCastEvent = new RedBoxCastEvent(type, params)
         dispatchEvent(event)
      }
      
      /**
       * Check if SmartFoxClient.myUserId and SmartFoxClient.myUserName are set.
       */
      private function myUserIsValid():Boolean
      {
         return (smartFox.myUserId >= 0 && smartFox.myUserName != "" && smartFox.myUserName != null)
      }
      
      /**
       * Initialize the available live casts list for the current room.
       */
      private function initCastList():void
      {
         Logger.log("Initializing Live Casts list for current room...")
         
         castListRequested = false
         
         castList = new Array()
         castListByUser = new Array()
         
         var currRoom:Room = smartFox.getActiveRoom()
         
         for each (var user:User in currRoom.getUserList())
         {
            // Exclude my own cast
            if (user.getId() != smartFox.myUserId)
            {
               var castId:String = (user.getVariable(CAST_USER_VAR) != undefined ? user.getVariable(CAST_USER_VAR) : "")
               
               if (castId != null && castId != "")
               {
                  Logger.log("Live cast found for user", user.getName())
                  
                  // Add live cast to list
                  addLiveCast(castId, user.getId(), user.getName(), false)
               }
            }
         }
      }
      
      /**
       * Add live cast to list.
       */
      private function addLiveCast(id:String, userId:int, userName:String, fireEvent:Boolean = true):void
      {
         // Create new live cast
         var params:Object = {}
         params.id = id
         params.uId = userId
         params.uName = userName
         
         var liveCast:LiveCast = new LiveCast(params)
         
         // Add cast to list
         castList[id] = liveCast
         castListByUser[userId] = liveCast
         
         // Dispatch event (only if the cast list has already been requested)
          if (fireEvent && castListRequested)
          {
             params = {}
            params.liveCast = liveCast
            
            dispatchAVCastEvent(RedBoxCastEvent.onLiveCastPublished, params)
         }
      }
      
      /**
       * Remove live cast from list.
       */
      private function removeLiveCast(userId:int):Boolean
      {
         if (castListByUser != null && castListByUser[userId] != null)
         {
            var liveCast:LiveCast = castListByUser[userId]
            
            // Unsubscribe live cast
             unsubscribeLiveCast(liveCast.id)
             
             // Dispatch event (only if the cast list has already been requested)
             if (castListRequested)
             {
                var params:Object = {}
               params.liveCast = liveCast
               
               dispatchAVCastEvent(RedBoxCastEvent.onLiveCastUnpublished, params)
             }
             
             // Remove cast from casts list
            delete castList[liveCast.id]
            delete castListByUser[userId]
            
            return true
           }
           
           return false
      }
   }
}


I have try to change your code but there are some thing that i don't understand and make always an error hehe ^^
User avatar
rjgtav
Posts: 2813
Joined: 19 Apr 2009, 11:31
Location: Lisbon, Portugal

Re: I need help for your videoconference

Postby rjgtav » 21 Nov 2012, 16:21

I'm sorry, I forgot to say that the version I had published was for ActionScript 2.0. I have updated the previous post and added the ActionScript 3.0 version, which is the one you're using
Skills: SFS Pro, SFS2X, AS2.0/AS3.0, Java, HTML5/CSS3/JS, C#
Portfolio: https://rjgtav.wordpress.com/
SFS Tutorials: http://sfs-tutor.blogspot.com/ - Discontinued. Some examples may be bugged.
supermk88
Posts: 239
Joined: 18 Mar 2011, 12:30

Re: I need help for your videoconference

Postby supermk88 » 21 Nov 2012, 19:03

Hi thx for the update ^^ there are some issue that appear when i try to compile in this function

Code: Select all

 private function publishMyLiveCast():Void
      {
         //We only publish the stream if the user allowed the application
         if((enableCamera && !camera.muted) || (enableMicrophone && !microphone.muted)){
            // Generate stream id
            var now:Date = new Date()
            var month:int = now.getUTCMonth() + 1
            var dateString:String = now.getUTCFullYear().toString() + (month < 10 ? "0" : "") + month.toString() + now.getUTCDate().toString()
            var timeString:String = now.getUTCHours().toString() + now.getUTCMinutes().toString() + now.getUTCSeconds().toString() + now.getUTCMilliseconds().toString()
            var roomId:int = smartFox.activeRoomId
            var userId:int = smartFox.myUserId
           
            var liveCastId:String = roomId + "_" + dateString + timeString + "_" + userId
           
            // Publish live stream
            myLiveCast.publish(liveCastId, Constants.BROADCAST_TYPE_LIVE)
           
            // Set user variable
            var userVar:Object = {}
            userVar[CAST_USER_VAR] = liveCastId
            smartFox.setUserVariables(userVar)
           
            _isCasting = true;
           
            Logger.log("User own live cast published; id:", liveCastId)
         }else{
            Logger.log("User didn't allow the app to use the cam and/or mic. No cast is going to be published.")
            unpublishLiveCast()
         }
         
         //Clear the interval
         waitForAllowInterval.stop();
         waitForAllowInterval.removeEventListener(TimerEvent.TIMER, publishMyLiveCast)
      }


private function publishMyLiveCast():Void in this code i think that "Void" must be "void" but then when i have change it appear other error, it say that can't find the constant Timer

private var waitForAllowInterval:Timer = new Timer();

Can you help?:P thx ^^
supermk88
Posts: 239
Joined: 18 Mar 2011, 12:30

Re: I need help for your videoconference

Postby supermk88 » 21 Nov 2012, 19:39

I have search on web and find some example and i have put in the top this two line:
import flash.events.TimerEvent;
import flash.utils.Timer;
But then it appear another error in the private var waitForAllowInterval:Timer = new Timer();
I have change this in private var waitForAllowInterval:Timer; and the error is disappear.. do you think is correct?

edit: i have try so but it don't publish the webcam when i click allow ^^'
User avatar
rjgtav
Posts: 2813
Joined: 19 Apr 2009, 11:31
Location: Lisbon, Portugal

Re: I need help for your videoconference

Postby rjgtav » 21 Nov 2012, 22:34

Sorry, as I don't have Flex on this computer, I didn't test the AS3 version of the class. Yes the imports were missing. And there was an error on the Timer() constructor. It should be working now.

Sorry for the inconvenience
Skills: SFS Pro, SFS2X, AS2.0/AS3.0, Java, HTML5/CSS3/JS, C#
Portfolio: https://rjgtav.wordpress.com/
SFS Tutorials: http://sfs-tutor.blogspot.com/ - Discontinued. Some examples may be bugged.
supermk88
Posts: 239
Joined: 18 Mar 2011, 12:30

Re: I need help for your videoconference

Postby supermk88 » 21 Nov 2012, 23:26

Oh no problem ^^ i'm happy that you can help :P now there aren't error but when i click allow don't appear the webcam :( i don't know why.. what can i do?^^
supermk88
Posts: 239
Joined: 18 Mar 2011, 12:30

Re: I need help for your videoconference

Postby supermk88 » 22 Nov 2012, 18:07

I have watch both of the avcastmanager and maybe the problem is that in mine after this code:

Code: Select all

var now:Date = new Date()
            var month:int = now.getUTCMonth() + 1
            var dateString:String = now.getUTCFullYear().toString() + (month < 10 ? "0" : "") + month.toString() + now.getUTCDate().toString()
            var timeString:String = now.getUTCHours().toString() + now.getUTCMinutes().toString() + now.getUTCSeconds().toString() + now.getUTCMilliseconds().toString()
            var roomId:int = smartFox.activeRoomId
            var userId:int = smartFox.myUserId
           
            var liveCastId:String = roomId + "_" + dateString + timeString + "_" + userId
           
            // Publish live stream
            myLiveCast.publish(liveCastId, Constants.BROADCAST_TYPE_LIVE)
           
            // Set user variable
            var userVar:Object = {}
            userVar[CAST_USER_VAR] = liveCastId
            smartFox.setUserVariables(userVar)
           
            _isCasting = true;
           
            Logger.log("User own live cast published; id:", liveCastId)


there is

return myLiveCast, is just an idea i'm not so good in as3 language and i don't remember how to make that code in your avcastmanager (think that the "private function publishMyLiveCast():void" must be different from void? or maybe there are other problem that don't allow to show the webcam?)
User avatar
rjgtav
Posts: 2813
Joined: 19 Apr 2009, 11:31
Location: Lisbon, Portugal

Re: I need help for your videoconference

Postby rjgtav » 22 Nov 2012, 18:54

Good catch! It seems I forgot to add the return myLiveCast to the publishLiveCast() method. Thanks, i've updated again the source.
Skills: SFS Pro, SFS2X, AS2.0/AS3.0, Java, HTML5/CSS3/JS, C#
Portfolio: https://rjgtav.wordpress.com/
SFS Tutorials: http://sfs-tutor.blogspot.com/ - Discontinued. Some examples may be bugged.
supermk88
Posts: 239
Joined: 18 Mar 2011, 12:30

Re: I need help for your videoconference

Postby supermk88 » 22 Nov 2012, 22:55

hi thx now it show correctly the webcam but i have a problem.. when i join the room and click on allow in the flash request it don't publish the stream, but then if i change the room it publish correctly.. so i have think that is correct the code

Code: Select all

if((enableCamera && !camera.muted) || (enableMicrophone && !microphone.muted)){
               //The user has already allowed the app to use the mic or the cam or both.
               //We can publish the stream
               publishMyLiveCast();
            }


but maybe there are some problem here

Code: Select all

else{
               //The user hasn't allowed yet the app to use the mic and the cam
               //We'll wait some seconds for the user to click the "Allow" button,
               //before we publish the stream and update the UV's
               this.waitForAllowInterval.delay = waitSeconds*1000;
               this.waitForAllowInterval.addEventListener(TimerEvent.TIMER, publishMyLiveCast, false, 0, true);
               this.waitForAllowInterval.start();
            }


i have watch the admin tool and he publish the livecast only if i change room after click on allow button.. can you help?^^ thx :)
User avatar
rjgtav
Posts: 2813
Joined: 19 Apr 2009, 11:31
Location: Lisbon, Portugal

Re: I need help for your videoconference

Postby rjgtav » 22 Nov 2012, 23:44

Does it show any error?
Can you try replacing the publishMyLiveCast's constructor with:

Code: Select all

private function publishMyLiveCast(e:Event = null):void
Skills: SFS Pro, SFS2X, AS2.0/AS3.0, Java, HTML5/CSS3/JS, C#
Portfolio: https://rjgtav.wordpress.com/
SFS Tutorials: http://sfs-tutor.blogspot.com/ - Discontinued. Some examples may be bugged.
supermk88
Posts: 239
Joined: 18 Mar 2011, 12:30

Re: I need help for your videoconference

Postby supermk88 » 23 Nov 2012, 00:04

yeaaaaah great :D now it work perfectly thx :) no error happen and work perfectly ^^
supermk88
Posts: 239
Joined: 18 Mar 2011, 12:30

Re: I need help for your videoconference

Postby supermk88 » 23 Nov 2012, 16:07

Hi again ^^ i have test the new videoconference and seem work good, but sometimes happen (after 30-40 minutes of webcam show) that i remain freeze (i see my webcam that continue to work but other user can't see me and if i go in admin tool is like that i have unpublish my livecast, i don't have plus my uservariable), and i can't see other webcam and sometimes i can't write or read from the public chat. How can i know what is the problem? i don't think that is a my adsl because i have try other flash chat with webcam and also after 1 hour i can write or see other webcam). Thx for answer ^^

edit: it doesn't happen always, i have try again and after 1 hour i being normally disconnected from the chat with user idle time set on 3600. I have build the chat with adobe flash player 10 and use mozilla firefox (i don't know why but google chrome make some problem with webcam now, in all the site with flash request it crash)
supermk88
Posts: 239
Joined: 18 Mar 2011, 12:30

Re: I need help for your videoconference

Postby supermk88 » 23 Nov 2012, 18:18

My brother have try with his computer (out of my lan) and after some time he remain freeze (no message can send, no message can read, can't change room or see webcam etc..).. i think that this happen with all my application and i don't know the reason.. i have try to start the server on my computer with default setting but remain the same problem.. and in the admin tool there aren't dropped message.. how can i find the bug?^^ i'm sure that is not the line because he have try to click on deny and when he become freeze he doesn't watch any webcam.
supermk88
Posts: 239
Joined: 18 Mar 2011, 12:30

Re: I need help for your videoconference

Postby supermk88 » 23 Nov 2012, 22:20

I have try to run the chat in a powerfull server (16gb ram 3.40 ghz dual core 100mbps) and seem to be better (in 1 hour no freeze), but when my brother have try to publish the webcam and me too when we watch together after like 20 minutes i become freeze.. i have try in other chat with webcam (in flash) and i see that my browser don't being freeze.. what can be the reason?

Return to “RedBox”

Who is online

Users browsing this forum: No registered users and 1 guest