Errors in Action Script 3 in streaming .mp3 player - actionscript

I'm trying to build a streaming .mp3 player to run various sound files on my web site. To do that, I followed a tutorial that includes a code template at:
http://blog.0tutor.com/post.aspx?id=202&title=Mp3%20player%20with%20volume%20slider%20using%20Actionscript%203
However, whether I preserve the template's direction to the author's own sound file or insert my own direction to my online sound file, I keep on running into glitches in the ActionScript that I can't fathom.
Those errors are:
1084: Syntax error: expecting rightparen before _.
1086: Syntax error: expecting semicolon before rightparen.
When I try to correct them, I get new errors. I can't determine whether the sound file is loading; it certainly never plays. The volume slider does not work.
I did find one line that looked like it should have been commented out, the one that reads
to start at the same place
So I tried commenting that out. No dice. Same errors.
Thanks in advance for any suggestions. Code follows:
var musicPiece:Sound = new Sound(new URLRequest _
("http://blog.0tutor.com/JeffWofford_Trouble.mp3"));
var mySoundChannel:SoundChannel;
var isPlaying:Boolean = false;
to start at the same place
var pos:Number = 0;
play_btn.addEventListener(MouseEvent.CLICK, play_);
function play_(event:Event):void {
if (!isPlaying) {
mySoundChannel = musicPiece.play(pos);
isPlaying = true;
}
}
pause_btn.addEventListener(MouseEvent.CLICK, pause_);
function pause_(event:Event):void {
if (isPlaying) {
pos = mySoundChannel.position;
mySoundChannel.stop();
isPlaying = false;
}
}
stop_btn.addEventListener(MouseEvent.CLICK, stop_);
function stop_(event:Event):void {
if (mySoundChannel != null) {
mySoundChannel.stop();
pos = 0;
isPlaying = false;
}
}
var rectangle:Rectangle = new Rectangle(0,0,100,0);
var dragging:Boolean = false;
volume_mc.mySlider_mc.addEventListener(MouseEvent.MOUSE_DOWN, startDragging);
function startDragging(event:Event):void {
volume_mc.mySlider_mc.startDrag(false,rectangle);
dragging = true;
volume_mc.mySlider_mc.addEventListener(Event.ENTER_FRAME, adjustVolume);
}
function adjustVolume(event:Event):void {
var myVol:Number = volume_mc.mySlider_mc.x / 100;
var mySoundTransform:SoundTransform = new SoundTransform(myVol);
if (mySoundChannel != null) {
mySoundChannel.soundTransform = mySoundTransform;
}
}
stage.addEventListener(MouseEvent.MOUSE_UP, stopDragging);
function stopDragging(event:Event):void {
if (dragging) {
dragging = false;
volume_mc.mySlider_mc.stopDrag();
}
}

Syntax errors are just what it says they are, the code is not properly written. For instance , you shouldn't have an underscore after URLREquest
var musicPiece:Sound =
new Sound(new URLRequest("http://blog.0tutor.com/JeffWofford_Trouble.mp3"));
to start at the same place should be commented out, simply because it's a comment, it's not a variable or a function.
to call a function "play_" is not really good practice either. Call it soundPlay, if you're concern about conflicts.
same comment for pause_ and stop_

Related

Firefox addon - monitoring network

If I add an nsIHttpChannel observer, is there any way I can know what initiated the HTTP request(script, iframe, image etc..)
In chrome when monitoring the network from the background page you have the request type telling you if it came from an iframe, script etc...
Don't accept this as solution yet. I hope some other people can come and help build this solution.
I know this is for sure correct:
TEST FOR: XHR - identify XHR (ajax) response while listening to http response in firefox addon
Get load context of request (like which tab, which html window, which xul window) - Firefox add-on pageMod, catch ajax done in contentScriptFile (this is marked as optional though in the code below it requires a helper function: https://gist.github.com/Noitidart/644494bdc26f996739ef )
This I think is correct, by this i mean it works in my test cases but I'm not sure if its the recommended way:
TEST FOR: Frame or full page load - Can we differentiate between frame and non-frame loads with Ci in firefox addon
This I don't know how to do so I need help from community on this:
TEST FOR image - Comment on "identify XHR (ajax) response while listening to http response in firefox addon"
Image detection can be done through the MIME type. Check channel.contentType
Solution in progress:
var myobserve = function(aSubject, aTopic, aData) {
var httpChannel = aSubject.QueryInterface(Ci.nsIHttpChannel);
//start - test if xhr
var isXHR;
try {
var callbacks = httpChannel.notificationCallbacks;
var xhr = callbacks ? callbacks.getInterface(Ci.nsIXMLHttpRequest) : null;
isXHR = !!xhr;
} catch (e) {
isXHR = false;
}
//end - test if xhr
//start - test if frame OR full page load
var isFrameLoad;
var isFullPageLoad;
if (httpChannel.loadFlags & Ci.nsIHttpChannel.LOAD_INITIAL_DOCUMENT_URI) {
isFullPageLoad = true;
isFrameLoad = false;
} else if (httpChannel.loadFlags & Ci.nsIHttpChannel.LOAD_DOCUMENT_URI) {
isFrameLoad = true;
isFullPageLoad = false;
}
//end - test if frame OR full page load
//start - test if image
var isImg;
var isCss;
var isJs;
var isAudio;
//can keep going here
var mimeType = httpChannel.contentType;
if (/^image/i.test(mimeType)) {
isImg = true;
}
if (/^audio/i.test(mimeType)) {
isAudio = true;
}
if (/\/css$/i.test(mimeType)) {
isCss = true;
}
if (/\/js$/i.test(mimeType)) {
isJs = true;
}
//end - test if image
//start - OPTIONAL use loadContext to get a bunch of good stuff
//must paste the function from here: https://gist.github.com/Noitidart/644494bdc26f996739ef somewhere in your code
var goodies = loadContextAndGoodies(aSubject, true);
/*
//goodies is an object that holds the following information:
var goodies = {
loadContext: loadContext,
DOMWindow: DOMWindow,
gBrowser: gBrowser,
contentWindow: contentWindow,
browser: browser,
tab: tab
};
*/
// test if resource (such as image, or whatever) is being loaded is going into a frame [can also be used as altnerative way to test if frame load or full page]
var itemDestinationIsFrame;
var itemDestinationIsTopWin;
if (goodies.contentWindow) {
if (goodies.contentWindow.frameElement) {
itemDestinationIsFrame = true;
itemDestinationIsTopWin = false;
} else {
itemDestinationIsFrame = false;
itemDestinationIsTopWin = true;
}
}
//end - OPTIONAL use loadContext to get a bunch of good stuff
}
Of course to start observing:
Services.obs.addObserver(myobserve, 'http-on-modify-request', false);
and to stop:
Services.obs.removeObserver(myobserve, 'http-on-modify-request', false);
To start observing
To start start obseving all requests do this (for example on startup of your addon)
for (var o in observers) {
observers[o].reg();
}
To stop observing
Its important to stop observring (make sure to run this at least on shutdown of addon, you dont want to leave the observer registered for memory reasons)
for (var o in observers) {
observers[o].unreg();
}

Use OS.File to test if path is locked?

With OS.File I am able to open a file with lock on it:
let options = {
winShare: 0 // Exclusive lock on Windows
};
if (OS.Constants.libc.O_EXLOCK) {
// Exclusive lock on *nix
options.unixFlags = OS.Constants.libc.O_EXLOCK;
}
let file = yield OS.File.open(..., options);
Is it possible to test if the path is locked though. I'm looking for alternative to nsiToolkitProfile.lockProfile
This is copy paste to scratchpad code. The top block uses nsitoolkitprofile to test if locked. And it works fine. The second part uses OS.File.open and it always throws error.
Cu.import('resource://gre/modules/osfile.jsm');
Cu.import('resource://gre/modules/FileUtils.jsm');
var tps = Cc['#mozilla.org/toolkit/profile-service;1'].createInstance(Ci.nsIToolkitProfileService); //toolkitProfileService
var folderOfProfile = 'k46wtieb.clean'; //folder names of relative profiles found here: %APPDATA%\Mozilla\Firefox\Profiles
var rootPathDefault = FileUtils.getFile('DefProfRt', []).path;
var localPathDefault = FileUtils.getFile('DefProfLRt', []).path;
var aDirect = new FileUtils.File(OS.Path.join(rootPathDefault, folderOfProfile));
var aTemp = new FileUtils.File(OS.Path.join(localPathDefault, folderOfProfile));
try {
var locker = tps.lockProfilePath(aDirect, aTemp)
Services.ww.activeWindow.alert('NOT open');
locker.unlock();
} catch (ex) {
if (ex.result == Cr.NS_ERROR_FILE_ACCESS_DENIED) {
Services.ww.activeWindow.alert('its in use');
} else {
throw ex;
}
}
var promise = OS.File.open(aDirect.path)
promise.then(
function(aVal) {
Services.ww.activeWindow.alert('promise success, aVal = ' + aVal);
aVal.close();
},
function(aReason) {
Services.ww.activeWindow.alert('promise rejected, aReason = ' + uneval(aReason));
}
)
The promise is always rejected with aReason.becauseAccessDenied every time :(
Just try to open it... If you cannot because of permissions, then the file is probably locked in another location.

Is my implementation of unloaders proper?

I was re-reading this post here: https://stackoverflow.com/a/24473888/1828637
And got concerned about if I did things correctly. This is how I do unloading:
So I set up some stuff per window. And unload them on shutdown. (i dont unload on window close, i havent found a need to yet, as when it closes, everything i added to it goes with with the close [such as my mutation observers]).
All code below is theoretical, the mutation stuff is example, so there might be typos or bugs in it. I was wondering if the idea behind it is appropriate:
var unloadersOnShutdown = [];
var unloadersOnClose = [];
function startup() {
let DOMWindows = Services.wm.getEnumerator(null);
while (DOMWindows.hasMoreElements()) {
let aDOMWindow = DOMWindows.getNext();
var worker = new winWorker(aDOMWindow);
unloadersOnShutdown.push({DOMWindow: aDOMWindow, fn: worker.destroy});
}
}
function shutdown() {
Array.forEach.call(unloadersOnShutdown, function(obj) {
//should probably test if obj.DOMWindow exists/is open, but just put it in try-ctach
try {
obj.fn();
} catch(ex) {
//window was probably closed
console.warn('on shutdown unlaoder:', ex);
}
});
}
function winWorker(aDOMWindow) {
this.DOMWindow = aDOMWindow;
this.init();
}
winWorker.prototype = {
init: function() {
this.gMutationObserver = new this.DOMWindow.MutationObserver(gMutationFunc.bind(this));
this.myElement = this.DOMWindow.querySelector('#myXulEl');
this.gMutationObserver.observe(this.myElement, gMutationConfig);
if (this.DOMWindow.gBrowser && this.DOMWindow.gBrowser.tabContainer) {
this.onTabSelectBinded = this.onTabSelect.bind(this);
this.gBrowser.tabContainer.addEventListener('TabSelect', this.onTabSelectBinded, false);
}
},
destroy: function() {
this.gMutationObserver.disconnect();
if (this.onTabSelectBinded) {
this.gBrowser.tabContainer.removeEventListener('TabSelect', this.onTabSelectBinded, false);
}
},
onTabSelect: function() {
console.log('tab selected = ', thisDOMWindow.gBrowser.selectedTab);
}
};
var windowListener = {
onOpenWindow: function (aXULWindow) {},
onCloseWindow: function (aXULWindow) {
var DOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
for (var i=0; i<unloadersOnClose.length; i++) {
if (unloadersOnClose.DOMWindow == DOMWindow) {
try {
unloadersOnClose.fn();
} catch(ex) {
console.warn('on close unloader:', ex);
}
unloadersOnClose.splice(i, 1);
i--;
}
}
},
onWindowTitleChange: function (aXULWindow, aNewTitle) {},
}
I think one problem is me not using weak references with DOMWindows but I'm not sure.
The idea around unloaders in general seems to be OK, but very limited (to windows only).
The implementation is lacking. E.g. there is a big, fat bug:
unloadersOnShutdown.push({DOMWindow: aDOMWindow, fn: worker.destroy});
// and
obj.fn();
// or
unloadersOnClose.fn();
This will call winWorker.prototype.destroy with the wrong this.
The i++/i-- loop also looks, um... "interesting"?!
Also, keep in mind that there can be subtle leaks, so you should mind and test for Zombie compartments.
Not only can a window leak parts of your add-on (e.g. bootstrap.js) but it is also possible to leak closed windows by keeping references in your add-on. And of course, it's not just windows you need to care about, but also e.g. observers, other types of (XPCOM) listeners etc.

youtube playlist video change

I am needing to have some info passed to scripts when onPlayerStateChange() function fires off.
What I am after is the current videoID of the currently playing video and the array position number from the playlist.
(-_-)ZZZzzz...
EDIT....
Ok. So I have progressed a bit.
In the player code, I have this fire off
if (event.data == -1) {
getPlaylistIndex();
}
I then have this script.
function getPlaylistIndex() {
var str = ""+ytplayer.getPlaylist();
var viedoString = str.split(',');
var videoID = viedoString[ytplayer.getPlaylistIndex()];
if(videoID == undefined){
} else {
alert(videoID);
loadComents(videoID);
loadVideoINFO(videoID);
}
}
You will notice an IF condition which is needed to not fire the code for normal videos... just on the PL's.
It is working apart from the fact that when I load the playlist in, I do not get a videoID from the script. If I select any video in the playlist and also go back to the first one, it works fine. Just not working when first loading the playlist.
Any ideas ?
P.S. the alert is for testing only.
RE-EDIT.... ;P
Ok. I have been playing with this for the whole day going in and out of all scripts.
I have it working now (so it seems).
First I added into my code to give me this.
function getPlaylistIndex() {
var str = ""+ytplayer.getPlaylist();
var viedoString = str.split(',');
var videoID = viedoString[ytplayer.getPlaylistIndex()];
if(videoID == undefined){
} else {
if(videoID == ''){
var str2 = ytplayer.getVideoUrl();
videoID = (str2.substring(31,42));
}
loadComents(videoID);
loadVideoINFO(videoID);
}
}
And so it works first time, I needed to change
event.data == -1 to event.data == 1 as YTplayer fires them in a particular order.
If anyone has anything to ad or correct, please do so.

How to wait for 3 seconds in ActionScript 2 or 3?

Is there any way to implement waiting for, say, 3 seconds in ActionScript, but to stay within same function? I have looked setInterval, setTimeOut and similar functions, but what I really need is this:
public function foo(param1, param2, param3) {
//do something here
//wait for 3 seconds
//3 seconds have passed, now do something more
}
In case you wonder why I need this - it is a legal requirement, and no, I can't change it.
Use the Timer to call a function after 3 seconds.
var timer:Timer = new Timer(3000);
timer.addEventListener(TimerEvent.TIMER, callback); // will call callback()
timer.start();
To do this properly, you should create the timer as an instance variable so you can remove the listener and the timer instance when the function is called, to avoid leaks.
class Test {
private var timer:Timer = new Timer(3000);
public function foo(param1:int, param2:int, param3:int):void {
// do something here
timer.addEventListener(TimerEvent.TIMER, fooPartTwo);
timer.start();
}
private function fooPartTwo(event:TimerEvent):void {
timer.removeEventListener(TimerEvent.TIMER, fooPartTwo);
timer = null;
// 3 seconds have passed, now do something more
}
}
You could also use another function inside your foo function and retain scope, so you don't need to pass variables around.
function foo(param1:int, param2:int, param3:int):void {
var x:int = 2; // you can use variables as you would normally
// do something here
var timer:Timer = new Timer(3000);
var afterWaiting:Function = function(event:TimerEvent):void {
timer.removeEventListener(TimerEvent.TIMER, afterWaiting);
timer = null;
// 3 seconds have passed, now do something more
// the scope is retained and you can still refer to the variables you
// used earlier
x += 2;
}
timer.addEventListener(TimerEvent.TIMER, afterWaiting);
timer.start();
}
For AS3 use Radu's answer.
For AS2 use the setInterval function like so:
var timer = setInterval(function, 3000, param1, param2);
function (param1, param2) {
// your function here
clearInterval(timer);
}
You can also use delayedCall, from TweenMax. IMHO, it's the sharpest way to do that if you are familiar to TweenMax family.
TweenMax.delayedCall(1, myFunction, ["param1", 2]);
function myFunction(param1:String, param2:Number):void
{
trace("called myFunction and passed params: " + param1 + ", " + param2);
}
In your case, using a anonymous function:
public function foo(param1, param2, param3) {
//do something here
trace("I gonna wait 3 seconds");
TweenMax.delayedCall(3, function()
{
trace("3 seconds have passed");
});
}
why you are doing some confused ways instead of doing the right way?
there is a method named:"setTimeout()";
setTimeout(myFunction,3000);
myFunction is the function you want to call after the period.and 3000 is the period you want to wait(as miliseconds).
you don't need to set then clear interval, or make a timer with one repeat count or do sth else with more trouble☺.
There is no Sleep in ActionScript. But there are other ways to achieve the same thing without having all your code in a single function and wait within that function a specific amount of time.
You can easily have your code in two functions and call the 2nd one after a specific timeout you set in your 1st function.
THIS IS NOT WITHIN ONE FUNCTION - ANSWERS: "How to wait for X seconds in AS2 & 3"
...without using setInterval or clearInterval.
The answers posted above are much faster and easier to use. I posted this here, just in case...
Sometimes you may not be able to use set/clearInterval or other methods based on development restrictions. Here is a way to make a delay happen without using those methods.
AS2 - If you copy/paste the code below to your timeline, make sure to add two movie clips to the stage, btnTest and btnGlowTest (include like instance names). Make "btnGlowTest" larger, a different color, & behind "btnTest" (to simulate a glow and a button, respectively).
Compile and check the output panel for the trace statements to see how the code is working. Click on btnTest - btnGlowTest will then become visible throughout the duration of the delay, (just for visual representation).
I have an onEnterFrame countdown timer in here as well, (demos stopping/switching timers).
If you want the delay/glow to be longer - increase the glowGameTime number. Change the names to fit your own needs and/or apply the logic differently.
var startTime:Number = 0;
var currentTime:Number = 0;
var mainTime:Number = 5;//"game" time on enter frame
var glowStartTime:Number = 0;
var glowCurrentTime:Number = 0;
var glowGameTime:Number = 1.8;//"delayed" time on press
btnGlowTest._visible = false;
this.onEnterFrame = TimerFunction;
startTime = getTimer();
function TimerFunction()
{
currentTime = getTimer();
var timeLeft:Number = mainTime - ((currentTime - startTime)/1000);
timeLeft = Math.floor(timeLeft);
trace("timeLeft = " + timeLeft);
if(timeLeft <= 0)
{
trace("time's up...3 bucks off");
//...do stuff here
btnGlowTest._visible = false;//just for show
btnTest._visible = false;//just for show
StopTime();
}
}
function glowTimerFunction()
{
glowCurrentTime = getTimer();
var glowTimeLeft:Number = glowGameTime - ((glowCurrentTime - glowStartTime)/1000);
glowTimeLeft = Math.floor(glowTimeLeft);
//trace("glowTimeleft = " + glowTimeLeft);
if(glowTimeLeft <= 0)
{
trace("TIME DELAY COMPLETE!");
//...do stuff here
btnGlowTest._visible = false;//just for show
btnTest._visible = false;//just for show
StopTime();
}
}
btnTest.onPress = function()
{
trace("onPress");
btnGlowTest._visible = true;
StopTime();
GlowTime();
}
function GlowTime()
{
trace("GlowTime Function");
this.onEnterFrame = glowTimerFunction;
glowStartTime = getTimer();
}
function StopTime()
{
trace(">>--StopTime--<<");
delete this.onEnterFrame;
}
AS3 - Below is the code from above setup to run in AS3. There are different ways to accomplish similar results, yet based on the project scope, these are the methods that were used in order to get things functioning properly.
If you copy/paste the code below to your timeline, make sure to add two movie clips to the stage, btnTest and btnGlowTest (include like instance names). Make "btnGlowTest" larger, a different color, & behind "btnTest" (to simulate a glow and a button, respectively).
Compile and check the output panel for the trace statements to see how the code is working. Click on btnTest - btnGlowTest will then become visible throughout the duration of the delay, (just for visual representation).
If you want the delay/glow to be longer - increase the GlowTimer:Timer number, (currently set to 950). Change the names to fit your own needs and/or apply the logic differently.
import flash.events.MouseEvent;
import flash.utils.Timer;
import flash.events.TimerEvent;
var startTime:Number = 0;
var currentTime:Number = 0;
var gameTime:Number = 4;//"game" time on enter frame
var GlowTimer:Timer = new Timer(950,0);//"delayed" time on press
btnGlowTest.visible = false;
GlowTimer.addEventListener(TimerEvent.TIMER, GlowTimeListener, false, 0, true);
btnTest.addEventListener(MouseEvent.MOUSE_DOWN, btnTestPressed, false, 0, true);
addEventListener(Event.ENTER_FRAME,TimerFunction, false, 0, true);
startTime = getTimer();
function TimerFunction(event:Event)
{
currentTime = getTimer();
var timeLeft:Number = gameTime - ((currentTime - startTime)/1000);
timeLeft = Math.floor(timeLeft);
trace("timeLeft = " + timeLeft);
if(timeLeft <= 0)
{
trace("time's up, 3 bucks off");
StopTime();
}
}
function GlowTimeListener (e:TimerEvent):void
{
trace("TIME DELAY COMPLETE!");
StopTime();
}
function btnTestPressed(e:MouseEvent)
{
trace("PRESSED");
removeEventListener(Event.ENTER_FRAME, TimerFunction);
btnGlowTest.visible = true;
GlowTimer.start();
}
function StopTime()
{
trace(">>--Stop Time--<<");
btnGlowTest.visible = false;//just for show
btnTest.visible = false;//just for show
GlowTimer.stop();
removeEventListener(TimerEvent.TIMER, GlowTimeListener);
removeEventListener(Event.ENTER_FRAME, TimerFunction);
}

Resources