summaryrefslogtreecommitdiffstats
path: root/arts/knotify/knotify.cpp
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commitce4a32fe52ef09d8f5ff1dd22c001110902b60a2 (patch)
tree5ac38a06f3dde268dc7927dc155896926aaf7012 /arts/knotify/knotify.cpp
downloadtdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.tar.gz
tdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdelibs@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'arts/knotify/knotify.cpp')
-rw-r--r--arts/knotify/knotify.cpp800
1 files changed, 800 insertions, 0 deletions
diff --git a/arts/knotify/knotify.cpp b/arts/knotify/knotify.cpp
new file mode 100644
index 000000000..794ef3dcd
--- /dev/null
+++ b/arts/knotify/knotify.cpp
@@ -0,0 +1,800 @@
+/*
+ Copyright (c) 1997 Christian Esken (esken@kde.org)
+ 2000 Charles Samuels (charles@kde.org)
+ 2000 Stefan Schimanski (1Stein@gmx.de)
+ 2000 Matthias Ettrich (ettrich@kde.org)
+ 2000 Waldo Bastian <bastian@kde.org>
+ 2000-2003 Carsten Pfeiffer <pfeiffer@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, 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+// C headers
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <config.h>
+#ifndef WITHOUT_ARTS
+// aRts headers
+#include <connect.h>
+#include <dispatcher.h>
+#include <flowsystem.h>
+#include <qiomanager.h>
+#include <soundserver.h>
+#endif
+
+// QT headers
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qstringlist.h>
+#include <qtextstream.h>
+
+// KDE headers
+#include <dcopclient.h>
+#include <kaboutdata.h>
+#ifndef WITHOUT_ARTS
+#include <kartsdispatcher.h>
+#include <kartsserver.h>
+#endif
+#include <kcmdlineargs.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kpassivepopup.h>
+#include <kiconloader.h>
+#include <kmacroexpander.h>
+#ifndef WITHOUT_ARTS
+#include <kplayobjectfactory.h>
+#include <kaudiomanagerplay.h>
+#endif
+#include <kprocess.h>
+#include <kstandarddirs.h>
+#include <kuniqueapplication.h>
+#include <kwin.h>
+
+#include "knotify.h"
+#include "knotify.moc"
+
+class KNotifyPrivate
+{
+public:
+ KConfig* globalEvents;
+ KConfig* globalConfig;
+ QMap<QString, KConfig*> events;
+ QMap<QString, KConfig*> configs;
+ QString externalPlayer;
+ KProcess *externalPlayerProc;
+
+#ifndef WITHOUT_ARTS
+ QPtrList<KDE::PlayObject> playObjects;
+ QMap<KDE::PlayObject*,int> playObjectEventMap;
+ KAudioManagerPlay *audioManager;
+#endif
+ int externalPlayerEventId;
+
+ bool useExternal;
+ bool useArts;
+ int volume;
+ QTimer *playTimer;
+ bool inStartup;
+ QString startupEvents;
+};
+
+// Yes, it's ugly to put this here, but this facilitates the cautious startup
+// procedure.
+#ifndef WITHOUT_ARTS
+KArtsServer *soundServer = 0;
+#endif
+
+extern "C"{
+
+KDE_EXPORT int kdemain(int argc, char **argv)
+{
+ KAboutData aboutdata("knotify", I18N_NOOP("KNotify"),
+ "3.0", I18N_NOOP("KDE Notification Server"),
+ KAboutData::License_GPL, "(C) 1997-2003, KDE Developers");
+ aboutdata.addAuthor("Carsten Pfeiffer",I18N_NOOP("Current Maintainer"),"pfeiffer@kde.org");
+ aboutdata.addAuthor("Christian Esken",0,"esken@kde.org");
+ aboutdata.addAuthor("Stefan Westerfeld",I18N_NOOP("Sound support"),"stefan@space.twc.de");
+ aboutdata.addAuthor("Charles Samuels",I18N_NOOP("Previous Maintainer"),"charles@kde.org");
+
+ KCmdLineArgs::init( argc, argv, &aboutdata );
+ KUniqueApplication::addCmdLineOptions();
+
+
+ // initialize application
+ if ( !KUniqueApplication::start() ) {
+ kdDebug() << "Running knotify found" << endl;
+ return 0;
+ }
+
+ KUniqueApplication app;
+ app.disableSessionManagement();
+
+ // KNotify is started on KDE startup and on demand (using
+ // KNotifClient::startDaemon()) whenever a KNotify event occurs. Especially
+ // KWin may fire many events (e.g. when a window pops up). When we have
+ // problems with aRts or the installation, we might get an infinite loop
+ // of knotify crashing, popping up the crashhandler window and kwin firing
+ // another event, starting knotify again...
+ // We try to prevent this by tracking our startup and offer options to
+ // abort this.
+
+#ifndef WITHOUT_ARTS
+ KConfigGroup config( KGlobal::config(), "StartProgress" );
+ KConfig artsKCMConfig( "kcmartsrc" );
+ artsKCMConfig.setGroup( "Arts" );
+ bool useArts = artsKCMConfig.readBoolEntry( "StartServer", true );
+ if (useArts)
+ useArts = config.readBoolEntry( "Use Arts", useArts );
+ bool ok = config.readBoolEntry( "Arts Init", true );
+
+ if ( useArts && !ok )
+ {
+ if ( KMessageBox::questionYesNo(
+ 0L,
+ i18n("During the previous startup, KNotify crashed while creating "
+ "Arts::Dispatcher. Do you want to try again or disable "
+ "aRts sound output?\n\n"
+ "If you choose to disable aRts output now, you can re-enable "
+ "it later or select an alternate sound player "
+ "in the System Notifications control panel."),
+ i18n("KNotify Problem"),
+ i18n("&Try Again"),
+ i18n("D&isable aRts Output"),
+ "KNotifyStartProgress",
+ 0 /* don't call KNotify :) */
+ )
+ == KMessageBox::No )
+ {
+ useArts = false;
+ }
+ }
+
+ // when ArtsDispatcher crashes, we know it the next start.
+ config.writeEntry( "Arts Init", false );
+ config.writeEntry( "Use Arts", useArts );
+ config.sync();
+
+ KArtsDispatcher *dispatcher = 0;
+ if ( useArts )
+ {
+ dispatcher = new KArtsDispatcher;
+ soundServer = new KArtsServer;
+ }
+
+ // ok, seemed to work.
+ config.writeEntry("Arts Init", useArts );
+ config.sync();
+
+ ok = config.readBoolEntry( "KNotify Init", true );
+ if ( useArts && !ok )
+ {
+ if ( KMessageBox::questionYesNo(
+ 0L,
+ i18n("During the previous startup, KNotify crashed while instantiating "
+ "KNotify. Do you want to try again or disable "
+ "aRts sound output?\n\n"
+ "If you choose to disable aRts output now, you can re-enable "
+ "it later or select an alternate sound player "
+ "in the System Notifications control panel."),
+ i18n("KNotify Problem"),
+ i18n("&Try Again"),
+ i18n("D&isable aRts Output"),
+ "KNotifyStartProgress",
+ 0 /* don't call KNotify :) */
+ )
+ == KMessageBox::No )
+ {
+ useArts = false;
+ delete soundServer;
+ soundServer = 0L;
+ delete dispatcher;
+ dispatcher = 0L;
+ }
+ }
+
+ // when KNotify instantiation crashes, we know it the next start.
+ config.writeEntry( "KNotify Init", false );
+ config.writeEntry( "Use Arts", useArts );
+ config.sync();
+
+ // start notify service
+ KNotify *notify = new KNotify( useArts );
+
+ config.writeEntry( "KNotify Init", true );
+ config.sync();
+
+#else
+
+ // start notify service, without aRts
+ KNotify *notify = new KNotify( false );
+
+#endif
+
+ app.dcopClient()->setDefaultObject( "Notify" );
+ app.dcopClient()->setDaemonMode( true );
+ // kdDebug() << "knotify starting" << endl;
+
+ int ret = app.exec();
+ delete notify;
+#ifndef WITHOUT_ARTS
+ delete soundServer;
+ delete dispatcher;
+#endif
+ return ret;
+}
+}// end extern "C"
+
+KNotify::KNotify( bool useArts )
+ : QObject(), DCOPObject("Notify")
+{
+ d = new KNotifyPrivate;
+ d->globalEvents = new KConfig("knotify/eventsrc", true, false, "data");
+ d->globalConfig = new KConfig("knotify.eventsrc", true, false);
+ d->externalPlayerProc = 0;
+ d->useArts = useArts;
+ d->inStartup = true;
+#ifndef WITHOUT_ARTS
+ d->playObjects.setAutoDelete(true);
+ d->audioManager = 0;
+ if( useArts )
+ {
+ connect( soundServer, SIGNAL( restartedServer() ), this, SLOT( restartedArtsd() ) );
+ restartedArtsd(); //started allready need to initialize d->audioManager
+ }
+#endif
+
+ d->volume = 100;
+
+ d->playTimer = 0;
+
+ loadConfig();
+}
+
+KNotify::~KNotify()
+{
+ reconfigure();
+
+#ifndef WITHOUT_ARTS
+ d->playObjects.clear();
+
+ delete d->globalEvents;
+ delete d->globalConfig;
+ delete d->externalPlayerProc;
+ delete d->audioManager;
+#endif
+ delete d;
+}
+
+
+void KNotify::loadConfig() {
+ // load external player settings
+ KConfig *kc = KGlobal::config();
+ kc->setGroup("Misc");
+ d->useExternal = kc->readBoolEntry( "Use external player", false );
+ d->externalPlayer = kc->readPathEntry("External player");
+
+ // try to locate a suitable player if none is configured
+ if ( d->externalPlayer.isEmpty() ) {
+ QStringList players;
+ players << "wavplay" << "aplay" << "auplay";
+ QStringList::Iterator it = players.begin();
+ while ( d->externalPlayer.isEmpty() && it != players.end() ) {
+ d->externalPlayer = KStandardDirs::findExe( *it );
+ ++it;
+ }
+ }
+
+ // load default volume
+ d->volume = kc->readNumEntry( "Volume", 100 );
+}
+
+
+void KNotify::reconfigure()
+{
+ kapp->config()->reparseConfiguration();
+ loadConfig();
+
+ // clear loaded config files
+ d->globalConfig->reparseConfiguration();
+ for ( QMapIterator<QString,KConfig*> it = d->configs.begin(); it != d->configs.end(); ++it )
+ delete it.data();
+ d->configs.clear();
+}
+
+
+void KNotify::notify(const QString &event, const QString &fromApp,
+ const QString &text, QString sound, QString file,
+ int present, int level)
+{
+ notify( event, fromApp, text, sound, file, present, level, 0, 1 );
+}
+
+void KNotify::notify(const QString &event, const QString &fromApp,
+ const QString &text, QString sound, QString file,
+ int present, int level, int winId)
+{
+ notify( event, fromApp, text, sound, file, present, level, winId, 1 );
+}
+
+void KNotify::notify(const QString &event, const QString &fromApp,
+ const QString &text, QString sound, QString file,
+ int present, int level, int winId, int eventId )
+{
+ // kdDebug() << "event=" << event << " fromApp=" << fromApp << " text=" << text << " sound=" << sound <<
+ // " file=" << file << " present=" << present << " level=" << level << " winId=" << winId << " eventId=" << eventId << endl;
+ if( d->inStartup ) {
+ d->startupEvents += "(" + event + ":" + fromApp + ")";
+ }
+
+ QString commandline;
+ KConfig *eventsFile = NULL;
+ KConfig *configFile = NULL;
+
+ // check for valid events
+ if ( !event.isEmpty() ) {
+
+ // get config file
+ if ( d->events.contains( fromApp ) ) {
+ eventsFile = d->events[fromApp];
+ } else {
+ eventsFile=new KConfig(locate("data", fromApp+"/eventsrc"),true,false);
+ d->events.insert( fromApp, eventsFile );
+ }
+ if ( d->configs.contains( fromApp) ) {
+ configFile = d->configs[fromApp];
+ } else {
+ configFile=new KConfig(fromApp+".eventsrc",true,false);
+ d->configs.insert( fromApp, configFile );
+ }
+
+ if ( !eventsFile->hasGroup( event ) && isGlobal(event) )
+ {
+ eventsFile = d->globalEvents;
+ configFile = d->globalConfig;
+ }
+
+ eventsFile->setGroup( event );
+ configFile->setGroup( event );
+
+ // get event presentation
+ if ( present==-1 )
+ present = configFile->readNumEntry( "presentation", -1 );
+ if ( present==-1 )
+ present = eventsFile->readNumEntry( "default_presentation", 0 );
+
+ // get sound file name
+ if( present & KNotifyClient::Sound ) {
+ QString theSound = configFile->readPathEntry( "soundfile" );
+ if ( theSound.isEmpty() )
+ theSound = eventsFile->readPathEntry( "default_sound" );
+ if ( !theSound.isEmpty() )
+ sound = theSound;
+ }
+
+ // get log file name
+ if( present & KNotifyClient::Logfile ) {
+ QString theFile = configFile->readPathEntry( "logfile" );
+ if ( theFile.isEmpty() )
+ theFile = eventsFile->readPathEntry( "default_logfile" );
+ if ( !theFile.isEmpty() )
+ file = theFile;
+ }
+
+ // get default event level
+ if( present & KNotifyClient::Messagebox )
+ level = eventsFile->readNumEntry( "level", 0 );
+
+ // get command line
+ if (present & KNotifyClient::Execute ) {
+ commandline = configFile->readPathEntry( "commandline" );
+ if ( commandline.isEmpty() )
+ commandline = eventsFile->readPathEntry( "default_commandline" );
+ }
+ }
+
+ // emit event
+ if ( present & KNotifyClient::Sound ) // && QFile(sound).isReadable()
+ notifyBySound( sound, fromApp, eventId );
+
+ if ( present & KNotifyClient::Execute )
+ notifyByExecute( commandline, event, fromApp, text, winId, eventId );
+
+ if ( present & KNotifyClient::Logfile ) // && QFile(file).isWritable()
+ notifyByLogfile( text, file );
+
+ if ( present & KNotifyClient::Stderr )
+ notifyByStderr( text );
+
+ if ( present & KNotifyClient::Taskbar )
+ notifyByTaskbar( checkWinId( fromApp, winId ));
+
+ if ( present & KNotifyClient::PassivePopup )
+ notifyByPassivePopup( text, fromApp, eventsFile, checkWinId( fromApp, winId ));
+ else if ( present & KNotifyClient::Messagebox )
+ notifyByMessagebox( text, level, checkWinId( fromApp, winId ));
+
+ QByteArray qbd;
+ QDataStream ds(qbd, IO_WriteOnly);
+ ds << event << fromApp << text << sound << file << present << level
+ << winId << eventId;
+ emitDCOPSignal("notifySignal(QString,QString,QString,QString,QString,int,int,int,int)", qbd);
+
+}
+
+
+bool KNotify::notifyBySound( const QString &sound, const QString &appname, int eventId )
+{
+ if (sound.isEmpty()) {
+ soundFinished( eventId, NoSoundFile );
+ return false;
+ }
+
+ bool external = d->useExternal && !d->externalPlayer.isEmpty();
+ // get file name
+ QString soundFile(sound);
+ if ( QFileInfo(sound).isRelative() )
+ {
+ QString search = QString("%1/sounds/%2").arg(appname).arg(sound);
+ soundFile = KGlobal::instance()->dirs()->findResource("data", search);
+ if ( soundFile.isEmpty() )
+ soundFile = locate( "sound", sound );
+ }
+ if ( soundFile.isEmpty() || isPlaying( soundFile ) )
+ {
+ soundFinished( eventId, soundFile.isEmpty() ? NoSoundFile : FileAlreadyPlaying );
+ return false;
+ }
+
+
+ // kdDebug() << "KNotify::notifyBySound - trying to play file " << soundFile << endl;
+
+ if (!external) {
+ //If we disabled using aRts, just return,
+ //(If we don't, we'll blow up accessing the null soundServer)
+ if (!d->useArts)
+ {
+ soundFinished( eventId, NoSoundSupport );
+ return false;
+ }
+
+#ifndef WITHOUT_ARTS
+ // play sound finally
+ while( d->playObjects.count()>5 )
+ abortFirstPlayObject();
+
+ KDE::PlayObjectFactory factory(soundServer->server());
+ if( d->audioManager )
+ factory.setAudioManagerPlay( d->audioManager );
+ KURL soundURL;
+ soundURL.setPath(soundFile);
+ KDE::PlayObject *playObject = factory.createPlayObject(soundURL, false);
+
+ if (playObject->isNull())
+ {
+ soundFinished( eventId, NoSoundSupport );
+ delete playObject;
+ return false;
+ }
+
+ if ( d->volume != 100 )
+ {
+ // It works to access the playObject immediately because we don't allow
+ // non-file URLs for sounds.
+ Arts::StereoVolumeControl volumeControl = Arts::DynamicCast(soundServer->server().createObject("Arts::StereoVolumeControl"));
+ Arts::PlayObject player = playObject->object();
+ Arts::Synth_AMAN_PLAY ap = d->audioManager->amanPlay();
+ if( ! volumeControl.isNull() && ! player.isNull() && ! ap.isNull() )
+ {
+ volumeControl.scaleFactor( d->volume/100.0 );
+
+ ap.stop();
+ Arts::disconnect( player, "left", ap, "left" );
+ Arts::disconnect( player, "right", ap, "right" );
+
+ ap.start();
+ volumeControl.start();
+
+ Arts::connect(player,"left",volumeControl,"inleft");
+ Arts::connect(player,"right",volumeControl,"inright");
+
+ Arts::connect(volumeControl,"outleft",ap,"left");
+ Arts::connect(volumeControl,"outright",ap,"right");
+
+ player._addChild( volumeControl, "volume" );
+ }
+ }
+
+ playObject->play();
+ d->playObjects.append( playObject );
+ d->playObjectEventMap.insert( playObject, eventId );
+
+ if ( !d->playTimer )
+ {
+ d->playTimer = new QTimer( this );
+ connect( d->playTimer, SIGNAL( timeout() ), SLOT( playTimeout() ) );
+ }
+ if ( !d->playTimer->isActive() )
+ d->playTimer->start( 1000 );
+#endif
+ return true;
+
+ } else if(!d->externalPlayer.isEmpty()) {
+ // use an external player to play the sound
+ KProcess *proc = d->externalPlayerProc;
+ if (!proc)
+ {
+ proc = d->externalPlayerProc = new KProcess;
+ connect( proc, SIGNAL( processExited( KProcess * )),
+ SLOT( slotPlayerProcessExited( KProcess * )));
+ }
+ if (proc->isRunning())
+ {
+ soundFinished( eventId, PlayerBusy );
+ return false; // Skip
+ }
+ proc->clearArguments();
+ (*proc) << d->externalPlayer << QFile::encodeName( soundFile );
+ d->externalPlayerEventId = eventId;
+ proc->start(KProcess::NotifyOnExit);
+ return true;
+ }
+
+ soundFinished( eventId, Unknown );
+ return false;
+}
+
+bool KNotify::notifyByMessagebox(const QString &text, int level, WId winId)
+{
+ // ignore empty messages
+ if ( text.isEmpty() )
+ return false;
+
+ // display message box for specified event level
+ switch( level ) {
+ default:
+ case KNotifyClient::Notification:
+ KMessageBox::informationWId( winId, text, i18n("Notification"), 0, false );
+ break;
+ case KNotifyClient::Warning:
+ KMessageBox::sorryWId( winId, text, i18n("Warning"), false );
+ break;
+ case KNotifyClient::Error:
+ KMessageBox::errorWId( winId, text, i18n("Error"), false );
+ break;
+ case KNotifyClient::Catastrophe:
+ KMessageBox::errorWId( winId, text, i18n("Catastrophe!"), false );
+ break;
+ }
+
+ return true;
+}
+
+bool KNotify::notifyByPassivePopup( const QString &text,
+ const QString &appName,
+ KConfig* eventsFile,
+ WId senderWinId )
+{
+ KIconLoader iconLoader( appName );
+ if ( eventsFile != NULL ) {
+ KConfigGroup config( eventsFile, "!Global!" );
+ QString iconName = config.readEntry( "IconName", appName );
+ QPixmap icon = iconLoader.loadIcon( iconName, KIcon::Small );
+ QString title = config.readEntry( "Comment", appName );
+ KPassivePopup::message(title, text, icon, senderWinId);
+ } else
+ kdError() << "No events for app " << appName << "defined!" <<endl;
+
+ return true;
+}
+
+bool KNotify::notifyByExecute(const QString &command, const QString& event,
+ const QString& fromApp, const QString& text,
+ int winId, int eventId) {
+ if (!command.isEmpty()) {
+ // kdDebug() << "executing command '" << command << "'" << endl;
+ QMap<QChar,QString> subst;
+ subst.insert( 'e', event );
+ subst.insert( 'a', fromApp );
+ subst.insert( 's', text );
+ subst.insert( 'w', QString::number( winId ));
+ subst.insert( 'i', QString::number( eventId ));
+ QString execLine = KMacroExpander::expandMacrosShellQuote( command, subst );
+ if ( execLine.isEmpty() )
+ execLine = command; // fallback
+
+ KProcess p;
+ p.setUseShell(true);
+ p << execLine;
+ p.start(KProcess::DontCare);
+ return true;
+ }
+ return false;
+}
+
+
+bool KNotify::notifyByLogfile(const QString &text, const QString &file)
+{
+ // ignore empty messages
+ if ( text.isEmpty() )
+ return true;
+
+ // open file in append mode
+ QFile logFile(file);
+ if ( !logFile.open(IO_WriteOnly | IO_Append) )
+ return false;
+
+ // append msg
+ QTextStream strm( &logFile );
+ strm << "- KNotify " << QDateTime::currentDateTime().toString() << ": ";
+ strm << text << endl;
+
+ // close file
+ logFile.close();
+ return true;
+}
+
+bool KNotify::notifyByStderr(const QString &text)
+{
+ // ignore empty messages
+ if ( text.isEmpty() )
+ return true;
+
+ // open stderr for output
+ QTextStream strm( stderr, IO_WriteOnly );
+
+ // output msg
+ strm << "KNotify " << QDateTime::currentDateTime().toString() << ": ";
+ strm << text << endl;
+
+ return true;
+}
+
+bool KNotify::notifyByTaskbar( WId win )
+{
+ if( win == 0 )
+ return false;
+ KWin::demandAttention( win );
+ return true;
+}
+
+bool KNotify::isGlobal(const QString &eventname)
+{
+ return d->globalEvents->hasGroup( eventname );
+}
+
+void KNotify::setVolume( int volume )
+{
+ if ( volume<0 ) volume=0;
+ if ( volume>=100 ) volume=100;
+ d->volume = volume;
+}
+
+void KNotify::playTimeout()
+{
+#ifndef WITHOUT_ARTS
+ for ( QPtrListIterator< KDE::PlayObject > it(d->playObjects); *it;)
+ {
+ QPtrListIterator< KDE::PlayObject > current = it;
+ ++it;
+ if ( (*current)->state() != Arts::posPlaying )
+ {
+ QMap<KDE::PlayObject*,int>::Iterator eit = d->playObjectEventMap.find( *current );
+ if ( eit != d->playObjectEventMap.end() )
+ {
+ soundFinished( *eit, PlayedOK );
+ d->playObjectEventMap.remove( eit );
+ }
+ d->playObjects.remove( current );
+ }
+ }
+ if ( !d->playObjects.count() )
+ d->playTimer->stop();
+#endif
+}
+
+bool KNotify::isPlaying( const QString& soundFile ) const
+{
+#ifndef WITHOUT_ARTS
+ for ( QPtrListIterator< KDE::PlayObject > it(d->playObjects); *it; ++it)
+ {
+ if ( (*it)->mediaName() == soundFile )
+ return true;
+ }
+#endif
+ return false;
+}
+
+void KNotify::slotPlayerProcessExited( KProcess *proc )
+{
+ soundFinished( d->externalPlayerEventId,
+ (proc->normalExit() && proc->exitStatus() == 0) ? PlayedOK : Unknown );
+}
+
+void KNotify::abortFirstPlayObject()
+{
+#ifndef WITHOUT_ARTS
+ QMap<KDE::PlayObject*,int>::Iterator it = d->playObjectEventMap.find( d->playObjects.getFirst() );
+ if ( it != d->playObjectEventMap.end() )
+ {
+ soundFinished( it.data(), Aborted );
+ d->playObjectEventMap.remove( it );
+ }
+ d->playObjects.removeFirst();
+#endif
+}
+
+void KNotify::soundFinished( int eventId, PlayingFinishedStatus reason )
+{
+ QByteArray data;
+ QDataStream stream( data, IO_WriteOnly );
+ stream << eventId << (int) reason;
+
+ DCOPClient::mainClient()->emitDCOPSignal( "KNotify", "playingFinished(int,int)", data );
+}
+
+WId KNotify::checkWinId( const QString &appName, WId senderWinId )
+{
+ if ( senderWinId == 0 )
+ {
+ QCString senderId = kapp->dcopClient()->senderId();
+ QCString compare = (appName + "-mainwindow").latin1();
+ int len = compare.length();
+ // kdDebug() << "notifyByPassivePopup: appName=" << appName << " sender=" << senderId << endl;
+
+ QCStringList objs = kapp->dcopClient()->remoteObjects( senderId );
+ for (QCStringList::ConstIterator it = objs.begin(); it != objs.end(); ++it ) {
+ QCString obj( *it );
+ if ( obj.left(len) == compare) {
+ // kdDebug( ) << "found " << obj << endl;
+ QCString replyType;
+ QByteArray data, replyData;
+
+ if ( kapp->dcopClient()->call(senderId, obj, "getWinID()", data, replyType, replyData) ) {
+ QDataStream answer(replyData, IO_ReadOnly);
+ if (replyType == "int") {
+ answer >> senderWinId;
+ // kdDebug() << "SUCCESS, found getWinID(): type='" << QString(replyType)
+ // << "' senderWinId=" << senderWinId << endl;
+ }
+ }
+ }
+ }
+ }
+ return senderWinId;
+}
+
+void KNotify::restartedArtsd()
+{
+#ifndef WITHOUT_ARTS
+ delete d->audioManager;
+ d->audioManager = new KAudioManagerPlay( soundServer );
+ d->audioManager->setTitle( i18n( "KDE System Notifications" ) );
+ d->audioManager->setAutoRestoreID( "KNotify Aman Play" );
+#endif
+}
+
+void KNotify::sessionReady()
+{
+ if( d->inStartup && !d->startupEvents.isEmpty())
+ kdDebug() << "There were knotify events while startup:" << d->startupEvents << endl;
+ d->inStartup = false;
+}
+
+// vim: sw=4 sts=4 ts=8 et