Esempio n. 1
0
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();
}
Esempio n. 2
0
/** \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");
        }
    }
}
Esempio n. 3
0
    /** \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));
    }
Esempio n. 4
0
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);
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
/** \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()));
}