Jednotné nastavenia mxmlc kompilátora

by Michal Gron on July 30, 2010


RTMFP Connection Tester

by josefchutka on July 29, 2010

Having problems connecting RTMFP? Use this application to test NetConnection, NetStream, NetGroup connection and publishing status. For success connection, opened UDP ports in range 1024..65535 required. Run two instances to test NetGroup neighboring.


The code behind testing application:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:s="library://ns.adobe.com/flex/spark"
    xmlns:mx="library://ns.adobe.com/flex/mx"
    width="100%" height="100%" applicationComplete="init()">
<s:layout>
    <s:HorizontalLayout/>
</s:layout>
<fx:Script>
<![CDATA[
    import flash.net.navigateToURL;

    import org.osmf.net.NetConnectionCodes;
    import org.osmf.net.NetStreamCodes;
    private static const HANDSHAKE_URL:String = "rtmfp://stratus.rtmfp.net";
    private static const DEVELOPER_KEY:String = "PUT***YOUR***OWN";

    private var netConnection:NetConnection = new NetConnection();
    private var netStream:NetStream;
    private var netStream2:NetStream;
    private var netGroup:NetGroup;
    private var d0:Date

    private function init():void
    {
        d0 = new Date();
        netConnection.connect(HANDSHAKE_URL + "/" + DEVELOPER_KEY);
        netConnection.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
    }

    private function netConnectionConnected():void
    {
        var groupSpecifier:GroupSpecifier = new GroupSpecifier("somegruop");
        groupSpecifier.serverChannelEnabled = true;
        groupSpecifier.multicastEnabled = true;
        groupSpecifier.ipMulticastMemberUpdatesEnabled = true;
        groupSpecifier.postingEnabled = true;
        var groupspec:String = groupSpecifier.groupspecWithAuthorizations();

        netStream = new NetStream(netConnection, groupspec);
        netStream.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
        netStream2 = new NetStream(netConnection, groupspec);
        netStream2.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
        netGroup = new NetGroup(netConnection, groupspec);
        netGroup.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
    }

    private function onNetStatus(event:NetStatusEvent):void
    {
        var code:String = event.info.code;
        var time:Number = Math.round((new Date().time - d0.time)/10) / 100;
        log.appendText(code + " (" + time + " sec)\n");
        switch(code)
        {
            case NetConnectionCodes.CONNECT_SUCCESS:
                netConnectionCheckBox.selected = true;
                netConnectionConnected();
                break;
            case "NetStream.Connect.Success":
                if(event.info.stream == netStream)
                {
                    netStreamCheckBox.selected = true;
                    netStream.publish("test");
                }
                else if(event.info.stream == netStream2)
                {
                    netStream2.play("test");
                }
                break;
            case "NetGroup.Connect.Success":
                netGroupCheckBox.selected = true;
                break;
            case NetStreamCodes.NETSTREAM_PUBLISH_START:
                netStreamPublishCheckBox.selected = true;
                break;
            case NetStreamCodes.NETSTREAM_PLAY_START:
                netStreamPlayCheckBox.selected = true;
                break;
            case "NetGroup.Neighbor.Connect":
                netGroupNeighborCheckBox.selected = true;
                break;
        }
    }

    private function onReadMore():void
    {
        var url:String = "http://blog.yoz.sk/2010/06/quick-tip-ports-required-for-rtmfp/";
        navigateToURL(new URLRequest(url), "_blank");
    }
]]>
</fx:Script>
<fx:Declarations>
    <!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:VGroup>
    <s:HGroup verticalAlign="middle">
        <s:CheckBox id="netConnectionCheckBox" enabled="false"/>
        <s:Label text="NetConnection" />
    </s:HGroup>
    <s:HGroup verticalAlign="middle">
        <s:CheckBox id="netStreamCheckBox" enabled="false"/>
        <s:Label text="NetStream" />
    </s:HGroup>
    <s:HGroup verticalAlign="middle" paddingLeft="10">
        <s:CheckBox id="netStreamPublishCheckBox" enabled="false"/>
        <s:Label text="NetStream.Publish" />
    </s:HGroup>
    <s:HGroup verticalAlign="middle" paddingLeft="10">
        <s:CheckBox id="netStreamPlayCheckBox" enabled="false"/>
        <s:Label text="NetStream.Play" />
    </s:HGroup>
    <s:HGroup verticalAlign="middle">
        <s:CheckBox id="netGroupCheckBox" enabled="false"/>
        <s:Label text="NetGroup" />
    </s:HGroup>
    <s:HGroup verticalAlign="middle" paddingLeft="10">
        <s:CheckBox id="netGroupNeighborCheckBox" enabled="false"/>
        <s:Label text="NetGroup.Neighbor" />
    </s:HGroup>
</s:VGroup>
<s:VGroup width="100%" height="100%">
    <s:TextArea id="log" width="100%" height="100%" text="For success connection, opened UDP ports in range 1024..65535 required.&#13;Run two instances to test NetGroup neighboring.&#13;" />
    <s:Button label="Read more about RTMFP requirements" click="onReadMore()"/>
</s:VGroup>
</s:Application>

Where to go from here:


UNIPacket and UNIPacketHeader classes is my attempt to standardize communication within NetStream and NetGroup communication. While both Net* classes enables you to send any raw data between two instances of flash, you should carefully handle incomming messages. Imagine you are willing to send additional info with your message (sender, id etc.). That is where UNIPacket classes comes into scene, both are very simple and able to selfcreate from incomming object.

UNIPacket contains only two variables: header:UNIPacketHeader and data:* (holds the actual data being sent).

UNIPacketHeader is dynamic class with prepared variables: id:uint (numeric identificator of message), hash:String (string identificator of message), sender:String (use for sender identification).

Preparing UNIPacket:

var header:UNIPacketHeader = new UNIPacketHeader();
header.sender = netGroup.convertPeerIDToGroupAddress(netConnection.nearID);
header.id = uint(Math.random() * uint.MAX_VALUE);
header.someDynamicVariable = "XYZ";
var data:String = "Hallo world"
var messageOut:UNIPacket = new UNIPacket(header, data);

Usage with NetStream:

// SENDER:
var netStream:NetStream = new NetStream(...);
netStream.send("onNotify", messageOut);

// RECEIVER:
var messageIn:UNIPacket;
var netStream:NetStream = new NetStream(...);
netStream.client = {
    onNotify: function(data:Object):void
    {
        messageIn = UNIPacket.create(data);
        messageIn.data;
        messageIn.header.sender;
        messageIn.header.id;
        messageIn.header.someDynamicVariable;
    }
}

Usage with NetGroup:

// SENDER:
var groupSpecifier:GroupSpecifier = new GroupSpecifier("somegruop");
groupSpecifier.serverChannelEnabled = true;
groupSpecifier.multicastEnabled = true;
groupSpecifier.ipMulticastMemberUpdatesEnabled = true;
groupSpecifier.postingEnabled = true;
var groupspec:String = groupSpecifier.groupspecWithAuthorizations();
var netGroup:NetGroup = new NetGroup(netConnection, groupspec);
...
netGroup.post(messageOut);

// RECEIVER:
var messageIn:UNIPacket;
var netGroup:NetGroup = new NetGroup(...);
netGroup.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
function onNetStatus(event:NetStatusEvent):void
{
    switch(event.info.code)
    {
        case "NetGroup.Posting.Notify":
            messageIn = UNIPacket.create(event.info.message);
            messageIn.data;
            messageIn.header.sender;
            messageIn.header.id;
            messageIn.header.someDynamicVariable;
            break;
    }
}

Flash/Flex Builder shortcuts

by Michal Gron on July 27, 2010


Quick Tip: SimpleButton to SelectableButton

by josefchutka on July 27, 2010

sk.yoz.ui.SelectableButton class may be handy for you if you decided to drop framework and make your own lightweight components. It extends SimpleButton (basic ActionScript 3 component) and ads selected state and toggle functionality by switching states on click event. You may want to extend it for selectedUpState, selectedOverState, selectedDownState, feel free to do that.

usage:

import sk.yoz.ui.SelectableButton;

// any graphics here
var upState:DisplayObject;
var overState:DisplayObject;
var downState:DisplayObject
var hitTestState:DisplayObject;

// changes selected state on mouse click
var toggle:Boolean = true;

var button:SelectableButton;
button = SelectableButton(upState, overState, downState, hitTestState, toggle);

// toggle select button without user interaction
button.selected = true;

Size comparision of empty instances of mx Button, spark Button and SelectableButton:

trace(getSize(new mx.controls.Button()));
// 1408 bytes

trace(getSize(new spark.components.Button()));
// 1248 bytes

trace(getSize(new sk.yoz.ui.SelectableButton()));
// 324 bytes

onStream – The Broadcasting Machine

by josefchutka on July 26, 2010

onStream – The Broadcasting Machine is the name of my latest flash project. Slogan says: “Broadcast LIVE video to your friends or the whole world from a computer or mobile. Watch other people broadcasting their webcamera, conferences, shows or movies.” With this flash application you can broadcast your webcamera, tv card, desktop or movies (read the section “What can be broadcasted?”). With different broadcasting settings you can broadcast to unlimited number of viewers as well as make private videochats. Based on your connection speed, choose appropriate quality for your broadcasts from 320×160 px webcamera resolution with 11kHz sound sampling up to high definition broadcasts.

The application is located on http://onstream.yoz.sk and there also exist a facebook application http://apps.facebook.com/onstream/. You can also publish and run the application from facebook newsfeed stream.

UI, requirements, technology

I have created custom UI components that easily works on ordinary PCs (mouse controlled) as well as on touch devices. You can switch the whole app or just one channel into fullscreen. Targeting Flash Player 10.1, you are able to use this application even on your android phones. The technology behind the app uses RTMFP protocol that use Flash Player for P2P communication between users (see protocol requirements). Together the Flash Player 10.1 and RTMFP let you create multicast streaming, what is expected to work on large streaming groups.

Broadcasting modes

  • Public / Private – With public mode anyone can search for your channel (based on channel name or description), while in private mode only people with correct link may join.
  • Broadcast / Video Chat – Broadcast your channel to unlimited number of viewers or select video chat mode where anyone who joins channel see and broadcast each other. Use broadcast mode for your live tweets, conferences, video or sound streaming.

What can be broadcasted?

  • Webcamera & Microphone – By default, you can select all your system installed webcameras and microphones.
  • MP3s / PC sounds – if your soundcard driver supports “Stereo-Mix” (“Mono-mix” “Wave Out”, “What U Hear”…), just make it as default sound source instead of your microphone
  • TV card – If you have one, plug it in and you should see your tv car in list (based on driver details).
  • Desktop / Movies / Images – There is some software available that let you broadcast your pc desktop, movies or images etc. My personal favourite is VH Toolkit (freeware) but there are also simplier alternatives like ManyCam (free), Fake Webcam (paid)…

Publishing channels

Once the broadcasting channel is created, there are several ways viewers notice:

  • Search – If the channel is in public mode, anyone can search / list the channel in the search section of the app.
  • Link – Any channel has its own unique link, click clipboard icon to copy this link into system clipboard and share link with your friends.
  • Facebook – Click facebook icon to publish the channel directly into your facebook newsfeed.

Screencast

Po dlouhé době dělám projekt, který se kompiluje přes Flash IDE (CS5) a dlouhou dobu mi z důvodů, kterým jsem nerozumněl, nefungovaly RobotLegs. Injectované modely nebyly přístupné, contextView mimo MainContext také ne…no v podstatě to nefungovalo vůbec. Řešení celého problému je naštěstí více než jednoduché v Publish settings stačí zapnout Export SWC. RobotLegs je závislé [...]

AS3-P2P-LIB and P2P Video Calls on Android

by Tom Krcha on July 22, 2010


Neverending Facebook API changes

by josefchutka on July 21, 2010

Believe it or not, facebook changed part of its api again. Since today, authorizing for iframe applications does not work the same way it used to. Previously it was enough to redirect:

https://graph.facebook.com/oauth/authorize
    ?client_id=268718683475
    &redirect_uri=http://apps.facebook.com/blogoauthgraph/
    &scope=publish_stream,user_photos,user_photo_video_tags

… where facebook authorized your app and redirects back to the:

http://apps.facebook.com/blogoauthgraph/
    ?session=123456...

… where session was valid access_token.

Since today the mechanism changed into something like this:

https://graph.facebook.com/oauth/authorize
    ?client_id=268718683475
    &redirect_uri=http://apps.facebook.com/blogoauthgraph/
    &scope=publish_stream,user_photos,user_photo_video_tags

… redirects you to the:

http://apps.facebook.com/blogoauthgraph/
    ?code=2.YndguK...

… while you do not have valid session (access_token), you have to do the following request:

https://graph.facebook.com/oauth/access_token
    ?client_id=268718683475
    &redirect_uri=http://apps.facebook.com/blogoauthgraph/
    &client_secret=YOURSECRET
    &code=2.YndguK...

… now facebook responds with:

access_token=268718683475|2.Yndgu...&expires=86183

Notice, this is the response, not the redirect! Now its time to grab the access_token and use it in your app. This change has direct impact on Authorizing Iframe Facebook Applications For Graph API article.

There have also been some other unannounced changes e.g. in facebook app settings in migrations tab “Remove fb_sig” toggler…

Credits goes to my readers Adam Cousins, David Bardos, Garcimore, Etienne for noticing the changes.

I have just spotted quick fix. All you need to do is add type=user_agent into your auth request:

https://graph.facebook.com/oauth/authorize
    ?client_id=268718683475
    &redirect_uri=http://apps.facebook.com/blogoauthgraph/
    &scope=publish_stream,user_photos,user_photo_video_tags
    &type=user_agent

… now facebook redirects you to:

http://apps.facebook.com/blogoauthgraph/
    ?access_token=123456...
    &expires_in=86729

This token is valid! I have updated the article with this quickfix.

updated Jul 22, 2010: Facebook rollbacked the change and added “Canvas Session Parameter” parameter in facebook app settings / Migrations tab. With this setting enabled, your apps should work normally as they previously did.