-rw-r--r-- | noncore/multimedia/opieplayer2/skin.cpp | 1 | ||||
-rw-r--r-- | noncore/multimedia/opieplayer2/threadutil.cpp | 1 |
2 files changed, 2 insertions, 0 deletions
diff --git a/noncore/multimedia/opieplayer2/skin.cpp b/noncore/multimedia/opieplayer2/skin.cpp index 84f5f87..5d8929e 100644 --- a/noncore/multimedia/opieplayer2/skin.cpp +++ b/noncore/multimedia/opieplayer2/skin.cpp | |||
@@ -1,322 +1,323 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2002 Simon Hausmann <simon@lst.de> | 2 | Copyright (C) 2002 Simon Hausmann <simon@lst.de> |
3 | (C) 2002 Max Reiss <harlekin@handhelds.org> | 3 | (C) 2002 Max Reiss <harlekin@handhelds.org> |
4 | (C) 2002 L. Potter <ljp@llornkcor.com> | 4 | (C) 2002 L. Potter <ljp@llornkcor.com> |
5 | (C) 2002 Holger Freyther <zecke@handhelds.org> | 5 | (C) 2002 Holger Freyther <zecke@handhelds.org> |
6 | 6 | ||
7 | This program is free software; you can redistribute it and/or | 7 | This program is free software; you can redistribute it and/or |
8 | modify it under the terms of the GNU General Public | 8 | modify it under the terms of the GNU General Public |
9 | License as published by the Free Software Foundation; either | 9 | License as published by the Free Software Foundation; either |
10 | version 2 of the License, or (at your option) any later version. | 10 | version 2 of the License, or (at your option) any later version. |
11 | 11 | ||
12 | This program is distributed in the hope that it will be useful, | 12 | This program is distributed in the hope that it will be useful, |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | General Public License for more details. | 15 | General Public License for more details. |
16 | 16 | ||
17 | You should have received a copy of the GNU General Public License | 17 | You should have received a copy of the GNU General Public License |
18 | along with this program; see the file COPYING. If not, write to | 18 | along with this program; see the file COPYING. If not, write to |
19 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 19 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
20 | Boston, MA 02111-1307, USA. | 20 | Boston, MA 02111-1307, USA. |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include "skin.h" | 23 | #include "skin.h" |
24 | #include "singleton.h" | 24 | #include "singleton.h" |
25 | #include <opie2/odebug.h> | ||
25 | 26 | ||
26 | #include <qcache.h> | 27 | #include <qcache.h> |
27 | #include <qtimer.h> | 28 | #include <qtimer.h> |
28 | 29 | ||
29 | #include <qpe/config.h> | 30 | #include <qpe/config.h> |
30 | 31 | ||
31 | #include <assert.h> | 32 | #include <assert.h> |
32 | 33 | ||
33 | struct SkinData | 34 | struct SkinData |
34 | { | 35 | { |
35 | typedef QMap<QString, QImage> ButtonMaskImageMap; | 36 | typedef QMap<QString, QImage> ButtonMaskImageMap; |
36 | 37 | ||
37 | QPixmap backgroundPixmap; | 38 | QPixmap backgroundPixmap; |
38 | QImage buttonUpImage; | 39 | QImage buttonUpImage; |
39 | QImage buttonDownImage; | 40 | QImage buttonDownImage; |
40 | QImage buttonMask; | 41 | QImage buttonMask; |
41 | ButtonMaskImageMap buttonMasks; | 42 | ButtonMaskImageMap buttonMasks; |
42 | }; | 43 | }; |
43 | 44 | ||
44 | class SkinCache : public Singleton<SkinCache> | 45 | class SkinCache : public Singleton<SkinCache> |
45 | { | 46 | { |
46 | public: | 47 | public: |
47 | SkinCache(); | 48 | SkinCache(); |
48 | 49 | ||
49 | SkinData *lookupAndTake( const QString &skinPath, const QString &fileNameInfix ); | 50 | SkinData *lookupAndTake( const QString &skinPath, const QString &fileNameInfix ); |
50 | 51 | ||
51 | void store( const QString &skinPath, const QString &fileNameInfix, SkinData *data ); | 52 | void store( const QString &skinPath, const QString &fileNameInfix, SkinData *data ); |
52 | 53 | ||
53 | private: | 54 | private: |
54 | typedef QCache<SkinData> DataCache; | 55 | typedef QCache<SkinData> DataCache; |
55 | typedef QCache<QPixmap> BackgroundPixmapCache; | 56 | typedef QCache<QPixmap> BackgroundPixmapCache; |
56 | 57 | ||
57 | template <class CacheType> | 58 | template <class CacheType> |
58 | void store( const QCache<CacheType> &cache, const QString &key, CacheType *data ); | 59 | void store( const QCache<CacheType> &cache, const QString &key, CacheType *data ); |
59 | 60 | ||
60 | DataCache m_cache; | 61 | DataCache m_cache; |
61 | BackgroundPixmapCache m_backgroundPixmapCache; | 62 | BackgroundPixmapCache m_backgroundPixmapCache; |
62 | }; | 63 | }; |
63 | 64 | ||
64 | Skin::Skin( const QString &name, const QString &fileNameInfix ) | 65 | Skin::Skin( const QString &name, const QString &fileNameInfix ) |
65 | : m_fileNameInfix( fileNameInfix ) | 66 | : m_fileNameInfix( fileNameInfix ) |
66 | { | 67 | { |
67 | init( name ); | 68 | init( name ); |
68 | } | 69 | } |
69 | 70 | ||
70 | Skin::Skin( const QString &fileNameInfix ) | 71 | Skin::Skin( const QString &fileNameInfix ) |
71 | : m_fileNameInfix( fileNameInfix ) | 72 | : m_fileNameInfix( fileNameInfix ) |
72 | { | 73 | { |
73 | init( defaultSkinName() ); | 74 | init( defaultSkinName() ); |
74 | } | 75 | } |
75 | 76 | ||
76 | Skin::~Skin() | 77 | Skin::~Skin() |
77 | { | 78 | { |
78 | if ( m_isCachable ) | 79 | if ( m_isCachable ) |
79 | SkinCache::self().store( m_skinPath, m_fileNameInfix, d ); | 80 | SkinCache::self().store( m_skinPath, m_fileNameInfix, d ); |
80 | else | 81 | else |
81 | delete d; | 82 | delete d; |
82 | } | 83 | } |
83 | 84 | ||
84 | void Skin::init( const QString &name ) | 85 | void Skin::init( const QString &name ) |
85 | { | 86 | { |
86 | m_isCachable = true; | 87 | m_isCachable = true; |
87 | m_skinPath = "opieplayer2/skins/" + name; | 88 | m_skinPath = "opieplayer2/skins/" + name; |
88 | d = SkinCache::self().lookupAndTake( m_skinPath, m_fileNameInfix ); | 89 | d = SkinCache::self().lookupAndTake( m_skinPath, m_fileNameInfix ); |
89 | } | 90 | } |
90 | 91 | ||
91 | QPixmap Skin::backgroundPixmap() const | 92 | QPixmap Skin::backgroundPixmap() const |
92 | { | 93 | { |
93 | if ( d->backgroundPixmap.isNull() ) | 94 | if ( d->backgroundPixmap.isNull() ) |
94 | d->backgroundPixmap = loadImage( QString( "%1/background" ).arg( m_skinPath ) ); | 95 | d->backgroundPixmap = loadImage( QString( "%1/background" ).arg( m_skinPath ) ); |
95 | return d->backgroundPixmap; | 96 | return d->backgroundPixmap; |
96 | } | 97 | } |
97 | 98 | ||
98 | QImage Skin::buttonUpImage() const | 99 | QImage Skin::buttonUpImage() const |
99 | { | 100 | { |
100 | if ( d->buttonUpImage.isNull() ) | 101 | if ( d->buttonUpImage.isNull() ) |
101 | d->buttonUpImage = loadImage( QString( "%1/skin%2_up" ).arg( m_skinPath ).arg( m_fileNameInfix ) ); | 102 | d->buttonUpImage = loadImage( QString( "%1/skin%2_up" ).arg( m_skinPath ).arg( m_fileNameInfix ) ); |
102 | return d->buttonUpImage; | 103 | return d->buttonUpImage; |
103 | } | 104 | } |
104 | 105 | ||
105 | QImage Skin::buttonDownImage() const | 106 | QImage Skin::buttonDownImage() const |
106 | { | 107 | { |
107 | if ( d->buttonDownImage.isNull() ) | 108 | if ( d->buttonDownImage.isNull() ) |
108 | d->buttonDownImage = loadImage( QString( "%1/skin%2_down" ).arg( m_skinPath ).arg( m_fileNameInfix ) ); | 109 | d->buttonDownImage = loadImage( QString( "%1/skin%2_down" ).arg( m_skinPath ).arg( m_fileNameInfix ) ); |
109 | return d->buttonDownImage; | 110 | return d->buttonDownImage; |
110 | } | 111 | } |
111 | 112 | ||
112 | QImage Skin::buttonMask( const MediaWidget::SkinButtonInfo *skinButtonInfo, uint buttonCount ) const | 113 | QImage Skin::buttonMask( const MediaWidget::SkinButtonInfo *skinButtonInfo, uint buttonCount ) const |
113 | { | 114 | { |
114 | if ( !d->buttonMask.isNull() ) | 115 | if ( !d->buttonMask.isNull() ) |
115 | return d->buttonMask; | 116 | return d->buttonMask; |
116 | 117 | ||
117 | QSize buttonAreaSize = buttonUpImage().size(); | 118 | QSize buttonAreaSize = buttonUpImage().size(); |
118 | 119 | ||
119 | d->buttonMask = QImage( buttonAreaSize, 8, 255 ); | 120 | d->buttonMask = QImage( buttonAreaSize, 8, 255 ); |
120 | d->buttonMask.fill( 0 ); | 121 | d->buttonMask.fill( 0 ); |
121 | 122 | ||
122 | for ( uint i = 0; i < buttonCount; ++i ) | 123 | for ( uint i = 0; i < buttonCount; ++i ) |
123 | addButtonToMask( skinButtonInfo[ i ].command + 1, buttonMaskImage( skinButtonInfo[ i ].fileName ) ); | 124 | addButtonToMask( skinButtonInfo[ i ].command + 1, buttonMaskImage( skinButtonInfo[ i ].fileName ) ); |
124 | 125 | ||
125 | return d->buttonMask; | 126 | return d->buttonMask; |
126 | } | 127 | } |
127 | 128 | ||
128 | void Skin::addButtonToMask( int tag, const QImage &maskImage ) const | 129 | void Skin::addButtonToMask( int tag, const QImage &maskImage ) const |
129 | { | 130 | { |
130 | if ( maskImage.isNull() ) | 131 | if ( maskImage.isNull() ) |
131 | return; | 132 | return; |
132 | 133 | ||
133 | uchar **dest = d->buttonMask.jumpTable(); | 134 | uchar **dest = d->buttonMask.jumpTable(); |
134 | for ( int y = 0; y < d->buttonMask.height(); y++ ) { | 135 | for ( int y = 0; y < d->buttonMask.height(); y++ ) { |
135 | uchar *line = dest[y]; | 136 | uchar *line = dest[y]; |
136 | for ( int x = 0; x < d->buttonMask.width(); x++ ) | 137 | for ( int x = 0; x < d->buttonMask.width(); x++ ) |
137 | if ( !qRed( maskImage.pixel( x, y ) ) ) | 138 | if ( !qRed( maskImage.pixel( x, y ) ) ) |
138 | line[x] = tag; | 139 | line[x] = tag; |
139 | } | 140 | } |
140 | } | 141 | } |
141 | 142 | ||
142 | QImage Skin::buttonMaskImage( const QString &fileName ) const | 143 | QImage Skin::buttonMaskImage( const QString &fileName ) const |
143 | { | 144 | { |
144 | SkinData::ButtonMaskImageMap::Iterator it = d->buttonMasks.find( fileName ); | 145 | SkinData::ButtonMaskImageMap::Iterator it = d->buttonMasks.find( fileName ); |
145 | if ( it == d->buttonMasks.end() ) { | 146 | if ( it == d->buttonMasks.end() ) { |
146 | QString prefix = m_skinPath + QString::fromLatin1( "/skin%1_mask_" ).arg( m_fileNameInfix ); | 147 | QString prefix = m_skinPath + QString::fromLatin1( "/skin%1_mask_" ).arg( m_fileNameInfix ); |
147 | QString path = prefix + fileName; | 148 | QString path = prefix + fileName; |
148 | it = d->buttonMasks.insert( fileName, loadImage( path ) ); | 149 | it = d->buttonMasks.insert( fileName, loadImage( path ) ); |
149 | } | 150 | } |
150 | return *it; | 151 | return *it; |
151 | } | 152 | } |
152 | 153 | ||
153 | QString Skin::defaultSkinName() | 154 | QString Skin::defaultSkinName() |
154 | { | 155 | { |
155 | Config cfg( "OpiePlayer" ); | 156 | Config cfg( "OpiePlayer" ); |
156 | cfg.setGroup( "Options" ); | 157 | cfg.setGroup( "Options" ); |
157 | return cfg.readEntry( "Skin", "default" ); | 158 | return cfg.readEntry( "Skin", "default" ); |
158 | } | 159 | } |
159 | 160 | ||
160 | QImage Skin::loadImage( const QString &fileName ) | 161 | QImage Skin::loadImage( const QString &fileName ) |
161 | { | 162 | { |
162 | return QImage( Resource::findPixmap( fileName ) ); | 163 | return QImage( Resource::findPixmap( fileName ) ); |
163 | } | 164 | } |
164 | 165 | ||
165 | SkinCache::SkinCache() | 166 | SkinCache::SkinCache() |
166 | { | 167 | { |
167 | // let's say we cache two skins (audio+video) at maximum | 168 | // let's say we cache two skins (audio+video) at maximum |
168 | m_cache.setMaxCost( 2 ); | 169 | m_cache.setMaxCost( 2 ); |
169 | // ... and one background pixmap | 170 | // ... and one background pixmap |
170 | m_backgroundPixmapCache.setMaxCost( 1 ); | 171 | m_backgroundPixmapCache.setMaxCost( 1 ); |
171 | } | 172 | } |
172 | 173 | ||
173 | SkinData *SkinCache::lookupAndTake( const QString &skinPath, const QString &fileNameInfix ) | 174 | SkinData *SkinCache::lookupAndTake( const QString &skinPath, const QString &fileNameInfix ) |
174 | { | 175 | { |
175 | QString key = skinPath + fileNameInfix; | 176 | QString key = skinPath + fileNameInfix; |
176 | 177 | ||
177 | SkinData *data = m_cache.take( key ); | 178 | SkinData *data = m_cache.take( key ); |
178 | if ( !data ) | 179 | if ( !data ) |
179 | data = new SkinData; | 180 | data = new SkinData; |
180 | else | 181 | else |
181 | odebug << "SkinCache: hit" << oendl; | 182 | odebug << "SkinCache: hit" << oendl; |
182 | 183 | ||
183 | QPixmap *bgPixmap = m_backgroundPixmapCache.find( skinPath ); | 184 | QPixmap *bgPixmap = m_backgroundPixmapCache.find( skinPath ); |
184 | if ( bgPixmap ) { | 185 | if ( bgPixmap ) { |
185 | odebug << "SkinCache: hit on bgpixmap" << oendl; | 186 | odebug << "SkinCache: hit on bgpixmap" << oendl; |
186 | data->backgroundPixmap = *bgPixmap; | 187 | data->backgroundPixmap = *bgPixmap; |
187 | } | 188 | } |
188 | else | 189 | else |
189 | data->backgroundPixmap = QPixmap(); | 190 | data->backgroundPixmap = QPixmap(); |
190 | 191 | ||
191 | return data; | 192 | return data; |
192 | } | 193 | } |
193 | 194 | ||
194 | void SkinCache::store( const QString &skinPath, const QString &fileNameInfix, SkinData *data ) | 195 | void SkinCache::store( const QString &skinPath, const QString &fileNameInfix, SkinData *data ) |
195 | { | 196 | { |
196 | QPixmap *backgroundPixmap = new QPixmap( data->backgroundPixmap ); | 197 | QPixmap *backgroundPixmap = new QPixmap( data->backgroundPixmap ); |
197 | 198 | ||
198 | data->backgroundPixmap = QPixmap(); | 199 | data->backgroundPixmap = QPixmap(); |
199 | 200 | ||
200 | QString key = skinPath + fileNameInfix; | 201 | QString key = skinPath + fileNameInfix; |
201 | 202 | ||
202 | if ( m_cache.find( key, false /*ref*/ ) != 0 || | 203 | if ( m_cache.find( key, false /*ref*/ ) != 0 || |
203 | !m_cache.insert( key, data ) ) | 204 | !m_cache.insert( key, data ) ) |
204 | delete data; | 205 | delete data; |
205 | 206 | ||
206 | if ( m_backgroundPixmapCache.find( skinPath, false /*ref*/ ) != 0 || | 207 | if ( m_backgroundPixmapCache.find( skinPath, false /*ref*/ ) != 0 || |
207 | !m_backgroundPixmapCache.insert( skinPath, backgroundPixmap ) ) | 208 | !m_backgroundPixmapCache.insert( skinPath, backgroundPixmap ) ) |
208 | delete backgroundPixmap; | 209 | delete backgroundPixmap; |
209 | } | 210 | } |
210 | 211 | ||
211 | SkinLoader::IncrementalLoader::IncrementalLoader( const Info &info ) | 212 | SkinLoader::IncrementalLoader::IncrementalLoader( const Info &info ) |
212 | : m_skin( info.skinName, info.fileNameInfix ), m_info( info ) | 213 | : m_skin( info.skinName, info.fileNameInfix ), m_info( info ) |
213 | { | 214 | { |
214 | m_currentState = LoadBackgroundPixmap; | 215 | m_currentState = LoadBackgroundPixmap; |
215 | } | 216 | } |
216 | 217 | ||
217 | SkinLoader::IncrementalLoader::LoaderResult SkinLoader::IncrementalLoader::loadStep() | 218 | SkinLoader::IncrementalLoader::LoaderResult SkinLoader::IncrementalLoader::loadStep() |
218 | { | 219 | { |
219 | switch ( m_currentState ) { | 220 | switch ( m_currentState ) { |
220 | case LoadBackgroundPixmap: | 221 | case LoadBackgroundPixmap: |
221 | odebug << "load bgpixmap" << oendl; | 222 | odebug << "load bgpixmap" << oendl; |
222 | m_skin.backgroundPixmap(); | 223 | m_skin.backgroundPixmap(); |
223 | m_currentState = LoadButtonUpImage; | 224 | m_currentState = LoadButtonUpImage; |
224 | break; | 225 | break; |
225 | case LoadButtonUpImage: | 226 | case LoadButtonUpImage: |
226 | odebug << "load upimage" << oendl; | 227 | odebug << "load upimage" << oendl; |
227 | m_skin.buttonUpImage(); | 228 | m_skin.buttonUpImage(); |
228 | m_currentState = LoadButtonDownImage; | 229 | m_currentState = LoadButtonDownImage; |
229 | break; | 230 | break; |
230 | case LoadButtonDownImage: | 231 | case LoadButtonDownImage: |
231 | odebug << "load downimage" << oendl; | 232 | odebug << "load downimage" << oendl; |
232 | m_skin.buttonDownImage(); | 233 | m_skin.buttonDownImage(); |
233 | m_currentState = LoadButtonMasks; | 234 | m_currentState = LoadButtonMasks; |
234 | m_currentButton = 0; | 235 | m_currentButton = 0; |
235 | break; | 236 | break; |
236 | case LoadButtonMasks: | 237 | case LoadButtonMasks: |
237 | odebug << "load button masks " << m_currentButton << "" << oendl; | 238 | odebug << "load button masks " << m_currentButton << "" << oendl; |
238 | m_skin.buttonMaskImage( m_info.buttonInfo[ m_currentButton ].fileName ); | 239 | m_skin.buttonMaskImage( m_info.buttonInfo[ m_currentButton ].fileName ); |
239 | 240 | ||
240 | m_currentButton++; | 241 | m_currentButton++; |
241 | if ( m_currentButton >= m_info.buttonCount ) | 242 | if ( m_currentButton >= m_info.buttonCount ) |
242 | m_currentState = LoadButtonMask; | 243 | m_currentState = LoadButtonMask; |
243 | 244 | ||
244 | break; | 245 | break; |
245 | case LoadButtonMask: | 246 | case LoadButtonMask: |
246 | odebug << "load whole mask" << oendl; | 247 | odebug << "load whole mask" << oendl; |
247 | m_skin.buttonMask( m_info.buttonInfo, m_info.buttonCount ); | 248 | m_skin.buttonMask( m_info.buttonInfo, m_info.buttonCount ); |
248 | return LoadingCompleted; | 249 | return LoadingCompleted; |
249 | } | 250 | } |
250 | 251 | ||
251 | return MoreToCome; | 252 | return MoreToCome; |
252 | } | 253 | } |
253 | 254 | ||
254 | SkinLoader::SkinLoader() | 255 | SkinLoader::SkinLoader() |
255 | : m_currentLoader( 0 ), m_timerId( -1 ) | 256 | : m_currentLoader( 0 ), m_timerId( -1 ) |
256 | { | 257 | { |
257 | } | 258 | } |
258 | 259 | ||
259 | SkinLoader::~SkinLoader() | 260 | SkinLoader::~SkinLoader() |
260 | { | 261 | { |
261 | odebug << "SkinLoader::~SkinLoader()" << oendl; | 262 | odebug << "SkinLoader::~SkinLoader()" << oendl; |
262 | killTimers(); | 263 | killTimers(); |
263 | delete m_currentLoader; | 264 | delete m_currentLoader; |
264 | } | 265 | } |
265 | 266 | ||
266 | void SkinLoader::schedule( const MediaWidget::GUIInfo &guiInfo ) | 267 | void SkinLoader::schedule( const MediaWidget::GUIInfo &guiInfo ) |
267 | { | 268 | { |
268 | schedule( Skin::defaultSkinName(), guiInfo ); | 269 | schedule( Skin::defaultSkinName(), guiInfo ); |
269 | } | 270 | } |
270 | 271 | ||
271 | void SkinLoader::schedule( const QString &skinName, const MediaWidget::GUIInfo &guiInfo ) | 272 | void SkinLoader::schedule( const QString &skinName, const MediaWidget::GUIInfo &guiInfo ) |
272 | { | 273 | { |
273 | pendingSkins << Info( skinName, guiInfo ); | 274 | pendingSkins << Info( skinName, guiInfo ); |
274 | } | 275 | } |
275 | 276 | ||
276 | void SkinLoader::start() | 277 | void SkinLoader::start() |
277 | { | 278 | { |
278 | assert( m_timerId == -1 ); | 279 | assert( m_timerId == -1 ); |
279 | m_timerId = startTimer( 100 /* ms */ ); | 280 | m_timerId = startTimer( 100 /* ms */ ); |
280 | odebug << "SkinLoader::start() " << pendingSkins.count() << " jobs" << oendl; | 281 | odebug << "SkinLoader::start() " << pendingSkins.count() << " jobs" << oendl; |
281 | } | 282 | } |
282 | 283 | ||
283 | void SkinLoader::timerEvent( QTimerEvent *ev ) | 284 | void SkinLoader::timerEvent( QTimerEvent *ev ) |
284 | { | 285 | { |
285 | if ( ev->timerId() != m_timerId ) { | 286 | if ( ev->timerId() != m_timerId ) { |
286 | QObject::timerEvent( ev ); | 287 | QObject::timerEvent( ev ); |
287 | return; | 288 | return; |
288 | } | 289 | } |
289 | 290 | ||
290 | if ( !m_currentLoader ) { | 291 | if ( !m_currentLoader ) { |
291 | 292 | ||
292 | if ( pendingSkins.isEmpty() ) { | 293 | if ( pendingSkins.isEmpty() ) { |
293 | odebug << "all jobs done" << oendl; | 294 | odebug << "all jobs done" << oendl; |
294 | killTimer( m_timerId ); | 295 | killTimer( m_timerId ); |
295 | m_timerId = -1; | 296 | m_timerId = -1; |
296 | // ### qt3: use deleteLater(); | 297 | // ### qt3: use deleteLater(); |
297 | QTimer::singleShot( 0, this, SLOT( deleteMe() ) ); | 298 | QTimer::singleShot( 0, this, SLOT( deleteMe() ) ); |
298 | return; | 299 | return; |
299 | } | 300 | } |
300 | 301 | ||
301 | Info nfo = *pendingSkins.begin(); | 302 | Info nfo = *pendingSkins.begin(); |
302 | pendingSkins.remove( pendingSkins.begin() ); | 303 | pendingSkins.remove( pendingSkins.begin() ); |
303 | 304 | ||
304 | m_currentLoader = new IncrementalLoader( nfo ); | 305 | m_currentLoader = new IncrementalLoader( nfo ); |
305 | odebug << "new loader " << pendingSkins.count() << " jobs left" << oendl; | 306 | odebug << "new loader " << pendingSkins.count() << " jobs left" << oendl; |
306 | } | 307 | } |
307 | 308 | ||
308 | if ( m_currentLoader->loadStep() == IncrementalLoader::LoadingCompleted ) { | 309 | if ( m_currentLoader->loadStep() == IncrementalLoader::LoadingCompleted ) { |
309 | delete m_currentLoader; | 310 | delete m_currentLoader; |
310 | m_currentLoader = 0; | 311 | m_currentLoader = 0; |
311 | } | 312 | } |
312 | 313 | ||
313 | odebug << "finished step" << oendl; | 314 | odebug << "finished step" << oendl; |
314 | } | 315 | } |
315 | 316 | ||
316 | void SkinLoader::deleteMe() | 317 | void SkinLoader::deleteMe() |
317 | { | 318 | { |
318 | delete this; | 319 | delete this; |
319 | } | 320 | } |
320 | 321 | ||
321 | /* vim: et sw=4 ts=4 | 322 | /* vim: et sw=4 ts=4 |
322 | */ | 323 | */ |
diff --git a/noncore/multimedia/opieplayer2/threadutil.cpp b/noncore/multimedia/opieplayer2/threadutil.cpp index d8b8abe..6ed9853 100644 --- a/noncore/multimedia/opieplayer2/threadutil.cpp +++ b/noncore/multimedia/opieplayer2/threadutil.cpp | |||
@@ -1,394 +1,395 @@ | |||
1 | /* This file is part of the KDE project | 1 | /* This file is part of the KDE project |
2 | Copyright (C) 2002 Simon Hausmann <hausmann@kde.org> | 2 | Copyright (C) 2002 Simon Hausmann <hausmann@kde.org> |
3 | 3 | ||
4 | This library is free software; you can redistribute it and/or | 4 | This library is free software; you can redistribute it and/or |
5 | modify it under the terms of the GNU Library General Public | 5 | modify it under the terms of the GNU Library General Public |
6 | License as published by the Free Software Foundation; either | 6 | License as published by the Free Software Foundation; either |
7 | version 2 of the License, or (at your option) any later version. | 7 | version 2 of the License, or (at your option) any later version. |
8 | 8 | ||
9 | This library is distributed in the hope that it will be useful, | 9 | This library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | Library General Public License for more details. | 12 | Library General Public License for more details. |
13 | 13 | ||
14 | You should have received a copy of the GNU Library General Public License | 14 | You should have received a copy of the GNU Library General Public License |
15 | along with this library; see the file COPYING.LIB. If not, write to | 15 | along with this library; see the file COPYING.LIB. If not, write to |
16 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 16 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
17 | Boston, MA 02111-1307, USA. | 17 | Boston, MA 02111-1307, USA. |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include "threadutil.h" | 20 | #include "threadutil.h" |
21 | 21 | ||
22 | #include <opie2/odebug.h> | ||
22 | #include <qsocketnotifier.h> | 23 | #include <qsocketnotifier.h> |
23 | 24 | ||
24 | #include <pthread.h> | 25 | #include <pthread.h> |
25 | #include <assert.h> | 26 | #include <assert.h> |
26 | #include <unistd.h> | 27 | #include <unistd.h> |
27 | #include <errno.h> | 28 | #include <errno.h> |
28 | 29 | ||
29 | using namespace ThreadUtil; | 30 | using namespace ThreadUtil; |
30 | 31 | ||
31 | struct Mutex::Data | 32 | struct Mutex::Data |
32 | { | 33 | { |
33 | Data() | 34 | Data() |
34 | { | 35 | { |
35 | pthread_mutex_init( &mutex, 0 ); | 36 | pthread_mutex_init( &mutex, 0 ); |
36 | } | 37 | } |
37 | ~Data() | 38 | ~Data() |
38 | { | 39 | { |
39 | pthread_mutex_destroy( &mutex ); | 40 | pthread_mutex_destroy( &mutex ); |
40 | } | 41 | } |
41 | 42 | ||
42 | pthread_mutex_t mutex; | 43 | pthread_mutex_t mutex; |
43 | }; | 44 | }; |
44 | 45 | ||
45 | Mutex::Mutex() | 46 | Mutex::Mutex() |
46 | : d( new Data ) | 47 | : d( new Data ) |
47 | { | 48 | { |
48 | } | 49 | } |
49 | 50 | ||
50 | Mutex::~Mutex() | 51 | Mutex::~Mutex() |
51 | { | 52 | { |
52 | delete d; | 53 | delete d; |
53 | } | 54 | } |
54 | 55 | ||
55 | void Mutex::lock() | 56 | void Mutex::lock() |
56 | { | 57 | { |
57 | pthread_mutex_lock( &d->mutex ); | 58 | pthread_mutex_lock( &d->mutex ); |
58 | } | 59 | } |
59 | 60 | ||
60 | void Mutex::unlock() | 61 | void Mutex::unlock() |
61 | { | 62 | { |
62 | pthread_mutex_unlock( &d->mutex ); | 63 | pthread_mutex_unlock( &d->mutex ); |
63 | } | 64 | } |
64 | 65 | ||
65 | bool Mutex::tryLock() | 66 | bool Mutex::tryLock() |
66 | { | 67 | { |
67 | return pthread_mutex_trylock( &d->mutex ) == 0; | 68 | return pthread_mutex_trylock( &d->mutex ) == 0; |
68 | } | 69 | } |
69 | 70 | ||
70 | bool Mutex::isLocked() | 71 | bool Mutex::isLocked() |
71 | { | 72 | { |
72 | if ( !tryLock() ) | 73 | if ( !tryLock() ) |
73 | return true; | 74 | return true; |
74 | 75 | ||
75 | unlock(); | 76 | unlock(); |
76 | return false; | 77 | return false; |
77 | } | 78 | } |
78 | 79 | ||
79 | struct WaitCondition::Data | 80 | struct WaitCondition::Data |
80 | { | 81 | { |
81 | Data() | 82 | Data() |
82 | { | 83 | { |
83 | int result = pthread_cond_init( &waitCondition, 0 ); | 84 | int result = pthread_cond_init( &waitCondition, 0 ); |
84 | assert( result == 0 ); | 85 | assert( result == 0 ); |
85 | } | 86 | } |
86 | ~Data() | 87 | ~Data() |
87 | { | 88 | { |
88 | pthread_cond_destroy( &waitCondition ); | 89 | pthread_cond_destroy( &waitCondition ); |
89 | } | 90 | } |
90 | 91 | ||
91 | pthread_cond_t waitCondition; | 92 | pthread_cond_t waitCondition; |
92 | }; | 93 | }; |
93 | 94 | ||
94 | WaitCondition::WaitCondition() | 95 | WaitCondition::WaitCondition() |
95 | : d( new Data ) | 96 | : d( new Data ) |
96 | { | 97 | { |
97 | } | 98 | } |
98 | 99 | ||
99 | WaitCondition::~WaitCondition() | 100 | WaitCondition::~WaitCondition() |
100 | { | 101 | { |
101 | delete d; | 102 | delete d; |
102 | } | 103 | } |
103 | 104 | ||
104 | bool WaitCondition::wait() | 105 | bool WaitCondition::wait() |
105 | { | 106 | { |
106 | Mutex m; | 107 | Mutex m; |
107 | m.lock(); | 108 | m.lock(); |
108 | return wait( m ); | 109 | return wait( m ); |
109 | } | 110 | } |
110 | 111 | ||
111 | bool WaitCondition::wait( Mutex &mutex ) | 112 | bool WaitCondition::wait( Mutex &mutex ) |
112 | { | 113 | { |
113 | return pthread_cond_wait( &d->waitCondition, &mutex.d->mutex ); | 114 | return pthread_cond_wait( &d->waitCondition, &mutex.d->mutex ); |
114 | } | 115 | } |
115 | 116 | ||
116 | void WaitCondition::wakeOne() | 117 | void WaitCondition::wakeOne() |
117 | { | 118 | { |
118 | pthread_cond_signal( &d->waitCondition ); | 119 | pthread_cond_signal( &d->waitCondition ); |
119 | } | 120 | } |
120 | 121 | ||
121 | void WaitCondition::wakeAll() | 122 | void WaitCondition::wakeAll() |
122 | { | 123 | { |
123 | pthread_cond_broadcast( &d->waitCondition ); | 124 | pthread_cond_broadcast( &d->waitCondition ); |
124 | } | 125 | } |
125 | 126 | ||
126 | struct Thread::Data | 127 | struct Thread::Data |
127 | { | 128 | { |
128 | Data() : isRunning( false ) | 129 | Data() : isRunning( false ) |
129 | {} | 130 | {} |
130 | 131 | ||
131 | pthread_t self; | 132 | pthread_t self; |
132 | Mutex guard; | 133 | Mutex guard; |
133 | bool isRunning; | 134 | bool isRunning; |
134 | 135 | ||
135 | WaitCondition finishCondition; | 136 | WaitCondition finishCondition; |
136 | 137 | ||
137 | Thread *thr; | 138 | Thread *thr; |
138 | 139 | ||
139 | void run() { thr->run(); } | 140 | void run() { thr->run(); } |
140 | }; | 141 | }; |
141 | 142 | ||
142 | extern "C" | 143 | extern "C" |
143 | { | 144 | { |
144 | 145 | ||
145 | static void terminate_thread( void *arg ) | 146 | static void terminate_thread( void *arg ) |
146 | { | 147 | { |
147 | Thread::Data *data = ( Thread::Data* )arg; | 148 | Thread::Data *data = ( Thread::Data* )arg; |
148 | 149 | ||
149 | assert( data ); | 150 | assert( data ); |
150 | 151 | ||
151 | AutoLock locker( data->guard ); | 152 | AutoLock locker( data->guard ); |
152 | data->isRunning = false; | 153 | data->isRunning = false; |
153 | data->finishCondition.wakeAll(); | 154 | data->finishCondition.wakeAll(); |
154 | } | 155 | } |
155 | 156 | ||
156 | static void *start_thread( void *arg ) | 157 | static void *start_thread( void *arg ) |
157 | { | 158 | { |
158 | Thread::Data *data = ( Thread::Data* )arg; | 159 | Thread::Data *data = ( Thread::Data* )arg; |
159 | 160 | ||
160 | pthread_cleanup_push( terminate_thread, data ); | 161 | pthread_cleanup_push( terminate_thread, data ); |
161 | 162 | ||
162 | data->isRunning = true; | 163 | data->isRunning = true; |
163 | data->run(); | 164 | data->run(); |
164 | 165 | ||
165 | pthread_cleanup_pop( true ); | 166 | pthread_cleanup_pop( true ); |
166 | 167 | ||
167 | Thread::exit(); | 168 | Thread::exit(); |
168 | return 0; // never reached | 169 | return 0; // never reached |
169 | } | 170 | } |
170 | 171 | ||
171 | } | 172 | } |
172 | 173 | ||
173 | Thread::Thread() | 174 | Thread::Thread() |
174 | : d( new Data ) | 175 | : d( new Data ) |
175 | { | 176 | { |
176 | d->thr = this; | 177 | d->thr = this; |
177 | } | 178 | } |
178 | 179 | ||
179 | Thread::~Thread() | 180 | Thread::~Thread() |
180 | { | 181 | { |
181 | assert( d->isRunning == false ); | 182 | assert( d->isRunning == false ); |
182 | delete d; | 183 | delete d; |
183 | } | 184 | } |
184 | 185 | ||
185 | void Thread::start() | 186 | void Thread::start() |
186 | { | 187 | { |
187 | AutoLock lock( d->guard ); | 188 | AutoLock lock( d->guard ); |
188 | 189 | ||
189 | if ( d->isRunning ) { | 190 | if ( d->isRunning ) { |
190 | odebug << "ThreadUtil::Thread::start() called for running thread." << oendl; | 191 | odebug << "ThreadUtil::Thread::start() called for running thread." << oendl; |
191 | return; | 192 | return; |
192 | } | 193 | } |
193 | 194 | ||
194 | pthread_attr_t attributes; | 195 | pthread_attr_t attributes; |
195 | pthread_attr_init( &attributes ); | 196 | pthread_attr_init( &attributes ); |
196 | pthread_attr_setscope( &attributes, PTHREAD_SCOPE_SYSTEM ); | 197 | pthread_attr_setscope( &attributes, PTHREAD_SCOPE_SYSTEM ); |
197 | int err = pthread_create( &d->self, &attributes, start_thread, ( void* )d ); | 198 | int err = pthread_create( &d->self, &attributes, start_thread, ( void* )d ); |
198 | if ( err != 0 ) { | 199 | if ( err != 0 ) { |
199 | odebug << "ThreadUtil::Thread::start() : can't create thread: " << strerror( err ) << "" << oendl; | 200 | odebug << "ThreadUtil::Thread::start() : can't create thread: " << strerror( err ) << "" << oendl; |
200 | pthread_attr_destroy( &attributes ); | 201 | pthread_attr_destroy( &attributes ); |
201 | return; | 202 | return; |
202 | } | 203 | } |
203 | pthread_attr_destroy( &attributes ); | 204 | pthread_attr_destroy( &attributes ); |
204 | } | 205 | } |
205 | 206 | ||
206 | void Thread::terminate() | 207 | void Thread::terminate() |
207 | { | 208 | { |
208 | AutoLock lock( d->guard ); | 209 | AutoLock lock( d->guard ); |
209 | if ( !d->isRunning ) | 210 | if ( !d->isRunning ) |
210 | return; | 211 | return; |
211 | 212 | ||
212 | pthread_cancel( d->self ); | 213 | pthread_cancel( d->self ); |
213 | } | 214 | } |
214 | 215 | ||
215 | bool Thread::wait() | 216 | bool Thread::wait() |
216 | { | 217 | { |
217 | AutoLock lock( d->guard ); | 218 | AutoLock lock( d->guard ); |
218 | if ( !d->isRunning ) | 219 | if ( !d->isRunning ) |
219 | return true; | 220 | return true; |
220 | 221 | ||
221 | return d->finishCondition.wait( d->guard ); | 222 | return d->finishCondition.wait( d->guard ); |
222 | } | 223 | } |
223 | 224 | ||
224 | bool Thread::isRunning() const | 225 | bool Thread::isRunning() const |
225 | { | 226 | { |
226 | AutoLock lock( d->guard ); | 227 | AutoLock lock( d->guard ); |
227 | return d->isRunning; | 228 | return d->isRunning; |
228 | } | 229 | } |
229 | 230 | ||
230 | void Thread::exit() | 231 | void Thread::exit() |
231 | { | 232 | { |
232 | pthread_exit( 0 ); | 233 | pthread_exit( 0 ); |
233 | } | 234 | } |
234 | 235 | ||
235 | OnewayNotifier::OnewayNotifier() | 236 | OnewayNotifier::OnewayNotifier() |
236 | { | 237 | { |
237 | int fds[ 2 ]; | 238 | int fds[ 2 ]; |
238 | pipe( fds ); | 239 | pipe( fds ); |
239 | m_readFd = fds[ 0 ]; | 240 | m_readFd = fds[ 0 ]; |
240 | m_writeFd = fds[ 1 ]; | 241 | m_writeFd = fds[ 1 ]; |
241 | 242 | ||
242 | m_notifier = new QSocketNotifier( m_readFd, QSocketNotifier::Read ); | 243 | m_notifier = new QSocketNotifier( m_readFd, QSocketNotifier::Read ); |
243 | connect( m_notifier, SIGNAL( activated(int) ), | 244 | connect( m_notifier, SIGNAL( activated(int) ), |
244 | this, SLOT( wakeUp() ) ); | 245 | this, SLOT( wakeUp() ) ); |
245 | } | 246 | } |
246 | 247 | ||
247 | OnewayNotifier::~OnewayNotifier() | 248 | OnewayNotifier::~OnewayNotifier() |
248 | { | 249 | { |
249 | delete m_notifier; | 250 | delete m_notifier; |
250 | 251 | ||
251 | ::close( m_readFd ); | 252 | ::close( m_readFd ); |
252 | ::close( m_writeFd ); | 253 | ::close( m_writeFd ); |
253 | } | 254 | } |
254 | 255 | ||
255 | void OnewayNotifier::notify() | 256 | void OnewayNotifier::notify() |
256 | { | 257 | { |
257 | const char c = 42; | 258 | const char c = 42; |
258 | ::write( m_writeFd, &c, 1 ); | 259 | ::write( m_writeFd, &c, 1 ); |
259 | } | 260 | } |
260 | 261 | ||
261 | void OnewayNotifier::wakeUp() | 262 | void OnewayNotifier::wakeUp() |
262 | { | 263 | { |
263 | char c = 0; | 264 | char c = 0; |
264 | 265 | ||
265 | if ( ::read( m_readFd, &c, 1 ) != 1 ) | 266 | if ( ::read( m_readFd, &c, 1 ) != 1 ) |
266 | return; | 267 | return; |
267 | 268 | ||
268 | emit awake(); | 269 | emit awake(); |
269 | } | 270 | } |
270 | 271 | ||
271 | ChannelMessage::ChannelMessage( int type ) | 272 | ChannelMessage::ChannelMessage( int type ) |
272 | : m_type( type ), m_isCall( false ), m_replied( false ), | 273 | : m_type( type ), m_isCall( false ), m_replied( false ), |
273 | m_inEventHandler( false ) | 274 | m_inEventHandler( false ) |
274 | { | 275 | { |
275 | } | 276 | } |
276 | 277 | ||
277 | ChannelMessage::~ChannelMessage() | 278 | ChannelMessage::~ChannelMessage() |
278 | { | 279 | { |
279 | if ( m_guard.isLocked() ) | 280 | if ( m_guard.isLocked() ) |
280 | m_guard.unlock(); | 281 | m_guard.unlock(); |
281 | } | 282 | } |
282 | 283 | ||
283 | void ChannelMessage::reply() | 284 | void ChannelMessage::reply() |
284 | { | 285 | { |
285 | if ( !m_isCall ) | 286 | if ( !m_isCall ) |
286 | { | 287 | { |
287 | odebug << "ChannelMessage::reply() - can't reply oneway message!" << oendl; | 288 | odebug << "ChannelMessage::reply() - can't reply oneway message!" << oendl; |
288 | return; | 289 | return; |
289 | } | 290 | } |
290 | 291 | ||
291 | if ( m_inEventHandler ) | 292 | if ( m_inEventHandler ) |
292 | { | 293 | { |
293 | m_replied = true; | 294 | m_replied = true; |
294 | return; | 295 | return; |
295 | } | 296 | } |
296 | 297 | ||
297 | m_condition.wakeOne(); | 298 | m_condition.wakeOne(); |
298 | m_guard.unlock(); | 299 | m_guard.unlock(); |
299 | } | 300 | } |
300 | 301 | ||
301 | struct Channel::Private | 302 | struct Channel::Private |
302 | { | 303 | { |
303 | Private() | 304 | Private() |
304 | { | 305 | { |
305 | ownerThread = pthread_self(); | 306 | ownerThread = pthread_self(); |
306 | } | 307 | } |
307 | 308 | ||
308 | pthread_t ownerThread; | 309 | pthread_t ownerThread; |
309 | }; | 310 | }; |
310 | 311 | ||
311 | Channel::Channel( QObject *parent, const char *name ) | 312 | Channel::Channel( QObject *parent, const char *name ) |
312 | : QObject( parent, name ), d( new Private ) | 313 | : QObject( parent, name ), d( new Private ) |
313 | { | 314 | { |
314 | connect( &m_notifier, SIGNAL( awake() ), | 315 | connect( &m_notifier, SIGNAL( awake() ), |
315 | this, SLOT( deliver() ) ); | 316 | this, SLOT( deliver() ) ); |
316 | } | 317 | } |
317 | 318 | ||
318 | Channel::~Channel() | 319 | Channel::~Channel() |
319 | { | 320 | { |
320 | delete d; | 321 | delete d; |
321 | } | 322 | } |
322 | 323 | ||
323 | void Channel::send( ChannelMessage *message, SendType type ) | 324 | void Channel::send( ChannelMessage *message, SendType type ) |
324 | { | 325 | { |
325 | if ( type == WaitForReply ) | 326 | if ( type == WaitForReply ) |
326 | { | 327 | { |
327 | message->m_guard.lock(); | 328 | message->m_guard.lock(); |
328 | message->m_isCall = true; | 329 | message->m_isCall = true; |
329 | } | 330 | } |
330 | 331 | ||
331 | m_pendingMessagesGuard.lock(); | 332 | m_pendingMessagesGuard.lock(); |
332 | m_pendingMessages << MsgEnvelope( type, message ); | 333 | m_pendingMessages << MsgEnvelope( type, message ); |
333 | m_pendingMessagesGuard.unlock(); | 334 | m_pendingMessagesGuard.unlock(); |
334 | 335 | ||
335 | if ( d->ownerThread == pthread_self() ) { | 336 | if ( d->ownerThread == pthread_self() ) { |
336 | assert( type != WaitForReply ); | 337 | assert( type != WaitForReply ); |
337 | 338 | ||
338 | deliver(); | 339 | deliver(); |
339 | } | 340 | } |
340 | else | 341 | else |
341 | m_notifier.notify(); | 342 | m_notifier.notify(); |
342 | //QThread::postEvent( this, new QCustomEvent( QEvent::User, envelope ) ); | 343 | //QThread::postEvent( this, new QCustomEvent( QEvent::User, envelope ) ); |
343 | 344 | ||
344 | if ( type == WaitForReply ) | 345 | if ( type == WaitForReply ) |
345 | { | 346 | { |
346 | message->m_condition.wait( message->m_guard ); | 347 | message->m_condition.wait( message->m_guard ); |
347 | message->m_guard.unlock(); | 348 | message->m_guard.unlock(); |
348 | } | 349 | } |
349 | } | 350 | } |
350 | 351 | ||
351 | void Channel::deliver() | 352 | void Channel::deliver() |
352 | { | 353 | { |
353 | AutoLock lock( m_pendingMessagesGuard ); | 354 | AutoLock lock( m_pendingMessagesGuard ); |
354 | 355 | ||
355 | while ( !m_pendingMessages.isEmpty() ) { | 356 | while ( !m_pendingMessages.isEmpty() ) { |
356 | MsgEnvelope envelope = m_pendingMessages.first(); | 357 | MsgEnvelope envelope = m_pendingMessages.first(); |
357 | 358 | ||
358 | m_pendingMessages.remove( m_pendingMessages.begin() ); | 359 | m_pendingMessages.remove( m_pendingMessages.begin() ); |
359 | 360 | ||
360 | m_pendingMessagesGuard.unlock(); | 361 | m_pendingMessagesGuard.unlock(); |
361 | deliverOne( envelope ); | 362 | deliverOne( envelope ); |
362 | m_pendingMessagesGuard.lock(); | 363 | m_pendingMessagesGuard.lock(); |
363 | } | 364 | } |
364 | } | 365 | } |
365 | 366 | ||
366 | void Channel::deliverOne( const MsgEnvelope &envelope ) | 367 | void Channel::deliverOne( const MsgEnvelope &envelope ) |
367 | { | 368 | { |
368 | ChannelMessage *msg = envelope.msg; | 369 | ChannelMessage *msg = envelope.msg; |
369 | 370 | ||
370 | assert( msg ); | 371 | assert( msg ); |
371 | 372 | ||
372 | if ( envelope.type == WaitForReply ) | 373 | if ( envelope.type == WaitForReply ) |
373 | { | 374 | { |
374 | msg->m_guard.lock(); | 375 | msg->m_guard.lock(); |
375 | msg->m_inEventHandler = true; | 376 | msg->m_inEventHandler = true; |
376 | } | 377 | } |
377 | 378 | ||
378 | receiveMessage( msg, envelope.type ); | 379 | receiveMessage( msg, envelope.type ); |
379 | 380 | ||
380 | if ( envelope.type == WaitForReply ) | 381 | if ( envelope.type == WaitForReply ) |
381 | { | 382 | { |
382 | msg->m_inEventHandler = false; | 383 | msg->m_inEventHandler = false; |
383 | if ( msg->m_replied ) | 384 | if ( msg->m_replied ) |
384 | { | 385 | { |
385 | msg->m_condition.wakeOne(); | 386 | msg->m_condition.wakeOne(); |
386 | // this is a bit tricky. we unlock only when we reply. | 387 | // this is a bit tricky. we unlock only when we reply. |
387 | // reply() does an unlock as well. | 388 | // reply() does an unlock as well. |
388 | msg->m_guard.unlock(); | 389 | msg->m_guard.unlock(); |
389 | } | 390 | } |
390 | } | 391 | } |
391 | } | 392 | } |
392 | 393 | ||
393 | /* vim: et sw=4 ts=4 | 394 | /* vim: et sw=4 ts=4 |
394 | */ | 395 | */ |