I've managed to discover Gilles Khouzam's playback implementation for WAV files in Silverlight 3 and while that would be the majority of the battle, I'm stuck on a final detail: how do I pull a wav file from the web some place and then feed it into his WaveMediaStreamSource for playback?
Here's the closest I've come:
public MainControl()
{
// Required to initialize variables
InitializeComponent();
PlayButton.Click += PlayButtonClicked;
}
private void PlayButtonClicked(object sender, RoutedEventArgs e)
{
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(#"soundfile.wav");
request.BeginGetResponse(ReadCallback, request);
}
private void ReadCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
WaveMediaStreamSource wavMss = new WaveMediaStreamSource(response.GetResponseStream());
MediaPlayer.SetSource(wavMss);
}
Edit:
It turns out the problem had to do with HttpWebRequest. Changing the code to:
public MainPage()
{
InitializeComponent();
WebClient webClient = new WebClient();
webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(webClient_OpenReadCompleted);
webClient.OpenReadAsync(new Uri(#"http://www.russellmyers.com/somefile.wav", UriKind.Absolute));
}
void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
WaveMediaStreamSource wavMss = new WaveMediaStreamSource(e.Result);
Debug.WriteLine("Setting source...");
Media.SetSource(wavMss);
}
Works fine. This makes sense too after reading Shawn Wildermuth's article on the differences. I would like to get HttpWebRequest working though because it won't be done on the UI thread.
Related
I'm making a web browser with CefSharp. I just implemented downloads 2 days ago but there is no progress bar to go along with the download. How do I make the progress bar show download progress?
Edit: Making things clearer
Add a ProgressBar Control to your Form and add a BackgroundWorker Component alongside it to your form. Figure out your file size first:
Int64 bytes_total= Convert.ToInt64(client.ResponseHeaders["Content-Length"])
This is code from Alex's amazing answer which can be found here:
public Form1()
{
InitializeComponent();
backgroundWorker1.DoWork += backgroundWorker1_DoWork;
backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged;
backgroundWorker1.WorkerReportsProgress = true;
}
private void button1_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
//Replace this code with a way to figure out how much of the file you have already downloaded and then use backgroundworker1.ReportProgress and send the percentage completion of the file download.
for (int i = 0; i < 100; i++)
{
Thread.Sleep(1000);
backgroundWorker1.ReportProgress(i);
}
}
private void backgroundWorker1_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
I have winforms application and i have texture SimpleTexture.xnb compiled as HiDef. I need to run XNA 3D visualisation from my winforms application in separate window. I try this:
private void button1_Click(object sender, EventArgs e)
{
System.Threading.Thread thStartGame = new System.Threading.Thread(StartGame);
thStartGame.Start();
}
private void StartGame()
{
using (Game1 game = new Game1())
{
game.Run();
}
}
But i get error:
Error loading "SimpleTexture". This file was compiled for the HiDef profile, and cannot be loaded into a Reach GraphicsDevice.
What can i do to run this??
Change reach to hidef:
YourGraphicsDeviceManager.PreparingDeviceSettings += new EventHandler<PreparingDeviceSettingsEventArgs (graphics_PreparingDeviceSettings);
void graphics_PreparingDeviceSettings(object sender, PreparingDeviceSettingsEventArgs e)
{
e.GraphicsDeviceInformation.GraphicsProfile = GraphicsProfile.HiDef;
}
I'm using the following code and it works nice
private void somethingButton_Click(object sender, System.Windows.RoutedEventArgs e)
{
WebClient webClient = new WebClient();
webClient.OpenReadCompleted += webClient_OpenReadCompleted;
webClient.OpenReadAsync(new Uri(myUri));
}
void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
if(e.Error != null)
{
messageTextBlock.Text = e.Error.Message;
return;
}
using (Stream s=e.Result)
{
XDocument document = XDocument.Load(s);
var q1 = from c in document.Descendants("result")
select new IndeedResult
{
Title =((string)c.Element("title")).Trim(),
ResultUri = ((string)c.Element("url")).Trim(),
Date = ((string)c.Element("date")).Trim(),
};
myDataGrid.ItemsSource = q1;
}
But I want to add another WebClient, webClient2 that will do exactly the same but has different uri and different structure so I will have webClient2_OpenReadCompleted...
The problem is that finally I need to merge (or do some logic before merge) var q1 from webClient_OpenReadCompleted and var q2 from webClient2_OpenReadCompleted and then
var mergedQs = q1.Union(q2).ToList();
myDataGrid.ItemsSource = mergedQs
Is there a simple way how to do it? I don't know how to do it using those event handlers.
Good question! Did it like this
void webClient_OpenReadCompleted( object sender, OpenReadCompletedEventArgs e )
{
Stream stream = (Stream)e.Result;
BinaryReader reader = new BinaryReader( stream );
byte[] buffer = reader.ReadBytes( (int)stream.Length );
Uri uri = (Uri)e.UserState;
streams.Add( uri.AbsoluteUri, new MemoryStream( buffer ) );
}
Note the usage of UserState in order to provide a unqiue key into my streams Dictionary. Works perfectly :-) This way you can work with as many files / images / binary data as you like!
See this to see just how powerful this can be....http://www.alansimes.com/warp3dsilverlighttestpage.html
I have built a simple game in WP7 and I am trying to add background music to it using MediaPlayer. The problem is it just bombs with
{"An unexpected error has occurred."} System.Exception {System.InvalidOperationException}
Code
try
{
MediaPlayer.Stop();
// Timer to run the XNA internals (MediaPlayer is from XNA)
DispatcherTimer dt = new DispatcherTimer();
dt.Interval = TimeSpan.FromMilliseconds(33);
dt.Tick += delegate { try { FrameworkDispatcher.Update(); } catch { } };
dt.Start();
Uri pathToFile = new Uri("Audio/music.m4a", UriKind.Relative);
Song playingSong = Song.FromUri("Music", pathToFile);
MediaPlayer.Play(playingSong);
}
catch (Exception e)
{
musicFailed = true;
Console.WriteLine("Exception: {0}", e.ToString());
MessageBox.Show("Warning, music failed to play however you can still continue to play your game.");
}
}
I tried a few tweaks, converting file to mp3, different paths etc. The file is marked for copy always and content type I also tried removing the Dispatcher as dont know what that is for.
If you can convert your audio files to WAV format, you can try using the XNA SoundEffect and SoundEffectInstance classes:
SoundEffect se = SoundEffect.FromStream(isolatedStorageFileStream);
SoundEffectInstance sei = se.CreateInstance();
sei.Play();
For this to work, you will need to reference the XNA library (Microsoft.XNA.Framework) and initialize the framework in this way:
App.xaml:
<Application>
<Application.ApplicationLifetimeObjects>
<local:XNAFrameworkDispatcherService />
...
</Application.ApplicationLifetimeObjects>
</Application>
And create this class somewhere in the app namespace ("local" in the previous xaml references this namespace):
public class XNAFrameworkDispatcherService : IApplicationService
{
private DispatcherTimer frameworkDispatcherTimer;
public XNAFrameworkDispatcherService()
{
this.frameworkDispatcherTimer = new DispatcherTimer();
this.frameworkDispatcherTimer.Interval = TimeSpan.FromTicks(333333);
this.frameworkDispatcherTimer.Tick += frameworkDispatcherTimer_Tick;
FrameworkDispatcher.Update();
}
void frameworkDispatcherTimer_Tick(object sender, EventArgs e) { FrameworkDispatcher.Update(); }
void IApplicationService.StartService(ApplicationServiceContext context) { this.frameworkDispatcherTimer.Start(); }
void IApplicationService.StopService() { this.frameworkDispatcherTimer.Stop(); }
}
Your problem is that your timer maybe not fired the first tick and FrameworkDispatcher.Update() not ran. Then Play throws a System.InvalidOperationException.
Better dispatch XNA Events global in your Application.
Complete Guide: XNAAsyncDispatcher
So I've downloaded the samples from http://archive.msdn.microsoft.com/ManagedMediaHelpers.
I've got my code working using MP3MediaStreamSource. However, I don't fully understand the code would like some explanation.
public partial class MainPage : PhoneApplicationPage
{
private static string mediaFileLocation = "http://file-here.mp3";
private static HttpWebRequest request = null;
private static Mp3MediaStreamSource mss = null;
public MainPage()
{
InitializeComponent();
}
private void RequestCallback(IAsyncResult asyncResult)
{
HttpWebResponse response = request.EndGetResponse(asyncResult) as HttpWebResponse;
Stream s = response.GetResponseStream();
mss = new Mp3MediaStreamSource(s, response.ContentLength);
Deployment.Current.Dispatcher.BeginInvoke(
() =>
{
this.wp7AudioElement.Volume = 100;
this.wp7AudioElement.SetSource(mss);
});
}
private void Button_Click(object sender, RoutedEventArgs e)
{
request = WebRequest.CreateHttp(MainPage.mediaFileLocation);
// NOTICE
// Makes this demo code easier but I wouldn't do this on a live phone as it will cause the whole
// file to download into memory at once.
//
// Instead, use the asynchronous methods and read the stream in the backgound and dispatch its
// data as needed to the ReportGetSampleCompleted call on the UIThread.
request.AllowReadStreamBuffering = true;
IAsyncResult result = request.BeginGetResponse(new AsyncCallback(this.RequestCallback), null);
}
}
It's really just the last method I need explained, I don't understand the Notice as to why it's a bad idea and how to do it differently?
Basically, it is trying to tell you that you are downloading 1 file COMPLETELY before it plays. It is not a good idea, since if the file is 10 MB, it may take a while before it completely downloads.
A better idea would be to chunk the file using Encoders, and read it in on need basis.