Playing music in Silverlight + XNA application - silverlight

I have several issues with playing music in a Silverlight+XNA combined application. It has several Silverlight pages and the "game" page rendered in XNA.
First, I added the following code to the OnNavigatedTo event of the main Silverlight page:
var song = (Application.Current as App).Content.Load<Song>("Music/Menu");
MediaPlayer.Play(song);
MediaPlayer.Volume = 0.9f;
MediaPlayer.IsRepeating = true;
The music starts playing, however the application fails with the following exception that has no evident callstack hints:
InvalidOperationException occured
FrameworkDispatcher.Update has not been called. Regular FrameworkDispatcher.Update calls are necessary for fire and forget sound effects and framework events to function correctly.
Secondly, I have a few Silverlight-based windows rendered using UIElementRenderer. When the need arises, I change the control's IsEnabled flag to true and start drawing it on the screen. This makes the music stop playing with a fadeout for no apparent reason and it wouldn't even start back when I close the Silverligh window.
Navigating from the frame and back to it makes things even worse. The same call to MediaPlayer.Play(song) says that the song has been disposed, even though I load it from the ContentManager anew.

Please see this StackOverflow question — answer is pretty clear. In short, you have to call FrameworkDispatcher.Update() before using XNA media libraries.

Related

Threading and stucked GUI update for Animations

The title sounds like some easy well-known problem, but please check out this:
I've got some WPF window that handles a list of Threads and shows ProgressBar for each Thread. The invoked GUI refresh is working for most threads showing right number of percent and also for unknown progress the IsIndeterminate state is animated. After the thread is done some animation fades out the ProgressBar.
However, for some of my heavy tasks the ProgressBar is not visually updated. For example, the IsIndeterminate state refreshes only if I force the GUI to redraw by some mouseover events or by moving the form. The fade out animation shows the same problem.
I think this is no usual stucking because the UI thread is not blocked by further operations (there's only one invoke setting IsIndeterminate = true). Until now, I wasn't able to find out what's the different between heavy tasks that result in this behavoir and tasks that do not.
Please notice that the replacement of the Thread by a BackgroundWorker shows exactly the same problem (I'm also not sure why people say BackgroundWorker will not freeze the GUI but Threads allegedly do - this seems not entirely right). Please also notice that although the thread is paused by Thread.Suspend() (yes, I know it's obsolete but this is an essential feature I need, since the task content is unknown) the GUI will not show up the IsIndeterminate animation if no other GUI element forces the refresh of the window.
Any ideas what that problem might be and how to fix it? I just need the usual refreshing rate for drawing animated controls...

MVVM Application not Restoring State Correctly

I have built a class library that acts as a GUI framework that can be inherited by other projects. This application is based on projects Wild and Gemini.
My problem is that upon restoring Avalon Dock's layout using the standard serializer
var layoutSerializer = new XmlLayoutSerializer(manager);
where manager is type DockingManager. The manager restores and empty tab. My guess is that Caliburn Micro cannot find the stored ViewModel (named HomeViewModel). However, I am struggling to confirm this.
I believe my bootstrapper to be correct and that the MEF containers are being setup correctly to allow resolution of external types. I have debugged the project to a point where I think this issue is occurring and in the output window I can see Attach(Home) where the attach is occurring (note, "Home" is the display name of the HomeViewModel). However, I don't know what is wrong with the attach process as this is handled by MEF/Caliburn.
I am really stuck with debugging this an wondered if
Any one could offer any insightful advice as to how to proceed with the debugging process?
Anyone would be willing to take a look at the solution?
I have spent a hell of a lot of time debugging this without any luck and the problem is sufficiently esoteric and illusive as to render most posts here irrelevant to me.
Thanks for your time.
as discussed and after looking on the sample code provided, I understand that the following
HomeViewModel or can say LayoutItemBase is not supposed to be reopened as ShouldReopenOnStartup is set to false
if you close the application while leaving a document open for HomeViewModel it is restored on next start with blank view [Not OK]
Analysis
the SaveState method was correctly honoring ShouldReopenOnStartup value and was not emitting the state for the HomeViewModel but dock manager was still emitting an element for the document.
So upon next restart the LoadState does not find any stored state but a window was created as an element was present in the dock manager's layout state
<LayoutDocument Title="HomePP" IsSelected="True" IsLastFocusedDocument="True" ContentId="d716f824-cfff-4b54-8fd6-2d026a99369a" .../>
you did try to use e.Cancel property of Serialization callback to cancel the event, but seems like it is not supposed to prevent of loading a window but just simply to cancel the event if not needed.
Resolution
So the ideal approach is to close the documents which are not supposed to be restored before saving the layout
here is how I did
ShellViewmodel.cs : Line 279 method SaveState(string)
change the following code
if (!item.ShouldReopenOnStartup)
continue;
to
if (!item.ShouldReopenOnStartup)
{
//this item is not supposed to be restored so close the window before saving layout
IDocument doc = item as IDocument;
if (doc != null)
CloseDocument(doc);
continue;
}

How to animate WPF WebBrowser

Just documenting this as a question an answer so that somebody else doesn't have to suffer the same pain.
I have a WPF application that animates pages, much like swiping on an iPhone. All was good until one of the pages needed to contain a WebBrowser. It did not respond at all well to the animation - when it was supposed to slide in, it wouldn't appear until you focused it, and when it was supposed to slide out, it would go away until you moved the mouse over it. In both cases it just popped in/out rather than animating.
Complicating matters, during the project it was decided to move back to .net 3.5 instead of 4 for unrelated reasons.
So the question is: how can I either (a) get the WebBrowser to properly animate; or (b) how can I hide the WebBrowser at the start of animation and show it again at the end. The animation is currently defined in XAML, and I don't particularly want to change it to code.
And a follow up question is: is there a better way, still using .net 3.5?
UPDATE The WPF WebBrowser is so pathetically lame compared to the WinForms one, I have swapped over, using WindowsFormsHost. Everything below still applies, but the WebBrowser is now not so nobbled (eg. it has a DocumentCompleted event).
I pretty quickly gave up on the option to animate the WebBrowser, as it just got all too hard, and instead decided to hide and re-show it. The start of the animation is triggered by a Command on the View Model. It then finds the page that should be displayed, creates it, and kicks off the animation through an attached property that reflects the transition state.
I created an interface, IRequireTransitionInfo, such that a call to IRequireTransitionInfo.TransitioningFrom gives it a chance to hide itself and IRequireTransitionInfo.TransitioningTo to show again. TransitioningFrom was easy, but TransitioningTo had to be called when the storyboard completed.
Initially, in the constructor of the View Model, it went looking for the Storyboard and hooked into its Completed event, as in the code below:
Storyboard animation = Application.Current.FindResource("SlideAnimation") as Storyboard;
if (animation != null)
{
animation.Completed += new EventHandler(animation_Completed);
}
And then the event handler:
void animation_Completed(object sender, EventArgs e)
{
IRequireTransitionInfo info = currentViewModel as IRequireTransitionInfo;
if (info != null)
info.TransitioningTo(currentView);
}
This seemed to be working pretty well with .net 4. After downgrading to .net 3.5, when the code above to hook up the Completed event ran, I got the following error:
Specified value of type 'System.Windows.Media.Animation.Storyboard' must have IsFrozen set to false to modify.
Despite some of the other answers on SO, you cannot unfreeze a frozen Freezable, and moving the code into the constructor of the MainWindow didn't help.
I went down the path of an attached property on the Storyboard that was bound to a command on the View Model.
<Storyboard x:Key="SlideAnimation" local:EventCommand.StoryboardCompleted="{Binding Source={StaticResource Locator}, Path=Current.MainViewModel.StoryboardCompletedCommand}">
However, this resulted in the following error at runtime:
Cannot convert the value in attribute 'ContentTemplate' to object of type 'System.Windows.DataTemplate'. Cannot freeze this Storyboard timeline tree for use across threads.
It seems you can't do any databinding on a Storyboard (under .net 3.5 at least). Consequently, I solved the problem somewhat inelegantly by having the attached property just define the string name of a resource that was expected to implement an interface supporting notification of storyboard completion.
<Storyboard x:Key="SlideAnimation" local:EventCommand.StoryboardCompletedHandler="Locator">
If anybody knows of a better way to handle this situation under .net 3.5, I would be glad to hear.

Windows Phone 7.1 - Media Element not playing

Windows Phone 7.1/7.5/Mango app.
I have four different MediaElements on the page.
One is played upon Load of the page.
Rest 3 I Play() it upon leftMouseButtonClick on different image element on the page.
I call Stop() in the MediaEnded event handler.
Issue: The last mediaElement in the top-down order won't play. So it's not the element itself bu the order of the element that is behaving weird.
I have read this where it talks about a single MediaElement which I don't understand.
Does anyone has any ideas on this?
Note: I don't have to play all sound at the same time. Only one sound at a time.
I found one reference that talks having single MediaElement only and dynamically set the Source in the code. I haven't tried it yet, will do soon.
To confirm your last sentence, you can only have one MediaElement per page. You'll have to consider changing the source from the code-behind (or using data-binding) instead of having a MediaElement for each piece of audio. Having multiple MediaElements won't throw an error, but it will just override the behaviour of the previously added one (like you're experiencing).
To set the audio from the code-behind, you can use either the SetSource (which accepts a stream) method, or the Source property which reads a Uri.
In my case, I get the error at the 6th media element. I try to put 14 Media Elements in a project (just to see what happens). You could also use SoundEffect from XNA if you really need to have a lot of sources playing at the same time or something

Change mediaelement Source Based on Actions

I have a WPF 4 and VB.net 2010 project. I am playing videos in a single mediaelement. This is what I need to do:
When the window first opens, I have the first video play just fine. However, it is after this video plays that I run into trouble figuring out how to do the following.
I need the video source to change immediately following a single play through of any video, and I need this video (henceforth referred to as an "ambient" video) to loop forever.
When a certain event happens, I need to change the video source again, have it play once through, and then go back to looping ambient video in step 1.
Here is the rub, however. Many of the video triggers are inside of If-Then or Select Case statements in code behind, so I'm not exclusively using simple WPF events such as "MouseUp" or "MouseEnter".
Also, all videos must play in the same mediaelement, for performance reasons.
Thank you in advance!
How do I do this?
The Source of the media element is a DependencyProperty, as such any changes to it will be immediately reflected in the UI.
If you combine this with the MediaEnded event that is fired, you can set the Source and your problem is solved.
When you hit the triggers in code, you can either call a method or fire an event. You will have to use some semblance of a State Pattern to deal with the other logic. As an aside, check out Programming Without Ifs, it's an awesome intro on how to avoid insane conditional logic.
I set the mediaelement's LoadedBehavior to "Play" and Unloadedbehavior to "Stop", then I was able to just change the source of the mediaelement itself in code, and put the video I needed played after every video into the MediaEnded event.
It turns out that MediaEnded does not fire automatically when the LoadedBehavior is set to "Manual", unless "Stop" is explicitly called in code.
I hate accepting my own answers, so Nate Noonen gets the bounty (he was going down the right alley originally)! TY!

Resources