31 #include <QtCore/QBasicTimer>
32 #include <QtCore/QQueue>
33 #include <QtCore/QTimer>
34 #include <QtCore/QTimerEvent>
35 #include <QtCore/QStack>
36 #include <QSignalMapper>
42 #include <kstandarddirs.h>
43 #include <kconfiggroup.h>
45 #include <config-runtime.h>
46 #include <kcomponentdata.h>
50 #include <phonon/mediaobject.h>
51 #include <phonon/path.h>
52 #include <phonon/audiooutput.h>
57 : media(new Phonon::MediaObject),
58 output(new Phonon::AudioOutput(Phonon::NotificationCategory))
64 inline void stop() { media->stop(); }
65 inline void setVolume(
float volume) { output->setVolume(volume); }
69 output->deleteLater();
80 PlayerPool() : m_idlePlayer(0), m_volume(1.0) {}
83 void returnPlayer(Player *);
86 void setVolume(
float volume);
94 Player *PlayerPool::getPlayer()
103 p->setVolume(m_volume);
108 void PlayerPool::returnPlayer(Player *p)
110 m_playersInUse.removeAll(p);
118 void PlayerPool::clear()
124 void PlayerPool::setVolume(
float v)
127 foreach (Player *p, m_playersInUse) {
132 class NotifyBySound::Private
135 enum { NoSound, UsePhonon, ExternalPlayer } playerMode;
141 PlayerPool playerPool;
152 connect(d->signalmapper, SIGNAL(mapped(
int)),
this, SLOT(slotSoundFinished(
int)));
164 void NotifyBySound::loadConfig()
167 KSharedConfig::Ptr kc = KGlobal::config();
168 KConfigGroup cg(kc,
"Sounds");
170 d->playerMode = Private::UsePhonon;
171 if(cg.readEntry(
"Use external player",
false ))
173 d->playerMode = Private::ExternalPlayer;
174 d->externalPlayer = cg.readPathEntry(
"External player",
QString());
176 if ( d->externalPlayer.isEmpty() ) {
178 players <<
"wavplay" <<
"aplay" <<
"auplay" <<
"artsplay" <<
"akodeplay";
180 while ( d->externalPlayer.isEmpty() && it != players.
constEnd() ) {
181 d->externalPlayer = KStandardDirs::findExe( *it );
186 else if(cg.readEntry(
"No sound" ,
false ))
188 d->playerMode = Private::NoSound;
191 setVolume( cg.readEntry(
"Volume", 100 ) );
199 if(d->playerMode == Private::NoSound)
205 if(d->playerObjects.contains(eventId) || d->processes.contains(eventId) )
212 KUrl soundFileURL = config->
readEntry(
"Sound" ,
true );
213 QString soundFile = soundFileURL.toLocalFile();
222 if ( KUrl::isRelativeUrl(soundFile) )
225 search = KGlobal::mainComponent().dirs()->findResource(
"data", search);
227 soundFile = KStandardDirs::locate(
"sound", soundFile );
237 kDebug() <<
" going to play " << soundFile;
240 if(d->playerMode == Private::UsePhonon)
242 Player *player = d->playerPool.getPlayer();
243 connect(player->media, SIGNAL(
finished()), d->signalmapper, SLOT(map()));
244 d->signalmapper->setMapping(player->media, eventId);
245 player->play(soundFile);
246 d->playerObjects.insert(eventId, player);
248 else if (d->playerMode == Private::ExternalPlayer && !d->externalPlayer.isEmpty())
251 KProcess *proc =
new KProcess(
this );
253 d->signalmapper, SLOT(map()) );
254 d->signalmapper->setMapping( proc , eventId );
256 (*proc) << d->externalPlayer << soundFile;
264 if ( volume<0 ) volume=0;
265 if ( volume>=100 ) volume=100;
267 d->playerPool.setVolume(d->volume / 100.0);
273 if (e->
timerId() == d->poolTimer.timerId()) {
275 d->playerPool.clear();
281 void NotifyBySound::slotSoundFinished(
int id)
284 if(d->playerObjects.contains(
id))
286 Player *player=d->playerObjects.take(
id);
288 d->playerPool.returnPlayer(player);
291 if(d->processes.contains(
id))
293 d->processes[id]->deleteLater();
294 d->processes.remove(
id);
303 d->closeQueue.enqueue(
id);
307 void NotifyBySound::closeNow()
309 const int id = d->closeQueue.dequeue();
310 if(d->playerObjects.contains(
id))
312 Player *p = d->playerObjects.take(
id);
314 d->playerPool.returnPlayer(p);
317 if(d->processes.contains(
id))
319 d->processes[id]->kill();
320 d->processes[id]->deleteLater();
321 d->processes.remove(
id);
325 #include "notifybysound.moc"
virtual void notify(int id, KNotifyConfig *config)
This function is called when the notification is sent.
QString readEntry(const QString &entry, bool path=false)
abstract class for KNotify actions
virtual void timerEvent(QTimerEvent *event)
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
virtual void close(int id)
This function is called when the notification has been closed.
Path createPath(MediaNode *source, MediaNode *sink)
void finished(int id)
the presentation is finished.
void finish(int id)
emit the finished signal you MUST call this function for each call to notify(), even if you do nothin...
NotifyBySound(QObject *parent=0l)
void timerEvent(QTimerEvent *)
const_iterator constEnd() const
const_iterator constBegin() const
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QString appname
the name of the application that triggered the notification
Represent the configuration for an event.
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const