arts Library API Documentation

knotify.cpp

00001 /*
00002    Copyright (c) 1997 Christian Esken (esken@kde.org)
00003                  2000 Charles Samuels (charles@kde.org)
00004                  2000 Stefan Schimanski (1Stein@gmx.de)
00005                  2000 Matthias Ettrich (ettrich@kde.org)
00006                  2000 Waldo Bastian <bastian@kde.org>
00007                  2000-2003 Carsten Pfeiffer <pfeiffer@kde.org>
00008 
00009    This program is free software; you can redistribute it and/or modify
00010    it under the terms of the GNU General Public License as published by
00011    the Free Software Foundation; either version 2, or (at your option)
00012    any later version.
00013 
00014    This program is distributed in the hope that it will be useful,
00015    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017    GNU General Public License for more details.
00018 
00019    You should have received a copy of the GNU General Public License
00020    along with this program; if not, write to the Free Software
00021    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00022 */
00023 
00024 // C headers
00025 #include <fcntl.h>
00026 #include <sys/types.h>
00027 #include <sys/stat.h>
00028 
00029 // aRts headers
00030 #include <connect.h>
00031 #include <dispatcher.h>
00032 #include <flowsystem.h>
00033 #include <soundserver.h>
00034 
00035 // QT headers
00036 #include <qfile.h>
00037 #include <qfileinfo.h>
00038 #include <qiomanager.h>
00039 #include <qstringlist.h>
00040 #include <qtextstream.h>
00041 
00042 // KDE headers
00043 #include <dcopclient.h>
00044 #include <kaboutdata.h>
00045 #include <kartsdispatcher.h>
00046 #include <kartsserver.h>
00047 #include <kcmdlineargs.h>
00048 #include <kconfig.h>
00049 #include <kdebug.h>
00050 #include <kglobal.h>
00051 #include <klocale.h>
00052 #include <kmessagebox.h>
00053 #include <kpassivepopup.h>
00054 #include <kiconloader.h>
00055 #include <kmacroexpander.h>
00056 #include <kplayobjectfactory.h>
00057 #include <kaudiomanagerplay.h>
00058 #include <kprocess.h>
00059 #include <kstandarddirs.h>
00060 #include <kuniqueapplication.h>
00061 #include <kwin.h>
00062 
00063 #include "knotify.h"
00064 #include "knotify.moc"
00065 
00066 class KNotifyPrivate
00067 {
00068 public:
00069     KConfig* globalEvents;
00070     KConfig* globalConfig;
00071     QMap<QString, KConfig*> events;
00072     QMap<QString, KConfig*> configs;
00073     QString externalPlayer;
00074     KProcess *externalPlayerProc;
00075 
00076     QPtrList<KDE::PlayObject> playObjects;
00077     QMap<KDE::PlayObject*,int> playObjectEventMap;
00078     int externalPlayerEventId;
00079 
00080     bool useExternal;
00081     bool useArts;
00082     int volume;
00083     QTimer *playTimer;
00084     KAudioManagerPlay *audioManager;
00085 };
00086 
00087 // Yes, it's ugly to put this here, but this facilitates the cautious startup
00088 // procedure.
00089 KArtsServer *soundServer;
00090 
00091 extern "C"{
00092 
00093 int kdemain(int argc, char **argv)
00094 {
00095     KAboutData aboutdata("knotify", I18N_NOOP("KNotify"),
00096                          "3.0", I18N_NOOP("KDE Notification Server"),
00097                          KAboutData::License_GPL, "(C) 1997-2003, KDE Developers");
00098     aboutdata.addAuthor("Carsten Pfeiffer",I18N_NOOP("Current Maintainer"),"pfeiffer@kde.org");
00099     aboutdata.addAuthor("Christian Esken",0,"esken@kde.org");
00100     aboutdata.addAuthor("Stefan Westerfeld",I18N_NOOP("Sound support"),"stefan@space.twc.de");
00101     aboutdata.addAuthor("Charles Samuels",I18N_NOOP("Previous Maintainer"),"charles@kde.org");
00102 
00103     KCmdLineArgs::init( argc, argv, &aboutdata );
00104     KUniqueApplication::addCmdLineOptions();
00105 
00106 
00107     // initialize application
00108     if ( !KUniqueApplication::start() ) {
00109         kdDebug() << "Running knotify found" << endl;
00110         return 0;
00111     }
00112 
00113     KUniqueApplication app;
00114     app.disableSessionManagement();
00115 
00116     // KNotify is started on KDE startup and on demand (using
00117     // KNotifClient::startDaemon()) whenever a KNotify event occurs. Especially
00118     // KWin may fire many events (e.g. when a window pops up). When we have
00119     // problems with aRts or the installation, we might get an infinite loop
00120     // of knotify crashing, popping up the crashhandler window and kwin firing
00121     // another event, starting knotify again...
00122     // We try to prevent this by tracking our startup and offer options to
00123     // abort this.
00124 
00125     KConfigGroup config( KGlobal::config(), "StartProgress" );
00126     KConfig artsKCMConfig( "kcmartsrc" );
00127     artsKCMConfig.setGroup( "Arts" );
00128     bool useArts = artsKCMConfig.readBoolEntry( "StartServer", true );
00129     if ( useArts )
00130         useArts = config.readBoolEntry( "Use Arts", true );
00131     bool ok = config.readBoolEntry( "Arts Init", true );
00132 
00133     if ( useArts && !ok )
00134     {
00135         if ( KMessageBox::questionYesNo(
00136                  0L,
00137                  i18n("During the previous startup, KNotify crashed while creating "
00138                       "Arts::Dispatcher. Do you want to try again or disable "
00139                       "aRts sound output?"),
00140                  i18n("KNotify Problem"),
00141                  i18n("Try Again"),
00142                  i18n("Disable aRts Output"),
00143                  "KNotifyStartProgress",
00144                  0 /* don't call KNotify :) */
00145                  )
00146              == KMessageBox::No )
00147         {
00148             useArts = false;
00149         }
00150     }
00151 
00152     // when ArtsDispatcher crashes, we know it the next start.
00153     config.writeEntry( "Arts Init", false );
00154     config.writeEntry( "Use Arts", useArts );
00155     config.sync();
00156 
00157     KArtsDispatcher *dispatcher = 0;
00158     if ( useArts )
00159     {
00160         dispatcher = new KArtsDispatcher;
00161         soundServer = new KArtsServer;
00162     }
00163 
00164     // ok, seemed to work.
00165     config.writeEntry("Arts Init", useArts );
00166     config.sync();
00167 
00168     ok = config.readBoolEntry( "KNotify Init", true );
00169     if ( useArts && !ok )
00170     {
00171         if ( KMessageBox::questionYesNo(
00172                  0L,
00173                  i18n("During the previous startup, KNotify crashed while instantiating "
00174                       "KNotify. Do you want to try again or disable "
00175                       "aRts sound output?"),
00176                  i18n("KNotify Problem"),
00177                  i18n("Try Again"),
00178                  i18n("Disable aRts Output"),
00179                  "KNotifyStartProgress",
00180                  0 /* don't call KNotify :) */
00181                  )
00182              == KMessageBox::No )
00183         {
00184             useArts = false;
00185             delete soundServer;
00186             soundServer = 0L;
00187             delete dispatcher;
00188             dispatcher = 0L;
00189         }
00190     }
00191 
00192     // when KNotify instantiation crashes, we know it the next start.
00193     config.writeEntry( "KNotify Init", false );
00194     config.writeEntry( "Use Arts", useArts );
00195     config.sync();
00196 
00197     // start notify service
00198     KNotify notify( useArts );
00199 
00200     config.writeEntry( "KNotify Init", true );
00201     config.sync();
00202 
00203     app.dcopClient()->setDefaultObject( "Notify" );
00204     app.dcopClient()->setDaemonMode( true );
00205     // kdDebug() << "knotify starting" << endl;
00206 
00207     int ret = app.exec();
00208     delete soundServer;
00209     delete dispatcher;
00210     return ret;
00211 }
00212 }// end extern "C"
00213 
00214 KNotify::KNotify( bool useArts )
00215     : QObject(), DCOPObject("Notify")
00216 {
00217     d = new KNotifyPrivate;
00218     d->globalEvents = new KConfig("knotify/eventsrc", true, false, "data");
00219     d->globalConfig = new KConfig("knotify.eventsrc", true, false);
00220     d->externalPlayerProc = 0;
00221     d->useArts = useArts;
00222     d->playObjects.setAutoDelete(true);
00223     d->audioManager = 0;
00224     if( useArts )
00225     {
00226         restartedArtsd(); //started allready need to initialize d->audioManager
00227         // FIXME: Under certain circumstances the restartedServer() signal is
00228         //        emitted in the restartedArtsd() slot. This can lead to
00229         //        infinite looping.
00230         connect( soundServer, SIGNAL( restartedServer() ), this, SLOT( restartedArtsd() ) );
00231     }
00232 
00233     d->volume = 100;
00234 
00235     d->playTimer = 0;
00236 
00237     loadConfig();
00238 }
00239 
00240 KNotify::~KNotify()
00241 {
00242     reconfigure();
00243 
00244     d->playObjects.clear();
00245 
00246     delete d->globalEvents;
00247     delete d->globalConfig;
00248     delete d->externalPlayerProc;
00249     delete d->audioManager;
00250     delete d;
00251 }
00252 
00253 
00254 void KNotify::loadConfig() {
00255     // load external player settings
00256     KConfig *kc = KGlobal::config();
00257     kc->setGroup("Misc");
00258     d->useExternal = kc->readBoolEntry( "Use external player", false );
00259     d->externalPlayer = kc->readPathEntry("External player");
00260 
00261     // try to locate a suitable player if none is configured
00262     if ( d->externalPlayer.isEmpty() ) {
00263         QStringList players;
00264         players << "wavplay" << "aplay" << "auplay";
00265         QStringList::Iterator it = players.begin();
00266         while ( d->externalPlayer.isEmpty() && it != players.end() ) {
00267             d->externalPlayer = KStandardDirs::findExe( *it );
00268             ++it;
00269         }
00270     }
00271 
00272     // load default volume
00273     d->volume = kc->readNumEntry( "Volume", 100 );
00274 }
00275 
00276 
00277 void KNotify::reconfigure()
00278 {
00279     kapp->config()->reparseConfiguration();
00280     loadConfig();
00281 
00282     // clear loaded config files
00283     d->globalConfig->reparseConfiguration();
00284     for ( QMapIterator<QString,KConfig*> it = d->configs.begin(); it != d->configs.end(); ++it )
00285         delete it.data();
00286     d->configs.clear();
00287 }
00288 
00289 
00290 void KNotify::notify(const QString &event, const QString &fromApp,
00291                      const QString &text, QString sound, QString file,
00292                      int present, int level)
00293 {
00294     notify( event, fromApp, text, sound, file, present, level, 0, 1 );
00295 }
00296 
00297 void KNotify::notify(const QString &event, const QString &fromApp,
00298                      const QString &text, QString sound, QString file,
00299                      int present, int level, int winId)
00300 {
00301     notify( event, fromApp, text, sound, file, present, level, winId, 1 );
00302 }
00303 
00304 void KNotify::notify(const QString &event, const QString &fromApp,
00305                      const QString &text, QString sound, QString file,
00306                      int present, int level, int winId, int eventId )
00307 {
00308     // kdDebug() << "event=" << event << " fromApp=" << fromApp << " text=" << text << " sound=" << sound <<
00309     //    " file=" << file << " present=" << present << " level=" << level <<  " winId=" << winId << " eventId=" << eventId endl;
00310 
00311     QString commandline;
00312 
00313     // check for valid events
00314     if ( !event.isEmpty() ) {
00315 
00316         // get config file
00317         KConfig *eventsFile;
00318         KConfig *configFile;
00319         if ( d->events.contains( fromApp ) ) {
00320             eventsFile = d->events[fromApp];
00321         } else {
00322             eventsFile=new KConfig(locate("data", fromApp+"/eventsrc"),true,false);
00323             d->events.insert( fromApp, eventsFile );
00324         }
00325         if ( d->configs.contains( fromApp) ) {
00326             configFile = d->configs[fromApp];
00327         } else {
00328             configFile=new KConfig(fromApp+".eventsrc",true,false);
00329             d->configs.insert( fromApp, configFile );
00330         }
00331 
00332         if ( !eventsFile->hasGroup( event ) && isGlobal(event) )
00333         {
00334             eventsFile = d->globalEvents;
00335             configFile = d->globalConfig;
00336         }
00337 
00338         eventsFile->setGroup( event );
00339         configFile->setGroup( event );
00340 
00341         // get event presentation
00342         if ( present==-1 )
00343             present = configFile->readNumEntry( "presentation", -1 );
00344         if ( present==-1 )
00345             present = eventsFile->readNumEntry( "default_presentation", 0 );
00346 
00347         // get sound file name
00348         if( present & KNotifyClient::Sound ) {
00349             QString theSound = configFile->readPathEntry( "soundfile" );
00350             if ( theSound.isEmpty() )
00351                 theSound = eventsFile->readPathEntry( "default_sound" );
00352             if ( !theSound.isEmpty() )
00353                 sound = theSound;
00354         }
00355 
00356         // get log file name
00357         if( present & KNotifyClient::Logfile ) {
00358             QString theFile = configFile->readPathEntry( "logfile" );
00359             if ( theFile.isEmpty() )
00360                 theFile = eventsFile->readPathEntry( "default_logfile" );
00361             if ( !theFile.isEmpty() )
00362                 file = theFile;
00363         }
00364 
00365         // get default event level
00366         if( present & KNotifyClient::Messagebox )
00367             level = eventsFile->readNumEntry( "level", 0 );
00368 
00369         // get command line
00370         if (present & KNotifyClient::Execute ) {
00371             commandline = configFile->readPathEntry( "commandline" );
00372             if ( commandline.isEmpty() )
00373                 commandline = eventsFile->readPathEntry( "default_commandline" );
00374         }
00375     }
00376 
00377     // emit event
00378     if ( present & KNotifyClient::Sound ) // && QFile(sound).isReadable()
00379         notifyBySound( sound, fromApp, eventId );
00380 
00381     if ( present & KNotifyClient::PassivePopup )
00382         notifyByPassivePopup( text, fromApp, checkWinId( fromApp, winId ));
00383 
00384     else if ( present & KNotifyClient::Messagebox )
00385         notifyByMessagebox( text, level, checkWinId( fromApp, winId ));
00386 
00387     if ( present & KNotifyClient::Logfile ) // && QFile(file).isWritable()
00388         notifyByLogfile( text, file );
00389 
00390     if ( present & KNotifyClient::Stderr )
00391         notifyByStderr( text );
00392 
00393     if ( present & KNotifyClient::Execute )
00394         notifyByExecute( commandline, event, fromApp, text, winId, eventId );
00395 
00396     if ( present & KNotifyClient::Taskbar )
00397         notifyByTaskbar( checkWinId( fromApp, winId ));
00398 
00399     QByteArray qbd;
00400     QDataStream ds(qbd, IO_WriteOnly);
00401     ds << event << fromApp << text << sound << file << present << level
00402         << winId << eventId;
00403     emitDCOPSignal("notifySignal(QString,QString,QString,QString,QString,int,int,int,int)", qbd);
00404 
00405 }
00406 
00407 
00408 bool KNotify::notifyBySound( const QString &sound, const QString &appname, int eventId )
00409 {
00410     if (sound.isEmpty()) {
00411         soundFinished( eventId, NoSoundFile );
00412         return false;
00413     }
00414 
00415     bool external = d->useExternal && !d->externalPlayer.isEmpty();
00416     // get file name
00417     QString soundFile(sound);
00418     if ( QFileInfo(sound).isRelative() )
00419     {
00420         QString search = QString("%1/sounds/%2").arg(appname).arg(sound);
00421         soundFile = KGlobal::instance()->dirs()->findResource("data", search);
00422         if ( soundFile.isEmpty() )
00423             soundFile = locate( "sound", sound );
00424     }
00425     if ( soundFile.isEmpty() || isPlaying( soundFile ) )
00426     {
00427         soundFinished( eventId, soundFile.isEmpty() ? NoSoundFile : FileAlreadyPlaying );
00428         return false;
00429     }
00430 
00431 
00432     // kdDebug() << "KNotify::notifyBySound - trying to play file " << soundFile << endl;
00433 
00434     if (!external) {
00435         //If we disabled using aRts, just return,
00436         //(If we don't, we'll blow up accessing the null soundServer)
00437         if (!d->useArts)
00438         {
00439             soundFinished( eventId, NoSoundSupport );
00440             return false;
00441         }
00442 
00443         // play sound finally
00444         while( d->playObjects.count()>5 )
00445             abortFirstPlayObject();
00446 
00447         KDE::PlayObjectFactory factory(soundServer->server());
00448         if( d->audioManager )
00449             factory.setAudioManagerPlay( d->audioManager );
00450         KURL soundURL;
00451         soundURL.setPath(soundFile);
00452         KDE::PlayObject *playObject = factory.createPlayObject(soundURL, false);
00453 
00454         if (playObject->isNull())
00455         {
00456             soundFinished( eventId, NoSoundSupport );
00457             delete playObject;
00458             return false;
00459         }
00460 
00461         if ( d->volume != 100 )
00462         {
00463             // It works to access the playObject immediately because we don't allow
00464             // non-file URLs for sounds.
00465             Arts::StereoVolumeControl volumeControl = Arts::DynamicCast(soundServer->server().createObject("Arts::StereoVolumeControl"));
00466             Arts::PlayObject player = playObject->object();
00467             Arts::Synth_AMAN_PLAY ap = d->audioManager->amanPlay();
00468             if( ! volumeControl.isNull() && ! player.isNull() && ! ap.isNull() )
00469             {
00470                 volumeControl.scaleFactor( d->volume/100.0 );
00471 
00472                 ap.stop();
00473                 player._node()->stop();
00474                 Arts::disconnect( player, "left", ap, "left" );
00475                 Arts::disconnect( player, "right", ap, "right" );
00476 
00477                 ap.start();
00478                 volumeControl.start();
00479                 player._node()->start();
00480 
00481                 Arts::connect(player,"left",volumeControl,"inleft");
00482                 Arts::connect(player,"right",volumeControl,"inright");
00483 
00484                 Arts::connect(volumeControl,"outleft",ap,"left");
00485                 Arts::connect(volumeControl,"outright",ap,"right");
00486 
00487                 player._addChild( volumeControl, "volume" );
00488             }
00489         }
00490 
00491         playObject->play();
00492         d->playObjects.append( playObject );
00493         d->playObjectEventMap.insert( playObject, eventId );
00494 
00495         if ( !d->playTimer )
00496         {
00497             d->playTimer = new QTimer( this );
00498             connect( d->playTimer, SIGNAL( timeout() ), SLOT( playTimeout() ) );
00499         }
00500         if ( !d->playTimer->isActive() )
00501             d->playTimer->start( 1000 );
00502 
00503         return true;
00504 
00505     } else if(!d->externalPlayer.isEmpty()) {
00506         // use an external player to play the sound
00507         KProcess *proc = d->externalPlayerProc;
00508         if (!proc)
00509         {
00510            proc = d->externalPlayerProc = new KProcess;
00511            connect( proc, SIGNAL( processExited( KProcess * )),
00512                     SLOT( slotPlayerProcessExited( KProcess * )));
00513         }
00514         if (proc->isRunning())
00515         {
00516            soundFinished( eventId, PlayerBusy );
00517            return false; // Skip
00518         }
00519         proc->clearArguments();
00520         (*proc) << d->externalPlayer << QFile::encodeName( soundFile );
00521         d->externalPlayerEventId = eventId;
00522         proc->start(KProcess::NotifyOnExit);
00523         return true;
00524     }
00525 
00526     soundFinished( eventId, Unknown );
00527     return false;
00528 }
00529 
00530 bool KNotify::notifyByMessagebox(const QString &text, int level, WId winId)
00531 {
00532     // ignore empty messages
00533     if ( text.isEmpty() )
00534         return false;
00535 
00536     // display message box for specified event level
00537     switch( level ) {
00538     default:
00539     case KNotifyClient::Notification:
00540         KMessageBox::informationWId( winId, text, i18n("Notification"), 0, false );
00541         break;
00542     case KNotifyClient::Warning:
00543         KMessageBox::sorryWId( winId, text, i18n("Warning"), false );
00544         break;
00545     case KNotifyClient::Error:
00546         KMessageBox::errorWId( winId, text, i18n("Error"), false );
00547         break;
00548     case KNotifyClient::Catastrophe:
00549         KMessageBox::errorWId( winId, text, i18n("Catastrophe!"), false );
00550         break;
00551     }
00552 
00553     return true;
00554 }
00555 
00556 bool KNotify::notifyByPassivePopup( const QString &text,
00557                                     const QString &appName,
00558                                     WId senderWinId )
00559 {
00560     KIconLoader iconLoader( appName );
00561     if ( d->events.find( appName ) != d->events.end() ) {
00562         KConfigGroup config( d->events[ appName ], "!Global!" );
00563         QString iconName = config.readEntry( "IconName", appName );
00564         QPixmap icon = iconLoader.loadIcon( iconName, KIcon::Small );
00565         QString title = config.readEntry( "Comment", appName );
00566         KPassivePopup::message(title, text, icon, senderWinId);
00567     } else
00568         kdError() << "No events for app " << appName << "defined!" <<endl;
00569 
00570     return true;
00571 }
00572 
00573 bool KNotify::notifyByExecute(const QString &command, const QString& event,
00574                               const QString& fromApp, const QString& text,
00575                               int winId, int eventId) {
00576     if (!command.isEmpty()) {
00577     // kdDebug() << "executing command '" << command << "'" << endl;
00578         QMap<QChar,QString> subst;
00579         subst.insert( 'e', event );
00580         subst.insert( 'a', fromApp );
00581         subst.insert( 's', text );
00582         subst.insert( 'w', QString::number( winId ));
00583         subst.insert( 'i', QString::number( eventId ));
00584         QString execLine = KMacroExpander::expandMacrosShellQuote( command, subst );
00585         if ( execLine.isEmpty() )
00586             execLine = command; // fallback
00587         
00588     KProcess p;
00589     p.setUseShell(true);
00590     p << execLine;
00591     p.start(KProcess::DontCare);
00592     return true;
00593     }
00594     return false;
00595 }
00596 
00597 
00598 bool KNotify::notifyByLogfile(const QString &text, const QString &file)
00599 {
00600     // ignore empty messages
00601     if ( text.isEmpty() )
00602         return true;
00603 
00604     // open file in append mode
00605     QFile logFile(file);
00606     if ( !logFile.open(IO_WriteOnly | IO_Append) )
00607         return false;
00608 
00609     // append msg
00610     QTextStream strm( &logFile );
00611     strm << "- KNotify " << QDateTime::currentDateTime().toString() << ": ";
00612     strm << text << endl;
00613 
00614     // close file
00615     logFile.close();
00616     return true;
00617 }
00618 
00619 bool KNotify::notifyByStderr(const QString &text)
00620 {
00621     // ignore empty messages
00622     if ( text.isEmpty() )
00623         return true;
00624 
00625     // open stderr for output
00626     QTextStream strm( stderr, IO_WriteOnly );
00627 
00628     // output msg
00629     strm << "KNotify " << QDateTime::currentDateTime().toString() << ": ";
00630     strm << text << endl;
00631 
00632     return true;
00633 }
00634 
00635 bool KNotify::notifyByTaskbar( WId win )
00636 {
00637     if( win == 0 )
00638         return false;
00639     KWin::demandAttention( win );
00640     return true;
00641 }
00642 
00643 bool KNotify::isGlobal(const QString &eventname)
00644 {
00645     return d->globalEvents->hasGroup( eventname );
00646 }
00647 
00648 void KNotify::setVolume( int volume )
00649 {
00650     if ( volume<0 ) volume=0;
00651     if ( volume>=100 ) volume=100;
00652     d->volume = volume;
00653 }
00654 
00655 void KNotify::playTimeout()
00656 {
00657     for ( QPtrListIterator< KDE::PlayObject > it(d->playObjects); *it;)
00658     {
00659         QPtrListIterator< KDE::PlayObject > current = it;
00660         ++it;
00661         if ( (*current)->state() != Arts::posPlaying )
00662         {
00663             QMap<KDE::PlayObject*,int>::Iterator eit = d->playObjectEventMap.find( *current );
00664             if ( eit != d->playObjectEventMap.end() )
00665             {
00666                 soundFinished( *eit, PlayedOK );
00667                 d->playObjectEventMap.remove( eit );
00668             }
00669             d->playObjects.remove( current );
00670         }
00671     }
00672     if ( !d->playObjects.count() )
00673         d->playTimer->stop();
00674 }
00675 
00676 bool KNotify::isPlaying( const QString& soundFile ) const
00677 {
00678     for ( QPtrListIterator< KDE::PlayObject > it(d->playObjects); *it; ++it)
00679     {
00680         if ( (*it)->mediaName() == soundFile )
00681             return true;
00682     }
00683 
00684     return false;
00685 }
00686 
00687 void KNotify::slotPlayerProcessExited( KProcess *proc )
00688 {
00689     soundFinished( d->externalPlayerEventId,
00690                    (proc->normalExit() && proc->exitStatus() == 0) ? PlayedOK : Unknown );
00691 }
00692 
00693 void KNotify::abortFirstPlayObject()
00694 {
00695     QMap<KDE::PlayObject*,int>::Iterator it = d->playObjectEventMap.find( d->playObjects.getFirst() );
00696     if ( it != d->playObjectEventMap.end() )
00697     {
00698         soundFinished( it.data(), Aborted );
00699         d->playObjectEventMap.remove( it );
00700     }
00701     d->playObjects.removeFirst();
00702 }
00703 
00704 void KNotify::soundFinished( int eventId, PlayingFinishedStatus reason )
00705 {
00706     QByteArray data;
00707     QDataStream stream( data, IO_WriteOnly );
00708     stream << eventId << (int) reason;
00709 
00710     DCOPClient::mainClient()->emitDCOPSignal( "KNotify", "playingFinished(int,int)", data );
00711 }
00712 
00713 WId KNotify::checkWinId( const QString &appName, WId senderWinId )
00714 {
00715     if ( senderWinId == 0 )
00716     {
00717         QCString senderId = kapp->dcopClient()->senderId();
00718         QCString compare = (appName + "-mainwindow").latin1();
00719         int len = compare.length();
00720         // kdDebug() << "notifyByPassivePopup: appName=" << appName << " sender=" << senderId << endl;
00721 
00722         QCStringList objs = kapp->dcopClient()->remoteObjects( senderId );
00723         for (QCStringList::ConstIterator it = objs.begin(); it != objs.end(); it++ ) {
00724             QCString obj( *it );
00725             if ( obj.left(len) == compare) {
00726                 // kdDebug( ) << "found " << obj << endl;
00727                 QCString replyType;
00728                 QByteArray data, replyData;
00729 
00730                 if ( kapp->dcopClient()->call(senderId, obj, "getWinID()", data, replyType, replyData) ) {
00731                     QDataStream answer(replyData, IO_ReadOnly);
00732                     if (replyType == "int") {
00733                         answer >> senderWinId;
00734                         // kdDebug() << "SUCCESS, found getWinID(): type='" << QString(replyType)
00735                         //      << "' senderWinId=" << senderWinId << endl;
00736                     }
00737         }
00738             }
00739         }
00740     }
00741     return senderWinId;
00742 }
00743 
00744 void KNotify::restartedArtsd()
00745 {
00746     delete d->audioManager;
00747     d->audioManager = new KAudioManagerPlay( soundServer );
00748     d->audioManager->setTitle( i18n( "KDE System Notifications" ) );
00749     d->audioManager->setAutoRestoreID( "KNotify Aman Play" );
00750 }
00751 
00752 // vim: sw=4 sts=4 ts=8 et
KDE Logo
This file is part of the documentation for arts Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Jan 21 09:58:07 2005 by doxygen 1.3.6 written by Dimitri van Heesch, © 1997-2003