|
MythTV
0.26-pre
|
00001 00002 #include <QApplication> 00003 #include <QFileInfo> 00004 #include <QRunnable> 00005 00006 #include "mythcorecontext.h" 00007 #include "mthreadpool.h" 00008 #include "mythsystem.h" 00009 #include "mythsystemevent.h" 00010 #include "programinfo.h" 00011 #include "remoteutil.h" 00012 #include "exitcodes.h" 00013 #include "mythlogging.h" 00014 00015 #define LOC QString("MythSystemEventHandler: ") 00016 00026 class SystemEventThread : public QRunnable 00027 { 00028 public: 00035 SystemEventThread(const QString cmd, QString eventName = "") 00036 : m_command(cmd), m_event(eventName) {}; 00037 00043 void run(void) 00044 { 00045 uint flags = kMSDontBlockInputDevs; 00046 00047 m_event.detach(); 00048 m_command.detach(); 00049 00050 uint result = myth_system(m_command, flags); 00051 00052 if (result != GENERIC_EXIT_OK) 00053 LOG(VB_GENERAL, LOG_WARNING, LOC + 00054 QString("Command '%1' returned %2") 00055 .arg(m_command).arg(result)); 00056 00057 if (m_event.isEmpty()) 00058 return; 00059 00060 gCoreContext->SendMessage( 00061 QString("SYSTEM_EVENT_RESULT %1 SENDER %2 RESULT %3") 00062 .arg(m_event).arg(gCoreContext->GetHostName()).arg(result)); 00063 } 00064 00065 private: 00066 // Private data storage 00067 QString m_command; 00068 QString m_event; 00069 }; 00070 00071 00077 MythSystemEventHandler::MythSystemEventHandler(void) 00078 { 00079 gCoreContext->addListener(this); 00080 } 00081 00087 MythSystemEventHandler::~MythSystemEventHandler() 00088 { 00089 gCoreContext->removeListener(this); 00090 } 00091 00105 void MythSystemEventHandler::SubstituteMatches(const QStringList &tokens, 00106 QString &command) 00107 { 00108 if (command.isEmpty()) 00109 return; 00110 00111 LOG(VB_FILE, LOG_DEBUG, LOC + QString("SubstituteMatches: BEFORE: %1") 00112 .arg(command)); 00113 QString args; 00114 uint chanid = 0; 00115 QDateTime recstartts; 00116 QString sender; 00117 00118 QStringList::const_iterator it = tokens.begin(); 00119 ++it; 00120 command.replace(QString("%EVENTNAME%"), *it); 00121 00122 ++it; 00123 while (it != tokens.end()) 00124 { 00125 if (!args.isEmpty()) 00126 args += " "; 00127 args += *it; 00128 00129 // Check for some token names that we substitute one for one as 00130 // %MATCH% type variables. 00131 if ((*it == "CARDID") || 00132 (*it == "RECSTATUS") || 00133 (*it == "HOSTNAME") || 00134 (*it == "SECS") || 00135 (*it == "SENDER") || 00136 (*it == "PATH")) 00137 { 00138 QString token = *it; 00139 00140 if (++it == tokens.end()) 00141 break; 00142 00143 if (token == "SENDER") 00144 sender = *it; 00145 00146 // The following string is broken up on purpose to indicate 00147 // what we're replacing is the token surrounded by percent signs 00148 command.replace(QString("%" "%1" "%").arg(token), *it); 00149 00150 if (!args.isEmpty()) 00151 args += " "; 00152 args += *it; 00153 } 00154 00155 // Remember any chanid and starttime so we can lookup info about 00156 // the recording from the database. 00157 if (*it == "CHANID") 00158 { 00159 if (++it == tokens.end()) 00160 break; 00161 00162 chanid = (*it).toUInt(); 00163 00164 if (!args.isEmpty()) 00165 args += " "; 00166 args += *it; 00167 } 00168 00169 if (*it == "STARTTIME") 00170 { 00171 if (++it == tokens.end()) 00172 break; 00173 00174 recstartts = QDateTime::fromString(*it, Qt::ISODate); 00175 00176 if (!args.isEmpty()) 00177 args += " "; 00178 args += *it; 00179 } 00180 00181 ++it; 00182 } 00183 00184 command.replace(QString("%ARGS%"), args); 00185 00186 ProgramInfo pginfo(chanid, recstartts); 00187 bool pginfo_loaded = pginfo.GetChanID(); 00188 if (!pginfo_loaded) 00189 { 00190 RecordingInfo::LoadStatus status; 00191 pginfo = RecordingInfo(chanid, recstartts, false, 0, &status); 00192 pginfo_loaded = RecordingInfo::kFoundProgram == status; 00193 } 00194 00195 if (pginfo_loaded) 00196 { 00197 pginfo.SubstituteMatches(command); 00198 } 00199 else 00200 { 00201 command.replace(QString("%CHANID%"), QString::number(chanid)); 00202 command.replace(QString("%STARTTIME%"), 00203 recstartts.toString("yyyyMMddhhmmss")); 00204 command.replace(QString("%STARTTIMEISO%"), 00205 recstartts.toString(Qt::ISODate)); 00206 } 00207 00208 command.replace(QString("%VERBOSELEVEL%"), QString("%1").arg(verboseMask)); 00209 00210 LOG(VB_FILE, LOG_DEBUG, LOC + QString("SubstituteMatches: AFTER : %1") 00211 .arg(command)); 00212 } 00213 00223 QString MythSystemEventHandler::EventNameToSetting(const QString &name) 00224 { 00225 QString result("EventCmd"); 00226 QStringList parts = name.toLower().split('_', QString::SkipEmptyParts); 00227 00228 QStringList::Iterator it = parts.begin(); 00229 while (it != parts.end()) 00230 { 00231 result += (*it).left(1).toUpper(); 00232 result += (*it).mid(1); 00233 00234 ++it; 00235 } 00236 00237 return result; 00238 } 00239 00255 void MythSystemEventHandler::customEvent(QEvent *e) 00256 { 00257 if ((MythEvent::Type)(e->type()) == MythEvent::MythEventMessage) 00258 { 00259 MythEvent *me = (MythEvent *)e; 00260 QString msg = me->Message().simplified(); 00261 00262 if (msg == "CLEAR_SETTINGS_CACHE") 00263 msg = "SYSTEM_EVENT SETTINGS_CACHE_CLEARED"; 00264 00265 // Listen for any GLOBAL_SYSTEM_EVENT messages and resend to 00266 // the master backend as regular SYSTEM_EVENT messages. 00267 if (msg.startsWith("GLOBAL_SYSTEM_EVENT ")) 00268 { 00269 gCoreContext->SendMessage(msg.mid(7) + 00270 QString(" SENDER %1").arg(gCoreContext->GetHostName())); 00271 return; 00272 } 00273 00274 if ((!msg.startsWith("SYSTEM_EVENT ")) && 00275 (!msg.startsWith("LOCAL_SYSTEM_EVENT "))) 00276 return; 00277 00278 QStringList tokens = msg.split(' ', QString::SkipEmptyParts); 00279 00280 // Return if this event is for another host 00281 if ((tokens.size() >= 4) && 00282 (tokens[2] == "HOST") && 00283 (tokens[3] != gCoreContext->GetHostName())) 00284 return; 00285 00286 QString cmd; 00287 00288 // See if this system has a command that runs for all system events 00289 cmd = gCoreContext->GetSetting("EventCmdAll"); 00290 if (!cmd.isEmpty()) 00291 { 00292 SubstituteMatches(tokens, cmd); 00293 00294 SystemEventThread *eventThread = new SystemEventThread(cmd); 00295 MThreadPool::globalInstance()->startReserved( 00296 eventThread, "SystemEvent"); 00297 } 00298 00299 // Check for an EventCmd for this particular event 00300 cmd = gCoreContext->GetSetting(EventNameToSetting(tokens[1])); 00301 if (!cmd.isEmpty()) 00302 { 00303 SubstituteMatches(tokens, cmd); 00304 00305 SystemEventThread *eventThread = 00306 new SystemEventThread(cmd, tokens[1]); 00307 MThreadPool::globalInstance()->startReserved( 00308 eventThread, "SystemEvent"); 00309 } 00310 } 00311 } 00312 00313 /****************************************************************************/ 00314 00321 void SendMythSystemRecEvent(const QString msg, const RecordingInfo *pginfo) 00322 { 00323 if (pginfo) 00324 gCoreContext->SendSystemEvent( 00325 QString("%1 CARDID %2 CHANID %3 STARTTIME %4 RECSTATUS %5") 00326 .arg(msg).arg(pginfo->GetCardID()) 00327 .arg(pginfo->GetChanID()) 00328 .arg(pginfo->GetRecordingStartTime(ISODate)) 00329 .arg(pginfo->GetRecordingStatus())); 00330 else 00331 LOG(VB_GENERAL, LOG_ERR, LOC + "SendMythSystemRecEvent() called with " 00332 "empty RecordingInfo"); 00333 } 00334 00341 void SendMythSystemPlayEvent(const QString msg, const ProgramInfo *pginfo) 00342 { 00343 if (pginfo) 00344 gCoreContext->SendSystemEvent( 00345 QString("%1 HOSTNAME %2 CHANID %3 STARTTIME %4") 00346 .arg(msg).arg(gCoreContext->GetHostName()) 00347 .arg(pginfo->GetChanID()) 00348 .arg(pginfo->GetRecordingStartTime(ISODate))); 00349 else 00350 LOG(VB_GENERAL, LOG_ERR, LOC + "SendMythSystemPlayEvent() called with " 00351 "empty ProgramInfo"); 00352 } 00353 00354 /****************************************************************************/ 00355 00367 MythSystemEventEditor::MythSystemEventEditor(MythScreenStack *parent, 00368 const char *name) 00369 : RawSettingsEditor(parent, name) 00370 { 00371 m_title = tr("System Event Command Editor"); 00372 00373 m_settings["EventCmdRecPending"] = tr("Recording pending"); 00374 m_settings["EventCmdRecStarted"] = tr("Recording started"); 00375 m_settings["EventCmdRecFinished"] = tr("Recording finished"); 00376 m_settings["EventCmdRecDeleted"] = tr("Recording deleted"); 00377 m_settings["EventCmdRecExpired"] = tr("Recording expired"); 00378 m_settings["EventCmdLivetvStarted"] = tr("LiveTV started"); 00379 m_settings["EventCmdPlayStarted"] = tr("Playback started"); 00380 m_settings["EventCmdPlayStopped"] = tr("Playback stopped"); 00381 m_settings["EventCmdPlayPaused"] = tr("Playback paused"); 00382 m_settings["EventCmdPlayUnpaused"] = tr("Playback unpaused"); 00383 m_settings["EventCmdPlayChanged"] = tr("Playback program changed"); 00384 m_settings["EventCmdMasterStarted"] = tr("Master backend started"); 00385 m_settings["EventCmdMasterShutdown"] = tr("Master backend shutdown"); 00386 m_settings["EventCmdClientConnected"] = tr("Client connected to master backend"); 00387 m_settings["EventCmdClientDisconnected"] = tr("Client disconnected from master backend"); 00388 m_settings["EventCmdSlaveConnected"] = tr("Slave backend connected to master"); 00389 m_settings["EventCmdSlaveDisconnected"] = tr("Slave backend disconnected from master"); 00390 m_settings["EventCmdNetCtrlConnected"] = tr("Network Control client connected"); 00391 m_settings["EventCmdNetCtrlDisconnected"] = tr("Network Control client disconnected"); 00392 m_settings["EventCmdMythfilldatabaseRan"] = tr("mythfilldatabase ran"); 00393 m_settings["EventCmdSchedulerRan"] = tr("Scheduler ran"); 00394 m_settings["EventCmdSettingsCacheCleared"] = tr("Settings cache cleared"); 00395 m_settings["EventCmdScreenType"] = tr("Screen created or destroyed"); 00396 m_settings["EventCmdKey01"] = tr("Keystroke event #1"); 00397 m_settings["EventCmdKey02"] = tr("Keystroke event #2"); 00398 m_settings["EventCmdKey03"] = tr("Keystroke event #3"); 00399 m_settings["EventCmdKey04"] = tr("Keystroke event #4"); 00400 m_settings["EventCmdKey05"] = tr("Keystroke event #5"); 00401 m_settings["EventCmdKey06"] = tr("Keystroke event #6"); 00402 m_settings["EventCmdKey07"] = tr("Keystroke event #7"); 00403 m_settings["EventCmdKey08"] = tr("Keystroke event #8"); 00404 m_settings["EventCmdKey09"] = tr("Keystroke event #9"); 00405 m_settings["EventCmdKey10"] = tr("Keystroke event #10"); 00406 m_settings["EventCmdAll"] = tr("Any event"); 00407 } 00408 00409 /* vim: set expandtab tabstop=4 shiftwidth=4: */
1.7.6.1