/** ****************************************************************************** * * @file notifyplugin.cpp * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. * @brief * @see The GNU Public License (GPL) Version 3 * @defgroup notifyplugin * @{ * *****************************************************************************/ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "notifyplugin.h" #include "notifypluginconfiguration.h" #include "notifypluginoptionspage.h" #include #include #include #include #include #include #include "qxttimer.h" //#define DEBUG_NOTIFIES SoundNotifyPlugin::SoundNotifyPlugin() { phonon.mo = NULL; phonon.ms = NULL; // Do nothing } SoundNotifyPlugin::~SoundNotifyPlugin() { // Do nothing } bool SoundNotifyPlugin::initialize(const QStringList& args, QString *errMsg) { Q_UNUSED(args); Q_UNUSED(errMsg); mop = new NotifyPluginOptionsPage(this); addAutoReleasedObject(mop); return true; } void SoundNotifyPlugin::extensionsInitialized() { settings = Core::ICore::instance()->settings(); settings->beginGroup(QLatin1String("NotifyPlugin")); // read list of notifications from settings int size = settings->beginReadArray("listNotifies"); for (int i = 0; i < size; ++i) { settings->setArrayIndex(i); NotifyPluginConfiguration* notification = new NotifyPluginConfiguration; notification->restoreState(settings); lstNotifications.append(notification); } settings->endArray(); setEnableSound(settings->value(QLatin1String("EnableSound"),0).toBool()); settings->endGroup(); ExtensionSystem::PluginManager* pm = ExtensionSystem::PluginManager::instance(); connect(pm, SIGNAL(objectAdded(QObject*)), this, SLOT(onTelemetryManagerAdded(QObject*))); removedNotifies.clear(); connectNotifications(); } void SoundNotifyPlugin::onTelemetryManagerAdded(QObject* obj) { telMngr = qobject_cast(obj); if(telMngr) connect(telMngr, SIGNAL(disconnected()), this, SLOT(onAutopilotDisconnect())); } void SoundNotifyPlugin::shutdown() { // Do nothing } void SoundNotifyPlugin::onAutopilotDisconnect() { connectNotifications(); } /*! clear any notify timers from previous flight; reset will be perform on start of option page */ void SoundNotifyPlugin::resetNotification(void) { //first, reject empty args and unknown fields. foreach(NotifyPluginConfiguration* notify,lstNotifications) { if(notify->timer) { disconnect(notify->timer, SIGNAL(timeout()), this, SLOT(repeatTimerHandler())); notify->timer->stop(); delete notify->timer; notify->timer = NULL; } if(notify->expireTimer) { disconnect(notify->expireTimer, SIGNAL(timeout()), this, SLOT(expireTimerHandler())); notify->expireTimer->stop(); delete notify->expireTimer; notify->expireTimer = NULL; } } } /*! update list of notifies; will be perform on OK or APPLY press of option page */ void SoundNotifyPlugin::updateNotificationList(QList list) { removedNotifies.clear(); lstNotifications.clear(); lstNotifications=list; connectNotifications(); } void SoundNotifyPlugin::connectNotifications() { foreach(UAVDataObject* obj,lstNotifiedUAVObjects) { if (obj != NULL) disconnect(obj,SIGNAL(objectUpdated(UAVObject*)),this,SLOT(appendNotification(UAVObject*))); } if(phonon.mo != NULL) delete phonon.mo; if(phonon.ms != NULL) delete phonon.ms; if(!enableSound) return; ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); UAVObjectManager *objManager = pm->getObject(); lstNotifiedUAVObjects.clear(); pendingNotifications.clear(); lstNotifications.append(removedNotifies); removedNotifies.clear(); //first, reject empty args and unknown fields. foreach(NotifyPluginConfiguration* notify,lstNotifications) { notify->firstStart=true; notify->isNowPlaying=false; // if(notify->timer) // { // disconnect(notify->timer, SIGNAL(timeout()), this, SLOT(repeatTimerHandler())); // notify->timer->stop(); // delete notify->timer; // notify->timer = NULL; // } // if(notify->expireTimer) // { // disconnect(notify->expireTimer, SIGNAL(timeout()), this, SLOT(expireTimerHandler())); // notify->expireTimer->stop(); // delete notify->expireTimer; // notify->expireTimer = NULL; // } UAVDataObject* obj = dynamic_cast( objManager->getObject(notify->getDataObject()) ); if (obj != NULL ) { if(!lstNotifiedUAVObjects.contains(obj)) { lstNotifiedUAVObjects.append(obj); connect(obj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(appendNotification(UAVObject*))); } } else std::cout << "Error: Object is unknown (" << notify->getDataObject().toStdString() << ")." << std::endl; } if(lstNotifications.isEmpty()) return; // set notification message to current event phonon.mo = new Phonon::MediaObject; phonon.mo = Phonon::createPlayer(Phonon::NotificationCategory); phonon.ms = new QList; phonon.mo->clear(); connect(phonon.mo,SIGNAL(stateChanged(Phonon::State,Phonon::State)), this,SLOT(stateChanged(Phonon::State,Phonon::State))); } void SoundNotifyPlugin::appendNotification(UAVObject *object) { disconnect(object, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(appendNotification(UAVObject*))); foreach(NotifyPluginConfiguration* notification, lstNotifications) { if(object->getName()!=notification->getDataObject()) continue; if(nowPlayingConfiguration == notification) continue; if(notification->getRepeatFlag()!= "Repeat Instantly" && notification->getRepeatFlag()!= "Repeat Once" && !notification->firstStart) continue; checkNotificationRule(notification,object); } connect(object, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(appendNotification(UAVObject*))); } void SoundNotifyPlugin::checkNotificationRule(NotifyPluginConfiguration* notification, UAVObject* object) { bool condition=false; double threshold; QString direction; QString fieldName; threshold = notification->getSpinBoxValue(); direction = notification->getValue(); fieldName = notification->getObjectField(); UAVObjectField* field = object->getField(fieldName); if (field->getName()!="") { double value = field->getDouble(); switch(direction[0].toAscii()) { case 'E': if(value==threshold) condition = true; break; case 'G': if(value>threshold) condition = true; break; case 'L': if(valuetimer) if(notification->timer->isActive()) notification->timer->stop(); #ifdef DEBUG_NOTIFIES qDebug() << "add to pending list - " << notification->parseNotifyMessage(); #endif // if audio is busy, start expiration timer //ms = (notification->getExpiredTimeout()[in sec])*1000 //QxtTimer::singleShot(notification->getExpireTimeout()*1000, this, SLOT(expirationTimerHandler(NotifyPluginConfiguration*)), qVariantFromValue(notification)); pendingNotifications.append(notification); if(!notification->expireTimer) { notification->expireTimer = new QTimer(notification); connect(notification->expireTimer, SIGNAL(timeout()), this, SLOT(expireTimerHandler())); } notification->expireTimer->start(notification->getExpireTimeout()*1000); } } } } bool SoundNotifyPlugin::playNotification(NotifyPluginConfiguration* notification) { if((phonon.mo->state()==Phonon::PausedState) || (phonon.mo->state()==Phonon::StoppedState)) { // don't fire expire timer //notification->expire = false; nowPlayingConfiguration = notification; if(notification->expireTimer) notification->expireTimer->stop(); if(notification->getRepeatFlag()=="Repeat Once") { removedNotifies.append(lstNotifications.takeAt(lstNotifications.indexOf(notification))); //if(!notification->firstStart) return true; } else { if(notification->getRepeatFlag()!="Repeat Instantly") { QRegExp rxlen("(\\d+)"); QString value; int timer_value; int pos = rxlen.indexIn(notification->getRepeatFlag()); if (pos > -1) { value = rxlen.cap(1); // "189" timer_value = (value.toInt()+8)*1000; //ms*1000 + average duration of meassage } if(!notification->timer) { notification->timer = new QTimer(notification); notification->timer->setInterval(timer_value); connect(notification->timer, SIGNAL(timeout()), this, SLOT(repeatTimerHandler())); } if(!notification->timer->isActive()) notification->timer->start(); //QxtTimer::singleShot(timer_value, this, SLOT(repeatTimerHandler(NotifyPluginConfiguration*)), qVariantFromValue(notification)); } } notification->firstStart=false; phonon.mo->clear(); phonon.ms->clear(); QString str = notification->parseNotifyMessage(); #ifdef DEBUG_NOTIFIES qDebug() << "play notification - " << str; #endif foreach(QString item, notification->getNotifyMessageList()) phonon.ms->append(Phonon::MediaSource(item)); phonon.mo->setQueue(*phonon.ms); phonon.mo->play(); } else return false; // if audio is busy return true; } //void SoundNotifyPlugin::repeatTimerHandler(NotifyPluginConfiguration* notification) //{ // qDebug() << "repeatTimerHandler - " << notification->parseNotifyMessage(); // ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); // UAVObjectManager *objManager = pm->getObject(); // UAVObject* object = objManager->getObject(notification->getDataObject()); // if(object) // checkNotificationRule(notification,object); //} void SoundNotifyPlugin::repeatTimerHandler() { NotifyPluginConfiguration* notification = static_cast(sender()->parent()); #ifdef DEBUG_NOTIFIES qDebug() << "repeatTimerHandler - " << notification->parseNotifyMessage(); #endif ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); UAVObjectManager *objManager = pm->getObject(); UAVObject* object = objManager->getObject(notification->getDataObject()); if(object) checkNotificationRule(notification,object); } void SoundNotifyPlugin::expireTimerHandler() { // fire expire timer NotifyPluginConfiguration* notification = static_cast(sender()->parent()); notification->expireTimer->stop(); if(!pendingNotifications.isEmpty()) { #ifdef DEBUG_NOTIFIES qDebug() << "expireTimerHandler - " << notification->parseNotifyMessage(); #endif pendingNotifications.removeOne(notification); } } void SoundNotifyPlugin::stateChanged(Phonon::State newstate, Phonon::State oldstate) { if((newstate == Phonon::PausedState) || (newstate == Phonon::StoppedState)) { nowPlayingConfiguration=NULL; if(!pendingNotifications.isEmpty()) { NotifyPluginConfiguration* notification = pendingNotifications.takeFirst(); #ifdef DEBUG_NOTIFIES qDebug() << "play audioFree - " << notification->parseNotifyMessage(); #endif playNotification(notification); } } if(newstate == Phonon::ErrorState) { if(phonon.mo->errorType()==0) { qDebug() << "Phonon::ErrorState: ErrorType = " << phonon.mo->errorType(); phonon.mo->clear(); } } // if(newstate == Phonon::BufferingState) // qDebug() << "Phonon::BufferingState!!!"; } Q_EXPORT_PLUGIN(SoundNotifyPlugin)