Forked from: seikimaiii's playing streamed chunks of mp3s diff:1 forked from: playing streamed chunks of mp3s hacker_mx_95.. forked:0favorite:0lines:417license : MIT License modified : 2012-02-03 13:30:50 Embed Tweet // 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); } } Code Fullscreen Preview Fullscreen