]>
Commit | Line | Data |
---|---|---|
0c0be4a3 RN |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: sound.cpp | |
3 | // Purpose: wxSound class implementation: optional | |
4 | // Author: Ryan Norton | |
5 | // Modified by: | |
6 | // Created: 2004-10-02 | |
7 | // RCS-ID: $Id$ | |
8 | // Copyright: (c) Ryan Norton | |
9 | // Licence: wxWindows licence | |
10 | ///////////////////////////////////////////////////////////////////////////// | |
dcb68102 | 11 | |
0c0be4a3 RN |
12 | #ifdef __GNUG__ |
13 | #pragma implementation "sound.h" | |
14 | #endif | |
15 | ||
16 | #include "wx/object.h" | |
17 | #include "wx/string.h" | |
18 | #include "wx/sound.h" | |
19 | ||
20 | #if wxUSE_SOUND | |
21 | ||
22 | #include "wx/app.h" | |
23 | #include "wx/cocoa/autorelease.h" | |
24 | #include "wx/cocoa/string.h" | |
25 | ||
26 | #import <AppKit/AppKit.h> | |
27 | ||
28 | // | |
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 | |
32 | // | |
33 | ||
34 | WX_NSSound lastSound=NULL; | |
35 | bool isLastSoundLooping = NO; | |
36 | bool isLastSoundInScope = NO; | |
37 | ||
38 | // ======================================================================== | |
39 | // wxNSSoundDelegate | |
40 | // ======================================================================== | |
41 | @interface wxNSSoundDelegate : NSObject | |
42 | { | |
43 | } | |
44 | ||
45 | // Delegate methods | |
46 | - (void)sound:(NSSound *)theSound didFinishPlaying:(BOOL)bOK; | |
47 | @end // interface wxNSSoundDelegate : NSObject | |
48 | ||
49 | @implementation wxNSSoundDelegate : NSObject | |
50 | ||
51 | - (void)sound:(NSSound *)theSound didFinishPlaying:(BOOL)bOK | |
52 | { | |
53 | if (bOK && isLastSoundLooping) | |
54 | [lastSound play]; | |
55 | else if (isLastSoundInScope = NO) | |
56 | { | |
57 | [lastSound release]; | |
58 | [self release]; | |
59 | } | |
60 | } | |
61 | ||
62 | @end // wxNSSoundDelegate | |
63 | ||
64 | // ------------------------------------------------------------------ | |
65 | // wxSound | |
66 | // ------------------------------------------------------------------ | |
67 | ||
68 | wxSound::wxSound() | |
69 | : m_hSnd(NULL), m_waveLength(0) | |
70 | { | |
71 | } | |
72 | ||
73 | wxSound::wxSound(const wxString& sFileName, bool isResource) | |
74 | : m_hSnd(NULL), m_waveLength(0) | |
75 | { | |
76 | Create(sFileName, isResource); | |
77 | } | |
78 | ||
79 | wxSound::wxSound(int size, const wxByte* data) | |
80 | : m_hSnd(NULL), m_waveLength(size) | |
81 | { | |
82 | NSData* theData = [[NSData alloc] dataWithBytesNoCopy:(void*)data length:size]; | |
83 | m_hSnd = [[NSSound alloc] initWithData:theData]; | |
84 | ||
85 | m_cocoaSoundDelegate = [[wxNSSoundDelegate alloc] init]; | |
86 | } | |
87 | ||
88 | wxSound::~wxSound() | |
89 | { | |
90 | if (m_hSnd != lastSound) | |
91 | { | |
92 | [m_hSnd release]; | |
93 | [m_cocoaSoundDelegate release]; | |
94 | } | |
95 | else | |
96 | isLastSoundInScope = NO; | |
97 | } | |
98 | ||
99 | bool wxSound::Create(const wxString& fileName, bool isResource) | |
100 | { | |
101 | wxAutoNSAutoreleasePool thePool; | |
102 | ||
103 | Stop(); | |
104 | ||
105 | if (isResource) | |
106 | { | |
107 | //oftype could be @"snd" @"wav" or @"aiff", nil or @"" autodetects (?) | |
108 | m_hSnd = [[NSSound alloc] initWithContentsOfFile: | |
109 | [[NSBundle mainBundle] pathForResource:wxNSStringWithWxString(fileName) ofType:nil] | |
110 | byReference:NO]; | |
111 | } | |
112 | else | |
113 | m_hSnd = [[NSSound alloc] initWithContentsOfFile:wxNSStringWithWxString(fileName) byReference:YES]; | |
114 | ||
115 | m_cocoaSoundDelegate = [[wxNSSoundDelegate alloc] init]; | |
116 | ||
117 | m_sndname = fileName; | |
118 | return m_hSnd != nil; | |
119 | } | |
120 | ||
121 | bool wxSound::DoPlay(unsigned flags) const | |
122 | { | |
123 | wxASSERT_MSG(!( (flags & wxSOUND_SYNC) && (flags & wxSOUND_LOOP)), | |
124 | wxT("Invalid flag combination passed to wxSound::Play")); | |
125 | ||
126 | Stop(); | |
127 | ||
128 | if (flags & wxSOUND_ASYNC) | |
129 | { | |
130 | lastSound = m_hSnd; | |
131 | isLastSoundLooping = (flags & wxSOUND_LOOP) == wxSOUND_LOOP; | |
132 | isLastSoundInScope = YES; | |
133 | [m_hSnd setDelegate:m_cocoaSoundDelegate]; | |
134 | return [m_hSnd play]; | |
135 | } | |
136 | else | |
137 | { | |
138 | [m_hSnd setDelegate:nil]; | |
139 | ||
140 | //play until done | |
141 | bool bOK = [m_hSnd play]; | |
142 | ||
143 | while ([m_hSnd isPlaying]) | |
144 | { | |
145 | wxTheApp->Yield(false); | |
146 | } | |
147 | return bOK; | |
148 | } | |
149 | } | |
150 | ||
151 | bool wxSound::IsPlaying() | |
152 | { | |
153 | return [lastSound isPlaying]; | |
154 | } | |
155 | ||
156 | void wxSound::Stop() | |
157 | { | |
158 | if (isLastSoundInScope) | |
159 | { | |
160 | isLastSoundInScope = NO; | |
161 | ||
162 | //remember that even though we're | |
163 | //programatically stopping it, the | |
164 | //delegate will still be called - | |
165 | //so it will free the memory here | |
166 | [((NSSound*&)lastSound) stop]; | |
167 | } | |
168 | ||
169 | lastSound = nil; | |
170 | } | |
171 | ||
172 | #endif //wxUSE_SOUND |