76 changes: 76 additions & 0 deletions mythtv/programs/mythutil/jobutils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// C++ includes
#include <iostream>

// libmyth* includes
#include "exitcodes.h"
#include "jobqueue.h"
#include "mythlogging.h"

// Local includes
#include "mythutil.h"

static int QueueJob(const MythUtilCommandLineParser &cmdline)
{
ProgramInfo pginfo;
if (!GetProgramInfo(cmdline, pginfo))
return GENERIC_EXIT_NO_RECORDING_DATA;

bool rebuildSeektable = false;
int jobType = JOB_NONE;

if (cmdline.toString("queuejob") == "transcode")
jobType = JOB_TRANSCODE;
else if (cmdline.toString("queuejob") == "commflag")
jobType = JOB_COMMFLAG;
else if (cmdline.toString("queuejob") == "rebuild")
{
jobType = JOB_COMMFLAG;
rebuildSeektable = true;
}
else if (cmdline.toString("queuejob") == "metadata")
jobType = JOB_METADATA;
else if (cmdline.toString("queuejob") == "userjob1")
jobType = JOB_USERJOB1;
else if (cmdline.toString("queuejob") == "userjob2")
jobType = JOB_USERJOB1;
else if (cmdline.toString("queuejob") == "userjob4")
jobType = JOB_USERJOB1;
else if (cmdline.toString("queuejob") == "userjob4")
jobType = JOB_USERJOB1;
else if (cmdline.toInt("queuejob") > 0)
jobType = cmdline.toInt("queuejob");

if (jobType == JOB_NONE)
{
LOG(VB_GENERAL, LOG_ERR,
"Error, invalid job type given with queuejob option");
return GENERIC_EXIT_INVALID_CMDLINE;
}

bool result = JobQueue::QueueJob(jobType,
pginfo.GetChanID(), pginfo.GetRecordingStartTime(), "", "", "",
rebuildSeektable, JOB_QUEUED, QDateTime());

if (result)
{
QString tmp = QString("%1 Job Queued for chanid %2 @ %3")
.arg(cmdline.toString("queuejob"))
.arg(pginfo.GetChanID())
.arg(pginfo.GetRecordingStartTime().toString());
cerr << tmp.toLocal8Bit().constData() << endl;
return GENERIC_EXIT_OK;
}

QString tmp = QString("Error queueing job for chanid %1 @ %2")
.arg(pginfo.GetChanID())
.arg(pginfo.GetRecordingStartTime().toString());
cerr << tmp.toLocal8Bit().constData() << endl;
return GENERIC_EXIT_DB_ERROR;
}

void registerJobUtils(UtilMap &utilMap)
{
utilMap["queuejob"] = &QueueJob;
}

/* vim: set expandtab tabstop=4 shiftwidth=4: */
4 changes: 4 additions & 0 deletions mythtv/programs/mythutil/jobutils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#include "mythutil.h"

void registerJobUtils(UtilMap &utilMap);

89 changes: 89 additions & 0 deletions mythtv/programs/mythutil/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Qt includes
#include <QApplication>

// libmyth* includes
#include "exitcodes.h"
#include "mythcontext.h"
#include "mythversion.h"
#include "mythlogging.h"

// Local includes
#include "mythutil.h"
#include "commandlineparser.h"
#include "backendutils.h"
#include "fileutils.h"
#include "jobutils.h"
#include "markuputils.h"
#include "messageutils.h"


int main(int argc, char *argv[])
{
MythUtilCommandLineParser cmdline;
if (!cmdline.Parse(argc, argv))
{
cmdline.PrintHelp();
return GENERIC_EXIT_INVALID_CMDLINE;
}

if (cmdline.toBool("showhelp"))
{
cmdline.PrintHelp();
return GENERIC_EXIT_OK;
}

if (cmdline.toBool("showversion"))
{
cmdline.PrintVersion();
return GENERIC_EXIT_OK;
}

QApplication a(argc, argv);
QCoreApplication::setApplicationName(MYTH_APPNAME_MYTHUTIL);

int retval;
if ((retval = cmdline.ConfigureLogging()) != GENERIC_EXIT_OK)
return retval;

gContext = new MythContext(MYTH_BINARY_VERSION);
if (!gContext->Init(false))
{
LOG(VB_GENERAL, LOG_ERR, "Failed to init MythContext, exiting.");
return GENERIC_EXIT_NO_MYTHCONTEXT;
}

cmdline.ApplySettingsOverride();

UtilMap utilMap;

registerBackendUtils(utilMap);
registerFileUtils(utilMap);
registerJobUtils(utilMap);
registerMarkupUtils(utilMap);
registerMessageUtils(utilMap);

bool cmdFound = false;
int cmdResult = GENERIC_EXIT_OK;
UtilMap::iterator i;
for (i = utilMap.begin(); i != utilMap.end(); i++)
{
if (cmdline.toBool(i.key()))
{
cmdResult = (i.value())(cmdline);
cmdFound = true;
break;
}
}

if(!cmdFound)
{
cmdline.PrintHelp();
cmdResult = GENERIC_EXIT_INVALID_CMDLINE;
}

delete gContext;

return cmdResult;
}

/* vim: set expandtab tabstop=4 shiftwidth=4: */
180 changes: 180 additions & 0 deletions mythtv/programs/mythutil/markuputils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
// C++ includes
#include <iostream>

// libmyth* includes
#include "exitcodes.h"
#include "mythlogging.h"

// Local includes
#include "mythutil.h"

static int GetMarkupList(const MythUtilCommandLineParser &cmdline,
const QString type)
{
ProgramInfo pginfo;
if (!GetProgramInfo(cmdline, pginfo))
return GENERIC_EXIT_NO_RECORDING_DATA;

frm_dir_map_t cutlist;
frm_dir_map_t::const_iterator it;
QString result;

if (type == "cutlist")
pginfo.QueryCutList(cutlist);
else
pginfo.QueryCommBreakList(cutlist);

uint64_t lastStart = 0;
for (it = cutlist.begin(); it != cutlist.end(); ++it)
{
if ((*it == MARK_COMM_START) ||
(*it == MARK_CUT_START))
{
if (!result.isEmpty())
result += ",";
lastStart = it.key();
result += QString("%1-").arg(lastStart);
}
else
{
if (result.isEmpty())
result += "0-";
result += QString("%1").arg(it.key());
}
}

if (result.endsWith('-'))
{
uint64_t lastFrame = pginfo.QueryLastFrameInPosMap() + 60;
if (lastFrame > lastStart)
result += QString("%1").arg(lastFrame);
}

if (type == "cutlist")
cout << QString("Cutlist: %1\n").arg(result).toLocal8Bit().constData();
else
{
cout << QString("Commercial Skip List: %1\n")
.arg(result).toLocal8Bit().constData();
}

return GENERIC_EXIT_OK;
}

static int SetMarkupList(const MythUtilCommandLineParser &cmdline,
const QString &type, QString newList)
{
ProgramInfo pginfo;
if (!GetProgramInfo(cmdline, pginfo))
return GENERIC_EXIT_NO_RECORDING_DATA;

bool isCutlist = (type == "cutlist");
frm_dir_map_t markuplist;

newList.replace(QRegExp(" "), "");

QStringList tokens = newList.split(",", QString::SkipEmptyParts);

if (newList.isEmpty())
newList = "(EMPTY)";

for (int i = 0; i < tokens.size(); i++)
{
QStringList cutpair = tokens[i].split("-", QString::SkipEmptyParts);
if (isCutlist)
{
markuplist[cutpair[0].toInt()] = MARK_CUT_START;
markuplist[cutpair[1].toInt()] = MARK_CUT_END;
}
else
{
markuplist[cutpair[0].toInt()] = MARK_COMM_START;
markuplist[cutpair[1].toInt()] = MARK_COMM_END;
}
}

if (isCutlist)
{
pginfo.SaveCutList(markuplist);
cout << QString("Cutlist set to: %1\n")
.arg(newList).toLocal8Bit().constData();
LOG(VB_GENERAL, LOG_NOTICE, QString("Cutlist set to: %1").arg(newList));
}
else
{
pginfo.SaveCommBreakList(markuplist);
cout << QString("Commercial Skip List set to: %1\n")
.arg(newList).toLocal8Bit().constData();
LOG(VB_GENERAL, LOG_NOTICE, QString("Commercial Skip List set to: %1").arg(newList));
}

return GENERIC_EXIT_OK;
}

static int GetCutList(const MythUtilCommandLineParser &cmdline)
{
return GetMarkupList(cmdline, "cutlist");
}

static int SetCutList(const MythUtilCommandLineParser &cmdline)
{
return SetMarkupList(cmdline, QString("cutlist"),
cmdline.toString("setcutlist"));
}

static int ClearCutList(const MythUtilCommandLineParser &cmdline)
{
return SetMarkupList(cmdline, QString("cutlist"), QString(""));
}

static int CopySkipListToCutList(const MythUtilCommandLineParser &cmdline)
{
ProgramInfo pginfo;
if (!GetProgramInfo(cmdline, pginfo))
return GENERIC_EXIT_NO_RECORDING_DATA;

frm_dir_map_t cutlist;
frm_dir_map_t::const_iterator it;

pginfo.QueryCommBreakList(cutlist);
for (it = cutlist.begin(); it != cutlist.end(); ++it)
if (*it == MARK_COMM_START)
cutlist[it.key()] = MARK_CUT_START;
else
cutlist[it.key()] = MARK_CUT_END;
pginfo.SaveCutList(cutlist);

cout << QString("Cutlist copied to Commercial Skip List\n")
.toLocal8Bit().constData();

return GENERIC_EXIT_OK;
}

static int GetSkipList(const MythUtilCommandLineParser &cmdline)
{
return GetMarkupList(cmdline, "skiplist");
}

static int SetSkipList(const MythUtilCommandLineParser &cmdline)
{
return SetMarkupList(cmdline, QString("skiplist"),
cmdline.toString("setskiplist"));
}

static int ClearSkipList(const MythUtilCommandLineParser &cmdline)
{
return SetMarkupList(cmdline, QString("skiplist"), QString(""));
}

void registerMarkupUtils(UtilMap &utilMap)
{
utilMap["gencutlist"] = &CopySkipListToCutList;
utilMap["getcutlist"] = &GetCutList;
utilMap["setcutlist"] = &SetCutList;
utilMap["clearcutlist"] = &ClearCutList;
utilMap["getskiplist"] = &GetSkipList;
utilMap["setskiplist"] = &SetSkipList;
utilMap["clearskiplist"] = &ClearSkipList;
}

/* vim: set expandtab tabstop=4 shiftwidth=4: */
4 changes: 4 additions & 0 deletions mythtv/programs/mythutil/markuputils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#include "mythutil.h"

void registerMarkupUtils(UtilMap &utilMap);

86 changes: 86 additions & 0 deletions mythtv/programs/mythutil/messageutils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// C++ includes
#include <iostream>

// Qt headers
#include <QHostAddress>
#include <QUdpSocket>
#include <QString>
#include <QFile>

// libmyth* includes
#include "compat.h"
#include "exitcodes.h"
#include "mythlogging.h"

// Local includes
#include "mythutil.h"

const QString kMessage =
"<mythmessage version=\"1\">\n"
" <text>%message_text%</text>\n"
"</mythmessage>";

static int PrintTemplate(const MythUtilCommandLineParser &cmdline)
{
cerr << kMessage.toLocal8Bit().constData() << endl;
return GENERIC_EXIT_OK;
}

static int SendMessage(const MythUtilCommandLineParser &cmdline)
{
QHostAddress address = QHostAddress::Broadcast;
unsigned short port = 6948;

QString message = kMessage;

if (cmdline.toBool("udpport"))
port = (unsigned short)cmdline.toUInt("udpport");
if (cmdline.toBool("bcastaddr"))
address.setAddress(cmdline.toString("bcastaddr"));

QMap<QString,QString>::const_iterator i;
QMap<QString,QString> extras = cmdline.GetExtra();
for (i = extras.begin(); i != extras.end(); ++i)
{
QString name = i.key();
QString value = i.value();

name.replace("--", "");
cerr << "name: " << name.toLocal8Bit().constData()
<< " -- value: " << value.toLocal8Bit().constData() << endl;

name.append("%");
name.prepend("%");
message.replace(name, value);
}

cout << "output:\n" << message.toLocal8Bit().constData() << endl;

QUdpSocket *sock = new QUdpSocket();
QByteArray utf8 = message.toUtf8();

int result = GENERIC_EXIT_OK;
if (sock->writeDatagram(utf8, address, port) < 0)
{
cout << "Failed to send UDP/XML packet" << endl;
result = GENERIC_EXIT_NOT_OK;
}
else
{
cout << "Sent UDP/XML packet to IP "
<< address.toString().toLocal8Bit().constData()
<< " and port: " << port << endl;
}

sock->deleteLater();

return result;
}

void registerMessageUtils(UtilMap &utilMap)
{
utilMap["message"] = &SendMessage;
utilMap["printtemplate"] = &PrintTemplate;
}

/* vim: set expandtab tabstop=4 shiftwidth=4: */
4 changes: 4 additions & 0 deletions mythtv/programs/mythutil/messageutils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#include "mythutil.h"

void registerMessageUtils(UtilMap &utilMap);

45 changes: 45 additions & 0 deletions mythtv/programs/mythutil/mythutil.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Qt includes
#include <QDateTime>
#include <QString>

// libmyth* includes
#include "mythlogging.h"

// Local includes
#include "mythutil.h"

bool GetProgramInfo(const MythUtilCommandLineParser &cmdline,
ProgramInfo &pginfo)
{
if (!cmdline.toBool("chanid"))
{
LOG(VB_GENERAL, LOG_ERR, "No chanid specified");
return false;
}

if (!cmdline.toBool("starttime"))
{
LOG(VB_GENERAL, LOG_ERR, "No start time specified");
return false;
}

uint chanid = cmdline.toUInt("chanid");
QDateTime starttime = cmdline.toDateTime("starttime");
QString startstring = starttime.toString("yyyyMMddhhmmss");

const ProgramInfo tmpInfo(chanid, starttime);

if (!tmpInfo.GetChanID())
{
LOG(VB_GENERAL, LOG_ERR,
QString("No program data exists for channel %1 at %2")
.arg(chanid).arg(startstring));
return false;
}

pginfo = tmpInfo;

return true;
}

/* vim: set expandtab tabstop=4 shiftwidth=4: */
21 changes: 21 additions & 0 deletions mythtv/programs/mythutil/mythutil.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#ifndef MYTHUTIL_H_
#define MYTHUTIL_H_

// Qt includes
#include <QMap>
#include <QString>

// libmyth* includes
#include "programinfo.h"

// Local includes
#include "commandlineparser.h"

typedef int (*UtilFunc)(const MythUtilCommandLineParser &cmdline);

typedef QMap<QString, UtilFunc> UtilMap;

bool GetProgramInfo(const MythUtilCommandLineParser &cmdline,
ProgramInfo &pginfo);

#endif
26 changes: 26 additions & 0 deletions mythtv/programs/mythutil/mythutil.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
include ( ../../settings.pro )
include ( ../../version.pro )
include ( ../programs-libs.pro )

QT += network sql

TEMPLATE = app
CONFIG += thread
TARGET = mythutil
target.path = $${PREFIX}/bin
INSTALLS = target

LIBS += $$EXTRA_LIBS
INCLUDEPATH += ../../libs/libmythbase

QMAKE_CLEAN += $(TARGET)

# Input
HEADERS += mythutil.h commandlineparser.h
HEADERS += backendutils.h fileutils.h jobutils.h markuputils.h
HEADERS += messageutils.h
SOURCES += main.cpp mythutil.cpp commandlineparser.cpp
SOURCES += backendutils.cpp fileutils.cpp jobutils.cpp markuputils.cpp
SOURCES += messageutils.cpp

mingw: LIBS += -lwinmm -lws2_32
2 changes: 1 addition & 1 deletion mythtv/programs/programs.pro
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ TEMPLATE = subdirs
using_frontend {
SUBDIRS += mythavtest mythfrontend mythcommflag
SUBDIRS += mythmessage mythjobqueue mythlcdserver
SUBDIRS += mythwelcome mythshutdown
SUBDIRS += mythwelcome mythshutdown mythutil
SUBDIRS += mythpreviewgen mythmediaserver mythccextractor
!mingw: SUBDIRS += mythtranscode/replex
}
Expand Down