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.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 12 15:09:01 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003