diff options
Diffstat (limited to 'kicker-applets/mediacontrol')
53 files changed, 4787 insertions, 0 deletions
diff --git a/kicker-applets/mediacontrol/AUTHORS b/kicker-applets/mediacontrol/AUTHORS new file mode 100644 index 0000000..b7d6d85 --- /dev/null +++ b/kicker-applets/mediacontrol/AUTHORS @@ -0,0 +1,5 @@ +Michael Startek <micha.startek@op.pl> +Stefan Gehn <metz {AT} gehn {DOT} net> +Teemu Rytilahti <teemu.rytilahti@kde-fi.org> +Thomas Capricelli <orzel@freehackers.org> +William Robinson <airbaggins@yahoo.co.uk> diff --git a/kicker-applets/mediacontrol/Makefile.am b/kicker-applets/mediacontrol/Makefile.am new file mode 100644 index 0000000..0afe266 --- /dev/null +++ b/kicker-applets/mediacontrol/Makefile.am @@ -0,0 +1,28 @@ +SUBDIRS = . pics +INCLUDES = $(XMMS_INCLUDES) $(all_includes) +METASOURCES = AUTO + +kde_module_LTLIBRARIES = mediacontrol_panelapplet.la + +mediacontrol_panelapplet_la_COMPILE_FIRST = mediacontrolconfigwidget.h +mediacontrol_panelapplet_la_SOURCES = mcslider.cpp \ + mediacontrol.cpp playerInterface.cpp \ + configfrontend.cpp mediacontrolconfigwidget.ui \ + mediacontrolconfig.cpp mediacontroliface.skel \ + noatunInterface.cpp \ + xmmsInterface.cpp \ + mpdInterface.cpp \ + jukInterface.cpp \ + amarokInterface.cpp \ + kscdInterface.cpp \ + simplebutton.cpp + +mediacontrol_panelapplet_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) $(XMMS_LIBS) +mediacontrol_panelapplet_la_LIBADD = $(LIB_KDEUI) + +lnkdir = $(kde_datadir)/kicker/applets +lnk_DATA = mediacontrol.desktop +EXTRA_DIST = $(lnk_DATA) + +messages: rc.cpp + $(XGETTEXT) *.cpp *.h -o $(podir)/mediacontrol.pot diff --git a/kicker-applets/mediacontrol/README b/kicker-applets/mediacontrol/README new file mode 100644 index 0000000..0c3acc7 --- /dev/null +++ b/kicker-applets/mediacontrol/README @@ -0,0 +1,28 @@ +MediaControl v0.4 +Stefan Gehn <metz AT gehn.net> +---------------------------------------------------------------------- + +This is a small applet for the kde-panel (kicker) to control various +mediaplayers with. + +Supported players at the moment are: +- Noatun +- XMMS +- JuK +- Amarok +- KsCD +- more to come :) + +If you ask "Why another applet for xmms?" then there are a few answers for you: + +1. most of those applets are for XMMS _only_ and I wanted to support various + mediaplayers +2. there was no applet for noatun (... and I was never able to find that noatun + -window on my huge desktop) +3. many xmms-applets use skins to look like xmms itself, I really dislike that + on a panel + +The applet is still very small and can't make coffee yet but this will surely +come one day ;) + +Have fun with this small and (hopefully) handy tool. diff --git a/kicker-applets/mediacontrol/TODO b/kicker-applets/mediacontrol/TODO new file mode 100644 index 0000000..0066900 --- /dev/null +++ b/kicker-applets/mediacontrol/TODO @@ -0,0 +1,7 @@ +Tooltip -> DONE (want to make it configurable) +Themes -> DONE (need some more contributions) +i18n -> need to find out where to put it in kde-cvs +Drag n Drop -> DONE +Playlist-Popup -> maybe never, what about 9000 files playlists in a popup, eh? :) +Squelch-Support -> when squelch got its dcopiface +more players -> hey gimme a nice interface for it and I'll add support ;) diff --git a/kicker-applets/mediacontrol/amarokInterface.cpp b/kicker-applets/mediacontrol/amarokInterface.cpp new file mode 100644 index 0000000..2045c12 --- /dev/null +++ b/kicker-applets/mediacontrol/amarokInterface.cpp @@ -0,0 +1,310 @@ +/*************************************************************************** + Interface to access Amarok + ------------------- + begin : Tue Dec 2 23:54:53 CET 2003 + copyright : (c) 2003 by Thomas Capricelli + adapted from juk* (C) 2001-2002 by Stefan Gehn (metz {AT} gehn {DOT} net) + email : orzel@freehackers.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. * + * * + ***************************************************************************/ + +#include "amarokInterface.h" +#include "amarokInterface.moc" + +#include <kdebug.h> +#include <qstringlist.h> +#include <qstrlist.h> +#include <kurldrag.h> + +#define TIMER_FAST 250 + +AmarokInterface::AmarokInterface() : PlayerInterface() +{ + mTimerValue = TIMER_FAST; + mAmarokTimer = new QTimer ( this, "mAmaroKTimer" ); + + connect(mAmarokTimer, SIGNAL(timeout()), SLOT(updateSlider()) ); + kapp->dcopClient()->setNotifications ( true ); + + connect(kapp->dcopClient(), SIGNAL(applicationRegistered(const QCString&)), + SLOT(appRegistered(const QCString&)) ); + + connect(kapp->dcopClient(), SIGNAL(applicationRemoved(const QCString&)), + SLOT(appRemoved(const QCString&))); + + QTimer::singleShot(0, this, SLOT(myInit())); +} + +AmarokInterface::~AmarokInterface() +{ + kapp->dcopClient()->setNotifications(false); + delete mAmarokTimer; +} + +void AmarokInterface::myInit() +{ + // Start the timer if amarok is already running + // Needed if user adds applet while running amarok + if ( findRunningAmarok() ) + { + emit playerStarted(); + mAmarokTimer->start(mTimerValue); + } + else + { + emit playerStopped(); + emit newSliderPosition(0,0); + } +} + +void AmarokInterface::appRegistered ( const QCString &appId ) +{ + if(appId.contains("amarok",false) ) + { + mAppId = appId; + emit playerStarted(); + mAmarokTimer->start(mTimerValue); + } +} + +void AmarokInterface::appRemoved ( const QCString &appId ) +{ + if ( appId.contains("amarok",false) ) + { + // is there still another amarok alive? + if ( findRunningAmarok() ) + return; + mAmarokTimer->stop(); + emit playerStopped(); + emit newSliderPosition(0,0); + } +} + +void AmarokInterface::updateSlider ( ) +{ + // length/time in msecs, -1 means "no playobject in amarok" + int len, time; + QByteArray data, replyData; + QCString replyType; + + if (!kapp->dcopClient()->call(mAppId, "player", "trackTotalTime()",data, replyType, replyData)) + { + //kdDebug(90200) << "mediacontrol: DCOP communication Error" << endl; + // -2 is an internal errornumber, might be used later + len = -2; + } + else + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "int") + { + reply >> len; + } + else + { + //kdDebug(90200) << "mediacontrol: unexpected type of DCOP-reply" << endl; + // -3 is an internal errornumber, might be used later + len = -3; + } + } + + data = 0; + replyData = 0; + replyType = 0; + + if (!kapp->dcopClient()->call(mAppId, "player", "trackCurrentTime()",data, replyType, replyData)) + { + //kdDebug(90200) << "mediacontrol: DCOP communication error" << endl; + time = -2; + } + else + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "int") + { + reply >> time; + } + else + { + //kdDebug(90200) << "mediacontrol: unexpected type of DCOP-reply" << endl; + time = -3; + } + } + + if ( (time < 0) || (len < 0)) // Amarok isn't playing and thus returns -1 + { + len = 0; + time = 0; + } + emit newSliderPosition(len,time); + emit playingStatusChanged(playingStatus()); +} + +// Drag-n-Drop stuff ================================================================= + +void AmarokInterface::dragEnterEvent(QDragEnterEvent* event) +{ +// kdDebug(90200) << "AmarokInterface::dragEnterEvent()" << endl; + event->accept( KURLDrag::canDecode(event) ); +} + +void AmarokInterface::dropEvent(QDropEvent* event) +{ + kdDebug(90200) << "AmarokInterface::dropEvent()" << endl; + KURL::List list; + if (KURLDrag::decode(event, list)) + { + QByteArray data; + QDataStream arg(data, IO_WriteOnly); + arg << list; + if (!kapp->dcopClient()->send(mAppId, "player", "addMediaList(KURL::List)",data)) + kdDebug(90200) << "Couldn't send drop to amarok" << endl; + } +} + +// ==================================================================================== + +void AmarokInterface::sliderStartDrag() +{ + mAmarokTimer->stop(); +} + +void AmarokInterface::sliderStopDrag() +{ + mAmarokTimer->start(mTimerValue); +} + +void AmarokInterface::jumpToTime( int sec ) +{ + QByteArray data; + QDataStream arg(data, IO_WriteOnly); + arg << sec; + kapp->dcopClient()->send(mAppId, "player", "seek(int)", data); +} + +void AmarokInterface::playpause() +{ + if (!findRunningAmarok()) + startPlayer("amarok"); + QByteArray data; + kapp->dcopClient()->send(mAppId, "player", "playPause()", data); +} + +void AmarokInterface::stop() +{ + QByteArray data; + kapp->dcopClient()->send(mAppId, "player", "stop()", data); +} + +void AmarokInterface::next() +{ + QByteArray data; + kapp->dcopClient()->send(mAppId, "player", "next()", data); +} + +void AmarokInterface::prev() +{ + QByteArray data; + kapp->dcopClient()->send(mAppId, "player", "prev()", data); +} + +void AmarokInterface::volumeUp() +{ + QByteArray data; + kapp->dcopClient()->send(mAppId, "player", "volumeUp()", data); +} + +void AmarokInterface::volumeDown() +{ + QByteArray data; + kapp->dcopClient()->send(mAppId, "player", "volumeDown()", data); +} + +const QString AmarokInterface::getTrackTitle() const +{ + QString title; + QByteArray data, replyData; + QCString replyType; + if (!kapp->dcopClient()->call(mAppId, "player", "nowPlaying()",data, replyType, replyData)) + { + //kdDebug(90200) << "mediacontrol: DCOP communication Error" << endl; + return QString(""); + } + else + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "QString") + { + reply >> title; + return title; + } + else + { + //kdDebug(90200) << "mediacontrol: unexpected type of DCOP-reply" << endl; + return QString(""); + } + } +} + +bool AmarokInterface::findRunningAmarok() +{ + QCStringList allApps = kapp->dcopClient()->registeredApplications(); + QValueList<QCString>::const_iterator iterator; + QByteArray data, replyData; + QCString replyType; + + for (iterator = allApps.constBegin(); iterator != allApps.constEnd(); ++iterator) + { + if ((*iterator).contains("amarok",false)) + { + if (kapp->dcopClient()->call((*iterator), "player", "interfaces()", data, replyType, replyData) ) + { + if ( replyType == "QCStringList" ) + { + QDataStream reply(replyData, IO_ReadOnly); + QCStringList list; + reply >> list; + + if ( list.contains("AmarokPlayerInterface") ) + { + kdDebug(90200) << "mediacontrol: amarok found" << endl; + mAppId = *iterator; + return true; + } + } + } + } + } + kdDebug(90200) << "mediacontrol: amarok not found" << endl; + return false; +} + + +int AmarokInterface::playingStatus() +{ + QByteArray data, replyData; + QCString replyType; + + if (kapp->dcopClient()->call(mAppId, "player", "status()", data, replyType, + replyData)) + { + int status = 0; + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "int") + reply >> status; + if (status == 2) + return Playing; + else if (status == 1) + return Paused; + } + return Stopped; +} diff --git a/kicker-applets/mediacontrol/amarokInterface.h b/kicker-applets/mediacontrol/amarokInterface.h new file mode 100644 index 0000000..3a71031 --- /dev/null +++ b/kicker-applets/mediacontrol/amarokInterface.h @@ -0,0 +1,69 @@ +/*************************************************************************** + Interface to access Amarok + ------------------- + begin : Tue Dec 2 23:54:53 CET 2003 + copyright : (c) 2003 by Thomas Capricelli + adapted from juk* (C) 2001-2002 by Stefan Gehn (metz {AT} gehn {DOT} net) + email : orzel@freehackers.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. * + * * + ***************************************************************************/ + +#ifndef AMAROKINTERFACE_H +#define AMAROKINTERFACE_H + +#include "playerInterface.h" + +#include <kapplication.h> +#include <dcopclient.h> + +#include <qtimer.h> + +class AmarokInterface : public PlayerInterface +{ + Q_OBJECT + public: + AmarokInterface(); + ~AmarokInterface(); + + public slots: + virtual void updateSlider(); // gets called on timer-timeout + virtual void sliderStartDrag(); + virtual void sliderStopDrag(); + virtual void jumpToTime( int msec ); + virtual void playpause(); + virtual void stop(); + virtual void next(); + virtual void prev(); + virtual void volumeUp(); + virtual void volumeDown(); + virtual void dragEnterEvent(QDragEnterEvent* event); + virtual void dropEvent(QDropEvent* event); + virtual const QString getTrackTitle() const; + virtual int playingStatus(); + + private slots: + void myInit(); + void appRegistered ( const QCString &appId ); + void appRemoved ( const QCString &appId ); + + private: + QTimer *mAmarokTimer; + int mTimerValue; + QCString mAppId; + + /** + * Tries to find a DCOP registered instance of AmaroK + * Stores the name of the first found instance in appId + * @returns true is instance is found, false otherwise + */ + bool findRunningAmarok(); +}; +#endif diff --git a/kicker-applets/mediacontrol/configfrontend.cpp b/kicker-applets/mediacontrol/configfrontend.cpp new file mode 100644 index 0000000..ba206c8 --- /dev/null +++ b/kicker-applets/mediacontrol/configfrontend.cpp @@ -0,0 +1,99 @@ +/*************************************************************************** + provides access to mediacontrol configuration file + ------------------- + begin : forgot :/ + copyright : (C) 2000-2002 by Stefan Gehn + email : metz {AT} gehn {DOT} net + + code-skeleton taken from knewsticker which is + Copyright (c) Frerich Raabe <raabe@kde.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. * + * * + ***************************************************************************/ + +#include "configfrontend.h" +// #include <kdebug.h> + +ConfigFrontend::ConfigFrontend() : QObject(0, 0) +{ + _config = new KConfig(QString::null, true, false); + _ownConfig = true; +} + +ConfigFrontend::~ConfigFrontend() +{ + if (_ownConfig) + { + delete _config; + } +} + +ConfigFrontend::ConfigFrontend(KConfig *config) : QObject(0, 0) +{ + _config = config; + _config->setGroup("MediaControl"); + _ownConfig = false; +} + +// ==================================================================================== + +uint ConfigFrontend::mouseWheelSpeed() const +{ + return _config->readNumEntry("Mouse wheel speed", 5); +} + +void ConfigFrontend::setMouseWheelSpeed(const uint mouseWheelSpeed) +{ + _config->writeEntry("Mouse wheel speed", mouseWheelSpeed); + _config->sync(); +} + +// ==================================================================================== + +QString ConfigFrontend::player() const +{ + return _config->readPathEntry("Player", "Noatun"); +} + +void ConfigFrontend::setPlayer(const QString &player) +{ + _config->writePathEntry("Player", player); + _config->sync(); +} + +// ==================================================================================== + +QString ConfigFrontend::theme() const +{ + return _config->readEntry("Theme", "default"); +} + +void ConfigFrontend::setTheme(const QString &theme) +{ + _config->writeEntry("Theme", theme); + _config->sync(); +} + +// ==================================================================================== + +bool ConfigFrontend::useCustomTheme() const +{ + return _config->readBoolEntry("UseCustomTheme", false); +} + +void ConfigFrontend::setUseCustomTheme(const bool use) +{ + _config->writeEntry("UseCustomTheme", use); + _config->sync(); +} + +// ==================================================================================== + +#include "configfrontend.moc" diff --git a/kicker-applets/mediacontrol/configfrontend.h b/kicker-applets/mediacontrol/configfrontend.h new file mode 100644 index 0000000..87a0bf4 --- /dev/null +++ b/kicker-applets/mediacontrol/configfrontend.h @@ -0,0 +1,52 @@ +/*************************************************************************** + provides access to mediacontrol configuration file + ------------------- + begin : forgot :/ + copyright : (C) 2000-2002 by Stefan Gehn + email : metz {AT} gehn {DOT} net + + code-skeleton taken from knewsticker which is + Copyright (c) Frerich Raabe <raabe@kde.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. * + * * + ***************************************************************************/ + +#ifndef CONFIGFRONTEND_H +#define CONFIGFRONTEND_H + +#include <kconfig.h> +#include <klocale.h> + +class ConfigFrontend : public QObject +{ + Q_OBJECT + public: + ConfigFrontend(); + ConfigFrontend(KConfig *); + virtual ~ConfigFrontend(); + + uint mouseWheelSpeed() const; + QString player() const; + QString theme() const; + bool useCustomTheme() const; + + public slots: + void setMouseWheelSpeed(const uint); + void setPlayer(const QString &player); + void setTheme(const QString &theme); + void setUseCustomTheme(const bool use); + void reparseConfiguration() { _config->reparseConfiguration(); } + + private: + KConfig *_config; + bool _ownConfig:1; +}; + +#endif // CONFIGFRONTEND_H diff --git a/kicker-applets/mediacontrol/configure.in.in b/kicker-applets/mediacontrol/configure.in.in new file mode 100644 index 0000000..8a48beb --- /dev/null +++ b/kicker-applets/mediacontrol/configure.in.in @@ -0,0 +1,48 @@ +dnl AM_PATH_XMMS([1.0.0]) +dnl AM_INIT_AUTOMAKE(mediacontrol, 0.1) +dnl AC_PATH_PROG(XMMS_CONFIG, xmms-config, no) +dnl AM_PATH_XMMS(1.0.0,,AC_MSG_ERROR([*** XMMS >= 1.0.0 not installed - please install first ***])) + +AC_DEFUN([AC_CHECK_XMMS], +[ + AC_MSG_CHECKING([for libxmms]) + AC_CACHE_VAL(ac_cv_have_xmms, + [ + ac_save_libs="$LIBS" + LIBS="`xmms-config --libs`" + ac_CPPFLAGS_save="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $all_includes `xmms-config --cflags 2> /dev/null`" + ac_LDFLAGS_save="$LDFLAGS" + LDFLAGS="$LDFLAGS $all_libraries" + AC_TRY_LINK( + [#include <xmms/xmmsctrl.h>], + [xmms_remote_play_pause(0);], + [ac_cv_have_xmms="yes"], + [ac_cv_have_xmms="no"] + ) + LIBS="$ac_save_libs" + LDFLAGS="$ac_LDFLAGS_save" + CPPFLAGS="$ac_CPPFLAGS_save" + ]) + AC_MSG_RESULT($ac_cv_have_xmms) + if test "$ac_cv_have_xmms" = "yes"; then + XMMS_LIBS="`xmms-config --libs`" + XMMS_INCLUDES="`xmms-config --cflags`" + AC_DEFINE(HAVE_XMMS, 1, [Define if you have xmms libraries and header files.]) + fi +]) + +AC_ARG_WITH(xmms, + [AC_HELP_STRING([--with-xmms],[enable XMMS control applet @<:@default=check@:>@])], + [], with_xmms=check) + +if test "x$with_xmms" != xno; then + AC_CHECK_XMMS + + if test "x$with_xmms" != xcheck && test "x$ac_cv_have_xmms" != xyes; then + AC_MSG_ERROR([--with-xmms was given, but test for XMMS failed]) + fi +fi + +AC_SUBST(XMMS_LIBS) +AC_SUBST(XMMS_INCLUDES) diff --git a/kicker-applets/mediacontrol/jukInterface.cpp b/kicker-applets/mediacontrol/jukInterface.cpp new file mode 100644 index 0000000..302e7f2 --- /dev/null +++ b/kicker-applets/mediacontrol/jukInterface.cpp @@ -0,0 +1,314 @@ +/*************************************************************************** + Interface to access JuK + ------------------- + begin : Mon Jan 15 21:09:00 CEST 2001 + copyright : (C) 2001-2002 by Stefan Gehn + email : metz {AT} gehn {DOT} net + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include "jukInterface.h" +#include "jukInterface.moc" + +#include <kapplication.h> +#include <kdebug.h> +#include <qstringlist.h> +#include <qstrlist.h> +#include <qprocess.h> +#include <kurldrag.h> + +#define TIMER_FAST 250 + +JuKInterface::JuKInterface() : PlayerInterface(), mProc(0) +{ + mTimerValue = TIMER_FAST; + mJuKTimer = new QTimer ( this, "mJukTimer" ); + + connect(mJuKTimer, SIGNAL(timeout()), SLOT(updateSlider()) ); + kapp->dcopClient()->setNotifications ( true ); + + connect(kapp->dcopClient(), SIGNAL(applicationRegistered(const QCString&)), + SLOT(appRegistered(const QCString&)) ); + + connect(kapp->dcopClient(), SIGNAL(applicationRemoved(const QCString&)), + SLOT(appRemoved(const QCString&))); + + QTimer::singleShot(0, this, SLOT(myInit())); +} + +JuKInterface::~JuKInterface() +{ + kapp->dcopClient()->setNotifications(false); + delete mJuKTimer; +} + +void JuKInterface::myInit() +{ + // Start the timer if juk is already running + // Needed if user adds applet while running juk + if ( findRunningJuK() ) + { + emit playerStarted(); + mJuKTimer->start(mTimerValue); + } + else + { + emit playerStopped(); + emit newSliderPosition(0,0); + } +} + +void JuKInterface::appRegistered ( const QCString &appId ) +{ + if(appId.contains("juk",false) ) + { + mAppId = appId; + + // BWAHAHAHA EVIL HACK + // JuK blocks DCOP signals on its startup, so if we try to + // ping it now, it'll simply cause us to block, which will + // cause kicker to block, which is bad, m'kay? + // + // So what we do is launch the dcop command instead, and let + // *it* block for us. As soon as the command exits, we know + // that JuK is ready to go (and so are we). + mProc = new QProcess(this, "jukdcopCheckProc"); + mProc->addArgument("dcop"); + mProc->addArgument("juk"); + mProc->addArgument("Player"); + mProc->addArgument("status()"); + + connect(mProc, SIGNAL(processExited()), SLOT(jukIsReady())); + mProc->start(); + } +} + +void JuKInterface::appRemoved ( const QCString &appId ) +{ + if ( appId.contains("juk",false) ) + { + // is there still another juk alive? + if ( findRunningJuK() ) + return; + mJuKTimer->stop(); + emit playerStopped(); + emit newSliderPosition(0,0); + } +} + +/* Called when the dcop process we launch terminates */ +void JuKInterface::jukIsReady() +{ + emit playerStarted(); + mJuKTimer->start(mTimerValue); + + mProc->deleteLater(); + mProc = 0; +} + +void JuKInterface::updateSlider () +{ + // length/time in msecs, -1 means "no playobject in juk" + int len = -1; + int time = -1; + QByteArray data, replyData; + QCString replyType; + + if (kapp->dcopClient()->call(mAppId, "Player", "totalTime()", data, + replyType, replyData)) + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "int") + reply >> len; + } + + data = 0; + replyData = 0; + replyType = 0; + + if (kapp->dcopClient()->call(mAppId, "Player", "currentTime()", data, + replyType, replyData)) + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "int") + reply >> time; + } + + if ( (time < 0) || (len < 0)) // JuK isn't playing and thus returns -1 + { + len = 0; + time = 0; + } + emit ( newSliderPosition(len,time) ); + emit playingStatusChanged(playingStatus()); +} + +// Drag-n-Drop stuff ================================================================= + +void JuKInterface::dragEnterEvent(QDragEnterEvent* event) +{ +// kdDebug(90200) << "JuKInterface::dragEnterEvent()" << endl; + event->accept( KURLDrag::canDecode(event) ); +} + +void JuKInterface::dropEvent(QDropEvent* event) +{ +// kdDebug(90200) << "JuKInterface::dropEvent()" << endl; + KURL::List list; + if (KURLDrag::decode(event, list)) + { + QByteArray data, replyData; + QStringList fileList; + QCString replyType; + QDataStream arg(data, IO_WriteOnly); + + // Juk doesn't handle KURL's yet, so we need to form a list + // that contains the local paths. + for (KURL::List::ConstIterator it = list.begin(); it != list.end(); ++it) + fileList += (*it).path(); + + arg << fileList << false; + + // Use call instead of send to make sure the files are added + // before we try to play. + if (!kapp->dcopClient()->call(mAppId, "Collection", "openFile(QStringList)", data, + replyType, replyData, true)) + { + kdDebug(90200) << "Couldn't send drop to juk" << endl; + } + + // Apparently we should auto-play? + QByteArray strData; + QDataStream strArg(strData, IO_WriteOnly); + strArg << *fileList.begin(); + + if (!kapp->dcopClient()->send(mAppId, "Player", "play(QString)", strData)) + kdDebug(90200) << "Couldn't send play command to juk" << endl; + } +} + +// ==================================================================================== + +void JuKInterface::sliderStartDrag() +{ + mJuKTimer->stop(); +} + +void JuKInterface::sliderStopDrag() +{ + mJuKTimer->start(mTimerValue); +} + +void JuKInterface::jumpToTime( int sec ) +{ + QByteArray data; + QDataStream arg(data, IO_WriteOnly); + arg << sec; + // Used in JuK shipping with KDE < 3.3 + //kapp->dcopClient()->send(mAppId, "Player", "setTime(int)", data); + kapp->dcopClient()->send(mAppId, "Player", "seek(int)", data); +} + +void JuKInterface::playpause() +{ + if (!findRunningJuK()) + startPlayer("juk"); + QByteArray data; + kapp->dcopClient()->send(mAppId, "Player", "playPause()", data); +} + +void JuKInterface::stop() +{ + QByteArray data; + kapp->dcopClient()->send(mAppId, "Player", "stop()", data); +} + +void JuKInterface::next() +{ + QByteArray data; + kapp->dcopClient()->send(mAppId, "Player", "forward()", data); +} + +void JuKInterface::prev() +{ + QByteArray data; + kapp->dcopClient()->send(mAppId, "Player", "back()", data); +} + +void JuKInterface::volumeUp() +{ + QByteArray data; + kapp->dcopClient()->send(mAppId, "Player", "volumeUp()", data); +} + +void JuKInterface::volumeDown() +{ + QByteArray data; + kapp->dcopClient()->send(mAppId, "Player", "volumeDown()", data); +} + +const QString JuKInterface::getTrackTitle() const +{ + QString title; + QByteArray data, replyData; + QCString replyType; + + if (kapp->dcopClient()->call(mAppId, "Player", "playingString()",data, + replyType, replyData)) + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "QString") + { + reply >> title; + return title; + } + } + return QString(""); +} + +// FIXME: what if we have a dcop app named, let's say, 'jukfrontend'? +bool JuKInterface::findRunningJuK() +{ + QCStringList allApps = kapp->dcopClient()->registeredApplications(); + QValueList<QCString>::const_iterator iterator; + + for (iterator = allApps.constBegin(); iterator != allApps.constEnd(); ++iterator) + { + if ((*iterator).contains("juk",false)) + { + mAppId = *iterator; + return true; + } + } + return false; +} + +int JuKInterface::playingStatus() +{ + QByteArray data, replyData; + QCString replyType; + + if (kapp->dcopClient()->call(mAppId, "Player", "status()", data, replyType, + replyData)) + { + int status = 0; + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "int") + reply >> status; + + if (status == 2) + return Playing; + else if (status == 1) + return Paused; + } + + return Stopped; +} diff --git a/kicker-applets/mediacontrol/jukInterface.h b/kicker-applets/mediacontrol/jukInterface.h new file mode 100644 index 0000000..fb7f9bb --- /dev/null +++ b/kicker-applets/mediacontrol/jukInterface.h @@ -0,0 +1,72 @@ +/*************************************************************************** + Interface to access JuK + ------------------- + begin : Mon Jan 15 21:09:00 CEST 2001 + copyright : (C) 2001-2002 by Stefan Gehn + email : metz {AT} gehn {DOT} net + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef JUKINTERFACE_H +#define JUKINTERFACE_H + +#include "playerInterface.h" + +#include <kapplication.h> +#include <dcopclient.h> + +#include <qtimer.h> + +class QProcess; + +class JuKInterface : public PlayerInterface +{ + Q_OBJECT + public: + JuKInterface(); + ~JuKInterface(); + + public slots: + void updateSlider(); + void sliderStartDrag(); + void sliderStopDrag(); + void jumpToTime( int sec ); + void playpause(); + void stop(); + void next(); + void prev(); + void volumeUp(); + void volumeDown(); + void dragEnterEvent(QDragEnterEvent* event); + void dropEvent(QDropEvent* event); + const QString getTrackTitle() const; + int playingStatus(); + + private slots: + void myInit(); + void appRegistered ( const QCString &appId ); + void appRemoved ( const QCString &appId ); + void jukIsReady(); + + private: + QTimer *mJuKTimer; + QProcess *mProc; + int mTimerValue; + QCString mAppId; + + /** + * Tries to find a DCOP registered instance of juk + * Stores the name of the first found instance in appId + * @returns true is instance is found, false otherwise + */ + bool findRunningJuK(); +}; +#endif diff --git a/kicker-applets/mediacontrol/kscdInterface.cpp b/kicker-applets/mediacontrol/kscdInterface.cpp new file mode 100644 index 0000000..f7f7e90 --- /dev/null +++ b/kicker-applets/mediacontrol/kscdInterface.cpp @@ -0,0 +1,332 @@ +/*************************************************************************** + Interface to access KsCD + ------------------- + begin : Sat Dec 04 13:36:00 CET 2004 + copyright : (C) 2004 by Michal Startek + adapted from JuK interface which is (C) 2001-2002 by Stefan Gehn + email : michal.startek@op.pl + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include "kscdInterface.h" +#include "kscdInterface.moc" + +#include <kapplication.h> +#include <kdebug.h> +#include <qstringlist.h> +#include <qstrlist.h> +#include <kurldrag.h> +#include <klocale.h> + +#define TIMER_FAST 250 + +KsCDInterface::KsCDInterface() : PlayerInterface() +{ + mKsCDTimer = new QTimer(this, "mKsCDTimer"); + + connect(mKsCDTimer, SIGNAL(timeout()), SLOT(updateSlider()) ); + kapp->dcopClient()->setNotifications ( true ); + + connect(kapp->dcopClient(), SIGNAL(applicationRegistered(const QCString&)), + SLOT(appRegistered(const QCString&)) ); + + connect(kapp->dcopClient(), SIGNAL(applicationRemoved(const QCString&)), + SLOT(appRemoved(const QCString&))); + + QTimer::singleShot(0, this, SLOT(myInit())); +} + +KsCDInterface::~KsCDInterface() +{ + kapp->dcopClient()->setNotifications(false); + delete mKsCDTimer; +} + +void KsCDInterface::myInit() +{ + // Start the timer if KsCD is already running + // Needed if user adds applet while running KsCD + if (findRunningKsCD()) + { + emit playerStarted(); + mKsCDTimer->start(TIMER_FAST); + } + else + { + emit playerStopped(); + emit newSliderPosition(0,0); + } +} + +void KsCDInterface::appRegistered(const QCString &appId) +{ + if((appId) == "kscd") + { + mAppId = appId; + emit playerStarted(); + mKsCDTimer->start(TIMER_FAST); + } +} + +void KsCDInterface::appRemoved(const QCString &appId) +{ + if ((appId) == "kscd") + { + // is there still another KsCD alive? + // Okay, KsCD does not allow multiple instances + // of it to run at the same time, but + // this can change. + if (findRunningKsCD()) + return; + mKsCDTimer->stop(); + emit playerStopped(); + emit newSliderPosition(0,0); + } +} + +void KsCDInterface::updateSlider() +{ + // length/time in secs, -1 means "no playobject in kscd" + int len = -1; + int time = -1; + QByteArray data, replyData; + QCString replyType; + + if (kapp->dcopClient()->call(mAppId, "CDPlayer", "currentTrackLength()", data, + replyType, replyData)) + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "int") + reply >> len; + } + + data = 0; + replyData = 0; + replyType = 0; + + if (kapp->dcopClient()->call(mAppId, "CDPlayer", "currentPosition()", data, + replyType, replyData)) + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "int") + reply >> time; + } + + if ( (time < 0) || (len < 0)) // KsCD isn't playing and thus returns -1 + { + len = 0; + time = 0; + } + emit newSliderPosition(len,time); + emit playingStatusChanged(playingStatus()); +} + +// Drag-n-Drop stuff ================================================================= +// As far as I know there is currently no way to drag an AudioCD track to KsCD, +// or even no application to drag AudioCD track from (not the KIO-wrapped track +// path (audiocd:/...) like from Konqueror) + +void KsCDInterface::dragEnterEvent(QDragEnterEvent* event) +{ + event->ignore(); +} + +void KsCDInterface::dropEvent(QDropEvent* event) +{ + event->ignore(); +} + +// ==================================================================================== + +void KsCDInterface::sliderStartDrag() +{ + mKsCDTimer->stop(); +} + +void KsCDInterface::sliderStopDrag() +{ + mKsCDTimer->start(TIMER_FAST); +} + +void KsCDInterface::jumpToTime(int sec) +{ + QByteArray data; + QDataStream arg(data, IO_WriteOnly); + arg << sec; + kapp->dcopClient()->send(mAppId, "CDPlayer", "jumpTo(int)", data); +} + +void KsCDInterface::playpause() +{ + if (!findRunningKsCD()) + startPlayer("kscd"); + QByteArray data; + kapp->dcopClient()->send(mAppId, "CDPlayer", "play()", data); +} + +void KsCDInterface::stop() +{ + QByteArray data; + kapp->dcopClient()->send(mAppId, "CDPlayer", "stop()", data); +} + +void KsCDInterface::next() +{ + QByteArray data; + kapp->dcopClient()->send(mAppId, "CDPlayer", "next()", data); +} + +void KsCDInterface::prev() +{ + QByteArray data; + kapp->dcopClient()->send(mAppId, "CDPlayer", "previous()", data); +} + +void KsCDInterface::volumeUp() +{ + QByteArray data; + kapp->dcopClient()->send(mAppId, "CDPlayer", "volumeUp()", data); +} + +void KsCDInterface::volumeDown() +{ + QByteArray data; + kapp->dcopClient()->send(mAppId, "CDPlayer", "volumeDown()", data); +} + +const QString KsCDInterface::getTrackTitle() const +{ + QString title, artist, album, result; + QByteArray data, replyData; + QCString replyType; + + // Get track title from KsCD... + if (kapp->dcopClient()->call(mAppId, "CDPlayer", "currentTrackTitle()", data, + replyType, replyData)) + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "QString") + { + reply >> title; + } + } + + // Album... + if (kapp->dcopClient()->call(mAppId, "CDPlayer", "currentAlbum()", data, + replyType, replyData)) + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "QString") + { + reply >> album; + } + } + + // Artist... + if (kapp->dcopClient()->call(mAppId, "CDPlayer", "currentArtist()", data, + replyType, replyData)) + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "QString") + { + reply >> artist; + } + } + + // And compose them into one string that will be displayed... + if(album.isEmpty()) + { + if(artist.isEmpty()) + { + result = title; + } + else // artist is non-empty + { + if(title.isEmpty()) + { + result = artist; + } + else + { + result = i18n("artist - trackname", "%1 - %2").arg(artist, title); + } + } + } + else // album is non-empty + { + if(artist.isEmpty()) + { + if(title.isEmpty()) + { + result = album; + } + else + { + result = i18n("(album) - trackname", "(%1) - %2").arg(artist, title); + } + } + else // artist is non-empty + { + if(title.isEmpty()) + { + result = i18n("artistname (albumname)", "%1 (%2)").arg(artist, album); + } + else + { + result = i18n("artistname (albumname) - trackname", "%1 (%2) - %3").arg(artist, album, title); + } + } + } + + return result; +} + +bool KsCDInterface::findRunningKsCD() +{ + QCStringList allApps = kapp->dcopClient()->registeredApplications(); + QValueList<QCString>::const_iterator iterator; + + for (iterator = allApps.constBegin(); iterator != allApps.constEnd(); ++iterator) + { + if ((*iterator) == "kscd") + { + mAppId = *iterator; + return true; + } + } + return false; +} + +int KsCDInterface::playingStatus() +{ + QByteArray data, replyData; + QCString replyType; + + if (kapp->dcopClient()->call(mAppId, "CDPlayer", "getStatus()", data, replyType, + replyData)) + { + int status = 0; + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "int") + reply >> status; + + switch (status) + { + case 2: + return Playing; + case 4: + return Paused; + default: + return Stopped; + } + } + return Stopped; +} diff --git a/kicker-applets/mediacontrol/kscdInterface.h b/kicker-applets/mediacontrol/kscdInterface.h new file mode 100644 index 0000000..0817b1e --- /dev/null +++ b/kicker-applets/mediacontrol/kscdInterface.h @@ -0,0 +1,68 @@ +/*************************************************************************** + Interface to access KsCD + ------------------- + begin : Sat Dec 04 12:48:00 CET 2004 + copyright : (C) 2004 by Michal Startek + adapted from JuK interface which is (C) 2001-2002 by Stefan Gehn + email : michal.startek@op.pl + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef KSCDINTERFACE_H +#define KSCDINTERFACE_H + +#include "playerInterface.h" + +#include <kapplication.h> +#include <dcopclient.h> + +#include <qtimer.h> + +class KsCDInterface : public PlayerInterface +{ + Q_OBJECT + public: + KsCDInterface(); + ~KsCDInterface(); + + public slots: + void updateSlider(); + void sliderStartDrag(); + void sliderStopDrag(); + void jumpToTime( int sec ); + void playpause(); + void stop(); + void next(); + void prev(); + void volumeUp(); + void volumeDown(); + void dragEnterEvent(QDragEnterEvent* event); + void dropEvent(QDropEvent* event); + const QString getTrackTitle() const; + int playingStatus(); + + private slots: + void myInit(); + void appRegistered ( const QCString &appId ); + void appRemoved ( const QCString &appId ); + + private: + QTimer *mKsCDTimer; + QCString mAppId; + + /** + * Tries to find a DCOP registered instance of KsCD + * Stores the name of the first found instance in appId + * @returns true is instance is found, false otherwise + */ + bool findRunningKsCD(); +}; +#endif diff --git a/kicker-applets/mediacontrol/mcslider.cpp b/kicker-applets/mediacontrol/mcslider.cpp new file mode 100644 index 0000000..642d2e2 --- /dev/null +++ b/kicker-applets/mediacontrol/mcslider.cpp @@ -0,0 +1,66 @@ +/*************************************************************************** + mcslider.cpp - description + ------------------- + begin : 20040410 + copyright : (C) 2004 by Teemu Rytilahti + email : teemu.rytilahti@kde-fi.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. * + * * + ***************************************************************************/ + +#include <qpixmap.h> + +#include "mcslider.h" + +MCSlider::MCSlider( Orientation orientation, QWidget *parent, const char *name ) + : QSlider( orientation, parent, name ) +{ + setBackgroundOrigin(WidgetOrigin); + setBackground(); +} + +MCSlider::~MCSlider() +{ +} + +// This is needed because KStyle draws slider background incorrectly. + +void MCSlider::setBackground() +{ + unsetPalette(); + + if (parentWidget()->paletteBackgroundPixmap()) + { + QPixmap pm(width(), height()); + pm.fill(parentWidget(), pos()); + setPaletteBackgroundPixmap(pm); + } +} + +void MCSlider::wheelEvent(QWheelEvent *e) +{ + if (e->orientation() == Horizontal) + return; + + if (e->state() == ShiftButton) + { + if (e->delta() > 0) + emit volumeUp(); + else + emit volumeDown(); + e->accept(); + } + else + { + QSlider::wheelEvent(e); + } +} + +#include "mcslider.moc" diff --git a/kicker-applets/mediacontrol/mcslider.h b/kicker-applets/mediacontrol/mcslider.h new file mode 100644 index 0000000..9b11893 --- /dev/null +++ b/kicker-applets/mediacontrol/mcslider.h @@ -0,0 +1,37 @@ +/*************************************************************************** + mcslider.h - description + ------------------- + begin : 20040410 + copyright : (C) 2004 by Teemu Rytilahti + email : teemu.rytilahti@kde-fi.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. * + * * + ***************************************************************************/ + +#ifndef MCSLIDER_H +#define MCSLIDER_H + +#include <qslider.h> + +class MCSlider : public QSlider +{ + Q_OBJECT + + public: + MCSlider( Orientation orientation, QWidget *parent, const char *name = 0 ); + ~MCSlider(); + void setBackground(); + private: + virtual void wheelEvent(QWheelEvent *e); + signals: + void volumeUp(); + void volumeDown(); +}; +#endif diff --git a/kicker-applets/mediacontrol/mediacontrol.cpp b/kicker-applets/mediacontrol/mediacontrol.cpp new file mode 100644 index 0000000..e69e0e0 --- /dev/null +++ b/kicker-applets/mediacontrol/mediacontrol.cpp @@ -0,0 +1,614 @@ +/*************************************************************************** + main file of mediacontrol applet + ------------------- + begin : Tue Apr 25 11:53:11 CEST 2000 + copyright : (C) 2000-2005 by Stefan Gehn + email : metz {AT} gehn {DOT} net + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "mediacontrol.h" +#include "mediacontrol.moc" + +#include "mediacontrolconfig.h" +#include "configfrontend.h" + + +#include "noatunInterface.h" +#include "xmmsInterface.h" +#include "jukInterface.h" +#include "amarokInterface.h" +#include "mpdInterface.h" +#include "kscdInterface.h" + +#include "mcslider.h" + +#include <qfile.h> +#include <qdragobject.h> +#include <qtooltip.h> +#include <qstyle.h> +#include <qslider.h> +#include <qpainter.h> +#include <qiconset.h> +#include <kpopupmenu.h> + +#include <kapplication.h> +#include <kipc.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <knotifyclient.h> +#include <kbugreport.h> +#include <dcopclient.h> + +const int MC_BUTTONSIZE = 20; // TODO: Might become dynamical for bigger panels +const int NO_BUTTONS = 4; + +extern "C" +{ + KDE_EXPORT KPanelApplet *init( QWidget *parent, const QString &configFile) + { + KGlobal::locale()->insertCatalogue("mediacontrol"); + return new MediaControl(configFile, KPanelApplet::Normal, + KPanelApplet::About | KPanelApplet::Preferences | + KPanelApplet::ReportBug, parent, "mediacontrol"); + } +} + +// ============================================================================= + +class MediaControlToolTip : public QToolTip +{ + public: + MediaControlToolTip(QWidget *widget, PlayerInterface *pl_obj) : + QToolTip(widget), mWidget(widget), mPlayer(pl_obj) {} + + protected: + virtual void maybeTip(const QPoint &pt) + { + QRect rc( mWidget->rect()); + if (rc.contains(pt)) + { + tip ( rc, mPlayer->getTrackTitle() ); + } + } + private: + QWidget *mWidget; + PlayerInterface *mPlayer; +}; + +// ============================================================================= + +MediaControl::MediaControl(const QString &configFile, Type t, int actions, + QWidget *parent, const char *name) + : DCOPObject("MediaControl"), + KPanelApplet(configFile, t, actions, parent, name), + mInstance(new KInstance("mediacontrol")), + mAboutData(new KAboutData("mediacontrol", + I18N_NOOP("MediaControl"), + MEDIACONTROL_VERSION, + I18N_NOOP("A small control-applet for various media players"), + KAboutData::License_GPL_V2, + "(c) 2001-2004 Stefan Gehn", + 0, + "http://metz.gehn.net")) +{ + setBackgroundOrigin(AncestorOrigin); + _player = 0L; + _prefsDialog = 0L; + + _configFrontend = new ConfigFrontend(config()); + // My own dcopclient + _dcopClient = new DCOPClient(); + _dcopClient->registerAs("mediacontrol", false); + + mAboutData->addAuthor("Stefan Gehn", I18N_NOOP("Main Developer"), + "metz@gehn.net", "http://metz.gehn.net"); + mAboutData->addAuthor("Robbie Ward", I18N_NOOP("Initial About-Dialog"), + "wardy@robbieward.co.uk", "http://www.robbieward.co.uk"); + + mAboutData->addCredit("Sascha Hoffman", I18N_NOOP("Button-Pixmaps"), + "tisch.sush@gmx.de", 0); + mAboutData->addCredit("Christian Hoffman", I18N_NOOP("Button-Pixmaps"), + "tisch.crix@gmx.de", "http://www.crixensgfxcorner.de.vu/"); + mAboutData->addCredit("Ulrik Mikaelsson", I18N_NOOP("Fix for Noatun-Support"), + "rawler@rsn.bth.se", 0); + mAboutData->addCredit("Anthony J Moulen", I18N_NOOP("Fix for Vertical Slider"), + "ajmoulen@moulen.org", 0); + mAboutData->addCredit("Teemu Rytilahti", I18N_NOOP("Volume Control Implementation"), + "teemu.rytilahti@kde-fi.org", 0); + mAboutData->addCredit("Jan Spitalnik", I18N_NOOP("Fix for JuK-Support"), + "honza@spitalnik.net", 0); + mAboutData->addCredit("William Robinson", I18N_NOOP("mpd-Support"), + "airbaggins@yahoo.co.uk", 0); + + setAcceptDrops(true); + + prev_button = new TrayButton (this, "PREVIOUS"); + playpause_button = new TrayButton (this, "PLAYPAUSE"); + stop_button = new TrayButton (this, "STOP"); + next_button = new TrayButton (this, "NEXT"); + time_slider = new MCSlider (QSlider::Horizontal, this, "time_slider" ); + time_slider->setRange(0,0); + time_slider->setValue(0); + time_slider->setTracking( false ); + time_slider->installEventFilter(this); + + // request notification of changes in icon style + kapp->addKipcEventMask(KIPC::IconChanged); + connect(kapp, SIGNAL(iconChanged(int)), this, SLOT(slotIconChanged())); + + reparseConfig(); + + rmbMenu = new KPopupMenu(this, "RMBMenu"); + rmbMenu->insertTitle(i18n("MediaControl"), 0, 0); + rmbMenu->insertItem(SmallIcon("configure"), i18n("Configure MediaControl..."), + this, SLOT(preferences())); + rmbMenu->insertItem(i18n("About MediaControl"), this, SLOT(about())); +} + +MediaControl::~MediaControl() +{ + delete _player; + delete _configFrontend; + delete _dcopClient; + KGlobal::locale()->removeCatalogue("mediacontrol"); +} + +// Drag-n-Drop stuff =========================================================== + +void MediaControl::dragEnterEvent(QDragEnterEvent* event) +{ + _player->dragEnterEvent(event); // Just pass dnd to the playerInterface +} + +void MediaControl::dropEvent(QDropEvent* event) +{ + _player->dropEvent(event); // Just pass dnd to the playerInterface +} + +// ============================================================================= + + +void MediaControl::setSliderPosition(int len ,int time) +{ + time_slider->blockSignals(true); + if(orientation() == Vertical) + time = len - time; + + if (mLastLen != len) + time_slider->setRange(0,len); + mLastLen = len; + + if (mLastTime != time) + time_slider->setValue(time); + mLastTime = time; + + time_slider->blockSignals(false); +} + +void MediaControl::enableAll() +{ + prev_button->setDisabled(false); + playpause_button->setDisabled(false); + QToolTip::remove(playpause_button); + stop_button->setDisabled(false); + next_button->setDisabled(false); + time_slider->setDisabled(false); +} + +void MediaControl::disableAll() +{ + prev_button->setDisabled(true); + playpause_button->setDisabled(false); + QToolTip::add(playpause_button, i18n("Start the player")); + stop_button->setDisabled(true); + next_button->setDisabled(true); + time_slider->setDisabled(true); + if(_configFrontend->useCustomTheme()) { + QString skindir = locate("data", "mediacontrol/"+_configFrontend->theme()+"/"); + playpause_button->setIconSet(SmallIconSet(locate("data",skindir+"play.png"))); + } + else + playpause_button->setIconSet(SmallIconSet("player_play")); +} + +void MediaControl::slotPlayingStatusChanged(int status) +{ + if (mLastStatus == status) + return; + + mLastStatus = status; + QString skindir = locate("data", "mediacontrol/"+_configFrontend->theme()+"/"); + + switch (status) + { + case (PlayerInterface::Stopped): + case (PlayerInterface::Paused): + if(_configFrontend->useCustomTheme()) + playpause_button->setIconSet(SmallIconSet(locate("data",skindir+"play.png"))); + else + playpause_button->setIconSet(SmallIconSet("player_play")); + break; + case (PlayerInterface::Playing): + if(_configFrontend->useCustomTheme()) + playpause_button->setIconSet(SmallIconSet(locate("data",skindir+"pause.png"))); + else + playpause_button->setIconSet(SmallIconSet("player_pause")); + break; + } +} + +void MediaControl::slotIconChanged() +{ + if(!_configFrontend->useCustomTheme()) + { + prev_button->setIconSet(SmallIconSet("player_start")); + if (_player->playingStatus() == PlayerInterface::Playing) + playpause_button->setIconSet(SmallIconSet("player_pause")); + else + playpause_button->setIconSet(SmallIconSet("player_play")); + stop_button->setIconSet(SmallIconSet("player_stop")); + next_button->setIconSet(SmallIconSet("player_end")); + } +} + +// Dialogs ===================================================================== + +void MediaControl::preferences() +{ + if ( _prefsDialog ) + { + _prefsDialog->raise(); + } + else + { + _prefsDialog = new MediaControlConfig ( _configFrontend ); + connect ( _prefsDialog, SIGNAL(closing()), + this, SLOT(slotClosePrefsDialog()) ); + connect ( _prefsDialog, SIGNAL(destroyed()), + this, SLOT(slotPrefsDialogClosing()) ); + connect ( _prefsDialog, SIGNAL(configChanged()), + this, SLOT(slotConfigChanged()) ); + } +} + +void MediaControl::slotConfigChanged() +{ + reparseConfig(); +} + +void MediaControl::slotClosePrefsDialog() +{ + delete _prefsDialog; +} + +void MediaControl::slotPrefsDialogClosing() +{ + if ( _prefsDialog ) + _prefsDialog = 0L; +} + + +void MediaControl::about() +{ + KAboutApplication aboutDlg(mAboutData); + aboutDlg.exec(); +} + + +void MediaControl::reportBug() +{ + KBugReport bugReport(this, true, mAboutData); + bugReport.exec(); +} + + +// Fixing the orientation problem in qslider. +void MediaControl::adjustTime(int time) +{ + if(orientation() == Vertical) + emit(newJumpToTime(mLastLen - time)); + else + emit(newJumpToTime(time)); +} + +// Config Stuff ================================================================ + +void MediaControl::reparseConfig() +{ +// kdDebug(90200) << "reparseConfig();" << endl; + _configFrontend->reparseConfiguration(); + + if (_player != 0L) // make sure there is no player-object + { + _player->disconnect(); // disconnect from all things + + time_slider->disconnect(); + prev_button->disconnect(); + playpause_button->disconnect(); + stop_button->disconnect(); + next_button->disconnect(); + + delete slider_tooltip; // tooltip depends on _player : delete it before _player gets deleted + slider_tooltip = 0L; + + delete _player; + _player = 0L; + } + + mLastLen = -1; + mLastTime = -1; + mLastStatus = -1; + + QString playerString = _configFrontend->player(); + + +#ifdef HAVE_XMMS + if (playerString == "XMMS") + { + _player = new XmmsInterface (); + time_slider->setSteps((_configFrontend->mouseWheelSpeed()*1000), + (_configFrontend->mouseWheelSpeed()*1000)); + } + else +#endif + if (playerString == "JuK") + { + _player = new JuKInterface(); + time_slider->setSteps((_configFrontend->mouseWheelSpeed()), + (_configFrontend->mouseWheelSpeed())); + } + else if (playerString == "Amarok") + { + _player = new AmarokInterface(); + time_slider->setSteps((_configFrontend->mouseWheelSpeed()), + (_configFrontend->mouseWheelSpeed())); + } + else if (playerString == "KsCD") + { + _player = new KsCDInterface(); + time_slider->setSteps((_configFrontend->mouseWheelSpeed()), + (_configFrontend->mouseWheelSpeed())); + } + else if (playerString == "mpd") + { + _player = new MpdInterface(); + time_slider->setSteps((_configFrontend->mouseWheelSpeed()), + (_configFrontend->mouseWheelSpeed())); + } + else // Fallback is Noatun + { + _player = new NoatunInterface(); + time_slider->setSteps((_configFrontend->mouseWheelSpeed()), + (_configFrontend->mouseWheelSpeed())); + } + + // this signal gets emitted by a playerInterface when the player's playtime changed + connect(_player, SIGNAL(newSliderPosition(int,int)), + this, SLOT(setSliderPosition(int,int))); + + connect(_player, SIGNAL(playerStarted()), SLOT(enableAll())); + connect(_player, SIGNAL(playerStopped()), SLOT(disableAll())); + connect(_player, SIGNAL(playingStatusChanged(int)), SLOT(slotPlayingStatusChanged(int))); + + // do we use our icons or the default ones from KDE? + if(_configFrontend->useCustomTheme()) + { + // load theme + QString skindir = locate("data", "mediacontrol/"+_configFrontend->theme()+"/"); + + // the user has to take care if all pixmaps are there, we only check for one of them + if (QFile(skindir+"play.png").exists()) + { + prev_button->setIconSet(SmallIconSet(locate("data",skindir+"prev.png"))); + if (_player->playingStatus() == PlayerInterface::Playing) + playpause_button->setIconSet(SmallIconSet(locate("data",skindir+"play.png"))); + else + playpause_button->setIconSet(SmallIconSet(locate("data",skindir+"pause.png"))); + stop_button->setIconSet(SmallIconSet(locate("data",skindir+"stop.png"))); + next_button->setIconSet(SmallIconSet(locate("data",skindir+"next.png"))); + } + else // icon-theme is invalid or not there + { + KNotifyClient::event(winId(), KNotifyClient::warning, + i18n("There was trouble loading theme %1. Please choose" \ + " a different theme.").arg(skindir)); + + // default to kde-icons, they have to be installed :) + slotIconChanged(); + + // and open prefs-dialog + preferences(); + } + } + else // KDE default-icons, assuming that these icons exist! + { + // sets icons from kde + slotIconChanged(); + } + + slider_tooltip = new MediaControlToolTip(time_slider, _player); + + connect(prev_button, SIGNAL(clicked()), _player, SLOT(prev())); + connect(playpause_button, SIGNAL(clicked()), _player, SLOT(playpause())); + connect(stop_button, SIGNAL(clicked()), _player, SLOT(stop())); + connect(next_button, SIGNAL(clicked()), _player, SLOT(next())); + + connect(time_slider, SIGNAL(sliderPressed()), _player, SLOT(sliderStartDrag())); + connect(time_slider, SIGNAL(sliderReleased()), _player, SLOT(sliderStopDrag())); + connect(time_slider, SIGNAL(valueChanged(int)), this, SLOT(adjustTime(int))); + connect(time_slider, SIGNAL(volumeUp()), _player, SLOT(volumeUp())); + connect(time_slider, SIGNAL(volumeDown()), _player, SLOT(volumeDown())); + connect(this, SIGNAL(newJumpToTime(int)), _player, SLOT(jumpToTime(int))); +} + +// Widget Placement =================================================================== + +// kicker wants to know what width we need for a given height +// (this is called when being a HORIZONTAL panel) +int MediaControl::widthForHeight(int height) const +{ +// kdDebug(90200) << "kicker height: " << height << endl; +// kdDebug(90200) << "slider needs: " << time_slider->minimumSizeHint().height() << endl; + + // slider height + button height + if ( height >= (time_slider->minimumSizeHint().height()+MC_BUTTONSIZE) ) + { // slider UNDER buttons + // (5 * button width + spaces between them); + return (4*MC_BUTTONSIZE+10); + } + else + { // slider ASIDE buttons + // (5 * button width + spaces between them) * 2 [size of slider = size of all buttons] + return ((4*MC_BUTTONSIZE+10)*2); + } +} + +// kicker wants to know what height we need for a given width +// (this is called when being a VERTICAL panel) +int MediaControl::heightForWidth(int width) const +{ +// kdDebug(90200) << "kicker width: " << width << endl; + + // slider height + button height + if ( width >= (time_slider->minimumSizeHint().width()+MC_BUTTONSIZE) ) + { // slider ASIDE icons + // (5 * button width + spaces between them); + return (4*MC_BUTTONSIZE+10); + } + else + { // slider UNDER buttons + // (5 * button width + spaces between them) * 2 + // because the size of the slider = the size of all buttons + return ((4*MC_BUTTONSIZE+10)*2); + } +} + +void MediaControl::mousePressEvent(QMouseEvent* e) +{ + if (e->button() == QMouseEvent::RightButton) + rmbMenu->popup(e->globalPos()); +} + +bool MediaControl::eventFilter(QObject *, QEvent *e) +{ + if (e->type() == QEvent::MouseButtonPress) + { + QMouseEvent *me = static_cast<QMouseEvent *>(e); + if (me->button() == QMouseEvent::RightButton) + { + rmbMenu->popup(me->globalPos()); + return true; + } + } + return false; +} + +void MediaControl::paletteChange( const QPalette& ) +{ + time_slider->setBackground(); +} + +void MediaControl::moveEvent( QMoveEvent* ) +{ + time_slider->setBackground(); +} + +// Danger: Weird Code ahead! ;)) +void MediaControl::resizeEvent( QResizeEvent* ) +{ +// kdDebug(90200) << "resizeEvent()" << endl; + int w = width(); + int h = height(); + if ( orientation() == Vertical ) + { // ====== VERTICAL ================================================= + time_slider->setOrientation(QSlider::Vertical); + int slider_width = time_slider->minimumSizeHint().width(); + // some styles need more space for sliders than avilable in very small panels :( + if ( slider_width > w ) slider_width = w; + + // that width would be needed to put the slider aside the buttons + if ( w >= (slider_width+MC_BUTTONSIZE) ) + { // Slider ASIDE icons + int applet_space = (w - (slider_width+MC_BUTTONSIZE) ) / 2; + if ( applet_space < 0 ) + applet_space = 0; + + prev_button->setGeometry ( applet_space, 1, MC_BUTTONSIZE, MC_BUTTONSIZE ); + playpause_button->setGeometry ( applet_space, 3+1*MC_BUTTONSIZE, MC_BUTTONSIZE, MC_BUTTONSIZE ); + stop_button->setGeometry ( applet_space, 5+2*MC_BUTTONSIZE, MC_BUTTONSIZE, MC_BUTTONSIZE ); + next_button->setGeometry ( applet_space, 7+3*MC_BUTTONSIZE, MC_BUTTONSIZE, MC_BUTTONSIZE ); + time_slider->setGeometry ( applet_space+MC_BUTTONSIZE, 1, slider_width, NO_BUTTONS*MC_BUTTONSIZE+8 ); + } + else + { // Slider UNDER Icons + int slider_space = (w - slider_width)/2; + int button_space = (w - MC_BUTTONSIZE)/2; + + prev_button->setGeometry ( button_space, 1 , MC_BUTTONSIZE, MC_BUTTONSIZE ); + playpause_button->setGeometry ( button_space, 3+1*MC_BUTTONSIZE, MC_BUTTONSIZE, MC_BUTTONSIZE ); + stop_button->setGeometry ( button_space, 5+2*MC_BUTTONSIZE, MC_BUTTONSIZE, MC_BUTTONSIZE ); + next_button->setGeometry ( button_space, 7+3*MC_BUTTONSIZE, MC_BUTTONSIZE, MC_BUTTONSIZE ); + time_slider->setGeometry ( slider_space, 9+4*MC_BUTTONSIZE, slider_width, NO_BUTTONS*MC_BUTTONSIZE+8 ); + } + } + else // ====== HORIZONTAL =============================================== + { + time_slider->setOrientation(QSlider::Horizontal); + int slider_height = time_slider->minimumSizeHint().height(); + // some styles need more space for sliders than avilable in very small panels :( + if ( slider_height > h ) slider_height = h; + + // that h would be needed to put the slider under the buttons + if ( h >= (slider_height+MC_BUTTONSIZE) ) + { // Slider UNDER icons + int applet_space = (h-(slider_height+MC_BUTTONSIZE))/2; + if ( applet_space < 0 ) + applet_space = 0; + + prev_button->setGeometry ( 1 , applet_space, MC_BUTTONSIZE, MC_BUTTONSIZE ); + playpause_button->setGeometry ( 3+MC_BUTTONSIZE, applet_space, MC_BUTTONSIZE, MC_BUTTONSIZE ); + stop_button->setGeometry ( 5+2*MC_BUTTONSIZE, applet_space, MC_BUTTONSIZE, MC_BUTTONSIZE ); + next_button->setGeometry ( 7+3*MC_BUTTONSIZE, applet_space, MC_BUTTONSIZE, MC_BUTTONSIZE ); + time_slider->setGeometry ( 1, applet_space + MC_BUTTONSIZE, NO_BUTTONS*MC_BUTTONSIZE+8, slider_height ); + } + else + { // Slider ASIDE Icons + int slider_space = (h - slider_height)/2; + int button_space = (h - MC_BUTTONSIZE)/2; + + prev_button->setGeometry ( 1 , button_space, MC_BUTTONSIZE, MC_BUTTONSIZE ); + playpause_button->setGeometry ( 3+1*MC_BUTTONSIZE, button_space, MC_BUTTONSIZE, MC_BUTTONSIZE ); + stop_button->setGeometry ( 5+2*MC_BUTTONSIZE, button_space, MC_BUTTONSIZE, MC_BUTTONSIZE ); + next_button->setGeometry ( 7+3*MC_BUTTONSIZE, button_space, MC_BUTTONSIZE, MC_BUTTONSIZE ); + time_slider->setGeometry ( 9+4*MC_BUTTONSIZE, slider_space, NO_BUTTONS*MC_BUTTONSIZE+8, slider_height ); + } + } +} + +// Our Button ======================================================================== + +TrayButton::TrayButton(QWidget* parent, const char* name) + : SimpleButton (parent, name) +{ + setBackgroundMode(PaletteBackground); + setBackgroundOrigin(AncestorOrigin); +} + +void TrayButton::setIconSet(const QIconSet &iconSet) +{ + setPixmap(iconSet.pixmap(QIconSet::Automatic, QIconSet::Normal, QIconSet::On)); +} + diff --git a/kicker-applets/mediacontrol/mediacontrol.desktop b/kicker-applets/mediacontrol/mediacontrol.desktop new file mode 100644 index 0000000..b7ed81d --- /dev/null +++ b/kicker-applets/mediacontrol/mediacontrol.desktop @@ -0,0 +1,121 @@ +[Desktop Entry] +Type=Plugin +Name=Media Control +Name[ar]=التحكم بلوسائط +Name[bg]=Медия контрол +Name[ca]=Control multimèdia +Name[cs]=Ovládání médií +Name[da]=Mediekontrol +Name[de]=Medienkontrolle +Name[el]=Έλεγχος μέσων +Name[eo]=Mediostirilo +Name[es]=Control de medios +Name[et]=Meediakontroll +Name[eu]=Multimedia kontrola +Name[fa]=کنترل رسانه +Name[fi]=Medianhallinta +Name[fr]=Télécommande multimédia +Name[gl]=Controlo Multimédia +Name[he]=בקרת מדיה +Name[hr]=Upravljanje medijima +Name[hu]=Médiavezérlő +Name[is]=Margmiðlunarstjórn +Name[it]=Controllo multimediale +Name[ja]=メディアコントロール +Name[ka]=მედიის მმართველი +Name[kk]=Ойнатқышты басқару +Name[km]=វត្ថុបញ្ជាមេឌៀ +Name[lt]=Media valdymas +Name[mk]=Контрола на мултимедија +Name[nb]=Mediastyring +Name[nds]=Medienkuntrull +Name[ne]=मिडिया नियन्त्रण +Name[nn]=Mediekontroll +Name[pa]=ਮੀਡਿਆ ਕੰਟਰੋਲ +Name[pl]=Zarządzanie mediami +Name[pt]=Controlo Multimédia +Name[pt_BR]=Controle de Mídia +Name[ru]=Управление мультимедиа +Name[sk]=Ovládanie médií +Name[sl]=Nadzor predvajalnikov +Name[sr]=Контрола медија +Name[sr@Latn]=Kontrola medija +Name[sv]=Mediakontroll +Name[tr]=Medya Kontrolü +Name[uk]=Керування медіа +Name[uz]=Media-pleyer boshqaruvi +Name[uz@cyrillic]=Медиа-плейер бошқаруви +Name[vi]=Điều khiển nhạc/ảnh +Name[zh_CN]=媒体控制 +Name[zh_TW]=媒體控制 +Comment=Applet to control mediaplayers +Comment[af]=Miniprogram na kontrole media spelers +Comment[ar]=بريمج للتحكم بمشغلات الوسائط +Comment[az]=Konsol medya çalğıcıları appleti +Comment[bg]=Лесно и универсално управление на плеъри за мултимедийни файлове +Comment[bs]=Applet za kontrolu mediaplayera +Comment[ca]=Applet controlador dels reproductors multimèdia +Comment[cs]=Applet pro ovládání přehrávačů médií +Comment[cy]=Rhaglennig i reoli chwaraewyr cyfryngau +Comment[da]=Program til at kontrollere medieafspillere +Comment[de]=Programm zur Steuerung von Medienabspielern +Comment[el]=Μικροεφαρμογή για τον έλεγχο αναπαραγωγέων μέσων +Comment[eo]=Aplikaĵo por stiri medioludilojn +Comment[es]=Aplicación integrada para controlar el reproductor de medios +Comment[et]=Meediafailide mängijate juhtimise aplett +Comment[eu]=Multimedia erreproduzigailuak kontrolatzeko appleta +Comment[fa]=برنامکی برای کنترل پخشکنندههای رسانه +Comment[fi]=Mediasoittimien hallintasovelma +Comment[fo]=Smáforrit at stýra mediuspælarum við +Comment[fr]=Applet pour commander les lecteurs multimédia +Comment[fy]=Applet om mediaspilers te bestjoeren +Comment[ga]=Feidhmchláirín chun seinnteoirí meán a rialú +Comment[gl]=Unha applet para controlar os reprodutores multimédia +Comment[he]=יישומן לשליטה בנגני מדיה +Comment[hi]=मीडिया प्लेयर्स को नियंत्रित करने का ऐपलेट +Comment[hr]=Aplet za upravljanje multimedijskim programima +Comment[hu]=Médialejátszók vezérlésére szolgáló kisalkalmazás +Comment[is]=Íforrit til að stjórna margmiðlunarspilurum +Comment[it]=Applet per controllare i lettori multimediali +Comment[ja]=メディアプレーヤを操作するアプレット +Comment[ka]=მედია დამკვრელის მართვის აპლეტი +Comment[kk]=Мультимедиа ойнатқыштарды басқару апплеті +Comment[km]=អាប់ភ្លេតដើម្បីត្រួតពិនិត្យកម្មវិធីចាក់មេឌៀ +Comment[lt]=Media grotuvų valdymo įskiepis +Comment[lv]=Aplets mēdijuatskaņotāju vadībai +Comment[mk]=Аплет за контрола на медијаплеери +Comment[ms]=Aplet untuk kawal pemain media +Comment[mt]=Applet biex tikkontrolla players ta' media +Comment[nb]=Miniprogram for å styre multimediaspillere +Comment[nds]=Lüttprogramm för't Stüern vun Medienafspelers +Comment[ne]=मिडिया प्लेएर नियन्त्रण गर्ने एप्लेट +Comment[nl]=Applet om mediaspelers te besturen +Comment[nn]=Applet for kontroll av mediespelarar +Comment[pa]=ਮੀਡਿਆ ਪਲੇਅਰ ਕੰਟਰੋਲ ਲਈ ਐਪਲਿਟ +Comment[pl]=Programik do zarządzania mediami +Comment[pt]=Uma 'applet' para controlar os reprodutores multimédia +Comment[pt_BR]=Mini-aplicativo para controlar tocadores de mídia +Comment[ro]=Miniaplicaţie pentru controlul redării multimedia +Comment[ru]=Аплет для управления медиаплеерами +Comment[sk]=Applet pre ovládanie prehrávačov médií +Comment[sl]=Vstavek za nadzor večpredstavnih predvajalnikov +Comment[sr]=Аплет за контролисање медија плејера +Comment[sr@Latn]=Aplet za kontrolisanje medija plejera +Comment[sv]=Miniprogram för att kontrollera mediaspelare +Comment[ta]=ஊடக வாசிப்பான்களை கட்டுப்படுத்துவதற்கு சிறுநிரல் +Comment[tg]=Аплет барои идоракунии медиаплеерҳо +Comment[th]=แอพเพล็ตควบคุมโปรแกรมเล่นสื่อ +Comment[tr]=Ortam yürütücülerini kontrol etmek için bir programcık +Comment[uk]=Аплет для керування програвачами мультимедіа +Comment[uz]=Media-pleyerlarni boshqarish uchun applet +Comment[uz@cyrillic]=Медиа-плейерларни бошқариш учун апплет +Comment[ven]=Apulete yau langula tshitambi tsha media +Comment[vi]=Tiểu dụng điều khiển bộ phát nhạc/ảnh +Comment[xh]=Applet ukulawula usasazo lwabadlali +Comment[zh_CN]=控制媒体播放器的小程序 +Comment[zh_TW]=控制媒體播放器的小程式 +Comment[zu]=i Applet ukulawula abadlali bolawulo laphakathi +X-KDE-Library=mediacontrol_panelapplet +X-KDE-UniqueApplet=true +Icon=multimedia +X-KDE-ParentApp=kicker diff --git a/kicker-applets/mediacontrol/mediacontrol.h b/kicker-applets/mediacontrol/mediacontrol.h new file mode 100644 index 0000000..f5a6e5e --- /dev/null +++ b/kicker-applets/mediacontrol/mediacontrol.h @@ -0,0 +1,122 @@ +/*************************************************************************** + main file of mediacontrol applet + ------------------- + begin : Tue Apr 25 11:53:11 CEST 2000 + copyright : (C) 2000-2005 by Stefan Gehn + email : metz {AT} gehn {DOT} net + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef MEDIACONTROL_H +#define MEDIACONTROL_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <klocale.h> +#include <kpanelapplet.h> +#include <kdebug.h> +#include <kstandarddirs.h> +#include <kaboutdata.h> +#include <kaboutapplication.h> + +#include <qpalette.h> + +// used everywhere :) +#include <qstring.h> + +#include "playerInterface.h" +#include "configfrontend.h" +#include "mediacontroliface.h" +#include "simplebutton.h" + +#define MEDIACONTROL_VERSION "0.4" + +class MCSlider; +class KPopupMenu; +class KInstance; +class MediaControlConfig; +class KAboutData; +class MediaControlToolTip; + +// ============================================================================= + +class TrayButton : public SimpleButton +{ + Q_OBJECT + + public: + TrayButton(QWidget* parent, const char* name); + virtual ~TrayButton() {} + void setIconSet(const QIconSet &iconSet); +}; + +// ============================================================================= + +class MediaControl : public KPanelApplet, virtual public MediaControlIface +{ + Q_OBJECT + + public: + MediaControl(const QString&, Type, int ,QWidget * = 0, const char * = 0); + virtual ~MediaControl(); + + int widthForHeight(int height) const; + int heightForWidth(int width) const; + void dragEnterEvent(QDragEnterEvent* event); + void dropEvent(QDropEvent* event); + virtual void reparseConfig(); + + public slots: + void about(); + void preferences(); + void reportBug(); + + private: + KInstance *mInstance; + KAboutData *mAboutData; + DCOPClient *_dcopClient; + PlayerInterface *_player; + ConfigFrontend *_configFrontend; + MediaControlConfig *_prefsDialog; + TrayButton *prev_button; // GoTo Previous Playlist-Item + TrayButton *playpause_button; // Start/Pause playing + TrayButton *stop_button; // Stop the music + TrayButton *next_button; // GoTo Next Playlist-Item + MCSlider *time_slider; + int mLastLen, mLastTime, mLastStatus; + KPopupMenu *rmbMenu; + + virtual void mousePressEvent(QMouseEvent* e); + virtual void moveEvent(QMoveEvent*); + virtual void paletteChange(const QPalette&); + virtual void resizeEvent(QResizeEvent*); + virtual bool eventFilter(QObject *watched, QEvent *e); + + friend class MediaControlToolTip; + MediaControlToolTip *slider_tooltip; + + private slots: + void setSliderPosition(int len, int time); + void slotIconChanged(); + void disableAll(); + void enableAll(); + void slotClosePrefsDialog(); + void slotPrefsDialogClosing(); + void slotConfigChanged(); + void adjustTime(int); + void slotPlayingStatusChanged(int status); + + signals: + void newJumpToTime(int); +}; +#endif diff --git a/kicker-applets/mediacontrol/mediacontrolconfig.cpp b/kicker-applets/mediacontrol/mediacontrolconfig.cpp new file mode 100644 index 0000000..b146ff1 --- /dev/null +++ b/kicker-applets/mediacontrol/mediacontrolconfig.cpp @@ -0,0 +1,197 @@ +/*************************************************************************** + mediacontrol configuration dialog + ------------------- + begin : forgot :/ + copyright : (C) 2000-2005 by Stefan Gehn + email : metz {AT} gehn {DOT} net + + code-skeleton taken from knewsticker which is + Copyright (c) Frerich Raabe <raabe@kde.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. * + * * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "mediacontrolconfig.h" +#include "mediacontrolconfigwidget.h" + +#include <qdir.h> +#include <qcheckbox.h> +#include <qlistbox.h> +#include <qtoolbutton.h> +#include <qlayout.h> +#include <qgroupbox.h> + +#include <kapplication.h> +#include <kdebug.h> +#include <kconfig.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <klistbox.h> +#include <klocale.h> +#include <knuminput.h> +#include <kstandarddirs.h> + +MediaControlConfig::MediaControlConfig( ConfigFrontend *cfg, QWidget *parent, const char* name) +: KDialogBase( parent, name, false, i18n("MediaControl"), Ok | Apply | Cancel, Ok, false ) +{ + _configFrontend = cfg; + if (!_configFrontend) // emergency!!! + return; + + _child = new MediaControlConfigWidget(this); + setMainWidget ( _child ); + +#ifdef HAVE_XMMS + _child->playerListBox->insertItem("XMMS"); +#endif + _child->playerListBox->insertItem("Noatun"); + _child->playerListBox->insertItem("Amarok"); + _child->playerListBox->insertItem("JuK"); + _child->playerListBox->insertItem("mpd"); + _child->playerListBox->insertItem("KsCD"); + + _child->themeListBox->clear(); + // fill with available skins + KGlobal::dirs()->addResourceType("themes", KStandardDirs::kde_default("data") + "mediacontrol"); + QStringList list = KGlobal::dirs()->resourceDirs("themes"); + for (QStringList::ConstIterator it = list.constBegin(); it != list.constEnd(); ++it) + readSkinDir(*it); + + connect(_child->mWheelScrollAmount, SIGNAL(valueChanged(int)), SLOT(slotConfigChanged())); + connect(_child->playerListBox, SIGNAL(selectionChanged()), SLOT(slotConfigChanged())); + connect(_child->themeListBox, SIGNAL(selectionChanged()), SLOT(slotConfigChanged())); + connect(_child->themeListBox, SIGNAL(selectionChanged(QListBoxItem *)), SLOT(slotChangePreview(QListBoxItem *))); + connect(_child->mUseThemes, SIGNAL(toggled(bool)), SLOT(slotConfigChanged()) ); + connect(_child->mUseThemes, SIGNAL(toggled(bool)), SLOT(slotUseThemesToggled(bool)) ); + + load(); + show(); + + enableButtonApply ( false ); // apply id disabled until something changed +} + +void MediaControlConfig::readSkinDir( const QString &dir ) +{ + QDir directory( dir ); + if (!directory.exists()) + return; + + const QFileInfoList *list = directory.entryInfoList(); + QFileInfoListIterator it(*list); + + while ( it.current() ) + { + // append directory-name to our theme-listbox + if ( QFile(it.current()->absFilePath()+"/play.png").exists() ) + _child->themeListBox->insertItem ( it.current()->baseName(), -1 ); + ++it; + } +} + +// ============================================================================ + +void MediaControlConfig::load() +{ + // find the playerstring from config in the playerlist and select it if found + QListBoxItem *item = 0; + + item = _child->playerListBox->findItem( _configFrontend->player() ); + if ( item ) + _child->playerListBox->setCurrentItem ( item ); + else + _child->playerListBox->setCurrentItem( 0 ); + + // reset item to a proper state + item=0; + + _child->mWheelScrollAmount->setValue( _configFrontend->mouseWheelSpeed() ); + + // Select the used Theme + item = _child->themeListBox->findItem( _configFrontend->theme() ); + if ( item ) + _child->themeListBox->setCurrentItem( item ); + else + _child->themeListBox->setCurrentItem( 0 ); + + + bool ison = _configFrontend->useCustomTheme(); + _child->mUseThemes->setChecked( ison ); + slotUseThemesToggled( ison ); +} + +void MediaControlConfig::save() +{ +// kdDebug(90200) << "MediaControlConfig::save()" << endl; + for ( int it=0 ; it <= _child->playerListBox->numRows(); ++it ) + { + if ( _child->playerListBox->isSelected(it) ) + { + _configFrontend->setPlayer ( _child->playerListBox->text(it) ); + } + } + + _configFrontend->setMouseWheelSpeed ( _child->mWheelScrollAmount->value() ); + + for ( int it=0 ; it <= _child->themeListBox->numRows(); ++it ) + { + if ( _child->themeListBox->isSelected(it) ) + { + _configFrontend->setTheme ( _child->themeListBox->text(it) ); + } + } + + _configFrontend->setUseCustomTheme( _child->mUseThemes->isChecked() ); + + emit configChanged(); +} + +void MediaControlConfig::slotApply() +{ + save(); + enableButtonApply(false); +} + +void MediaControlConfig::slotOk() +{ + save(); + emit closing(); +} + +void MediaControlConfig::slotCancel() +{ + emit closing(); +} + +void MediaControlConfig::slotConfigChanged() +{ + enableButtonApply ( true ); +} + +void MediaControlConfig::slotChangePreview(QListBoxItem *item) +{ + QString skindir = item->text(); + _child->previewPrev->setIconSet(SmallIconSet(locate("themes",skindir+"/prev.png"))); + _child->previewPlay->setIconSet(SmallIconSet(locate("themes",skindir+"/play.png"))); + _child->previewPause->setIconSet(SmallIconSet(locate("themes",skindir+"/pause.png"))); + _child->previewStop->setIconSet(SmallIconSet(locate("themes",skindir+"/stop.png"))); + _child->previewNext->setIconSet(SmallIconSet(locate("themes",skindir+"/next.png"))); +} + +void MediaControlConfig::slotUseThemesToggled(bool on) +{ + _child->themeListBox->setEnabled(on); + _child->previewGroupBox->setEnabled(on); +} + +#include "mediacontrolconfig.moc" diff --git a/kicker-applets/mediacontrol/mediacontrolconfig.h b/kicker-applets/mediacontrol/mediacontrolconfig.h new file mode 100644 index 0000000..5869722 --- /dev/null +++ b/kicker-applets/mediacontrol/mediacontrolconfig.h @@ -0,0 +1,54 @@ +/*************************************************************************** + mediacontrol configuration dialog + ------------------- + begin : forgot :/ + copyright : (C) 2000-2005 by Stefan Gehn + email : metz {AT} gehn {DOT} net + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef MEDIACONTROLCONFIG_H +#define MEDIACONTROLCONFIG_H + +#include "configfrontend.h" +#include <kdialogbase.h> + +class MediaControlConfigWidget; +class ConfigFrontend; +class KConfig; + +class MediaControlConfig: public KDialogBase +{ +Q_OBJECT +public: + MediaControlConfig(ConfigFrontend *cfg, QWidget *parent = 0, const char* name = "MediaControlConfig"); + + void readSkinDir(const QString &dir); + void load(); + void save(); + +signals: + void closing(); + void configChanged(); + +protected slots: + void slotConfigChanged(); + void slotChangePreview(QListBoxItem *item); + void slotUseThemesToggled(bool); + virtual void slotApply(); + virtual void slotOk(); + virtual void slotCancel(); + +private: + ConfigFrontend *_configFrontend; + MediaControlConfigWidget *_child; +}; +#endif // MEDIACONTROLCONFIG_H diff --git a/kicker-applets/mediacontrol/mediacontrolconfigwidget.ui b/kicker-applets/mediacontrol/mediacontrolconfigwidget.ui new file mode 100644 index 0000000..9f5c662 --- /dev/null +++ b/kicker-applets/mediacontrol/mediacontrolconfigwidget.ui @@ -0,0 +1,374 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>MediaControlConfigWidget</class> +<comment>Preferences-Dialog for MediaControl </comment> +<author>Stefan Gehn <metz@gehn.net></author> +<widget class="QWidget"> + <property name="name"> + <cstring>MediaControlConfigWidget</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>318</width> + <height>245</height> + </rect> + </property> + <property name="layoutMargin" stdset="0"> + </property> + <property name="layoutSpacing" stdset="0"> + </property> + <property name="toolTip" stdset="0"> + <string></string> + </property> + <property name="whatsThis" stdset="0"> + <string></string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <widget class="QTabWidget"> + <property name="name"> + <cstring>tabWidget</cstring> + </property> + <widget class="QWidget"> + <property name="name"> + <cstring>tabGeneral</cstring> + </property> + <attribute name="title"> + <string>&General</string> + </attribute> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox" row="0" column="0"> + <property name="name"> + <cstring>gbMediaPlayer</cstring> + </property> + <property name="title"> + <string>Media-Player</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KListBox" row="0" column="0"> + <property name="name"> + <cstring>playerListBox</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string>Select the multimedia player you are using from this list.</string> + </property> + </widget> + </grid> + </widget> + <widget class="QLayoutWidget" row="1" column="0"> + <property name="name"> + <cstring>Layout5</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>lmousewheelscrollingamount</cstring> + </property> + <property name="text"> + <string>&Wheel scroll seconds:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>mWheelScrollAmount</cstring> + </property> + </widget> + <widget class="KIntSpinBox"> + <property name="name"> + <cstring>mWheelScrollAmount</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string>Sets the number of lines a mousewheel will scroll in the current file.</string> + </property> + </widget> + </hbox> + </widget> + </grid> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>themes</cstring> + </property> + <attribute name="title"> + <string>&Themes</string> + </attribute> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>mUseThemes</cstring> + </property> + <property name="text"> + <string>&Use themes</string> + </property> + </widget> + <widget class="KListBox"> + <item> + <property name="text"> + <string>default</string> + </property> + </item> + <property name="name"> + <cstring>themeListBox</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>7</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>Layout4</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>Spacer1</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>0</height> + </size> + </property> + </spacer> + <widget class="QGroupBox"> + <property name="name"> + <cstring>previewGroupBox</cstring> + </property> + <property name="title"> + <string>Preview</string> + </property> + <property name="layoutMargin" stdset="0"> + </property> + <property name="layoutSpacing" stdset="0"> + </property> + <property name="whatsThis" stdset="0"> + <string>Shows you how the selected theme will look</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>8</number> + </property> + <property name="spacing"> + <number>2</number> + </property> + <widget class="QToolButton" row="0" column="0"> + <property name="name"> + <cstring>previewPrev</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>18</width> + <height>18</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>18</width> + <height>18</height> + </size> + </property> + <property name="text"> + <string><</string> + </property> + </widget> + <widget class="QToolButton" row="0" column="1"> + <property name="name"> + <cstring>previewPlay</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>18</width> + <height>18</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>18</width> + <height>18</height> + </size> + </property> + <property name="text"> + <string>></string> + </property> + </widget> + <widget class="QToolButton" row="0" column="2"> + <property name="name"> + <cstring>previewPause</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>18</width> + <height>18</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>18</width> + <height>18</height> + </size> + </property> + <property name="text"> + <string>o</string> + </property> + </widget> + <widget class="QToolButton" row="0" column="3"> + <property name="name"> + <cstring>previewStop</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>18</width> + <height>18</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>18</width> + <height>18</height> + </size> + </property> + <property name="text"> + <string>O</string> + </property> + </widget> + <widget class="QToolButton" row="0" column="4"> + <property name="name"> + <cstring>previewNext</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>18</width> + <height>18</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>18</width> + <height>18</height> + </size> + </property> + <property name="text"> + <string>></string> + </property> + </widget> + </grid> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer1_2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>0</height> + </size> + </property> + </spacer> + </hbox> + </widget> + </vbox> + </widget> + </widget> + </hbox> +</widget> +<customwidgets> +</customwidgets> +<includes> + <include location="local" impldecl="in implementation"></include> + <include location="local" impldecl="in declaration"></include> + <include location="global" impldecl="in declaration">knuminput.h</include> + <include location="global" impldecl="in declaration">klistview.h</include> + <include location="global" impldecl="in declaration">klistbox.h</include> +</includes> +<signals> + <signal>toggled(bool)</signal> +</signals> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>klistbox.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>klistbox.h</includehint> +</includehints> +</UI> diff --git a/kicker-applets/mediacontrol/mediacontroliface.h b/kicker-applets/mediacontrol/mediacontroliface.h new file mode 100644 index 0000000..5a47fb3 --- /dev/null +++ b/kicker-applets/mediacontrol/mediacontroliface.h @@ -0,0 +1,31 @@ +/*************************************************************************** + dcopinterface for mediacontrol + mainly used to be informed about new settings + ------------------- + begin : Mon Jan 15 21:09:00 MEZ 2001 + copyright : (C) 2001 by Stefan Gehn + email : metz {AT} gehn {DOT} net + ***************************************************************************/ +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef MEDIACONTROLIFACE_H +#define MEDIACONTROLIFACE_H + +#include <dcopobject.h> + +class MediaControlIface : virtual public DCOPObject +{ + K_DCOP + + k_dcop: + virtual void reparseConfig() = 0; +}; + +#endif // MEDIACONTROLIFACE_H diff --git a/kicker-applets/mediacontrol/mpdInterface.cpp b/kicker-applets/mediacontrol/mpdInterface.cpp new file mode 100644 index 0000000..8027f82 --- /dev/null +++ b/kicker-applets/mediacontrol/mpdInterface.cpp @@ -0,0 +1,585 @@ +/*************************************************************************** + Interface to access mpd + ------------------- + begin : Tue Apr 19 18:31:00 BST 2005 + copyright : (C) 2005 by William Robinson + email : airbaggins@yahoo.co.uk + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "mpdInterface.h" + +#include <cstring> + +#include <qregexp.h> + +#include <kmessagebox.h> +#include <kdebug.h> +#include <kurldrag.h> + +MpdInterface::MpdInterface() +: PlayerInterface() +, sock() +, sock_mutex() +, messagebox_mutex() +, hostname("localhost") +, port(6600) +, slider_timer(0) +, reconnect_timer(0) +{ + connect(&sock, SIGNAL(error(int)), this, SLOT(connectionError(int))); + connect(&sock, SIGNAL(error(int)), this, SLOT(stopSliderClock())); + + connect(&sock, SIGNAL(connected()), this, SLOT(startSliderClock())); + connect(&sock, SIGNAL(connected()), this, SLOT(stopReconnectClock())); + connect(&sock, SIGNAL(connected()), this, SLOT(connected())); + + connect(&sock, SIGNAL(connectionClosed()), this, SLOT(stopSliderClock())); + connect(&sock, SIGNAL(connectionClosed()), this, SLOT(startReconnectClock())); + connect(&sock, SIGNAL(connectionClosed()), this, SIGNAL(playerStopped())); + + reconnect(); +} + +MpdInterface::~MpdInterface() +{ +} + +void MpdInterface::startSliderClock() +{ + if (!slider_timer) + { + //kdDebug(90200) << "Starting slider clock\n"; + slider_timer = startTimer(SLIDER_TIMER_INTERVAL); + } +} + +void MpdInterface::stopSliderClock() +{ + if (slider_timer) + { + //kdDebug(90200) << "Stopping slider clock\n"; + killTimer(slider_timer); + slider_timer=0; + } +} +void MpdInterface::startReconnectClock() +{ + if (!reconnect_timer) + { + //kdDebug(90200) << "Starting Reconnect clock\n"; + reconnect_timer = startTimer(RECONNECT_TIMER_INTERVAL); + } +} + +void MpdInterface::stopReconnectClock() +{ + if (reconnect_timer) + { + //kdDebug(90200) << "Stopping Reconnect clock\n"; + killTimer(reconnect_timer); + reconnect_timer=0; + } +} + + +void MpdInterface::timerEvent(QTimerEvent* te) +{ + if (te->timerId() == slider_timer) updateSlider(); + else if (te->timerId() == reconnect_timer) reconnect(); +} + + +void MpdInterface::reconnect() const +{ + if (sock.state()==QSocket::Idle) + { + sock_mutex.tryLock(); + //kdDebug(90200) << "Connecting to " << hostname.latin1() << ":" << port << "...\n"; + sock.connectToHost(hostname,port); + } +} + +void MpdInterface::connected() +{ + if (fetchOk()) // unlocks + { + //kdDebug(90200) << "Connected ok\n"; + emit playerStarted(); + emit playingStatusChanged(playingStatus()); + } + else + { + //kdDebug(90200) << "Connection error\n"; + emit playerStopped(); + } +} + +void MpdInterface::connectionError(int e) +{ + sock_mutex.unlock(); + emit playerStopped(); + QString message; + if (messagebox_mutex.tryLock()) + { + switch (e) + { + case QSocket::ErrConnectionRefused: + message=i18n("Connection refused to %1:%2.\nIs mpd running?").arg(hostname).arg(port); + break; + case QSocket::ErrHostNotFound: + message=i18n("Host '%1' not found.").arg(hostname); + break; + case QSocket::ErrSocketRead: + message=i18n("Error reading socket."); + break; + default: + message=i18n("Connection error"); + break; + } + // :TODO: KSimpleConfig to prompt for hostname/port values ? + if (KMessageBox::warningContinueCancel( 0, message, + i18n("MediaControl MPD Error"), + i18n("Reconnect"))==KMessageBox::Continue) + { + startReconnectClock(); + } + else + { + stopReconnectClock(); + } + messagebox_mutex.unlock(); + } +} + +bool MpdInterface::dispatch(const char* cmd) const +{ + if (sock.state()==QSocket::Connected && sock_mutex.tryLock()) + { + long cmd_len=strlen(cmd); + //kdDebug(90200) << "sending: " << cmd; + long written=sock.writeBlock(cmd,cmd_len); + if (written==cmd_len) + { + //kdDebug(90200) << "All bytes written\n"; + sock.flush(); + return true; + } + else + { + //kdDebug(90200) << written << '/' << cmd_len << " bytes written\n"; + } + sock.flush(); + } + return false; +} + +bool MpdInterface::fetchLine(QString& res) const +{ + QString errormessage; + while (sock.state()==QSocket::Connected) + { + if (!sock.canReadLine()) + { + sock.waitForMore(20); + continue; + } + res=sock.readLine().stripWhiteSpace(); + //kdDebug(90200) << "received: " << res.latin1() << "\n"; + if (res.startsWith("OK")) + { + sock_mutex.unlock(); + // if theres a message and we clear it and there's no other messagebox + if (!errormessage.isEmpty() + && dispatch("clearerror\n") && fetchOk() + && messagebox_mutex.tryLock()) + { + KMessageBox::error(0,errormessage,i18n("MediaControl MPD Error")); + messagebox_mutex.unlock(); + } + return false; + } + else if (res.startsWith("ACK")) + { + sock_mutex.unlock(); + return false; + } + else if (res.startsWith("error: ")) + { + errormessage=i18n(res.latin1()); + } + else + { + return true; + } + } + sock_mutex.unlock(); + return false; +} + +bool MpdInterface::fetchOk() const +{ + QString res; + while (fetchLine(res)) { } + if (res.startsWith("OK")) + return true; + else + return false; +} + +void MpdInterface::updateSlider() +{ + //kdDebug(90200) << "update slider\n"; + if (!dispatch("status\n")) return; + + QString res; + QRegExp time_re("time: (\\d+):(\\d+)"); + while(fetchLine(res)) + { + if (res.startsWith("state: ")) + { + if (res.endsWith("play")) + { + emit playingStatusChanged(Playing); + } + else if (res.endsWith("pause")) + { + emit playingStatusChanged(Paused); + } + else + { + emit playingStatusChanged(Stopped); + } + } + else if (time_re.search(res)>=0) + { + QStringList timeinfo=time_re.capturedTexts(); + timeinfo.pop_front(); + int elapsed_seconds=timeinfo.first().toInt(); + timeinfo.pop_front(); + int total_seconds=timeinfo.first().toInt(); + emit newSliderPosition(total_seconds,elapsed_seconds); + } + } +} + +void MpdInterface::sliderStartDrag() +{ + stopSliderClock(); +} + +void MpdInterface::sliderStopDrag() +{ + startSliderClock(); +} + +void MpdInterface::jumpToTime(int sec) +{ + reconnect(); + if (!dispatch("status\n")) return; + + long songid=-1; + + QString res; + QRegExp songid_re("songid: (\\d+)"); + while(fetchLine(res)) + { + if (songid_re.search(res)>=0) + { + QStringList songidinfo=songid_re.capturedTexts(); + songidinfo.pop_front(); + songid=songidinfo.first().toInt(); + } + } + + if (songid>-1) + { + if (dispatch(QString("seekid %1 %2\n").arg(songid).arg(sec).latin1())) + { + fetchOk(); // unlocks + } + } +} + +void MpdInterface::playpause() +{ + reconnect(); + if (playingStatus()==Stopped ? dispatch("play\n") : dispatch("pause\n")) + { + fetchOk(); + } +} + +void MpdInterface::stop() +{ + reconnect(); + if (dispatch("stop\n")) fetchOk(); +} + +void MpdInterface::next() +{ + reconnect(); + if (dispatch("next\n")) fetchOk(); +} + +void MpdInterface::prev() +{ + reconnect(); + if (dispatch("previous\n")) fetchOk(); +} + + +void MpdInterface::changeVolume(int delta) +{ + reconnect(); + + if (!dispatch("status\n")) return; + + int volume=-1; + + QString res; + QRegExp volume_re("volume: (\\d+)"); + while(fetchLine(res)) + { + if (volume_re.search(res)>=0) + { + QStringList info=volume_re.capturedTexts(); + info.pop_front(); + volume=info.first().toInt(); + } + } + + if (volume>-1) + { + volume+=delta; + if (volume<0) volume=0; + if (volume>100) volume=100; + if (dispatch(QString("setvol %1\n").arg(volume).latin1())) + { + fetchOk(); + } + } +} + +void MpdInterface::volumeUp() +{ + reconnect(); + changeVolume(5); +} + +void MpdInterface::volumeDown() +{ + reconnect(); + changeVolume(-5); +} + +void MpdInterface::dragEnterEvent(QDragEnterEvent* event) +{ + event->accept( KURLDrag::canDecode(event) ); +} + +void MpdInterface::dropEvent(QDropEvent* event) +{ + reconnect(); + + KURL::List list; + if (KURLDrag::decode(event, list)) + { + if (list.count()==1) // just one file dropped + { + // check to see if its in the playlist already + if (dispatch("playlistid\n")) + { + long songid=-1; + QString file; + QString res; + while(fetchLine(res)) + { + QRegExp file_re("file: (.+)"); + QRegExp id_re("Id: (.+)"); + if (file.isEmpty() && file_re.search(res)>=0) + { + QStringList info=file_re.capturedTexts(); + info.pop_front(); + // if the dropped file ends with the same name, record it + if (list.front().path().endsWith(info.first())) + { + file=info.first().toInt(); + } + } + else if (!file.isEmpty() && id_re.search(res)>=0) + { + // when we have the file, pick up the id (file scomes first) + QStringList info=id_re.capturedTexts(); + info.pop_front(); + songid=info.first().toInt(); + fetchOk(); // skip to the end + break; + } + } + + // found song, so lets play it + if (songid>-1) + { + if (dispatch((QString("playid %1\n").arg(songid)).latin1())) + { + if (fetchOk()) list.pop_front(); + return; + } + } + } + } + + // now if we have got this far, just try to add any files + for (KURL::List::const_iterator i = list.constBegin(); i!=list.constEnd(); ++i) + { + if ((*i).isLocalFile()) + { + QStringList path=QStringList::split("/",(*i).path()); + + while (!path.empty()) + { + if (dispatch((QString("add \"") + +path.join("/").replace("\"","\\\"") + +QString("\"\n")).latin1())) + { + if (fetchOk()) break; + } + path.pop_front(); + } + } + else + { + // :TODO: can handle http:// urls but maybe should check port or something + } + } + } +} + +const QString MpdInterface::getTrackTitle() const +{ + QString result; + + reconnect(); + + if (!dispatch("status\n")) return result; + + long songid=-1; + QString res; + while(fetchLine(res)) + { + QRegExp songid_re("songid: (\\d+)"); + if (songid_re.search(res)>=0) + { + QStringList songidinfo=songid_re.capturedTexts(); + songidinfo.pop_front(); + songid=songidinfo.first().toInt(); + } + } + + if (!(songid>-1)) return result; + + if (!dispatch(QString("playlistid %1\n").arg(songid).latin1())) + return result; + + QString artist; + QString album; + QString title; + QString track; + QString file; + while(fetchLine(res)) + { + QRegExp artist_re("Artist: (.+)"); + QRegExp album_re("Album: (.+)"); + QRegExp track_re("Album: (.+)"); + QRegExp title_re("Title: (.+)"); + QRegExp file_re("file: (.+)"); + if (artist_re.search(res)>=0) + { + QStringList info=artist_re.capturedTexts(); + info.pop_front(); + artist=info.first(); + } + else if (album_re.search(res)>=0) + { + QStringList info=album_re.capturedTexts(); + info.pop_front(); + album=info.first(); + } + else if (title_re.search(res)>=0) + { + QStringList info=title_re.capturedTexts(); + info.pop_front(); + title=info.first(); + } + else if (track_re.search(res)>=0) + { + QStringList info=track_re.capturedTexts(); + info.pop_front(); + track=info.first(); + } + else if (file_re.search(res)>=0) + { + QStringList info=file_re.capturedTexts(); + info.pop_front(); + file=info.first(); + } + } + + if (!artist.isEmpty()) + { + if (!title.isEmpty()) + return artist.append(" - ").append(title); + else if (!album.isEmpty()) + return artist.append(" - ").append(album); + } + else if (!title.isEmpty()) + { + if (!album.isEmpty()) + return album.append(" - ").append(title); + else + return title; + } + else if (!album.isEmpty()) + { + if (!track.isEmpty()) + return album.append(" - ").append(track); + else + return album; + } + return i18n("No tags: %1").arg(file); +} + +int MpdInterface::playingStatus() +{ + //kdDebug(90200) << "looking up playing status\n"; + if (!dispatch("status\n")) return Stopped; + + PlayingStatus status=Stopped; + QString res; + while(fetchLine(res)) + { + if (res.startsWith("state: ")) + { + if (res.endsWith("play")) status=Playing; + else if (res.endsWith("pause")) status=Paused; + else status=Stopped; + } + } + + return status; +} + +#include "mpdInterface.moc" diff --git a/kicker-applets/mediacontrol/mpdInterface.h b/kicker-applets/mediacontrol/mpdInterface.h new file mode 100644 index 0000000..d891586 --- /dev/null +++ b/kicker-applets/mediacontrol/mpdInterface.h @@ -0,0 +1,100 @@ +/*************************************************************************** + this is the class to access mpd from + ------------------- + begin : Tue Apr 19 18:31:00 BST 2005 + copyright : (C) 2005 by William Robinson + email : airbaggins@yahoo.co.uk + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifndef MPDINTERFACE_H +#define MPDINTERFACE_H + +#include "playerInterface.h" +#include <qtimer.h> +#include <klocale.h> +#include <qsocket.h> +#include <qmutex.h> + +class MpdInterface +: public PlayerInterface +{ + Q_OBJECT + public: + MpdInterface(); + ~MpdInterface(); + + public slots: + virtual void updateSlider(); + virtual void sliderStartDrag(); + virtual void sliderStopDrag(); + virtual void jumpToTime(int sec); + virtual void playpause(); + virtual void stop(); + virtual void next(); + virtual void prev(); + virtual void volumeUp(); + virtual void volumeDown(); + virtual void dragEnterEvent(QDragEnterEvent* event); + virtual void dropEvent(QDropEvent* event); + virtual const QString getTrackTitle() const; + virtual int playingStatus(); + + void changeVolume(int delta); + + void connectionError(int e); + void connected(); + + void startSliderClock(); + void stopSliderClock(); + + void startReconnectClock(); + void stopReconnectClock(); + + + protected: + virtual void timerEvent(QTimerEvent* te); + + private: + mutable QSocket sock; + mutable QMutex sock_mutex; + + mutable QMutex messagebox_mutex; + + QString hostname; + int port; + + static const int SLIDER_TIMER_INTERVAL = 500; // ms + int slider_timer; + + static const int RECONNECT_TIMER_INTERVAL = 5000; // ms + int reconnect_timer; + + /** starts connecting and returns, if not connected already. */ + void reconnect() const; + + /** this locks the sock sock_mutex. remember to unlock it. */ + bool dispatch(const char* cmd) const; + + /** fetches everything from the sock to the OK and unlocks the mutex. + returns true if OK, false on anything else. */ + bool fetchOk() const; + + /** fetches a line and returns true, or false if OK or ACK (end of + message). Will unlock the sock_mutex on the end of message. */ + bool fetchLine(QString& res) const; +}; + +#endif // MPDINTERFACE_H diff --git a/kicker-applets/mediacontrol/noatunInterface.cpp b/kicker-applets/mediacontrol/noatunInterface.cpp new file mode 100644 index 0000000..f6cdfc8 --- /dev/null +++ b/kicker-applets/mediacontrol/noatunInterface.cpp @@ -0,0 +1,283 @@ +/*************************************************************************** + Interface to access Noatun + ------------------- + begin : Mon Jan 15 21:09:00 CEST 2001 + copyright : (C) 2000-2002 by Stefan Gehn + email : metz {AT} gehn {DOT} net + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include "noatunInterface.h" +#include "noatunInterface.moc" + +#include <kapplication.h> +#include <kdebug.h> +#include <qstringlist.h> +#include <qstrlist.h> +#include <kurldrag.h> + +#define TIMER_FAST 250 + +NoatunInterface::NoatunInterface() : PlayerInterface() +{ + mTimerValue = TIMER_FAST; + mNoatunTimer = new QTimer(this, "mNoatunTimer"); + + connect(mNoatunTimer, SIGNAL(timeout()), SLOT(updateSlider())); + + connect(kapp->dcopClient(), SIGNAL(applicationRegistered(const QCString&)), + SLOT(appRegistered(const QCString&)) ); + + connect(kapp->dcopClient(), SIGNAL(applicationRemoved(const QCString&)), + SLOT(appRemoved(const QCString&))); + + kapp->dcopClient()->setNotifications(true); + QTimer::singleShot(0, this, SLOT(myInit())); +} + +NoatunInterface::~NoatunInterface() +{ + kapp->dcopClient()->setNotifications(false); +} + +void NoatunInterface::myInit() +{ + // Start the timer if noatun is already running + // Needed if user adds applet while running noatun + if ( findRunningNoatun() ) + { + emit playerStarted(); + mNoatunTimer->start(mTimerValue); + } + else + { + emit playerStopped(); + emit newSliderPosition(0,0); + } +} + +void NoatunInterface::appRegistered(const QCString &appId) +{ + if (appId.contains("noatun",false)) + { + mAppId = appId; + emit playerStarted(); + mNoatunTimer->start(mTimerValue); + } +} + +void NoatunInterface::appRemoved(const QCString &appId) +{ + if (appId.contains("noatun",false)) + { + // is there still another noatun alive? + if (findRunningNoatun()) + return; + mNoatunTimer->stop(); + emit playerStopped(); + emit newSliderPosition(0,0); + } +} + +void NoatunInterface::updateSlider() +{ + // length/time in msecs, -1 means "no playobject in noatun" + int len, time; + QByteArray data, replyData; + QCString replyType; + + if (!kapp->dcopClient()->call(mAppId, "Noatun", "length()", data, replyType, replyData, false, 200)) + { + //kdDebug(90200) << "mediacontrol: DCOP communication Error" << endl; + // -2 is an internal errornumber, might be used later + len = -2; + } + else + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "int") + { + reply >> len; + } + else + { + //kdDebug(90200) << "mediacontrol: unexpected type of DCOP-reply" << endl; + // -3 is an internal errornumber, might be used later + len = -3; + } + } + + data = 0; + replyData = 0; + replyType = 0; + + if (!kapp->dcopClient()->call(mAppId, "Noatun", "position()", data, + replyType, replyData, false, 200)) + { + //kdDebug(90200) << "mediacontrol: DCOP communication error" << endl; + time = -2; + } + else + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "int") + { + reply >> time; + } + else + { + //kdDebug(90200) << "mediacontrol: unexpected type of DCOP-reply" << endl; + time = -3; + } + } + + if ((time < 0) || (len < 0)) // Noatun isn't playing and thus returns -1 + { + len = 0; + time = 0; + } + emit newSliderPosition(len/1000,time/1000); + emit playingStatusChanged(playingStatus()); +} + +int NoatunInterface::playingStatus() +{ + QByteArray data, replyData; + QCString replyType; + + if (!kapp->dcopClient()->call(mAppId, "Noatun", "state()", data, replyType, + replyData, false, 200)) + { + return Stopped; + } + else + { + int status = 0; + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "int") + reply >> status; + + if (status == 1) + return Paused; + else if (status == 2) + return Playing; + else + return Stopped; + } +} + + +// Drag-n-Drop stuff ================================================================= + +void NoatunInterface::dragEnterEvent(QDragEnterEvent* event) +{ +// kdDebug(90200) << "NoatunInterface::dragEnterEvent()" << endl; + event->accept(KURLDrag::canDecode(event)); +} + +void NoatunInterface::dropEvent(QDropEvent* event) +{ +// kdDebug(90200) << "NoatunInterface::dropEvent()" << endl; + KURL::List list; + if (KURLDrag::decode(event, list)) + { + QByteArray data; + QDataStream arg(data, IO_WriteOnly); + arg << list.toStringList() << false; + kapp->dcopClient()->send(mAppId, "Noatun", "addFile(QStringList,bool)", data); + } +} + +// ==================================================================================== + +void NoatunInterface::sliderStartDrag() +{ + mNoatunTimer->stop(); +} + +void NoatunInterface::sliderStopDrag() +{ + mNoatunTimer->start(mTimerValue); +} + +void NoatunInterface::jumpToTime(int sec) +{ + QByteArray data; + QDataStream arg(data, IO_WriteOnly); + arg << (sec*1000); // noatun wants milliseconds + kapp->dcopClient()->send(mAppId, "Noatun", "skipTo(int)", data); +} + +void NoatunInterface::playpause() +{ + if (!findRunningNoatun()) + startPlayer("noatun"); + kapp->dcopClient()->send(mAppId, "Noatun", "playpause()", QString::null); +} + +void NoatunInterface::stop() +{ + kapp->dcopClient()->send(mAppId, "Noatun", "stop()", QString::null); +} + +void NoatunInterface::next() +{ + // fastForward() is noatun from kde2 + //kapp->dcopClient()->send("noatun", "Noatun", "fastForward()", QString::null); + kapp->dcopClient()->send(mAppId, "Noatun", "forward()", QString::null); +} + +void NoatunInterface::prev() +{ + kapp->dcopClient()->send(mAppId, "Noatun", "back()", QString::null); +} + +void NoatunInterface::volumeUp() +{ + kapp->dcopClient()->send(mAppId, "Noatun", "volumeDown()", QString::null); +} + +void NoatunInterface::volumeDown() +{ + kapp->dcopClient()->send(mAppId, "Noatun", "volumeUp()", QString::null); +} + +const QString NoatunInterface::getTrackTitle() const +{ + QString title(""); + QByteArray data, replyData; + QCString replyType; + if (kapp->dcopClient()->call(mAppId, "Noatun", "title()", data, replyType, + replyData, false, 200)) + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "QString") + reply >> title; + } + return title; +} + +bool NoatunInterface::findRunningNoatun() +{ + // FIXME: what if we have a dcop app named, let's say, 'noatunfrontend'? + QCStringList allApps = kapp->dcopClient()->registeredApplications(); + QValueList<QCString>::const_iterator iterator; + + for (iterator = allApps.constBegin(); iterator != allApps.constEnd(); ++iterator) + { + if ((*iterator).contains("noatun", false)) + { + mAppId = *iterator; + return true; + } + } + return false; +} diff --git a/kicker-applets/mediacontrol/noatunInterface.h b/kicker-applets/mediacontrol/noatunInterface.h new file mode 100644 index 0000000..99191b5 --- /dev/null +++ b/kicker-applets/mediacontrol/noatunInterface.h @@ -0,0 +1,67 @@ +/*************************************************************************** + Interface to access Noatun + ------------------- + begin : Mon Jan 15 21:09:00 MEZ 2001 + copyright : (C) 2001-2002 by Stefan Gehn + email : metz {AT} gehn {DOT} net + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef NOATUNINTERFACE_H +#define NOATUNINTERFACE_H + +#include "playerInterface.h" + +#include <kapplication.h> +#include <dcopclient.h> + +#include <qtimer.h> + +class NoatunInterface : public PlayerInterface +{ + Q_OBJECT + public: + NoatunInterface(); + ~NoatunInterface(); + + public slots: + void updateSlider(); + void sliderStartDrag(); + void sliderStopDrag(); + void jumpToTime(int sec); + void playpause(); + void stop(); + void next(); + void prev(); + void volumeUp(); + void volumeDown(); + void dragEnterEvent(QDragEnterEvent* event); + void dropEvent(QDropEvent* event); + const QString getTrackTitle() const; + void appRegistered(const QCString &appId); + void appRemoved(const QCString &appId); + int playingStatus(); + + void myInit(void); + + private: + QTimer *mNoatunTimer; + int mTimerValue; + QCString mAppId; + + /** + * Tries to find a DCOP registered instance of Noatun + * Stores the name of the first found instance in appId + * @returns true is instance is found, false otherwise + */ + bool findRunningNoatun(); +}; +#endif diff --git a/kicker-applets/mediacontrol/pics/Makefile.am b/kicker-applets/mediacontrol/pics/Makefile.am new file mode 100644 index 0000000..85ecf9b --- /dev/null +++ b/kicker-applets/mediacontrol/pics/Makefile.am @@ -0,0 +1,2 @@ +# Files to install +SUBDIRS= blueish default fulldecent diff --git a/kicker-applets/mediacontrol/pics/blueish/Makefile.am b/kicker-applets/mediacontrol/pics/blueish/Makefile.am new file mode 100644 index 0000000..5f7d372 --- /dev/null +++ b/kicker-applets/mediacontrol/pics/blueish/Makefile.am @@ -0,0 +1,4 @@ +# Files to install +pics_DATA = next.png pause.png play.png prev.png stop.png +# This is where it will all be installed +picsdir = $(kde_datadir)/mediacontrol/blueish diff --git a/kicker-applets/mediacontrol/pics/blueish/next.png b/kicker-applets/mediacontrol/pics/blueish/next.png Binary files differnew file mode 100644 index 0000000..260a033 --- /dev/null +++ b/kicker-applets/mediacontrol/pics/blueish/next.png diff --git a/kicker-applets/mediacontrol/pics/blueish/pause.png b/kicker-applets/mediacontrol/pics/blueish/pause.png Binary files differnew file mode 100644 index 0000000..4c62dae --- /dev/null +++ b/kicker-applets/mediacontrol/pics/blueish/pause.png diff --git a/kicker-applets/mediacontrol/pics/blueish/play.png b/kicker-applets/mediacontrol/pics/blueish/play.png Binary files differnew file mode 100644 index 0000000..6e85050 --- /dev/null +++ b/kicker-applets/mediacontrol/pics/blueish/play.png diff --git a/kicker-applets/mediacontrol/pics/blueish/prev.png b/kicker-applets/mediacontrol/pics/blueish/prev.png Binary files differnew file mode 100644 index 0000000..d4d8640 --- /dev/null +++ b/kicker-applets/mediacontrol/pics/blueish/prev.png diff --git a/kicker-applets/mediacontrol/pics/blueish/stop.png b/kicker-applets/mediacontrol/pics/blueish/stop.png Binary files differnew file mode 100644 index 0000000..05b1d33 --- /dev/null +++ b/kicker-applets/mediacontrol/pics/blueish/stop.png diff --git a/kicker-applets/mediacontrol/pics/default/Makefile.am b/kicker-applets/mediacontrol/pics/default/Makefile.am new file mode 100644 index 0000000..0ab094e --- /dev/null +++ b/kicker-applets/mediacontrol/pics/default/Makefile.am @@ -0,0 +1,4 @@ +# Files to install +pics_DATA = next.png pause.png play.png prev.png stop.png +# This is where it will all be installed +picsdir = $(kde_datadir)/mediacontrol/default diff --git a/kicker-applets/mediacontrol/pics/default/next.png b/kicker-applets/mediacontrol/pics/default/next.png Binary files differnew file mode 100644 index 0000000..7c47f76 --- /dev/null +++ b/kicker-applets/mediacontrol/pics/default/next.png diff --git a/kicker-applets/mediacontrol/pics/default/pause.png b/kicker-applets/mediacontrol/pics/default/pause.png Binary files differnew file mode 100644 index 0000000..6f51172 --- /dev/null +++ b/kicker-applets/mediacontrol/pics/default/pause.png diff --git a/kicker-applets/mediacontrol/pics/default/play.png b/kicker-applets/mediacontrol/pics/default/play.png Binary files differnew file mode 100644 index 0000000..789065f --- /dev/null +++ b/kicker-applets/mediacontrol/pics/default/play.png diff --git a/kicker-applets/mediacontrol/pics/default/prev.png b/kicker-applets/mediacontrol/pics/default/prev.png Binary files differnew file mode 100644 index 0000000..addcfc9 --- /dev/null +++ b/kicker-applets/mediacontrol/pics/default/prev.png diff --git a/kicker-applets/mediacontrol/pics/default/stop.png b/kicker-applets/mediacontrol/pics/default/stop.png Binary files differnew file mode 100644 index 0000000..e2bf48d --- /dev/null +++ b/kicker-applets/mediacontrol/pics/default/stop.png diff --git a/kicker-applets/mediacontrol/pics/fulldecent/Makefile.am b/kicker-applets/mediacontrol/pics/fulldecent/Makefile.am new file mode 100644 index 0000000..6892b15 --- /dev/null +++ b/kicker-applets/mediacontrol/pics/fulldecent/Makefile.am @@ -0,0 +1,4 @@ +# Files to install +pics_DATA = next.png pause.png play.png prev.png stop.png +# This is where it will all be installed +picsdir = $(kde_datadir)/mediacontrol/fulldecent diff --git a/kicker-applets/mediacontrol/pics/fulldecent/README b/kicker-applets/mediacontrol/pics/fulldecent/README new file mode 100644 index 0000000..17fadd0 --- /dev/null +++ b/kicker-applets/mediacontrol/pics/fulldecent/README @@ -0,0 +1,12 @@ +# +# "Sketchy" mediacontrol theme +# (c) 2003 Will Entriken "Full Decent" +# + +This theme is was drawn freehand with GIMP, the original layered gimp file +is included as an XCF file for your modifying pleasure. + +The artwork is released under the terms of the GNU GPL version 2. +The license is available at http://www.gnu.org + +Hope you enjoy!
\ No newline at end of file diff --git a/kicker-applets/mediacontrol/pics/fulldecent/next.png b/kicker-applets/mediacontrol/pics/fulldecent/next.png Binary files differnew file mode 100644 index 0000000..e833248 --- /dev/null +++ b/kicker-applets/mediacontrol/pics/fulldecent/next.png diff --git a/kicker-applets/mediacontrol/pics/fulldecent/pause.png b/kicker-applets/mediacontrol/pics/fulldecent/pause.png Binary files differnew file mode 100644 index 0000000..2fb8572 --- /dev/null +++ b/kicker-applets/mediacontrol/pics/fulldecent/pause.png diff --git a/kicker-applets/mediacontrol/pics/fulldecent/play.png b/kicker-applets/mediacontrol/pics/fulldecent/play.png Binary files differnew file mode 100644 index 0000000..836c46e --- /dev/null +++ b/kicker-applets/mediacontrol/pics/fulldecent/play.png diff --git a/kicker-applets/mediacontrol/pics/fulldecent/prev.png b/kicker-applets/mediacontrol/pics/fulldecent/prev.png Binary files differnew file mode 100644 index 0000000..7e24e76 --- /dev/null +++ b/kicker-applets/mediacontrol/pics/fulldecent/prev.png diff --git a/kicker-applets/mediacontrol/pics/fulldecent/source.xcf b/kicker-applets/mediacontrol/pics/fulldecent/source.xcf Binary files differnew file mode 100644 index 0000000..712236a --- /dev/null +++ b/kicker-applets/mediacontrol/pics/fulldecent/source.xcf diff --git a/kicker-applets/mediacontrol/pics/fulldecent/stop.png b/kicker-applets/mediacontrol/pics/fulldecent/stop.png Binary files differnew file mode 100644 index 0000000..dc26b5f --- /dev/null +++ b/kicker-applets/mediacontrol/pics/fulldecent/stop.png diff --git a/kicker-applets/mediacontrol/playerInterface.cpp b/kicker-applets/mediacontrol/playerInterface.cpp new file mode 100644 index 0000000..cc388c0 --- /dev/null +++ b/kicker-applets/mediacontrol/playerInterface.cpp @@ -0,0 +1,34 @@ +/*************************************************************************** + this is the abstract class to access a player from + ------------------- + begin : Mon Jan 15 21:09:00 CEST 2001 + copyright : (C) 2001-2002 by Stefan Gehn + email : metz {AT} gehn {DOT} net + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include "playerInterface.h" +#include "playerInterface.moc" +#include <kapplication.h> +#include <kmessagebox.h> +#include <klocale.h> + +PlayerInterface::PlayerInterface() { } // Constructor +PlayerInterface::~PlayerInterface() { } // Destructor + +void PlayerInterface::startPlayer(const QString &desktopname) +{ + if (KApplication::startServiceByDesktopName(desktopname, QStringList(), + 0, 0, 0, "", false) > 0) + { + KMessageBox::error(0, i18n("Could not start media player.")); + } +} diff --git a/kicker-applets/mediacontrol/playerInterface.h b/kicker-applets/mediacontrol/playerInterface.h new file mode 100644 index 0000000..aa4701e --- /dev/null +++ b/kicker-applets/mediacontrol/playerInterface.h @@ -0,0 +1,57 @@ +/*************************************************************************** + this is the abstract class to access a player from + ------------------- + begin : Mon Jan 15 21:09:00 MEZ 2001 + copyright : (C) 2001 by Stefan Gehn + email : metz {AT} gehn {DOT} net + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef PLAYERINTERFACE_H +#define PLAYERINTERFACE_H + +#include <qobject.h> +#include <qdragobject.h> + +class PlayerInterface : public QObject +{ + Q_OBJECT + public: + PlayerInterface(); + virtual ~PlayerInterface(); + + enum PlayingStatus { Stopped=0, Playing, Paused }; + + public slots: + virtual void updateSlider()=0; // gets called on timer-timeout + virtual void sliderStartDrag()=0; + virtual void sliderStopDrag()=0; + virtual void jumpToTime( int msec )=0; + virtual void playpause()=0; + virtual void stop()=0; + virtual void next()=0; + virtual void prev()=0; + virtual void volumeUp()=0; + virtual void volumeDown()=0; + virtual void dragEnterEvent(QDragEnterEvent* event)=0; + virtual void dropEvent(QDropEvent* event)=0; + virtual const QString getTrackTitle() const=0; + virtual int playingStatus()=0; + + void startPlayer(const QString &desktopname); + + signals: + void newSliderPosition(int, int); + void playingStatusChanged(int); + void playerStarted(); + void playerStopped(); +}; +#endif diff --git a/kicker-applets/mediacontrol/simplebutton.cpp b/kicker-applets/mediacontrol/simplebutton.cpp new file mode 100644 index 0000000..9daa926 --- /dev/null +++ b/kicker-applets/mediacontrol/simplebutton.cpp @@ -0,0 +1,256 @@ +/* This file is part of the KDE project + Copyright (C) 2003-2004 Nadeem Hasan <nhasan@kde.org> + Copyright (C) 2004-2005 Aaron J. Seigo <aseigo@kde.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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "simplebutton.h" + +#include <qpainter.h> +#include <qstyle.h> + +#include <kapplication.h> +#include <kcursor.h> +#include <kdialog.h> +#include <kglobalsettings.h> +#include <kiconeffect.h> +#include <kicontheme.h> +#include <kipc.h> +#include <kstandarddirs.h> + +SimpleButton::SimpleButton(QWidget *parent, const char *name) + : QButton(parent, name), + m_highlight(false), + m_orientation(Qt::Horizontal) +{ + setBackgroundOrigin( AncestorOrigin ); + + connect( kapp, SIGNAL( settingsChanged( int ) ), + SLOT( slotSettingsChanged( int ) ) ); + connect( kapp, SIGNAL( iconChanged( int ) ), + SLOT( slotIconChanged( int ) ) ); + + kapp->addKipcEventMask( KIPC::SettingsChanged ); + kapp->addKipcEventMask( KIPC::IconChanged ); + + slotSettingsChanged( KApplication::SETTINGS_MOUSE ); +} + +void SimpleButton::setPixmap(const QPixmap &pix) +{ + QButton::setPixmap(pix); + generateIcons(); + update(); +} + +void SimpleButton::setOrientation(Qt::Orientation orientation) +{ + m_orientation = orientation; + update(); +} + +QSize SimpleButton::sizeHint() const +{ + const QPixmap* pm = pixmap(); + + if (!pm) + return QButton::sizeHint(); + else + return QSize(pm->width() + KDialog::spacingHint(), pm->height() + KDialog::spacingHint()); +} + +QSize SimpleButton::minimumSizeHint() const +{ + const QPixmap* pm = pixmap(); + + if (!pm) + return QButton::minimumSizeHint(); + else + return QSize(pm->width(), pm->height()); +} + +void SimpleButton::drawButton( QPainter *p ) +{ + drawButtonLabel(p); +} + +void SimpleButton::drawButtonLabel( QPainter *p ) +{ + if (!pixmap()) + { + return; + } + + QPixmap pix = isEnabled() ? (m_highlight? m_activeIcon : m_normalIcon) : m_disabledIcon; + + if (isOn() || isDown()) + { + pix = pix.convertToImage().smoothScale(pix.width() - 2, + pix.height() - 2); + } + + int h = height(); + int w = width(); + int ph = pix.height(); + int pw = pix.width(); + int margin = KDialog::spacingHint(); + QPoint origin(margin / 2, margin / 2); + + if (ph < (h - margin)) + { + origin.setY((h - ph) / 2); + } + + if (pw < (w - margin)) + { + origin.setX((w - pw) / 2); + } + + p->drawPixmap(origin, pix); +} + +void SimpleButton::generateIcons() +{ + if (!pixmap()) + { + return; + } + + QImage image = pixmap()->convertToImage(); + KIconEffect effect; + + m_normalIcon = effect.apply(image, KIcon::Panel, KIcon::DefaultState); + m_activeIcon = effect.apply(image, KIcon::Panel, KIcon::ActiveState); + m_disabledIcon = effect.apply(image, KIcon::Panel, KIcon::DisabledState); + + updateGeometry(); +} + +void SimpleButton::slotSettingsChanged(int category) +{ + if (category != KApplication::SETTINGS_MOUSE) + { + return; + } + + bool changeCursor = KGlobalSettings::changeCursorOverIcon(); + + if (changeCursor) + { + setCursor(KCursor::handCursor()); + } + else + { + unsetCursor(); + } +} + +void SimpleButton::slotIconChanged( int group ) +{ + if (group != KIcon::Panel) + { + return; + } + + generateIcons(); + update(); +} + +void SimpleButton::enterEvent( QEvent *e ) +{ + m_highlight = true; + + repaint( false ); + QButton::enterEvent( e ); +} + +void SimpleButton::leaveEvent( QEvent *e ) +{ + m_highlight = false; + + repaint( false ); + QButton::enterEvent( e ); +} + +void SimpleButton::resizeEvent( QResizeEvent * ) +{ + generateIcons(); +} + + +SimpleArrowButton::SimpleArrowButton(QWidget *parent, Qt::ArrowType arrow, const char *name) + : SimpleButton(parent, name) +{ + setBackgroundOrigin(AncestorOrigin); + _arrow = arrow; + _inside = false; +} + +QSize SimpleArrowButton::sizeHint() const +{ + return QSize( 12, 12 ); +} + +void SimpleArrowButton::setArrowType(Qt::ArrowType a) +{ + if (_arrow != a) + { + _arrow = a; + update(); + } +} + +Qt::ArrowType SimpleArrowButton::arrowType() const +{ + return _arrow; +} + +void SimpleArrowButton::drawButton( QPainter *p ) +{ + QRect r(1, 1, width() - 2, height() - 2); + + QStyle::PrimitiveElement pe = QStyle::PE_ArrowLeft; + switch (_arrow) + { + case Qt::LeftArrow: pe = QStyle::PE_ArrowLeft; break; + case Qt::RightArrow: pe = QStyle::PE_ArrowRight; break; + case Qt::UpArrow: pe = QStyle::PE_ArrowUp; break; + case Qt::DownArrow: pe = QStyle::PE_ArrowDown; break; + } + + int flags = QStyle::Style_Default | QStyle::Style_Enabled; + if (isDown() || isOn()) flags |= QStyle::Style_Down; + style().drawPrimitive(pe, p, r, colorGroup(), flags); +} + +void SimpleArrowButton::enterEvent( QEvent *e ) +{ + _inside = true; + SimpleButton::enterEvent( e ); + update(); +} + +void SimpleArrowButton::leaveEvent( QEvent *e ) +{ + _inside = false; + SimpleButton::enterEvent( e ); + update(); +} + +#include "simplebutton.moc" + +// vim:ts=4:sw=4:et diff --git a/kicker-applets/mediacontrol/simplebutton.h b/kicker-applets/mediacontrol/simplebutton.h new file mode 100644 index 0000000..5423dff --- /dev/null +++ b/kicker-applets/mediacontrol/simplebutton.h @@ -0,0 +1,89 @@ +/* This file is part of the KDE project + Copyright (C) 2003-2004 Nadeem Hasan <nhasan@kde.org> + Copyright (C) 2004-2005 Aaron J. Seigo <aseigo@kde.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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef SIMPLEBUTTON_H +#define SIMPLEBUTTON_H + +#include <qbutton.h> +#include <qpixmap.h> + +#include <kdemacros.h> + +class KDE_EXPORT SimpleButton : public QButton +{ + Q_OBJECT + + public: + SimpleButton(QWidget *parent, const char *name = 0); + void setPixmap(const QPixmap &pix); + void setOrientation(Qt::Orientation orientaton); + QSize sizeHint() const; + QSize minimumSizeHint() const; + + protected: + void drawButton( QPainter *p ); + void drawButtonLabel( QPainter *p ); + void generateIcons(); + + void enterEvent( QEvent *e ); + void leaveEvent( QEvent *e ); + void resizeEvent( QResizeEvent *e ); + + protected slots: + virtual void slotSettingsChanged( int category ); + virtual void slotIconChanged( int group ); + + private: + bool m_highlight; + QPixmap m_normalIcon; + QPixmap m_activeIcon; + QPixmap m_disabledIcon; + Qt::Orientation m_orientation; + class SimpleButtonPrivate; + SimpleButtonPrivate* d; +}; + +class KDE_EXPORT SimpleArrowButton: public SimpleButton +{ + Q_OBJECT + + public: + SimpleArrowButton(QWidget *parent = 0, Qt::ArrowType arrow = Qt::UpArrow, const char *name = 0); + virtual ~SimpleArrowButton() {}; + QSize sizeHint() const; + + protected: + virtual void enterEvent( QEvent *e ); + virtual void leaveEvent( QEvent *e ); + virtual void drawButton(QPainter *p); + Qt::ArrowType arrowType() const; + + public slots: + void setArrowType(Qt::ArrowType a); + + private: + Qt::ArrowType _arrow; + bool _inside; +}; + + +#endif // HIDEBUTTON_H + +// vim:ts=4:sw=4:et diff --git a/kicker-applets/mediacontrol/xmmsInterface.cpp b/kicker-applets/mediacontrol/xmmsInterface.cpp new file mode 100644 index 0000000..e2512e5 --- /dev/null +++ b/kicker-applets/mediacontrol/xmmsInterface.cpp @@ -0,0 +1,183 @@ +/*************************************************************************** + Interface to access XMMS + ------------------- + begin : Tue Apr 25 11:53:11 CEST 2000 + copyright : (C) 2000-2002 by Stefan Gehn + email : metz {AT} gehn {DOT} net + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_XMMS // only use if there is xmms installed on compiletime + +#include "xmmsInterface.h" +#include "xmmsInterface.moc" +#include <xmms/xmmsctrl.h> +#include <kdebug.h> + +#define TIMER_SLOW 1000 +#define TIMER_FAST 100 +#define XMMS_SESSION 0 + +XmmsInterface::XmmsInterface() : PlayerInterface() +{ + timervalue = TIMER_FAST; + bStartingXMMS = false; + xmms_timer = new QTimer ( this, "xmms_timer" ); + + QObject::connect( xmms_timer, SIGNAL(timeout()), SLOT(updateSlider()) ); + + // Better start the timer as late as possible in initialization + xmms_timer->start ( timervalue ); +} + +XmmsInterface::~XmmsInterface() +{ + delete xmms_timer; +} + +void XmmsInterface::updateSlider ( void ) +{ + if ( !xmms_remote_is_running(XMMS_SESSION) ) + { // XMMS not running + if (timervalue == TIMER_FAST) // timer is running fast + { + emit playerStopped(); + timervalue = TIMER_SLOW; // timer does not need to run fast if XMMS is not running + xmms_timer->changeInterval(timervalue); + emit newSliderPosition(0,0); + } + return; // as XMMS is not running we can leave now + } + + // huh, XMMS is running :) + if (timervalue == TIMER_SLOW) // what? Still running slow? + { + emit playerStarted(); + timervalue = TIMER_FAST; // boost the timer to have better reaction-times for the applet + xmms_timer->changeInterval(timervalue); + } + + int len = xmms_remote_get_playlist_time ( XMMS_SESSION, xmms_remote_get_playlist_pos(XMMS_SESSION) ); + int time = xmms_remote_get_output_time(XMMS_SESSION); + + if (len < 0) + { + len = 0; + time = 0; + } + + emit newSliderPosition(len,time); + emit playingStatusChanged(playingStatus()); +} + + +// Drag-n-Drop stuff ================================================================= + +void XmmsInterface::dragEnterEvent(QDragEnterEvent* event) +{ + event->accept( QTextDrag::canDecode(event) ); +} + +void XmmsInterface::dropEvent(QDropEvent* event) +{ + QString text; +// kdDebug(90200) << "XmmsInterface::dropEvent()" << endl; + if ( QTextDrag::decode(event, text) ) + { + xmms_remote_playlist_add_url_string(XMMS_SESSION, + (gchar *)text.local8Bit().data()); + } +} + +// ==================================================================================== + + +void XmmsInterface::sliderStartDrag() +{ + xmms_timer->stop(); +} + +void XmmsInterface::sliderStopDrag() +{ + xmms_timer->start( timervalue ); +} + +void XmmsInterface::jumpToTime( int msec ) +{ + xmms_remote_jump_to_time(XMMS_SESSION, msec); +} + +void XmmsInterface::playpause() +{ + if (!xmms_remote_is_running(XMMS_SESSION)) + { + if (bStartingXMMS) + return; + startPlayer("xmms"); + bStartingXMMS = true; + QTimer::singleShot(500, this, SLOT(playpause())); + } + else + { + bStartingXMMS = false; + xmms_remote_play_pause(XMMS_SESSION); + } +} + +void XmmsInterface::stop() +{ + xmms_remote_stop(XMMS_SESSION); +} + +void XmmsInterface::next() +{ + xmms_remote_playlist_next(XMMS_SESSION); +} + +void XmmsInterface::prev() +{ + xmms_remote_playlist_prev(XMMS_SESSION); +} + +void XmmsInterface::volumeUp() +{ + const int cur = xmms_remote_get_main_volume(XMMS_SESSION); + xmms_remote_set_main_volume(XMMS_SESSION, cur+1); +} + +void XmmsInterface::volumeDown() +{ + const int cur = xmms_remote_get_main_volume(XMMS_SESSION); + xmms_remote_set_main_volume(XMMS_SESSION, cur-1); +} + +int XmmsInterface::playingStatus() +{ + if (xmms_remote_is_paused(XMMS_SESSION)) + return Paused; + + if (xmms_remote_is_playing(XMMS_SESSION)) + return Playing; + + return Stopped; +} + +const QString XmmsInterface::getTrackTitle() const +{ + return QString::fromLocal8Bit( + xmms_remote_get_playlist_title(XMMS_SESSION, + xmms_remote_get_playlist_pos(XMMS_SESSION))); +} +#endif // HAVE_XMMS diff --git a/kicker-applets/mediacontrol/xmmsInterface.h b/kicker-applets/mediacontrol/xmmsInterface.h new file mode 100644 index 0000000..ca514b2 --- /dev/null +++ b/kicker-applets/mediacontrol/xmmsInterface.h @@ -0,0 +1,59 @@ +/*************************************************************************** + Interface to access XMMS + ------------------- + begin : Tue Apr 25 11:53:11 CEST 2000 + copyright : (C) 2000-2002 by Stefan Gehn + email : metz {AT} gehn {DOT} net + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_XMMS // only use if there's xmms installed on compiletime + +#ifndef XMMSINTERFACE_H +#define XMMSINTERFACE_H + +#include "playerInterface.h" +#include <qtimer.h> + +class XmmsInterface : public PlayerInterface +{ + Q_OBJECT + public: + XmmsInterface(); + ~XmmsInterface(); + + public slots: + virtual void updateSlider(); + virtual void sliderStartDrag(); + virtual void sliderStopDrag(); + virtual void jumpToTime(int msec); + virtual void playpause(); + virtual void stop(); + virtual void next(); + virtual void prev(); + virtual void volumeUp(); + virtual void volumeDown(); + virtual void dragEnterEvent(QDragEnterEvent* event); + virtual void dropEvent(QDropEvent* event); + virtual const QString getTrackTitle() const; + virtual int playingStatus(); + + private: + QTimer *xmms_timer; + int timervalue; + bool bStartingXMMS; +}; +#endif // XMMSINTERFACE_H +#endif // HAVE_XMMS |