/// <summary> /// Import the specified Zip file into the SoundManager sound scheme /// </summary> /// <param name="zipfile">Input Zip file</param> public static void Import(string zipfile) { using (ZipFile zip = ZipFile.Read(zipfile)) { foreach (SoundEvent soundEvent in SoundEvent.GetAll()) { if (TryExtract(zip, soundEvent.FileName, SoundEvent.DataDirectory) || TryExtract(zip, soundEvent.LegacyFileName, SoundEvent.DataDirectory, soundEvent.FileName)) { SoundScheme.Update(soundEvent, soundEvent.FilePath); } else { SoundScheme.Remove(soundEvent); } } SchemeMeta.ResetAll(); if (!TryExtract(zip, Path.GetFileName(SchemeMeta.SchemeImageFilePath), SoundEvent.DataDirectory)) { TryExtract(zip, "visuel.bmp", SoundEvent.DataDirectory, Path.GetFileName(SchemeMeta.SchemeImageFilePath)); } if (!TryExtract(zip, Path.GetFileName(SchemeMeta.SchemeInfoFilePath), SoundEvent.DataDirectory)) { TryExtract(zip, "infos.ini", SoundEvent.DataDirectory, Path.GetFileName(SchemeMeta.SchemeInfoFilePath)); } SchemeMeta.ReloadFromDisk(); SoundScheme.Apply(SoundScheme.GetSchemeSoundManager(), Settings.MissingSoundUseDefault); } }
/// <summary> /// Show sound event file in Windows Explorer /// </summary> private void soundContextMenu_OpenLocation_Click(object sender, EventArgs e) { if (soundList.FocusedItem != null) { SoundEvent soundEvent = soundList.FocusedItem.Tag as SoundEvent; try { if (File.Exists(soundEvent.FilePath)) { Process.Start("explorer", "/select, \"" + soundEvent.FilePath + '"'); } else { Process.Start("explorer", '"' + SoundEvent.DataDirectory + '"'); } } catch (Exception browseException) { MessageBox.Show( Translations.Get("browse_failed_text") + '\n' + browseException.Message, Translations.Get("browse_failed_title"), MessageBoxButtons.OK, MessageBoxIcon.Error ); } } }
/// <summary> /// Setup will create and apply the SoundManager sound scheme, create data directory /// </summary> /// <param name="forceResetSounds">Also reset all sounds to their default values</param> /// <param name="systemIntegration">Also setup maximum system integration</param> public static void Setup(bool forceResetSounds, bool systemIntegration) { bool createDataDir = !Directory.Exists(DataFolder); if (createDataDir) { Directory.CreateDirectory(DataFolder); } SoundScheme.Setup(); if (forceResetSounds || createDataDir) { foreach (SoundEvent soundEvent in SoundEvent.GetAll()) { SoundScheme.CopyDefault(soundEvent); } } SoundScheme.Apply(SoundScheme.GetSchemeSoundManager(), true); if (systemIntegration) { SoundArchive.AssocFiles(); if (BgSoundPlayer.RequiredForThisWindowsVersion) { BgSoundPlayer.RegisteredForStartup = true; Process.Start(Application.ExecutablePath, ArgumentBgSoundPlayer); } } }
/// <summary> /// Remove a sound event /// </summary> private void soundContextMenu_Remove_Click(object sender, EventArgs e) { if (soundList.FocusedItem != null) { SoundEvent soundEvent = soundList.FocusedItem.Tag as SoundEvent; SoundScheme.Remove(soundEvent); } }
/// <summary> /// Reset a sound event to the default system sound /// </summary> private void soundContextMenu_Reset_Click(object sender, EventArgs e) { if (soundList.FocusedItem != null) { SoundEvent soundEvent = soundList.FocusedItem.Tag as SoundEvent; SoundScheme.CopyDefault(soundEvent); soundContextMenu_Play_Click(sender, e); } }
/// <summary> /// Instantiate a new Background Sound Player. /// Will play the startup/logon sound and create a hidden window, which is required by the ShutdownBlockReason API. /// </summary> public BgSoundPlayer() { this.Text = Program.DisplayName; this.Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath); this.FormBorderStyle = FormBorderStyle.FixedToolWindow; this.ShowInTaskbar = false; this.StartPosition = FormStartPosition.Manual; this.Location = new System.Drawing.Point(-2000, -2000); this.Size = new System.Drawing.Size(1, 1); foreach (SoundEvent soundEvent in SoundEvent.GetAll()) { switch (soundEvent.FileName.Replace(".wav", "").ToLower()) { case "startup": soundStartup = soundEvent; break; case "shutdown": soundShutdown = soundEvent; break; case "logon": soundLogon = soundEvent; break; case "logoff": soundLogoff = soundEvent; break; } } string bootTime = GetBootTimestamp().ToString(); bootTime = bootTime.Substring(0, bootTime.Length - 1) + '0'; string lastBootTime = ""; if (File.Exists(LastBootFile)) { lastBootTime = File.ReadAllText(LastBootFile); } if (bootTime != lastBootTime && File.Exists(soundStartup.FilePath)) { File.WriteAllText(LastBootFile, bootTime); PlaySound(soundStartup); } else { PlaySound(soundLogon); } SystemEvents.SessionEnding += new SessionEndingEventHandler(SystemEvents_SessionEnding); SystemEvents.SessionSwitch += new SessionSwitchEventHandler(SystemEvents_SessionSwitch); }
/// <summary> /// Dropping a file /// </summary> void window_DragDrop(object sender, DragEventArgs e) { if (mainTabs.SelectedIndex == 0) { string[] files = (e.Data.GetData(DataFormats.FileDrop) as string[] ?? new string[] { }); if (files.Length > 0) { try { Image.FromFile(files[0]); changeSchemeThumbnail(files[0]); } catch { if (Path.GetExtension(files[0]).ToLower().Trim('.') == SoundArchive.FileExtension) { if (MessageBox.Show( String.Concat(Translations.Get("scheme_load_prompt_text"), '\n', Path.GetFileName(files[0])), Translations.Get("scheme_load_prompt_title"), MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { ImportSoundScheme(files[0]); } } else if (soundList.SelectedItems.Count > 0) { SoundEvent soundEvent = soundList.SelectedItems[0].Tag as SoundEvent; if (MessageBox.Show( Translations.Get("drag_drop_sound_confirm_text") + '\n' + soundEvent.DisplayName, Translations.Get("drag_drop_sound_confirm_title"), MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { replaceSoundEvent(soundEvent, files[0]); } } else { MessageBox.Show( Translations.Get("drag_drop_no_target_sound_text"), Translations.Get("drag_drop_no_target_sound_title"), MessageBoxButtons.OK, MessageBoxIcon.Information ); } } } } }
/// <summary> /// Play the specified system event sound. /// The sound currently associated with the event is played, which is not necessarily from the SoundManager scheme. /// </summary> /// <param name="soundEvent">System event to play</param> private static void PlaySound(SoundEvent soundEvent) { if (soundEvent != null) { string soundFile = SoundScheme.GetCurrentFile(soundEvent); if (soundFile != null && File.Exists(soundFile)) { try { new SoundPlayer(soundFile).PlaySync(); } catch (InvalidOperationException) { /* Invalid WAV file */ } } } }
/// <summary> /// Replace a sound event /// </summary> private void soundContextMenu_Change_Click(object sender, EventArgs e) { if (soundList.FocusedItem != null) { SoundEvent soundEvent = soundList.FocusedItem.Tag as SoundEvent; OpenFileDialog dlg = new OpenFileDialog(); dlg.Filter = Translations.Get(SoundScheme.CanConvertSounds ? "browse_media_files" : "browse_wave_files") + (SoundScheme.CanConvertSounds ? "|*.wav;*.mp3;*.wma;*.ogg;*.aac;*.cda;*.m4a;*.flac;*.ac3;*.dts;*.mp4;*.avi;*.wmv;*.mkv;*.flv" : "|*.wav"); if (dlg.ShowDialog() == DialogResult.OK) { replaceSoundEvent(soundEvent, dlg.FileName); } } }
/// <summary> /// Replace the sound file associated with the specified sound event /// </summary> private void replaceSoundEvent(SoundEvent soundEvent, string soundFile) { try { SoundScheme.Update(soundEvent, soundFile); soundContextMenu_Play_Click(this, EventArgs.Empty); SoundScheme.Apply(SoundScheme.GetSchemeSoundManager(), Settings.MissingSoundUseDefault); } catch (Exception loadException) { MessageBox.Show( Translations.Get("sound_load_failed_text") + '\n' + loadException.Message, Translations.Get("sound_load_failed_title"), MessageBoxButtons.OK, MessageBoxIcon.Error ); } }
/// <summary> /// Copy default sound from the specified sound scheme to the SoundManager sound scheme /// </summary> /// <param name="source">If not specified, sounds are copied from the default sound sheme</param> public static void CopyDefault(SoundEvent soundEvent, SoundScheme source = null) { bool defaultFileFound = false; string originalScheme = SchemeDefault; if (source != null) { originalScheme = source.internalName; } foreach (string registryKey in soundEvent.RegistryKeys) { RegistryKey defaultSoundKey = RegCurrentUser.OpenSubKey(RegApps + registryKey + '\\' + originalScheme); string defaultSoundPath = null; if (defaultSoundKey != null) { defaultSoundPath = Environment.ExpandEnvironmentVariables(defaultSoundKey.GetValue(null) as string ?? ""); } if (!Directory.Exists(Path.GetDirectoryName(soundEvent.FilePath))) { Directory.CreateDirectory(Path.GetDirectoryName(soundEvent.FilePath)); } if (File.Exists(defaultSoundPath)) { Update(soundEvent, defaultSoundPath); defaultFileFound = true; } } if (soundEvent.Imageres && ImageresPatcher.IsWindowsVista7) { if (FileSystemAdmin.IsAdmin()) { ImageresPatcher.Restore(); } ImageresPatcher.ExtractDefault(soundEvent.FilePath); } else if (!defaultFileFound) { Remove(soundEvent); } }
/// <summary> /// Play a sound event /// </summary> private void soundContextMenu_Play_Click(object sender, EventArgs e) { if (soundList.FocusedItem != null) { SoundEvent soundEvent = soundList.FocusedItem.Tag as SoundEvent; if (File.Exists(soundEvent.FilePath)) { try { System.Media.SoundPlayer player = new System.Media.SoundPlayer(soundEvent.FilePath); player.Play(); } catch (InvalidOperationException) { //Not a WAV file File.Delete(soundEvent.FilePath); } } } }
/// <summary> /// Get sound file path for the specified event from registry. /// Will return file path for the currently applied sound scheme, which is not necessarily the SoundManager sound scheme. /// </summary> /// <param name="soundEvent">SoundEvent to query</param> /// <returns>Sound file path or NULL if no file was found</returns> public static string GetCurrentFile(SoundEvent soundEvent) { if (soundEvent != null) { foreach (string registryKey in soundEvent.RegistryKeys) { RegistryKey currentSoundKey = RegCurrentUser.OpenSubKey(RegApps + registryKey + '\\' + SchemeCurrent); string currentSoundPath = null; if (currentSoundKey != null) { currentSoundPath = Environment.ExpandEnvironmentVariables(currentSoundKey.GetValue(null) as string ?? ""); } if (currentSoundPath != null && File.Exists(currentSoundPath)) { return(currentSoundPath); } } } return(null); }
/// <summary> /// Export the SoundManager sound scheme to the specified Zip file /// </summary> /// <param name="zipfile">Output Zip file</param> public static void Export(string zipfile) { using (ZipFile zip = new ZipFile()) { foreach (SoundEvent soundEvent in SoundEvent.GetAll()) { if (File.Exists(soundEvent.FilePath)) { zip.AddFile(soundEvent.FilePath, ""); } } if (File.Exists(SchemeMeta.SchemeImageFilePath)) { zip.AddFile(SchemeMeta.SchemeImageFilePath, ""); } if (File.Exists(SchemeMeta.SchemeInfoFilePath)) { zip.AddFile(SchemeMeta.SchemeInfoFilePath, ""); } zip.Save(zipfile); } }
/// <summary> /// Reset all sound events to the specified system sound sheme /// </summary> private void loadSystemScheme(bool warning, SoundScheme scheme) { if (!warning || MessageBox.Show( Translations.Get("reset_warn_text"), Translations.Get("reset_warn_title"), MessageBoxButtons.OKCancel, MessageBoxIcon.Warning ) == DialogResult.OK) { foreach (SoundEvent soundEvent in SoundEvent.GetAll()) { SoundScheme.CopyDefault(soundEvent, scheme); } SchemeMeta.ResetAll(); if (scheme != null) { SchemeMeta.Name = scheme.ToString(); SchemeMeta.Author = ""; SchemeMeta.About = ""; } RefreshSchemeMetadata(); imageContextMenu_Remove_Click(this, EventArgs.Empty); } }
// ============================ // // == Sound sheme management == // // ============================ // /// <summary> /// Create the "SoundManager" sound scheme in registry /// </summary> public static void Setup() { RegistryKey name = RegCurrentUser.CreateSubKey(RegNames + SchemeManager); name.SetValue(null, Program.DisplayName); name.Close(); foreach (SoundEvent soundEvent in SoundEvent.GetAll()) { foreach (string registryKey in soundEvent.RegistryKeys) { string eventKeyPath = RegApps + registryKey + '\\' + SchemeManager; RegistryKey eventKey = RegCurrentUser.OpenSubKey(eventKeyPath, true) ?? RegCurrentUser.CreateSubKey(eventKeyPath); eventKey.SetValue(null, soundEvent.FilePath); eventKey.Close(); } } //Windows 7 : Also backup imageres.dll when creating sound scheme if (ImageresPatcher.IsWindowsVista7 && FileSystemAdmin.IsAdmin()) { ImageresPatcher.Backup(); } }
/// <summary> /// Initialize window contents /// </summary> public FormMain(string importFile = null) { InitializeComponent(); // Icon and translations this.Text = Program.DisplayName; this.Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath); tabPageScheme.Text = Translations.Get("tab_current_scheme"); tabPageSettings.Text = Translations.Get("tab_settings"); soundImageText.Text = Translations.Get("no_image"); soundInfoNameText.Text = Translations.Get("meta_name"); soundInfoAuthorText.Text = Translations.Get("meta_author"); soundInfoAboutText.Text = Translations.Get("meta_about"); buttonOpen.Text = Translations.Get("button_open"); buttonImport.Text = Translations.Get("button_import"); buttonExport.Text = Translations.Get("button_export"); buttonReset.Text = Translations.Get("button_reset"); buttonExit.Text = Translations.Get("button_exit"); imageContextMenu_Change.Text = Translations.Get("image_change"); imageContextMenu_Remove.Text = Translations.Get("image_remove"); soundContextMenu_Change.Text = Translations.Get("sound_change"); soundContextMenu_OpenLocation.Text = Translations.Get("sound_open_location"); soundContextMenu_Play.Text = Translations.Get("sound_play"); soundContextMenu_Reset.Text = Translations.Get("sound_reset"); soundContextMenu_Remove.Text = Translations.Get("sound_remove"); groupBoxImport.Text = Translations.Get("box_import_system_scheme"); groupBoxSystemIntegration.Text = Translations.Get("box_system_integration"); checkBoxPatchImageres.Text = Translations.Get("check_box_imageres_patch"); checkBoxBgSoundPlayer.Text = Translations.Get("check_box_bg_sound_player"); checkBoxFileAssoc.Text = Translations.Get("check_box_file_assoc"); checkBoxMissingSoundsUseDefault.Text = Translations.Get("check_box_reset_missing_on_load"); groupBoxMaintenance.Text = Translations.Get("box_maintenance"); buttonReinstall.Text = Translations.Get("button_reinstall"); buttonUninstall.Text = Translations.Get("button_uninstall"); tabPageAbout.Text = Translations.Get("tab_about"); labelProgramName.Text = Program.DisplayName; labelProgramVersionAuthor.Text = "Version " + Program.Version + " - By ORelio"; labelTranslationAuthor.Text = Translations.Get("translation_author"); labelProgramDescription.Text = Translations.Get("app_desc"); buttonHelp.Text = Translations.Get("button_help"); buttonWebsite.Text = Translations.Get("button_website"); groupBoxSystemInfo.Text = Translations.Get("box_system_info"); // System information labelSystemInfo.Text = String.Format( "{0} / Windows NT {1}.{2}", WindowsVersion.FriendlyName, WindowsVersion.WinMajorVersion, WindowsVersion.WinMinorVersion ); labelSystemSupportStatus.Text = WindowsVersion.IsBetween(Program.WindowsVersionMin, Program.WindowsVersionMax) ? Translations.Get("supported_system_version") : Translations.Get("unsupported_system_version"); // Load UI settings checkBoxPatchImageres.Enabled = ImageresPatcher.IsWindowsVista7; checkBoxPatchImageres.Checked = ImageresPatcher.IsWindowsVista7 && Settings.WinVista7PatchEnabled; checkBoxPatchImageres.CheckedChanged += new System.EventHandler(this.checkBoxPatchImageres_CheckedChanged); checkBoxBgSoundPlayer.Enabled = BgSoundPlayer.RequiredForThisWindowsVersion; checkBoxBgSoundPlayer.Checked = BgSoundPlayer.RequiredForThisWindowsVersion && BgSoundPlayer.RegisteredForStartup; checkBoxBgSoundPlayer.CheckedChanged += new EventHandler(checkBoxBgSoundPlayer_CheckedChanged); checkBoxMissingSoundsUseDefault.Checked = Settings.MissingSoundUseDefault; checkBoxMissingSoundsUseDefault.CheckedChanged += new EventHandler(checkBoxMissingSoundsUseDefault_CheckedChanged); checkBoxFileAssoc.Checked = SoundArchive.FileAssociation; checkBoxFileAssoc.CheckedChanged += new System.EventHandler(this.checkBoxFileAssoc_CheckedChanged); // Image and scheme info RefreshSchemeMetadata(); // Sound event list soundList.View = View.LargeIcon; soundList.MultiSelect = false; soundList.LargeImageList = new ImageList(); soundList.LargeImageList.ImageSize = new Size(32, 32); soundList.ShowItemToolTips = true; foreach (SoundEvent soundEvent in SoundEvent.GetAll()) { string iconName = Path.GetFileNameWithoutExtension(soundEvent.FileName); Bitmap icon = soundIcons.GetObject(iconName, SoundManager.SoundIcons.Culture) as Bitmap; if (icon != null) { soundList.LargeImageList.Images.Add(iconName, icon); } ListViewItem item = soundList.Items.Add(soundEvent.DisplayName); item.ToolTipText = soundEvent.Description; item.ImageKey = iconName; item.Tag = soundEvent; } // Load system sound schemes list foreach (SoundScheme scheme in SoundScheme.GetSchemeList()) { if (scheme.ToString() != Program.DisplayName && scheme.ToString() != ".None") { comboBoxSystemSchemes.Items.Add(scheme); } } if (comboBoxSystemSchemes.Items.Count > 0) { comboBoxSystemSchemes.SelectedIndex = 0; } // Auto-import sound scheme passed as program argument if (importFile != null && File.Exists(importFile)) { if (MessageBox.Show( String.Concat(Translations.Get("scheme_load_prompt_text"), '\n', Path.GetFileName(importFile)), Translations.Get("scheme_load_prompt_title"), MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { ImportSoundScheme(importFile); foreach (Process process in Process.GetProcessesByName(Path.GetFileNameWithoutExtension(Application.ExecutablePath))) { if (process.Id != Process.GetCurrentProcess().Id&& process.MainWindowTitle == this.Text) { process.CloseMainWindow(); } } } else { Environment.Exit(0); } } }
/// <summary> /// Remove the sound associated with a sound event from the SoundManager sound scheme /// </summary> /// <param name="soundEvent">Sound event to remove</param> public static void Remove(SoundEvent soundEvent) { Update(soundEvent, null); }
/// <summary> /// Update the sound event with a new sound file in the SoundManager sound scheme /// </summary> /// <param name="soundEvent">Sound event to update</param> /// <param name="soundFile">New sound file. Null value or non-existing file has the same effect as calling Remove().</param> /// <remarks>If soundFile is set to soundEvent.FilePath, the sound file is not updated but triggers additional steps such as refreshing imageres.dll</remarks> public static void Update(SoundEvent soundEvent, string soundFile) { if (soundFile != soundEvent.FilePath) { if (File.Exists(soundFile)) { MediaFoundationReader soundReader = null; if (CanConvertSounds) { soundReader = new MediaFoundationReader(soundFile); } if (CanConvertSounds && soundReader.TotalTime > TimeSpan.FromSeconds(30)) { throw new InvalidOperationException(Translations.Get("sound_file_too_long")); } else { try { // Check for WAV format by trying to play it and directly copy the WAV file SoundPlayer player = new SoundPlayer(soundFile); player.Play(); player.Stop(); File.Copy(soundFile, soundEvent.FilePath, true); } catch (InvalidOperationException playException) { if (CanConvertSounds) { // Transcode non-native input file formats into WAV format that Windows can play using (WaveStream pcm = WaveFormatConversionStream.CreatePcmStream(soundReader)) { try { WaveFileWriter.CreateWaveFile(soundEvent.FilePath, pcm); } catch { File.Delete(soundEvent.FilePath); throw; } } } else { File.Delete(soundEvent.FilePath); throw playException; } } } if (soundReader != null) { soundReader.Dispose(); } } else { File.Delete(soundEvent.FilePath); } } //Windows 7 : Also patch imageres.dll when updating startup sound if (soundEvent.Imageres && ImageresPatcher.IsWindowsVista7 && FileSystemAdmin.IsAdmin()) { ImageresPatcher.Patch(soundEvent.FilePath); } //Windows 10 : Also make sure file read access is set for All Application Packages, otherwise UWP UI parts will not be able to play the sound event if (File.Exists(soundEvent.FilePath) && WindowsVersion.WinMajorVersion >= 10) { FileInfo fileInfo = new FileInfo(soundEvent.FilePath); FileSecurity fileSecurity = fileInfo.GetAccessControl(); fileSecurity.AddAccessRule(new FileSystemAccessRule(new SecurityIdentifier("S-1-15-2-1"), FileSystemRights.ReadAndExecute, AccessControlType.Allow)); fileInfo.SetAccessControl(fileSecurity); } }