Localization not getting right sound - c#

I have three resx files for three languages, Resources.resx, Resources.en-gb.resx and Resources.de-de.resx . When i change the locale all the strings do translate, but the sound files do not. I have the right sound files in the right resx files.
Changing the locale:
SelectedLanguage = locale;
Resources.Culture = new CultureInfo(locale);
With locale being a string like "en-gb".
Getting the audio file:
SoundPlayer _player = new SoundPlayer(Resources.Alarm);
When in change the language i want to get the sound file with the right language instead of the one from the default Resources.resx file.

Related

absolute sound path to work in other machines

I am using the following code:
SoundPlayer soundPlay = new SoundPlayer(#"C:\more\more\Assets\Sounds\menuHoover.mp3");
soundPlay.Play();
when clicking in a button to reproduce a sound, but I have to use the absolute path to works, since I am not the only one doing working on this project, I have to use a poth comon to others too. How can I use the relative path to make this work?
I have tried diferent paths, but none seems to work. Only the absolute one.
You may include the file as Embedded Resource into your executable. Then there is no need to distrubute the file separately.
To access the sound resource, use Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("<Namespace>.menuHoover.mp3"); and initialize the SoundPlayer as new SoundPlayer(stream);
What to put in <Namespace>? Have a look in the project properties at "Default namespace". Suppose this is A.B.C. This would be the Namespace if you add the mp3 file at the root directory of the project. If you add it to a sub-directory, say X\Y\Z, the namespace would be A.B.C.X.Y.Z (special rules apply if the directory name contains characters not allowed in an identifier). See also Name of embedded resource
You have several options one is to add the location of the assets to a configuration file such as app.config
For example you could add to your app.config file:
<configuration>
<appSettings>
<add key="AssetPath" value="C:\\more\\more\\Assets\\Sounds\\"/>
</appSettings>
</configuration>
Then in your code you could use something like:
string assetPath = ConfigurationManager.AppSettings["AssetPath"];
SoundPlayer soundPlay = new SoundPlayer(Path.Combine(assetPath,"menuHoover.mp3");
soundPlay.Play();
Another would be to build a path dynamically based on where your application was executed from and then build a relative path from that:
string appDirectory = AppDomain.CurrentDomain.BaseDirectory;
string assetPath = Path.Combine(appDirectory,"Assets","Sounds");
SoundPlayer soundPlay = new SoundPlayer(Path.Combine(assetPath,"menuHoover.mp3");
soundPlay.Play();

playing of .wav file

I am making a piano app, where each key plays a different .wav file. For instance, if the C note is pressed then C.wav is played.
So far I have only managed to play a wav file using the code in the screenshot, otherwise the file is not found. However this method is not suitable for what I am trying to do. The wav file i am trying to play is called hello.wav and I have provided the location. Any suggestions?
This is the current code:
SoundPlayer sp = new SoundPlayer(PianoApp.Properties.Resources.Hello);
sp.Play();
or as it appears in my IDE:
This is the file location:
I,
Add you your file .wav in ressource of your project with mySoundFile as name, and code like this
Stream str = Properties.Resources.mySoundFile;
SoundPlayer snd = new SoundPlayer(str);
snd.Play();
with multiple .wav ressources
Stream str1 = Properties.Resources.mySoundFile1;
Stream str2 = Properties.Resources.mySoundFile2;
RecordPlayer rp = new RecordPlayer();
rp.Open(new WaveReader(str1));
rp.Play();
rp.Open(new WaveReader(str2));
rp.Play();
If your problem is to find your files in the output folder of your application, then just set the "Copy to Output Directory" option to "Copy always" in the Properties window.
But if you want to keep them in resources, then you can also use Properties.Resources.ResourceManager.GetStream("audioResourceName") to get your audio files according to a particular key name that was pressed. Thus, you should name all your resources accordingly.

.resx form icon cascade updates

Suppose that we have a Windows Form, Form1, for which we have set an icon. Visual Studio will store the icon in Form1.resx ($this.Icon).
Now we decide to localize the application into N languages, so we set Localizable to True, we pick the first language from the Language option, we translate the texts and we continue with the next language repeating the procedure (pick another and translate) up to N. The result will be N .resx files containing the $this.Icon entry with the original icon.
Then we realize we want to update the form icon, so we set Language to "(Default)" and we set the new icon. To our surprise, we discover that the N .resx files were not updated.
Do we have to update the N .resx files manually? Is there something like cascade updates? What would you do in this case to avoid updating N icons?
I just added code to my Program.Main to modify all solution .resx files to remove Form.Icon.
try
{
string solutionDirPath = #"path\to\solution";
string[] resxFilePaths = Directory.GetFiles(solutionDirPath, "*.resx", SearchOption.AllDirectories);
foreach (string resxFilePath in resxFilePaths)
{
XDocument xdoc = XDocument.Load(resxFilePath);
var iconElement = xdoc.Root.Elements("data").SingleOrDefault(el => (string)el.Attribute("name") == "$this.Icon");
if (iconElement != null)
{
iconElement.Remove();
xdoc.Save(resxFilePath);
}
}
}
catch (Exception ex)
{
}
finally
{
}
And my bin size reduced almost twice!
Also for all forms I just will use icon from my app executable
Icon.ExtractAssociatedIcon(Application.ExecutablePath)
Honestly there is no reason to have the same icon in every resx.
ResX files cascade based on language, from the most specific language resource to the least.
If you remove the icon from all your resx files excepting your default, that icon will always be used.
If you wanted a different icon for a particular language, you would simply add the different icon to that resx file.
You can see this easily yourself. Add a label to your form, and populate it based on the value of a key called 'test' (You can do this with a call to 'GetLocalResourceObject("test")' in your code).
Add the key-value pair 'test'-'Hello' to your resx file. Let's say your resx is called 'foo.resx'. In a language-specific file (such as 'foo.fr.resx') add 'test'-'Bonjour'. If you run your program in any non-French language, you will see 'Hello', but if you switch to French you will see 'Bonjour'.
It will work the same way with your icon - you can set it in the base resx, and it will show up for every language. You can then override it in a different resource file.

playing .wav file with C#

I'm trying to play a .Wav file thats located in a folder inside my project.
The sound file is located on "Resource/Sounds/slot_roll_on.Wav"
The resource folder is a folder I created myself, in the root of the project.
This is the code I'm using to run the .wav file
Assembly a = Assembly.GetExecutingAssembly();
Stream s = a.GetManifestResourceStream("kisscam.g.resources.Resources.Sounds.slot_roll_on.wav");
SoundPlayer snd = new SoundPlayer(s);
snd.Play();
I couldn't get the sound to play, I keep getting the windows sound for sound not found.
Somewhere on stack overflow I found this code to find what the right assembly path should be.
Assembly a = Assembly.GetExecutingAssembly();
string[] resourceNames = Assembly.GetExecutingAssembly().GetManifestResourceNames();
int i;
for (i = 0; i < resourceNames.Length; i++)
{
MessageBox.Show(resourceNames[i]);
}
It output these 2 paths
kisscam.Properties.Resources.resources
and
kissscam.g.resources
I tried using them both, but none of them works.
Anyone know what I'm doing wrong ?
Add your Wav file to resources by going to your Project Properties --> Resources Select Audio and Browse to the file. You will then be able to see it as part pf Propeties.Resources. It will add it to a Resources Folder where you can set it to embedded or leave it as is, which is set as content
Accessed like this
private void button1_Click(object sender, EventArgs e)
{
SoundPlayer snd = new SoundPlayer( Properties.Resources.tada);
snd.Play();
}
If you want to add music in your program by playing your .wav file in projects. Then you have to add the .wav file like this.
using System.Media; // write down it at the top of the FORM
SoundPlayer my_wave_file = new SoundPlayer("F:/SOund wave file/airplanefly.wav");
my_wave_file.PlaySync(); // PlaySync means that once sound start then no other activity if form will occur untill sound goes to finish
Remember that you have to write the path of the file with forward slashes (/) format, don't use back slashes () during giving a path to the file, otherwise you will get an error
Currently I know two ways to do so, see below:
Use file path
First put the file in the root folder of the project, then no matter you run the program under Debug or Release mode, the file can both be accessed for sure. Next use the class SoundPlayer to paly it.
var basePath = System.AppDomain.CurrentDomain.BaseDirectory;
SoundPlayer player = new SoundPlayer();
player.SoundLocation = Path.Combine(basePath, #"./../../Reminder.wav");
player.Load();
player.Play();
Use resource
Follow below animate, add "Exsiting file" to the project.
SoundPlayer player = new SoundPlayer(Properties.Resources.Reminder);
player.Play();
The strength of this way compared to the other is:
Only the folder "Release" under the "bin" directory need to be copy when run the program.

Resourcemanager is returning same resource, although CultureInfo is specified

A very simple thing, and I can't get it to work. I want to globalise my dll thus I'm using resource files + the ResourceManager.
I call the resourcemanager like this:
var p = new ResourceManager("Appname.Default", Assembly.GetExecutingAssembly());
Get the strings like this
System.Diagnostics.Debug.WriteLine(p.GetString("greeting"));
System.Diagnostics.Debug.WriteLine(p.GetString("greeting", new CultureInfo("nl")));
System.Diagnostics.Debug.WriteLine(p.GetString("greeting", new CultureInfo("nl-NL")));
System.Diagnostics.Debug.WriteLine(p.GetString("greeting", new CultureInfo("en")));
And it returns 4 times the same string. My files are called
Default.resx
Default.en.resx
Default.nl.resx
Default.nl-NL.resx
All file settings are the same, but as mentioned - only the resource in the Default file is used.
What am I overlooking here?
There are a few ways of using resource files, one of which is using .resx files. These files get localized automatically, based on the value of Thread.CurrentThread.CurrentUICulture. The default .resx file gets compiled into the assembly it is part of (for example your main executable), while the localized resources (Default.nl-NL.resx) get compiled into their own directory (based on the culture identifier, nl-NL in this case) into an assembly, called <AssemblyName>.resources.dll.
Addressing values from those resources is as easy as <ResourceName>.<KeyName>, for example Default.Greeting. To test it, you change the culture, using:
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-US");
Console.WriteLine(Default.Greeting);
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("nl-NL");
Console.WriteLine(Default.Greeting);
Which will output
Hello
Hallo
On program startup, the UI Culture is set to the culture of the computer it's running on, so you won't have to specify the language yourself to always present the localized resources. So, .resx files seem the way to go.
When using the ResourceManager from var p = new ResourceManager("Appname.Default", Assembly.GetExecutingAssembly());, you will have to read .resources files. If there is no (in your case) Appname.Default.resources file, the p.GetString will fail. So I guess you have created one .resources file earlier, but haven't converted the localized .resx files to .resources files.
If you want to use the ResourceManager to be able to specify the culture, you can use:
Default.ResourceManager.GetString("Greeting", new CultureInfo("en-US"));

Categories