]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/timer.cpp
Fix so sound looping will stop, courtesy of Ryan Norton.
[wxWidgets.git] / src / mac / carbon / timer.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: timer.cpp
3 // Purpose: wxTimer implementation
4 // Author: Stefan Csomor
5 // Modified by:
6 // Created: 1998-01-01
7 // RCS-ID: $Id$
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "timer.h"
14 #endif
15
16 #include "wx/timer.h"
17
18 #if !USE_SHARED_LIBRARY
19 IMPLEMENT_ABSTRACT_CLASS(wxTimer, wxEvtHandler)
20 #endif
21
22 #ifdef __WXMAC__
23 #include "wx/mac/private.h"
24 #endif
25 #ifndef __DARWIN__
26 #include <Timer.h>
27 #endif
28
29 #include "wx/dynarray.h"
30
31 #define wxMAC_USE_CARBON_TIMER 1
32
33 #if wxMAC_USE_CARBON_TIMER
34
35 typedef struct MacTimerInfo
36 {
37 wxTimer* m_timer ;
38 EventLoopTimerUPP m_proc ;
39 EventLoopTimerRef m_timerRef ;
40 } ;
41
42 static pascal void wxProcessTimer( EventLoopTimerRef theTimer , void *data ) ;
43 static pascal void wxProcessTimer( EventLoopTimerRef theTimer , void *data )
44 {
45 if ( !data )
46 return ;
47
48 wxTimer* timer = (wxTimer*) data ;
49
50 if ( timer->IsOneShot() )
51 timer->Stop() ;
52
53 timer->Notify();
54 }
55
56 void wxTimer::Init()
57 {
58 m_info = new MacTimerInfo() ;
59 m_info->m_timer = this ;
60 m_info->m_proc = NULL ;
61 m_info->m_timerRef = kInvalidID ;
62 }
63
64 bool wxTimer::IsRunning() const
65 {
66 return ( m_info->m_timerRef != kInvalidID ) ;
67 }
68
69 wxTimer::~wxTimer()
70 {
71 Stop();
72 if (m_info != NULL) {
73 delete m_info ;
74 m_info = NULL ;
75 }
76 }
77
78 bool wxTimer::Start(int milliseconds,bool mode)
79 {
80 (void)wxTimerBase::Start(milliseconds, mode);
81
82 wxCHECK_MSG( m_milli > 0, FALSE, wxT("invalid value for timer timeout") );
83 wxCHECK_MSG( m_info->m_timerRef == NULL , FALSE, wxT("attempting to restart a timer") );
84
85 m_info->m_timer = this ;
86 m_info->m_proc = NewEventLoopTimerUPP( &wxProcessTimer);
87 verify_noerr( InstallEventLoopTimer (
88 GetMainEventLoop() ,
89 m_milli*kEventDurationMillisecond,
90 IsOneShot() ? 0 : m_milli*kEventDurationMillisecond ,
91 m_info->m_proc,
92 this,
93 &m_info->m_timerRef) ) ;
94 return TRUE;
95 }
96
97 void wxTimer::Stop()
98 {
99 if (m_info->m_timerRef)
100 RemoveEventLoopTimer( m_info->m_timerRef ) ;
101 if (m_info->m_proc)
102 DisposeEventLoopTimerUPP(m_info->m_proc) ;
103 m_info->m_proc = NULL ;
104 m_info->m_timerRef = kInvalidID ;
105 }
106
107 #else
108
109 typedef struct MacTimerInfo
110 {
111 TMTask m_task;
112 wxMacNotifierTableRef m_table ;
113 wxTimer* m_timer ;
114 } ;
115
116 static void wxProcessTimer( unsigned long event , void *data ) ;
117
118 static pascal void MacTimerProc( TMTask * t )
119 {
120 MacTimerInfo * tm = (MacTimerInfo*) t ;
121 wxMacAddEvent( tm->m_table , wxProcessTimer, 0 , (void*) tm->m_timer , TRUE ) ;
122 }
123
124 // we need this array to track timers that are being deleted within the Notify procedure
125 // adding the timer before the Notify call and checking after whether it still is in there
126 // as the destructor would have removed it from the array
127
128 wxArrayPtrVoid gTimersInProcess ;
129
130 static void wxProcessTimer( unsigned long event , void *data )
131 {
132 if ( !data )
133 return ;
134
135 wxTimer* timer = (wxTimer*) data ;
136
137 if ( timer->IsOneShot() )
138 timer->Stop() ;
139
140 gTimersInProcess.Add( timer ) ;
141
142 timer->Notify();
143
144 int index = gTimersInProcess.Index( timer ) ;
145
146 if ( index != wxNOT_FOUND )
147 {
148 gTimersInProcess.RemoveAt( index ) ;
149
150 if ( !timer->IsOneShot() && timer->m_info->m_task.tmAddr )
151 {
152 PrimeTime( (QElemPtr) &timer->m_info->m_task , timer->GetInterval() ) ;
153 }
154
155 }
156 }
157
158 void wxTimer::Init()
159 {
160 m_info = new MacTimerInfo() ;
161 m_info->m_task.tmAddr = NULL ;
162 m_info->m_task.tmWakeUp = 0 ;
163 m_info->m_task.tmReserved = 0 ;
164 m_info->m_task.qType = 0 ;
165 m_info->m_table = wxMacGetNotifierTable() ;
166 m_info->m_timer = this ;
167 }
168
169 bool wxTimer::IsRunning() const
170 {
171 // as the qType may already indicate it is elapsed, but it
172 // was not handled internally yet
173 return ( m_info->m_task.tmAddr != NULL ) ;
174 }
175
176 wxTimer::~wxTimer()
177 {
178 Stop();
179 if (m_info != NULL) {
180 delete m_info ;
181 m_info = NULL ;
182 }
183 int index = gTimersInProcess.Index( this ) ;
184 if ( index != wxNOT_FOUND )
185 gTimersInProcess.RemoveAt( index ) ;
186 }
187
188 bool wxTimer::Start(int milliseconds,bool mode)
189 {
190 (void)wxTimerBase::Start(milliseconds, mode);
191
192 wxCHECK_MSG( m_milli > 0, FALSE, wxT("invalid value for timer timeout") );
193 wxCHECK_MSG( m_info->m_task.tmAddr == NULL , FALSE, wxT("attempting to restart a timer") );
194
195 m_info->m_task.tmAddr = NewTimerUPP( MacTimerProc ) ;
196 m_info->m_task.tmWakeUp = 0 ;
197 m_info->m_task.tmReserved = 0 ;
198 m_info->m_task.qType = 0 ;
199 m_info->m_timer = this ;
200 InsXTime((QElemPtr) &m_info->m_task ) ;
201 PrimeTime( (QElemPtr) &m_info->m_task , m_milli ) ;
202 return TRUE;
203 }
204
205 void wxTimer::Stop()
206 {
207 if ( m_info->m_task.tmAddr )
208 {
209 RmvTime( (QElemPtr) &m_info->m_task ) ;
210 DisposeTimerUPP(m_info->m_task.tmAddr) ;
211 m_info->m_task.tmAddr = NULL ;
212 }
213 wxMacRemoveAllNotifiersForData( wxMacGetNotifierTable() , this ) ;
214 }
215
216 #endif
217
218