How to create a background music? - silverlight

I need to run a background music in WP7 Silverlight application. I need it to keep playing when navigating between pages.
Also I don't want it to stop when another sound effect is played.

You can use a MediaElement to do that or use XNA SoundEffects but I have a better solution. Create a SilverXNA project for your app. You don't really need to use XNA but this project automatically creates some stuff which makes life easier. You can use this to build a Silverlight App with no problems.
After creating the project include your sound file in the project say "7am.mp3" and set it's build action to "Content".
Create a song in GamePage.xaml.cs:
Song music;
Now add this in OnNavigatedTo():
music = contentManager.Load<Song>("7am");
After this you can play this song as:
MediaPlayer.Play(music);
You may set the volume etc.
So, why this approach? Well, because according to technical certification guidelines you cannot interrupt a user if he is already listening to a song and SoundEffects class cannot be used for background music thus this method is the only way to get such flexibility.
You can use MediaPlayer.GameHasControl to see if user is playing music or not.

The solution was in referencing Microsoft.Xna.Framework then using the following function:
public static void PlaySound(string soundFile)
{
var stream = Application.GetResourceStream(new Uri(soundFile, UriKind.Relative)).Stream;
if (stream != null)
{
var effect = Microsoft.Xna.Framework.Audio.SoundEffect.FromStream(stream);
Microsoft.Xna.Framework.FrameworkDispatcher.Update();
effect.Play();
}
}
http://spacemigas.wordpress.com/2011/04/07/overcoming-windows-phone-7-mediaelement-limitations/

Related

WPF SoundPlayer multi-channel sound?

I have an app that emits sounds at a random interval. When two sounds collide they do not nicely overplay each other but one interrupts the other.
I'm using SoundPlayer to play the sounds. (this is a WPF app)
How can I use multiple sound channels so that if two sounds occur at the same time they are both played at the same time instead of one interrupting the other?
To my knowledge SoundPlayer uses the native PlaySound function which does not support playing multiple sound simultaneously.
You can however do this with System.Windows.Media.MediaPlayer.
var p1 = new MediaPlayer();
p1.Open(new Uri(#"C:\windows\media\ringout.wav"));
p1.Play();
System.Threading.Thread.Sleep(250);
var p2 = new MediaPlayer();
p2.Open(new System.Uri(#"C:\windows\media\ringout.wav"));
p2.Play();
The sleep is there simply to add a bit of a delay to the playback, making it clear that the two sounds do actually play at the same time.

How to save HTML5 video plays/hits

Is that possible to save the plays that a video (HTML5 based) was played in a Database?
If yes, how?
I properly search for this answer, not so lucky.
Two things you'll need. First you need to figure out your events. If you just want the play event, you can add an event listener.
Something like the following (not using jquery)
var _video = document.getElementById("video");
_video.addEventListener("playing", play_clicked, false);
function play_clicked() {
/* Put your tracking function here */
alert("play was clicked");
}
To track it, I would use some Analytics, Google Analytics is a good one.
Here are some links to help you along a bit further:
Previously Asked Question (with answer)
A page showing example of how to track all kinds of video events
Event Tracking with Google Analytics

MediaElement is repeating clips automatically, and sometimes fails to play them

I have an app which plays a few short sound clips. To play them I simply set the source to the new clip path, which is a WMA I encoded with Expression Encoder using WP7 settings. It's not even worth sharing the code -- there's an event handler. In it, I set the ME.Source property to a new Uri. It's set to AutoPlay, so that's it! Here:
private void PlaySound(ItemViewModel sound) {
Model.CurrentSound = sound;
CurrentSound.Source = new Uri(sound.Path, UriKind.Relative);
}
private void Sounds_SelectionChanged(object sender, SelectionChangedEventArgs e) {
var list = ((ListBox) sender);
var item = (ItemViewModel) list.SelectedItem;
SelectItem(item);
}
Also I should point out that the sounds are all resources (build type = Resource). I need them to be because the app needs to discover them dynamically. The paths are all like this, "sounds/foo/bar/sound.wma". Sometimes there is a space in the path, it is url encoded with %20 (this is how the resource manager returns the path, I didn't do that).
The problem is many people, but not all, are saying that the sound auto-repeats. The sounds are very short, only a few seconds, so it's very annoying. I don't understand how this is happening, the MediaElement doesn't even have an auto repeat feature.
Perhaps related, but some have also complained that every now and then the sound does not play. They have to click it again. All I can think of is that there is something wrong with how the sounds are encoded, but they are WMA, and as I said, I encoded them using the 'playback in WP7' settings in expression encoder. How could it be that it works usually but not other times if that were the case, anyway?
I'm at a loss and my app is getting some bad reviews because of this behavior. Help!
"there's and event handler" but you don't say of what? It could be that event firing over and over or not at all in some cases. Potentially your code has a logical errors where you have failed to detach an existing handler and then added another. As usage progresses you end up with a single event being handled by multiple handlers.
Edit
The Selection changed event is notorious for firing more frequently than we'd like. I suggest you add some debounce code that makes record of the last item selected and how long ago. If the next selected item is the same as the last one and it was say less than a second ago then swallow the event without doing anything else.
It sounds like you might be trying to play Sound Effects - in which case you might be better off using the XNA SoundEffect mechanism
e.g. http://www.japf.fr/2010/08/sound-effect-in-wp7-sl-application/
SoundEffect only works for WAV files (PCM) - but I've used it in several apps and scripts including embedded content files and downloaded files (e.g. translation and ironruby scripts).
The XNA class works well within SL and allows multiple sound effects to be played at the same time.
The problem with repeating turned out to be needing to do this:
MediaPlayer.IsRepeating = false;
I think what happened was the user would be in another app that sets this to true, and upon opening my app that value was still true! That has to be a bug, it's totally unexpected. If you look at other sound-playing apps like soundboard apps, there are users complaining in the reviews about the very same thing.. "I wish it wouldn't repeat the sounds..."

MyGroups not implemented in Communicator.UIAutomation

I'm working on a out of browser Silverlight app that provides some MS Office Communicator 2007 controls. I'm using the Automation SDK. The docs that were installed with the SDK state that there's a MyGroups property in the IMessenger2 interface, which will return the groups that a user has defined, but when I try to use it, I get a NotImplementedException. Here's the code that I'm using:
dynamic communicator = AutomationFactory.CreateObject("Communicator.UIAutomation");
communicator.AutoSignin();
foreach (dynamic g in communicator.MyGroups)
{
//Do something with the group
}
If I replace MyGroups with MyContacts, I can get the contact list just fine. Do I have to do something different to access properties in the IMessenger2 interface? I've seen a few things on the web that say that MyGroups was deprecated for Windows Messenger, but from the docs, it seems like it should be available for MS Office Communicator.
If I can't use MyGroups, is there another way to get the groups that a user has created?
The problem here is that the MyGroups property is marked as NotScriptable, meaning you can't call it in the way you are doing i.e. using the AutomationFactory. For security reasons, some properties and methods in the Automation API are not scriptable - this is to avoid malicious pages automating Communicator and carrying out certain tasks without you knowing.
It looks like the COM interop in Silverlight is treated in the same way as e.g. creating and calling the API from VBScript, so you won't be able to access any of the non-scriptable properties and methods. See the reference for details of which properties and methods are not scriptable.
I'm guessing this is going to seriously hobble your app. I think what's hurting you is the decision to go with Silverlight OOB. Is there any way you could use WPF (or even winforms) rather than Silverlight? If you did this, you could reference the API directly, and have full access to all properties/methods.
Otherwise, I can't think of too many options. You can't trap the OnContactAddedToGroup event, as this is not scriptable.
It might be possible to wrap the API with a .NET assembly, and expose it via COM, then instantiate it in the same way - but the Not Scriptable might still be respected in that case, so it won't buy you anything. Hard to say without trying it, and still a fairly horrible solution.
Edit: I've just given the wrapper method a try (needed to do something similar as a proof of concept for a customer), and it seems to work. This is the way I did it:
Create a new .NET class library. Define a COM interface:
[ComVisible(true)]
[Guid("8999F93E-52F6-4E29-BA64-0ADC22A1FB11")]
public interface IComm
{
string GetMyGroups();
}
Define a class that implements that interface (you'll need to reference CommunicatorAPI.dll from the SDK):
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[GuidAttribute("C5C5A1A8-9BFB-4CE5-B42C-4E6688F6840B")]
[ProgId("Test.Comm.1")]
public class Comm : IComm
{
public string GetMyGroups()
{
var comm = new CommunicatorAPI.MessengerClass();
var groups = comm.MyGroups as IMessengerGroups;
return string.Join(", ", groups.OfType<IMessengerGroup>().Select(g => g.Name).ToArray());
}
}
Build, and register using RegAsm. Then call from the OOB silverlight app:
dynamic communicator = AutomationFactory.CreateObject("Test.Comm.1");
MessageBox.Show(communicator.GetMyGroups());
Note, the same technique also works using the Lync API:
public string GetMyGroups()
{
var comm = LyncClient.GetClient();
return string.Join(", ", comm.ContactManager.Groups.Select(g => g.Name).ToArray());
}
Although this works, I can't really say whether it's a good practice, as it's working around a security restriction which was presumably there for a good reason. I guess the worst that could happen is that a malicious web page could potentially use the component, if it knew the ProgId of the control.
Edit: Also, using this method you'd need to be careful about memory leaks, e.g. make sure you're releasing COM objects when you're finished with them - easy enough to do, just needs a little discipline ;o)

Using Silverlight 2 for short audio caching

I'm attempting to use a large number of short sound samples in a game I'm creating in Silverlight 2. The samples are less than 2 seconds long.
I would prefer to load all the audio samples onto the canvas during the initualization. I have been adding the media element to the canvas and a generic list to manage it. So far, it appears to work.
When I play the sample the first time, it plays perfectly. If it has finished playing and I want to re-use the same element, it cuts off the first part of the sound. To play the sample again, I stop and play the media element.
Is there another method I should use the samples so that the audio is not clipped and good performance is obtained?
Also, it's probably a good idea to make sure that all of your audio samples are brought down to the client side initially. Depending on how you set it up, it's possible that the MediaElements are using their progressive download functionality to get the media files from the server. While there's nothing wrong with this per se (browser caching should be helping you out after the initial download), it does mean that you have to deal with the browser cache, and there are some potential issues there.
Possible steps to try:
Mark your audio files as "Content". This will get them balled up in the .xap.
Load your audio files into MemoryStreams (see Application.GetResourceStream method) and call MediaElement.SetSource().
HTH,
Erik
Some comments:
From MSDN:
Try to limit the number of MediaElement objects you have in your application at once. If you have over one hundred MediaElement objects in your application tree, regardless of whether they are playing concurrently or not, MediaFailed events may be raised. The way to work around this is to add MediaElement objects to the tree as they are needed and remove them when they are not.
You could try to seek to the start of the sample to reset the point currently being played before re-using it with:
mediaelement.Position = new TimeSpan();
See also MSDNs MediaElement.Position.
One techique you can use, although I'm not sure how well it will work in Silverlight, is create one large file with all of your samples joined together (probably with a half-second or so of silence between each). Figure out the timecode for each sample and seek the media element to that position and play. You'll only need as many media elements as simultaneous sounds you want to play.

Resources