How to completely disable sound in externally loaded SWF? - actionscript-3

In my application I need to play externally loaded third-party SWFs (ads) without sound. What I've done so far:
using SoundTransform set volume to 0;
do this every frame so if the ad tries to reset the volume, I will set it back to 0.
Most of the time it works. However, occasionally there are ads that still play sound.
I suspect those ads do the same trick and here we have a race condition - who is the last to change the volume.
Is there any way to totally disable sound for the loaded SWF? Is there any way to prevent such race condition?
Here is my code:
function onAdStart():void
{
setMasterSound(0);
addEventListener(Event.ENTER_FRAME, tick);
}
function tick( e:Event ):void {
setMasterSound(0);
}
function SetMasterSound(volume:Number):void
{
var masterSound:SoundTransform;
if(SoundMixer.soundTransform.volume != volume)
{
masterSound = new SoundTransform();
masterSound.volume = volume;
SoundMixer.soundTransform = masterSound;
}
}

Related

Controlling Sound on flash video with Play/pause/stop buttons

I have a flash video that is short, has sound, and I've got Play Pause and Stop buttons.
Without sound, it works perfectly. It autoplays, you can hit pause and it pauses, and play resumes where it leaves off. Hitting stop goes to an empty frame if someone wants to turn it off.
I have audio inside my library, and would like connect the audio with the same elements. I've been researching for awhile now, and I've not come up with a solution yet, and having a hard time.
Here is my ActionScript code for my currently working buttons:
StopBtn.addEventListener(MouseEvent.CLICK, stopplaying);
function stopplaying(Event:MouseEvent):void {
stop()
}
PlayBtn.addEventListener(MouseEvent.CLICK, startplaying);
function startplaying(Event:MouseEvent):void {
play()
}
CloseBtn.addEventListener(MouseEvent.CLICK, close);
function close(Event:MouseEvent):void {
gotoAndStop(240)
}
You should use Sound and SoundChannel to do this. And for pause you'll have to save the current play position so that you can continue from there:
var audio:Sound = new audioFromLibrary(); //linkage name
var soundChannel:SoundChannel = new SoundChannel();
var audioPosition:Number = 0;
//PLAY:
soundChannel = audio.play(audioPosition);
//PAUSE:
audioPosition = soundChannel.position;
soundChannel.stop();
//STOP:
soundChannel.stop();

AS3 Preloader doesn't work locally, loaderInfo ProgressEvent.PROGRESS event does not fire

Making a custom AS3 preloader, I noticed that when my SWF is executed locally (file:///) the preloader gets stuck in the loading screen when previewed in a web browser like Chrome.
When executed from a remote server or through the standalone Flash Player, then it works. I noticed other SWF that have preloaders do not have this issue. What I need to change?
this.loaderInfo.addEventListener(ProgressEvent.PROGRESS, preloaderProgress);
function preloaderProgress(event:ProgressEvent):void {
var loadedPercent:Number = event.bytesLoaded/event.bytesTotal*100;
if (loadedPercent == 100){
this.gotoAndStop(2);
}
}
Loading locally goes very fast. Not only you should check if the file is completely loaded using the Event.COMPLETE and not the ProgessEvent but you should also make sure to register your listeners before actually calling load or the file might end up completely loaded before you register your listeners.
Following the example at http://stephenscholtz.com/201110/single-movie-flash-preloading-as3
It seems that there was no ProgressEvent.COMPLETE, but there is a Event.COMPLETE instead, a bit confusing.
I changed my code to the following, (also including some tweaks for right click menu to prohibit the user from right clicking and pressing Play before movie has loaded and such)
//Initialize any variables
var loadedPercent:Number = 0;
//Remove all items from right click Flash Player menu (except Quality, and the mandatory About... & Settings...)
var cxMenu:ContextMenu = new ContextMenu();
cxMenu.hideBuiltInItems();
cxMenu.builtInItems.quality = true;
this.contextMenu = cxMenu;
/* or disable right click menu completely (Flash Player 11.2.202.228 and over) */
/* this.addEventListener(MouseEvent.RIGHT_CLICK, onMouseRightClick);
function onMouseRightClick(event:MouseEvent)
{
return false;
} */
//Disable shortcut keys and window menubar when played from desktop Standalone Flash Player app
if (Capabilities.playerType == "StandAlone" || Capabilities.playerType == "External") {
fscommand("showmenu", "false");
fscommand("trapallkeys", "true");
}
/* Preloader: begin */
//Update loading bar and percent text as SWF loads
function onProgress(e:Event) {
//Get the amount of bytes that have been loaded / bytes total to load
loadedPercent = this.loaderInfo.bytesLoaded/this.loaderInfo.bytesTotal*100;
//Update the text of _preloaderProgress movieclip
_preloaderProgress.text = int(loadedPercent)+"%";
//Update the _preloaderBar amount by scaling horizontally as it loads
_preloaderBar.scaleX = loadedPercent/100;
}
//Go to next frame after everything loads
function init(e:Event) {
gotoAndStop(2);
}
//Attach the events to the stage
this.loaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgress);
this.loaderInfo.addEventListener(Event.COMPLETE, init);
/* Preloader: end */
//Stop to 1st frame and wait until it is loaded
stop();
This will allow the movie to play both remotely and locally with no problems.

Is there any way to remove and addListener based on a timer?

How would i go about disabling the controls for a character for 5 seconds after they've hit an object and then immediatly afterwards allowing the character to move freely? So far, i've been able to get the code for the hitTest done and the removing keyboard controls (the easy part) but now i'm stumped as to how i would set the keyboard controls on a timer. Any help? My code for the hitTest and removing of controls is as follows.
if (player.hitTestObject(folder))
{
trace("success!");
addChild(myInfo);
//stops player movement
stage.removeEventListener(KeyboardEvent.KEY_DOWN,kD);
}
else
{
addChild(myInfo);
removeChild(myInfo);
}
The other problems in the code are of no concern right now (such as the add/remove child in the else function.
private var m_tmr:Timer = new Timer(5000, 1);
private function someFunc():void
{
if (player.hitTestObject(folder))
{
trace("success!");
addChild(myInfo);
//stops player movement
stage.removeEventListener(KeyboardEvent.KEY_DOWN,kD);
m_tmr.addEventListener(TimerEvent.TIMER, onTimer);
m_tmr.start();
}
else
{
addChild(myInfo);
removeChild(myInfo);
}
}
private function onTimer(pEvent:TimerEvent):void
{
m_tmr.removeEventListener(TimerEvent.TIMER, onTimer);
stage.addEventListener(KeyboardEvent.KEY_DOWN, kD);
}
Adding/removing the timer's event listener each time is for purposes of efficiency; it's not critical that you keep adding/removing it like that.

external swf should unload when reaches final frame

I have a swf file loaded into a main movie. When the child is finished playing, ie reaches its final frame, I would like the swf to unload. Can anyone tell me what bits I can add to this code?
//start button
start_button_aboriginal.addEventListener(MouseEvent.CLICK, fl_ClickToLoadUnloadSWF_3,false,0,true);
import fl.display.ProLoader;
var fl_ProLoader_3:ProLoader;
var fl_ToLoad_3:Boolean = true;
function fl_ClickToLoadUnloadSWF_3(event:MouseEvent):void
{
//ADDED APR02 START
fl_ProLoader_3.contentLoaderInfo.addEventListener(Event.INIT, childInitHandler);
fl_ProLoader_3.load(new URLRequest("myths/myth_aboriginal.swf"));
//ADDED APR02 END
if(fl_ToLoad_3)
{
fl_ProLoader_3 = new ProLoader();
fl_ProLoader_3.load(new URLRequest("myths/myth_aboriginal.swf"));
addChild(fl_ProLoader_3);
fl_ProLoader_3.x = 114;
fl_ProLoader_3.y = 41;
}
else
{
removeChild(fl_ProLoader_3);
fl_ProLoader_3.unloadAndStop();
fl_ProLoader_3 = null;
}
// Toggle whether you want to load or unload the SWF
fl_ToLoad_3 = !fl_ToLoad_3;
}
You could
1) Use the undocumented addFrameScript function defined in the MovieClip class to place a callback on the last frame of the child SWF. Useful if you don't have control over the code in your loaded SWF.
addFrameScript() has the following signature:
addFrameScript(frameNumber, callback); //frameNumber is zero-based (unlike in the Flash authoring suite, here you would enter 0 to refer to the first frame, and 1 for the second.)
In the parent SWF, add the following:
function fl_ClickToLoadUnloadSWF_3(event:MouseEvent):void {
...
fl_ProLoader_3.contentLoaderInfo.addEventListener(Event.INIT, childInitHandler);
fl_ProLoader_3.load(new URLRequest("myths/myth_aboriginal.swf"));
...
}
function childInitHandler(event:Event):void {
MovieClip(fl_ProLoader_3.content).addFrameScript(MovieClip(fl_ProLoader_3.content).totalFrames-1, unloadChild);
}
function unloadChild() {
fl_ProLoader_3.unloadAndStop();
}
If you're worried about addFrameScript going away - don't be. When you put code on the timeline, all that code is actually compiled into functions in the document class, with frame listeners added via addFrameScript.
Remember to define function unloadChild().
function unloadChild():void {
fl_ProLoader_3.unloadAndStop();
}
-OR-
2) Dispatch an event from your loaded SWF when it reaches the final frame.
In last frame of child SWF:
this.dispatchEvent(new Event("lastFrameReached"));
In parent SWF, add the following:
fl_ProLoader_3.content.addEventListener("lastFrameReached", unloadChild);
-OR-
3) Subscribe to the ENTER_FRAME event of the child and check if the child is on its last frame.
In parent SWF, add the following:
fl_ProLoader_3.content.addEventListener(Event.ENTER_FRAME, checkIfEnded);
function checkIfEnded(event:Event):void {
if (fl_ProLoader_3.content.currentFrame == fl_ProLoader_3.content.totalFrames) {
unloadChild();
}
}
I personally prefer addFrameScript - seems to me a cleaner solution. Callback runs once, you don't have to poll and you don't need to modify the child SWF.
There are a number of ways to solve this, and it has been asked many times...
Unload child swf on last frame of child swf
When External SWF has reached Frame X, how do I unload it?
That said, one way you could resolve this without creating event listeners on the child swf, is by periodically checking the child swf for the current frame. If it's the last one on the swf, call the unload method.
// once every second, indefinitely.
var tick:Timer = new Timer(1000, 0);
tick.addEventListener(TimerEvent.TIMER, checkSWF);
tick.start();
//Load something to the stage.
var loader:Loader = new Loader();
loader.load(new URLRequest("child.swf"));
addChild(loader);
function checkSWF(e:Event):void {
if (loader.content.currentFrame == loader.content.totalFrames) {
tick.stop(); // stop the timer
loader.unloadAndStop();
}
}

Play sound at certain playProgress or videoTime with greensock?

I'm using greensock LoaderMax to load video files and sound files. I've copied as much code as is available to me. A video (s9) is playing and at a certain percentage through the video, I need to play another sound.
if(s9.playProgress > .1) // This is what I can't get to work
{
s12_sound.playSound(); //This sound won't play at .1 playProgress
}
s9.content.visible = true;
s9.playVideo();
stop();
s9.addEventListener(VideoLoader.VIDEO_COMPLETE, play_s9_loop); //This plays a video once s9 is done.
function play_s9_loop(event:Event):void
{
s9.content.visible = false;
s9_loop.content.visible = true;
s9_loop.playVideo();
}
I'm guessing you just can't do an if() on playProgress? Furthermore, I suck at AS3.
You should be able to just listen for the INIT event on the video (which typically means it has loaded enough to determine the duration of the video) and then add an AS cue point.
//...after you create your VideoLoader...
myVideoLoader.addEventListener(LoaderEvent.INIT, initHandler);
myVideoLoader.load();
function initHandler(event:LoaderEvent):void {
myVideoLoader.addASCuePoint( myVideoLoader.duration * 0.1, "myLabel" );
myVideoLoader.addEventListener(VideoLoader.VIDEO_CUE_POINT, cuePointHandler);
}
function cuePointHandler(event:LoaderEvent):void {
trace("Hit the cue point " + event.data.name);
s12_sound.playSound();
}
Also make sure that you preload that s12_sound so that it's ready to play when you need it. Otherwise, you can call playSound() all you want and it ain't gonna happen :)
I haven't used this class before but after reading the docs it looks like you can do something like this:
http://www.greensock.com/as/docs/tween/com/greensock/loading/VideoLoader.html
var mid:Number = s9_loop.duration/2; //get the midpoint using the duration property
s9_loop.addASCuePoint(mid, "middle") //using addASCubePoint to add a cuepoint to the midpoint of the video
s9_loop.addEventListener(VideoLoader.VIDEO_CUE_POINT, handleMidpoint); //listen for the cuepoint
Inside the handler function
protected function handleMidpoint(e:Event):void{
//play your sound
}