1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxSound class implementation: optional
8 // Copyright: (c) Ryan Norton
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "sound.h"
16 #include "wx/object.h"
17 #include "wx/string.h"
23 #include "wx/cocoa/autorelease.h"
24 #include "wx/cocoa/string.h"
26 #import <AppKit/AppKit.h>
29 // NB: Vaclav's new wxSound API is really tricky -
30 // Basically, we need to make sure that if the wxSound
31 // object is still in scope we don't release it's NSSound
34 WX_NSSound lastSound=NULL;
35 bool isLastSoundLooping = false;
36 bool isLastSoundInScope = false;
38 // ========================================================================
40 // ========================================================================
41 @interface wxNSSoundDelegate : NSObject
46 - (void)sound:(NSSound *)theSound didFinishPlaying:(BOOL)bOK;
47 @end // interface wxNSSoundDelegate : NSObject
49 @implementation wxNSSoundDelegate : NSObject
51 - (void)sound:(NSSound *)theSound didFinishPlaying:(BOOL)bOK
53 if (bOK && isLastSoundLooping)
55 else if (!isLastSoundInScope)
61 @end // wxNSSoundDelegate
63 const wxObjcAutoRefFromAlloc<struct objc_object*> wxSound::sm_cocoaDelegate = [[wxNSSoundDelegate alloc] init];
65 // ------------------------------------------------------------------
67 // ------------------------------------------------------------------
75 wxSound::wxSound(const wxString& sFileName, bool isResource)
79 Create(sFileName, isResource);
82 wxSound::wxSound(int size, const wxByte* data)
86 NSData* theData = [[NSData alloc] dataWithBytesNoCopy:(void*)data length:size];
87 m_cocoaNSSound = [[NSSound alloc] initWithData:theData];
93 if (m_cocoaNSSound != lastSound)
95 [m_cocoaNSSound release];
98 isLastSoundInScope = false;
101 bool wxSound::Create(const wxString& fileName, bool isResource)
103 wxAutoNSAutoreleasePool thePool;
109 //oftype could be @"snd" @"wav" or @"aiff"; nil or @"" autodetects (?)
110 m_cocoaNSSound = [[NSSound alloc]
111 initWithContentsOfFile:[[NSBundle mainBundle]
112 pathForResource:wxNSStringWithWxString(fileName)
117 m_cocoaNSSound = [[NSSound alloc] initWithContentsOfFile:wxNSStringWithWxString(fileName) byReference:YES];
119 m_sndname = fileName;
120 return m_cocoaNSSound;
123 bool wxSound::DoPlay(unsigned flags) const
125 wxASSERT_MSG(!( (flags & wxSOUND_SYNC) && (flags & wxSOUND_LOOP)),
126 wxT("Invalid flag combination passed to wxSound::Play"));
130 if (flags & wxSOUND_ASYNC)
132 lastSound = m_cocoaNSSound;
133 isLastSoundLooping = (flags & wxSOUND_LOOP) == wxSOUND_LOOP;
134 isLastSoundInScope = true;
135 [m_cocoaNSSound setDelegate:sm_cocoaDelegate];
136 return [m_cocoaNSSound play];
140 [m_cocoaNSSound setDelegate:nil];
143 bool bOK = [m_cocoaNSSound play];
145 while ([m_cocoaNSSound isPlaying])
147 wxTheApp->Yield(false);
153 bool wxSound::IsPlaying()
155 return [lastSound isPlaying];
160 if (isLastSoundInScope)
162 isLastSoundInScope = false;
164 //remember that even though we're
165 //programatically stopping it, the
166 //delegate will still be called -
167 //so it will free the memory here
168 [((NSSound*&)lastSound) stop];