To support playing async sounds on the stack on Mac, do not delete the wxSoundData...
[wxWidgets.git] / src / osx / sound_osx.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/sound_osx.cpp
3 // Purpose: wxSound class common osx code
4 // Author: Stefan Csomor
5 // Modified by:
6 // Created: 2009-09-01
7 // RCS-ID: $Id: sound.cpp 61475 2009-07-20 16:47:54Z VZ $
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #if wxUSE_SOUND
16
17 #include "wx/sound.h"
18
19 #ifndef WX_PRECOMP
20 #include "wx/object.h"
21 #include "wx/string.h"
22 #include "wx/intl.h"
23 #include "wx/log.h"
24 #include "wx/timer.h"
25 #endif
26
27 #include "wx/file.h"
28
29 #include "wx/vector.h"
30
31 class wxSoundTimer : public wxTimer
32 {
33 public:
34 wxSoundTimer(wxSoundData* snd)
35 : m_sound(snd)
36 {
37 }
38
39 virtual ~wxSoundTimer()
40 {
41 Stop();
42 if (m_sound)
43 m_sound->DoStop();
44 }
45
46 void Notify()
47 {
48 if (m_sound)
49 m_sound->SoundTask();
50 }
51
52 protected:
53 wxSoundData* m_sound;
54 };
55
56 wxVector<wxSoundData*> s_soundsPlaying;
57
58 wxSoundData::wxSoundData()
59 {
60 m_pTimer = NULL;
61 m_markedForDeletion = false;
62 }
63
64 wxSoundData::~wxSoundData()
65 {
66 }
67
68 void wxSoundData::MarkForDeletion()
69 {
70 m_markedForDeletion = true;
71 }
72
73 void wxSoundData::Stop()
74 {
75 DoStop();
76 if ( m_pTimer )
77 {
78 delete m_pTimer;
79 m_pTimer = NULL;
80 }
81 }
82
83 //Time between timer calls
84 #define MOVIE_DELAY 100
85
86 void wxSoundData::SoundTask()
87 {
88 }
89
90 void wxSoundData::CreateAndStartTimer()
91 {
92 //Start timer and play movie asyncronously
93 m_pTimer = new wxSoundTimer(this);
94 m_pTimer->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS);
95 }
96
97 wxSound::wxSound()
98 {
99 Init();
100 }
101
102 wxSound::wxSound(const wxString& sFileName, bool isResource)
103 {
104 Init();
105 Create(sFileName, isResource);
106 }
107
108 wxSound::wxSound(int size, const wxByte* data)
109 {
110 Init();
111 Create( size, data );
112 }
113
114 wxSound::~wxSound()
115 {
116 // if the sound is in a playing state, just mark it to be deleted and
117 // delete it after it plays. Otherwise, async sounds created on the stack
118 // may never get the chance to play.
119 bool isPlaying = false;
120 for ( wxVector<wxSoundData*>::reverse_iterator s = s_soundsPlaying.rbegin();
121 s != s_soundsPlaying.rend(); ++s )
122 {
123 if (*s == m_data)
124 {
125 isPlaying = true;
126 break;
127 }
128 }
129
130 if (isPlaying)
131 m_data->MarkForDeletion();
132 else
133 delete m_data;
134 }
135
136 void wxSound::Init()
137 {
138 m_data = NULL;
139 }
140
141 bool wxSound::DoPlay(unsigned flags) const
142 {
143 if ( m_data )
144 {
145 s_soundsPlaying.push_back(m_data);
146 if ( !m_data->Play(flags) )
147 s_soundsPlaying.pop_back();
148 }
149
150 return false;
151 }
152
153 bool wxSound::IsPlaying()
154 {
155 return s_soundsPlaying.size() > 0;
156 }
157
158 void wxSound::Stop()
159 {
160 for ( wxVector<wxSoundData*>::reverse_iterator s = s_soundsPlaying.rbegin();
161 s != s_soundsPlaying.rend(); ++s )
162 {
163 (*s)->Stop();
164 }
165 }
166
167 // Notification when a sound has stopped
168 void wxSound::SoundStopped(const wxSoundData* data)
169 {
170 for ( wxVector<wxSoundData*>::iterator s = s_soundsPlaying.begin();
171 s != s_soundsPlaying.end(); ++s )
172 {
173 if ( (*s) == data )
174 {
175 s_soundsPlaying.erase(s);
176 break;
177 }
178 }
179 }
180
181 #endif //wxUSE_SOUND