1.4. The Communication Classes
While
RTMP conveniently manages the flow of
multiple streams of data across a network, the real power of Flash
and FlashCom for developers is realized in the high-level classes
that make connecting to the server, sharing information, and
streaming audio and video so easy and flexible. I'll
briefly review the major classes, which will be explored in more
detail and used in examples throughout the remainder of the book.
1.4.1. Connecting to the Server
The
NetConnection class
connects a client to an application
instance on a server. In the simplest case, you can create a
connection by invoking NetConnection.connect(
)
with the URI of the remote application:
nc = new NetConnection( );
nc.connect("rtmp://echo.ryerson.ca/campusCameras/connector");
To determine if the connection was established successfully, define
an onStatus( ) method on the
NetConnection object before invoking
connect( ):
nc = new NetConnection( );
nc.onStatus = function (info) {
trace("The connection code is: " + info.code);
};
nc.connect("rtmp://echo.ryerson.ca/campusCameras/connector");
In this example, the RTMP address includes the host
(echo.ryerson.ca), the application name
(campusCameras), and the instance name
(connector). If you've ever
developed network applications using other application programming
interfaces, you'll likely agree that creating a
network connection between Flash and FlashCom is ridiculously easy.
Chapter 3 goes into greater detail on the
NetConnection class and how to use
NetConnection objects.
1.4.2. Streaming Audio, Video, and ActionScript Data
Once you establish a connection using a
NetConnection object in the client, you can use
it to send or receive a stream containing audio and/or video.
Suppose you know that a recorded Flash video file named
Ryerson_High_Speed.flv is available in the
instance's public directory.
You can attach the video stream to a video object, here named
videoArea, using Video.attachVideo(
) and play it using
NetStream.play( ).
The NetStream object, in_ns,
is created by passing the NetConnection object,
nc, from the preceding example to the
NetStream( ) constructor function:
in_ns = new NetStream(nc);
videoArea.attachVideo(in_ns);
in_ns.play("public/Ryerson_High_Speed");
In this case, the video appears in a video object that was placed on
the Stage during authoring and given the instance name
videoArea; the audio within the video stream is
heard automatically. Note that the .flv
extension is not included in the stream URI passed into the
play( ) method.
Publishing a stream in a Flash movie is also easy. Here, we create a
new NetStream object, out_ns,
and attach the audio and video streams from the
user's microphone and camera before publishing the
stream using NetStream.publish(
):
out_ns = new NetStream(nc);
out_ns.attachAudio(Microphone.get( ));
out_ns.attachVideo(Camera.get( ));
out_ns.publish(userName); // Name the stream after the user's name.
The Camera class can get a video stream from a web
camera or other video source, and the
Microphone class can get an audio stream from a
microphone or other source.
You can create multiple streams (NetStream
objects) for a single
NetConnection, as shown in Figure 1-3. Each stream can publish or play a stream to
or from the server, but data within a stream travels in only one
direction. If each user must publish a single stream, it is easiest
to name the stream after his unique username or unique ID number.

On the server, the
Stream class can be used to create playlists of
streams and even to play and publish streams across multiple servers.
A playlist defines a sequence of streams to be played one after the
other. The server buffers them so they play seamlessly without
interruption; when one stream ends, another begins. Chapter 5 covers the NetStream
and Stream classes in depth.
1.4.3. Camera, Microphone, and Video
The Camera and Microphone
classes, covered in depth in Chapter 6, provide
access to video and audio sources (typically cameras and microphones)
on the client system. Multiple cameras and microphones can be
accessed by the same Flash movie. Only one video and audio stream can
be published or played within a single
NetStream; however, there can be multiple
NetStreams within a single
NetConnection, as shown in Figure 1-4. The Flash Player is responsible for encoding
all audio and video data. Video encoding from each video source is
currently limited to constant bit rate encoding at a single
resolution. The Camera and
Microphone classes can be used to control the
amount of audio and video data being sent to the server and can be
dynamically adjusted to match the bandwidth limitations of the
clients connected to an application. No real-time hardware
encoding options are currently available, though that may have
changed by the time you read this. Some video cards can present
different resolution video streams from the same input as separate
video sources so that multiple NetStream objects
carrying different resolution video from the same source can be
published simultaneously. Otherwise, the only way to provide
different streams matched to the bandwidth of each client is to use
multiple video sources.

The Camera class provides a convenient way to change
the resolution, frame rate, and quality settings for each video
source. The
Microphone class allows setting the sampling rate,
gain, and silence level, among others. A Video
object is used to display video within a Flash
movie and can be dynamically resized and moved as video is played.
See Chapter 6 for working examples.
1.4.4. Sharing Data in Real Time
Real-time applications often require data to be
shared among or transmitted between multiple movies. The
SharedObject class is familiar to many Flash
programmers as a way to create a kind of supercookie; a
local shared object (LSO) can store ActionScript
data on the client between sessions. Flash communication applications
can use remote shared objects (RSOs) to share
information in real time between movies running on different clients.
If a movie updates a property of a remote shared object, the same
property is updated in every other movie connected to it. When a
shared object changes, each client is notified of the changes. Shared
objects can be used to:
Notify all the movies connected to a video conference application of
the name of every available live stream Update the position of elements in a game Hold the position, shape, and color information of each graphical
element in a shared whiteboard Hold the data for each form element in a shared form
In object-oriented programming (OOP), the data within all the objects
in an application defines the current state of the application.
 |
Shared objects provide a convenient mechanism to hold the state of a
communication application distributed across multiple clients and
servers.
|
|
Remote shared objects can be temporary or persistent. Temporary
shared objects last only while they are being used. Persistent shared
objects are saved on the server when they are not in use, allowing
clients to pick up where they left off as soon as they reconnect to
the server. Proxied shared
objects are a mechanism for making
shared objects available across multiple application instances; one
application instance always owns the shared object but others can
create a network connection to the master instance and create proxies
(essentially an alias) of the shared object. That way, clients
connected to any instance can connect to the same shared object. The
feature is often important for creating large scale applications.
The code to work with shared
objects on the client is a little different from that required on the
server. Working with shared objects is also a little more complicated
than working with streams or managing network connections. You need
to do four basic things when working with shared objects:
Get a remote shared object using SharedObject.getRemote(
). Customize the shared object so your program can respond to changes
made to the shared object by each movie or by the server. Connect to the shared object. Once connected, update the shared object's
properties as necessary.
Chapter 8 provides complete coverage of using
shared objects, but let's have a quick look at what
some client-side code looks like. On the client, the
SharedObject.getRemote( ) method returns a
remote shared object. However, the shared object usually needs to be
set up with an onSync(
) method and then connected using a
NetConnection object before it can be used. Here
we get a shared object named users to which each
movie will connect. Then, an onSync( ) method is
defined that, for demonstration purposes, displays information about
changes made to the shared object as soon as they occur. Then the
shared object is connected to the server:
users_so = SharedObject.getRemote("users", nc.uri);
users_so.onSync = function (infoList) {
for (var i in infoList) {
var info = infoList[i];
switch (info.code) {
case "change":
var id = info.name;
trace("User connected with id: " + id);
trace("and name: " + users_so.data[id]);
break;
case "delete":
var id = info.name;
trace("User disconnected with id: " + id);
break;
}
}
};
users_so.connect(nc);
The onSync( ) method is often the most
interesting part of shared object coding. When the local
copy of the shared object is synchronized with the server and
whenever any slots (properties) in the shared
object change, the onSync( ) method is invoked
automatically. The onSync( ) method is passed an
array of information objects. Each object contains information about
the shared object or about what has happened to a slot (property) in
the shared object. Chapter 8 describes
shared objects and the onSync( ) method in
detail. Each information object has a code
property, which describes what happened
("clear" if every slot is deleted,
"change" if a slot is added or
updated remotely, or "delete" if a
slot is deleted). The name of the slot that has been updated or
deleted is always found in the information object's
name property. To add or update data to a shared
object slot within Flash, use the data property of
the shared object:
users_so.data["guest_4"] = "brian";
Likewise, you can retrieve the value in a slot using the
data property:
trace("The user's name is: " + users_so.data["guest_4"]);
1.4.5. Client and Application Objects
Whenever a client connects to an application instance on the server,
a Client object is created on the server side to
represent the remote client. The Client object
can be used by server-side scripts to send and receive data messages
to and from each individual remote Flash client. Every application
instance also has a single application object that
provides a convenient way to manage the instance's
life cycle. The application is a singleton
instance of the server-side
Application class.
Scripting Client objects and the
application object is covered in Chapter 4. The Client and
application objects, in concert with the ability
to query web application servers, provide the core features needed to
authenticate clients as they connect. Authentication is covered in
detail in Chapter 18.
1.4.6. Remote Methods
In a typical application, an individual client may need to ask the
server to perform some action on its behalf. For example, it may need
to ask the server for the length of a recorded stream before playing
it. The server may also have to ask the client to do something. For
example, the server may need to have the client use a unique string
provided by the server to name the streams the client will publish.
Remote method calls are a way that the client and server can invoke
methods on each other.
An application instance can invoke a method on a client using the
Client.call( ) method.
A client can invoke a method on an application instance using the
NetConnection.call( ) method. For example, a
server-side script can invoke a method on an individual client in
order to let the client know its unique ID number:
client.call("setID", null, id);
If a client method named setID( ) is invoked
using Client.call( ) from the server, the method
must be defined on the client's
NetConnection object or nothing will happen. For
example, the client-side script might look like this:
nc = new NetConnection( );
nc.setID = function (id) {
myID = id;
};
Conversely, the client can call a method on the server using a
NetConnection object:
nc.call("getStreamLength", streamInfoResponder, streamName);
For a result to be returned by the remote method, the second parameter
passed to NetConnection.call( ) must be a object
with an onResult( ) method.
FlashCom also supports mechanisms to send a
remote method request to multiple
clients at the same time. Clients connected to the same shared object
or playing the same stream can all receive a remote method call at
the same time. For example, a popular way to update a text chat area
is to use the send( ) method of a shared object to send a text
message to every client:
chat_so.send("showMessage", "Welcome to the chat.");
In this case, a showMessage(
) method must be defined on the shared
object or nothing will happen:
chat_so.showMessage = function (msg) {
chatTextArea.text += msg + '\n';
chatTextArea.vPosition = chatTextArea.maxVPosition;
};
Chapter 9 describes calling and defining remote
methods in detail.
 |