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