home icon contact icon rss icon last FM icon facebook icon LinkedIn icon Delicious icon twitter icon

Archive pour le mot clé Code

Building a streaming mp3 player

I wanted to write a post on an open source old initiative to build Flash application without any Adobe stuff : mtasc. This is for later.

For a professionnal project, I had to make a mp3 streaming player for some famous french radios. And remember I hate Flash.

I was tempted to try it with Javascript, you know, with something like :

<script>
function EvalSound(soundobj) {
  var thissound=document.getElementById(soundobj);
  thissound.Play();
}
</script>

And then :

<embed src="success.wav" autostart=false width=0 height=0 id="sound1" enablejavascript="true" />
    <form>
        <input type="button" value="Play Sound" onClick="EvalSound('sound1')">
    </form>

But even if I wasn't sure that stremed mp3 (you know, endless files) were compatible with this, some Facebook specific required features prevent me to go further. I had to use Flash.

Since I don't have any licence for using Flash IDE, I've found mtasc. And started to code the player with actionscript 2. The code to load and play a sound is pretty simple :

public class SoundPlayer {

    private var _sound:Sound;
    private var _soundUrl:String;

    public var isPlaying:Boolean = false;
    public var isLoaded:Boolean = false;

    public function SoundPlayer(soundUrl) {
        _soundUrl = soundUrl;
    }

    public function preLoadSound():Void {
        this._sound = new Sound();
        this._sound.loadSound(_soundUrl, true);
    }

    public function play():Void {
    if (!this.isLoaded) {
        this.preLoadSound();
    }

    if (!this.isPlaying) {
        this._sound.start(0, 1);
    }

        this.isPlaying = true;
    }

    public function stop():Void {
        this._sound.stop();
        this.isPlaying = false;
        this.isLoaded = false;
    }
}

And this was good. We went to test it on various computer configurations and it apear that some plugins on Internet Explorer 7 and 8 where causing the browser to freeze and relaunch. We identified this list of plugins, but I'm sure there is some others:

  • WsftpBrowserHelper Class
  • RealPLayer Downloader and record
  • AcrolEHlprObj Class

At first, I thought it was mtasc that didn't compile properly the Sound object, but I tried to compile it with the Flash IDE under the latest Flash versions (> 10) and that didn't resolve the bug.

The answer was to translate the code from ActionScript 2 to ActionScript 3. ActionScript 3 add a new Sound class and Event listener to control it. The code in ActionScript 3 is something like:

package streamPlayer {

    import flash.media.Sound;
    import flash.media.SoundChannel;
    import flash.media.SoundTransform;
    import flash.media.SoundLoaderContext;
    import flash.net.URLRequest;

    public class SoundPlayer {
        private var _sound:Sound;
        private var _channel:SoundChannel;
        private var _soundUrl:String;

        public var isPlaying:Boolean = false;
        public var isLoaded:Boolean = false;

        public function SoundPlayer(soundUrl) {
            _soundUrl = soundUrl;
        }

        public function preLoadSound() {
            this._sound = new Sound();
            var req:URLRequest = new URLRequest(_soundUrl);
            var context:SoundLoaderContext = new SoundLoaderContext(100, true);
            this._sound.load(req, context);
        }

        public function play() {
        if (!this.isLoaded) {
            this.preLoadSound();
        }

        if (!this.isPlaying) {
            this._channel = this._sound.play();
        }

            this.isPlaying = true;
        }

        public function stop() {
            var transform:SoundTransform = this._channel.soundTransform;
            transform.volume = 0;
            this._channel.soundTransform = transform;
            this._sound.close();
            this.isPlaying = false;
            this.isLoaded = false;
        }
    }
}

And it work perfectly well!

Javascript image preloader, without document.images nor Image class

I've maid this twit saying that I built a JavaScript image preloader. Since many wanted to see it. There it is.

I wanted to preload image for a Facebook application displaying a JavaScript photo viewer widget. And when developing Facebook applications, you have deal with Facebook JavaScript rules and what they call FBJS. I already built a FBJS framework, YAPS, helping me (and other developpers) to do simple javascript tasks.
But YAPS can't replace the Image JavasScript class nor the document.images that Facebook prevent us tu use. So I built this code to preload images in a Facebook environment.

Code :

// An image preloader without using Image class nor document.images
// Built for a Facebook environment where those two are forbiden. May not work in a regular web page.
// Just change 

function Preloader(options) {
  var defaultSettings = {
    preloaderID: "preloader_id",
    container: document.body
  };

  this.settings = this.extend(defaultSettings, options || {});
  this.buildPreloader();
};

Preloader.prototype = {
  extend: function(destination, source) {
    for (var property in source)
      destination[property] = source[property];
    return destination;
  },

  // Prepare the preloader. Just a IMG html element hidden with css.
  buildPreloader: function(preloaderId) {
    var image = document.createElement('IMG')
      .setId(this.settings.preloaderId)
      .setStyle({display: 'none'});
    this.settings.container.appendChild(image);
  },

  // Update de src attribute of our hidden tag with the passing url.
  // Having the src updated will make the tag to load the image.
  preloadPic: function(imageUrl) {
    var preloader = document.getElementById(this.settings.preloaderId);
    if (preloader) {
      preloader.setSrc(imageUrl);
      // Don't know why, setting the src make the picture visible. 
      // Have to hide it again.
      preloader.setStyle({display: 'none'});
    }
  }

};

Usage :

preloader = new Preloader({
  preloaderID: "my_image_preloader",
  container: document.getElementById("my_container")
});
preloader.preloadPic("http://imeuble.info/assets/2008/5/21/stéphane-akkaoui-maxime-guilbot-discussion_1.jpg");

Improvements :

  • If I use the same Preloader instance multiple time in a row, I'm not sure the previous image is entirely preloaded before with change the src attribut with the new url.
  • It would have been great if I could passe an Array of urls to the preloader and let him do the work.
  • It must be many other possible improvments. This feat my needs for the moment. Please feel free to modify it. Post an updated code in the comments.