Hi there,
My awesome twin brother and I recently re-launched our super-cool-oh-my-gosh-this-rocks website www.3am.co.za
With the relaunch we changed frameworks and our old Flash media player no longer could do the job.
I looked into using the awesome Flowplayer but was suggested by my good friend Bruno
(balexandre #magento) to use JW player from Longtail.
I built the flash JW Player into my Magento website and started plugging in my samples.
The JW Player is quite cool, and it took me a couple of days to get to grips with the framework and how it functions. When all was setup I noticed that my Autostart function doesn’t work. This was bad because of the following.
- When a user click on a song to play, it would start the autoplay, and downloading the song, but no sound would come through
- The user then had to click Pause and then Play for the song to start playing.
So 3 clicks made a play.
I then decided to look into it and came across this BUG post.
The fix there was stated by Pablo as
This issue can probably be tracked down to the following line: trunk/fl5/src/com/longtailvideo/jwplayer/media/SoundMediaProvider.as#L150
Replace
if (_sound.isBuffering == true && _sound.bytesTotal > _sound.bytesLoaded) {
with
if (_sound.isBuffering == true && _sound.bytesTotal > _sound.bytesLoaded > 0) {
So I decided to give it a try, nevermind the fact that I have never in my life compiled Actionscript. But hey..more on that later. See my blog Post on How to Compile Actionscript and JW Player 5.2
This change did not make a huge difference so I went back into the code this morning and came up with this:
In the file:
/trac/browser/trunk/fl5/src/com/longtailvideo/jwplayer/media/SoundMediaProvider.as#L150″>trunk/fl5/src/com/longtailvideo/jwplayer/media/SoundMediaProvider.as
I changed this protected function positionHandler(progressEvent:ProgressEvent=null):void function
For sake of clarity I’m just going to paste the whole file. Look for my changes around Line 141, Line 144, Line 155 and Line 157. Let me just tell you now, that I have NEVER in my whole entire life written even one line of ActionScript. This code is not the prettiest, but as you can see on this page it does work
/**
* Wrapper for playback of mp3 sounds.
**/
package com.longtailvideo.jwplayer.media {
import com.jeroenwijering.events.*;
import com.longtailvideo.jwplayer.events.MediaEvent;
import com.longtailvideo.jwplayer.model.PlayerConfig;
import com.longtailvideo.jwplayer.model.PlaylistItem;
import com.longtailvideo.jwplayer.player.PlayerState;
import flash.events.*;
import flash.media.*;
import flash.net.URLRequest;
import flash.utils.*;
public class SoundMediaProvider extends MediaProvider {
/** _sound object to be instantiated. **/
private var _sound:Sound;
/** Sound control object. **/
private var _transformer:SoundTransform;
/** Sound _channel object. **/
private var _channel:SoundChannel;
/** Sound _context object. **/
private var _context:SoundLoaderContext;
/** ID for the position interval. **/
protected var _positionInterval:Number;
/** Whether the buffer has filled **/
private var _bufferFull:Boolean;
/** Whether the enitre video has been buffered **/
private var _bufferingComplete:Boolean;
/** User-defined item duration **/
private var _userDuration:Number = -1;
/** Constructor; sets up the connection and display. **/
public function SoundMediaProvider() {
super('_sound');
}
public override function initializeMediaProvider(cfg:PlayerConfig):void {
super.initializeMediaProvider(cfg);
_transformer = new SoundTransform();
_context = new SoundLoaderContext(config.bufferlength * 1000, true);
}
/** Sound completed; send event. **/
private function completeHandler(evt:Event):void {
complete();
}
/** Catch errors. **/
private function errorHandler(evt:ErrorEvent):void {
stop();
error(evt.text);
}
/** Forward ID3 data from the _sound. **/
private function id3Handler(evt:Event):void {
try {
var id3:ID3Info = _sound.id3;
var obj:Object = {type: 'id3', album: id3.album,
artist: id3.artist, comment: id3.comment,
genre: id3.genre, name: id3.songName, track: id3.track,
year: id3.year}
sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_META, {metadata:obj});
} catch (err:Error) {
}
}
/** Load the _sound. **/
override public function load(itm:PlaylistItem):void {
_position = 0;
_bufferFull = false;
_bufferingComplete = false;
_userDuration = itm.duration > 0 ? itm.duration : -1;
if (!_item || _item.file != itm.file) {
_item = itm;
_sound = new Sound();
_sound.addEventListener(IOErrorEvent.IO_ERROR, errorHandler);
_sound.addEventListener(Event.ID3, id3Handler);
_sound.addEventListener(ProgressEvent.PROGRESS, positionHandler);
_sound.load(new URLRequest(encodeURI(_item.file)), _context);
}
if (!_positionInterval) {
_positionInterval = setInterval(positionHandler, 100);
}
sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_LOADED);
setState(PlayerState.BUFFERING);
sendBufferEvent(0);
streamVolume(config.mute ? 0 : config.volume);
}
/** Pause the _sound. **/
override public function pause():void {
if (_positionInterval){
clearInterval(_positionInterval);
_positionInterval = undefined;
}
if (_channel) {
_channel.stop();
}
super.pause();
}
/** Play the _sound. **/
override public function play():void {
if (position == 0 && _item.start > 0) {
seek(item.start);
return;
}
if (!_positionInterval) {
_positionInterval = setInterval(positionHandler, 100);
}
if (_channel){
_channel.stop();
_channel = null;
}
_channel = _sound.play(_position * 1000, 0, _transformer);
_channel.addEventListener(Event.SOUND_COMPLETE, completeHandler);
super.play();
}
/** Interval for the _position progress **/
protected function positionHandler(progressEvent:ProgressEvent=null):void {
var bufferPercent:Number;
if (_sound.bytesTotal > 0 && _sound.bytesLoaded / _sound.bytesTotal > 0.1 && (_item.duration <= 0 || _userDuration < 0)) {
_item.duration = _sound.length / 1000 / _sound.bytesLoaded * _sound.bytesTotal;
}
if (_channel && _sound && _sound.bytesTotal > 0) {
_position = Math.round(_channel.position / 100) / 10;
bufferPercent = Math.floor(_sound.bytesLoaded / _sound.bytesTotal * 100);
} else if (!_channel && progressEvent && progressEvent.bytesTotal > 0) {
bufferPercent = Math.floor(progressEvent.bytesLoaded / progressEvent.bytesTotal * 100);
} else {
bufferPercent = 0;
}
//if (_sound.isBuffering == true && _sound.bytesTotal > _sound.bytesLoaded) {
if (_sound.isBuffering == true && _sound.bytesTotal > _sound.bytesLoaded > 0) {
if (state != PlayerState.BUFFERING) {
//_bufferFull = false;
_bufferFull = true;
if (_channel) {
_channel.stop();
play();
}
if (!progressEvent) {
setState(PlayerState.BUFFERING);
}
}
} else if (state == PlayerState.BUFFERING && _sound.bytesLoaded > 0 && !_bufferFull) {
//_bufferFull = true;
_bufferFull = false;
//sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_BUFFER_FULL);
play();
}
if (!isNaN(bufferPercent) && !_bufferingComplete){
if (bufferPercent == 100 && _bufferingComplete == false) {
_bufferingComplete = true;
}
sendBufferEvent(bufferPercent, 0, {loaded:_sound.bytesLoaded, total:_sound.bytesTotal});
}
if (state != PlayerState.PLAYING) {
return;
}
if (_position < _item.duration) {
sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_TIME, {position: _position, duration: _item.duration});
} else if (_item.duration > 0) {
complete();
}
}
/** Seek in the _sound. **/
override public function seek(pos:Number):void {
if (_sound && _sound.bytesTotal > 0 && (pos < (_sound.bytesLoaded / _sound.bytesTotal) * item.duration) || item.start) {
clearInterval(_positionInterval);
_positionInterval = undefined;
if (_channel) {
_channel.stop();
}
_position = pos;
play();
}
}
/** Destroy the _sound. **/
override public function stop():void {
clearInterval(_positionInterval);
_positionInterval = undefined;
super.stop();
if (_channel) {
_channel.stop();
_channel = null;
}
try {
_sound.close();
} catch (err:Error) {
}
}
/** Set the volume level. **/
override public function setVolume(vol:Number):void {
streamVolume(vol);
super.setVolume(vol);
}
/** Set the stream's volume, without sending a volume event **/
protected function streamVolume(level:Number):void {
_transformer.volume = level / 100;
if (_channel) {
_channel.soundTransform = _transformer;
}
}
}
}
Okay, so now we have that covered. I’ll submit my changes to the Longtail forums and then maybe a pro can make some changes – and then we have opensource going – and then we can all go and drink some beer at the Pub *YAY!*
I hope this helps you in any way,
Winston