1
+ #import " SSYAlertSounder.h"
2
+ #import < AudioToolbox/AudioServices.h>
3
+ #import " NSBundle+MainApp.h"
4
+ #import " SSY_ARC_OR_NO_ARC.h"
5
+
6
+
7
+ static SSYAlertSounder* static_sharedSounder = nil ;
8
+
9
+ @interface SSYAlertSounder ()
10
+
11
+ @end
12
+
13
+ @implementation SSYAlertSounder
14
+
15
+ - (id )init {
16
+ self = [super init ] ;
17
+ if (self) {
18
+ m_soundIds = [[NSMutableDictionary alloc ] init ] ;
19
+ }
20
+
21
+ return self ;
22
+ }
23
+
24
+ - (void )dealloc {
25
+ for (NSNumber * soundId in [m_soundIds allValues ]) {
26
+ AudioServicesDisposeSystemSoundID ((unsigned int )[soundId longValue ]) ;
27
+ }
28
+
29
+ #if NO_ARC
30
+ [m_soundIds release ] ;
31
+
32
+ [super dealloc ] ;
33
+ #endif
34
+ }
35
+
36
+ - (NSMutableDictionary *)soundIds {
37
+ return m_soundIds ;
38
+ }
39
+
40
+
41
+ + (SSYAlertSounder*)sharedSounder {
42
+ @synchronized (self) {
43
+ if (!static_sharedSounder) {
44
+ static_sharedSounder = [[self alloc ] init ] ;
45
+ }
46
+ }
47
+
48
+ // No autorelease. This sticks around forever.
49
+ return static_sharedSounder ;
50
+ }
51
+
52
+ - (SystemSoundID)soundIdForPath : (NSString *)path
53
+ rememberAs : (NSString *)name {
54
+ SystemSoundID soundId = 0 ;
55
+
56
+ if (path) {
57
+ CFURLRef url = (__bridge CFURLRef )[NSURL fileURLWithPath: path] ;
58
+ if (url) {
59
+ OSStatus err ;
60
+ err = AudioServicesCreateSystemSoundID (url, &soundId) ;
61
+
62
+ if (err) {
63
+ // This will happen if file was not found.
64
+ soundId = 0 ;
65
+ }
66
+ else {
67
+ [[self soundIds ] setObject: [NSNumber numberWithLong: soundId]
68
+ forKey: name] ;
69
+ }
70
+ }
71
+ }
72
+
73
+ return soundId ;
74
+ }
75
+
76
+ - (NSArray *)availableSoundsSorted {
77
+ NSString * const type = @" aiff" ;
78
+ NSMutableArray * paths = [[NSMutableArray alloc ] init ] ;
79
+ NSString * path ;
80
+ NSArray * morePaths ;
81
+
82
+ morePaths = [[NSBundle mainAppBundle ] pathsForResourcesOfType: type
83
+ inDirectory: nil ] ;
84
+ [paths addObjectsFromArray: morePaths] ;
85
+
86
+ path = [NSHomeDirectory () stringByAppendingPathComponent: @" Library/Sounds" ] ;
87
+ morePaths = [[NSFileManager defaultManager ] contentsOfDirectoryAtPath: path
88
+ error: NULL ] ;
89
+ [paths addObjectsFromArray: morePaths] ;
90
+
91
+ path = @" /System/Library/Sounds" ;
92
+ morePaths = [[NSFileManager defaultManager ] contentsOfDirectoryAtPath: path
93
+ error: NULL ] ;
94
+ [paths addObjectsFromArray: morePaths] ;
95
+
96
+ NSMutableArray * names = [[NSMutableArray alloc ] init ] ;
97
+ for (NSString * path in paths) {
98
+ NSString * name = [[path lastPathComponent ] stringByDeletingPathExtension ] ;
99
+ if ([[path pathExtension ] isEqualToString: type]) {
100
+ [names addObject: name] ;
101
+ }
102
+ }
103
+
104
+ [names sortUsingComparator: ^NSComparisonResult (NSString * s1, NSString * s2) {
105
+ return [s1 localizedCaseInsensitiveCompare: s2] ;
106
+ }] ;
107
+
108
+ NSArray * answer = [names copy ] ;
109
+
110
+ #if NO_ARC
111
+ [paths release ] ;
112
+ [names release ] ;
113
+ [answer autorelease ] ;
114
+ #endif
115
+
116
+ return answer ;
117
+ }
118
+
119
+
120
+ - (void )playAlertSoundNamed : (NSString *)name {
121
+ if (!name) {
122
+ return ;
123
+ }
124
+
125
+ // First, see if we've got this sound cached
126
+ SystemSoundID soundId = (SystemSoundID)[[[self soundIds ] objectForKey: name] longValue ] ;
127
+ // Used -longValue because SystemSoundID is a UInt32
128
+
129
+ NSString * path ;
130
+
131
+ // If not found, look in the current application's bundle
132
+ if (!soundId) {
133
+ path = [[NSBundle mainAppBundle ] pathForResource: name
134
+ ofType: @" aiff" ] ;
135
+
136
+ soundId = [self soundIdForPath: path
137
+ rememberAs: name] ;
138
+ // If not found, look in current user's library
139
+ if (!soundId) {
140
+ path = [NSHomeDirectory () stringByAppendingPathComponent: @" Library/Sounds" ] ;
141
+ path = [path stringByAppendingPathComponent: [name stringByAppendingPathExtension: @" aiff" ]] ;
142
+
143
+ soundId = [self soundIdForPath: path
144
+ rememberAs: name] ;
145
+
146
+ // If not found, look in system's library
147
+ if (!soundId) {
148
+ path = @" /System/Library/Sounds" ;
149
+ path = [path stringByAppendingPathComponent: [name stringByAppendingPathExtension: @" aiff" ]] ;
150
+
151
+ soundId = [self soundIdForPath: path
152
+ rememberAs: name] ;
153
+ }
154
+ }
155
+ }
156
+
157
+ if (soundId) {
158
+ AudioServicesPlayAlertSound (soundId) ;
159
+ }
160
+ else {
161
+ NSBeep () ;
162
+ }
163
+ }
164
+
165
+ @end
0 commit comments