void ProgramInfoUpdater::run(void) { // we don't need instant updates allow a few to queue up // if they come in quick succession, this allows multiple // updates to be consolidated into one update... usleep(50 * 1000); QMutexLocker locker(&lock); isQueued = false; // send adds and deletes in the order they were queued vector<PIKeyAction>::iterator ita = needsAddDelete.begin(); for (; ita != needsAddDelete.end(); ++ita) { if (kPIAdd != (*ita).action && kPIDelete != (*ita).action) continue; QString type = (kPIAdd == (*ita).action) ? "ADD" : "DELETE"; QString msg = QString("RECORDING_LIST_CHANGE %1 %2 %3") .arg(type).arg((*ita).chanid) .arg((*ita).recstartts.toString(Qt::ISODate)); RemoteSendMessage(msg); } needsAddDelete.clear(); // Send updates in any old order, we just need // one per updated ProgramInfo. QHash<PIKey,PIKeyData>::iterator itu = needsUpdate.begin(); for (; itu != needsUpdate.end(); ++itu) { QString msg; if (kPIUpdateFileSize == (*itu).action) { msg = QString("UPDATE_FILE_SIZE %1 %2 %3") .arg(itu.key().chanid) .arg(itu.key().recstartts.toString(Qt::ISODate)) .arg((*itu).filesize); } else { msg = QString("MASTER_UPDATE_PROG_INFO %1 %2") .arg(itu.key().chanid) .arg(itu.key().recstartts.toString(Qt::ISODate)); } RemoteSendMessage(msg); } needsUpdate.clear(); }
/** \fn MythSystemEventHandler::customEvent(QEvent *e) * \brief Custom Event handler for receiving and processing System Events * \sa MythSystemEventHandler::SubstituteMatches(const QStringList &tokens, QString &command) * MythSystemEventHandler::EventNameToSetting(const QString &name) * * This function listens for SYSTEM_EVENT messages and fires off any * necessary event handler commands. In addition to SYSTEM_EVENT messages, * this code also forwards GLOBAL_SYSTEM_EVENT which may have been sent * by the local system via code that does not have access to the master * backend connection to send events on its own. One example is the * code that sends KEY_xx system events. * * \param e Pointer to QEvent containing event to handle */ void MythSystemEventHandler::customEvent(QEvent *e) { if ((MythEvent::Type)(e->type()) == MythEvent::MythEventMessage) { MythEvent *me = (MythEvent *)e; QString msg = me->Message().simplified(); if (msg == "CLEAR_SETTINGS_CACHE") msg = "SYSTEM_EVENT SETTINGS_CACHE_CLEARED"; // Listen for any GLOBAL_SYSTEM_EVENT messages and resend to // the master backend as regular SYSTEM_EVENT messages. if (msg.startsWith("GLOBAL_SYSTEM_EVENT ")) { RemoteSendMessage(msg.mid(7) + QString(" SENDER %1") .arg(gCoreContext->GetHostName())); return; } if ((!msg.startsWith("SYSTEM_EVENT ")) && (!msg.startsWith("LOCAL_SYSTEM_EVENT "))) return; QStringList tokens = msg.split(' ', QString::SkipEmptyParts); // Return if this event is for another host if ((tokens.size() >= 4) && (tokens[2] == "HOST") && (tokens[3] != gCoreContext->GetHostName())) return; QString cmd; // See if this system has a command that runs for all system events cmd = gCoreContext->GetSetting("EventCmdAll"); if (!cmd.isEmpty()) { SubstituteMatches(tokens, cmd); SystemEventThread *eventThread = new SystemEventThread(cmd); MThreadPool::globalInstance()->startReserved( eventThread, "SystemEvent"); } // Check for an EventCmd for this particular event cmd = gCoreContext->GetSetting(EventNameToSetting(tokens[1])); if (!cmd.isEmpty()) { SubstituteMatches(tokens, cmd); SystemEventThread *eventThread = new SystemEventThread(cmd, tokens[1]); MThreadPool::globalInstance()->startReserved( eventThread, "SystemEvent"); } } }
/** \fn SystemEventThread::run() * \brief Runs the System Event handler command * * Overrides QRunnable::run() */ void run(void) { uint flags = kMSDontBlockInputDevs; m_event.detach(); m_command.detach(); uint result = myth_system(m_command, flags); if (result != GENERIC_EXIT_OK) LOG(VB_GENERAL, LOG_WARNING, LOC + QString("Command '%1' returned %2") .arg(m_command).arg(result)); if (m_event.isEmpty()) return; RemoteSendMessage(QString("SYSTEM_EVENT_RESULT %1 SENDER %2 RESULT %3") .arg(m_event).arg(gCoreContext->GetHostName()) .arg(result)); }
void ExitPrompter::quit() { // If the backend was stopped restart it here if (gCoreContext->GetSetting("AutoRestartBackend") == "1") { QString commandString = gCoreContext->GetSetting("BackendStartCommand"); if (!commandString.isEmpty()) { VERBOSE(VB_IMPORTANT, "backendrestart"+commandString); myth_system(commandString); } } else { // No need to run this if the backend has just restarted if (gCoreContext->BackendIsRunning()) { RemoteSendMessage("CLEAR_SETTINGS_CACHE"); } } qApp->exit(GENERIC_EXIT_OK); }
bool WelcomeDialog::keyPressEvent(QKeyEvent *event) { if (GetFocusWidget()->keyPressEvent(event)) return true; bool handled = false; QStringList actions; handled = GetMythMainWindow()->TranslateKeyPress("Welcome", event, actions); for (int i = 0; i < actions.size() && !handled; i++) { QString action = actions[i]; handled = true; if (action == "ESCAPE") { return true; // eat escape key } else if (action == "MENU") { showMenu(); } else if (action == "NEXTVIEW") { Close(); } else if (action == "INFO") { MythWelcomeSettings settings; if (kDialogCodeAccepted == settings.exec()) { RemoteSendMessage("CLEAR_SETTINGS_CACHE"); updateStatus(); updateScreen(); m_dateFormat = gCoreContext->GetSetting("MythWelcomeDateFormat", "dddd\\ndd MMM yyyy"); m_dateFormat.replace("\\n", "\n"); } } else if (action == "SHOWSETTINGS") { MythShutdownSettings settings; if (kDialogCodeAccepted == settings.exec()) RemoteSendMessage("CLEAR_SETTINGS_CACHE"); } else if (action == "0") { QString mythshutdown_status = m_installDir + "/bin/mythshutdown --status 0"; QString mythshutdown_unlock = m_installDir + "/bin/mythshutdown --unlock"; QString mythshutdown_lock = m_installDir + "/bin/mythshutdown --lock"; uint statusCode = myth_system(mythshutdown_status); // is shutdown locked by a user if (!(statusCode & 0xFF00) && statusCode & 16) { myth_system(mythshutdown_unlock); } else { myth_system(mythshutdown_lock); } updateStatusMessage(); updateScreen(); } else if (action == "STARTXTERM") { QString cmd = gCoreContext->GetSetting("MythShutdownXTermCmd", ""); if (!cmd.isEmpty()) myth_system(cmd); } else if (action == "STARTSETUP") { QString mythtv_setup = m_installDir + "/bin/mythtv-setup"; myth_system(mythtv_setup); } else handled = false; } if (!handled && MythScreenType::keyPressEvent(event)) handled = true; return handled; }
int handle_command(const MythCommandLineParser &cmdline) { QString eventString = cmdline.GetEventString(); if (!eventString.isEmpty()) { if (gCoreContext->ConnectToMasterServer()) { if (eventString.startsWith("SYSTEM_EVENT")) { eventString += QString(" SENDER %1") .arg(gCoreContext->GetHostName()); } RemoteSendMessage(eventString); return GENERIC_EXIT_OK; } return GENERIC_EXIT_NO_MYTHCONTEXT; } if (cmdline.WantUPnPRebuild()) { VERBOSE(VB_GENERAL, "Rebuilding UPNP Media Map is no longer supported. Rescan videos using MythVideo."); return GENERIC_EXIT_OK; } if (cmdline.SetVerbose()) { if (gCoreContext->ConnectToMasterServer()) { QString message = "SET_VERBOSE "; message += cmdline.GetNewVerbose(); RemoteSendMessage(message); VERBOSE(VB_IMPORTANT, QString("Sent '%1' message").arg(message)); return GENERIC_EXIT_OK; } else { VERBOSE(VB_IMPORTANT, "Unable to connect to backend, verbose level unchanged "); return GENERIC_EXIT_CONNECT_ERROR; } } if (cmdline.ClearSettingsCache()) { if (gCoreContext->ConnectToMasterServer()) { RemoteSendMessage("CLEAR_SETTINGS_CACHE"); VERBOSE(VB_IMPORTANT, "Sent CLEAR_SETTINGS_CACHE message"); return GENERIC_EXIT_OK; } else { VERBOSE(VB_IMPORTANT, "Unable to connect to backend, settings " "cache will not be cleared."); return GENERIC_EXIT_CONNECT_ERROR; } } if (cmdline.IsPrintScheduleEnabled() || cmdline.IsTestSchedulerEnabled()) { sched = new Scheduler(false, &tvList); if (!cmdline.IsTestSchedulerEnabled() && gCoreContext->ConnectToMasterServer()) { cout << "Retrieving Schedule from Master backend.\n"; sched->FillRecordListFromMaster(); } else { cout << "Calculating Schedule from database.\n" << "Inputs, Card IDs, and Conflict info may be invalid " "if you have multiple tuners.\n"; sched->FillRecordListFromDB(); } print_verbose_messages |= VB_SCHEDULE; sched->PrintList(true); return GENERIC_EXIT_OK; } if (cmdline.Reschedule()) { bool ok = false; if (gCoreContext->ConnectToMasterServer()) { VERBOSE(VB_IMPORTANT, "Connected to master for reschedule"); ScheduledRecording::signalChange(-1); ok = true; } else VERBOSE(VB_IMPORTANT, "Cannot connect to master for reschedule"); return (ok) ? GENERIC_EXIT_OK : GENERIC_EXIT_CONNECT_ERROR; } if (cmdline.ScanVideos()) { bool ok = false; if (gCoreContext->ConnectToMasterServer()) { gCoreContext->SendReceiveStringList(QStringList() << "SCAN_VIDEOS"); VERBOSE(VB_IMPORTANT, "Requested video scan"); ok = true; } else VERBOSE(VB_IMPORTANT, "Cannot connect to master for video scan"); return (ok) ? GENERIC_EXIT_OK : GENERIC_EXIT_CONNECT_ERROR; } if (!cmdline.GetPrintExpire().isEmpty()) { expirer = new AutoExpire(); expirer->PrintExpireList(cmdline.GetPrintExpire()); return GENERIC_EXIT_OK; } // This should never actually be reached.. return GENERIC_EXIT_OK; }
int handle_command(const MythBackendCommandLineParser &cmdline) { QString eventString; if (cmdline.toBool("event")) eventString = cmdline.toString("event"); else if (cmdline.toBool("systemevent")) eventString = "SYSTEM_EVENT " + cmdline.toString("systemevent") + QString(" SENDER %1").arg(gCoreContext->GetHostName()); if (!eventString.isEmpty()) { if (gCoreContext->ConnectToMasterServer()) { RemoteSendMessage(eventString); return GENERIC_EXIT_OK; } return GENERIC_EXIT_NO_MYTHCONTEXT; } if (cmdline.toBool("setverbose")) { if (gCoreContext->ConnectToMasterServer()) { QString message = "SET_VERBOSE "; message += cmdline.toString("setverbose"); RemoteSendMessage(message); LOG(VB_GENERAL, LOG_INFO, QString("Sent '%1' message").arg(message)); return GENERIC_EXIT_OK; } else { LOG(VB_GENERAL, LOG_ERR, "Unable to connect to backend, verbose level unchanged "); return GENERIC_EXIT_CONNECT_ERROR; } } if (cmdline.toBool("clearcache")) { if (gCoreContext->ConnectToMasterServer()) { RemoteSendMessage("CLEAR_SETTINGS_CACHE"); LOG(VB_GENERAL, LOG_INFO, "Sent CLEAR_SETTINGS_CACHE message"); return GENERIC_EXIT_OK; } else { LOG(VB_GENERAL, LOG_ERR, "Unable to connect to backend, settings " "cache will not be cleared."); return GENERIC_EXIT_CONNECT_ERROR; } } if (cmdline.toBool("printsched") || cmdline.toBool("testsched")) { sched = new Scheduler(false, &tvList); if (!cmdline.toBool("testsched") && gCoreContext->ConnectToMasterServer()) { cout << "Retrieving Schedule from Master backend.\n"; sched->FillRecordListFromMaster(); } else { cout << "Calculating Schedule from database.\n" << "Inputs, Card IDs, and Conflict info may be invalid " "if you have multiple tuners.\n"; sched->FillRecordListFromDB(); } verboseMask |= VB_SCHEDULE; sched->PrintList(true); return GENERIC_EXIT_OK; } if (cmdline.toBool("resched")) { bool ok = false; if (gCoreContext->ConnectToMasterServer()) { LOG(VB_GENERAL, LOG_INFO, "Connected to master for reschedule"); ScheduledRecording::signalChange(-1); ok = true; } else LOG(VB_GENERAL, LOG_ERR, "Cannot connect to master for reschedule"); return (ok) ? GENERIC_EXIT_OK : GENERIC_EXIT_CONNECT_ERROR; } if (cmdline.toBool("scanvideos")) { bool ok = false; if (gCoreContext->ConnectToMasterServer()) { gCoreContext->SendReceiveStringList(QStringList() << "SCAN_VIDEOS"); LOG(VB_GENERAL, LOG_INFO, "Requested video scan"); ok = true; } else LOG(VB_GENERAL, LOG_ERR, "Cannot connect to master for video scan"); return (ok) ? GENERIC_EXIT_OK : GENERIC_EXIT_CONNECT_ERROR; } if (!cmdline.toBool("printexpire")) { expirer = new AutoExpire(); expirer->PrintExpireList(cmdline.toString("printexpire")); return GENERIC_EXIT_OK; } // This should never actually be reached.. return GENERIC_EXIT_OK; }
/** \fn SendMythSystemEvent(const QString msg) * \brief Send the given message as a System Event * \param msg Const QString to send as a System Event */ void SendMythSystemEvent(const QString msg) { RemoteSendMessage(QString("SYSTEM_EVENT %1 SENDER %2") .arg(msg).arg(gCoreContext->GetHostName())); }