[mythtv] [PATCH] Updated System Status

Kevin Kuphal kuphal at dls.net
Fri Jul 23 10:22:13 EDT 2004


Kevin Kuphal wrote:

> Kevin Kuphal wrote:
>
>> This patch contains my initial revision of an updated system status 
>> screen.  It currently reports the mythfilldatabase status from the 
>> original screen as well as a basic tuner status list indicating the 
>> state of each tuner (watching tv, recording) and if recording, what 
>> it is currently recording.
>>
>> I plan to update this again in the near future with more detail and 
>> more items but wanted to get this to the list for 
>> comments/suggestions and any fixes for problems I might have made.
>>
>> Includes one diff against CVS and the two new files for mythfrontend
>
>
> I'm attaching new copies of this.  It was late last night and I 
> realized this morning I had an error in the mythfrontend.pro as well 
> as wasn't being very efficient about enumerating the tuners.  This 
> should be better
>
Sorry to keep posting over and over on this but here is an updated 
version with DVB status from the mythbackend PrintDVBStatus function 
replicated here.  I don't have a DVB card to test this with so if 
someone who does can verify it works...

Kevin
-------------- next part --------------
#ifndef STATUSBOX_H_
#define STATUSBOX_H_

#include "mythwidgets.h"
#include "mythdialogs.h"

class QIconView;
class QIconViewItem;
class QWidgetStack;
//class QListViewItem;
//class QLabel;
//class QProgressBar;
//class NuppelVideoPlayer;
//class RingBuffer;
//class QTimer;
//class ProgramInfo;

class StatusBox : public MythDialog
{
    Q_OBJECT
  public:
    StatusBox(MythMainWindow *parent, const char *name = 0);
   ~StatusBox(void);

  protected slots:
    void selectionChanged(QIconViewItem *);
    void clicked(QIconViewItem *);
    void returnPressed(QIconViewItem *);
   
  protected:
    void doListingsStatus();
    void doTunerStatus();
    void doDVBStatus();

  private:
    QIconView *status_list;
    QListView *tuner_list;
    QLabel *heading, *status_label, *helptext, *listing_label, *dvb_label;
    QGridLayout *grid;
    QWidgetStack *content_stack;

    // Add a QIconViewItem here for each category
    QIconViewItem *listings_item, *tuner_item, *dvb_item;
};

#endif
-------------- next part --------------
#include <qlayout.h>
#include <qiconview.h>
#include <qsqldatabase.h>
#include <qwidgetstack.h>

#include <unistd.h>

#include <iostream>
using namespace std;

#include "statusbox.h"
#include "mythcontext.h"
#include "remoteutil.h"
#include "programinfo.h"
#include "tv.h"

StatusBox::StatusBox(MythMainWindow *parent, const char *name)
         : MythDialog(parent, name)
{
    // It would be nice if some nice person with graphics skills
    // could make some nice icons here
    const QPixmap icon;

    grid = new QGridLayout(this, 3, 2, 10, 10);
    grid->setRowStretch(1,1);
    grid->setResizeMode(QLayout::FreeResize);

    heading = new QLabel(QString("System Status"), this);
    heading->setBackgroundOrigin(QWidget::AncestorOrigin);
    grid->addMultiCellWidget(heading, 0, 0, 0, 1, Qt::AlignLeft|Qt::AlignTop);

    helptext = new QLabel(QString("%1 %2").arg(screenwidth).arg(screenheight), this);
    helptext->setBackgroundOrigin(QWidget::AncestorOrigin);
    grid->addMultiCellWidget(helptext, 1, 1, 0, 1, Qt::AlignLeft|Qt::AlignTop);

    status_list = new QIconView(this, "status list");

    connect(status_list, SIGNAL(selectionChanged(QIconViewItem *)), this, SLOT(selectionChanged(QIconViewItem *)));
    connect(status_list, SIGNAL(clicked(QIconViewItem *)), this, SLOT(clicked(QIconViewItem *)));
    connect(status_list, SIGNAL(returnPressed(QIconViewItem *)), this, SLOT(returnPressed(QIconViewItem *)));

    status_list->setFixedHeight((screenheight/3)*2);
    status_list->setWordWrapIconText(false);
    status_list->setArrangement(QIconView::TopToBottom);
    status_list->setItemTextPos(QIconView::Right);
    status_list->setResizeMode(QIconView::Adjust);
    status_list->setSpacing(20);
    status_list->setMinimumWidth((int)((screenwidth-20)/4));
    status_list->setMaxItemWidth(status_list->minimumWidth());

    listings_item = new QIconViewItem(status_list, "Listings Status");
    listings_item->setPixmap(icon);

    status_list->setSelected(listings_item, true);
    status_list->setFocus();

    tuner_item = new QIconViewItem(status_list, "Tuner Status");
    tuner_item->setPixmap(icon);

#if USING_DVB
    dvb_item = new QIconViewItem(status_list, "DVB Status");
    dvb_item->setPixmap(icon);
#endif

    grid->addWidget(status_list, 2, 0, Qt::AlignLeft|Qt::AlignBottom);

    // Create the stack for the content pane
    // If you are adding new content, make sure you define your widget globally
    // and add it to the content_stack.  Then modify the clicked function
    // to raise your widget as needed
    content_stack = new QWidgetStack(this, "content_stack");
    content_stack->setFixedHeight((screenheight/3)*2);
    content_stack->setFrameShape(status_list->frameShape());
    content_stack->setFrameShadow(status_list->frameShadow());
    content_stack->setLineWidth(status_list->lineWidth());
    content_stack->setPaletteBackgroundColor(status_list->paletteBackgroundColor());
    content_stack->setPaletteForegroundColor(status_list->paletteForegroundColor());
    content_stack->setMinimumWidth((int)(((screenwidth-20)/4)*3)-20);
    content_stack->setMargin(10);

    // Display object for Listing Status
    listing_label = new QLabel(this, "listing_label");
    listing_label->setAlignment(Qt::AlignTop|Qt::WordBreak);
    content_stack->addWidget(listing_label);

    // Display object for Tuner Status
    tuner_list = new QListView(this, "tuner list");
    tuner_list->addColumn("Tuner");
    tuner_list->addColumn("Status");
    tuner_list->setAllColumnsShowFocus(true);
    tuner_list->setColumnAlignment(0, Qt::AlignTop|Qt::AlignCenter);
    tuner_list->setColumnAlignment(1, Qt::AlignTop|Qt::AlignLeft);
    content_stack->addWidget(tuner_list);

    dvb_label = new QLabel(this, "listing_label");
    dvb_label->setAlignment(Qt::AlignTop|Qt::WordBreak);
    content_stack->addWidget(dvb_label);

    grid->addWidget(content_stack, 2, 1, Qt::AlignTop|Qt::AlignLeft);
}

void StatusBox::selectionChanged(QIconViewItem *item)
{
    if (item == listings_item)
        helptext->setText(QString("Show the status of mythfilldatabase"));
    if (item == tuner_item)
        helptext->setText(QString("Show the status of tuner cards"));
    if (item == dvb_item)
        helptext->setText(QString("Show the status of DVB tuner cards"));
}

void StatusBox::clicked(QIconViewItem *item)
{
    if (item == listings_item)
    {
        content_stack->raiseWidget(listing_label);
        doListingsStatus();
    }
    if (item == tuner_item)
    {
        content_stack->raiseWidget(tuner_list);
        doTunerStatus();
    }

    if (item == dvb_item)
    {
        content_stack->raiseWidget(dvb_label);
        doDVBStatus();
    }
 
    status_list->setFocus();
}

void StatusBox::returnPressed(QIconViewItem *item)
{
    clicked(item);
}

void StatusBox::doListingsStatus()
{
    QString mfdLastRunStart, mfdLastRunEnd, mfdLastRunStatus, Status;
    QString querytext, DataDirectMessage;
    int DaysOfData;
    QDateTime qdtNow, GuideDataThrough;
    QSqlDatabase *db = QSqlDatabase::database();

    qdtNow = QDateTime::currentDateTime();
    querytext = QString("SELECT max(endtime) FROM program;");

    QSqlQuery query = db->exec(querytext);

    if (query.isActive() && query.numRowsAffected())
    {
        query.next();
        GuideDataThrough = QDateTime::fromString(query.value(0).toString(),
                                                 Qt::ISODate);
    }

    mfdLastRunStart = gContext->GetSetting("mythfilldatabaseLastRunStart");
    mfdLastRunEnd = gContext->GetSetting("mythfilldatabaseLastRunEnd");
    mfdLastRunStatus = gContext->GetSetting("mythfilldatabaseLastRunStatus");
    DataDirectMessage = gContext->GetSetting("DataDirectMessage");

    Status = QObject::tr("Myth version:") + " " + MYTH_BINARY_VERSION + "\n";

    Status += QObject::tr("Last mythfilldatabase guide update:");
    Status += "\n   ";
    Status += QObject::tr("Started:   ");
    Status += mfdLastRunStart;
    if (mfdLastRunEnd > mfdLastRunStart)  //if end < start, it's still running.
    {
        Status += "\n   ";
        Status += QObject::tr("Finished: ");
        Status += mfdLastRunEnd;
    }

    Status += "\n   ";
    Status += QObject::tr("Result: ");
    Status += mfdLastRunStatus;

    DaysOfData = qdtNow.daysTo(GuideDataThrough);

    if (GuideDataThrough.isNull())
    {
        Status += "\n\n";
        Status += QObject::tr("There's no guide data available! ");
        Status += QObject::tr("Have you run mythfilldatabase?");
        Status += "\n";
    }
    else
    {
        Status += "\n\n";
        Status += QObject::tr("There is guide data until ");
        Status += QDateTime(GuideDataThrough).toString("yyyy-MM-dd hh:mm");

        if (DaysOfData > 0)
        {
            Status += QString("\n(%1 ").arg(DaysOfData);
            if (DaysOfData >1)
                Status += QObject::tr("days");
            else
                Status += QObject::tr("day");
            Status += ").";
        }
        else
            Status += ".";
    }

    if (DaysOfData <= 3)
    {
        Status += "\n";
        Status += QObject::tr("WARNING: is mythfilldatabase running?");
    }

    if (!DataDirectMessage.isNull())
    {
        Status += "\n";
        Status += QObject::tr("DataDirect Status: \n");
        Status += DataDirectMessage;
    }
   
    listing_label->setText(Status);
}

void StatusBox::doTunerStatus()
{
    QString querytext = QString("SELECT cardid FROM capturecard;");
    QSqlDatabase *db = QSqlDatabase::database();
    QSqlQuery query = db->exec(querytext);
    if (query.isActive() && query.numRowsAffected())
    {
        tuner_list->clear();
        while(query.next())
        {
            int cardid = query.value(0).toInt();

            QString cmd = QString("QUERY_REMOTEENCODER %1").arg(cardid);
            QStringList strlist = cmd;
            strlist << "GET_STATE";

            gContext->SendReceiveStringList(strlist);
  
            QString Status = QString("Tuner ");
            if (strlist[0].toInt()==kState_WatchingLiveTV)
                Status += "is watching live TV";
            else if (strlist[0].toInt()==kState_RecordingOnly ||
                     strlist[0].toInt()==kState_WatchingRecording)
                Status += "is recording";
            else 
                Status += "is not recording";

            if (strlist[0].toInt()==kState_RecordingOnly)
            {
                strlist = QString("QUERY_RECORDER %1").arg(cardid);
                strlist << "GET_RECORDING";
                gContext->SendReceiveStringList(strlist);
                ProgramInfo *proginfo = new ProgramInfo;
                proginfo->FromStringList(strlist, 0);
                Status += "\n";
                Status += proginfo->title;
                Status += " - ";
                Status += proginfo->subtitle;
            }

            QListViewItem *tuner_item = new QListViewItem(tuner_list, QString::number(cardid), Status);
            tuner_item->setMultiLinesEnabled(true);
        }
    }
}

void StatusBox::doDVBStatus(void)
{
    QString querytext;

    bool doneAnything = false;
    
    QString Status = QString("Details of DVB error statistics for last 48 hours:\n");

    QString outerqry =
        "SELECT starttime,endtime FROM recorded "
        "WHERE starttime >= DATE_SUB(NOW(), INTERVAL 48 HOUR) "
        "ORDER BY starttime;";

    QSqlDatabase *db = QSqlDatabase::database();
    QSqlQuery oquery = db->exec(outerqry);

    if (oquery.isActive() && oquery.numRowsAffected())
    {
        querytext = QString("SELECT cardid,"
                            "max(fe_ss),min(fe_ss),avg(fe_ss),"
                            "max(fe_snr),min(fe_snr),avg(fe_snr),"
                            "max(fe_ber),min(fe_ber),avg(fe_ber),"
                            "max(fe_unc),min(fe_unc),avg(fe_unc),"
                            "max(myth_cont),max(myth_over),max(myth_pkts) "
                            "FROM dvb_signal_quality "
                            "WHERE sampletime BETWEEN ? AND ? "
                            "GROUP BY cardid");

        QSqlQuery query = db->exec(NULL);
        query.prepare(querytext);
        
        while (oquery.next())
        {
            QDateTime t_start = oquery.value(0).toDateTime();
            QDateTime t_end = oquery.value(1).toDateTime();

            query.bindValue(0, t_start);
            query.bindValue(1, t_end);

            if (!query.exec())
                cout << query.lastError().databaseText() << "\r\n" 
                     << query.lastError().driverText() << "\r\n";
            
            if (query.isActive() && query.numRowsAffected())
            {
                Status += QString("Recording period from %1 to %2\n").arg(t_start.toString()).arg(t_end.toString());
                
                while (query.next())
                {
		    Status += QString("Encoder %1 Min SNR: %2 Avg SNR: %3 Min BER %4 Avg BER %5 Cont Errs: %6 Overflows: %7\n")
                              .arg(query.value(0).toInt())
                              .arg(query.value(5).toInt())
                              .arg(query.value(6).toInt())
                              .arg(query.value(8).toInt())
                              .arg(query.value(9).toInt())
                              .arg(query.value(13).toInt())
                              .arg(query.value(14).toInt());

                    doneAnything = true;
                }
            }
        }
    }

    if (!doneAnything)
    {
        Status += QString("There is no DVB signal quality data available to display.\n");
    }

    dvb_label->setText(Status);
}

StatusBox::~StatusBox(void)
{
}



More information about the mythtv-dev mailing list