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