Section 6.3. Building a Message-Taking Application

6.3. Building a Message-Taking Application

You've had a chance to learn about the intricacies of the Microphone and Camera classes in theory. Next you can put what you've learned into practice by building a simple message-taking (and retrieval) application.

In order to create the application, complete the following steps:

  1. Create a new FlashCom application on the server. In the applications directory of the FlashCom Server, create a new subdirectory named message_taker .

  2. Create a new Flash document and save it as MessageTaker.fla .

  3. Within the Flash document, create a new Video symbol in the Library.

  4. On the Stage add the following, as shown in Figure 6-3:

  5. Two instances of the Video symbol. Give them instance names of record_vid and playback_vid . Place record_vid to the left and playback_vid to the right. The Video objects will display the video while recording and playing back a message.

  6. Two Button component instances below record_vid . Give them instance names of cbtPreview and cbtRecord . The Button instances allow the user to preview the settings without recording or to record a new message.

  7. One ComboBox component instance below the Button instances. Give it an instance name of ccbRate . The component allows the user to adjust the rate at which the microphone is capturing data.

  8. Three NumericStepper component instances below ccbRate . Give them instance names of cnsGain , cnsQuality , and cnsBandwidth . The components allow the user to adjust the microphone gain, video quality, and video bandwidth.

  9. One List component instance below playback_vid . Give it an instance name of clMessages . The List component displays the dates and timesin a form similar to "Thu Dec 9 22:32:32 GMT-0500 2004"of messages that have been previously recorded.

  10. One Button component instance below clMessages . Give it an instance name of cbtPlayback . The Button instance allows the user to play back the selected message.

    Figure 6-3. The layout of the components

  11. Rename the default layer to Components , and create a new layer named Actions above it.

  12. Select the first keyframe of the Actions layer, and open the Actions panel.

  13. Add the following code to the Actions panel:

     // Create the Microphone and Camera objects. var user_mic = Microphone.get(  ); var user_cam = Camera.get(  ); // Create the NetConnection object. var fcs_nc = new NetConnection( ); // Create listener objects to be used with the components. var recordListener    = new Object( ); var playbackListener  = new Object( ); var previewListener   = new Object( ); var rateListener      = new Object( ); var gainListener      = new Object( ); var bandwidthListener = new Object( ); var qualityListener   = new Object( ); var rsoMessages;    // Variable to store the RSO. var mcMain = this;  // Store a reference to the main timeline. var record_ns;      // NetStream for recording. var playback_ns;    // NetStream for playback. var sMessageTitle;  // Store title of message being recorded. // Initialize the microphone threshold and camera mode and quality. user_mic.setSilenceLevel(10, 2000); user_cam.setMode(320, 240, 15); user_cam.setQuality(0, 100); // Set the loopback to true so user can see what the output stream looks like. user_cam.setLoopback(true); // Connect to the FlashCom application. fcs_nc.connect("rtmp:/message_taker"); // Get the RSO that keeps track of the messages. rsoMessages = SharedObject.getRemote("messages", fcs_nc.uri, true); rsoMessages.connect(fcs_nc); // When the RSO synchronizes, assign the data to the data provider for the List. rsoMessages.onSync = function (info) {   clMessages.dataProvider = this.data.messages; }; // Set up the ComboBox instance. ccbRate.dataProvider = [5, 8, 11, 22, 44]; for (var i:Number = 0; i < ccbRate.length; i++) {   if (ccbRate.getItemAt(i) == user_mic.rate) {     ccbRate.selectedIndex = i;     break;   } } // Define the listener for the Rate combo box. rateListener.change = function (event) {   user_mic.setRate(event.target.value); }; ccbRate.addEventListener("change", rateListener); // Define the listener for the gain stepper. gainListener.change = function (event) {   user_mic.setGain(event.target.value); }; cnsGain.addEventListener("change", gainListener); cnsGain.minimum = 0; cnsGain.maximum = 100; cnsGain.value = user_mic.gain; // Define the listener for the quality stepper. qualityListener.change = function (event) {   user_cam.setQuality(user_cam.bandwidth, event.target.value); }; cnsQuality.addEventListener("change", qualityListener); cnsQuality.minimum = 0; cnsQuality.maximum = 100; cnsQuality.value = user_cam.quality; // Define the listener for the bandwidth stepper. bandwidthListener.change = function (event) {   user_cam.setQuality(event.target.value, user_cam.quality); }; cnsBandwidth.addEventListener("change", bandwidthListener); cnsBandwidth.minimum = 0; cnsBandwidth.maximum = 400000; cnsBandwidth.stepSize = 1000; cnsBandwidth.value = user_cam.quality; // Define the listener for the Record button. recordListener.click = function (event) {   // The Record toggle button has a selected value of true or false.   // If true, start recording the video.   if (event.target.selected) {     // Set the label of the button to Stop while in Record mode.     event.target.label = "Stop";     // Display the video in the Video object.     record_vid.attachVideo(user_cam);     // Create the NetStream object, and add the audio and video.     record_ns = new NetStream(fcs_nc);     record_ns.attachAudio(user_mic);     record_ns.attachVideo(user_cam);     // Create a unique message title with the Epoch milliseconds prefixed by     // "message". It becomes the stream filename, such as   message1102647695650.flv   sMessageTitle = "message" + (new Date( )).getTime( );     // Publish the stream.     record_ns.publish(sMessageTitle, "record");   }   else {     /* Otherwise, the Record button is toggled to the deselected state, so      * stop recording the video.      * Set the button label back to Record while in stopped mode.     */     event.target.label = "Record";     // Clear the video and audio from the Video and NetStream objects.     record_vid.attachVideo(null);     record_vid.clear( );     record_ns.attachAudio(null);     record_ns.attachVideo(null);     // Stop publishing and close the stream.     record_ns.publish(false);     record_ns.close( );     // If the RSO doesn't have a   messages   property, define one as an array.     if (rsoMessages.data.messages == undefined) {       rsoMessages.data.messages = new Array( );     }     /* Add the message to the array. This creates a   label   property string from the       * current date and time similar to "Thu Dec 9 22:32:32 GMT-0500 2004".      * The   data   property is the stream name (used to retrieve the   .flv   file).     */     rsoMessages.data.messages.push({label: new Date( ), data: sMessageTitle});   } }; // When the user clicks the Play Message button, play the selected stream. playbackListener.click = function (event) {   if (clMessages.value != undefined) {     playback_ns = new NetStream(fcs_nc);     playback_ns.play(clMessages.value);     playback_vid.attachVideo(playback_ns);   } }; // When the user clicks the Preview button, display the video and preview // the audio. previewListener.click = function (event) {   if (event.target.selected) {     event.target.label = "Stop";     mcMain.attachAudio(user_mic);     record_vid.attachVideo(user_cam);   }   else {     event.target.label = "Preview";     mcMain.attachAudio(null);     record_vid.attachVideo(null);     record_vid.clear( );   } }; // Set the properties for the Button instances (Preview, Record, Play Message). cbtPreview.toggle = true; cbtPreview.addEventListener("click", previewListener); cbtPreview.label = "Preview"; cbtRecord.toggle = true; cbtRecord.addEventListener("click", recordListener); cbtRecord.label = "Record"; cbtPlayback.addEventListener("click", playbackListener); cbtPlayback.label = "Play Message"; 

  14. Test the movie. Try the different features, including previewing, adjusting settings, recording messages, and playing back messages.

The preceding steps used quite a lot of code, so it may benefit from some further explanation.

Obviously, one of the first steps is to create Microphone and Camera objects:

 var user_mic = Microphone.get(  ); var user_cam = Camera.get(  ); 

Following that, the code sets up a NetConnection object because you'll be connecting the Flash interface to a server-side FlashCom application:

 var fcs_nc = new NetConnection(  ); 

The code then creates a series of listener objects used to handle events dispatched by the components. That way you can have Flash take the appropriate actions when buttons are clicked, combo boxes are changed, or new values are selected from numeric steppers:

 var recordListener    = new Object(  ); var playbackListener  = new Object(  ); var previewListener   = new Object(  ); var rateListener      = new Object( ); var gainListener      = new Object( ); var bandwidthListener = new Object( ); var qualityListener   = new Object( ); 

Set values for the microphone activity threshold and camera mode and quality (the audio gain, video quality, and video bandwidth can be changed via the UI but you have to change this code if you prefer a different activity threshold or camera mode):

 user_mic.setSilenceLevel(10, 2000); user_cam.setMode(320, 240, 30); user_cam.setQuality(0, 100); 

We want the user to be able to preview the video as it would appear when the stream is playing back. Therefore, we set the loopback to TRue :

 user_cam.setLoopback(true); 

The listeners for the numeric steppers and the combo box simply update the internal values based on the user input.

The recordListener.click( ) method handles click events dispatched by cbtRecord . The Record button is a toggle button, which means that it has two possible statesselected and deselected. You can use the Boolean selected property, which indicates the current state of the button, to determine which action to take:

 recordListener.click = function (event) {   if (event.target.selected) { 

If the button is selected, the code instructs Flash to start recording the video and audio to a stream. It attaches the audio and video to a NetStream object and then calls publish( ) to record it to the server. Additionally, the code attaches the video to the Video object so the user can see it while the stream is recording:

 event.target.label = "Stop"; record_vid.attachVideo(user_cam); record_ns = new NetStream(fcs_nc); record_ns.attachAudio(user_mic); record_ns.attachVideo(user_cam); sMessageTitle = "message" + (new Date( )).getTime( ); record_ns.publish(sMessageTitle, "record"); 

Notice that the title of the message stream is generated using Date.getTime( ) , which returns the current time in Epoch milliseconds (a long integer, such as 1102647695650, representing the number of milliseconds since January 1, 1970). Using the current timestamp is a simple way to make sure the stream names, such as message1102647695650 , will be unique. It is unlikely that two users will start recording at exactly the same time (down to the millisecond) even for high-traffic applications. The stream name becomes the name of the .flv file that will be stored, such as message1102647695650.flv .

If the Record button is in the deselected state, the code tells Flash to stop recording the stream. It invokes attachAudio( ) and attachVideo( ) with a parameter value of null to remove the camera and microphone data. Calling publish( ) with a value of false stops publishing the stream. And calling NetStream.close( ) closes the stream:

 event.target.label = "Record"; record_vid.attachVideo(null); record_vid.clear(  ); record_ns.attachAudio(null); record_ns.attachVideo(null); record_ns.publish(false); record_ns.close( ); 

The application uses a remote shared object (RSO) to store information about the messages that have been recorded. That way, it can retrieve that information each time the application is run and use it to populate the List component. Therefore, use the SharedObject.getRemote( ) method to get the connection to the shared object and then connect to it:

 rsoMessages = SharedObject.getRemote("messages", fcs_nc.uri, true); rsoMessages.connect(fcs_nc); 

Once the user finishes recording the stream, the code updates the RSO to include information about the stream that was just recorded. Each element of the messages array contains an object with two properties: label and data . The label property contains the date and time at which the message was recorded. The data property contains the stream name:

 if (rsoMessages.data.messages == undefined) {    rsoMessages.data.messages = new Array(  ); } rsoMessages.data.messages.push({label: new Date( ), data: sMessageTitle}); 

We create the messages array in this manner because the List component expects to be populated with precisely such an array of objects; we can use messages as a data provider for the List component without any modification. Each time the shared object data updates, the onSync( ) event handler updates the List component (which displays the label of each element in the messages array):

 rsoMessages.onSync = function(info) {   clMessages.dataProvider = this.data.messages; }; 

Playing back the selected stream is quite simple. Just check to make sure a value has been selected from the List component. Then, create a NetStream object and play the corresponding stream:

 playbackListener.click = function (event) {   if (clMessages.value != undefined) {     playback_ns = new NetStream(fcs_nc);     playback_ns.play(clMessages.value);     playback_vid.attachVideo(playback_ns);   } }; 

Like the Record button, the Preview button is a toggle button. Therefore, in the previewListener.click( ) method, you can check for the current selected state. If the button is selected, attach the Microphone object to the main timeline to preview the audio and attach the Camera object to the record_vid Video object to preview the video. Otherwise, if the selected state is false , remove the attached audio and video using the attachAudio( ) and attachVideo( ) methods with values of null :

 previewListener.click = function (event) {   if (event.target.selected) {     event.target.label = "Stop";     mcMain.attachAudio(user_mic);     record_vid.attachVideo(user_cam);   }   else {     event.target.label = "Preview";     mcMain.attachAudio(null);     record_vid.attachVideo(null);     record_vid.clear( );   } }; 



Programming Flash Communication Server
Programming Flash Communication Server
ISBN: 0596005040
EAN: 2147483647
Year: 2003
Pages: 203

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net