I'm making a soundboard with sound effects and I'm getting :
"A first chance exception of type 'System.NullReferenceException'"
when building after 'UI Task' (Managed):
Loaded 'Microsoft.Xna.Framework.dll'
I did have it working but after changes (overwrote previous version) I have been getting this error and I'm stuck. Java is my first language and with C# I'm a beginner. I have spent countless hours looking for a solution.
The nullReferenceException is coming from loadsound(), I think! I have the sound files(.wav) in a folder called resources and build action:resources and copy to output:do not copy(have tried all options here). Also in references a reference was made to Microsoft.Xna.Framework
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Resources;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Media;
namespace Craggy_Island
{
public partial class MainPage : PhoneApplicationPage
{
// The Resources to play
private SoundEffect drink;//(plus 23 more effects)
// Flag that indicates if we need to resume Zune playback upon exiting.
bool resumeMediaPlayerAfterDone = false;
// Constructor
public MainPage()
{
InitializeComponent();
// Timer to simulate the XNA game loop (SoundEffect class is from the XNA Framework)
GameTimer gameTimer = new GameTimer();
gameTimer.UpdateInterval = TimeSpan.FromMilliseconds(33);
// Call FrameworkDispatcher.Update to update the XNA Framework internals.
gameTimer.Update += delegate { try { FrameworkDispatcher.Update(); } catch { } };
// Start the GameTimer running.
gameTimer.Start();
// Prime the pump or we'll get an exception.
FrameworkDispatcher.Update();
//LoadSound("Resources/drink.wav", out drink);
// Create and load SoundEffect objects.
LoadSound("Resources/drink.wav", out drink);
}
private void LoadSound(String SoundFilePath, out SoundEffect Sound)
{
// For error checking, assume we'll fail to load the file.
Sound = null;
try
{
// Holds informations about a file stream.
StreamResourceInfo SoundFileInfo = App.GetResourceStream(new Uri(SoundFilePath, UriKind.Relative));
// Create the SoundEffect from the Stream
Sound = SoundEffect.FromStream(SoundFileInfo.Stream);
}
catch (NullReferenceException)
{
// Display an error message
MessageBox.Show("Couldn't load sound " + SoundFilePath);
}
}
private void button_Click(object sender, RoutedEventArgs e)
{
Button Current = sender as Button;
try
{
if (Current.Equals(button1))
drink.Play();//(other buttons here for other sound effects)
}
catch (NullReferenceException)
{
MessageBox.Show("Can't play, sound file problem.");
}
}
#region Zune Pause/Resume
private void ZunePause()
{
// Please see the MainPage() constructor above where the GameTimer object is created.
// This enables the use of the XNA framework MediaPlayer class by pumping the XNA FrameworkDispatcher.
// Pause the Zune player if it is already playing music.
if (!MediaPlayer.GameHasControl)
{
MediaPlayer.Pause();
resumeMediaPlayerAfterDone = true;
}
}
private void ZuneResume()
{
// If Zune was playing music, resume playback
if (resumeMediaPlayerAfterDone)
{
MediaPlayer.Resume();
}
}
#endregion Zune Pause/Resume
}
}
Scrap my original answer unless you're using XNA for game development on Windows/Xbox. (Original poster is using it for the Zune.)
Regarding the WAV file:
First problem is that you need to set Copy to Output Directory to Copy if newer. (You could use Always, but that would be unnecessary.)
Second problem is that its type needs to be set to Content.
You are taking the hard approach. Look into ContentManager (accessible as this.Content from within the Game instance). You can use Content.Load<T>(string) to access your audio file, but you'll need to put the audio file in the content project. Don't change its type: leave it at the default. Even it's not a resource, leave it be. It will be compiled into a different format. Also, omit the file extension from the parameter passed to Content.Load<>.
You are starting the game before you are loading the sound:
gameTimer.Start();
FrameworkDispatcher.Update();
LoadSound("Resources/drink.wav", out drink);
I had almost the same problem. Finally I got it accidently as follows:
StreamResourceInfo streaminfo = Application.GetResourceStream(new Uri("project_name;component/folder_name/Sound3.wav", UriKind.RelativeOrAbsolute));
SoundEffect effect1 = SoundEffect.FromStream(streaminfo.Stream);
effect1.Play();
AND:
the Property "Build Action" of the .wav file must be setted to "Resource" and the Porperty "Copy to Output Directory" should be setted to "Copy if newer"
By the way, I´m working with Silverlight5.
Related
I'm trying to add background music to my WPF program. I also want additional sounds to happen "over" the background music. I tried using a SoundPlayer however, this could only play one piece of audio at once.
I am now trying to use MediaPlayer but I cannot get any audio to play. Here is my code:
In my ShellViewModel I start the background music:
Sounds.StartBackgroundMusic()
In my sounds class I have the following:
private static MediaPlayer _backgroundMusic = new MediaPlayer();
public static void StartBackgroundMusic()
{
_backgroundMusic.Open(new Uri("pack://application:,,,/Assets/Sounds/backgroundmusic.wav"));
_backgroundMusic.MediaEnded += new EventHandler (BackgroundMusic_Ended);
_backgroundMusic.Play();
}
private static void BackgroundMusic_Ended(object sender, EventArgs e)
{
_backgroundMusic.Position = TimeSpan.Zero;
_backgroundMusic.Play();
}
Since I want the background music to loop continuously, I used the answer in this question to add the BackgroundMusic_Ended event. Can someone please help shed some light on why my audio isn't playing?
I tried to reproduce the problem but it worked as expected.
I created a new WPF application in Visual Studio and used the following code in MainWindow.xaml.cs:
using System;
using System.Windows;
using System.Windows.Media;
namespace WpfApp1
{
public partial class MainWindow : Window
{
private static MediaPlayer _backgroundMusic = new MediaPlayer();
public MainWindow()
{
InitializeComponent();
StartBackgroundMusic();
}
public static void StartBackgroundMusic()
{
_backgroundMusic.Open(new Uri(#"C:\<path-to-sound-file>\music.wav"));
_backgroundMusic.MediaEnded += new EventHandler(BackgroundMusic_Ended);
_backgroundMusic.Play();
}
private static void BackgroundMusic_Ended(object sender, EventArgs e)
{
_backgroundMusic.Position = TimeSpan.Zero;
_backgroundMusic.Play();
}
}
}
Did you try to use a "regular" file path to load a sound file instead of "pack://..."? When I used the wrong path I didn't get any sound and there was no error message or exception.
Since I couldn't use MediaPlayer to play embedded resources and SoundPlayer can only play one sound at a time, I used a combination of them and saved the embedded background music resource to disk so that MediaPlayer could play it. I make a blog about it here
Heres what I did:
I set up my SoundPlayer as this was the simplest one of the two. I created a new SoundPlayer object using the embedded resource
private static readonly SoundPlayer _soundOne = new SoundPlayer(WPF.Properties.Resources.soundOne);
Now the MediaPlayer. I make sure that my audio file is set as an Embedded Resource under the Build Actions in the file’s properties in Visual Studio. Now that we have done this, we can create the method for saving the embedded WAV file to the %temp% location on disk:
public static void SaveMusicToDisk(){
//This sets up a new temporary file in the %temp% location called "backgroundmusic.wav"
using (FileStream fileStream = File.Create(Path.GetTempPath() + "backgroundmusic.wav")){
//This them looks into the assembly and finds the embedded resource
//inside the WPF project, under the assets folder
//under the sounds folder called backgroundmusic.wav
//PLEASE NOTE: this will be different to you
Assembly.GetExecutingAssembly().GetManifestResourceStream("WPF.Assets.Sounds.backgroundmusic.wav").CopyTo(fileStream);
}
}
We play this by creating a new MediaPlayer object and using the temp file location to play the audio:
//Create a new MediaPlayer object
private static readonly MediaPlayer _backgroundMusic = new MediaPlayer();
public static void StartBackgroundMusic(){
//Open the temp WAV file saved in the temp location and called "backgroundmusic.wav"
_backgroundMusic.Open(new Uri(Path.Combine(Path.GetTempPath(), "backgroundmusic.wav")));
//Add an event handler for when the media has ended, this way
//the music can be played on a loop
_backgroundMusic.MediaEnded += new EventHandler(BackgroundMusic_Ended);
//Start the music playing
_backgroundMusic.Play();
}
My BackgroundMusic_Ended method looks like this and just makes sure that the music is always restarted once it has finished:
private static void BackgroundMusic_Ended(object sender, EventArgs e){
//Set the music back to the beginning
_backgroundMusic.Position = TimeSpan.Zro;
//Play the music
_backgroundMusic.Play();
}
Then I just had to worry about disposing of the objects and cleaning up the temp file when the program is closing.
Anyone ever tried A Xamarin.Forms Listview with an ItemTemplate containing a Image view? Now, what happens when ListView contains ca 20 or more rows?
As for me, I have a .png file of around 4K in size loaded into the Image view. Got a maximum of 9 - 12 rows shown before application crashed with a OutOfMemoryError. After requesting a large heap in the android Manifest, the app crashes after 60 - 70 rows.
I know that Xamarin is promoting the use of the BitmapFactory class to scale down bitmaps, but this is not applicable (out of the box) for the Xamarin Forms Image View.
I'm about trying to fiddle with a Sub Class of the ImageRenderer to see if I can add a BitmapFactory.Options property and if this will solve the problem.
Also, I might need to check out if Xamarin.Forms does dispose (recycle) the contained bitmap after the ViewCell is being scrolled of the screen.
Before setting out on this journey, I would be very keen to get any comments that could make this easier or a simpler solution that would deem this process unnecessary.
Looking forward...
Yes, I found a solution. Code to follow. But before that, let me explain a bit what I have done.
So, there's definitely a need to take maters in our own hands to dispose the image and its underlying resources (bitmap or drawable, however you want to call it). Basically, it comes down to dispose the native 'ImageRenderer' object.
Now, there's no way to obtain a reference to that ImageRenderer from anywhere because in order to do so, one need to be able to call Platform.GetRenderer(...). Access to the 'Platform' class is inaccessible since its scope is declared as 'internal'.
So, I have been left with no choice other than to sub-class the Image class and its (Android) Renderer and destroy this Renderer itself from inside (passing 'true' as argument. Don't try with 'false'). Inside the Renderer I hook on to page disappear (In case of a TabbedPage). In most situations the Page Disappear event will not serve the purpose well, such as when the page is still in the screen stack but disappears due to a another page is being drawn on Top of it. If you dispose the Image(s) than, when the page gets uncovered (shown) again, it will not display the images. In such case we have to hook on the the main Navigation Page's 'Popped' event.
I have tried to explain to the best I could. The rest - I hope - you will be able to get from the code:
This is the Image Sub-Class in the PCL Project.
using System;
using Xamarin.Forms;
namespace ApplicationClient.CustomControls
{
public class LSImage : Image
{
}
}
The following code is in the Droid project.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Views.InputMethods;
using Android.Widget;
using Android.Util;
using Application.Droid.CustomControls;
using ApplicationClient.CustomControls;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(ApplicationClient.CustomControls.LSImage), typeof(LSImageRenderer))]
namespace Application.Droid.CustomControls
{
public class LSImageRenderer : ImageRenderer
{
Page page;
NavigationPage navigPage;
protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
{
base.OnElementChanged(e);
if (e.OldElement == null)
{
if (GetContainingViewCell(e.NewElement) != null)
{
page = GetContainingPage(e.NewElement);
if (page.Parent is TabbedPage)
{
page.Disappearing += PageContainedInTabbedPageDisapearing;
return;
}
navigPage = GetContainingNavigationPage(page);
if (navigPage != null)
navigPage.Popped += OnPagePopped;
}
else if ((page = GetContainingTabbedPage(e.NewElement)) != null)
{
page.Disappearing += PageContainedInTabbedPageDisapearing;
}
}
}
void PageContainedInTabbedPageDisapearing (object sender, EventArgs e)
{
this.Dispose(true);
page.Disappearing -= PageContainedInTabbedPageDisapearing;
}
protected override void Dispose(bool disposing)
{
Log.Info("**** LSImageRenderer *****", "Image got disposed");
base.Dispose(disposing);
}
private void OnPagePopped(object s, NavigationEventArgs e)
{
if (e.Page == page)
{
this.Dispose(true);
navigPage.Popped -= OnPagePopped;
}
}
private Page GetContainingPage(Xamarin.Forms.Element element)
{
Element parentElement = element.ParentView;
if (typeof(Page).IsAssignableFrom(parentElement.GetType()))
return (Page)parentElement;
else
return GetContainingPage(parentElement);
}
private ViewCell GetContainingViewCell(Xamarin.Forms.Element element)
{
Element parentElement = element.Parent;
if (parentElement == null)
return null;
if (typeof(ViewCell).IsAssignableFrom(parentElement.GetType()))
return (ViewCell)parentElement;
else
return GetContainingViewCell(parentElement);
}
private TabbedPage GetContainingTabbedPage(Element element)
{
Element parentElement = element.Parent;
if (parentElement == null)
return null;
if (typeof(TabbedPage).IsAssignableFrom(parentElement.GetType()))
return (TabbedPage)parentElement;
else
return GetContainingTabbedPage(parentElement);
}
private NavigationPage GetContainingNavigationPage(Element element)
{
Element parentElement = element.Parent;
if (parentElement == null)
return null;
if (typeof(NavigationPage).IsAssignableFrom(parentElement.GetType()))
return (NavigationPage)parentElement;
else
return GetContainingNavigationPage(parentElement);
}
}
}
Finally, I have changed the Name of the Application in the namespace to 'ApplicationClient' in the PCL project and to 'Application.Droid' in Droid project. You should change it to your app name.
Also, the few recursive methods at the end of the Renderer class, I know that I could combine it into one Generic method. The thing is, that I have build one at a time as the need arose. So, this is how I left it.
Happy coding,
Avrohom
Another set of steps that may help is the following:
There appears to be a memory leak on android involving listviews with custom cells. I did some investigating and found that if I did the following in my pages:
protected override void OnAppearing()
{
BindingContext = controller.Model;
base.OnAppearing();
}
protected override void OnDisappearing()
{
BindingContext = null;
Content = null;
base.OnDisappearing();
GC.Collect();
}
Set the android option in the manifest to use a large Heap (android:largeHeap="true") , and lastly, used the new Garbage collector, (in the environment.txt, MONO_GC_PARAMS=bridge-implementation=new)
This combination of things, seems to fix the crashing issue. I can only assume that this is just because the setting of things to null, helps the GC to dispose of the elements, the large heap size to buy the GC time to do so, and the new GC option to help accelerate the collection itself. I sincerely hope this helps someone else...
In Visual Studio 2015 Go to Debug option>.droid Properties>Android Options>Advanced and set Java Max Heap Size to 1G
I am trying to make a main menu in Windows Forms. When you click a label in the form, the XNA game should start playing.
But it didn't work.
my code in the program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace _2DSpaceShooter
{
if WINDOWS || XBOX
static class Program
{
static void Main(string[] args)
{
Application.Run(new MainMenu());
}
}
endif
}
My code in the label click event
private void label1_Click(object sender, EventArgs e)
{
using (Game1 game = new Game1())
{
game.Run();
}
}
Please help me!!!
I am sorry for possible English mistakes (I am not American)
I don't know if you can do it, but if you can one of the simplest way is by using GameComponents. Making your game as a GC enables you to launch multiples parts of it at one time, without having issues with threads.
As #eudabash mentioned in the comment section, you'll need to do the game.Run() in a seperate thread:
Game1 game = new Game1();
Thread thread = new Thread(() =>
{
game.Run();
};
thread.Start();
or, if you're on .Net 4.0 (I think. Or even 3.5)
Game1 game = new Game1();
Task.Factory.StartNew(() =>
{
game.Run();
}
Optionally make 'game' a field in your Form1 class, so you can access it anywhere. Just make sure to only retrieve data from Game, and never edit the UI from within Game. Cross-thread operations and whatnot. If you need to, remember to invoke.
everyone. I have been stuck here dealing with this bugs for days, but I still couldn't figure it out.
My guess: I think my code has some problem as I did not dispose the object properly after using it, (I'm not very familiar with these concepts of releasing resources, threading) .
I got these code by taking reference of what people did on youtube, but despite me doing exactly the same thing, my code didn't work out nicely.
SITUATION:
I have two picture boxes, left one can take video of me, right one take the snapshot, if you press button1 , you will start the video, clone_button will copy a image i.e. take a snapshot, and save_image should save it to the path reference, however, i get a generic error occured in GDI+ again and again while I'm trying to save it. Also, my debugger seemed to get crazy (i.e. failed to terminate the vshost.exe ) once I ran this program, I have to restart the computer to get my code running again, which is bleak and frustrating.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Drawing.Imaging;
//AForge.Video dll
using AForge.Video;
using AForge.Video.DirectShow;
using AForge.Imaging;
using AForge.Imaging.Filters;
using AForge;
namespace WebCameraCapture
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private FilterInfoCollection CaptureDevice; // list of webcam
private VideoCaptureDevice FinalFrame;
private void Form1_Load(object sender, EventArgs e)
{
CaptureDevice = new FilterInfoCollection(FilterCategory.VideoInputDevice);//constructor
foreach (FilterInfo Device in CaptureDevice)
{
comboBox1.Items.Add(Device.Name);
}
comboBox1.SelectedIndex = 0; // default
FinalFrame = new VideoCaptureDevice();
}
private void button1_Click(object sender, EventArgs e)
{
FinalFrame = new VideoCaptureDevice(CaptureDevice[comboBox1.SelectedIndex].MonikerString);// specified web cam and its filter moniker string
FinalFrame.NewFrame += new NewFrameEventHandler(FinalFrame_NewFrame);// click button event is fired,
FinalFrame.Start();
}
void FinalFrame_NewFrame(object sender, NewFrameEventArgs eventArgs) // must be void so that it can be accessed everywhere.
// New Frame Event Args is an constructor of a class
{
pictureBox1.Image = (Bitmap)eventArgs.Frame.Clone();// clone the bitmap
}
private void From1_CLosing(object sender, EventArgs e)
{
if (FinalFrame.IsRunning==true) FinalFrame.Stop();
}
private void save_Click(object sender, EventArgs e)
{
if (pictureBox2.Image != null)
{
Bitmap varBmp = new Bitmap(pictureBox2.Image);
Bitmap newBitmap = new Bitmap(varBmp);
varBmp.Dispose();
varBmp = null;
varBmp.Save(#"C:\a.png", ImageFormat.Png);
}
else
{ MessageBox.Show("null exception"); }
}
private void clone_Click(object sender, EventArgs e)
{
pictureBox2.Image = (Bitmap)pictureBox1.Image.Clone();
}
}
}
Any AForge.net user can just PRESS the LINK below and try it out. Thanks!
SAMPLE
After having a look at your code, to me it appears that you are disposing of your image right before you save it. Meaning that your program can't save the image, because it doesn't exist anymore. Actually it reads that you've essentially removed the captured image twice, once on dispose, the second when you set it as null.
So if you move the two code segments after the save, it should be working. Granted without using a dialog box to change the name of the file, you'll surely receive an error unless you remove that file after each time it has been created.
private void save_Click(object sender, EventArgs e)
{
if (pictureBox2.Image != null)
{
//Save First
Bitmap varBmp = new Bitmap(pictureBox2.Image);
Bitmap newBitmap = new Bitmap(varBmp);
varBmp.Save(#"C:\a.png", ImageFormat.Png);
//Now Dispose to free the memory
varBmp.Dispose();
varBmp = null;
}
else
{ MessageBox.Show("null exception"); }
}
If you open the task manager, you can watch how much memory your program is soaking up.
Disposing of the memory after you're done using it, gives it back to the system.
You don't have a dispose inside your FinalFrame_NewFrame thread, so when the camera is reading images,
you should see the memory usage continue to climb until you stop the program.
I've added dispose to my thread, putting the memory usage under control, but now I'm debugging my image saves. Because I'm disposing, I can't save the image lol. My program ends up trying to save a null image file and throws the appropriate error.
I'm using a 2nd picurebox just as you are, but using for example, pbox2.image = pbox1.image, doesn't copy the data, it copies the memory location with the image data, so when I dispose pbox1 to free memory, the image data disappears with the memory location.
So, I had the same issue, and it was resolved one, by moving the dispose method, and two, I had to change the path, it didnt want to save to C:, so I put it on my desktop, you may not have had this issue if you were running as admin but I did so for anyone else who sees this, dont save to the root of C:.
I'm trying to create an example program and I'm having issues creating the Bitmap needed for it. When I try running the code below I'm getting an ArgumentException.
I think this is being thrown because it cannot find the file on the disk. If this is the case where do I put the file in my project so it can find it? I've tried putting the file in the main project directory and have tried placing it within the debug and release folders.
If this is not what is causing the issue can someone point me in the right direction?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Drawing;
namespace Given
{
public class Photo : Form
{
Image image;
public Photo()
{
image = new Bitmap("jug.jpg"); // ArgumentException thrown here
this.Text = "Lemonade";
this.Paint += new PaintEventHandler(Drawer);
}
public virtual void Drawer(Object source, PaintEventArgs e)
{
e.Graphics.DrawImage(image, 30, 20);
}
}
}
namespace Photo_Decorator
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Given.Photo());
}
}
}
It's throwing this because it can't find the JPG, and therefore can't create a proper bitmap object. You need to either place the image file in the same folder as the EXE (Debug? Release?), or specify the entire path to the image (e.g C:/jug.jpg). Hope this helps :)
You'd need to put the file in the same folder as the executable (bin\Debug or bin\Release). You could place it in the bin folder and just use #"..\jug.jpg" as the path instead so it worked in both Debug and Release modes.