I'm having problems with Full Screen in Flex.
Here's the Code:
private function toggleFullScreen(event:Event):void {
try {
switch (Application.application.stage.displayState) {
case StageDisplayState.FULL_SCREEN:
// If already in full screen mode, switch to normal mode.
Application.application.stage.displayState = StageDisplayState.NORMAL;
break;
default:
//If not in full screen mode, switch to full screen mode.
Application.application.stage.displayState = StageDisplayState.FULL_SCREEN;
break;
}
} catch (err:SecurityError) {
// ignore
}
}
I've already verified that this method is correctly being called, and that the SWITCH/CASE is working.
Still, after setting the displayState, nothing happens, and the attribute displayState remais with "normal" String.
I tested with previous versions of Firefox and Internet Explorer, but it didn't work either.
Does anybody know why is this happening? I'm new in flex and this code was developed by previous developers, that aren't working here anymore.
I've been searching a fix for weeks, but I didn't find anything that could help.
Thanks for the help.
Most likely you need to include the "allowFullscreen" in both of your param tag and embed attribute within the HTML template:
<object>
...
<param name="allowFullScreen" value="true" />
<embed ... allowfullscreen="true" />
</object>
And just a reference to the stage should be enough:
stage.displayState = StageDisplayState.FULL_SCREEN;
Related
I have a bit of a problem, in that I have a tree:
<mx:Tree iconField="#icon" />
That's been fine for a while, but now I want parts of the tree to have their default icons. Now, for reasons I haven't figured out yet, the icon member of the source XML is ignored for branch nodes, and the default is used But for leaf nodes, I must have a valid icon member, or I get an exception. icon="" doesn't work.
Taking a look under the hood, I ran:
trace('The default tree icon: ' + tree.itemToIcon(tree.selectedItem).toString());
which revealed the default to be:
class _TreeStyle__embed_css_Assets_swf_TreeNodeIcon_770392128
which is way too magic string. No thanks. I didn't even try assign that to icon.
Rather than do a screen cap, Gimp edit, and then make it into a custom icon, how do I simply reference the default icon that the platform provides?
Flex 3.5 SDK here.
I think you do over think & with that over complicate everything!
I have not worked with this a long time, but maybe this still could help you a little.From memory I had more complex once as well but have not looked at any of it quiet awhile! One Link of many I used with Tree setup
gallery icon="iconSymbol0AG"
gallery label=" AR - ARGENTINA" src="com/assets/images/countriesFlagsRoundLarge/ar.png"
gallery label=" Mauricio Photography" src="com/assets/images/PageOne/PhotographyBlogs/BlankArtists/AR/TheMauricioBlog.swf"
file label=" Web Site" icon="iconSymbolAR" src="com/assets/images/PageOne/PhotographyBlogs/WebSites/AR/TheCollazosBlog.swf"
gallery
Following Amy's suggestion, I tried:
public var m_icoDefaultLeaf:Class;
private static var m_oDummyTree:Tree;
private static var m_xmlDummy:XML;
...
m_oDummyTree = new Tree;
m_xmlDummy = <dummynode />;
m_oDummyTree.dataProvider = m_xmlDummy;
m_oDummyTree.addEventListener(FlexEvent.CREATION_COMPLETE,
function (evt:FlexEvent):void {
m_icoDefaultLeaf = m_oDummyTree.itemToIcon(m_xmlDummy);
removeChild(m_oDummyTree);
m_oDummyTree = null;
m_xmlDummy = null;
}
);
addChild(m_oDummyTree);
Then I just used icon="m_icoDefaultLeaf" in the XML for the leaves and amazingly, it worked!
Yes, it does have to be that complicated. I had to handle that event, and I had to add the tree as a child of something.
And another thing I tried, was to erase all that code and just use
public var m_icoDefaultLeaf:Class = null;
But that just made a blank icon, not a default.
I am working on an application which has quite a bit of field-validation in it. The validation works great and I am 1000000% sure the validation message popups were appearing earlier. Now I did quite a bit of work and refactoring. One of the things I changed was the way I open up Popups/Dialog. In order to have these centered over the entire application instead of the opening component I refactored the way I open dialogs. I used the source of the Alert as a base for this but extended it quite a bit as I was having other issues (Focus Manager etc.) (I am just mentioning this as I am assuming that my missing popups are related to this).
Here comes the code responsible for opening popups in my application:
public function show(realParent:Sprite,
displayParent:Sprite = null,
closeHandler:Function = null,
moduleFactory:IFlexModuleFactory = null):Dialog {
// Get the parent ...
// If none is set, use the top-level-application.
if (!displayParent) {
var sm:ISystemManager = ISystemManager(FlexGlobals.topLevelApplication.systemManager);
// no types so no dependencies
var mp:Object = sm.getImplementation("mx.managers.IMarshallPlanSystemManager");
if (mp && mp.useSWFBridge())
displayParent = Sprite(sm.getSandboxRoot());
else
displayParent = Sprite(FlexGlobals.topLevelApplication);
}
// Register for close-events, making sure the pop-up is closed.
if (closeHandler != null) {
this.addEventListener(CloseEvent.CLOSE, closeHandler);
}
// Setting a module factory allows the correct embedded font to be found.
if (moduleFactory) {
this.moduleFactory = moduleFactory;
} else if (realParent is IFlexModule) {
this.moduleFactory = IFlexModule(realParent).moduleFactory;
} else {
if (realParent is IFlexModuleFactory) {
this.moduleFactory = IFlexModuleFactory(realParent);
} else {
this.moduleFactory = FlexGlobals.topLevelApplication.moduleFactory;
}
// also set document if parent isn't a UIComponent
if (!parent is UIComponent) {
this.document = FlexGlobals.topLevelApplication.document;
}
}
// Make the dialog center itself relative to the parent.
PopUpManager.addPopUp(this, displayParent, true);
PopUpManager.centerPopUp(this);
return this;
}
What could be responsible for the Validation popups not showing up any more? Where should I look?
Chris
Ok ... so I figgured this out by myself again. I coould bang my head at the wall for taking so long for finding it though.
If I use the Spart forms, the FormItems and Forms themselves can define error text areas in order to output error messages. So as soon as the FormItem posesses a skin part with the id "errorTextDisplay" the error messages go there. I was now expecting that if there was no such part, the old notifications would be used ... nope.
After about 2-3 Hours of messing around with the code of FormItem and it's skins, I noticed that the "contentGroup" explicitly defined an attribute to suppress error tooltyips by setting showErrorTip to false. Simply removing the "errorTextDisplay" from the skin and changing the showErrorTip to true made my popups appear nicely :-)
Hopefully this post might help someone with the same problems.
EDIT
If someone can at least tell me how to receive an event when the streams disconnects that would be great.
The documentation for this control is simply horrible. I have an application that will have a live video stream and I'm looking for a way to make the VideoDisplay control restore its connection in case of the occurrence of any of these specific scenarios:
The application starts and the stream is not online yet.
The application is streaming and the user is disconnected from the internet.
The application is streaming and the video server crashes and reboots.
I'm using Wowza Media Server and Wirecast to test this. 1 and 3 don't work, I'm not sure number 2 does. I made number 1 work by adding this very questionable piece of code:
protected function onMediaPlayerStateChange(event:MediaPlayerStateChangeEvent):void
{
if (event.state == MediaPlayerState.PLAYBACK_ERROR)
{
var videoSource:DynamicStreamingVideoSource = this.videoDisplay.source as DynamicStreamingVideoSource;
try
{
this.videoDisplay.source = null;
this.videoDisplay.source = videoSource;
}
catch (any:*) {}
}
}
As you can see I need a try/catch block since both calls to source cause exceptions, yet whatever happens before those exceptions seems to fix problem #1. This doesn't fix problem #3 because a media state change event apparently doesn't occur when you stop the video server.
This is my control declaration:
<s:VideoDisplay id="videoDisplay" click="onVideoStreamClick(event)" mediaPlayerStateChange="onMediaPlayerStateChange(event)" muted="{this.videoMuted}" top="10" width="280" height="220" autoPlay="true" horizontalCenter="0">
<s:source>
<s:DynamicStreamingVideoSource id="videoSource" streamType="live" host="{FlexGlobals.topLevelApplication.parameters.videoStreamURL}">
<s:DynamicStreamingVideoItem id="videoItemLow" streamName="{FlexGlobals.topLevelApplication.parameters.videoLow}" bitrate="{FlexGlobals.topLevelApplication.parameters.videoLowBitrate}" />
<s:DynamicStreamingVideoItem id="videoItemMedium" streamName="{FlexGlobals.topLevelApplication.parameters.videoMedium}" bitrate="{FlexGlobals.topLevelApplication.parameters.videoMediumBitrate}" />
<s:DynamicStreamingVideoItem id="videoItemHigh" streamName="{FlexGlobals.topLevelApplication.parameters.videoHigh}" bitrate="{FlexGlobals.topLevelApplication.parameters.videoHighBitrate}" />
</s:DynamicStreamingVideoSource>
</s:source>
</s:VideoDisplay>
Does anyone know how to make the VideoDisplay recover from these issues? Any help is appreciated, thanks.
If anyone has this problem, this is how I solved it. You need to set the video source to a blank image in order to stop the streaming, otherwise it will never, ever stop. This solution works for all scenarios described above:
private function resetVideo():void
{
//save current source object
this.videoEventsDisabled = true;
var videoSource:DynamicStreamingVideoSource = this.videoDisplay.source as DynamicStreamingVideoSource;
try //switch to blank image, only this will stop the video stream
{
this.videoDisplay.source = "assets/images/video_offline.png";
}
catch (any:*) {}
//wait a few seconds and reset video source
setTimeout(resetVideoSource, 2000, videoSource);
}
private function resetVideoSource(videoSource:DynamicStreamingVideoSource):void
{
this.videoEventsDisabled = false;
this.videoDisplay.source = videoSource;
}
protected function onMediaPlayerStateChange(event:MediaPlayerStateChangeEvent):void
{
if (this.videoEventsDisabled)
{
return;
}
//something went wrong
if (event.state == MediaPlayerState.PLAYBACK_ERROR)
{
resetVideo();
}
}
protected function onCurrentTimeChange(event:TimeEvent):void
{
if (this.videoEventsDisabled)
{
return;
}
//if there was a number before, and its suddendly NaN, video is offline
if (isNaN(event.time) && !isNaN(this.previousVideoTime))
{
resetVideo();
}
else //store event time for future comparisons
{
this.previousVideoTime = event.time;
}
}
MXML:
<s:VideoDisplay id="videoDisplay" click="onVideoStreamClick(event)" mediaPlayerStateChange="onMediaPlayerStateChange(event)" currentTimeChange="onCurrentTimeChange(event)" muted="{this.videoMuted}" top="10" width="280" height="220" autoPlay="true" horizontalCenter="0">
<s:source>
<s:DynamicStreamingVideoSource id="videoSource" streamType="live" host="{FlexGlobals.topLevelApplication.parameters.videoStreamURL}">
<s:DynamicStreamingVideoItem id="videoItemLow" streamName="{FlexGlobals.topLevelApplication.parameters.videoLow}" bitrate="{FlexGlobals.topLevelApplication.parameters.videoLowBitrate}" />
<s:DynamicStreamingVideoItem id="videoItemMedium" streamName="{FlexGlobals.topLevelApplication.parameters.videoMedium}" bitrate="{FlexGlobals.topLevelApplication.parameters.videoMediumBitrate}" />
<s:DynamicStreamingVideoItem id="videoItemHigh" streamName="{FlexGlobals.topLevelApplication.parameters.videoHigh}" bitrate="{FlexGlobals.topLevelApplication.parameters.videoHighBitrate}" />
</s:DynamicStreamingVideoSource>
</s:source>
</s:VideoDisplay>
As a variant you may handle NetStream.Play.PublishNotify from NetStream object.
var _source:DynamicStreamingResource;
_source = new DynamicStreamingResource("rtmp://...", StreamType.LIVE);
var streamItems:Vector.<DynamicStreamingItem> = new Vector.<DynamicStreamingItem>();
streamItems.push(new DynamicStreamingItem(streamName, 0));
_source.streamItems = streamItems;
_rtmpDynamicStreamingNetLoader = new RTMPDynamicStreamingNetLoader();
_rtmpDynamicStreamingNetLoader.addEventListener(LoaderEvent.LOAD_STATE_CHANGE, rtmpDynamicStreamingNetLoaderStateChangeHandler);
var cvp:VideoDisplay = new VideoDisplay();
_source.mediaType = MediaType.VIDEO;
var videoElement:MediaElement = new VideoElement(_source, _rtmpDynamicStreamingNetLoader);
cvp.source = videoElement;
private function rtmpDynamicStreamingNetLoaderStateChangeHandler(event:LoaderEvent):void
{
var netStream:NetStream = event.loadTrait["netStream"] as NetStream;
if (netStream != null && !netStream.hasEventListener(NetStatusEvent.NET_STATUS)) {
netStream.addEventListener(NetStatusEvent.NET_STATUS, netStreamNetStatusHandler, false, 0, true);
}
}
private function netStreamNetStatusHandler(event:NetStatusEvent):void
{
if (event.info.code == "NetStream.Play.UnpublishNotify") {
}
if (event.info.code == "NetStream.Play.PublishNotify") {
}
}
I used Johnatan's code along with JayPea's idea to solve my problem!
I used all that Johnatan gave, with the following small change in the netStreamNetStatusHandler():
private function netStreamNetStatusHandler(event:NetStatusEvent):void
{
trace(event.info.code);
if (event.info.code == "NetStream.Play.PublishNotify")
{
try
{
cvp.source = ''; //Doesn't need to be a valid path. Empty string should suffice.
}
catch (error:Error)
{
trace('Video source error: ' + error.message);
}
cvp.source = videoElement;
}
}
This resets the source when the stream stops and restarts, thus causing the video display to play again.
NOTE: The video display's autoPlay property needs to be set as 'true'.
I know this question was asked many years ago, but it still helped me solving my problem encouraging me diving into the sources of VideoDisplay (since there obviously is no "clean" solution ;-(
And for those who have the same problem my "solution" ,ight be helpful too:
I had to restart the same video after the user clicked abort but then decided to play it again. Without "resetting" VideoDisplay this resulted in a black screen.
Here's how I solved the issue after I found out that in VideoDisplay an internal function "setupSource()" was called when in the commitProperties() function no thumnailSource was defined.
Since the setupSource() function was not publicly accessible I used this:
myVideoDisplaySpark.enabled = false; // changes properties
myVideoDisplaySpark.source = ""; // does not harm ;-)
myVideoDisplaySpark.mx_internal::thumbnailSource = null; // forces a setupSource in commitProperties
myVideoDisplaySpark.enabled = true; // finally results in the call if setupSource
That's at least what I understood; and at the end it worked for me ;-)
I have a simple Silverlight player that uses the MediaElement. For reasons out of my control, they want to be able to have all the play/pause/stop, volume controls etc. based in the ASP.NET code and not be built in Silverlight. I embed the Silverlight in my aspx as follows:
<object id="SilverlightPlayer" data="data:application/x-silverlight,"
type="application/x-silverlight-2" width="750" height="460" >
<param name="source" value="ClientBin/VideoPlayer.xap"/>
<param name="EnableGPUAcceleration" value="true" />
<param name="OnResize" value="HandleResize" />
<param name="autoUpgrade" value="true" />
<param name="initParams" id="SLInitParameters" value='video=MyVideo.wmv' />
</object>
I want to have the user click a "Play" button in the ASPX and it will tell the Silverlight player to play the video. (Same kind of thing for all the other buttons) I have been unable to find out how to do this anywhere since everyone it seems builds these controls into their Silverlight.
Any help is greatly appreciated.
UPDATE:
I am using the following to recreate the silverlight:
function CreateSilverlight(hostElement, source, initParams) {
var pluginId = hostElement.id + "PluginId";
hostElement.innerHTML = Silverlight.createObject(source, null, pluginId,
{
width: '750',
height: '460',
background: 'black',
isWindowless: true,
alt: '<!--Silverlight not installed-->',
data: 'data:application/x-silverlight,',
type: 'application/x-silverlight-2',
EnableGPUAcceleration: true,
version: '4.0',
autoUpgrade: true
},
{ onError: null, onLoad: null, OnResize: HandleResize },
initParams, hostElement.id);
}
So I don't have the reference to the object.
In the constructor of your silverlight page on which the media element appears, call:
HtmlPage.RegisterScriptableObject("player", this)
Then, you can add methods to your page like this:
[ScriptableMember]
public void Play()
{
this.MediaElement.Play();
}
[ScriptableMember]
public void Pause()
{
this.MediaElement.Pause();
}
[ScriptableMember]
public void Stop()
{
this.MediaElement.Stop();
}
Those [ScriptableMember] attributes are important. Then, from javascript, you can do:
var slApp = document.getElementById("SilverlightPlayer");
slApp.player.Play();
That would call the exposed "Play" method, which in turn tells the MediaElement to Play().
You can communicate from HTML to Silverlight via Javascript through the HtmlPage.Window.Invoke() method. Check out this link.
I didn't need to reload the silverlight control to get it to load a different video. I just needed to pass a new media path to the silverlight mediaElement.Source via the JS to silverlight bridge. I also solved my issue of loading a video passed to the page by adding to invoke a js function once the SL was loaded on the screen.
I'm stuck on what appears to be a CSS/z-index conflict with the YouTube player. In Firefox 3 under Windows XP, Take a look at this page: http://spokenword.org/program/21396 Click on the Collect button and note that the pop-up <div> appears under the YouTube player. On other browsers the <div> appears on top. It has a z-index value of 999999. I've tried setting the z-index of the <object> element containing the player to a lower value, but that didn't work. Any idea how to get the pop-up to appear over the player?
Try to add the wmode parameter to be opaque like this:
(Note that it's included in both a <param> tag and a wmode attribute on the <embed> tag.)
<object width='425' height='344'>
<param name='movie' value='http://www.youtube.com/v/Wj_JNwNbETA&hl=en&fs=1'>
<param name='type' value='application/x-shockwave-flash'>
<param name='allowfullscreen' value='true'>
<param name='allowscriptaccess' value='always'>
<param name="wmode" value="opaque" />
<embed width='425' height='344'
src='http://www.youtube.com/v/Wj_JNwNbETA&hl=en&fs=1'
type='application/x-shockwave-flash'
allowfullscreen='true'
allowscriptaccess='always'
wmode="opaque"
></embed>
</object>
although the recommendation by CMS is valid, there is an important update. If you want to use 'iframe' instead of 'embed' , simply add ?wmode=transparent to your video link and that does the magic. I find this more simple and clean.
Update, Feb 2014
It's been a while and this may be outdated.
Somebody reported that now &wmode=transparent works instead.
i've found a pure JS function that fix it in all browsers!
there you go:
function fix_flash() {
// loop through every embed tag on the site
var embeds = document.getElementsByTagName('embed');
for (i = 0; i < embeds.length; i++) {
embed = embeds[i];
var new_embed;
// everything but Firefox & Konqueror
if (embed.outerHTML) {
var html = embed.outerHTML;
// replace an existing wmode parameter
if (html.match(/wmode\s*=\s*('|")[a-zA-Z]+('|")/i))
new_embed = html.replace(/wmode\s*=\s*('|")window('|")/i, "wmode='transparent'");
// add a new wmode parameter
else
new_embed = html.replace(/<embed\s/i, "<embed wmode='transparent' ");
// replace the old embed object with the fixed version
embed.insertAdjacentHTML('beforeBegin', new_embed);
embed.parentNode.removeChild(embed);
} else {
// cloneNode is buggy in some versions of Safari & Opera, but works fine in FF
new_embed = embed.cloneNode(true);
if (!new_embed.getAttribute('wmode') || new_embed.getAttribute('wmode').toLowerCase() == 'window')
new_embed.setAttribute('wmode', 'transparent');
embed.parentNode.replaceChild(new_embed, embed);
}
}
// loop through every object tag on the site
var objects = document.getElementsByTagName('object');
for (i = 0; i < objects.length; i++) {
object = objects[i];
var new_object;
// object is an IE specific tag so we can use outerHTML here
if (object.outerHTML) {
var html = object.outerHTML;
// replace an existing wmode parameter
if (html.match(/<param\s+name\s*=\s*('|")wmode('|")\s+value\s*=\s*('|")[a-zA-Z]+('|")\s*\/?\>/i))
new_object = html.replace(/<param\s+name\s*=\s*('|")wmode('|")\s+value\s*=\s*('|")window('|")\s*\/?\>/i, "<param name='wmode' value='transparent' />");
// add a new wmode parameter
else
new_object = html.replace(/<\/object\>/i, "<param name='wmode' value='transparent' />\n</object>");
// loop through each of the param tags
var children = object.childNodes;
for (j = 0; j < children.length; j++) {
try {
if (children[j] != null) {
var theName = children[j].getAttribute('name');
if (theName != null && theName.match(/flashvars/i)) {
new_object = new_object.replace(/<param\s+name\s*=\s*('|")flashvars('|")\s+value\s*=\s*('|")[^'"]*('|")\s*\/?\>/i, "<param name='flashvars' value='" + children[j].getAttribute('value') + "' />");
}
}
}
catch (err) {
}
}
// replace the old embed object with the fixed versiony
object.insertAdjacentHTML('beforeBegin', new_object);
object.parentNode.removeChild(object);
}
}
}
now you can just run in when the page loads with jQuery:
$(document).ready(function () {
fix_flash();
});
We use jQuery Flash plugin to convert YouTube links to Flash movies. In this case, wmode is passed as an option in order to get the YouTube video to appear underneath the jQuery Dialog we open:
$('a[href^="http://www.youtube.com"]').flash(
{ width: nnn, height: nnn, wmode: 'opaque' }
);
I've noticed that wmode="opaque" terribly affects on usage of CPU.
Chrome make on my notebook 50% CPU usage (without opaque ~8%).
So be careful with this option.