author | simon <simon> | 2002-12-11 23:12:16 (UTC) |
---|---|---|
committer | simon <simon> | 2002-12-11 23:12:16 (UTC) |
commit | d4a0626f01fae21ed19d0eea88d8eca1935c6bc8 (patch) (side-by-side diff) | |
tree | 9747bdd478c1bd93f46eaa49c95381404a6fd55b | |
parent | 8d5ae95e770bc387420fc094c54d8ac55e64e04b (diff) | |
download | opie-d4a0626f01fae21ed19d0eea88d8eca1935c6bc8.zip opie-d4a0626f01fae21ed19d0eea88d8eca1935c6bc8.tar.gz opie-d4a0626f01fae21ed19d0eea88d8eca1935c6bc8.tar.bz2 |
- skins are now pre-loaded in the background (step by step)
-rw-r--r-- | noncore/multimedia/opieplayer2/mediaplayer.cpp | 7 | ||||
-rw-r--r-- | noncore/multimedia/opieplayer2/mediaplayer.h | 3 | ||||
-rw-r--r-- | noncore/multimedia/opieplayer2/mediawidget.h | 1 | ||||
-rw-r--r-- | noncore/multimedia/opieplayer2/skin.cpp | 115 | ||||
-rw-r--r-- | noncore/multimedia/opieplayer2/skin.h | 53 |
5 files changed, 148 insertions, 31 deletions
diff --git a/noncore/multimedia/opieplayer2/mediaplayer.cpp b/noncore/multimedia/opieplayer2/mediaplayer.cpp index bbc60dd..963e783 100644 --- a/noncore/multimedia/opieplayer2/mediaplayer.cpp +++ b/noncore/multimedia/opieplayer2/mediaplayer.cpp @@ -1,154 +1,159 @@ #include <qpe/qpeapplication.h> #include <qpe/qlibrary.h> #include <qpe/resource.h> #include <qpe/config.h> #include <qpe/qcopenvelope_qws.h> #include <qfileinfo.h> #include <qmainwindow.h> #include <qmessagebox.h> #include <qwidgetstack.h> #include <qfile.h> #include "mediaplayer.h" #include "playlistwidget.h" #include "audiowidget.h" #include "videowidget.h" #include "volumecontrol.h" #include "mediaplayerstate.h" // for setBacklight() #include <linux/fb.h> #include <sys/file.h> #include <sys/ioctl.h> #define FBIOBLANK 0x4611 MediaPlayer::MediaPlayer( PlayListWidget &_playList, MediaPlayerState &_mediaPlayerState, QObject *parent, const char *name ) : QObject( parent, name ), volumeDirection( 0 ), mediaPlayerState( _mediaPlayerState ), playList( _playList ) { m_audioUI = 0; m_videoUI = 0; m_xineControl = 0; fd=-1;fl=-1; playList.setCaption( tr( "OpiePlayer: Initializating" ) ); qApp->processEvents(); // QPEApplication::grabKeyboard(); // EVIL connect( qApp,SIGNAL( aboutToQuit()),SLOT( cleanUp()) ); connect( &mediaPlayerState, SIGNAL( playingToggled( bool ) ), this, SLOT( setPlaying( bool ) ) ); // What is pauseCheck good for? (Simon) // connect( &mediaPlayerState, SIGNAL( pausedToggled( bool ) ), this, SLOT( pauseCheck( bool ) ) ); connect( &mediaPlayerState, SIGNAL( next() ), this, SLOT( next() ) ); connect( &mediaPlayerState, SIGNAL( prev() ), this, SLOT( prev() ) ); connect( &mediaPlayerState, SIGNAL( blankToggled( bool ) ), this, SLOT ( blank( bool ) ) ); volControl = new VolumeControl; Config cfg( "OpiePlayer" ); cfg.setGroup("PlayList"); QString currentPlaylist = cfg.readEntry( "CurrentPlaylist", "default"); playList.setCaption( tr( "OpiePlayer: " ) + QFileInfo(currentPlaylist).baseName() ); + + m_skinLoader = new SkinLoader; + m_skinLoader->schedule( AudioWidget::guiInfo() ); + m_skinLoader->schedule( VideoWidget::guiInfo() ); + m_skinLoader->start(); } MediaPlayer::~MediaPlayer() { delete m_xineControl; delete m_audioUI; delete m_videoUI; delete volControl; } void MediaPlayer::pauseCheck( bool b ) { if ( b && !mediaPlayerState.isPlaying() ) { mediaPlayerState.setPaused( FALSE ); } } void MediaPlayer::play() { mediaPlayerState.setPlaying( FALSE ); mediaPlayerState.setPlaying( TRUE ); } void MediaPlayer::setPlaying( bool play ) { if ( !play ) { return; } if ( mediaPlayerState.isPaused() ) { mediaPlayerState.setPaused( FALSE ); return; } QString tickerText, time, fileName; if ( playList.currentTab() != PlayListWidget::CurrentPlayList ) { //if playing in file list.. play in a different way // random and looping settings enabled causes problems here, // since there is no selected file in the playlist, but a selected file in the file list, // so we remember and shutoff l = mediaPlayerState.isLooping(); if(l) { mediaPlayerState.setLooping( false ); } r = mediaPlayerState.isShuffled(); mediaPlayerState.setShuffled( false ); } PlayListWidget::Entry playListEntry = playList.currentEntry(); fileName = playListEntry.name; xineControl()->play( playListEntry.file ); long seconds = mediaPlayerState.length(); time.sprintf("%li:%02i", seconds/60, (int)seconds%60 ); if( fileName.left(4) == "http" ) { fileName = QFileInfo( fileName ).baseName(); if ( xineControl()->getMetaInfo().isEmpty() ) { tickerText = tr( " File: " ) + fileName; } else { tickerText = xineControl()->getMetaInfo(); } } else { if ( xineControl()->getMetaInfo().isEmpty() ) { tickerText = tr( " File: " ) + fileName + tr( ", Length: " ) + time + " "; } else { tickerText = xineControl()->getMetaInfo() + " Length: " + time + " "; } } audioUI()->setTickerText( tickerText ); } void MediaPlayer::prev() { if( playList.currentTab() == PlayListWidget::CurrentPlayList ) { //if using the playlist if ( playList.prev() ) { play(); } else if ( mediaPlayerState.isLooping() ) { if ( playList.last() ) { play(); } } else { mediaPlayerState.setList(); } } } void MediaPlayer::next() { if(playList.currentTab() == PlayListWidget::CurrentPlayList) { //if using the playlist if ( playList.next() ) { play(); } else if ( mediaPlayerState.isLooping() ) { if ( playList.first() ) { play(); } } else { mediaPlayerState.setList(); } @@ -254,142 +259,144 @@ void MediaPlayer::timerEvent( QTimerEvent * ) { if ( drawnOnScreenDisplay ) { if ( onScreenDisplayVolume > v ) { videoUI()->repaint( (w - 200) / 2 + v * 20 + 0, h - yoff + 40, ( onScreenDisplayVolume - v ) * 20 + 9, 30, FALSE ); } } drawnOnScreenDisplay = TRUE; onScreenDisplayVolume = v; QPainter p( videoUI() ); p.setPen( QColor( 0x10, 0xD0, 0x10 ) ); p.setBrush( QColor( 0x10, 0xD0, 0x10 ) ); QFont f; f.setPixelSize( 20 ); f.setBold( TRUE ); p.setFont( f ); p.drawText( (w - 200) / 2, h - yoff + 20, tr( "Volume" ) ); for ( unsigned int i = 0; i < 10; i++ ) { if ( v > i ) { p.drawRect( (w - 200) / 2 + i * 20 + 0, h - yoff + 40, 9, 30 ); } else { p.drawRect( (w - 200) / 2 + i * 20 + 3, h - yoff + 50, 3, 10 ); } } } } void MediaPlayer::blank( bool b ) { fd=open("/dev/fb0",O_RDWR); #ifdef QT_QWS_EBX fl= open( "/dev/fl", O_RDWR ); #endif if (fd != -1) { if ( b ) { qDebug("do blanking"); #ifdef QT_QWS_EBX ioctl( fd, FBIOBLANK, 1 ); if(fl !=-1) { ioctl( fl, 2 ); ::close(fl); } #else ioctl( fd, FBIOBLANK, 3 ); #endif isBlanked = TRUE; } else { qDebug("do unblanking"); ioctl( fd, FBIOBLANK, 0); #ifdef QT_QWS_EBX if(fl != -1) { ioctl( fl, 1); ::close(fl); } #endif isBlanked = FALSE; } close( fd ); } else { qDebug("<< /dev/fb0 could not be opened >>"); } } void MediaPlayer::keyReleaseEvent( QKeyEvent *e) { switch ( e->key() ) { ////////////////////////////// Zaurus keys case Key_Home: break; case Key_F9: //activity break; case Key_F10: //contacts break; case Key_F11: //menu break; case Key_F12: //home qDebug("Blank here"); // mediaPlayerState->toggleBlank(); break; case Key_F13: //mail qDebug("Blank here"); // mediaPlayerState->toggleBlank(); break; } } void MediaPlayer::cleanUp() {// this happens on closing Config cfg( "OpiePlayer" ); mediaPlayerState.writeConfig( cfg ); playList.writeDefaultPlaylist( ); // QPEApplication::grabKeyboard(); // QPEApplication::ungrabKeyboard(); } void MediaPlayer::recreateAudioAndVideoWidgets() const { + delete m_skinLoader; + delete m_xineControl; delete m_audioUI; delete m_videoUI; m_audioUI = new AudioWidget( playList, mediaPlayerState, 0, "audioUI" ); m_videoUI = new VideoWidget( playList, mediaPlayerState, 0, "videoUI" ); connect( m_audioUI, SIGNAL( moreClicked() ), this, SLOT( startIncreasingVolume() ) ); connect( m_audioUI, SIGNAL( lessClicked() ), this, SLOT( startDecreasingVolume() ) ); connect( m_audioUI, SIGNAL( moreReleased() ), this, SLOT( stopChangingVolume() ) ); connect( m_audioUI, SIGNAL( lessReleased() ), this, SLOT( stopChangingVolume() ) ); connect( m_videoUI, SIGNAL( moreClicked() ), this, SLOT( startIncreasingVolume() ) ); connect( m_videoUI, SIGNAL( lessClicked() ), this, SLOT( startDecreasingVolume() ) ); connect( m_videoUI, SIGNAL( moreReleased() ), this, SLOT( stopChangingVolume() ) ); connect( m_videoUI, SIGNAL( lessReleased() ), this, SLOT( stopChangingVolume() ) ); m_xineControl = new XineControl( m_videoUI->vidWidget(), mediaPlayerState ); } AudioWidget *MediaPlayer::audioUI() const { if ( !m_audioUI ) recreateAudioAndVideoWidgets(); return m_audioUI; } VideoWidget *MediaPlayer::videoUI() const { if ( !m_videoUI ) recreateAudioAndVideoWidgets(); return m_videoUI; } XineControl *MediaPlayer::xineControl() const { if ( !m_xineControl ) recreateAudioAndVideoWidgets(); return m_xineControl; } void MediaPlayer::reloadSkins() { audioUI()->loadSkin(); videoUI()->loadSkin(); } diff --git a/noncore/multimedia/opieplayer2/mediaplayer.h b/noncore/multimedia/opieplayer2/mediaplayer.h index 5975731..351c884 100644 --- a/noncore/multimedia/opieplayer2/mediaplayer.h +++ b/noncore/multimedia/opieplayer2/mediaplayer.h @@ -1,96 +1,99 @@ /* This file is part of the Opie Project Copyright (c) 2002 Max Reiss <harlekin@handhelds.org> Copyright (c) 2002 LJP <> Copyright (c) 2002 Holger Freyther <zecke@handhelds.org> =. .=l. .>+-= _;:, .> :=|. This program is free software; you can .> <`_, > . <= redistribute it and/or modify it under :`=1 )Y*s>-.-- : the terms of the GNU General Public .="- .-=="i, .._ License as published by the Free Software - . .-<_> .<> Foundation; either version 2 of the License, ._= =} : or (at your option) any later version. .%`+i> _;_. .i_,=:_. -<s. This program is distributed in the hope that + . -:. = it will be useful, but WITHOUT ANY WARRANTY; : .. .:, . . . without even the implied warranty of =_ + =;=|` MERCHANTABILITY or FITNESS FOR A _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU ..}^=.= = ; Library General Public License for more ++= -. .` .: details. : = ...= . :.=- -. .:....=;==+<; You should have received a copy of the GNU -_. . . )=. = Library General Public License along with -- :-=` this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef MEDIA_PLAYER_H #define MEDIA_PLAYER_H #include <qmainwindow.h> #include <qframe.h> #include "xinecontrol.h" #include "playlistwidget.h" +#include "skin.h" class DocLnk; class VolumeControl; class MediaPlayerState; class AudioWidget; class VideoWidget; class MediaPlayer : public QObject { Q_OBJECT public: MediaPlayer( PlayListWidget &_playList, MediaPlayerState &_mediaPlayerState, QObject *parent, const char *name ); ~MediaPlayer(); public slots: void reloadSkins(); private slots: void setPlaying( bool ); void pauseCheck( bool ); void play(); void next(); void prev(); void startIncreasingVolume(); void startDecreasingVolume(); void stopChangingVolume(); void cleanUp(); void blank( bool ); protected: void timerEvent( QTimerEvent *e ); void keyReleaseEvent( QKeyEvent *e); private: AudioWidget *audioUI() const; VideoWidget *videoUI() const; XineControl *xineControl() const; bool isBlanked, l, r; int fd, fl; int volumeDirection; VolumeControl *volControl; MediaPlayerState &mediaPlayerState; PlayListWidget &playList; void recreateAudioAndVideoWidgets() const; mutable XineControl *m_xineControl; mutable AudioWidget *m_audioUI; mutable VideoWidget *m_videoUI; + + QGuardedPtr<SkinLoader> m_skinLoader; }; #endif // MEDIA_PLAYER_H diff --git a/noncore/multimedia/opieplayer2/mediawidget.h b/noncore/multimedia/opieplayer2/mediawidget.h index 40eb0af..45c46ea 100644 --- a/noncore/multimedia/opieplayer2/mediawidget.h +++ b/noncore/multimedia/opieplayer2/mediawidget.h @@ -1,167 +1,168 @@ /* Copyright (C) 2002 Simon Hausmann <simon@lst.de> (C) 2002 Max Reiss <harlekin@handhelds.org> (C) 2002 L. Potter <ljp@llornkcor.com> (C) 2002 Holger Freyther <zecke@handhelds.org> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef MEDIAWIDGET_H #define MEDIAWIDGET_H #include <qwidget.h> #include <qmap.h> #include "mediaplayerstate.h" #include "playlistwidget.h" #include <vector> #include <memory> namespace { struct simpleAndStupidAllocator { static void *allocate( size_t amount ) { return ::operator new( amount ); } static void deallocate( void *p, size_t ) { ::operator delete( p ); } }; } class Skin; class MediaWidget : public QWidget { Q_OBJECT public: enum Command { Play = 0, Stop, Next, Previous, VolumeUp, VolumeDown, Loop, PlayList, Forward, Back, FullScreen, Undefined }; enum ButtonType { NormalButton, ToggleButton }; struct Button { Button() : command( Undefined ), type( NormalButton ), isDown( false ) {} Command command; ButtonType type; // this should be part of the bitfield but gcc2 is too buggy to support this :-( bool isDown : 1; QBitmap mask; QPixmap pixUp; QPixmap pixDown; }; #if defined( _CC_GNU_ ) // use that allocator to avoid the default allocator that on gcc2 requires libstdc++ because // in the BAD_ALLOC macro it uses std::cerr and friends :-( typedef std::vector<Button, std::__allocator<Button, simpleAndStupidAllocator> > ButtonVector; #else typedef std::vector<Button> ButtonVector; #endif struct SkinButtonInfo { Command command; const char *fileName; ButtonType type; }; struct GUIInfo { GUIInfo() : buttonInfo( 0 ), buttonCount( 0 ) {} GUIInfo( const QString &_fileNameInfix, const SkinButtonInfo *_buttonInfo, const uint _buttonCount ) : fileNameInfix( _fileNameInfix ), buttonInfo( _buttonInfo ), buttonCount( _buttonCount ) {} QString fileNameInfix; const SkinButtonInfo *buttonInfo; const uint buttonCount; }; + typedef QValueList<GUIInfo> GUIInfoList; MediaWidget( PlayListWidget &_playList, MediaPlayerState &_mediaPlayerState, QWidget *parent = 0, const char *name = 0 ); virtual ~MediaWidget(); public slots: virtual void setDisplayType( MediaPlayerState::DisplayType displayType ) = 0; virtual void setLength( long length ) = 0; virtual void setPlaying( bool playing ) = 0; virtual void loadSkin() = 0; signals: void moreReleased(); void lessReleased(); void forwardReleased(); void backReleased(); void forwardClicked(); void backClicked(); void moreClicked(); void lessClicked(); protected: void setupButtons( const SkinButtonInfo *skinInfo, uint buttonCount, const Skin &skin ); Button setupButton( const SkinButtonInfo &buttonInfo, const Skin &skin ); void loadDefaultSkin( const GUIInfo &guiInfo ); void loadSkin( const SkinButtonInfo *skinInfo, uint buttonCount, const Skin &skin ); virtual void closeEvent( QCloseEvent * ); virtual void paintEvent( QPaintEvent *pe ); virtual void resizeEvent( QResizeEvent *e ); Button *buttonAt( const QPoint &position ); virtual void mousePressEvent( QMouseEvent *event ); virtual void mouseReleaseEvent( QMouseEvent *event ); virtual void makeVisible(); void handleCommand( Command command, bool buttonDown ); bool isOverButton( const QPoint &position, int buttonId ) const; void paintAllButtons( QPainter &p ); void paintButton( const Button &button ); void paintButton( QPainter &p, const Button &button ); void setToggleButton( Button &button, bool down ); void setToggleButton( Command command, bool down ); void toggleButton( Button &button ); MediaPlayerState &mediaPlayerState; PlayListWidget &playList; ButtonVector buttons; QImage buttonMask; QPoint upperLeftOfButtonMask; QPixmap backgroundPixmap; QImage buttonUpImage; QImage buttonDownImage; static QPixmap combineImageWithBackground( const QImage &background, const QPixmap &pixmap, const QPoint &offset ); static QPixmap addMaskToPixmap( const QPixmap &pix, const QBitmap &mask ); }; #endif // MEDIAWIDGET_H /* vim: et sw=4 ts=4 */ diff --git a/noncore/multimedia/opieplayer2/skin.cpp b/noncore/multimedia/opieplayer2/skin.cpp index 0f49862..e9fb5a6 100644 --- a/noncore/multimedia/opieplayer2/skin.cpp +++ b/noncore/multimedia/opieplayer2/skin.cpp @@ -1,241 +1,328 @@ /* Copyright (C) 2002 Simon Hausmann <simon@lst.de> (C) 2002 Max Reiss <harlekin@handhelds.org> (C) 2002 L. Potter <ljp@llornkcor.com> (C) 2002 Holger Freyther <zecke@handhelds.org> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "skin.h" #include "singleton.h" #include <qcache.h> #include <qmap.h> +#include <qtimer.h> #include <qpe/resource.h> #include <qpe/config.h> #include <assert.h> struct SkinData { typedef QMap<QString, QImage> ButtonMaskImageMap; QImage backgroundImage; QImage buttonUpImage; QImage buttonDownImage; QImage buttonMask; ButtonMaskImageMap buttonMasks; }; class SkinCache : public Singleton<SkinCache> { public: SkinCache(); SkinData *lookupAndTake( const QString &skinPath, const QString &fileNameInfix ); void store( const QString &skinPath, const QString &fileNameInfix, SkinData *data ); private: typedef QCache<SkinData> DataCache; typedef QCache<QImage> BackgroundImageCache; template <class CacheType> void store( const QCache<CacheType> &cache, const QString &key, CacheType *data ); DataCache m_cache; BackgroundImageCache m_backgroundImageCache; }; Skin::Skin( const QString &name, const QString &fileNameInfix ) : m_fileNameInfix( fileNameInfix ) { init( name ); } Skin::Skin( const QString &fileNameInfix ) : m_fileNameInfix( fileNameInfix ) { init( defaultSkinName() ); } Skin::~Skin() { SkinCache::self().store( m_skinPath, m_fileNameInfix, d ); } void Skin::init( const QString &name ) { m_skinPath = "opieplayer2/skins/" + name; d = SkinCache::self().lookupAndTake( m_skinPath, m_fileNameInfix ); } void Skin::preload( const MediaWidget::SkinButtonInfo *skinButtonInfo, uint buttonCount ) { backgroundImage(); buttonUpImage(); buttonDownImage(); ( void )buttonMask( skinButtonInfo, buttonCount ); } QImage Skin::backgroundImage() const { if ( d->backgroundImage.isNull() ) d->backgroundImage = loadImage( QString( "%1/background" ).arg( m_skinPath ) ); return d->backgroundImage; } QImage Skin::buttonUpImage() const { if ( d->buttonUpImage.isNull() ) d->buttonUpImage = loadImage( QString( "%1/skin%2_up" ).arg( m_skinPath ).arg( m_fileNameInfix ) ); return d->buttonUpImage; } QImage Skin::buttonDownImage() const { if ( d->buttonDownImage.isNull() ) d->buttonDownImage = loadImage( QString( "%1/skin%2_down" ).arg( m_skinPath ).arg( m_fileNameInfix ) ); return d->buttonDownImage; } QImage Skin::buttonMask( const MediaWidget::SkinButtonInfo *skinButtonInfo, uint buttonCount ) const { if ( !d->buttonMask.isNull() ) return d->buttonMask; QSize buttonAreaSize = buttonUpImage().size(); d->buttonMask = QImage( buttonAreaSize, 8, 255 ); d->buttonMask.fill( 0 ); for ( uint i = 0; i < buttonCount; ++i ) addButtonToMask( skinButtonInfo[ i ].command + 1, buttonMaskImage( skinButtonInfo[ i ].fileName ) ); return d->buttonMask; } void Skin::addButtonToMask( int tag, const QImage &maskImage ) const { if ( maskImage.isNull() ) return; uchar **dest = d->buttonMask.jumpTable(); for ( int y = 0; y < d->buttonMask.height(); y++ ) { uchar *line = dest[y]; for ( int x = 0; x < d->buttonMask.width(); x++ ) if ( !qRed( maskImage.pixel( x, y ) ) ) line[x] = tag; } } QImage Skin::buttonMaskImage( const QString &fileName ) const { SkinData::ButtonMaskImageMap::Iterator it = d->buttonMasks.find( fileName ); if ( it == d->buttonMasks.end() ) { QString prefix = m_skinPath + QString::fromLatin1( "/skin%1_mask_" ).arg( m_fileNameInfix ); QString path = prefix + fileName + ".png"; it = d->buttonMasks.insert( fileName, loadImage( path ) ); } return *it; } QString Skin::defaultSkinName() { Config cfg( "OpiePlayer" ); cfg.setGroup( "Options" ); return cfg.readEntry( "Skin", "default" ); } QImage Skin::loadImage( const QString &fileName ) { return QImage( Resource::findPixmap( fileName ) ); } SkinCache::SkinCache() { // let's say we cache two skins (audio+video) at maximum m_cache.setMaxCost( 2 ); // ... and one background pixmap m_backgroundImageCache.setMaxCost( 1 ); } SkinData *SkinCache::lookupAndTake( const QString &skinPath, const QString &fileNameInfix ) { QString key = skinPath + fileNameInfix; SkinData *data = m_cache.take( key ); if ( !data ) data = new SkinData; + else + qDebug( "SkinCache: hit" ); QImage *bgImage = m_backgroundImageCache.find( skinPath ); - if ( bgImage ) + if ( bgImage ) { + qDebug( "SkinCache: hit on bgimage" ); data->backgroundImage = *bgImage; + } else data->backgroundImage = QImage(); return data; } void SkinCache::store( const QString &skinPath, const QString &fileNameInfix, SkinData *data ) { QImage *backgroundImage = new QImage( data->backgroundImage ); data->backgroundImage = QImage(); QString key = skinPath + fileNameInfix; if ( m_cache.find( key, false /*ref*/ ) != 0 || !m_cache.insert( key, data ) ) delete data; if ( m_backgroundImageCache.find( skinPath, false /*ref*/ ) != 0 || !m_backgroundImageCache.insert( skinPath, backgroundImage ) ) delete backgroundImage; } +SkinLoader::IncrementalLoader::IncrementalLoader( const Info &info ) + : m_skin( info.skinName, info.fileNameInfix ), m_info( info ) +{ + m_currentState = LoadBackgroundImage; +} + +SkinLoader::IncrementalLoader::LoaderResult SkinLoader::IncrementalLoader::loadStep() +{ + switch ( m_currentState ) { + case LoadBackgroundImage: + qDebug( "load bgimage" ); + m_skin.backgroundImage(); + m_currentState = LoadButtonUpImage; + break; + case LoadButtonUpImage: + qDebug( "load upimage" ); + m_skin.buttonUpImage(); + m_currentState = LoadButtonDownImage; + break; + case LoadButtonDownImage: + qDebug( "load downimage" ); + m_skin.buttonDownImage(); + m_currentState = LoadButtonMasks; + m_currentButton = 0; + break; + case LoadButtonMasks: + qDebug( "load button masks %i", m_currentButton ); + m_skin.buttonMaskImage( m_info.buttonInfo[ m_currentButton ].fileName ); + + m_currentButton++; + if ( m_currentButton >= m_info.buttonCount ) + m_currentState = LoadButtonMask; + + break; + case LoadButtonMask: + qDebug( "load whole mask" ); + m_skin.buttonMask( m_info.buttonInfo, m_info.buttonCount ); + return LoadingCompleted; + } + + return MoreToCome; +} + SkinLoader::SkinLoader() + : m_currentLoader( 0 ), m_timerId( -1 ) { } -void SkinLoader::schedule( const QString &skinName, const QString &fileNameInfix, - const MediaWidget::SkinButtonInfo *skinButtonInfo, const uint buttonCount ) +SkinLoader::~SkinLoader() { - assert( isRunning() == false ); + qDebug( "SkinLoader::~SkinLoader()" ); + killTimers(); + delete m_currentLoader; +} - pendingSkins << Info( skinName, fileNameInfix, skinButtonInfo, buttonCount ); +void SkinLoader::schedule( const MediaWidget::GUIInfo &guiInfo ) +{ + schedule( Skin::defaultSkinName(), guiInfo ); } -void SkinLoader::run() +void SkinLoader::schedule( const QString &skinName, const MediaWidget::GUIInfo &guiInfo ) { - qDebug( "SkinLoader::run()" ); - for ( InfoList::ConstIterator it = pendingSkins.begin(); it != pendingSkins.end(); ++it ) - load( *it ); - qDebug( "SkinLoader is done." ); + pendingSkins << Info( skinName, guiInfo ); } -void SkinLoader::load( const Info &nfo ) +void SkinLoader::start() { - qDebug( "preloading %s with infix %s", nfo.skinName.ascii(), nfo.fileNameInfix.ascii() ); + assert( m_timerId == -1 ); + m_timerId = startTimer( 100 /* ms */ ); + qDebug( "SkinLoader::start() %d jobs", pendingSkins.count() ); +} - Skin skin( nfo.skinName, nfo.fileNameInfix ); - skin.preload( nfo.skinButtonInfo, nfo.buttonCount ); +void SkinLoader::timerEvent( QTimerEvent *ev ) +{ + if ( ev->timerId() != m_timerId ) { + QObject::timerEvent( ev ); + return; + } + + if ( !m_currentLoader ) { + + if ( pendingSkins.isEmpty() ) { + qDebug( "all jobs done" ); + killTimer( m_timerId ); + m_timerId = -1; + // ### qt3: use deleteLater(); + QTimer::singleShot( 0, this, SLOT( deleteMe() ) ); + return; + } + + Info nfo = *pendingSkins.begin(); + pendingSkins.remove( pendingSkins.begin() ); + + m_currentLoader = new IncrementalLoader( nfo ); + qDebug( "new loader %i jobs left", pendingSkins.count() ); + } + + if ( m_currentLoader->loadStep() == IncrementalLoader::LoadingCompleted ) { + delete m_currentLoader; + m_currentLoader = 0; + } + + qDebug( "finished step" ); +} + +void SkinLoader::deleteMe() +{ + delete this; } /* vim: et sw=4 ts=4 */ diff --git a/noncore/multimedia/opieplayer2/skin.h b/noncore/multimedia/opieplayer2/skin.h index 9180067..a43a1d0 100644 --- a/noncore/multimedia/opieplayer2/skin.h +++ b/noncore/multimedia/opieplayer2/skin.h @@ -1,105 +1,124 @@ /* Copyright (C) 2002 Simon Hausmann <simon@lst.de> (C) 2002 Max Reiss <harlekin@handhelds.org> (C) 2002 L. Potter <ljp@llornkcor.com> (C) 2002 Holger Freyther <zecke@handhelds.org> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef SKIN_H #define SKIN_H #include <qstring.h> #include <qimage.h> +#include <qobject.h> #include "mediawidget.h" -#include "threadutil.h" struct SkinData; class Skin { public: Skin( const QString &name, const QString &fileNameInfix ); Skin( const QString &fileNameInfix ); ~Skin(); void preload( const MediaWidget::SkinButtonInfo *skinButtonInfo, uint buttonCount ); QImage backgroundImage() const; QImage buttonUpImage() const; QImage buttonDownImage() const; QImage buttonMask( const MediaWidget::SkinButtonInfo *skinButtonInfo, uint buttonCount ) const; QImage buttonMaskImage( const QString &fileName ) const; static QString defaultSkinName(); private: void init( const QString &name ); void addButtonToMask( int tag, const QImage &maskImage ) const; static QImage loadImage( const QString &fileName ); QString m_fileNameInfix; QString m_skinPath; SkinData *d; Skin( const Skin & ); Skin &operator=( const Skin & ); }; -class SkinLoader : public ThreadUtil::Thread +class SkinLoader : public QObject { + Q_OBJECT public: SkinLoader(); + virtual ~SkinLoader(); - void schedule( const QString &skinName, const QString &fileNameInfix, - const MediaWidget::SkinButtonInfo *skinButtonInfo, const uint buttonCount ); + void schedule( const MediaWidget::GUIInfo &guiInfo ); + void schedule( const QString &skinName, const MediaWidget::GUIInfo &guiInfo ); + + void start(); protected: - virtual void run(); + virtual void timerEvent( QTimerEvent *ev ); + +private slots: + void deleteMe(); private: - struct Info + struct Info : public MediaWidget::GUIInfo { - Info() : skinButtonInfo( 0 ), buttonCount( 0 ) {} - Info( const QString &_skinName, const QString &_fileNameInfix, - const MediaWidget::SkinButtonInfo *_skinButtonInfo, const uint _buttonCount ) - : skinName( _skinName ), fileNameInfix( _fileNameInfix ), - skinButtonInfo( _skinButtonInfo ), buttonCount( _buttonCount ) + Info() {} + Info( const QString &_skinName, const MediaWidget::GUIInfo &guiInfo ) + : MediaWidget::GUIInfo( guiInfo ), skinName( _skinName ) {} - const QString skinName; - const QString fileNameInfix; - const MediaWidget::SkinButtonInfo *skinButtonInfo; - const uint buttonCount; + QString skinName; }; typedef QValueList<Info> InfoList; - void load( const Info &nfo ); + class IncrementalLoader + { + public: + enum LoaderResult { LoadingCompleted, MoreToCome }; + + IncrementalLoader( const Info &info ); + + LoaderResult loadStep(); + + private: + enum State { LoadBackgroundImage, LoadButtonUpImage, LoadButtonDownImage, LoadButtonMasks, LoadButtonMask }; + + Skin m_skin; + Info m_info; + State m_currentState; + uint m_currentButton; + }; InfoList pendingSkins; - ThreadUtil::Mutex guard; + IncrementalLoader *m_currentLoader; + int m_timerId; }; #endif // SKIN_H /* vim: et sw=4 ts=4 */ |