Influxis Flash Media Interactive Server 3.5 Hosting Specialists


Synx Platform Preview

It’s almost here.

I know I’ve been kind of quiet since my position with Influxis was announced last year, and with good reason. I’ve been working in my laboratory (read: basement office) on some really cool stuff for anybody who develops for, or would like to develop for, Flash Media Server. One of the things I first noticed about being an FMS developer was the repetitive nature of a ton of the things we do when building applications. Creating a NetConnection, creating a NetStream, handling SharedObjects, listening for NetStatus messages… and it seemed to me that there had to be a better way. The rest of the team agreed, and I started working on an AS3 micro-architecture for FMS applications, the Synx Platform. It’s built to make a ton of things simple, and like I said above, it’s almost ready to be given to all of you.

The core of the Synx Platform is the (cleverly-named) Synx class. It’s a Singleton class that handles all the details of using a NetConnection, creating a place for a single NetConnection instance to be used anywhere in your application. It also handles every message that Flash Media Server sends back to the client, and converts them all into events, making it really easy to handle those messages. No more parsing the message to figure out what happened. Just capture the appropriate event, and you’re set. Here’s a list of the events broadcast by the core Synx class:

Event NetStatusEvent code
SynxEvent.READY NetConnection.Connect.Success
SynxEvent.NC_CONNECTION_CLOSED NetConnection.Connect.Closed
SynxEvent.NS_PUBLISH_START NetStream.Publish.Start
SynxEvent.NS_RECORD_START NetStream.Record.Start
SynxFaultEvent.NC_CONNECTION_FAILED NetConnection.Connect.Failed
SynxFaultEvent.NC_CONNECTION_REJECTED NetConnection.Connect.Rejected
SynxFaultEvent.NC_CONNECTION_INVALID_APP NetConnection.Connect.InvalidApp
SynxFaultEvent.NC_CONNECTION_APP_SHUTDOWN NetConnection.Connect.AppShutdown
SynxFaultEvent.NC_CALL_BADVERSION NetConnection.Call.BadVersion
SynxFaultEvent.NC_CALL_FAILED NetConnection.Call.Failed
SynxFaultEvent.NC_CALL_PROHIBITED NetConnection.Call.Prohibited
SynxFaultEvent.NS_PUBLISH_BAD_NAME NetStream.Publish.BadName
SynxFaultEvent.NS_PLAY_FAILED NetStream.Play.Failed
SynxFaultEvent.NS_PLAY_STREAM_NOT_FOUND NetStream.Play.StreamNotFound
SynxFaultEvent.NS_PLAY_FILE_STRUCTURE_INVALID NetStream.Play.FileStructureInvalid
SynxFaultEvent.NS_PLAY_NO_SUPPORTED_TRACK_FOUND NetStream.Play.NoSupportedTrackFound
SynxFaultEvent.NS_PLAY_INSUFFICIENT_BANDWIDTH NetStream.Play.InsufficientBW
SynxFaultEvent.NS_RECORD_NO_ACCESS NetStream.Record.NoAccess
SynxFaultEvent.NS_RECORD_FAILED NetStream.Record.Failed
SynxFaultEvent.NS_SEEK_INVALID_TIME NetStream.Seek.InvalidTime
SynxFaultEvent.SO_FLUSH_FAILED SharedObject.Flush.Failed
SynxFaultEvent.SO_BAD_PERSISTANCE SharedObject.BadPersistance
SynxFaultEvent.SO_URI_MISMATCH SharedObject.UriMismatch

No more parsing to figure out what’s happening. Synx does it for you. And how do you get all this functionality to work? It’s really very simple:

Synx.init("rtmp://youraccount.rtmphost.com/appName/");

So, that’s the first step in using Synx, initializing the platform. Once you’ve done that, everything uses the URI you passed to the init() method.

Where you go from there is really dependent on your application. Do you need streaming video? Do you need to record video from the client’s camera? Or are you looking to share data between multiple connected users? There are two Connection classes in Synx, StreamingConnection and SharedObjectConnection. For today’s demo, we’re going to focus on using the SharedObjectConnection, which handles how Shared Objects are stored on the client and synced to FMS. We’ll cover the various uses of StreamingConnection in a future post.

So, SharedObjectConnection is relatively easy to use, too. That was one of our biggest focuses in creating Synx; making your life as a developer (or designer with some coding experience) as easy as possible. Creating a SharedObjectConnection is really easy, but needs to happen after Synx has initialized completely, so we’re going to add an event listener to the Synx class, and create an event handler method that’s called when Synx says it’s ready to work. We’ll be including the code from previous steps in every example, so you can see how it all works together.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class SynxChatDemo extends MovieClip
{
    public var soConn:SharedObjectConnection;
    public var sChat:Slot;
 
    public function SynxChatDemo()
    {
        super();
        Synx.init("rtmp://youraccount.rtmphost.com/appName/");
        soConn = new SharedObjectConnection();
        soConn.addEventListener(SharedObjectEvent.READY, initSlots, false, 0, true);
    }
 
    public function initSlots(event:SharedObjectEvent):void
    {
        sChat = soConn.addSlot("chatDemo");
        sChat.addEventListener(SlotEvent.CHANGE, clearAndUpdate, false, 0, true);
        sChat.addEventListener(SlotEvent.SUCCESS, updateChatLog, false, 0, true);
    }
}

So, quite a few things are happening here. First, we’re creating a variable to hold our SharedObjectConnection, soConn. We’re also creating a placeholder for a Slot, sChat. A Shared Object can have many slots, each holding different data, kind of like files in a filing cabinet. We’ll talk a little bit more about the Slot class in a moment. During the constructor for our document class, SynxChatDemo, we’re instantiating our SharedObjectConnection. We have to wait to instantiate it after SynxEvent.READY has been captured because the Connection classes are dependent on the information provided by the Synx singleton’s instantiation. So, remember: Synx initializes, then we do everything else. We then set up a listener to let us know when the SharedObjectConnection is ready to do it’s job (SharedObjectEvent.READY), and call initSlots when the event occurs.

The initSlots method is pretty simple. It creates one slot, saving it to our sChat variable we created earlier, but it doesn’t create it by calling new Slot(), it creates it by calling the addSlot() method on the SharedObjectConnection class. This method returns the Slot object once it has done it’s magic. We add a couple listeners to the Slot, listening for SlotEvent.CHANGE and SlotEvent.SUCCESS. On change, we’re calling the clearAndUpdate method, and on success, we’re calling the updateChatLog method. What’s the difference between change and success? Change occurs when the update to the Slot’s data property comes from you, and success occurs when the update comes from another user. We’re going to use the change event to clear the TextField the user types a message into every time the user sends a message. Like I said, simple. The cool thing about the Slot class is that it automatically syncs changes to it’s data property to the server, and the data property always contains the latest data. There are other features there that won’t be used in this example, such as a local history for the data property, but they’re outside the scope of this post.

So, how do we send the chat message?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class SynxChatDemo extends MovieClip
{
    public var soConn:SharedObjectConnection;
    public var sChat:Slot;
 
    public function SynxChatDemo()
    {
        super();
        Synx.init("rtmp://youraccount.rtmphost.com/appName/");
        soConn = new SharedObjectConnection();
        soConn.addEventListener(SharedObjectEvent.READY, initSlots, false, 0, true);
    }
 
    public function initSlots(event:SharedObjectEvent):void
    {
        sChat = soConn.addSlot("chatDemo");
        sChat.addEventListener(SlotEvent.CHANGE, clearAndUpdate, false, 0, true);
        sChat.addEventListener(SlotEvent.SUCCESS, updateChatLog, false, 0, true);
    }
 
    public function sendChatMessage(user:String, message:String):void
    {
        var chatMsg:Object = new Object();
        chatMsg.user = user;
        chatMsg.message = message;
        sChat.data = chatMsg;
    }
}

In the sendChatMessage method, we create an object, add a user and message property to it, and set the Slot’s data property to our object. Because of the automatic syncing, that’s it!

So, what’s left to do? Well, we have to write a couple more methods. Let’s assume that the user interface has been created already, and there are three TextFields. One has an instance name of usernameInput, the second is messageInput, and the last is named chatLog. We have two Buttons, one named sendButton, and one named setUsernameButton. We simply add a few more variables to our document class that match those instance names and types, and write a few more methods.

The first is handleSetUsername, which sets a username property on the document class to the text content of the usernameInput TextField. We attach that as a listener to setUsernameButton’s click event. We also create a method called handleSendButton, which calls sendChatMessage, passing this.username and the text content of the messageInput TextField as it’s two parameters, user and message.

We also need to create the handler methods for our two SlotEvent listeners, clearAndUpdate() and updateChatLog(). In clearAndUpdate(), we call updateChatLog passing the SlotEvent object, and then set the text property of messageInput to an empty string. In updateChatLog, we concatenate the existing text in the log with the username and message from the event.data property, which had been set to our generic object earlier. I’ve also included the code for a simple “enter” handler that allows you to call the sendChatMessage method when the user presses the enter (or return) key on the keyboard while the messageInput has focus.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
public class SynxChatDemo extends MovieClip
{
    public var soConn:SharedObjectConnection;
    public var sChat:Slot;
 
    public var sendButton:SimpleButton;
    public var setUserNameButton:SimpleButton;
 
    public var usernameInput:TextField;
    public var messageInput:TextField;
    public var chatLog:TextField;
 
    public var username:String = "Guest";
 
    public function SynxChatDemo()
    {
        super();
        Synx.init("rtmp://youraccount.rtmphost.com/appName/");
        soConn = new SharedObjectConnection();
        soConn.addEventListener(SharedObjectEvent.READY, initSlots, false, 0, true);
        sendButton.addEventListener(MouseEvent.CLICK, handleSendButton, false, 0, true);
        setUserNameButton.addEventListener(MouseEvent.CLICK, handleSetUsername, false, 0, true);
        messageInput.addEventListener(KeyboardEvent.KEY_DOWN, checkForEnter, false, 0, true);
    }
 
    public function initSlots(event:SharedObjectEvent):void
    {
        sChat = soConn.addSlot("chatDemo");
        sChat.addEventListener(SlotEvent.CHANGE, clearAndUpdate, false, 0, true);
        sChat.addEventListener(SlotEvent.SUCCESS, updateChatLog, false, 0, true);
    }
 
    public function sendChatMessage(user:String, message:String):void
    {
        var chatMsg:Object = new Object();
        chatMsg.user = user;
        chatMsg.message = message;
        sChat.data = chatMsg;
    }
 
    public function handleSetUsername(event:MouseEvent):void
    {
        this.username = usernameInput.text;
    }
 
    public function handleSendButton(event:MouseEvent):void
    {
        sendChatMessage(this.username, messageInput.text);
    }
 
    public function clearAndUpdate(event:SlotEvent):void
    {
        updateChatLog(event);
        messageInput.text = "";
    }
 
    public function updateChatLog(event:SlotEvent):void
    {
        chatLog.text = chatLog.text + event.data.user + ": " + event.data.message + "\n";
        chatLog.scrollV = chatLog.maxScrollV;
    }
 
    public function checkForEnter(event:KeyboardEvent):void
    {
        if (event.keyCode == Keyboard.ENTER)
        {
            sendChatMessage(this.username, messageInput.text);
        }
    }
}

That’s the full code for our simple chat application. I know, it seems too easy, doesn’t it? But, with the Synx Platform, even complex applications are relatively simple to write. Feel free to use the application below to try it out. We’ll be back soon with more details about Synx. The release is just around the corner now, and we’ve got a few more things to show you before then.

Get Adobe Flash player

Tags: , , ,

3 Responses to “Synx Platform Preview”

  1. Very nice stuff, I would love to be one of the beta tester :)

  2. [...] Streaming and Beyond! I think this was Lisa Larson’s session where she talked about the AS framework from Influxis: SYNX. Very good [...]

  3. [...] @influxis: Flash coding is now simpler! Preview the new Flux platform from Influxis’ @zstepek http://labs.influxis.com/?p=643     Comments [...]

Leave a Reply