author | simon <simon> | 2002-12-11 17:18:17 (UTC) |
---|---|---|
committer | simon <simon> | 2002-12-11 17:18:17 (UTC) |
commit | 75f0ed4978579eb4b27cdece64c597741ed24b79 (patch) (unidiff) | |
tree | 6443323e08a9639ad0db7b5b1852d3804172e70a | |
parent | 94461696cfdcf8cdbaabec1400300e546edc447e (diff) | |
download | opie-75f0ed4978579eb4b27cdece64c597741ed24b79.zip opie-75f0ed4978579eb4b27cdece64c597741ed24b79.tar.gz opie-75f0ed4978579eb4b27cdece64c597741ed24b79.tar.bz2 |
- added a skin cache and a threaded skin loader. looks like the latter
we have to disable though, because pure image loading with qt is
anything but threadsafe :(
-rw-r--r-- | noncore/multimedia/opieplayer2/singleton.h | 49 | ||||
-rw-r--r-- | noncore/multimedia/opieplayer2/skin.cpp | 58 | ||||
-rw-r--r-- | noncore/multimedia/opieplayer2/skin.h | 52 |
3 files changed, 155 insertions, 4 deletions
diff --git a/noncore/multimedia/opieplayer2/singleton.h b/noncore/multimedia/opieplayer2/singleton.h new file mode 100644 index 0000000..35b3dff --- a/dev/null +++ b/noncore/multimedia/opieplayer2/singleton.h | |||
@@ -0,0 +1,49 @@ | |||
1 | #ifndef SINGLETON_H | ||
2 | #define SINGLETON_H | ||
3 | |||
4 | template <class Product> | ||
5 | struct DefaultSingletonCreator | ||
6 | { | ||
7 | static Product *create() { return new Product; } | ||
8 | }; | ||
9 | |||
10 | template <class Product> | ||
11 | struct NullSingletonCreator | ||
12 | { | ||
13 | static Product *create() { return 0; } | ||
14 | }; | ||
15 | |||
16 | template | ||
17 | < | ||
18 | class T, | ||
19 | template <class> class Creator = DefaultSingletonCreator | ||
20 | > | ||
21 | class Singleton | ||
22 | { | ||
23 | public: | ||
24 | static T &self() | ||
25 | { | ||
26 | if ( !s_self ) | ||
27 | s_self = Creator<T>::create(); | ||
28 | return *s_self; | ||
29 | } | ||
30 | |||
31 | protected: | ||
32 | Singleton() | ||
33 | { s_self = static_cast<T *>( this ); } | ||
34 | ~Singleton() | ||
35 | { s_self = 0; } | ||
36 | |||
37 | private: | ||
38 | Singleton( const Singleton<T, Creator> &rhs ); | ||
39 | Singleton<T, Creator> &operator=( const Singleton<T, Creator> &rhs ); | ||
40 | |||
41 | static T *s_self; | ||
42 | }; | ||
43 | |||
44 | template <class T, template <class> class Creator> | ||
45 | T *Singleton<T, Creator>::s_self = 0; | ||
46 | |||
47 | #endif // SINGLETON_H | ||
48 | /* vim: et sw=4 ts=4 | ||
49 | */ | ||
diff --git a/noncore/multimedia/opieplayer2/skin.cpp b/noncore/multimedia/opieplayer2/skin.cpp index 8281b20..0de3023 100644 --- a/noncore/multimedia/opieplayer2/skin.cpp +++ b/noncore/multimedia/opieplayer2/skin.cpp | |||
@@ -1,102 +1,152 @@ | |||
1 | 1 | ||
2 | #include "skin.h" | 2 | #include "skin.h" |
3 | 3 | ||
4 | #include <qpe/resource.h> | 4 | #include <qpe/resource.h> |
5 | #include <qpe/config.h> | 5 | #include <qpe/config.h> |
6 | 6 | ||
7 | #include <assert.h> | ||
8 | |||
7 | Skin::Skin( const QString &name, const QString &fileNameInfix ) | 9 | Skin::Skin( const QString &name, const QString &fileNameInfix ) |
8 | : m_fileNameInfix( fileNameInfix ) | 10 | : m_fileNameInfix( fileNameInfix ) |
9 | { | 11 | { |
10 | init( name ); | 12 | init( name ); |
11 | } | 13 | } |
12 | 14 | ||
13 | Skin::Skin( const QString &fileNameInfix ) | 15 | Skin::Skin( const QString &fileNameInfix ) |
14 | : m_fileNameInfix( fileNameInfix ) | 16 | : m_fileNameInfix( fileNameInfix ) |
15 | { | 17 | { |
16 | init( defaultSkinName() ); | 18 | init( defaultSkinName() ); |
17 | } | 19 | } |
18 | 20 | ||
19 | void Skin::init( const QString &name ) | 21 | void Skin::init( const QString &name ) |
20 | { | 22 | { |
21 | m_skinPath = "opieplayer2/skins/" + name; | 23 | m_skinPath = "opieplayer2/skins/" + name; |
22 | } | 24 | } |
23 | 25 | ||
24 | void Skin::preload( const MediaWidget::SkinButtonInfo *skinButtonInfo, uint buttonCount ) | 26 | void Skin::preload( const MediaWidget::SkinButtonInfo *skinButtonInfo, uint buttonCount ) |
25 | { | 27 | { |
26 | backgroundImage(); | 28 | backgroundImage(); |
27 | buttonUpImage(); | 29 | buttonUpImage(); |
28 | buttonDownImage(); | 30 | buttonDownImage(); |
29 | ( void )buttonMask( skinButtonInfo, buttonCount ); | 31 | ( void )buttonMask( skinButtonInfo, buttonCount ); |
30 | } | 32 | } |
31 | 33 | ||
32 | QImage Skin::backgroundImage() const | 34 | QImage Skin::backgroundImage() const |
33 | { | 35 | { |
34 | if ( m_backgroundImage.isNull() ) | 36 | if ( m_backgroundImage.isNull() ) |
35 | m_backgroundImage = QImage( Resource::findPixmap( QString( "%1/background" ).arg( m_skinPath ) ) ); | 37 | m_backgroundImage = SkinCache::self().loadImage( QString( "%1/background" ).arg( m_skinPath ) ); |
36 | return m_backgroundImage; | 38 | return m_backgroundImage; |
37 | } | 39 | } |
38 | 40 | ||
39 | QImage Skin::buttonUpImage() const | 41 | QImage Skin::buttonUpImage() const |
40 | { | 42 | { |
41 | if ( m_buttonUpImage.isNull() ) | 43 | if ( m_buttonUpImage.isNull() ) |
42 | m_buttonUpImage = QImage( Resource::findPixmap( QString( "%1/skin%2_up" ).arg( m_skinPath ).arg( m_fileNameInfix ) ) ); | 44 | m_buttonUpImage = SkinCache::self().loadImage( QString( "%1/skin%2_up" ).arg( m_skinPath ).arg( m_fileNameInfix ) ); |
43 | return m_buttonUpImage; | 45 | return m_buttonUpImage; |
44 | } | 46 | } |
45 | 47 | ||
46 | QImage Skin::buttonDownImage() const | 48 | QImage Skin::buttonDownImage() const |
47 | { | 49 | { |
48 | if ( m_buttonDownImage.isNull() ) | 50 | if ( m_buttonDownImage.isNull() ) |
49 | m_buttonDownImage = QImage( Resource::findPixmap( QString( "%1/skin%2_down" ).arg( m_skinPath ).arg( m_fileNameInfix ) ) ); | 51 | m_buttonDownImage = SkinCache::self().loadImage( QString( "%1/skin%2_down" ).arg( m_skinPath ).arg( m_fileNameInfix ) ); |
50 | return m_buttonDownImage; | 52 | return m_buttonDownImage; |
51 | } | 53 | } |
52 | 54 | ||
53 | QImage Skin::buttonMask( const MediaWidget::SkinButtonInfo *skinButtonInfo, uint buttonCount ) const | 55 | QImage Skin::buttonMask( const MediaWidget::SkinButtonInfo *skinButtonInfo, uint buttonCount ) const |
54 | { | 56 | { |
55 | if ( !m_buttonMask.isNull() ) | 57 | if ( !m_buttonMask.isNull() ) |
56 | return m_buttonMask; | 58 | return m_buttonMask; |
57 | 59 | ||
58 | QSize buttonAreaSize = buttonUpImage().size(); | 60 | QSize buttonAreaSize = buttonUpImage().size(); |
59 | 61 | ||
60 | m_buttonMask = QImage( buttonAreaSize, 8, 255 ); | 62 | m_buttonMask = QImage( buttonAreaSize, 8, 255 ); |
61 | m_buttonMask.fill( 0 ); | 63 | m_buttonMask.fill( 0 ); |
62 | 64 | ||
63 | for ( uint i = 0; i < buttonCount; ++i ) | 65 | for ( uint i = 0; i < buttonCount; ++i ) |
64 | addButtonToMask( skinButtonInfo[ i ].command + 1, buttonMaskImage( skinButtonInfo[ i ].fileName ) ); | 66 | addButtonToMask( skinButtonInfo[ i ].command + 1, buttonMaskImage( skinButtonInfo[ i ].fileName ) ); |
65 | 67 | ||
66 | return m_buttonMask; | 68 | return m_buttonMask; |
67 | } | 69 | } |
68 | 70 | ||
69 | void Skin::addButtonToMask( int tag, const QImage &maskImage ) const | 71 | void Skin::addButtonToMask( int tag, const QImage &maskImage ) const |
70 | { | 72 | { |
71 | if ( maskImage.isNull() ) | 73 | if ( maskImage.isNull() ) |
72 | return; | 74 | return; |
73 | 75 | ||
74 | uchar **dest = m_buttonMask.jumpTable(); | 76 | uchar **dest = m_buttonMask.jumpTable(); |
75 | for ( int y = 0; y < m_buttonMask.height(); y++ ) { | 77 | for ( int y = 0; y < m_buttonMask.height(); y++ ) { |
76 | uchar *line = dest[y]; | 78 | uchar *line = dest[y]; |
77 | for ( int x = 0; x < m_buttonMask.width(); x++ ) | 79 | for ( int x = 0; x < m_buttonMask.width(); x++ ) |
78 | if ( !qRed( maskImage.pixel( x, y ) ) ) | 80 | if ( !qRed( maskImage.pixel( x, y ) ) ) |
79 | line[x] = tag; | 81 | line[x] = tag; |
80 | } | 82 | } |
81 | } | 83 | } |
82 | 84 | ||
83 | QImage Skin::buttonMaskImage( const QString &fileName ) const | 85 | QImage Skin::buttonMaskImage( const QString &fileName ) const |
84 | { | 86 | { |
85 | ButtonMaskImageMap::Iterator it = m_buttonMasks.find( fileName ); | 87 | ButtonMaskImageMap::Iterator it = m_buttonMasks.find( fileName ); |
86 | if ( it == m_buttonMasks.end() ) { | 88 | if ( it == m_buttonMasks.end() ) { |
87 | QString prefix = m_skinPath + QString::fromLatin1( "/skin%1_mask_" ).arg( m_fileNameInfix ); | 89 | QString prefix = m_skinPath + QString::fromLatin1( "/skin%1_mask_" ).arg( m_fileNameInfix ); |
88 | QString path = prefix + fileName + ".png"; | 90 | QString path = prefix + fileName + ".png"; |
89 | it = m_buttonMasks.insert( fileName, QImage( Resource::findPixmap( path ) ) ); | 91 | it = m_buttonMasks.insert( fileName, SkinCache::self().loadImage( path ) ); |
90 | } | 92 | } |
91 | return *it; | 93 | return *it; |
92 | } | 94 | } |
93 | 95 | ||
94 | QString Skin::defaultSkinName() | 96 | QString Skin::defaultSkinName() |
95 | { | 97 | { |
96 | Config cfg( "OpiePlayer" ); | 98 | Config cfg( "OpiePlayer" ); |
97 | cfg.setGroup( "Options" ); | 99 | cfg.setGroup( "Options" ); |
98 | return cfg.readEntry( "Skin", "default" ); | 100 | return cfg.readEntry( "Skin", "default" ); |
99 | } | 101 | } |
100 | 102 | ||
103 | SkinCache::SkinCache() | ||
104 | { | ||
105 | m_cache.setAutoDelete( true ); | ||
106 | } | ||
107 | |||
108 | QImage SkinCache::loadImage( const QString &name ) | ||
109 | { | ||
110 | ThreadUtil::AutoLock lock( m_cacheGuard ); | ||
111 | |||
112 | QImage *image = m_cache.find( name ); | ||
113 | if ( image ) { | ||
114 | qDebug( "cache hit for %s", name.ascii() ); | ||
115 | return *image; | ||
116 | } | ||
117 | |||
118 | image = new QImage( Resource::findPixmap( name ) ); | ||
119 | m_cache.insert( name, image ); | ||
120 | return *image; | ||
121 | } | ||
122 | |||
123 | SkinLoader::SkinLoader() | ||
124 | { | ||
125 | } | ||
126 | |||
127 | void SkinLoader::schedule( const QString &skinName, const QString &fileNameInfix, | ||
128 | const MediaWidget::SkinButtonInfo *skinButtonInfo, const uint buttonCount ) | ||
129 | { | ||
130 | assert( isRunning() == false ); | ||
131 | |||
132 | pendingSkins << Info( skinName, fileNameInfix, skinButtonInfo, buttonCount ); | ||
133 | } | ||
134 | |||
135 | void SkinLoader::run() | ||
136 | { | ||
137 | qDebug( "SkinLoader::run()" ); | ||
138 | for ( InfoList::ConstIterator it = pendingSkins.begin(); it != pendingSkins.end(); ++it ) | ||
139 | load( *it ); | ||
140 | qDebug( "SkinLoader is done." ); | ||
141 | } | ||
142 | |||
143 | void SkinLoader::load( const Info &nfo ) | ||
144 | { | ||
145 | qDebug( "preloading %s with infix %s", nfo.skinName.ascii(), nfo.fileNameInfix.ascii() ); | ||
146 | |||
147 | Skin skin( nfo.skinName, nfo.fileNameInfix ); | ||
148 | skin.preload( nfo.skinButtonInfo, nfo.buttonCount ); | ||
149 | } | ||
150 | |||
101 | /* vim: et sw=4 ts=4 | 151 | /* vim: et sw=4 ts=4 |
102 | */ | 152 | */ |
diff --git a/noncore/multimedia/opieplayer2/skin.h b/noncore/multimedia/opieplayer2/skin.h index 58f1849..c15d9dc 100644 --- a/noncore/multimedia/opieplayer2/skin.h +++ b/noncore/multimedia/opieplayer2/skin.h | |||
@@ -1,50 +1,102 @@ | |||
1 | #ifndef SKIN_H | 1 | #ifndef SKIN_H |
2 | #define SKIN_H | 2 | #define SKIN_H |
3 | 3 | ||
4 | #include <qstring.h> | 4 | #include <qstring.h> |
5 | #include <qimage.h> | 5 | #include <qimage.h> |
6 | #include <qmap.h> | 6 | #include <qmap.h> |
7 | #include <qdict.h> | ||
7 | 8 | ||
8 | #include "mediawidget.h" | 9 | #include "mediawidget.h" |
10 | #include "threadutil.h" | ||
11 | #include "singleton.h" | ||
9 | 12 | ||
10 | class Skin | 13 | class Skin |
11 | { | 14 | { |
12 | public: | 15 | public: |
13 | Skin( const QString &name, const QString &fileNameInfix ); | 16 | Skin( const QString &name, const QString &fileNameInfix ); |
14 | Skin( const QString &fileNameInfix ); | 17 | Skin( const QString &fileNameInfix ); |
15 | 18 | ||
16 | void preload( const MediaWidget::SkinButtonInfo *skinButtonInfo, uint buttonCount ); | 19 | void preload( const MediaWidget::SkinButtonInfo *skinButtonInfo, uint buttonCount ); |
17 | 20 | ||
18 | QImage backgroundImage() const; | 21 | QImage backgroundImage() const; |
19 | QImage buttonUpImage() const; | 22 | QImage buttonUpImage() const; |
20 | QImage buttonDownImage() const; | 23 | QImage buttonDownImage() const; |
21 | 24 | ||
22 | QImage buttonMask( const MediaWidget::SkinButtonInfo *skinButtonInfo, uint buttonCount ) const; | 25 | QImage buttonMask( const MediaWidget::SkinButtonInfo *skinButtonInfo, uint buttonCount ) const; |
23 | 26 | ||
24 | QImage buttonMaskImage( const QString &fileName ) const; | 27 | QImage buttonMaskImage( const QString &fileName ) const; |
25 | 28 | ||
26 | static QString defaultSkinName(); | 29 | static QString defaultSkinName(); |
27 | 30 | ||
28 | private: | 31 | private: |
29 | void init( const QString &name ); | 32 | void init( const QString &name ); |
30 | 33 | ||
31 | void addButtonToMask( int tag, const QImage &maskImage ) const; | 34 | void addButtonToMask( int tag, const QImage &maskImage ) const; |
32 | 35 | ||
33 | QString m_fileNameInfix; | 36 | QString m_fileNameInfix; |
34 | QString m_skinPath; | 37 | QString m_skinPath; |
35 | 38 | ||
36 | typedef QMap<QString, QImage> ButtonMaskImageMap; | 39 | typedef QMap<QString, QImage> ButtonMaskImageMap; |
37 | 40 | ||
38 | mutable QImage m_backgroundImage; | 41 | mutable QImage m_backgroundImage; |
39 | mutable QImage m_buttonUpImage; | 42 | mutable QImage m_buttonUpImage; |
40 | mutable QImage m_buttonDownImage; | 43 | mutable QImage m_buttonDownImage; |
41 | mutable QImage m_buttonMask; | 44 | mutable QImage m_buttonMask; |
42 | mutable ButtonMaskImageMap m_buttonMasks; | 45 | mutable ButtonMaskImageMap m_buttonMasks; |
43 | 46 | ||
44 | Skin( const Skin & ); | 47 | Skin( const Skin & ); |
45 | Skin &operator=( const Skin & ); | 48 | Skin &operator=( const Skin & ); |
46 | }; | 49 | }; |
47 | 50 | ||
51 | class SkinCache : public Singleton<SkinCache> | ||
52 | { | ||
53 | public: | ||
54 | SkinCache(); | ||
55 | |||
56 | QImage loadImage( const QString &name ); | ||
57 | |||
58 | private: | ||
59 | typedef QDict<QImage> ImageCache; | ||
60 | |||
61 | ImageCache m_cache; | ||
62 | |||
63 | ThreadUtil::Mutex m_cacheGuard; | ||
64 | }; | ||
65 | |||
66 | class SkinLoader : public ThreadUtil::Thread | ||
67 | { | ||
68 | public: | ||
69 | SkinLoader(); | ||
70 | |||
71 | void schedule( const QString &skinName, const QString &fileNameInfix, | ||
72 | const MediaWidget::SkinButtonInfo *skinButtonInfo, const uint buttonCount ); | ||
73 | |||
74 | protected: | ||
75 | virtual void run(); | ||
76 | |||
77 | private: | ||
78 | struct Info | ||
79 | { | ||
80 | Info() : skinButtonInfo( 0 ), buttonCount( 0 ) {} | ||
81 | Info( const QString &_skinName, const QString &_fileNameInfix, | ||
82 | const MediaWidget::SkinButtonInfo *_skinButtonInfo, const uint _buttonCount ) | ||
83 | : skinName( _skinName ), fileNameInfix( _fileNameInfix ), | ||
84 | skinButtonInfo( _skinButtonInfo ), buttonCount( _buttonCount ) | ||
85 | {} | ||
86 | |||
87 | const QString skinName; | ||
88 | const QString fileNameInfix; | ||
89 | const MediaWidget::SkinButtonInfo *skinButtonInfo; | ||
90 | const uint buttonCount; | ||
91 | }; | ||
92 | typedef QValueList<Info> InfoList; | ||
93 | |||
94 | void load( const Info &nfo ); | ||
95 | |||
96 | InfoList pendingSkins; | ||
97 | ThreadUtil::Mutex guard; | ||
98 | }; | ||
99 | |||
48 | #endif // SKIN_H | 100 | #endif // SKIN_H |
49 | /* vim: et sw=4 ts=4 | 101 | /* vim: et sw=4 ts=4 |
50 | */ | 102 | */ |