DekGenius.com
[ Team LiB ] Previous Section Next Section

24.4 Creating the Administrator Client

The administrator client should include the following functionality:

  • The administrator should be able to view a list of available messages that have been left.

  • The administrator should be able to play and/or delete messages.

  • The administrator should be alerted when there is an incoming call and should be able to accept or ignore the call.

  • If the administrator accepts a call, she should be able to end the call by clicking on a button.

Complete the following steps to make the administrator client movie:

  1. Create a new Flash document named adminClient.fla and open it.

  2. Add the PushButton and ListBox component symbols to the Library by creating an instance of each on the Stage and then deleting them.

  3. Add a new video symbol by choosing New Video from the Library panel's pop-up Options menu.

  4. Create a new movie clip symbol named videoMc.

  5. Edit videoMc and create an instance of the video symbol within it so that the video symbol instance is placed at (0,0).

  6. Name the video symbol instance vid.

  7. Open the linkage properties for videoMc.

  8. Select the Export for ActionScript and Export on First Frame options and set the linkage identifier to VideoMcSymbol.

  9. Add the following code to the first frame of the main timeline:

    // NetDebug.as is part of Flash Remoting.
    #include "NetDebug.as"
    
    // Include MovieClip.as from Chapter 7 and Date.as from Chapter 10.
    #include "MovieClip.as"
    #include "Date.as"
    
    // Include Table.as and Forms.as from Chapter 11.
    #include "Table.as"
    #include "Forms.as"
    
    // Include DrawingMethods.as from Chapter 4.
    #include "DrawingMethods.as"
    
    function init (  ) {
    
      // Create a net connection and connect to the FlashCom application as the
      // administrator (username = "admin", password = "adminPass").
      myConnection = new NetConnection(  );
      myConnection.connect("rtmp:/communicationCenterApp/", "admin", "adminPass");
    
      // Once the connection has been made successfully, invoke initMessagesList(  ).
      myConnection.onStatus = function (infoObject) {
        if (infoObject.code == "NetConnection.Connect.Success") {
          _root.initMessagesList(this);
        }
      };
    
      // The onIncomingCall(  ) method is invoked from the server when a calling
      // client places a call to the administrator.
      myConnection.onIncomingCall = function (username) {
        _root.incomingCallUser = username;
    
        // Make the incoming call button visible.
        _root.incomingCallBtn._visible = true;
    
        // Create an interval on which the notifyIncomingCall(  ) function is called.
        _root.incomingCallInterval = setInterval(_root, "notifyIncomingCall", 
                                                 1000, getTimer(  ));
      }
    
      // This method is invoked when a call is ended.
      myConnection.incomingCallEnd = function (  ) {
        // Delete the incoming caller name and clear the videos and net streams.
        delete _root.incomingCallUser;
        _root.livePublishNs.publish(false);
        _root.livePublishNs.close(  );
        _root.liveSubscribeNs.close(  );
        _root.incomingVideoMc.vid.attachVideo(null);
        _root.localVideoMc.vid.attachVideo(null);
        _root.imcomingVideoMc.vid.clear(  );
        _root.localVideoMc.vid.clear(  );
      };
    
      createForm(  );
    }
    
    // The createForm(  ) function creates all the movie clip/component/symbol
    // instances and positions them.
    function createForm (  ) {
    
      // Add the list box to display the list of available messages.
      _root.attachMovie("FListBoxSymbol", "messageList", _root.getNewDepth(  ));
    
      // Create the video instance for the incoming calls.
      _root.attachMovie("videoMcSymbol", "incomingVideoMc", _root.getNewDepth(  ));
    
      // Add a push button instance that enables the administrator to accept an
      // incoming call.
      _root.attachMovie("FPushButtonSymbol", "incomingCallBtn", 
                        _root.getNewDepth(  ));
    
      // Create a movie clip containing a small, green circle used to alert the
      // administrator of an incoming call.
      _root.createEmptyMovieClip("callLight", _root.getNewDepth(  ));
      with (callLight) {
        lineStyle(0, 0, 0);
        beginFill(0x00FF00, 100);
        drawCircle(5);
        endFill(  );
      }
      callLight._visible = false;
    
      incomingCallBtn.setLabel("incoming call");
      incomingCallBtn._visible = false;
      incomingCallBtn.setClickHandler("acceptCall");
    
      // Create the videos for displaying the messages 
      // and for monitoring the local camera stream during calls.
      _root.attachMovie("videoMcSymbol", "messageVideoMc", _root.getNewDepth(  ));
      _root.attachMovie("videoMcSymbol", "localVideoMc", _root.getNewDepth(  ));
    
      // Create buttons for playing and removing messages.
      _root.attachMovie("FPushButtonSymbol", "playBtn", _root.getNewDepth(  ));
      _root.attachMovie("FPushButtonSymbol", "removeBtn", _root.getNewDepth(  ));
      playBtn.setClickHandler("viewMessage");
      playBtn.setLabel("play message");
      removeBtn.setClickHandler("removeMessage");
      removeBtn.setLabel("remove message");
    
      // Use a table to position all the elements.
      tr0 = new TableRow(5, new TableColumn(5, messagelist, playBtn, removeBtn),
                            new TableColumn(5, messageVideoMc));
      tr1 = new TableRow(5, new TableColumn(5, incomingVideoMc), 
                            new TableColumn(5, localVideoMc));
      tr2 = new TableRow(5, new TableColumn(0, callLight, incomingCallBtn));
      t = new Table(5, 0, 0, tr0, tr1, tr2);
    }
    
    // The startLiveCall(  ) function is invoked when the administrator accepts an
    // incoming call.
    function startLiveCall (  ) {
    
      // Create a net stream for subscribing to the calling client's audio and video.
      liveSubscribeNs = new NetStream(myConnection);
      liveSubscribeNs.play(incomingCallUser + "live");
    
      // Attach the local and remote video streams to the respective video instances.
      localVideoMc.vid.attachVideo(Camera.get(  ));
      incomingVideoMc.vid.attachVideo(liveSubscribeNs);
    
      // Create a net stream for publishing the administrator's audio and video.
      livePublishNs = new NetStream(myConnection);
      livePublishNs.attachVideo(Camera.get(  ));
      livePublishNs.attachAudio(Microphone.get(  ));
      livePublishNs.publish("adminLive", "live");
    }
    
    // The notifyIncomingCall(  ) function is invoked at 
    // one-second intervals when an incoming call is being placed.
    function notifyIncomingCall(startTime) {
    
      // Toggle the visibility of the call light. This creates a blinking effect.
      callLight._visible = !callLight._visible;
    
      // If the user has been trying to place the call for more than ten seconds,
      // clear the interval, make the call button and call light invisible, and send
      // the incoming caller to record a message instead.
      if (getTimer(  ) - startTime > 10000) {
        clearInterval(incomingCallInterval);
        callLight._visible = false;
        incomingCallBtn._visible = false;
        myConnection.call("sendToLeaveMessage", null, incomingUser);
        delete incomingCallUser;
      }
    }
    
    // The acceptCall(  ) function is invoked when the administrator accepts an
    // incoming call.
    function acceptCall(  ) {
    
      // Once the call is accepted, turn off the call light.
      callLight._visible = false;
    
      // Modify the button so that it allows the administrator to end the call.
      incomingCallBtn.setLabel("end call");
      incomingCallBtn.setClickHandler("endCall");
    
      // If there is an incoming caller, clear the interval that blinks the call
      // light and call the server-side acceptIncomingCall(  ) method.
      if (incomingCallUser != undefined) {
        clearInterval(incomingCallInterval);
        myConnection.call("acceptIncomingCall", null);
        startLiveCall(  );
      }
    }
    
    // The endCall(  ) function is invoked when 
    // the administrator clicks the End Call button.
    function endCall (  ) {
    
      // Reset the button behavior so that when another call comes in, the
      // administrator can accept it.
      incomingCallBtn.setLabel("incoming call");
      incomingCallBtn._visible = false;
      incomingCallBtn.setClickHandler("acceptCall");
    
      // Invoke the endCall(  ) method on the server 
      // to take care of all the loose ends.
      myConnection.call("endCall", null);
    }
    
    // The viewMessage(  ) function is invoked when the 
    // administrator clicks on the button to play a message.
    function viewMessage (  ) {
      subscribeNs.play("message" + messageList.getSelectedItem(  ).data);
      _root.messageVideoMc.vid.attachVideo(subscribeNs);
    }
    
    // The initMessagesList(  ) function is invoked when the administrator has
    // connected to the FlashCom application. It retrieves the list of messages from
    // the server and populates the list box.
    function initMessagesList (  ) {
    
      // Create a remote shared object to retrieve the message data from the server.
      messagesSO = SharedObject.getRemote("messages", myConnection.uri, true);
      messagesSO.connect(myConnection);
    
      // When there is an update to the messages 
      // information, repopulate the list box.
      messagesSO.onSync = function (  ) {
    
        // First, remove all existing items from the list box.
        _root.messageList.removeAll(  );
        var mssg, un, dt;
    
        // Loop through all the items in the messages list from the server and add an
        // item to the list box for each.
        for (var i = 0; i < this.data.messages.length; i++) {
           mssg = this.data.messages[i];
           un = mssg.username;
           dt = mssg.dateTime;
           _root.messageList.addItem(un + " " + dt.format("MM-dd-yyyy") + " " +
                                     dt.format("hh:mm a"), mssg.id);
           _root.messageList.adjustWidth(  );
           _root.t.render(true);
        }
      };
    
      // Create the net stream over which each video message can be retrieved.
      subscribeNs = new NetStream(myConnection);
    }
    
    // The removeMessage(  ) function is invoked when the administrator clicks the 
    // Remove Message button. It invokes the removeMessage(  ) method on the server.
    function removeMessage(  ) {
      var messageName = "message" + messageList.getSelectedItem(  ).data;
      myConnection.call("removeMessage", null, messageName);
    }
    
    init(  );

Now that you have completed the administrator client, save the file, and let's take a closer look at some elements of the code.

The init( ) function creates the net connection and connects the administrator to the FlashCom application. Notice that the username and password are hardcoded into the connect( ) method invocation. This is not a secure approach, although for this example application it should not pose a problem. If you need to ensure security, the username and password should be entered by the administrator via a login screen.

myConnection = new NetConnection(  );
myConnection.connect("rtmp:/communicationCenterApp/", "admin", "adminPass");

You want to invoke the initMessagesList( ) function once the connection is completed. Do this by invoking it from within the connection object's onStatus( ) method:

myConnection.onStatus = function (infoObject) {
  if (infoObject.code == "NetConnection.Connect.Success") {
    _root.initMessagesList(this);
  }
};

When the administrator accepts an incoming call, you want to start a live call. To do this, follow these steps:

  1. Create a net stream, subscribe to the stream that the calling client is publishing, and display that video.

  2. Display the video that the administrator is publishing so that she can monitor what the calling client is seeing.

  3. Publish the camera and microphone data so that the calling client can subscribe to it.

For example:

function startLiveCall (  ) {
  liveSubscribeNs = new NetStream(myConnection);
  liveSubscribeNs.play(incomingCallUser + "live");
  localVideoMc.vid.attachVideo(Camera.get(  ));
  incomingVideoMc.vid.attachVideo(liveSubscribeNs);
  livePublishNs = new NetStream(myConnection);
  livePublishNs.attachVideo(Camera.get(  ));
  livePublishNs.attachAudio(Microphone.get(  ));
  livePublishNs.publish("adminLive", "live");
}

When a calling client places a call to the administrator, blink the call light by creating an interval that invokes notifyIncomingCall( ) once per second. Each time the function is invoked, the visibility of the call light is toggled. Additionally, you want the call to time out after 10 seconds. To do this, compare the current timer value with the timer value from when the interval began (which is passed to the function as the startTime parameter). Once the call request has timed out, clear the interval and reset the rest of the values that changed when the call request came in.

function notifyIncomingCall(startTime) {
  callLight._visible = !callLight._visible;
  if (getTimer(  ) - startTime > 10000) {
    clearInterval(incomingCallInterval);
    callLight._visible = false;
    incomingCallBtn._visible = false;
    myConnection.call("sendToLeaveMessage", null, incomingUser);
    delete incomingCallUser;
  }
}

The initMessagesList( ) function is invoked when the connection to the FlashCom application is made successfully. This function creates a remote shared object and uses it to populate the list box with the available messages. By placing the code to populate the list box within the onSync( ) method, the list box is updated every time a new message is left.

function initMessagesList (  ) {
  messagesSO = SharedObject.getRemote("messages", myConnection.uri, true);
  messagesSO.connect(myConnection);
  messagesSO.onSync = function (  ) {
    _root.messageList.removeAll(  );
    var mssg, un, dt;
    for (var i = 0; i < this.data.messages.length; i++) {
       mssg = this.data.messages[i];
       un = mssg.username;
       dt = mssg.dateTime;
       _root.messageList.addItem(un + " " + dt.format("MM-dd-yyyy") + " " +
                                 dt.format("hh:mm a"), mssg.id);
       _root.messageList.adjustWidth(  );
       _root.t.render(true);
    }
  };
  subscribeNs = new NetStream(myConnection);
}
    [ Team LiB ] Previous Section Next Section