Peter Hosey avatar Peter Hosey committed 033e8fb

Switched over to the remodeled Audio Toolbox version of the System Sound API. Fixes #70 and suppresses a few deprecated-API warnings.

Comments (0)

Files changed (3)

Core/Source/GrowlApplicationController.h

 	CFRunLoopTimerRef			updateTimer;
 
 	NSThread					*mainThread;
-
-	SystemSoundCompletionUPP	soundCompletionCallback;
 }
 
 + (GrowlApplicationController *) sharedController;

Core/Source/GrowlApplicationController.m

 #include "CFMutableDictionaryAdditions.h"
 #include "cdsa.h"
 #include <SystemConfiguration/SystemConfiguration.h>
+#include <AudioToolbox/AudioToolbox.h>
 #include <sys/errno.h>
 #include <string.h>
 #include <sys/socket.h>
 #define USER_WENT_IDLE_NOTIFICATION		@"User went idle"
 #define USER_RETURNED_NOTIFICATION		@"User returned"
 
-static OSStatus soundCompletionCallbackProc(SystemSoundActionID actionID, void *refcon);
+static void soundCompletionCallbackProc(SystemSoundID soundID, void *refcon);
 
 extern CFRunLoopRef CFRunLoopGetMain(void);
 
 		[growlNotificationCenterConnection setRootObject:growlNotificationCenter];
 		if (![growlNotificationCenterConnection registerName:@"GrowlNotificationCenter"])
 			NSLog(@"WARNING: could not register GrowlNotificationCenter for interprocess access");
-
-		soundCompletionCallback = NewSystemSoundCompletionUPP(soundCompletionCallbackProc);
 	}
 
 	return self;
 
 	cdsaShutdown();
 	
-	DisposeSystemSoundCompletionUPP(soundCompletionCallback);
-
 	[super destroy];
 }
 
 
 	return err;
 }
+- (OSStatus) getURL:(out NSURL **)outURL forSoundNamed:(NSString *)soundName {
+	FSRef ref;
+	OSStatus err = [self getFSRef:&ref forSoundNamed:soundName];
+	if (err == noErr) {
+		CFURLRef CFURL = CFURLCreateFromFSRef(kCFAllocatorDefault, &ref);
+		NSURL *URL = [NSMakeCollectable(CFURL) autorelease];
+		if (outURL != NULL)
+			*outURL = URL;
+		if (!URL)
+			err = errFSBadFSRef; //For lack of any more specific knowledge.
+	}
+	return err;
+}
 
 #pragma mark Dispatching notifications
 
 			NSError *error = nil;
 			NSDictionary *userInfo;
 
-			FSRef soundRef;
-			OSStatus err = [self getFSRef:&soundRef forSoundNamed:soundName];
+			NSURL *soundURL;
+			OSStatus err = [self getURL:&soundURL forSoundNamed:soundName];
 			if (err == noErr) {
-				SystemSoundActionID actionID;
-				err = SystemSoundGetActionID(&soundRef, &actionID);
-				if (err == noErr) {
-					err = SystemSoundSetCompletionRoutine(actionID, CFRunLoopGetCurrent(), /*runLoopMode*/ NULL, soundCompletionCallback, /*refcon*/ NULL);
-					SystemSoundPlay(actionID);
+				SystemSoundID soundID;
+				err = AudioServicesCreateSystemSoundID((CFURLRef)soundURL, &soundID);
+				if (err == kAudioServicesNoError) {
+					err = AudioServicesAddSystemSoundCompletion(soundID, CFRunLoopGetCurrent(), /*runLoopMode*/ NULL, soundCompletionCallbackProc, /*refcon*/ NULL);
+
+					//GCH ticket #70: Since the user set up this sound, we should play it regardless of the system's UI-sounds preference.
+					UInt32 shouldBeSubjectToUISoundsPref = false;
+					err = AudioServicesSetProperty(kAudioServicesPropertyIsUISound, sizeof(soundID), &soundID, sizeof(shouldBeSubjectToUISoundsPref), &shouldBeSubjectToUISoundsPref);
+
+					AudioServicesPlaySystemSound(soundID);
 					userInfo = nil;
 				} else {
 					userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
 
 @end
 
-static OSStatus soundCompletionCallbackProc(SystemSoundActionID actionID, void *refcon) 
+static void soundCompletionCallbackProc(SystemSoundID soundID, void *refcon) 
 {
 #pragma unused(refcon)
 
-	SystemSoundRemoveCompletionRoutine(actionID);
+	AudioServicesRemoveSystemSoundCompletion(soundID);
 
-	return SystemSoundRemoveActionID(actionID);
+	AudioServicesDisposeSystemSoundID(soundID);
 }

Growl.xcodeproj/project.pbxproj

 		0A7F62600767C84E00E1C1E4 /* GrowlMusicVideoWindowView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A7F62570767C84E00E1C1E4 /* GrowlMusicVideoWindowView.m */; };
 		0AEE179D0702C4960024B1A0 /* ApplicationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0AEE179C0702C4960024B1A0 /* ApplicationServices.framework */; };
 		31340CDD0D5B8E7100B9BEE0 /* GrowlPropertyListFilePathway.m in Sources */ = {isa = PBXBuildFile; fileRef = 31340CDB0D5B8E7100B9BEE0 /* GrowlPropertyListFilePathway.m */; };
+		317ED5CC12CFCB7F00263CFC /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 317ED5CB12CFCB7F00263CFC /* AudioToolbox.framework */; };
 		318984C5108825F10086E973 /* TestVersionUnparsing.m in Sources */ = {isa = PBXBuildFile; fileRef = 318984C4108825F10086E973 /* TestVersionUnparsing.m */; };
 		31B9BA5C1086C4CA007DA1E2 /* TestVersionComparisonBetweenStringsConverting1_0To0_5.m in Sources */ = {isa = PBXBuildFile; fileRef = 31B9BA5B1086C4CA007DA1E2 /* TestVersionComparisonBetweenStringsConverting1_0To0_5.m */; };
 		31C7594B1047202B008547BF /* simple-mailer.py in Resources */ = {isa = PBXBuildFile; fileRef = 31C7594A1047202B008547BF /* simple-mailer.py */; };
 		31340CDA0D5B8E7100B9BEE0 /* GrowlPropertyListFilePathway.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GrowlPropertyListFilePathway.h; path = Core/Source/GrowlPropertyListFilePathway.h; sourceTree = "<group>"; };
 		31340CDB0D5B8E7100B9BEE0 /* GrowlPropertyListFilePathway.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GrowlPropertyListFilePathway.m; path = Core/Source/GrowlPropertyListFilePathway.m; sourceTree = "<group>"; };
 		315C88BB1068F9A200880530 /* Localization.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Localization.xcconfig; path = xcconfig/Localization.xcconfig; sourceTree = "<group>"; };
+		317ED5CB12CFCB7F00263CFC /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
 		318984C3108825F10086E973 /* TestVersionUnparsing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestVersionUnparsing.h; sourceTree = "<group>"; };
 		318984C4108825F10086E973 /* TestVersionUnparsing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestVersionUnparsing.m; sourceTree = "<group>"; };
 		31B9BA5A1086C4CA007DA1E2 /* TestVersionComparisonBetweenStringsConverting1_0To0_5.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestVersionComparisonBetweenStringsConverting1_0To0_5.h; sourceTree = "<group>"; };
 				95C36A640753299E009FAEA2 /* AppKit.framework in Frameworks */,
 				95AA8654080065DE0045589D /* SystemConfiguration.framework in Frameworks */,
 				93CD92E80B5AFAAE000C39CD /* QuartzCore.framework in Frameworks */,
+				317ED5CC12CFCB7F00263CFC /* AudioToolbox.framework in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 				343354B20792F84B00C84B15 /* Carbon.framework */,
 				93FCE57D0812D93B00320D8E /* SystemUIPlugin.framework */,
 				31E184DF108462F30011C78B /* SenTestingKit.framework */,
+				317ED5CB12CFCB7F00263CFC /* AudioToolbox.framework */,
 			);
 			name = "Linked Frameworks";
 			sourceTree = "<group>";
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.