/// <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> /// Remove the "SoundManager" sound scheme from registry /// </summary> public static void Uninstall() { string currentScheme = RegCurrentUser.OpenSubKey(RegSchemes).GetValue(null) as string; if (currentScheme == SchemeManager) { Apply(GetSchemeDefault(), true); } RegistryKey apps = RegCurrentUser.OpenSubKey(RegApps); foreach (string appName in apps.GetSubKeyNames()) { RegistryKey app = apps.OpenSubKey(appName); foreach (string soundName in app.GetSubKeyNames()) { RegistryKey sound = app.OpenSubKey(soundName, true); if (sound.OpenSubKey(SchemeManager) != null) { sound.DeleteSubKey(SchemeManager); } sound.Close(); } } if (RegCurrentUser.OpenSubKey(RegNames + SchemeManager) != null) { RegCurrentUser.DeleteSubKey(RegNames + SchemeManager); } //Windows 7 : Also restore imageres.dll when removing sound scheme try { if (ImageresPatcher.IsWindowsVista7 && FileSystemAdmin.IsAdmin()) { ImageresPatcher.Restore(); } } catch (FileNotFoundException) { /* No imageres backup to restore */ } catch (UnauthorizedAccessException) { /* Insufficient privileges or file locked */ } }
// ============================ // // == 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> /// 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); } }