AS3 - XML Playlist with Single-Track Looping - actionscript-3

So this one has me stumped. My plan for my website is to have music tracks pulled from an XML file which act as the background music for the various .swfs loaded by the menu buttons. I.e. hit 'Home', and it takes you back to the home .swf and plays the appropriate music. I want to do this through XML rather than attaching the music directly to the .swf to cut down on load time (syncing isn't a concern), as I can't seem to retain audio quality without bulking up the .swf significantly.
I'm encountering two problems: one is that with the current code, the music only plays once, and doesn't loop. The other is that I want the functionality to play one song as an intro, and then continue to loop another. I.e., hit the home button, intro plays, followed by the looping section, and never returns to the intro unless you hit home again. I can't seem to figure out how to manage either of these things short of creating a unique function for every single button.
Here's the code I'm using:
var my_songs:XMLList;
var my_total:Number;
var my_sound:Sound;
var my_channel:SoundChannel;
var current_song:Number;
var myXMLLoader:URLLoader = new URLLoader();
myXMLLoader.load(new URLRequest("playlist.xml"));
myXMLLoader.addEventListener(Event.COMPLETE, processXML);
function processXML(e:Event):void {
var myXML:XML = new XML(e.target.data);
my_songs = myXML.SONG;
my_total = my_songs.length();
//playSong(0);
myXMLLoader.removeEventListener(Event.COMPLETE, processXML);
myXMLLoader = null;
}
function playSong(mySong:Number):void {
var myURL = my_songs[mySong].#URL;
if (my_channel) {
my_channel.stop();
my_channel.removeEventListener(Event.SOUND_COMPLETE, playSong);
}
my_sound = new Sound();
my_sound.load(new URLRequest(myURL));
my_channel = my_sound.play();
my_channel.addEventListener(Event.SOUND_COMPLETE, playSong);
}
test_btn.addEventListener(MouseEvent.CLICK, onPlay);
function onPlay(e:MouseEvent):void {
playSong(0);
}
Thanks in advance for any help you can give!

YourSongstarting(0,999); // how ever you call to play the song
This above will repeat song forever. I suggest you stream the audio file as this will load the song quicker, then you can keep the songs in memory.you can still use xml or any other external textfile for the audio tracks locations or directly in flash/class files if this site is concrete.
any events you wold like to control simply compare the "Buffer" value out of 100%.Look up streaming audio as3 there are plenty of tutorials with source code if need be let me know i can give you an example.

You were close
var my_songs:XMLList;
var my_total:Number;
var my_sound:Sound;
var my_channel:SoundChannel;
var current_song:Number;
var myXMLLoader:URLLoader = new URLLoader();
myXMLLoader.load(new URLRequest("playlist.xml"));
myXMLLoader.addEventListener(Event.COMPLETE, processXML);
function processXML(e:Event):void {
var myXML:XML = new XML(e.target.data);
my_songs = myXML.SONG;
my_total = my_songs.length();
playSong(0);
myXMLLoader.removeEventListener(Event.COMPLETE, processXML);
myXMLLoader = null;
}
function playSong(e:Event):void {
if( current_song > my_total )
current_song = 0;
var myURL = my_songs[current_song++].#URL;
if (my_channel) {
my_channel.stop();
my_channel.removeEventListener(Event.SOUND_COMPLETE, playSong);
}
my_sound = new Sound();
my_sound.load(new URLRequest(myURL));
my_channel = my_sound.play();
my_channel.addEventListener(Event.SOUND_COMPLETE, playSong);
}
test_btn.addEventListener(MouseEvent.CLICK, onPlay);
function onPlay(e:MouseEvent):void {
playSong(e);
}

Related

I am looking for a simple solution to loading a new/different mp3 sound file upon clicking a thumbnail using my existing code below

This seems simple enough, I just can't crack it though.
currently, in the below code. its a UILoader with a series of thumbnail mc's horizontally across the bottom of the FLA. when the thumbs are clicked and new SWF loads in the UI.
I am simply looking for the error of my ways, hopefully by simply added to this code and a possible explanation. I need to figure out how to play/stop on exit and new mp3 sound file.
UILoader
With movieClips used for thumbnail loads
var imagesXML:XML;
var xmlLoader: URLLoader = new URLLoader();
xmlLoader.load(new URLRequest("lessons/images/Images5.xml"));
/////////////////////////////////////////////////////////////
//////////// thumbnail loader /////////////////////////
function xmlLoaded(evt:Event):void
{
imagesXML = new XML(xmlloader.data);
var thumbLoader:UILoader;
for(var i:uint = 0; i < imagesXML.image.length(); i++)
{
thumbLoader UILoader(getChildByName("thumb" + 1));
thumbLoader.load(new URLRequest("lessons/images/thumbs/" + imagesXML.image[i].#file));
thumbLoader.buttonmode = true;
thumbLoader.addEventListener(MouseEvent.CLICK, thumbClicked);
var fullPath:String = "lessons/images/file-1.swf";
mainLoader.load(new URLRequest(fullpath));
}
}
/////////////////////////////////////////////////////////////
//////////////// load Images /////////////////////////////
function thumbClicked(evt:MouseEvent):void
{
var thumbName:String = evt.currentTarget.name;
var thumbIndex:uint = uint(thumbName.substr(5));
var fullPath:String = "lessons/images/" + imagesXML. image[thumbIndex].#file;
mainLoader.load(new URLRequest(fullPath));
}
you can try to use this library https://github.com/treefortress/SoundAS
or try to google "Sound manager for as3" and I sure you will find library you like
Declare sound object outside of functions so it is available to all functions
var mySound:Sound;
var myChannel:SoundChannel;
function thumbClicked(evt:MouseEvent):void
{
var thumbName:String = evt.currentTarget.name;
var thumbIndex:uint = uint(thumbName.substr(5));
var fullPath:String = "lessons/images/" + imagesXML. image[thumbIndex].#file;
mainLoader.load(new URLRequest(fullPath));
//stop any already playing sound
if ( myChannel != null) { myChannel.stop(); }
//load an MP3 file
mySound = new Sound(); mychannel = new SoundChannel();
mySound.load(new URLRequest("myAudio.mp3"));
mySound.play();
}

AS3 browse and load video

I'm currently working on a AS3 AIR project which involves allowing the user to browse a video file and load that same video onto the stage. I've managed to allow the user to browse for a video file type and according to my traces it completes loading the video but this is as far as I've got. There is plenty of tutorials which involve how to load video files from local sources or external links but nothing to show me what to do with a browsed file to display it on the stage. Here is the code so far for browsing to the video file:
private function browseVideo():void {
fileReference = new FileReference();
fileReference.addEventListener(Event.SELECT, videoFileSelected);
var videoTypeFilter:FileFilter = new FileFilter("Video files", "*.3g2; *.3gp; *.asf; *.asx; *.avi; *.flv; *.m4v; *.mov; *.mp4; *.mpg; *.rm; *.swf; *.vob; *.wmv;");
fileReference.browse([videoTypeFilter]);
}
private function videoFileSelected(e:Event):void {
fileReference.addEventListener(Event.COMPLETE, onVideoFileLoaded);
fileReference.addEventListener(IOErrorEvent.IO_ERROR, onVideoFileLoadError);
fileReference.load();
}
function onVideoFileLoaded(e:Event):void {
var fileReferenceTarget:FileReference = e.target as FileReference;
var data:ByteArray = fileReferenceTarget["data"];
fileReference.removeEventListener(Event.COMPLETE, onVideoFileLoaded);
fileReference.removeEventListener(IOErrorEvent.IO_ERROR, onVideoFileLoadError);
var videoLoader:Loader = new Loader();
videoLoader.loadBytes(data);
videoLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onVideoLoaderComplete);
trace("video file loaded");
}
function onVideoFileLoadError(e:Event):void {
fileReference.removeEventListener(Event.COMPLETE, onVideoFileLoaded);
fileReference.removeEventListener(IOErrorEvent.IO_ERROR, onVideoFileLoadError);
trace("video file load failed");
}
function onVideoLoaderComplete(e:Event):void {
var loadedContent:DisplayObject = e.target.content;
var loader:Loader = e.target.loader as Loader;
scope.addChild(loader);
}
To play a video using AS3 ( Flash ) you can use a Video object on which you can attach a NetStream object, you can also use an FLVPlayback component. For flex, take a look on my answer of this question where I put an example of playing a video stream. And in all cases, I think that you don't need a FileReference object because a File is suffisant to get the path of your local file and then play it with any manner you want.
Take a look on this example :
function browseVideo():void {
var file:File = new File();
file.addEventListener(Event.SELECT, videoFileSelected);
file.browse([videoTypeFilter]);
}
function videoFileSelected(e:Event):void {
playVideo(e.currentTarget.nativePath);
}
function playVideo(video_path:String){
// using a Video + NetStream object
var nc:NetConnection = new NetConnection();
nc.connect(null);
var ns:NetStream = new NetStream(nc);
ns.client = this;
var video:Video = new Video();
video.attachNetStream(ns);
addChild(video);
ns.play(video_path);
// using an FLVPlayback component inserted on the Stage
flvplayback.load(video_path);
flvplayback.play();
}
For more details on how to work with video, you can take a look here, you can find all what you need to know about video ( loading videos, supported formats, cue points, ... ).
Hope that can help.

Text stops showing unless not playing

So i finally got my flash application to work and have it running on a website but after a while the dynamic text stops showing up in the fields. The file is set to loop every 5 seconds and it is supposed to update to show the staff on air and what is currently playing. Link to the website is http://mischieffm.com/
var xmlData:XML = new XML();
var header:URLRequestHeader = new URLRequestHeader("pragma", "no-cache");
var theURL_ur:URLRequest = new URLRequest ("/stream/shout.xml?rnd=" + Math.random());
var loader_ul:URLLoader = new URLLoader(theURL_ur);
loader_ul.addEventListener("complete", fileLoaded);
function fileLoaded(e:Event):void
{
xmlData = XML(loader_ul.data);
show_txt.text = xmlData.SERVERTITLE;
song_txt.text = xmlData.SONGTITLE;
}
This is all done in cs6 flash pro and actionscript 3
Try this:
function fileLoaded(e:Event):void
{
loader_ul.removeEventListener("complete", fileLoaded);
xmlData = new XML(loader_ul.data);
if (xmlData.SONGTITLE && xmlData.SERVERTITLE)
{
show_txt.text = xmlData.SERVERTITLE;
song_txt.text = xmlData.SONGTITLE;
}
else
{
show_txt.text = "Untitled artist";
song_txt.text = "Untitled song";
}
}
Note: In order to prevent memory leaks, always call removeEventListener("someEvent", someMethod); after your event gets dispatched. There are some exclusions, but generally you should do it all the time.

actionscript 3.0 function calling using button click

im creating a simple flash playlist using buttons, in my stage i have 4 buttons which is button for song1,song2, stop and play. i have a working code for this one, but i decided to revise it because my previous code is like, per song they have each stop and play button,so i created this one to have a dynamic stop and play, i created a function for each song, the function will change the filename of the song to be loaded,
heres the catch, so i first pick a song, (either song1 or song2) then i click stop, then when i select a new song this error appears
Error: Error #2037: Functions called in incorrect sequence, or earlier call was unsuccessful.
at flash.media::Sound/_load()
at flash.media::Sound/load()
at playlist_fla::MainTimeline/songSelect1()
i think its not calling the second function because i cant see the trace i put inside it,anyway heres my code, sorry for the long post,
THANKS IN ADVANCE
var mySound:Sound = new Sound();
var myChannel:SoundChannel = new SoundChannel();
var myTransform = new SoundTransform();
var lastPosition:Number = 0;
var song;
song1.addEventListener(MouseEvent.CLICK,songSelect1);
function songSelect1(e:MouseEvent):void{
song = "<filenameofthe1stsong>";
mySound.load(new URLRequest(song));
myTransform.volume = 0.5;
myChannel.soundTransform = myTransform;
lastPosition=0;
trace(1);
}
song2.addEventListener(MouseEvent.CLICK,songSelect2);
function songSelect2(e:MouseEvent):void{
song = "<filenameofthe2ndsong>";
mySound.load(new URLRequest(song));
myTransform.volume = 0.5;
myChannel.soundTransform = myTransform;
lastPosition=0;
trace(2);
}
btnStop.addEventListener(MouseEvent.CLICK,onClickStop);
function onClickStop(e:MouseEvent):void{
lastPosition = myChannel.position;
myChannel.stop();
}
btnPlay.addEventListener(MouseEvent.CLICK,onClickPlay);
function onClickPlay(e:MouseEvent):void{
myChannel = mySound.play(lastPosition);
myChannel.soundTransform = myTransform();
}
Correction:
According to Adobe:
Once load() is called on a Sound object, you can't later load a
different sound file into that Sound object. To load a different sound
file, create a new Sound object.
So, creating a new sound object would be the only way to fix it.
- - - Original Post - - -
If you enable debugging in your flash settings, it'd be easier to determine exactly what line is causing issues. That said, your code doesn't look incorrect apart from defining your sound transform twice. Try this:
var mySound:Sound = new Sound();
var myChannel:SoundChannel = new SoundChannel();
var myTransform = new SoundTransform();
myChannel.soundTransform = myTransform;
var lastPosition:Number = 0;
var song;
song1.addEventListener(MouseEvent.CLICK,songHandler);
song2.addEventListener(MouseEvent.CLICK,songHandler);
btnStop.addEventListener(MouseEvent.CLICK,onClickStop);
btnPlay.addEventListener(MouseEvent.CLICK,onClickPlay);
function songHandler(e:MouseEvent):void {
switch (e.currentTarget.name) {
case "song1":
songSelect("<filenameofthe1stsong>")
break;
case "song2":
songSelect("<filenameofthe2ndsong>")
break;
}
}
function songSelect(songPath:String):void {
mySound.load(new URLRequest(songPath));
myChannel.soundTransform.volume = 0.5;
lastPosition = 0;
trace("Loading " + songPath);
}
function onClickStop(e:MouseEvent):void {
lastPosition = myChannel.position;
myChannel.stop();
}
function onClickPlay(e:MouseEvent):void {
myChannel = mySound.play(lastPosition);
myChannel.soundTransform = myTransform();
}

as3 loop loading urls - continue loop on complete

I am trying to load a bunch of files in order. I want the other to start downloading once the previous has downloaded. I thought the best way to do this would be thru a for loop.
TheURL = is a bunch of urls in a ARRAY
for(var i:int=0;i<TheURL.length;i++)
{
var urlString:String = TheURL[i];
var urlReq:URLRequest = new URLRequest(urlString);
var urlStream:URLStream = new URLStream();
var fileData:ByteArray = new ByteArray();
urlStream.addEventListener(Event.COMPLETE, loaded);
urlStream.load(urlReq);
function loaded(event:Event):void
{
/// code to continue loop
}
}
It is important that the others do not start downloading until the previous has completed. Any suggestions on how to do that? Thanks
function downloadFiles():void
{
downloadNextFile();
}
function downloadNextFile():void
{
var urlString:String = TheURL.shift();
var urlReq:URLRequest = new URLRequest(urlString);
var urlStream:URLStream = new URLStream();
var fileData:ByteArray = new ByteArray();
urlStream.addEventListener(Event.COMPLETE, loaded);
urlStream.load(urlReq);
}
function loaded(event:Event):void
{
downloadNextFile();
}
Using a for-loop does not solve what you want to do.
In my opinion the easiest way should be to use the array of URLs as a queue. This can be done by using Array.shift(). But you should make a copy of your array if you need the original set of URLs when finished, because shift() makes an inline modification of the array.
The solution could be the following:
function loadQueue(urlQueue:Array):void
{
var url:String = urlQueue.shift();
var request:URLRequest = new URLRequest(url);
var stream:URLStream = new URLStream();
var data:ByteArray = new ByteArray();
var completeHandler:Function = function(event:Event)
{
// remove listener from stream to be a clean coder ;)
stream.removeEventListener(Event.COMPLETE, completeHandler);
// handle completion in the way you need ...
// continue with the next element
if (urlQueue.length > 0)
loadQueue(urls);
}
urlStream.addEventListener(Event.COMPLETE, loaded);
urlStream.load(urlReq);
}
Loading your queue will then look like:
loadQueue(TheURL.concat()); // concat() will clone your array
You should use a library like greensock LoaderMax http://www.greensock.com/loadermax/.
It's much more difficult than it seems to create your own loading queue. There are plenty of bugs, traps and special cases to deal with. It seems to work fine, and one day a customer call you back because of a bug on this particular flash version on this computer behind this firewall... I've started to do mine library, but finally I used LoadManager.