summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/multimedia/opieplayer2/skin.cpp25
1 files changed, 13 insertions, 12 deletions
diff --git a/noncore/multimedia/opieplayer2/skin.cpp b/noncore/multimedia/opieplayer2/skin.cpp
index 5d8929e..b2c1649 100644
--- a/noncore/multimedia/opieplayer2/skin.cpp
+++ b/noncore/multimedia/opieplayer2/skin.cpp
@@ -1,323 +1,324 @@
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#include <opie2/odebug.h>
26 26
27#include <qcache.h> 27#include <qcache.h>
28#include <qtimer.h> 28#include <qtimer.h>
29 29
30#include <qpe/config.h> 30#include <qpe/config.h>
31#include <qpe/global.h>
31 32
32#include <assert.h> 33#include <assert.h>
33 34
34struct SkinData 35struct SkinData
35{ 36{
36 typedef QMap<QString, QImage> ButtonMaskImageMap; 37 typedef QMap<QString, QImage> ButtonMaskImageMap;
37 38
38 QPixmap backgroundPixmap; 39 QPixmap backgroundPixmap;
39 QImage buttonUpImage; 40 QImage buttonUpImage;
40 QImage buttonDownImage; 41 QImage buttonDownImage;
41 QImage buttonMask; 42 QImage buttonMask;
42 ButtonMaskImageMap buttonMasks; 43 ButtonMaskImageMap buttonMasks;
43}; 44};
44 45
45class SkinCache : public Singleton<SkinCache> 46class SkinCache : public Singleton<SkinCache>
46{ 47{
47public: 48public:
48 SkinCache(); 49 SkinCache();
49 50
50 SkinData *lookupAndTake( const QString &skinPath, const QString &fileNameInfix ); 51 SkinData *lookupAndTake( const QString &skinPath, const QString &fileNameInfix );
51 52
52 void store( const QString &skinPath, const QString &fileNameInfix, SkinData *data ); 53 void store( const QString &skinPath, const QString &fileNameInfix, SkinData *data );
53 54
54private: 55private:
55 typedef QCache<SkinData> DataCache; 56 typedef QCache<SkinData> DataCache;
56 typedef QCache<QPixmap> BackgroundPixmapCache; 57 typedef QCache<QPixmap> BackgroundPixmapCache;
57 58
58 template <class CacheType> 59 template <class CacheType>
59 void store( const QCache<CacheType> &cache, const QString &key, CacheType *data ); 60 void store( const QCache<CacheType> &cache, const QString &key, CacheType *data );
60 61
61 DataCache m_cache; 62 DataCache m_cache;
62 BackgroundPixmapCache m_backgroundPixmapCache; 63 BackgroundPixmapCache m_backgroundPixmapCache;
63}; 64};
64 65
65Skin::Skin( const QString &name, const QString &fileNameInfix ) 66Skin::Skin( const QString &name, const QString &fileNameInfix )
66 : m_fileNameInfix( fileNameInfix ) 67 : m_fileNameInfix( fileNameInfix )
67{ 68{
68 init( name ); 69 init( name );
69} 70}
70 71
71Skin::Skin( const QString &fileNameInfix ) 72Skin::Skin( const QString &fileNameInfix )
72 : m_fileNameInfix( fileNameInfix ) 73 : m_fileNameInfix( fileNameInfix )
73{ 74{
74 init( defaultSkinName() ); 75 init( defaultSkinName() );
75} 76}
76 77
77Skin::~Skin() 78Skin::~Skin()
78{ 79{
79 if ( m_isCachable ) 80 if ( m_isCachable )
80 SkinCache::self().store( m_skinPath, m_fileNameInfix, d ); 81 SkinCache::self().store( m_skinPath, m_fileNameInfix, d );
81 else 82 else
82 delete d; 83 delete d;
83} 84}
84 85
85void Skin::init( const QString &name ) 86void Skin::init( const QString &name )
86{ 87{
87 m_isCachable = true; 88 m_isCachable = true;
88 m_skinPath = "opieplayer2/skins/" + name; 89 m_skinPath = "opieplayer2/skins/" + name;
89 d = SkinCache::self().lookupAndTake( m_skinPath, m_fileNameInfix ); 90 d = SkinCache::self().lookupAndTake( m_skinPath, m_fileNameInfix );
90} 91}
91 92
92QPixmap Skin::backgroundPixmap() const 93QPixmap Skin::backgroundPixmap() const
93{ 94{
94 if ( d->backgroundPixmap.isNull() ) 95 if ( d->backgroundPixmap.isNull() )
95 d->backgroundPixmap = loadImage( QString( "%1/background" ).arg( m_skinPath ) ); 96 d->backgroundPixmap = loadImage( QString( "%1/background" ).arg( m_skinPath ) );
96 return d->backgroundPixmap; 97 return d->backgroundPixmap;
97} 98}
98 99
99QImage Skin::buttonUpImage() const 100QImage Skin::buttonUpImage() const
100{ 101{
101 if ( d->buttonUpImage.isNull() ) 102 if ( d->buttonUpImage.isNull() )
102 d->buttonUpImage = loadImage( QString( "%1/skin%2_up" ).arg( m_skinPath ).arg( m_fileNameInfix ) ); 103 d->buttonUpImage = loadImage( QString( "%1/skin%2_up" ).arg( m_skinPath ).arg( m_fileNameInfix ) );
103 return d->buttonUpImage; 104 return d->buttonUpImage;
104} 105}
105 106
106QImage Skin::buttonDownImage() const 107QImage Skin::buttonDownImage() const
107{ 108{
108 if ( d->buttonDownImage.isNull() ) 109 if ( d->buttonDownImage.isNull() )
109 d->buttonDownImage = loadImage( QString( "%1/skin%2_down" ).arg( m_skinPath ).arg( m_fileNameInfix ) ); 110 d->buttonDownImage = loadImage( QString( "%1/skin%2_down" ).arg( m_skinPath ).arg( m_fileNameInfix ) );
110 return d->buttonDownImage; 111 return d->buttonDownImage;
111} 112}
112 113
113QImage Skin::buttonMask( const MediaWidget::SkinButtonInfo *skinButtonInfo, uint buttonCount ) const 114QImage Skin::buttonMask( const MediaWidget::SkinButtonInfo *skinButtonInfo, uint buttonCount ) const
114{ 115{
115 if ( !d->buttonMask.isNull() ) 116 if ( !d->buttonMask.isNull() )
116 return d->buttonMask; 117 return d->buttonMask;
117 118
118 QSize buttonAreaSize = buttonUpImage().size(); 119 QSize buttonAreaSize = buttonUpImage().size();
119 120
120 d->buttonMask = QImage( buttonAreaSize, 8, 255 ); 121 d->buttonMask = QImage( buttonAreaSize, 8, 255 );
121 d->buttonMask.fill( 0 ); 122 d->buttonMask.fill( 0 );
122 123
123 for ( uint i = 0; i < buttonCount; ++i ) 124 for ( uint i = 0; i < buttonCount; ++i )
124 addButtonToMask( skinButtonInfo[ i ].command + 1, buttonMaskImage( skinButtonInfo[ i ].fileName ) ); 125 addButtonToMask( skinButtonInfo[ i ].command + 1, buttonMaskImage( skinButtonInfo[ i ].fileName ) );
125 126
126 return d->buttonMask; 127 return d->buttonMask;
127} 128}
128 129
129void Skin::addButtonToMask( int tag, const QImage &maskImage ) const 130void Skin::addButtonToMask( int tag, const QImage &maskImage ) const
130{ 131{
131 if ( maskImage.isNull() ) 132 if ( maskImage.isNull() )
132 return; 133 return;
133 134
134 uchar **dest = d->buttonMask.jumpTable(); 135 uchar **dest = d->buttonMask.jumpTable();
135 for ( int y = 0; y < d->buttonMask.height(); y++ ) { 136 for ( int y = 0; y < d->buttonMask.height(); y++ ) {
136 uchar *line = dest[y]; 137 uchar *line = dest[y];
137 for ( int x = 0; x < d->buttonMask.width(); x++ ) 138 for ( int x = 0; x < d->buttonMask.width(); x++ )
138 if ( !qRed( maskImage.pixel( x, y ) ) ) 139 if ( !qRed( maskImage.pixel( x, y ) ) )
139 line[x] = tag; 140 line[x] = tag;
140 } 141 }
141} 142}
142 143
143QImage Skin::buttonMaskImage( const QString &fileName ) const 144QImage Skin::buttonMaskImage( const QString &fileName ) const
144{ 145{
145 SkinData::ButtonMaskImageMap::Iterator it = d->buttonMasks.find( fileName ); 146 SkinData::ButtonMaskImageMap::Iterator it = d->buttonMasks.find( fileName );
146 if ( it == d->buttonMasks.end() ) { 147 if ( it == d->buttonMasks.end() ) {
147 QString prefix = m_skinPath + QString::fromLatin1( "/skin%1_mask_" ).arg( m_fileNameInfix ); 148 QString prefix = m_skinPath + QString::fromLatin1( "/skin%1_mask_" ).arg( m_fileNameInfix );
148 QString path = prefix + fileName; 149 QString path = prefix + fileName;
149 it = d->buttonMasks.insert( fileName, loadImage( path ) ); 150 it = d->buttonMasks.insert( fileName, loadImage( path ) );
150 } 151 }
151 return *it; 152 return *it;
152} 153}
153 154
154QString Skin::defaultSkinName() 155QString Skin::defaultSkinName()
155{ 156{
156 Config cfg( "OpiePlayer" ); 157 Config cfg( "OpiePlayer" );
157 cfg.setGroup( "Options" ); 158 cfg.setGroup( "Options" );
158 return cfg.readEntry( "Skin", "default" ); 159 return cfg.readEntry( "Skin", "default" );
159} 160}
160 161
161QImage Skin::loadImage( const QString &fileName ) 162QImage Skin::loadImage( const QString &fileName )
162{ 163{
163 return QImage( Resource::findPixmap( fileName ) ); 164 return QImage( Resource::findPixmap( fileName ) );
164} 165}
165 166
166SkinCache::SkinCache() 167SkinCache::SkinCache()
167{ 168{
168 // let's say we cache two skins (audio+video) at maximum 169 // let's say we cache two skins (audio+video) at maximum
169 m_cache.setMaxCost( 2 ); 170 m_cache.setMaxCost( 2 );
170 // ... and one background pixmap 171 // ... and one background pixmap
171 m_backgroundPixmapCache.setMaxCost( 1 ); 172 m_backgroundPixmapCache.setMaxCost( 1 );
172} 173}
173 174
174SkinData *SkinCache::lookupAndTake( const QString &skinPath, const QString &fileNameInfix ) 175SkinData *SkinCache::lookupAndTake( const QString &skinPath, const QString &fileNameInfix )
175{ 176{
176 QString key = skinPath + fileNameInfix; 177 QString key = skinPath + fileNameInfix;
177 178
178 SkinData *data = m_cache.take( key ); 179 SkinData *data = m_cache.take( key );
179 if ( !data ) 180 if ( !data )
180 data = new SkinData; 181 data = new SkinData;
181 else 182 else
182 odebug << "SkinCache: hit" << oendl; 183 odebug << "SkinCache: hit" << oendl;
183 184
184 QPixmap *bgPixmap = m_backgroundPixmapCache.find( skinPath ); 185 QPixmap *bgPixmap = m_backgroundPixmapCache.find( skinPath );
185 if ( bgPixmap ) { 186 if ( bgPixmap ) {
186 odebug << "SkinCache: hit on bgpixmap" << oendl; 187 odebug << "SkinCache: hit on bgpixmap" << oendl;
187 data->backgroundPixmap = *bgPixmap; 188 data->backgroundPixmap = *bgPixmap;
188 } 189 }
189 else 190 else
190 data->backgroundPixmap = QPixmap(); 191 data->backgroundPixmap = QPixmap();
191 192
192 return data; 193 return data;
193} 194}
194 195
195void SkinCache::store( const QString &skinPath, const QString &fileNameInfix, SkinData *data ) 196void SkinCache::store( const QString &skinPath, const QString &fileNameInfix, SkinData *data )
196{ 197{
197 QPixmap *backgroundPixmap = new QPixmap( data->backgroundPixmap ); 198 QPixmap *backgroundPixmap = new QPixmap( data->backgroundPixmap );
198 199
199 data->backgroundPixmap = QPixmap(); 200 data->backgroundPixmap = QPixmap();
200 201
201 QString key = skinPath + fileNameInfix; 202 QString key = skinPath + fileNameInfix;
202 203
203 if ( m_cache.find( key, false /*ref*/ ) != 0 || 204 if ( m_cache.find( key, false /*ref*/ ) != 0 ||
204 !m_cache.insert( key, data ) ) 205 !m_cache.insert( key, data ) )
205 delete data; 206 delete data;
206 207
207 if ( m_backgroundPixmapCache.find( skinPath, false /*ref*/ ) != 0 || 208 if ( m_backgroundPixmapCache.find( skinPath, false /*ref*/ ) != 0 ||
208 !m_backgroundPixmapCache.insert( skinPath, backgroundPixmap ) ) 209 !m_backgroundPixmapCache.insert( skinPath, backgroundPixmap ) )
209 delete backgroundPixmap; 210 delete backgroundPixmap;
210} 211}
211 212
212SkinLoader::IncrementalLoader::IncrementalLoader( const Info &info ) 213SkinLoader::IncrementalLoader::IncrementalLoader( const Info &info )
213 : m_skin( info.skinName, info.fileNameInfix ), m_info( info ) 214 : m_skin( info.skinName, info.fileNameInfix ), m_info( info )
214{ 215{
215 m_currentState = LoadBackgroundPixmap; 216 m_currentState = LoadBackgroundPixmap;
216} 217}
217 218
218SkinLoader::IncrementalLoader::LoaderResult SkinLoader::IncrementalLoader::loadStep() 219SkinLoader::IncrementalLoader::LoaderResult SkinLoader::IncrementalLoader::loadStep()
219{ 220{
220 switch ( m_currentState ) { 221 switch ( m_currentState ) {
221 case LoadBackgroundPixmap: 222 case LoadBackgroundPixmap:
222 odebug << "load bgpixmap" << oendl; 223 odebug << "load bgpixmap" << oendl;
223 m_skin.backgroundPixmap(); 224 m_skin.backgroundPixmap();
224 m_currentState = LoadButtonUpImage; 225 m_currentState = LoadButtonUpImage;
225 break; 226 break;
226 case LoadButtonUpImage: 227 case LoadButtonUpImage:
227 odebug << "load upimage" << oendl; 228 odebug << "load upimage" << oendl;
228 m_skin.buttonUpImage(); 229 m_skin.buttonUpImage();
229 m_currentState = LoadButtonDownImage; 230 m_currentState = LoadButtonDownImage;
230 break; 231 break;
231 case LoadButtonDownImage: 232 case LoadButtonDownImage:
232 odebug << "load downimage" << oendl; 233 odebug << "load downimage" << oendl;
233 m_skin.buttonDownImage(); 234 m_skin.buttonDownImage();
234 m_currentState = LoadButtonMasks; 235 m_currentState = LoadButtonMasks;
235 m_currentButton = 0; 236 m_currentButton = 0;
236 break; 237 break;
237 case LoadButtonMasks: 238 case LoadButtonMasks:
238 odebug << "load button masks " << m_currentButton << "" << oendl; 239 odebug << "load button masks " << m_currentButton << "" << oendl;
239 m_skin.buttonMaskImage( m_info.buttonInfo[ m_currentButton ].fileName ); 240 m_skin.buttonMaskImage( m_info.buttonInfo[ m_currentButton ].fileName );
240 241
241 m_currentButton++; 242 m_currentButton++;
242 if ( m_currentButton >= m_info.buttonCount ) 243 if ( m_currentButton >= m_info.buttonCount )
243 m_currentState = LoadButtonMask; 244 m_currentState = LoadButtonMask;
244 245
245 break; 246 break;
246 case LoadButtonMask: 247 case LoadButtonMask:
247 odebug << "load whole mask" << oendl; 248 odebug << "load whole mask" << oendl;
248 m_skin.buttonMask( m_info.buttonInfo, m_info.buttonCount ); 249 m_skin.buttonMask( m_info.buttonInfo, m_info.buttonCount );
249 return LoadingCompleted; 250 return LoadingCompleted;
250 } 251 }
251 252
252 return MoreToCome; 253 return MoreToCome;
253} 254}
254 255
255SkinLoader::SkinLoader() 256SkinLoader::SkinLoader()
256 : m_currentLoader( 0 ), m_timerId( -1 ) 257 : m_currentLoader( 0 ), m_timerId( -1 )
257{ 258{
258} 259}
259 260
260SkinLoader::~SkinLoader() 261SkinLoader::~SkinLoader()
261{ 262{
262 odebug << "SkinLoader::~SkinLoader()" << oendl; 263 Global::statusMessage( tr( "Loading of Skin finished" ) );
263 killTimers(); 264 killTimers();
264 delete m_currentLoader; 265 delete m_currentLoader;
265} 266}
266 267
267void SkinLoader::schedule( const MediaWidget::GUIInfo &guiInfo ) 268void SkinLoader::schedule( const MediaWidget::GUIInfo &guiInfo )
268{ 269{
269 schedule( Skin::defaultSkinName(), guiInfo ); 270 schedule( Skin::defaultSkinName(), guiInfo );
270} 271}
271 272
272void SkinLoader::schedule( const QString &skinName, const MediaWidget::GUIInfo &guiInfo ) 273void SkinLoader::schedule( const QString &skinName, const MediaWidget::GUIInfo &guiInfo )
273{ 274{
274 pendingSkins << Info( skinName, guiInfo ); 275 pendingSkins << Info( skinName, guiInfo );
275} 276}
276 277
277void SkinLoader::start() 278void SkinLoader::start()
278{ 279{
279 assert( m_timerId == -1 ); 280 assert( m_timerId == -1 );
280 m_timerId = startTimer( 100 /* ms */ ); 281 m_timerId = startTimer( 100 /* ms */ );
281 odebug << "SkinLoader::start() " << pendingSkins.count() << " jobs" << oendl; 282 odebug << "SkinLoader::start() " << pendingSkins.count() << " jobs" << oendl;
282} 283}
283 284
284void SkinLoader::timerEvent( QTimerEvent *ev ) 285void SkinLoader::timerEvent( QTimerEvent *ev )
285{ 286{
286 if ( ev->timerId() != m_timerId ) { 287 if ( ev->timerId() != m_timerId ) {
287 QObject::timerEvent( ev ); 288 QObject::timerEvent( ev );
288 return; 289 return;
289 } 290 }
290 291
291 if ( !m_currentLoader ) { 292 if ( !m_currentLoader ) {
292 293
293 if ( pendingSkins.isEmpty() ) { 294 if ( pendingSkins.isEmpty() ) {
294 odebug << "all jobs done" << oendl; 295 odebug << "all jobs done" << oendl;
295 killTimer( m_timerId ); 296 killTimer( m_timerId );
296 m_timerId = -1; 297 m_timerId = -1;
297 // ### qt3: use deleteLater(); 298 // ### qt3: use deleteLater();
298 QTimer::singleShot( 0, this, SLOT( deleteMe() ) ); 299 QTimer::singleShot( 0, this, SLOT( deleteMe() ) );
299 return; 300 return;
300 } 301 }
301 302
302 Info nfo = *pendingSkins.begin(); 303 Info nfo = *pendingSkins.begin();
303 pendingSkins.remove( pendingSkins.begin() ); 304 pendingSkins.remove( pendingSkins.begin() );
304 305
305 m_currentLoader = new IncrementalLoader( nfo ); 306 m_currentLoader = new IncrementalLoader( nfo );
306 odebug << "new loader " << pendingSkins.count() << " jobs left" << oendl; 307 odebug << "new loader " << pendingSkins.count() << " jobs left" << oendl;
307 } 308 }
308 309
309 if ( m_currentLoader->loadStep() == IncrementalLoader::LoadingCompleted ) { 310 if ( m_currentLoader->loadStep() == IncrementalLoader::LoadingCompleted ) {
310 delete m_currentLoader; 311 delete m_currentLoader;
311 m_currentLoader = 0; 312 m_currentLoader = 0;
312 } 313 }
313 314
314 odebug << "finished step" << oendl; 315 odebug << "finished step" << oendl;
315} 316}
316 317
317void SkinLoader::deleteMe() 318void SkinLoader::deleteMe()
318{ 319{
319 delete this; 320 delete this;
320} 321}
321 322
322/* vim: et sw=4 ts=4 323/* vim: et sw=4 ts=4
323 */ 324 */