C# .NET MediaPlayer can't use relative URL - c#

I'm developing a retro-style game in C# .NET-Framework, and I would like to use different sounds and music in my game. But I have a problem. The original System.Windows.Media.SoundPlayer doesn't support 2 (or more) sounds being played. When one starts, it stops the active one.
I'm looking for a solution that can play different audio at the same time. I tried threading the different SoundPlayers to different threads, but that wasn't a good solution for me (+ it didn't work).
I read about System.Windows.Media.MediaPlayer, and the different controls that you could use with it. This instantly had me interested, especially after I read that you could play different sounds at once.
But trying to use the MediaPlayer in my game, it throws an error, because the URL isn't spelled correct. Here is my code:
using System.Windows.Media;
MediaPlayer Sound = new MediaPlayer();
MediaPlayer BackgroundMusic = new MediaPlayer();
private void Form1_Load(object sender, EventArgs e)
{
Sound.Open(new Uri("Text1.wav"));
BackgroundMusic.Open(new Uri("BackgroundMusicMix.wav"));
}
private void BtnSound_Click(object sender, EventArgs e)
{
Sound.Play();
}
private void BtnBackgroundSound_Click(object sender, EventArgs e)
{
BackgroundMusic.Play();
}
The .wav-files are here located in the \bin\debug folder of my solution, because the SoundPlayer also gets it's sounds from there. I am aware of the fact that you can always put in the full filepath, but the project is being edited by multiple people, so we need the sounds to be located in the solution folder (relative URL).
SO my question is: what is the correct spelling for relative URL? Or even better, is there a simpler method to play 2 sounds simultaneously?

The issue with the "relative URL" you're seeking is that it'd be relative to what? This is a compiled application, not a web page, so neither Uri nor MediaPlayer can assume the answer to that.
That you don't want to hard-code an absolute path doesn't mean you can't construct one at runtime, though. You can use the Assembly.GetExecutingAssembly() method to get the absolute path to your application...
string executableFilePath = Assembly.GetExecutingAssembly().Location;
...and then use the Path class to turn that into an absolute path to your audio file...
string executableDirectoryPath = Path.GetDirectoryName(executableFilePath);
string audioFilePath = Path.Combine(executableDirectoryPath, "BackgroundMusicMix.wav");
...from which you can create an absolute file URL...
Uri audioFileUri = new Uri(audioFilePath);
See Convert file path to a file URI? for some of the peculiarities to consider when constructing a Uri from a filesystem path like that.
By the way, as far as alternatives, I've not used this myself so I don't know how suited it is for what you're doing, but I know NAudio is a thing that exists.

Related

Playing WPF music as a resource [duplicate]

I am trying to play a sound file in my WPF application. Currently I have the following call:
private void PlaySound(string uriPath)
{
Uri uri = new Uri(#"pack://application:,,,/Media/movepoint.wav");
var player = new MediaPlayer();
player.Open(uri);
player.Play();
}
Now if I specify Media/movepoint.wav as build action Content and load it as a relative or absolute file path it works fine, so I suspect this has something to do with the Pack URI, but I cannot for the life of me figure out what.
The objective is to store the file as a resource so that its not available in the output directory. I can provide either the WAV copy or the MP3 copy.
I tried this with an image file, which works the same as a sound file as far as the uri is concerned because it's just another resource. I used the code below which essentially matches what you have.
new Uri(#"pack://application:,,,/Resources/logo.png")
Make sure that your 'Media' folder is not nested in any other folder. If it is, you need to include that folder as well.
Using .NET Framework 4.0, VS2012.
This link gives a pretty good description of the whole "pack" scheme of things.
EDIT
More research on this topic seems to indicate that what you want to do might not be possible with audio or video files. The excerpt below is taken from the remarks section of this MSDN page.
Although you can declare an instance of this class in Extensible
Application Markup Language (XAML), you cannot load and play its media
without using code. To play media in XAML only, use a MediaElement.
Also, if you declare an instance in XAML, the only practical use is to
fill property element syntax for the Player property.
When distributing media with your application, you cannot use a media
file as a project resource. In your project file, you must instead set
the media type to Content and set CopyToOutputDirectory to
PreserveNewest or Always.
MediaPlayer can be used in two different modes, depending on what is
driving the player: independent mode or clock mode. In independent
mode, the MediaPlayer is analogous to an image and the media opened
through the Open method drives playback. In Clock mode, the
MediaPlayer can be thought of as a target for an animation, and thus
it will have corresponding Timeline and Clock entries in the Timing
tree which controls playback. For more information on media modes, see
the Multimedia Overview.
MediaPlayer is different from a MediaElement in that it is not a
control that can be added directly to the user interface (UI) of an
application. To display media loaded using MediaPlayer, a VideoDrawing
or DrawingContext must be used.
The following seems to work in .NET Framework 4.5:
var sri = Application.GetResourceStream(new Uri("pack://application:,,,/MyAssemblyName;component/Resources/CameraShutter.wav"));
if ((sri != null))
{
using (s == sri.Stream)
{
System.Media.SoundPlayer player = new System.Media.SoundPlayer(s);
player.Load();
player.Play();
}
}
CameraShutter.wav is embedded as Resource in my project (and resides inside Resources subfolder, as indicated in the pack URI).
You can also load a Stream into the SoundPlayer if the .wav file is an Embedded Resource. Note that in this example the resources are in a folder called Resources that is in the root of the project, that is why it is written {0}.Resources.{1}.
//the wav filename
string file = "emergency_alarm_002.wav";
//get the current assembly
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
//load the embedded resource as a stream
var stream = assembly.GetManifestResourceStream(string.Format("{0}.Resources.{1}", assembly.GetName().Name, file));
//load the stream into the player
var player = new System.Media.SoundPlayer(stream);
//play the sound
player.Play();
This also seems to work and is maybe simpler to remember than that long line of pack or assembly stuff..
I opened the Resources.resx and dragged a sound file in there called aa_pickup.wav Then set the properties of it to Copy to Output Dir = Copy Always.
System.IO.Stream str = Properties.Resources.aa_pickup;
System.Media.SoundPlayer snd = new System.Media.SoundPlayer(str);
snd.Play();
Now.. if I could only work out how to change the volume.

Starting a .exe file but won't work?

I wanted to start a .exe file in a different folder but I wanted other people to also use it and I've been trying many things but it just keeps opening the file that the program that I'm creating is in. (I'm new to c#).
My ex of ^: \Desktop\VSCheatDetector\CheatDetector.exe(the program) and another regular file named viper_screenshare_tool and it has CheatDetector.exe (which I want to open when I click a certain button)
Code:
private void cheat_smasher_click(object sender, EventArgs e)
{
string dir = AppDomain.CurrentDomain.BaseDirectory;
Process.Start(dir, "vipers_screenshare_tool\\CheatDetector.exe");
}
You don't want to use AppDomain.CurrentDomain.BaseDirectory; - I'd suggest using App.config or something like that instead.

How can I make a windows media player control's URL truly null?

I am trying to modify my track's metadata, but I can't because the file I try to edit is constantly in use. I believe this is because my axwindowsmediaplayer control is still reading from the file. I want it to stop reading from the file so I can edit it, but it seems I can't make its URL property equivalent to nothing- it wants to keep the same URL if I tell it to set the URL to null or " ". If I give it an invalid URL though, it errors. How can I make it so its URL is actually null or better yet, make it so it stops reading from my file altogether?
private void editTrackMetadataToolStripMenuItem_Click(object sender, EventArgs e)
{
Form metaform = new MetaData();
metaform.Show();
Properties.Settings.Default.StopMedia = true;
axWindowsMediaPlayer1.URL = null;//ahahahahahahaha
}
According to the documentation, it is possible to release the current resource with the close method.
Try
axWindowsMediaPlayer1.currentPlaylist.clear();
For folks who are still looking for answers:
close method does not work, it stops the player but you can still click the
play button to play the old one.
axWindowsMediaPlayer1.currentPlaylist.clear(); works as a charm.

System.Windows.Controls.WebBrowser Navigate to html-file on disk

I feel really stupid but i cant figure this one out.
This works flawless;
((System.Windows.Controls.WebBrowser)e.Control).Navigate(new Uri("http://www.google.com"));
But when i try to navigate to a file on disk it fails
string path =#"D:\dev\MySite.html";
((System.Windows.Controls.WebBrowser)e.Control).Navigate(new Uri(path));
I guess i cant use Uri but what else should i use to navigate to a file on disk?
full code;
private void webControlAvailable(object sender, ControlAvailableEventArgs e)
{
string path =#"D:\dev\MySite.html";
((System.Windows.Controls.WebBrowser)e.Control).Navigate(new Uri(path));
}
Using the System.Windows.Controls.WebBrowser to navigate to local files is quite a tough one. You can try this one, though:
string path =#"file://127.0.0.1/D$/dev/MySite.html";
((System.Windows.Controls.WebBrowser)e.Control).Navigate(new Uri(path));
If you have JavaScript one your site it might be a little ugly and fail.
You can also use a System.IO.Stream to navigate, using WebBrwoser.NavigateToStream(), see this thread on SO and the official documentation.

How do I stream videos from web server in Silverlight using ExpressionMediaPlayer control?

I would like to stream videos that reside at the webserver from within a ExpressionMediaPlayer control. The following results in a network error. I believe that the problem is with my Uri. I have the videos inside the 'ClentBin' folder. Can anyone tell me how this is done?
private void videoList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var selectedVideo = (Video)videoList.SelectedItem;
PlaylistItem item = new PlaylistItem();
item.MediaSource = new Uri(#"/ClientBin/" + selectedVideo.FilePath, UriKind.RelativeOrAbsolute);
item.IsAdaptiveStreaming = false;
ep.Playlist.Items.Add(item);
}
Thanks!
There can be a number of factors that contribute to a network error in the Expression Media Player. Here are some basic checks...
1. Check the video file itself
Launch Windows Media Player, go to File > Open URL... and make sure you can play the video with the absolute URL, just to rule out any basic problems with the web server. (Note that this does not apply if you are working with Adaptive Streaming, which it doesn't appear you are.)
2. What does selectedVideo.FilePath contain?
Is this a simple file name (i.e. MyVideo.wmv) or is it a relative file path? Forward or backward slashes?
3. Try it with an absolute static URI
Just to rule out relative path issues with your app / web server / any virtual directory configuration, try:
item.MediaSource = new Uri(#"http://mysite.com/ClientBin/MyVideo.wmv", UriKind.Absolute);
4. Remove the leading slash from /ClientBin/
Try just new Uri(#"ClientBin/" + selectedVideo.FilePath, UriKind.Relative); and see if the relative path is then correct.

Categories

Resources