0
votes

I have a Flash MP3 player with an external HTML interface which controls everything, it works fine except for one problem: I can't help but feel that there's a better way to show the elapsed time!

I am currently sending the elapsed time value through the ExternalInterface in AS3 to JavaScript and updating the HTML. The Flash player is a 1px by 1px file which is only there to play the sounds. The problem is that I am using ( AS3) setInterval() to fire every .2 seconds and update the value that way.

I have a feeling that there is probably a better way to do this which doesn't involve setInterval() and also doesn't involve using the Flash player as the timer (although this is the way it is looking like it's going!)

I have tried Event.ENTER_FRAME to no avail, assumingly as I don't use anything on the stage.

1

1 Answers

1
votes

Like Lars Blåsjö said, you can use the Timer class instead of setInterval() method. I made an alteration to the previous example I made for your previous question to incorporate a Timer object. Take a look at the following example:

Main.as(document class):

package 
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.TimerEvent;
    import flash.external.ExternalInterface;
    import flash.media.Sound;
    import flash.media.SoundChannel;
    import flash.net.URLRequest;
    import flash.utils.Timer;

    public class Main extends Sprite 
    {
        private var _sound:Sound;
        private var _soundChannel:SoundChannel;
        private var _onTimer:String;
        private var _timer:Timer;
        private var _currentSoundName:String;

        public function Main():void 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);

        }// end function

        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);

            if (ExternalInterface.available)
            {
                ExternalInterface.addCallback("loadSound", loadSound);
                ExternalInterface.addCallback("stopSounds", stopSounds);

            }// end if

            _onTimer = loaderInfo.parameters["onTimer"] as String;

        }// end function

        private function loadSound(name:String, url:String):void
        {
            _currentSoundName = name;
            _sound = new Sound();
            _sound.load(new URLRequest(url));
            if (_soundChannel) _soundChannel.stop();
            _soundChannel = _sound.play();

            if (_onTimer)
            {
                _timer = new Timer(100);
                _timer.addEventListener(TimerEvent.TIMER, onTimer);
                _timer.start();

            }// end function

        }// end function

        private function stopSounds():void
        {
            _soundChannel.stop();
            if(_timer) _timer.stop();

        }// end function

        private function onTimer(e:Event):void
        {
            var event:Object = 
            { 
                soundChannel :
                { 
                    position: _soundChannel.position 
                },
                sound : 
                {
                    name : _currentSoundName,
                    length : _sound.length
                }
            }

            ExternalInterface.call(_onTimer, event);

        }// end function

    }// end class

}// end package

sounds.json:

{ "sounds" : {
    "sound": [
        { "name": "Sound 1", "url": "sounds/sound1.mp3" },
        { "name": "Sound 2", "url": "sounds/sound2.mp3" },
        { "name": "Sound 3", "url": "sounds/sound3.mp3" }
    ]
}}

index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8"/>
    <title>SoundPlayer</title>
    <meta name="description" content="" />
    <script src="js/swfobject.js"></script>
    <script src="js/jquery.min.js"></script>
    <script>
        var flashvars = {
            onTimer : "onTimer"
        };
        var params = {
            menu: "false",
            scale: "noScale",
            allowFullscreen: "true",
            allowScriptAccess: "always",
            bgcolor: "",
            wmode: "direct" // can cause issues with FP settings & webcam
        };
        var attributes = {
            id:"SoundPlayer"
        };
        swfobject.embedSWF(
            "SoundPlayer.swf", 
            "altContent", "0", "0", "10.0.0", 
            "expressInstall.swf", 
            flashvars, params, attributes);
    </script>
    <style>
        html, body { margin-left:25px; height:100%; overflow:hidden; font-family: arial; font-size:15px;}
        body { margin:0;  }
        .sound-component 
            { margin-top:25px; width:500px; height:100px; background-color:#fafafa; 
              border: 1px solid #e1e1e1; border-radius: 20px; }
        .sound-component span { padding-left:20px; padding-top:16px; }
        .sound-component .suffix
            { width:130px; display:inline-block; font-weight:bold; }
        .sound-component .name 
            { width: 399px; height: 49px; border-bottom: 1px solid #e1e1e1; 
              border-right:  1px solid #e1e1e1; }
        .sound-component .position-length 
            { width: 399px; height: 49px; border-right: 1px solid #e1e1e1; }
        .sound-component .play-stop-button 
            { float:right; width:100px; height:60px; text-align:center; padding-top:40px; 
               font-weight:bold; font-size:18px; color:#c8c8c8; }
        .sound-component .play-stop-button:hover { color:#323232; }
    </style>
</head>
<body>
    <script>

    $(document).ready(function() {

        // get the flash object
        var soundPlayer = $("#SoundPlayer").get(0);

        // load the json file with the list of sounds
        $.getJSON('json/sounds.json', function(data) {

            // loop through each sound in the list in the loaded json file
            $.each(data.sounds.sound, function(i, sound) {

                // create a html component for the current sound
                var soundComponent = $(

                    '<div class="sound-component">' +
                        '<div class="play-stop-button">Play</div>' +
                        '<div class="name">' +
                            '<span class="suffix">Name: </span>' +
                            '<span class="value"></span>' +
                        '</div>' +
                        '<div class="position-length">' +
                            '<span class="suffix">Position/Length: </span>' +
                            '<span class="value">#</span>' +
                        '</div>' +
                    '</div>'
                );

                $(soundComponent).find(".name .value").text(sound.name);

                $(soundComponent).find(".play-stop-button").click(function ()   { 

                    var text = $(this).find(".play-stop-button").text();

                    soundPlayer.loadSound(sound.name, sound.url); 

                });

                $(soundComponent).appendTo("body");

            });

        });

    });

    function onTimer(event)
    {
        $(".sound-component").each(function(i) {

            var name = $(this).find(".name .value").text();

            if(event.sound.name == name)
            {
                var position = parseInt(event.soundChannel.position).toFixed(0);
                var length = parseInt(event.sound.length).toFixed(0);

                $(this).find(".position-length .value").text(
                    position + "/" + length
                );
            }
            else 
            {
                $(this).find(".position-length .value").text("#");
            }

        });

    }

    </script>

    <div id="altContent">
        <h1>SoundPlayer</h1>
        <p><a href="http://www.adobe.com/go/getflashplayer">Get Adobe Flash player</a></p>
    </div>

</body>
</html>


The following is a screenshot of the index.html file being executed and a sound being played:

enter image description here


Without going into too much detail, the gist is that the flash object calls an event handler in the parent container using the ExternalInterface.call() method. It is called upon every TimerEvent.Timer event that the Timer object dispatches. Upon calling the event handler it parses an event object that contains information on the current sound that is playing(e.g. sound name, sound position, etc).