@@ -8,12 +8,95 @@ namespace ManagedShell.Common.Helpers
88 public class SoundHelper
99 {
1010 private const string SYSTEM_SOUND_ROOT_KEY = @"AppEvents\Schemes\Apps" ;
11- private const int SND_FILENAME = 0x00020000 ;
12- private const int SND_ASYNC = 0x0001 ;
13- private const long SND_SYSTEM = 0x00200000L ;
11+
12+ /// <summary>
13+ /// Flag values for playing the sound.
14+ /// </summary>
15+ [ Flags ]
16+ public enum SND : uint
17+ {
18+ /// <summary>
19+ /// The sound is played synchronously; PlaySound returns after the sound event completes (default behavior).
20+ /// </summary>
21+ SYNC = 0x0000 ,
22+
23+ /// <summary>
24+ /// The sound is played asynchronously; PlaySound returns immediately after initiating the sound.
25+ /// To stop an asynchronously played sound, call PlaySound with pszSound set to NULL.
26+ /// </summary>
27+ ASYNC = 0x00000001 ,
28+
29+ /// <summary>
30+ /// No default sound event is used. If the sound is not found, PlaySound returns without playing a sound.
31+ /// </summary>
32+ NODEFAULT = 0x00000002 ,
33+
34+ /// <summary>
35+ /// The pszSound parameter points to a sound loaded in memory.
36+ /// </summary>
37+ MEMORY = 0x00000004 ,
38+
39+ /// <summary>
40+ /// The sound plays repeatedly until PlaySound is called with pszSound set to NULL.
41+ /// Use the ASYNC flag with LOOP.
42+ /// </summary>
43+ LOOP = 0x00000008 ,
44+
45+ /// <summary>
46+ /// The specified sound event will yield to another sound event already playing in the same process.
47+ /// If the required resource is busy, the function returns immediately without playing the sound.
48+ /// </summary>
49+ NOSTOP = 0x00000010 ,
50+
51+ /// <summary>
52+ /// The pszSound parameter is a system-event alias from the registry or WIN.INI file.
53+ /// Do not use with FILENAME or RESOURCE.
54+ /// </summary>
55+ ALIAS = 0x00010000 ,
56+
57+ /// <summary>
58+ /// The pszSound parameter is a predefined identifier for a system-event alias.
59+ /// </summary>
60+ ALIAS_ID = 0x00110000 ,
61+
62+ /// <summary>
63+ /// The pszSound parameter is a file name. If the file is not found, the default sound is played unless NODEFAULT is set.
64+ /// </summary>
65+ FILENAME = 0x00020000 ,
66+
67+ /// <summary>
68+ /// The pszSound parameter is a resource identifier; hmod must identify the instance that contains the resource.
69+ /// </summary>
70+ RESOURCE = 0x00040004 ,
71+
72+ /// <summary>
73+ /// The pszSound parameter is an application-specific alias in the registry.
74+ /// Can be combined with ALIAS or ALIAS_ID to specify an application-defined sound alias.
75+ /// </summary>
76+ APPLICATION = 0x00000080 ,
77+
78+ /// <summary>
79+ /// Requires Windows Vista or later. If set, triggers a SoundSentry event when the sound is played,
80+ /// providing a visual cue for accessibility.
81+ /// </summary>
82+ SENTRY = 0x00080000 ,
83+
84+ /// <summary>
85+ /// Treats the sound as a ring from a communications app.
86+ /// </summary>
87+ RING = 0x00100000 ,
88+
89+ /// <summary>
90+ /// Requires Windows Vista or later. If set, the sound is assigned to the audio session for system notification sounds,
91+ /// allowing control via the system volume slider. Otherwise, it is assigned to the application's default audio session.
92+ /// </summary>
93+ SYSTEM = 0x00200000 ,
94+ }
95+
96+ private const SND DEFAULT_SYSTEM_SOUND_FLAGS = SND . ASYNC | SND . NODEFAULT | SND . SYSTEM ;
1497
1598 [ DllImport ( "winmm.dll" , SetLastError = true , CharSet = CharSet . Auto ) ]
16- private static extern bool PlaySound ( string pszSound , IntPtr hmod , uint fdwSound ) ;
99+ public static extern bool PlaySound ( string pszSound , IntPtr hmod , SND soundFlags ) ;
17100
18101 /// <summary>
19102 /// Plays the specified system sound using the audio session for system notification sounds.
@@ -24,34 +107,42 @@ public static bool PlaySystemSound(string app, string name)
24107 {
25108 try
26109 {
27- using ( RegistryKey key = Registry . CurrentUser . OpenSubKey ( $ "{ SYSTEM_SOUND_ROOT_KEY } \\ { app } \\ { name } \\ .Current") )
110+ using var key = Registry . CurrentUser . OpenSubKey ( $@ "{ SYSTEM_SOUND_ROOT_KEY } \{ app } \{ name } \.Current") ;
111+ if ( key == null )
112+ {
113+ ShellLogger . Debug ( $ "SoundHelper: Unable to find sound { name } for app { app } ") ;
114+ return false ;
115+ }
116+
117+ var soundFileName = key . GetValue ( null ) as string ;
118+ if ( string . IsNullOrEmpty ( soundFileName ) )
28119 {
29- if ( key == null )
30- {
31- ShellLogger . Error ( $ "SoundHelper: Unable to find sound { name } for app { app } ") ;
32- return false ;
33- }
34-
35- if ( key . GetValue ( null ) is string soundFileName )
36- {
37- if ( string . IsNullOrEmpty ( soundFileName ) )
38- {
39- ShellLogger . Error ( $ "SoundHelper: Missing file for sound { name } for app { app } ") ;
40- return false ;
41- }
42-
43- return PlaySound ( soundFileName , IntPtr . Zero , ( uint ) ( SND_ASYNC | SND_FILENAME | SND_SYSTEM ) ) ;
44- }
45- else
46- {
47- ShellLogger . Error ( $ "SoundHelper: Missing file for sound { name } for app { app } ") ;
48- return false ;
49- }
120+ ShellLogger . Debug ( $ "SoundHelper: Missing file for sound { name } for app { app } ") ;
121+ return false ;
50122 }
123+
124+ return PlaySound ( soundFileName , IntPtr . Zero , DEFAULT_SYSTEM_SOUND_FLAGS | SND . FILENAME ) ;
51125 }
52126 catch ( Exception e )
53127 {
54- ShellLogger . Error ( $ "SoundHelper: Unable to play sound { name } for app { app } : { e . Message } ") ;
128+ ShellLogger . Debug ( $ "SoundHelper: Unable to play sound { name } for app { app } : { e . Message } ") ;
129+ return false ;
130+ }
131+ }
132+
133+ /// <summary>
134+ /// Plays the specified system sound using the audio session for system notification sounds.
135+ /// </summary>
136+ /// <param name="alias">The name of the system sound for ".Default" to play.</param>
137+ public static bool PlaySystemSound ( string alias )
138+ {
139+ try
140+ {
141+ return PlaySound ( alias , IntPtr . Zero , DEFAULT_SYSTEM_SOUND_FLAGS | SND . ALIAS ) ;
142+ }
143+ catch ( Exception e )
144+ {
145+ ShellLogger . Debug ( $ "SoundHelper: Unable to play sound { alias } : { e . Message } ") ;
55146 return false ;
56147 }
57148 }
@@ -62,24 +153,22 @@ public static bool PlaySystemSound(string app, string name)
62153 public static void PlayNotificationSound ( )
63154 {
64155 // System default sound for the classic notification balloon.
65- if ( ! PlaySystemSound ( "Explorer" , "SystemNotification" ) )
156+ if ( PlaySystemSound ( "Explorer" , "SystemNotification" ) ) return ;
157+ if ( EnvironmentHelper . IsWindows8OrBetter )
66158 {
67- if ( EnvironmentHelper . IsWindows8OrBetter )
68- {
69- // Toast notification sound.
70- if ( ! PlaySystemSound ( ".Default" , "Notification.Default" ) )
71- PlayXPNotificationSound ( ) ;
72- }
73- else
74- {
159+ // Toast notification sound.
160+ if ( ! PlaySystemSound ( "Notification.Default" ) )
75161 PlayXPNotificationSound ( ) ;
76- }
162+ }
163+ else
164+ {
165+ PlayXPNotificationSound ( ) ;
77166 }
78167 }
79168
80- public static bool PlayXPNotificationSound ( )
169+ public static void PlayXPNotificationSound ( )
81170 {
82- return PlaySystemSound ( ".Default" , "SystemNotification" ) ;
171+ PlaySystemSound ( "SystemNotification" ) ;
83172 }
84173 }
85174}
0 commit comments