2
// SystemSound.cs: AudioServices system sound
4
4
// Authors: Mono Team
5
// Marek Safar (marek.safar@gmail.com)
6
7
// Copyright 2009 Novell, Inc
8
// Copyright 2012 Xamarin Inc.
8
10
// Permission is hereby granted, free of charge, to any person obtaining
9
11
// a copy of this software and associated documentation files (the
29
31
using System.Runtime.InteropServices;
31
33
using MonoMac.Foundation;
34
using MonoMac.CoreFoundation;
32
35
using MonoMac.ObjCRuntime;
34
37
namespace MonoMac.AudioToolbox {
36
enum AudioServiceErrors {
38
UnsupportedProperty = 0x7074793f, // 'pty?'
39
BadPropertySize = 0x2173697a, // '!siz'
40
BadSpecifierSize = 0x21737063, // '!spc'
41
SystemSoundUnspecified = -1500,
42
SystemSoundClientTimedOut = -1501,
45
delegate void SystemSoundCompletionCallback (uint ssID, IntPtr clientData);
47
39
enum SystemSoundId : uint {
48
40
Vibrate = 0x00000FFF,
51
43
public class SystemSound : INativeObject, IDisposable {
53
47
public static readonly SystemSound Vibrate = new SystemSound ((uint) SystemSoundId.Vibrate, false);
53
Action completionRoutine;
55
static readonly Action<SystemSoundId, IntPtr> SoundCompletionCallback = SoundCompletionShared;
58
57
internal SystemSound (uint soundId, bool ownsHandle)
60
59
this.soundId = soundId;
75
public bool IsUISound {
77
uint out_size = sizeof (uint);
80
var res = AudioServices.AudioServicesGetProperty (AudioServicesPropertyKey.IsUISound, sizeof (AudioServicesPropertyKey), ref soundId, out out_size, out data);
81
if (res != AudioServicesError.None)
82
throw new ArgumentException (res.ToString ());
88
uint data = value ? (uint)1 : 0;
90
var res = AudioServices.AudioServicesSetProperty (AudioServicesPropertyKey.IsUISound, sizeof (AudioServicesPropertyKey), ref soundId, sizeof (uint), ref data);
91
if (res != AudioServicesError.None)
92
throw new ArgumentException (res.ToString ());
96
public bool CompletePlaybackIfAppDies {
98
uint out_size = sizeof (uint);
101
var res = AudioServices.AudioServicesGetProperty (AudioServicesPropertyKey.CompletePlaybackIfAppDies, sizeof (AudioServicesPropertyKey), ref soundId, out out_size, out data);
102
if (res != AudioServicesError.None)
103
throw new ArgumentException (res.ToString ());
109
uint data = value ? (uint)1 : 0;
111
var res = AudioServices.AudioServicesSetProperty (AudioServicesPropertyKey.CompletePlaybackIfAppDies, sizeof (AudioServicesPropertyKey), ref soundId, sizeof (uint), ref data);
112
if (res != AudioServicesError.None)
113
throw new ArgumentException (res.ToString ());
76
117
void AssertNotDisposed ()
93
134
[DllImport (Constants.AudioToolboxLibrary)]
94
static extern AudioServiceErrors AudioServicesDisposeSystemSoundID (uint soundId);
135
static extern AudioServicesError AudioServicesDisposeSystemSoundID (uint soundId);
96
137
void Cleanup (bool checkForError)
98
139
if (soundId == 0 || !ownsHandle)
142
if (gc_handle.IsAllocated) {
146
if (completionRoutine != null) {
147
RemoveSystemSoundCompletion ();
100
150
var error = AudioServicesDisposeSystemSoundID (soundId);
101
151
var oldId = soundId;
103
if (checkForError && error != AudioServiceErrors.None) {
153
if (checkForError && error != AudioServicesError.None) {
104
154
throw new InvalidOperationException (string.Format ("Error while disposing SystemSound with ID {0}: {1}",
105
155
oldId, error.ToString()));
130
180
[DllImport (Constants.AudioToolboxLibrary)]
131
static extern AudioServiceErrors AudioServicesCreateSystemSoundID (IntPtr fileUrl, out uint soundId);
181
static extern AudioServicesError AudioServicesCreateSystemSoundID (IntPtr fileUrl, out uint soundId);
133
183
public SystemSound (NSUrl fileUrl)
135
185
var error = AudioServicesCreateSystemSoundID (fileUrl.Handle, out soundId);
136
if (error != AudioServiceErrors.None)
186
if (error != AudioServicesError.None)
137
187
throw new InvalidOperationException (string.Format ("Could not create system sound ID for url {0}; error={1}",
138
188
fileUrl, error));
139
189
ownsHandle = true;
145
195
var error = AudioServicesCreateSystemSoundID (fileUrl.Handle, out soundId);
146
if (error != AudioServiceErrors.None)
196
if (error != AudioServicesError.None)
148
198
return new SystemSound (soundId, true);
153
203
using (var url = new NSUrl (filename)){
155
205
var error = AudioServicesCreateSystemSoundID (url.Handle, out soundId);
156
if (error != AudioServiceErrors.None)
206
if (error != AudioServicesError.None)
158
208
return new SystemSound (soundId, true);
212
[DllImport (Constants.AudioToolboxLibrary)]
213
static extern AudioServicesError AudioServicesAddSystemSoundCompletion (uint soundId, IntPtr runLoop, IntPtr runLoopMode, Action<SystemSoundId, IntPtr> completionRoutine, IntPtr clientData);
215
[MonoPInvokeCallback (typeof (Action<SystemSoundId, IntPtr>))]
216
static void SoundCompletionShared (SystemSoundId id, IntPtr clientData)
218
GCHandle gch = GCHandle.FromIntPtr (clientData);
219
var ss = (SystemSound) gch.Target;
221
ss.completionRoutine ();
224
public AudioServicesError AddSystemSoundCompletion (Action routine, CFRunLoop runLoop = null)
226
if (gc_handle.IsAllocated)
227
throw new ArgumentException ("Only single completion routine is supported");
229
gc_handle = GCHandle.Alloc (this);
230
completionRoutine = routine;
232
return AudioServicesAddSystemSoundCompletion (soundId,
233
runLoop == null ? IntPtr.Zero : runLoop.Handle,
234
IntPtr.Zero, // runLoopMode should be enum runLoopMode == null ? IntPtr.Zero : runLoopMode.Handle,
235
SoundCompletionCallback, GCHandle.ToIntPtr (gc_handle));
238
[DllImport (Constants.AudioToolboxLibrary)]
239
static extern void AudioServicesRemoveSystemSoundCompletion (uint soundId);
241
public void RemoveSystemSoundCompletion ()
243
completionRoutine = null;
244
AudioServicesRemoveSystemSoundCompletion (soundId);