forked from: playing streamed chunks of mp3s
forked from playing streamed chunks of mp3s (diff: 1)
ActionScript3 source code
/**
* Copyright hacker_mx_95scj ( http://wonderfl.net/user/hacker_mx_95scj )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/3y9W
*/
// forked from seikimaiii's playing streamed chunks of mp3s
package
{
import flash.geom.*;
import flash.display.*;
import flash.events.*;
import flash.media.*;
import flash.utils.ByteArray;
import flash.utils.Timer;
import flash.net.URLRequest;
import flash.text.TextField;
import flash.external.ExternalInterface;
import flash.system.Security;
[SWF(frameRate="30",width=400,height=400,backgroundColor=0)]
/**
*
* @author SeikimaIII
* v1.0
*
* Music Class
* Container for all the individual player elements.
*
*/
public class Music extends MovieClip
{
public var _box_top:Shape; // I suppose I don't need this
public var _box_bottom:Shape; // I suppose I don't need this
public var _button_previous:PlayerButton;
public var _button_play:PlayerButton;
public var _button_next:PlayerButton;
//private var _button_volume:PlayerButton;
public var _info_bar:InfoBar;
private var _timer:Timer;
private var _carrier:Sound;
private var _carrierChannel:SoundChannel;
private var _isChannelStopped:Boolean = true;
private var _soundLoader:SoundLoader;
public function Music():void
{
inittrace(stage);
Security.loadPolicyFile("http://music.lunchbin.com/crossdomain.xml");
// Initialize graphics objects
_box_top = new Shape();
_box_bottom = new Shape();
// Initialize buttons
_button_previous = new PlayerButton("previous");
_button_play = new PlayerButton("play");
_button_next = new PlayerButton("next");
//_button_volume = new PlayerButton(); // need volume button class
// Initialize info
_info_bar = new InfoBar();
// Top box
_box_top.graphics.lineStyle(1, 0xFFFFFF, 1);
_box_top.graphics.drawRect(0, 0, 400, 30);
// Bottom boxawda
_box_bottom.graphics.lineStyle(1, 0xFFFFFF, 1);
_box_bottom.graphics.drawRect(0, 30, 400, 30);
// Buttons
_button_previous.SetPosition(0, 30);
_button_play.SetPosition(100, 30);
_button_next.SetPosition(200, 30);
_button_play.addEventListener(MouseEvent.MOUSE_UP, Play);
// Add graphic objects
addChild(_button_previous);
addChild(_button_play);
addChild(_button_next);
//addChild(button_volume);
addChild(_info_bar);
addChild(_box_top);
addChild(_box_bottom);
_timer = new Timer(33.33); //30fps
_timer.addEventListener(TimerEvent.TIMER, Tick);
_timer.start();
_soundLoader = new SoundLoader();
_carrier = new Sound();
_carrier.addEventListener(SampleDataEvent.SAMPLE_DATA, _soundLoader.OnSampleData);
}
// Main loop
public function Tick(e:TimerEvent) : void
{
//_info_bar.Update();
_soundLoader.Update();
// Check if we can start/restart the carrier sound
if (_isChannelStopped && _soundLoader.HasData())
{
_carrierChannel = _carrier.play();
_isChannelStopped = false;
}
}
public function Play(e:MouseEvent) : void
{
_soundLoader.Load("0");
}
public function OnSoundComplete(e:Event) : void
{
_isChannelStopped = true;
}
}
}
import flash.utils.ByteArray;
import flash.media.Sound;
import flash.events.*;
import flash.geom.*;
import flash.display.*;
import flash.net.*;
import flash.text.TextField;
import flash.text.TextFormat;
class SoundLoader
{
// An array of sounds used to load data
private var _sounds:Array;
// A number pointing to the currently active sound to extract samples from
private var _currentSound:Number;
// A number pointing to the currently loading sound
private var _loadingSound:Number;
// A number containing the current amount of time loaded for the song (in seconds)
private var _time:Number;
// A string containing the song id
private var _songid:String;
// The url to the php file
private var _url:String = "http://music.lunchbin.com/public/io.php";
// The byte array buffer
private var _buffer:ByteArray;
// The maximum number of samples that can be extracted
private var MAXSAMPLES:Number = 4096;
private var MAXSAMPLES_BYTES:Number = 65536;
// Constructor
public function SoundLoader() : void
{
}
/**
* Load function
*
* @param url:String the file to start loading
*/
public function Load(songid:String) : void
{
_songid = songid;
// Clear everything
_sounds = [null, null, null];
_buffer = new ByteArray();
_currentSound = 0;
_loadingSound = 0;
_time = 20;
// Set up the first sound
_sounds[_loadingSound] = new Sound();
var sound:Sound = _sounds[_loadingSound];
sound.load(new URLRequest(GetURL()));
}
public function OnSampleData(e:SampleDataEvent):void
{
// Reset buffer position
_buffer.position = 0;
// Get the extract sound
var extractSound:Sound = _sounds[_currentSound];
// Extract Samples
var numSamples:Number = extractSound.extract(_buffer, MAXSAMPLES);
//trace("numsamples: " + numSamples);
// Were the full amount of samples extracted
if (numSamples < MAXSAMPLES)
{
// Clear out the current sound
_sounds[_currentSound] = null;
// Adjust next sample extraction
var samples:Number = MAXSAMPLES - numSamples;
// Move to the next available extract sound
var nextSound:Number = (_currentSound + 1) % _sounds.length;
extractSound = _sounds[nextSound];
// Is the next sound finished loading
if (!extractSound.isBuffering)
{
_currentSound = nextSound;
numSamples = extractSound.extract(_buffer, samples);
}
}
// Write buffer data
_buffer.position = 0;
e.data.writeBytes(_buffer);
}
public function Update():void
{
// Not loading anything
if (_loadingSound == -1)
{
return;
}
// Get the loading sound object
var sound:Sound = _sounds[_loadingSound];
// Is it done buffering
if (!sound.isBuffering)
{
// Extract empty data
sound.extract(_buffer, 2048);
_buffer.position = 0;
var nextLoadingSound:Number = (_loadingSound + 1) % _sounds.length;
if (_sounds[nextLoadingSound] == null)
{
// Move to the next sound spot
_loadingSound = nextLoadingSound;
// Create the sound object
_sounds[_loadingSound] = new Sound();
sound = _sounds[_loadingSound];
// Download data
sound.load(new URLRequest(GetURL()));
}
}
}
public function HasData():Boolean
{
// Check all the sounds to see if any are fully loaded
for (var i:Number = 0; i < _sounds.length; i++)
{
var sound:Sound = _sounds[i];
if (sound != null && !sound.isBuffering)
{
return true;
}
}
return false;
}
public function GetURL():String
{
var random:Number = Math.floor(Math.random() * 1000); // Damn you flash quit caching files
// Generate the url - url + action + songid + start time + end time
var url:String = _url + "?" + "action=get_mp3" + "&" + "songid=" + _songid + "&" + "start=" + _time + "&" + "end=" + (_time + 10) + "&random=" + random;
trace("Retrieving chunk [" + _time + "s - " + (_time+10) + "s]");
// Increment the start time by 10 seconds
_time = _time + 10;
return url;
}
}
/**
*
* @author SeikimaIII
* v1.0
*
* Player Button Class
* Makes buttons on the player (play, prev, next).
*
* TODO:
* Add shine gradient
* Figure out mouse up events triggering functions in MP3Player class
*
*/
class PlayerButton extends MovieClip
{
public var _mc:MovieClip;
private var _type:String;
private var _primary_color:uint;
private var _secondary_color:uint;
public function PlayerButton(type:String):void
{
_mc = new MovieClip();
// Member variables
_type = type;
_primary_color = 0xFFFFFF;
_secondary_color = 0x675122;
// Button modifiers
_mc.buttonMode = true;
_mc.useHandCursor = true;
// Events
_mc.addEventListener(MouseEvent.MOUSE_DOWN, OnMouseDown);
_mc.addEventListener(MouseEvent.MOUSE_UP, OnMouseUp);
_mc.addEventListener(MouseEvent.MOUSE_OUT, OnMouseOut);
// Draw
this.Draw(_primary_color);
addChild(_mc);
}
private function Draw(color:uint) : void
{
// Gradient filter
var m:Matrix = new Matrix();
m.createGradientBox(100, 30, Math.PI * 0.5);
_mc.graphics.beginGradientFill(GradientType.LINEAR, [0x1e1e1e, 0x65e5e5e], null, null, m);
// Rect
_mc.graphics.lineStyle(1, 0xFFFFFF, 1);
_mc.graphics.drawRect(0, 0, 100, 30);
_mc.graphics.endFill();
// Create the button face
switch (_type)
{
case "previous":
{
_mc.graphics.lineStyle(1, color);
_mc.graphics.beginFill(color);
_mc.graphics.moveTo(55, 5);
_mc.graphics.lineTo(55, 25);
_mc.graphics.lineTo(35, 14);
_mc.graphics.lineTo(55, 5);
_mc.graphics.endFill();
_mc.graphics.beginFill(color);
_mc.graphics.moveTo(65, 5);
_mc.graphics.lineTo(65, 25);
_mc.graphics.lineTo(45, 14);
_mc.graphics.lineTo(65, 5);
_mc.graphics.endFill();
break;
}
case "play":
{
_mc.graphics.lineStyle(1, color);
_mc.graphics.beginFill(color);
_mc.graphics.moveTo(40, 5);
_mc.graphics.lineTo(40, 25);
_mc.graphics.lineTo(60, 14);
_mc.graphics.lineTo(40, 5);
_mc.graphics.endFill();
break;
}
case "next":
{
_mc.graphics.lineStyle(1, color);
_mc.graphics.beginFill(color);
_mc.graphics.moveTo(35, 5);
_mc.graphics.lineTo(35, 25);
_mc.graphics.lineTo(55, 14);
_mc.graphics.lineTo(35, 5);
_mc.graphics.endFill();
_mc.graphics.beginFill(color);
_mc.graphics.moveTo(45, 5);
_mc.graphics.lineTo(45, 25);
_mc.graphics.lineTo(65, 14);
_mc.graphics.lineTo(45, 5);
_mc.graphics.endFill();
break;
}
}
}
private function OnMouseDown(e:MouseEvent) : void
{
this.Draw(_secondary_color);
}
private function OnMouseUp(e:MouseEvent) : void
{
this.Draw(_primary_color);
}
private function OnMouseOut(e:MouseEvent) : void
{
this.Draw(_primary_color);
}
public function SetPosition(x:Number, y:Number) : void
{
_mc.x = x;
_mc.y = y;
}
}
/**
*
* @author SeikimaIII
* v1.0
*
* InfoBar Class
* Contains all the information layers for the player (song title, song position, etc.).
* Controls the player position via mouse down event on the top bar.
*
* TODO:
* Move timer to MP3Player class
* Add background color
* Add play position bar
* Add mouse down event
*
*/
class InfoBar extends MovieClip
{
private var _play_position:TextField;
private var _play_time:Number = 0;
private var _song_title:TextField;
private var _song_title_mask:MovieClip;
private var _play_bar:MovieClip;
public function InfoBar() : void
{
// Background
graphics.beginFill(0xCCCCCC);
graphics.drawRect(0, 0, 400, 30);
// Play position bar
_play_bar = new MovieClip();
_play_bar.graphics.beginFill(0x675122);
_play_bar.graphics.drawRect(0, 0, 400, 30);
addChild(_play_bar);
// Play position text
_play_position = new TextField();
_play_position.x = 335;
_play_position.y = 2;
_play_position.text = "00:00";
_play_position.setTextFormat(new TextFormat("Verdana", 18, 0xFFFFFF));
_play_position.width = _play_position.textWidth + 10;
_play_position.selectable = false;
addChild(_play_position);
// Song title mask
_song_title_mask = new MovieClip();
_song_title_mask.graphics.beginFill(0);
_song_title_mask.graphics.drawRect(0, 0, 330, 30);
// Song title text
_song_title = new TextField();
_song_title.x = 330;
_song_title.y = 8;
_song_title.text = "test text";
_song_title.setTextFormat(new TextFormat("Verdana", 10, 0xFFFFFF));
_song_title.width = _song_title.textWidth + 10;
_song_title.selectable = false;
_song_title.mask = _song_title_mask;
addChild(_song_title);
addEventListener(MouseEvent.MOUSE_UP, OnMouseUp);
}
public function Update() : void
{
// Play bar
_play_bar.width = _play_bar.width + 0.1;
if (_play_bar.width >= 400)
{
_play_bar.width = 0;
}
// Play Position
_play_time = _play_time + 1;
var minutes:Number = Math.floor(_play_time/60);
var seconds:Number = _play_time - minutes*60;
// Check the time
if (isNaN(minutes) || isNaN(seconds))
{
_play_position.text = "00:00";
}
else
{
if (minutes < 10)
{
_play_position.text = "0";
_play_position.appendText(String(minutes));
}
else
{
_play_position.text = String(minutes);
}
if (seconds < 10)
{
_play_position.appendText(":0");
_play_position.appendText(String(seconds));
}
else
{
_play_position.appendText(":");
_play_position.appendText(String(seconds));
}
}
_play_position.setTextFormat(new TextFormat("Verdana", 18, 0xFFFFFF)); // Why do I have to do this every time?
_play_position.width = _play_position.textWidth + 2;
_play_position.x = 400 - _play_position.width - 10;
// Song Title
_song_title.x = _song_title.x - 1;
if (_song_title.x <= (0 - _song_title.textWidth))
{
_song_title.x = 330;
}
}
public function SetSongTitle(title:String) : void
{
_song_title.text = title;
_song_title.setTextFormat(new TextFormat("Verdana", 10, 0xFFFFFF));
}
public function Reset() : void
{
_play_time = 0;
}
public function OnMouseUp(e:MouseEvent) : void
{
_play_bar.width = mouseX;
}
}
///// WONDERFL TRACE /////
import flash.display.Sprite;
import flash.display.Stage;
import flash.text.TextField;
import flash.text.TextFormat;
function inittrace(s:Stage):void
{
WTrace.initTrace(s);
}
//global trace function
var trace:Function;
//wtreace class
class WTrace
{
private static var FONT:String = "Fixedsys";
private static var SIZE:Number = 12;
private static var TextFields:Array = [];
private static var trace_stage:Stage;
public static function initTrace(stg:Stage):void
{
trace_stage = stg;
trace = wtrace;
}
private static function scrollup():void
{
// maximum number of lines: 100
if (TextFields.length > 1000)
{
var removeme:TextField = TextFields.shift();
trace_stage.removeChild(removeme);
removeme = null;
}
for(var x:Number=0;x<TextFields.length;x++)
{
(TextFields[x] as TextField).y -= SIZE*1.2;
}
}
public static function wtrace(... args):void
{
var s:String="";
var tracefield:TextField;
for (var i:int;i < args.length;i++)
{
// imitating flash:
// putting a space between the parameters
if (i != 0) s+=" ";
s+=args[i].toString();
}
tracefield= new TextField();
tracefield.autoSize = "left";
tracefield.text = s;
tracefield.y = trace_stage.stageHeight - 20;
tracefield.width = trace_stage.stageWidth;
var tf:TextFormat = new TextFormat(FONT, SIZE, 0xFFFFFF);
tracefield.setTextFormat(tf);
trace_stage.addChild(tracefield);
scrollup();
TextFields.push(tracefield);
}
}