Javascript-Caching Video Player - apache-flex

I've got the following Javascript for creating the HTML of video player. I use Javascript because this is the only way I can tell the player which video to play.
function createPlayer(videoSource){
document.writeln("<div id=\"player\">");
document.writeln("<object width=\"489\" height=\"414\" >");
document.writeln("<param name=\"player\" value=\"bin-debug/FlexPlayer.swf\">");
//etc
The problem is FlexPlayer.swf is loading every time and I need to cache this SWF file. Maybe I should use Javascript constructor but don't know how in this case. Any code help will be greatly appreciated.

If you're video player is in flex (and I'm guessing that it is with the flex tag and the bin-debug folder) - you should just call into the flex app in order to set the video.
You can allow flex and javascript to communicate with each other, without having to embed different versions of it in the HTML! It's awesome, check it out...
In your flex app, after it is initialized you can add something like this :
ExternalInterface.addCallback( 'playVideoFromJS' , playVideo );
What the above does is expose a function named "playVideoFromJS" that can be called in your javascript that will execute the 'playVideo' funciton in the flex app! Neat!
Then add a function like so somewhere in your flex app:
public function playVideo ( videoToPlay : String ) : void {
...play video code here
}
Then in javascript, you can actually call your flex function playVideo!
myFlexAppName.playVideoFromJS( 'myvideoofile.flv' );
More information on ExternalInterface here :
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/external/ExternalInterface.html?filter_flash=cs5&filter_flashplayer=10.2&filter_air=2.6#addCallback()

Related

How to disable sound on flashplayer in my custom application?

I use Qt QWebView component which uses flash-player for video playback. How to disable sound on flashplayer executed inside of my QWebView?
One approach that I consider is to execute some javascript code for disabling sound on player, but when to execute it? For example next code disable sound if run it on 1 second after call "load":
page.mainFrame().evaluateJavaScript("""
var mute_all_tags=function(tag){
var elems = document.getElementsByTagName(tag);
for(var i = 0; i < elems.length; i++){
elems[i].muted=true;
//alert(elems[i]);
}
}
mute_all_tags("video");
mute_all_tags("audio");
""")
Earlier calls don't stop sound. Calls on QWebView.loadFinished stops sound but for that moment some sound already issued , how can i stop sound immediately?
It sounds like you are loading external pages (i.e. 3rd-party sites) with HTML5 video or Flash video into your QWebView. Also, keeping the videos muted right from the start with absolutely no audio seems like the critical feature you are seeking.
Solution 1
Your page.mainFrame().evaluateJavaScript("...") seems to be the easiest solution, but there will be a lag before this script is executed.
Solution 2
An alternative is to scrape the target website, then using regex or something similar change all the <video> tags to add the mute property e.g. <video controls muted>. Do something analogous for any <embed> tags too. Then, load this modified HTML into the web view with the setHtml() method, also setting the base url, and possibly the referer header. Then the HTML will render with your videos muted from the start.
Solution 3
Another idea might be to intercept media URLs with Qt itself (e.g. .mp4, .mov), and initially hold them in a paused queue, call your page.mainFrame().evaluateJavaScript("...") to programmatically mute the <video> and <audio> tags, then allow the queue to proceed when the evaluateJavaScript() call returns. The media, if auto-playing, should start muted.
Please fix your code to following :
page.mainFrame().evaluateJavaScript("var mute_all_tags=function(tag){var elems = document.getElementsByTagName(tag);for(var i = 0; i < elems.length; i++){elems[i].muted=true;}}mute_all_tags('video');mute_all_tags('audio');")
The String in your code is not valid :
You are adding double quotes to string without Concatenation .
You are using double quotes inside double quotes which is a mess.

How to add flex controls to my AS3 project?

I'm absolute newbie in Flash development but anyway I need to do something.
I have a pure AS3 project that plays video from youtube (chromeless player). I need to add some controls to manage this player. I don't know how to do that? If I just add mxml file into the project nothing happens. How to bind this file to as3?
Thanks
Flex components need to have UIComponent parent to function properly. If your player is based on Sprite, controls will not be initialized.
There is a trick to use Flex controls in the Sprite, but only after initialization in Flex Application. If you don't have Application, no luck.
You could use an AS3-only alternative. One library I've used is minimalcomps which offers some simple but effective controls for use in any AS3 project.
You can't use MXML, but nobody stops you to create your own controls if they are simple.
A short and simple example of how to add a button with an image:
loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
loader.load(new URLRequest('http://i1.nyt.com/images/misc/nytlogo379x64.gif'));
function onComplete(event:Event):void
{
var button:Sprite = new Sprite();
button.addChild(event.currentTarget.content);
addChild(button);
button.buttonMode = true;
button.addEventListener(MouseEvent.CLICK, onButtonClick);
}
function onButtonClick(event:MouseEvent):void
{
trace ('click');
}
This would be the most basic version of a button with a loaded bitmap image.
Normally you would like to check for errors as well... what to do if the image is not found, or when you're not allowed to access it.
If you're going to need more then one button you could make a class which accepts an url, so you could just pass the url to the class and the button would be created.
A completely other way to approach this is with an SWC file, you could create the buttons in the Flash IDE and export them as an swc, which you can embed and use in your pure AS3 project.

ActionScript 3 - a loader that supports many apps?

I have created a simple SWF-loader in ActionScript 3.0. It loads an SWF from a server and then plays it. While downloading, it displays the "loading" screen.
Its main defect is that it can load only one Flash application - the one which it is compiled for. Let's say it's named test1.swf.
Is there any way to make the loader support more than one Flash app (for example test2.swf and test3.swf)? I mean by passing external parameters to it and not by creating another loader. Is using Javascript the only way to do it? I don't want my loader to require the Javascript support.
And I really don't want to create separate loaders for all of my apps...
Thanks in advance.
In order to load an external SWF your loader only need the url of the swf to be loaded, this url doesn't have to be hardcoded. There are many ways to pass parameters to a SWF file and they don't necessarily require Javascript.
You could load a XML file for instance, a simple text file would work too , you could also use a PHP script. Using flahsvars would require Javascript, although only to set your application in your HTML page.
With the following example , your app doesn't need to recompile , you simply change the url in the text file.
Example with a text file containing a url, something like this:
http://yourwebsite.com/test1.swf
var urlLoader:URLLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE , completeHandler );
urlLoader.load( new URLRequest('swfURL.txt') );
function completeHandler(event:Event):void
{
loadExternalSWF(event.target.data );
event.target.removeEventListener(Event.COMPLETE , completeHandler );
}
function loadExternalSWF(url:String ):void
{
//your code here , using the url value
trace(url );//should return your text file content
}

externalinterface - calling javascript from SWF

HI,
im trying to call a javascript function from my actionscript code but its not working;
as3:
if (ExternalInterface.available)
{
try
{
ExternalInterface.addCallback("changeDocumentTitle",null);
}
catch(error:Error)
js (inside velocity file using swfobject)
function changeDocumentTitle()
{
alert('call from SWF');
}
anyone know what could be happenin?
If you are trying to invoke a JS function from within your Flex app, you want to use ExternalInterface.call(...) and not ExternalInterface.addCallback(...). From the docs:
public static function call(functionName:String, ... arguments):*
Calls a function exposed by the Flash Player container, passing zero or more arguments. If the function is not available, the call returns null; otherwise it returns the value provided by the function. Recursion is not permitted on Opera or Netscape browsers; on these browsers a recursive call produces a null response. (Recursion is supported on Internet Explorer and Firefox browsers.)
If the container is an HTML page, this method invokes a JavaScript function in a script element.
http://livedocs.adobe.com/flex/3/langref/flash/external/ExternalInterface.html
addCallback() is used if you want to expose an ActionScript function from your Flash app to the HTML container so that it can be invoked via JavaScript.
On the local system, communication between the SWF and Javascript tends to be hampered by security issues. You can reconfigure your flash to allow some of these communications via the "settings manager".
It may also be an issue with "allowscriptacces" not being set where you embed the flash object.
Another problem may be that flash tries to call javascript before the javascript is loaded. The init order thing can be quite annoying.

How do I unload a externally loaded SWF file from a SWFLoader component in Adobe Flex?

I have an application that loads external SWF files and plays them inside a Adobe Flex / Air application via the SWFLoader Flex component. I have been trying to find a way to unload them from a button click event. I have Google'd far and wide and no one seems to have been able to do it without a hack. The combination of code I see people use is:
swfLoader.source = ""; // Removes the external link to the SWF.
swfLoader.load(null); // Forces the loader to try to load nothing.
// Note: At this point sound from the SWF is still playing, and
// seems to still be playing in memory.
flash.media.SoundMixer.stopAll();
// Stops the sound. This works on my development machine, but not
// on the client's.
If the SWFs are closed (hidden) this way, eventually the program crashes.
Any ideas? I have found tons of posts in various forums with people having the same problem. I assume I will get one wrong/incomplete answer here, and than my post will sink into nothingness as usual, but either way, thanks in advance!
Edit 1: I can't edit the actual SWF movies, they're created by the client. If I can't close any SWF opened through Flex, isn't that a problem with the Flex architecture? Is my only option sending the SWFs to the web browser?
... isn't that a problem with the Flex architecture?
Yes it is, and it also affects Flash in general. Until you can take advantage of the Loader.unloadAndStop() method in FP10 (AIR 1.5), you can't guarantee that externally loaded content will not continue to consume memory and cpu resources, even if you use the Loader.unload() method. (To be honest, I'm not 100% sure that even that will guarantee freeing of resources, but maybe I'm a pessimist.)
The next best thing is for you to insist that the creators of the content you load adhere to a set of guidelines, including exposing something like a dispose() method which your app can call to ask it to release as many resources as possible before you unload() it. If this isn't possible, then your application will almost definitely bloat in memory and cpu usage each time you load an external swf. Sorry.
If it makes you feel any better, you're not alone. ;)
It is a problem that a badly created SWF can sink your application, and many of the issues with this will be fixed in Flash Player 10, as others have mentioned. However, regardless of platform you will always risk having problems if you load third party code, there's always the possibility that it contains bugs, memory leaks or downright malicious code. Unless you can load content into a sandbox (and you can't in Flash, at least not yet), loading bad things will sink your app, it's as simple as that.
I'm sorry to say that unless you can guarantee the quality of the loaded content you can't guarantee the quality of your own application. Flash developers are notorious for writing things that leak, or can't be unloaded, because Flash makes it easy to do the wrong thing, especially for things that live on the time line. Loading any Flash content that you don't have control over directly is very perilous.
The best solution is
swfLoader.autoLoad = false;
swfLoader.unloadAndStop();
swfLoader.autoLoad = true;
In this way you stop the player, unload the content from memory and avoid the sound to remain playing..
Cheers
The problem resides in the loaded swf, it simply does not clean up the audio after itself.
Try attaching an unload event onto movieclips like this:
MovieClip(event.target.content).loaderInfo.addEventListener(Event.UNLOAD, unloadMovieClipHandler);
private function unloadMovieClipHandler(event:Event) : void
{
SoundMixer.stopAll();
}
I'd generally stay away from SWFLoader and use the classes in the mx.modules package.
Flex has a module system that enables this type of behavior. You can check it out here : http://livedocs.adobe.com/flex/3/html/help.html?content=modular_3.html . In general, dynamically loading and unloading swf components is tricky, especially if those modules modify any global state in the application (styles, etc..). But if you create an interface for your modules, and then each class you load/unload implement that interface as well as extend the flex module class, you can load and unload them cleanly.
Try the following:
try {
new LocalConnection().connect('foo');
new LocalConnection().connect('foo');
} catch (e:*) {}
That will force a Garbage Collection routine. If your SWF is still attached, then you've missed some sort of connection, like the audio.
There are a couple ways to force GC, which all kind of suck because they spike CPU, but the good news is that an official way is coming in Flash Player 10:
unloadAndStop
link: http://www.gskinner.com/blog/archives/2008/07/unloadandstop_i.html
Until then, I'm afraid you'll have to force it with hacks like I showed above.
You have not shown all of your code so I am going to assume you didn't use the unload method of the Loader class. Also swfLoader.load(null) seems wrong to me as the load method is expecting a URLRequest object. When you want to clean things up at the end, set the object's value to null instead of calling a null load. The fact that your still hearing audio indicates that your data wasn't unloaded, or the audio file does not reside inside the content that was unloaded. Lets walk through this.
Example below
var loader:Loader = new Loader();
var request:URLRequest = new URLRequest('test.swf');
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onSwfLoad, false, 0, true);
function onSwfLoad(e:Event):void
{
addChild(loader);
loader.contentLoaderInfo.addEventListener(Event.UNLOAD, onLoaderUnload, false, 0, true);
loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onSwfLoad, false);
}
function onLoaderUnload(e:Event):void
{
trace('LOADER WAS SUCCESSFULLY UNLOADED.');
}
//Now to remove this with the click of a button, assuming the buttons name is button_mc
button_mc.addEventListener(MouseEvent.MOUSE_DOWN, onButtonDown, false, 0, true);
function onButtonDown(e:MouseEvent):void
{
loader.unload();
loader.contentLoaderInfo.removeEventListener(Event.UNLOAD, onLoaderUnload);
//When you want to remove things completely from memory you simply set their value to null.
loader = null;
button_mc.removeEventListener(MouseEvent.MOUSE_DOWN, onButtonDown);
}
I do hope that this was helpful, and I am sorry if it was redundant, but without seeing your code I have no way of knowing exactly how you approached this.

Resources