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::Execute ) 00392 notifyByExecute( commandline, event, fromApp, text, winId, eventId ); 00393 00394 if ( present & KNotifyClient::Logfile ) // && QFile(file).isWritable() 00395 notifyByLogfile( text, file ); 00396 00397 if ( present & KNotifyClient::Stderr ) 00398 notifyByStderr( text ); 00399 00400 if ( present & KNotifyClient::Taskbar ) 00401 notifyByTaskbar( checkWinId( fromApp, winId )); 00402 00403 if ( present & KNotifyClient::PassivePopup ) 00404 notifyByPassivePopup( text, fromApp, checkWinId( fromApp, winId )); 00405 else if ( present & KNotifyClient::Messagebox ) 00406 notifyByMessagebox( text, level, checkWinId( fromApp, winId )); 00407 00408 QByteArray qbd; 00409 QDataStream ds(qbd, IO_WriteOnly); 00410 ds << event << fromApp << text << sound << file << present << level 00411 << winId << eventId; 00412 emitDCOPSignal("notifySignal(QString,QString,QString,QString,QString,int,int,int,int)", qbd); 00413 00414 } 00415 00416 00417 bool KNotify::notifyBySound( const QString &sound, const QString &appname, int eventId ) 00418 { 00419 if (sound.isEmpty()) { 00420 soundFinished( eventId, NoSoundFile ); 00421 return false; 00422 } 00423 00424 bool external = d->useExternal && !d->externalPlayer.isEmpty(); 00425 // get file name 00426 QString soundFile(sound); 00427 if ( QFileInfo(sound).isRelative() ) 00428 { 00429 QString search = QString("%1/sounds/%2").arg(appname).arg(sound); 00430 soundFile = KGlobal::instance()->dirs()->findResource("data", search); 00431 if ( soundFile.isEmpty() ) 00432 soundFile = locate( "sound", sound ); 00433 } 00434 if ( soundFile.isEmpty() || isPlaying( soundFile ) ) 00435 { 00436 soundFinished( eventId, soundFile.isEmpty() ? NoSoundFile : FileAlreadyPlaying ); 00437 return false; 00438 } 00439 00440 00441 // kdDebug() << "KNotify::notifyBySound - trying to play file " << soundFile << endl; 00442 00443 if (!external) { 00444 //If we disabled using aRts, just return, 00445 //(If we don't, we'll blow up accessing the null soundServer) 00446 if (!d->useArts) 00447 { 00448 soundFinished( eventId, NoSoundSupport ); 00449 return false; 00450 } 00451 00452 // play sound finally 00453 while( d->playObjects.count()>5 ) 00454 abortFirstPlayObject(); 00455 00456 KDE::PlayObjectFactory factory(soundServer->server()); 00457 if( d->audioManager ) 00458 factory.setAudioManagerPlay( d->audioManager ); 00459 KURL soundURL; 00460 soundURL.setPath(soundFile); 00461 KDE::PlayObject *playObject = factory.createPlayObject(soundURL, false); 00462 00463 if (playObject->isNull()) 00464 { 00465 soundFinished( eventId, NoSoundSupport ); 00466 delete playObject; 00467 return false; 00468 } 00469 00470 if ( d->volume != 100 ) 00471 { 00472 // It works to access the playObject immediately because we don't allow 00473 // non-file URLs for sounds. 00474 Arts::StereoVolumeControl volumeControl = Arts::DynamicCast(soundServer->server().createObject("Arts::StereoVolumeControl")); 00475 Arts::PlayObject player = playObject->object(); 00476 Arts::Synth_AMAN_PLAY ap = d->audioManager->amanPlay(); 00477 if( ! volumeControl.isNull() && ! player.isNull() && ! ap.isNull() ) 00478 { 00479 volumeControl.scaleFactor( d->volume/100.0 ); 00480 00481 ap.stop(); 00482 player._node()->stop(); 00483 Arts::disconnect( player, "left", ap, "left" ); 00484 Arts::disconnect( player, "right", ap, "right" ); 00485 00486 ap.start(); 00487 volumeControl.start(); 00488 player._node()->start(); 00489 00490 Arts::connect(player,"left",volumeControl,"inleft"); 00491 Arts::connect(player,"right",volumeControl,"inright"); 00492 00493 Arts::connect(volumeControl,"outleft",ap,"left"); 00494 Arts::connect(volumeControl,"outright",ap,"right"); 00495 00496 player._addChild( volumeControl, "volume" ); 00497 } 00498 } 00499 00500 playObject->play(); 00501 d->playObjects.append( playObject ); 00502 d->playObjectEventMap.insert( playObject, eventId ); 00503 00504 if ( !d->playTimer ) 00505 { 00506 d->playTimer = new QTimer( this ); 00507 connect( d->playTimer, SIGNAL( timeout() ), SLOT( playTimeout() ) ); 00508 } 00509 if ( !d->playTimer->isActive() ) 00510 d->playTimer->start( 1000 ); 00511 00512 return true; 00513 00514 } else if(!d->externalPlayer.isEmpty()) { 00515 // use an external player to play the sound 00516 KProcess *proc = d->externalPlayerProc; 00517 if (!proc) 00518 { 00519 proc = d->externalPlayerProc = new KProcess; 00520 connect( proc, SIGNAL( processExited( KProcess * )), 00521 SLOT( slotPlayerProcessExited( KProcess * ))); 00522 } 00523 if (proc->isRunning()) 00524 { 00525 soundFinished( eventId, PlayerBusy ); 00526 return false; // Skip 00527 } 00528 proc->clearArguments(); 00529 (*proc) << d->externalPlayer << QFile::encodeName( soundFile ); 00530 d->externalPlayerEventId = eventId; 00531 proc->start(KProcess::NotifyOnExit); 00532 return true; 00533 } 00534 00535 soundFinished( eventId, Unknown ); 00536 return false; 00537 } 00538 00539 bool KNotify::notifyByMessagebox(const QString &text, int level, WId winId) 00540 { 00541 // ignore empty messages 00542 if ( text.isEmpty() ) 00543 return false; 00544 00545 // display message box for specified event level 00546 switch( level ) { 00547 default: 00548 case KNotifyClient::Notification: 00549 KMessageBox::informationWId( winId, text, i18n("Notification"), 0, false ); 00550 break; 00551 case KNotifyClient::Warning: 00552 KMessageBox::sorryWId( winId, text, i18n("Warning"), false ); 00553 break; 00554 case KNotifyClient::Error: 00555 KMessageBox::errorWId( winId, text, i18n("Error"), false ); 00556 break; 00557 case KNotifyClient::Catastrophe: 00558 KMessageBox::errorWId( winId, text, i18n("Catastrophe!"), false ); 00559 break; 00560 } 00561 00562 return true; 00563 } 00564 00565 bool KNotify::notifyByPassivePopup( const QString &text, 00566 const QString &appName, 00567 WId senderWinId ) 00568 { 00569 KIconLoader iconLoader( appName ); 00570 if ( d->events.find( appName ) != d->events.end() ) { 00571 KConfigGroup config( d->events[ appName ], "!Global!" ); 00572 QString iconName = config.readEntry( "IconName", appName ); 00573 QPixmap icon = iconLoader.loadIcon( iconName, KIcon::Small ); 00574 QString title = config.readEntry( "Comment", appName ); 00575 KPassivePopup::message(title, text, icon, senderWinId); 00576 } else 00577 kdError() << "No events for app " << appName << "defined!" <<endl; 00578 00579 return true; 00580 } 00581 00582 bool KNotify::notifyByExecute(const QString &command, const QString& event, 00583 const QString& fromApp, const QString& text, 00584 int winId, int eventId) { 00585 if (!command.isEmpty()) { 00586 // kdDebug() << "executing command '" << command << "'" << endl; 00587 QMap<QChar,QString> subst; 00588 subst.insert( 'e', event ); 00589 subst.insert( 'a', fromApp ); 00590 subst.insert( 's', text ); 00591 subst.insert( 'w', QString::number( winId )); 00592 subst.insert( 'i', QString::number( eventId )); 00593 QString execLine = KMacroExpander::expandMacrosShellQuote( command, subst ); 00594 if ( execLine.isEmpty() ) 00595 execLine = command; // fallback 00596 00597 KProcess p; 00598 p.setUseShell(true); 00599 p << execLine; 00600 p.start(KProcess::DontCare); 00601 return true; 00602 } 00603 return false; 00604 } 00605 00606 00607 bool KNotify::notifyByLogfile(const QString &text, const QString &file) 00608 { 00609 // ignore empty messages 00610 if ( text.isEmpty() ) 00611 return true; 00612 00613 // open file in append mode 00614 QFile logFile(file); 00615 if ( !logFile.open(IO_WriteOnly | IO_Append) ) 00616 return false; 00617 00618 // append msg 00619 QTextStream strm( &logFile ); 00620 strm << "- KNotify " << QDateTime::currentDateTime().toString() << ": "; 00621 strm << text << endl; 00622 00623 // close file 00624 logFile.close(); 00625 return true; 00626 } 00627 00628 bool KNotify::notifyByStderr(const QString &text) 00629 { 00630 // ignore empty messages 00631 if ( text.isEmpty() ) 00632 return true; 00633 00634 // open stderr for output 00635 QTextStream strm( stderr, IO_WriteOnly ); 00636 00637 // output msg 00638 strm << "KNotify " << QDateTime::currentDateTime().toString() << ": "; 00639 strm << text << endl; 00640 00641 return true; 00642 } 00643 00644 bool KNotify::notifyByTaskbar( WId win ) 00645 { 00646 if( win == 0 ) 00647 return false; 00648 KWin::demandAttention( win ); 00649 return true; 00650 } 00651 00652 bool KNotify::isGlobal(const QString &eventname) 00653 { 00654 return d->globalEvents->hasGroup( eventname ); 00655 } 00656 00657 void KNotify::setVolume( int volume ) 00658 { 00659 if ( volume<0 ) volume=0; 00660 if ( volume>=100 ) volume=100; 00661 d->volume = volume; 00662 } 00663 00664 void KNotify::playTimeout() 00665 { 00666 for ( QPtrListIterator< KDE::PlayObject > it(d->playObjects); *it;) 00667 { 00668 QPtrListIterator< KDE::PlayObject > current = it; 00669 ++it; 00670 if ( (*current)->state() != Arts::posPlaying ) 00671 { 00672 QMap<KDE::PlayObject*,int>::Iterator eit = d->playObjectEventMap.find( *current ); 00673 if ( eit != d->playObjectEventMap.end() ) 00674 { 00675 soundFinished( *eit, PlayedOK ); 00676 d->playObjectEventMap.remove( eit ); 00677 } 00678 d->playObjects.remove( current ); 00679 } 00680 } 00681 if ( !d->playObjects.count() ) 00682 d->playTimer->stop(); 00683 } 00684 00685 bool KNotify::isPlaying( const QString& soundFile ) const 00686 { 00687 for ( QPtrListIterator< KDE::PlayObject > it(d->playObjects); *it; ++it) 00688 { 00689 if ( (*it)->mediaName() == soundFile ) 00690 return true; 00691 } 00692 00693 return false; 00694 } 00695 00696 void KNotify::slotPlayerProcessExited( KProcess *proc ) 00697 { 00698 soundFinished( d->externalPlayerEventId, 00699 (proc->normalExit() && proc->exitStatus() == 0) ? PlayedOK : Unknown ); 00700 } 00701 00702 void KNotify::abortFirstPlayObject() 00703 { 00704 QMap<KDE::PlayObject*,int>::Iterator it = d->playObjectEventMap.find( d->playObjects.getFirst() ); 00705 if ( it != d->playObjectEventMap.end() ) 00706 { 00707 soundFinished( it.data(), Aborted ); 00708 d->playObjectEventMap.remove( it ); 00709 } 00710 d->playObjects.removeFirst(); 00711 } 00712 00713 void KNotify::soundFinished( int eventId, PlayingFinishedStatus reason ) 00714 { 00715 QByteArray data; 00716 QDataStream stream( data, IO_WriteOnly ); 00717 stream << eventId << (int) reason; 00718 00719 DCOPClient::mainClient()->emitDCOPSignal( "KNotify", "playingFinished(int,int)", data ); 00720 } 00721 00722 WId KNotify::checkWinId( const QString &appName, WId senderWinId ) 00723 { 00724 if ( senderWinId == 0 ) 00725 { 00726 QCString senderId = kapp->dcopClient()->senderId(); 00727 QCString compare = (appName + "-mainwindow").latin1(); 00728 int len = compare.length(); 00729 // kdDebug() << "notifyByPassivePopup: appName=" << appName << " sender=" << senderId << endl; 00730 00731 QCStringList objs = kapp->dcopClient()->remoteObjects( senderId ); 00732 for (QCStringList::ConstIterator it = objs.begin(); it != objs.end(); it++ ) { 00733 QCString obj( *it ); 00734 if ( obj.left(len) == compare) { 00735 // kdDebug( ) << "found " << obj << endl; 00736 QCString replyType; 00737 QByteArray data, replyData; 00738 00739 if ( kapp->dcopClient()->call(senderId, obj, "getWinID()", data, replyType, replyData) ) { 00740 QDataStream answer(replyData, IO_ReadOnly); 00741 if (replyType == "int") { 00742 answer >> senderWinId; 00743 // kdDebug() << "SUCCESS, found getWinID(): type='" << QString(replyType) 00744 // << "' senderWinId=" << senderWinId << endl; 00745 } 00746 } 00747 } 00748 } 00749 } 00750 return senderWinId; 00751 } 00752 00753 void KNotify::restartedArtsd() 00754 { 00755 delete d->audioManager; 00756 d->audioManager = new KAudioManagerPlay( soundServer ); 00757 d->audioManager->setTitle( i18n( "KDE System Notifications" ) ); 00758 d->audioManager->setAutoRestoreID( "KNotify Aman Play" ); 00759 } 00760 00761 void KNotify::sessionReady() 00762 { 00763 if( d->inStartup && !d->startupEvents.isEmpty()) 00764 kdDebug() << "There were knotify events while startup:" << d->startupEvents << endl; 00765 d->inStartup = false; 00766 } 00767 00768 // 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 Tue Apr 12 23:21:27 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003