aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar Alexey Uzhva2008-08-14 18:05:27 +0000
committerGravatar Alexey Uzhva2008-08-14 18:05:27 +0000
commit8d6cbf0f025dab052ae4e16e451f65906c5f24b6 (patch)
treee1b7cae96c4561f32e566c93005c44d77c8aae78 /src
parentupdated german translation (diff)
downloadKVIrc-8d6cbf0f025dab052ae4e16e451f65906c5f24b6.tar.gz
KVIrc-8d6cbf0f025dab052ae4e16e451f65906c5f24b6.tar.bz2
KVIrc-8d6cbf0f025dab052ae4e16e451f65906c5f24b6.zip
animation tweaks: now uses 1 shared timer for all animated pixmaps
git-svn-id: https://svn.kvirc.de/svn/trunk/kvirc@2245 17fca916-40b9-46aa-a4ea-0a15b648b75c
Diffstat (limited to 'src')
-rw-r--r--src/kvilib/CMakeLists.txt1
-rw-r--r--src/kvilib/ext/kvi_animatedpixmap.cpp17
-rw-r--r--src/kvilib/ext/kvi_animatedpixmap.h19
-rw-r--r--src/kvilib/ext/kvi_animatedpixmapcache.cpp137
-rw-r--r--src/kvilib/ext/kvi_animatedpixmapcache.h24
-rw-r--r--src/kvilib/irc/kvi_avatar.h9
-rw-r--r--src/kvilib/system/kvi_time.cpp8
-rw-r--r--src/kvilib/system/kvi_time.h1
-rw-r--r--src/kvirc/kernel/kvi_iconmanager.cpp15
-rw-r--r--src/kvirc/ui/kvi_console.cpp9
-rw-r--r--src/kvirc/ui/kvi_ircview.cpp2
11 files changed, 210 insertions, 32 deletions
diff --git a/src/kvilib/CMakeLists.txt b/src/kvilib/CMakeLists.txt
index 09aaa9476..80e6eee8b 100644
--- a/src/kvilib/CMakeLists.txt
+++ b/src/kvilib/CMakeLists.txt
@@ -40,6 +40,7 @@ SET(kvilib_MOC_HDRS
tal/kvi_tal_vbox.h
tal/kvi_tal_widgetstack.h
tal/kvi_tal_wizard.h
+ ext/kvi_animatedpixmapcache.h
)
IF(COMPILE_KDE_SUPPORT)
diff --git a/src/kvilib/ext/kvi_animatedpixmap.cpp b/src/kvilib/ext/kvi_animatedpixmap.cpp
index 33c079bce..bd2631fe1 100644
--- a/src/kvilib/ext/kvi_animatedpixmap.cpp
+++ b/src/kvilib/ext/kvi_animatedpixmap.cpp
@@ -8,6 +8,7 @@
#include "kvi_animatedpixmap.h"
#include "kvi_settings.h"
#include <QImageReader>
+#include <QTime>
#include <QHash>
#include <QMutexLocker>
@@ -17,8 +18,6 @@ KviAnimatedPixmap::KviAnimatedPixmap(QString fileName)
m_bStarted = 0;
m_uCurrentFrameNumber = 0;
- connect(&m_timer,SIGNAL(timeout()),this,SLOT(animationTimerShot()));
-
m_lFrames=KviAnimatedPixmapCache::load(fileName);
start();
}
@@ -30,20 +29,17 @@ KviAnimatedPixmap::KviAnimatedPixmap(KviAnimatedPixmap* source)
m_lFrames(source->m_lFrames)
{
m_lFrames->refs++;
- connect(&m_timer,SIGNAL(timeout()),this,SLOT(animationTimerShot()));
//restore started state
if(isStarted() && (framesCount()>1))
{
- m_timer.start(m_lFrames->at(m_uCurrentFrameNumber).delay);
+ KviAnimatedPixmapCache::sceduleFrameChange(m_lFrames->at(m_uCurrentFrameNumber).delay,this);
}
}
KviAnimatedPixmap::~KviAnimatedPixmap()
{
- // all pixmaps will be automagically deleted at
- // FrameInfo::~FrameInfo destructor:))
-
+ KviAnimatedPixmapCache::notifyDelete(this);
KviAnimatedPixmapCache::free(m_lFrames);
}
@@ -51,7 +47,7 @@ void KviAnimatedPixmap::start()
{
if(!isStarted() && (framesCount()>1))
{
- m_timer.start(m_lFrames->at(m_uCurrentFrameNumber).delay);
+ KviAnimatedPixmapCache::sceduleFrameChange(m_lFrames->at(m_uCurrentFrameNumber).delay,this);
m_bStarted = true;
}
}
@@ -60,12 +56,11 @@ void KviAnimatedPixmap::stop()
{
if(isStarted())
{
- m_timer.stop();
m_bStarted = false;
}
}
-void KviAnimatedPixmap::animationTimerShot()
+void KviAnimatedPixmap::nextFrame()
{
m_uCurrentFrameNumber++;
//Ensure, that we are not out of bounds
@@ -74,7 +69,7 @@ void KviAnimatedPixmap::animationTimerShot()
emit(frameChanged());
//run timer again
- m_timer.start(m_lFrames->at(m_uCurrentFrameNumber).delay);
+ KviAnimatedPixmapCache::sceduleFrameChange(m_lFrames->at(m_uCurrentFrameNumber).delay,this);
}
void KviAnimatedPixmap::resize(QSize newSize,Qt::AspectRatioMode ratioMode)
diff --git a/src/kvilib/ext/kvi_animatedpixmap.h b/src/kvilib/ext/kvi_animatedpixmap.h
index 5a54f9dc5..e9c2c2e49 100644
--- a/src/kvilib/ext/kvi_animatedpixmap.h
+++ b/src/kvilib/ext/kvi_animatedpixmap.h
@@ -48,13 +48,12 @@
* This class owns all pixmaps. Do not store links to them.
*/
-class KVILIB_API KviAnimatedPixmap : public QObject{
+class KVILIB_API KviAnimatedPixmap : public QObject , public KviAnimatedPixmapInterface{
Q_OBJECT
protected:
QString m_szFileName;
KviAnimatedPixmapCache::Data* m_lFrames;
- QTimer m_timer;
uint m_uCurrentFrameNumber;
bool m_bStarted;
@@ -100,14 +99,15 @@ public:
}
/*
- * Returns active frame's pixmap
+ * Returns active frame's pixmap.
+ * Never fails.
*/
inline QPixmap* pixmap()
{
if(m_lFrames->count()>0)
return m_lFrames->at(m_uCurrentFrameNumber).pixmap;
else
- return 0;
+ return KviAnimatedPixmapCache::dummyPixmap();
}
/*
@@ -140,17 +140,16 @@ public:
*/
void resize(QSize newSize,Qt::AspectRatioMode ratioMode);
-protected slots:
-
/*
- * Slot, to be connected to m_animationTimer, to receive animation
- * frame changes.
+ * Called when the frame changes
*/
- void animationTimerShot();
+ void nextFrame();
signals:
+
/*
- * This signal emitted when active frame changes
+ * Slot, to be connected to m_animationTimer, to receive animation
+ * frame changes.
*/
void frameChanged();
};
diff --git a/src/kvilib/ext/kvi_animatedpixmapcache.cpp b/src/kvilib/ext/kvi_animatedpixmapcache.cpp
index 4e997ad39..38d3ec18b 100644
--- a/src/kvilib/ext/kvi_animatedpixmapcache.cpp
+++ b/src/kvilib/ext/kvi_animatedpixmapcache.cpp
@@ -8,15 +8,23 @@
#include <kvi_animatedpixmapcache.h>
#include <QImageReader>
#include <QImage>
+#include "kvi_time.h"
static KviAnimatedPixmapCache* g_pAnimatedCache = 0;
+static QPixmap* g_pDummyPixmap = 0;
-KviAnimatedPixmapCache::KviAnimatedPixmapCache() {
+KviAnimatedPixmapCache::KviAnimatedPixmapCache()
+{
g_pAnimatedCache = this;
+ m_animationTimer.setSingleShot(true);
+ connect(&m_animationTimer,SIGNAL(timeout()),this,SLOT(timerEvent()));
}
KviAnimatedPixmapCache::~KviAnimatedPixmapCache() {
- // TODO Auto-generated destructor stub
+ if(g_pDummyPixmap) {
+ delete g_pDummyPixmap;
+ }
+ g_pAnimatedCache = 0;
}
KviAnimatedPixmapCache::Data* KviAnimatedPixmapCache::internalLoad(QString szFile) {
@@ -135,3 +143,128 @@ void KviAnimatedPixmapCache::free(KviAnimatedPixmapCache::Data* data) {
}
g_pAnimatedCache->internalFree(data);
}
+
+void KviAnimatedPixmapCache::internalSceduleFrameChange(uint delay,KviAnimatedPixmapInterface* receiver)
+{
+ debug("Adding %i - %i",(uint)KviTimeUtils::getCurrentTimeMills()+delay,receiver);
+ m_timerMutex.lock();
+ bool needTimerChange = false;
+ long long when = KviTimeUtils::getCurrentTimeMills()+delay;
+
+ if(m_timerData.isEmpty())
+ {
+
+ m_timerData.insert(when,receiver);
+ needTimerChange = true;
+
+ } else {
+ long long currentNext = m_timerData.begin().key();
+
+ if(when<currentNext){
+ needTimerChange = true;
+ }
+
+ m_timerData.insert(when,receiver);
+ }
+
+ if(needTimerChange)
+ {
+ m_animationTimer.start(delay);
+ }
+
+ m_timerMutex.unlock();
+}
+
+void KviAnimatedPixmapCache::timerEvent()
+{
+ /*
+ * We are adding 15msecs to the current time. This MAY lead to the situation,
+ * when the current frame will be painted a bit earlier, then i should.
+ * But we are just playing animated gifs, not a HDTV video. So it should be ok.
+ *
+ * But it makes good speedup if there will be event, sceduled in such order:
+ * 1 event at time X
+ * 3 events at time X+2msec
+ * 2 events at time X+6msec
+ * 1 event at time X+8msec
+ * 1 event at time X+9msec
+ * 1 event at time X+12msec
+ * ...
+ *
+ * Such situation is possible if we will have lots of smiles with almost the same
+ * frame delays.
+ *
+ * So it will not emit additional 5 events.
+ */
+ long long now = KviTimeUtils::getCurrentTimeMills() + 15;
+
+// m_timerMutex.lock();
+
+ QMultiMap<long long, KviAnimatedPixmapInterface*>::iterator i =
+ m_timerData.begin();
+
+ while (i != m_timerData.end() && i.key() <= now)
+ {
+ i.value()->nextFrame();
+ debug("Calling %i - %i",(uint)KviTimeUtils::getCurrentTimeMills(),i.value());
+ i = m_timerData.erase(i);
+ }
+
+ if (i != m_timerData.end())
+ {
+ long long nextDelay = i.key();
+ uint delay = (uint) (nextDelay - KviTimeUtils::getCurrentTimeMills());
+ if (delay < 0)
+ {
+ delay = 0;
+ }
+ m_animationTimer.start(delay);
+ }
+// m_timerMutex.unlock();
+}
+
+void KviAnimatedPixmapCache::sceduleFrameChange(uint when,KviAnimatedPixmapInterface* receiver)
+{
+ if (g_pAnimatedCache)
+ {
+ g_pAnimatedCache->internalSceduleFrameChange(when,receiver);
+ }
+}
+
+QPixmap* KviAnimatedPixmapCache::dummyPixmap()
+{
+ if(!g_pDummyPixmap)
+ {
+ g_pDummyPixmap = new QPixmap();
+ }
+ return g_pDummyPixmap;
+}
+
+void KviAnimatedPixmapCache::internalNotifyDelete(
+ KviAnimatedPixmapInterface* receiver)
+{
+ m_timerMutex.lock();
+
+ QMultiMap<long long, KviAnimatedPixmapInterface*>::iterator i =
+ m_timerData.begin();
+
+ while (i != m_timerData.end())
+ {
+ if (i.value() == receiver)
+ {
+ i = m_timerData.erase(i);
+ } else {
+ i++;
+ }
+ }
+
+ m_timerMutex.unlock();
+}
+
+void KviAnimatedPixmapCache::notifyDelete(KviAnimatedPixmapInterface* receiver)
+{
+ if (g_pAnimatedCache)
+ {
+ g_pAnimatedCache->internalNotifyDelete(receiver);
+ }
+}
diff --git a/src/kvilib/ext/kvi_animatedpixmapcache.h b/src/kvilib/ext/kvi_animatedpixmapcache.h
index 9fe558688..76c8037d4 100644
--- a/src/kvilib/ext/kvi_animatedpixmapcache.h
+++ b/src/kvilib/ext/kvi_animatedpixmapcache.h
@@ -11,9 +11,16 @@
#include <QMutex>
#include <QPixmap>
#include <QMultiHash>
+#include <QMultiMap>
+#include <QTimer>
-class KviAnimatedPixmapCache {
+class KviAnimatedPixmapInterface {
+ public:
+ virtual void nextFrame() = 0;
+};
+class KviAnimatedPixmapCache : public QObject {
+ Q_OBJECT
public:
/*
* This subclass represents simple structure
@@ -72,8 +79,12 @@ public:
};
protected:
- mutable QMutex m_cacheMutex;
- QMultiHash<QString,Data*> m_hCache;
+ mutable QMutex m_cacheMutex;
+ mutable QMutex m_timerMutex;
+
+ QMultiHash<QString,Data*> m_hCache;
+ QMultiMap<long long,KviAnimatedPixmapInterface*> m_timerData;
+ QTimer m_animationTimer;
/*
* This class is a singletone.
@@ -85,12 +96,19 @@ protected:
Data* internalResize(Data* data,QSize size);
void internalFree(Data* data);
+ void internalSceduleFrameChange(uint delay,KviAnimatedPixmapInterface* receiver);
+ void internalNotifyDelete(KviAnimatedPixmapInterface* receiver);
+protected slots:
+ void timerEvent();
public:
virtual ~KviAnimatedPixmapCache();
+ static void sceduleFrameChange(uint delay,KviAnimatedPixmapInterface* receiver);
static Data* load(QString szFileName);
static Data* resize(Data* data,QSize size);
static void free(Data* data);
+ static QPixmap* dummyPixmap();
+ static void notifyDelete(KviAnimatedPixmapInterface* receiver);
};
#endif /* KVI_ANIMATEDPIXMAPCACHE_H_ */
diff --git a/src/kvilib/irc/kvi_avatar.h b/src/kvilib/irc/kvi_avatar.h
index 46c47d237..595859add 100644
--- a/src/kvilib/irc/kvi_avatar.h
+++ b/src/kvilib/irc/kvi_avatar.h
@@ -96,6 +96,15 @@ public:
}
/*
+ * Returns true if pixmap has at least one loaded frame.
+ * Returns false otherways.
+ */
+ inline bool isValid()
+ {
+ return m_pPixmap->isValid();
+ }
+
+ /*
* Returns original animated pixmap.
*/
inline KviAnimatedPixmap * animatedPixmap() {
diff --git a/src/kvilib/system/kvi_time.cpp b/src/kvilib/system/kvi_time.cpp
index 4c6af9f69..d3deb3f77 100644
--- a/src/kvilib/system/kvi_time.cpp
+++ b/src/kvilib/system/kvi_time.cpp
@@ -81,6 +81,14 @@ unsigned long KviMSecTimeInterval::mark()
namespace KviTimeUtils
{
+ long long getCurrentTimeMills()
+ {
+ struct timeval tmv;
+ kvi_gettimeofday(&tmv,0);
+ long long result = tmv.tv_sec * 1000 + tmv.tv_usec / 1000;
+ return result;
+ }
+
void secondsToDaysHoursMinsSecs(unsigned int uSecs,
unsigned int * uD,unsigned int * uH,unsigned int * uM,unsigned int * uS)
{
diff --git a/src/kvilib/system/kvi_time.h b/src/kvilib/system/kvi_time.h
index ff4042ccf..b0dd475dd 100644
--- a/src/kvilib/system/kvi_time.h
+++ b/src/kvilib/system/kvi_time.h
@@ -77,6 +77,7 @@ namespace KviTimeUtils
{
+ long long getCurrentTimeMills();
// splits the time span uSecs in days, hours, minutes and seconds
KVILIB_API void secondsToDaysHoursMinsSecs(unsigned int uSecs,
unsigned int * uD,unsigned int * uH,unsigned int * uM,unsigned int * uS);
diff --git a/src/kvirc/kernel/kvi_iconmanager.cpp b/src/kvirc/kernel/kvi_iconmanager.cpp
index ece07194b..5460ee616 100644
--- a/src/kvirc/kernel/kvi_iconmanager.cpp
+++ b/src/kvirc/kernel/kvi_iconmanager.cpp
@@ -793,24 +793,31 @@ KviAvatar * KviIconManager::getAvatar(const QString &szLocalPath,const QString &
//if(!p)return 0;
+ KviAvatar* result = 0;
if(KviFileUtils::fileExists(szP))
{
if(KVI_OPTION_BOOL(KviOption_boolScaleAvatarsOnLoad))
{
- return new KviAvatar(szP,szN,
+ result = new KviAvatar(szP,szN,
QSize(
KVI_OPTION_UINT(KviOption_uintScaleAvatarsOnLoadWidth),
KVI_OPTION_UINT(KviOption_uintScaleAvatarsOnLoadHeight)
)
);
} else {
- return new KviAvatar(szP,szN);
+ result = new KviAvatar(szP,szN);
}
- } else {
- return 0;
}
+ //Can't load it
+ if(result && !result->isValid())
+ {
+ delete result;
+ result = 0;
+ }
+
+ return result;
}
void KviIconManager::clearCache()
diff --git a/src/kvirc/ui/kvi_console.cpp b/src/kvirc/ui/kvi_console.cpp
index b86253114..a2a2ea597 100644
--- a/src/kvirc/ui/kvi_console.cpp
+++ b/src/kvirc/ui/kvi_console.cpp
@@ -997,7 +997,14 @@ KviAvatar * KviConsole::defaultAvatarFromOptions()
if(!avatar)return 0;
if(avatar->isNull())return 0;
if(KVI_OPTION_STRING(KviOption_stringMyAvatar).isEmpty())return 0;
- return new KviAvatar(KVI_OPTION_PIXMAP(KviOption_pixmapMyAvatar).path(),KVI_OPTION_STRING(KviOption_stringMyAvatar));
+ KviAvatar * loadedAvatar = new KviAvatar(KVI_OPTION_PIXMAP(KviOption_pixmapMyAvatar).path(),KVI_OPTION_STRING(KviOption_stringMyAvatar));
+ if(loadedAvatar->isValid())
+ {
+ return loadedAvatar;
+ } else {
+ delete loadedAvatar;
+ return 0;
+ }
}
KviAvatar * KviConsole::currentAvatar()
diff --git a/src/kvirc/ui/kvi_ircview.cpp b/src/kvirc/ui/kvi_ircview.cpp
index d4c4d450a..cde6897c9 100644
--- a/src/kvirc/ui/kvi_ircview.cpp
+++ b/src/kvirc/ui/kvi_ircview.cpp
@@ -2042,7 +2042,7 @@ const kvi_wchar_t * KviIrcView::getTextLine(int iMsgType,
static void * char_to_check_jump_table[256]=
{
- &&found_end_of_buffer ,0 ,&&found_mirc_escape ,&&found_color_escape ,
+ &(&found_end_of_buffer),0 ,&&found_mirc_escape ,&&found_color_escape ,
0 ,0 ,0 ,0 ,
0 ,0 ,&&found_end_of_line ,0 ,
0 ,&&found_command_escape ,0 ,&&found_mirc_escape ,