summaryrefslogtreecommitdiffstats
path: root/noatun/modules/kjofol-skin/kjtextdisplay.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'noatun/modules/kjofol-skin/kjtextdisplay.cpp')
-rw-r--r--noatun/modules/kjofol-skin/kjtextdisplay.cpp650
1 files changed, 650 insertions, 0 deletions
diff --git a/noatun/modules/kjofol-skin/kjtextdisplay.cpp b/noatun/modules/kjofol-skin/kjtextdisplay.cpp
new file mode 100644
index 00000000..89f92526
--- /dev/null
+++ b/noatun/modules/kjofol-skin/kjtextdisplay.cpp
@@ -0,0 +1,650 @@
+/***************************************************************************
+ kjtexdisplay.cpp
+ ---------------------------------------------
+ Displays for time and other things
+ using fonts provided by KJFont
+ ---------------------------------------------
+ Maintainer: Stefan Gehn <sgehn@gmx.net>
+
+ ***************************************************************************/
+
+// local includes
+#include "kjtextdisplay.h"
+#include "kjfont.h"
+#include "kjprefs.h"
+
+// kde includes
+#include <klocale.h>
+#include <kdebug.h>
+#include <kpixmap.h>
+#include <kurl.h>
+#include <krun.h>
+#include <kmimemagic.h>
+
+// arts-includes, needed for pitch
+#include <artsmodules.h>
+#include <arts/reference.h>
+#include <arts/soundserver.h>
+#include <arts/kmedia2.h>
+
+// noatun includes
+#include <noatun/player.h>
+#include <noatun/engine.h>
+
+/*******************************************
+ * KJFilename
+ *******************************************/
+
+KJFilename::KJFilename(const QStringList &l, KJLoader *p)
+ : QObject(0), KJWidget(p), mBack(0)
+{
+ int x = l[1].toInt();
+ int y = l[2].toInt();
+ int xs = l[3].toInt() - x;
+ int ys = l[4].toInt() - y;
+
+ // fix for all those weird skins where the filenamewindow has more
+ // height than needed for the font
+ // ( ... usually resulting in garbage on-screen )
+ if ( ys > (textFont().fontHeight()) )
+ ys = textFont().fontHeight();
+
+ // background under filename-scroller
+ QPixmap tmp = p->pixmap(p->item("backgroundimage")[1]);
+ mBack = new KPixmap ( QSize(xs,ys) );
+ bitBlt( mBack, 0, 0, &tmp, x, y, xs, ys, Qt::CopyROP );
+
+ setRect(x,y,xs,ys);
+
+ // how far it moves per cycle
+ // TODO: make that configurable for the user
+
+ //mDistance = 1;
+// mDistance = (int)(textFont().fontWidth()/2);
+ readConfig();
+
+ prepareString(i18n("Welcome to Noatun").local8Bit());
+ killTimers();
+}
+
+KJFilename::~KJFilename()
+{
+ delete mBack;
+}
+
+void KJFilename::paint(QPainter *p, const QRect &)
+{
+ QPixmap temp ( rect().width(), rect().height() );
+
+ // draw background into buffer
+ bitBlt ( &temp, 0, 0, mBack, 0, 0, -1, -1, Qt::CopyROP );
+ // draw font into buffer
+ bitBlt( &temp, 0, 0, &mView, 0, 0, rect().width(), rect().height(), Qt::CopyROP);
+ // and draw it on screen
+ bitBlt(p->device(), rect().topLeft(), &temp,
+ QRect(0,0,-1,-1), Qt::CopyROP);
+}
+
+void KJFilename::timerEvent(QTimerEvent *)
+{
+ int height = mView.height();
+ int width = mView.width();
+
+ QBitmap cycleMask ( mDistance, height ); // temporary-space for moving parts of the mask
+ QPixmap cycle ( mDistance, height ); // temporary-space for moving parts of the pixmap
+ QBitmap newMask ( *mView.mask() ); // save old mask
+
+ // copy mask like the same way we're doing it with the pixmap
+ // a mask does not get copied on a bitblt automatically, we have to do
+ // it "by hand"
+ bitBlt(&cycleMask, 0,0, &newMask, 0,0, mDistance, height, Qt::CopyROP);
+ bitBlt(&newMask, 0,0, &newMask, mDistance, 0, width-mDistance, height, Qt::CopyROP);
+ bitBlt(&newMask, width-mDistance, 0, &cycleMask, 0,0, mDistance, height, Qt::CopyROP);
+
+ bitBlt(&cycle, 0,0, &mView, 0,0, mDistance, height, Qt::CopyROP);
+ bitBlt(&mView, 0,0, &mView, mDistance, 0, width-mDistance, height, Qt::CopyROP);
+ bitBlt(&mView, width-mDistance, 0, &cycle, 0,0, mDistance, height, Qt::CopyROP);
+
+ // apply the newly created mask
+ mView.setMask(newMask);
+
+ repaint();
+}
+
+bool KJFilename::mousePress(const QPoint &)
+{
+ return true;
+}
+
+void KJFilename::mouseRelease(const QPoint &, bool in)
+{
+ if (!in) // only do something if users is still inside the button
+ return;
+
+ if ( !napp->player()->current() )
+ return;
+
+ KURL dirURL = napp->player()->current().url().upURL();
+
+ KMimeMagicResult *result = KMimeMagic::self()->findFileType( dirURL.path() );
+
+ // TODO: Maybe test for protocol type?
+// if ( napp->player()->current().url().protocol() == "file" )
+ if ( result->isValid() )
+ KRun::runURL ( dirURL, result->mimeType() );
+}
+
+void KJFilename::readConfig()
+{
+ kdDebug(66666) << "KJFilename::readConfig()" << endl;
+ mDistance = (int)( textFont().fontWidth() * KJLoader::kjofol->prefs()->titleMovingDistance() );
+ if ( mDistance <= 0 )
+ mDistance = 1;
+ mTimerUpdates = KJLoader::kjofol->prefs()->titleMovingUpdates();
+ textFont().recalcSysFont();
+ mLastTitle=""; // invalidate title so it gets repainted on next timeUpdate()
+}
+
+void KJFilename::prepareString(const QCString &str)
+{
+ killTimers(); // i.e. stop timers
+
+ mView = textFont().draw(str, rect().width());
+
+ startTimer(mTimerUpdates);
+}
+
+void KJFilename::timeUpdate(int)
+{
+ if ( !napp->player()->current() ) // just for safety
+ return;
+
+ QCString title = QCString( napp->player()->current().title().local8Bit() );
+
+ if ( title == mLastTitle )
+ return;
+
+ mLastTitle = title;
+
+ QCString timestring = napp->player()->lengthString().local8Bit();
+ timestring = timestring.mid(timestring.find('/')+1);
+ prepareString ( title + " (" + timestring + ") ");
+}
+
+QString KJFilename::tip()
+{
+ if ( !napp->player()->current() ) // just for safety
+ return i18n("Filename");
+ else
+ return napp->player()->current().url().prettyURL();
+}
+
+
+/*******************************************
+ * KJTime
+ *******************************************/
+
+KJTime::KJTime(const QStringList &l, KJLoader *p)
+ : KJWidget(p), mBack(0)
+{
+ int x = l[1].toInt();
+ int y = l[2].toInt();
+ int xs = l[3].toInt() - x;
+ int ys = l[4].toInt() - y;
+
+ // fix for all those weird skins where the timewindow
+ // has more space than needed for the font
+ int maxNeededHeight = timeFont().fontHeight();
+ if ( ys > maxNeededHeight )
+ ys = maxNeededHeight;
+
+ // five digits + spacing between them
+ int maxNeededWidth = ( 5 *timeFont().fontWidth() ) + ( 4 * timeFont().fontSpacing() );
+ if ( xs > maxNeededWidth )
+ xs = maxNeededWidth;
+
+ // background under time-display
+ QPixmap tmp = p->pixmap(p->item("backgroundimage")[1]);
+ mBack = new KPixmap ( QSize(xs,ys) );
+ bitBlt( mBack, 0, 0, &tmp, x, y, xs, ys, Qt::CopyROP );
+
+ setRect(x,y,xs,ys);
+
+ readConfig();
+
+ prepareString("00:00");
+}
+
+KJTime::~KJTime()
+{
+ delete mBack;
+}
+
+void KJTime::paint(QPainter *p, const QRect &)
+{
+// kdDebug(66666) << "KJTime::paint(QPainter *p, const QRect &)" << endl;
+ QPixmap temp ( rect().width(), rect().height() );
+
+ // draw background into buffer
+ bitBlt ( &temp, 0, 0, mBack, 0, 0, -1, -1, Qt::CopyROP );
+ // draw time-display into buffer (that's a pixmap with a mask applied)
+ bitBlt( &temp, 0, 0, &mTime, 0, 0, rect().width(), rect().height(), Qt::CopyROP);
+
+ // and draw it on screen
+ bitBlt(p->device(), rect().topLeft(), &temp,
+ QRect(0,0, rect().width(), rect().height()), Qt::CopyROP);
+}
+
+bool KJTime::mousePress(const QPoint &)
+{
+ return true;
+}
+
+void KJTime::mouseRelease(const QPoint &, bool in)
+{
+ if (!in) // only do something if users is still inside the button
+ return;
+
+ countDown = !countDown;
+ napp->setDisplayRemaining( countDown );
+// KJLoader::kjofol->prefs()->setTimeCountMode( countDown );
+}
+
+void KJTime::readConfig()
+{
+// kdDebug(66666) << "KJTime::readConfig()" << endl;
+ countDown = napp->displayRemaining();
+ timeFont().recalcSysFont();
+ mLastTime=""; // invalidate time so it gets repainted on next timeUpdate()
+}
+
+QString KJTime::lengthString ( void )
+{
+ int pos = 0;
+ QString posString;
+ int secs = 0,
+ seconds = 0,
+ minutes = 0,
+ hours = 0;
+
+ if ( countDown )
+ { // current remaining time
+ pos = napp->player()->getLength() - napp->player()->getTime();
+ }
+ else
+ { // current time
+ pos = napp->player()->getTime();
+ }
+
+ if ( pos < 0 )
+ {
+ posString = "00:00";
+ }
+ else
+ { // get the position
+ secs = pos / 1000; // convert milliseconds -> seconds
+
+ seconds = secs % 60;
+ minutes = (secs - seconds) / 60;
+ hours = minutes / 60;
+ minutes %= 60; // remove the hours from minutes ;)
+
+// cerr << " " << hours << ":" << minutes << ":" << seconds << endl;
+
+// if ( hours > 0 ) // looks ugly :)
+ if ( (napp->player()->getLength()/1000) >= 3600 ) // displays hh:mm if file is long
+ {
+ posString.sprintf("%d:%.2d", hours, minutes);
+ }
+ else // displays mm:ss
+ {
+ posString.sprintf("%.2d:%.2d", minutes, seconds);
+ }
+ }
+
+ return posString;
+}
+
+void KJTime::timeUpdate(int)
+{
+// kdDebug(66666) << "START KJTime::timeUpdate(int)" << endl;
+ if (!napp->player()->current())
+ return;
+
+ prepareString( (lengthString()).latin1() );
+
+// kdDebug(66666) << "END KJTime::timeUpdate(int)" << endl;
+}
+
+void KJTime::prepareString(const QCString &str)
+{
+// kdDebug(66666) << "START KJTime::prepareString(const QCString &str)" << endl;
+ if ( str == mLastTime )
+ return;
+
+ mLastTime = str;
+ mTime = timeFont().draw(str, rect().width());
+
+ repaint();
+// kdDebug(66666) << "END KJTime::prepareString(const QCString &str)" << endl;
+}
+
+QString KJTime::tip()
+{
+ if ( countDown )
+ return i18n("Play time left");
+ else
+ return i18n("Current play time");
+}
+
+
+/*******************************************
+ * KJVolumeText
+ *******************************************/
+
+KJVolumeText::KJVolumeText(const QStringList &l, KJLoader *p)
+ : KJWidget(p), mBack(0)
+{
+ int x=l[1].toInt();
+ int y=l[2].toInt();
+ int xs=l[3].toInt()-x;
+ int ys=l[4].toInt()-y;
+
+ // fix for all those weird skins where the timewindow has more space than needed for the font
+ if ( ys > (volumeFont().fontHeight()) )
+ ys = volumeFont().fontHeight();
+
+ // 3 digits for volume (1-100)
+ // + spaces according to spacing
+ // + percentage letter (seems to be 1px wider than a normal char)
+ int tempWidth = (3*volumeFont().fontWidth()) + (2*volumeFont().fontSpacing()) + ((volumeFont().fontWidth()+1));
+ if ( xs > ( tempWidth ) )
+ xs = tempWidth;
+
+ // background under volumetext-display
+ QPixmap tmp = p->pixmap(p->item("backgroundimage")[1]);
+ mBack = new KPixmap ( QSize(xs,ys) );
+ bitBlt( mBack, 0, 0, &tmp, x, y, xs, ys, Qt::CopyROP );
+
+ setRect(x,y,xs,ys);
+
+ prepareString("100%");
+}
+
+KJVolumeText::~KJVolumeText()
+{
+ delete mBack;
+}
+
+void KJVolumeText::paint(QPainter *p, const QRect &)
+{
+ QPixmap temp ( rect().width(), rect().height() );
+
+ // draw background into buffer
+ bitBlt ( &temp, 0, 0, mBack, 0, 0, -1, -1, Qt::CopyROP );
+ // draw time-display into buffer
+ bitBlt( &temp, 0, 0, &mVolume, 0, 0, rect().width(), rect().height(), Qt::CopyROP);
+
+ // and draw it on screen
+ bitBlt(p->device(), rect().topLeft(), &temp,
+ QRect(0,0,-1,-1), Qt::CopyROP);
+}
+
+bool KJVolumeText::mousePress(const QPoint &)
+{
+ return false;
+}
+
+void KJVolumeText::readConfig()
+{
+ volumeFont().recalcSysFont();
+ mLastVolume=""; // invalidate value so it gets repainted on next timeUpdate()
+}
+
+void KJVolumeText::timeUpdate(int)
+{
+ QCString volume;
+
+ if (!napp->player()->current())
+ return;
+
+ volume.sprintf("%d%%", napp->player()->volume() ); // FIXME: is sprintf safe to use?
+
+ prepareString(volume);
+}
+
+void KJVolumeText::prepareString(const QCString &str)
+{
+ if ( str == mLastVolume )
+ return;
+
+ mLastVolume = str;
+ mVolume = volumeFont().draw(str, rect().width());
+
+ repaint();
+}
+
+QString KJVolumeText::tip()
+{
+ return i18n("Volume");
+}
+
+
+/*******************************************
+ * KJPitchText
+ *******************************************/
+
+KJPitchText::KJPitchText(const QStringList &l, KJLoader *p)
+ : KJWidget(p), mBack(0)
+{
+ int x = l[1].toInt();
+ int y = l[2].toInt();
+ int xs = l[3].toInt() - x;
+ int ys = l[4].toInt() - y;
+
+ // fix for all those weird skins where the timewindow has more space than needed for the font
+ if ( ys > (pitchFont().fontHeight()) )
+ ys = pitchFont().fontHeight();
+
+ // 3 digits for volume (1-100), spaces according to spacing and percentage letter
+ int tempWidth = (3*pitchFont().fontWidth()) + (2*pitchFont().fontSpacing());
+ if ( xs > tempWidth )
+ xs = tempWidth;
+
+ // background under time-display
+ QPixmap tmp = p->pixmap(p->item("backgroundimage")[1]);
+ mBack = new KPixmap ( QSize(xs,ys) );
+ bitBlt( mBack, 0, 0, &tmp, x, y, xs, ys, Qt::CopyROP );
+
+ setRect(x,y,xs,ys);
+
+ prepareString("100");
+}
+
+KJPitchText::~KJPitchText()
+{
+ delete mBack;
+}
+
+
+void KJPitchText::paint(QPainter *p, const QRect &)
+{
+ QPixmap temp ( rect().width(), rect().height() );
+
+ // draw background into buffer
+ bitBlt ( &temp, 0, 0, mBack, 0, 0, -1, -1, Qt::CopyROP );
+ // draw time-display into buffer
+ bitBlt( &temp, 0, 0, &mSpeed, 0, 0, rect().width(), rect().height(), Qt::CopyROP);
+ // and draw it on screen
+ bitBlt(p->device(), rect().topLeft(), &temp, QRect(0,0,-1,-1), Qt::CopyROP);
+}
+
+bool KJPitchText::mousePress(const QPoint &)
+{
+ return true;
+}
+
+void KJPitchText::mouseRelease(const QPoint &, bool in)
+{
+ if (!in)
+ return;
+
+ Arts::PlayObject playobject = napp->player()->engine()->playObject();
+ Arts::PitchablePlayObject pitchable = Arts::DynamicCast(playobject);
+
+ if (pitchable.isNull())
+ return;
+
+ pitchable.speed( 1.00f ); // reset pitch
+}
+
+void KJPitchText::readConfig()
+{
+ pitchFont().recalcSysFont();
+ mLastPitch=""; // invalidate value so it gets repainted on next timeUpdate()
+}
+
+void KJPitchText::timeUpdate(int)
+{
+ QCString speed;
+
+ if (!napp->player()->current())
+ return;
+
+ Arts::PlayObject playobject = napp->player()->engine()->playObject();
+ Arts::PitchablePlayObject pitchable = Arts::DynamicCast(playobject);
+
+ if (pitchable.isNull())
+ return;
+
+ speed.setNum ( (int) ((float)pitchable.speed()*(float)100) );
+ prepareString ( speed );
+}
+
+void KJPitchText::prepareString(const QCString &str)
+{
+ if ( str == mLastPitch )
+ return;
+
+ mLastPitch = str;
+ mSpeed = pitchFont().draw(str, rect().width());
+
+ repaint();
+}
+
+QString KJPitchText::tip()
+{
+ return i18n("Pitch");
+}
+
+
+/*******************************************
+ * KJFileInfo
+ *******************************************/
+
+KJFileInfo::KJFileInfo(const QStringList &l, KJLoader *p)
+ : KJWidget(p), mBack(0)
+{
+ mInfoType = l[0]; // type of info-display
+
+ int x = l[1].toInt();
+ int y = l[2].toInt();
+ int xs = l[3].toInt() - x;
+ int ys = l[4].toInt() - y;
+
+ // fix for all those weird skins where the timewindow
+ // has more space than needed for the font
+ int maxNeededHeight = timeFont().fontHeight();
+ if ( ys > maxNeededHeight )
+ ys = maxNeededHeight;
+
+ // five digits + spacing between them
+ int maxNeededWidth = ( 3 *timeFont().fontWidth() ) + ( 2 * timeFont().fontSpacing() );
+ if ( xs > maxNeededWidth )
+ xs = maxNeededWidth;
+
+ // background under info-display
+ QPixmap tmp = p->pixmap(p->item("backgroundimage")[1]);
+ mBack = new KPixmap ( QSize(xs,ys) );
+ bitBlt( mBack, 0, 0, &tmp, x, y, xs, ys, Qt::CopyROP );
+
+ setRect(x,y,xs,ys);
+
+ prepareString("");
+}
+
+KJFileInfo::~KJFileInfo()
+{
+ delete mBack;
+}
+
+void KJFileInfo::paint(QPainter *p, const QRect &)
+{
+ QPixmap temp ( rect().width(), rect().height() );
+
+ // draw background into buffer
+ bitBlt ( &temp, 0, 0, mBack, 0, 0, -1, -1, Qt::CopyROP );
+ // draw time-display into buffer (that's a pixmap with a mask applied)
+ bitBlt( &temp, 0, 0, &mTime, 0, 0, rect().width(), rect().height(), Qt::CopyROP);
+
+ // and draw it on screen
+ bitBlt(p->device(), rect().topLeft(), &temp,
+ QRect(0,0, rect().width(), rect().height()), Qt::CopyROP);
+}
+
+bool KJFileInfo::mousePress(const QPoint &)
+{
+ return false;
+}
+
+void KJFileInfo::readConfig()
+{
+ textFont().recalcSysFont();
+ mLastTime=""; // invalidate value so it gets repainted on next timeUpdate()
+}
+
+void KJFileInfo::timeUpdate(int)
+{
+ if (!napp->player()->current())
+ return;
+
+ const PlaylistItem &item = napp->player()->current();
+ QString prop;
+
+ if ( mInfoType == "mp3khzwindow" )
+ {
+ prop = item.property("samplerate");
+ prop.truncate(2); // we just want 44 instead of 44100
+ }
+ else if ( mInfoType == "mp3kbpswindow" )
+ {
+ prop = item.property("bitrate");
+ }
+ else // for safety: no infoType we know of
+ return;
+
+ if (prop.isNull())
+ prop="";
+ prepareString( prop.latin1() );
+}
+
+void KJFileInfo::prepareString(const QCString &str)
+{
+ if ( str == mLastTime )
+ return;
+ mLastTime = str;
+ mTime = textFont().draw(str, rect().width());
+ repaint();
+}
+
+QString KJFileInfo::tip()
+{
+ if ( mInfoType == "mp3khzwindow" )
+ return i18n("Sample rate in kHz");
+ else if ( mInfoType == "mp3kbpswindow" )
+ return i18n("Bitrate in kbps");
+
+ return QString();
+}
+
+#include "kjtextdisplay.moc"