Skip to content
Permalink
Browse files

Add a mythutil binary as a place to consolidate helper utilities

mythutil reimplements the following from various places:

--clearcache
--clearcutlist
--clearskiplist
--event
--gencutlist
--getcutlist
--getskiplist
--message (and --print-template)
--resched
--scanvideos
--setcutlist
--setskiplist
--systemevent

It also adds the following new functions:
--copyfile (to copy a file to or from a Storage Group between a
            myth:// URI and a local file or between two myth:// URIs)

--queuejob (to insert a job into the jobqueue for a recording)

Usage for the new functions:

mythutil --copyfile --srcfile myth://host/file.mpg --destfile ./file.mpg

mythutil --queuejob commflag --chanid 1011 --starttime 20111001180000

The above functions will be removed from their original places in a
subsequent commit.
  • Loading branch information
cpinkham committed Oct 8, 2011
1 parent 8e043a2 commit 1b66c042236478d09c98d1b6cefa3d42717d4126
@@ -0,0 +1 @@
mythutil
@@ -0,0 +1,91 @@
// libmyth* headers
#include "exitcodes.h"
#include "mythcorecontext.h"
#include "mythlogging.h"
#include "remoteutil.h"

// local headers
#include "mythutil.h"

static int RawSendEvent(const QString &eventString)
{
if (eventString.isEmpty())
return GENERIC_EXIT_INVALID_CMDLINE;

if (gCoreContext->ConnectToMasterServer(false, false))
{
RemoteSendMessage(eventString);
return GENERIC_EXIT_OK;
}
return GENERIC_EXIT_CONNECT_ERROR;
}

static int ClearSettingsCache(const MythUtilCommandLineParser &cmdline)
{
if (gCoreContext->ConnectToMasterServer(false, false))
{
RemoteSendMessage("CLEAR_SETTINGS_CACHE");
LOG(VB_GENERAL, LOG_INFO, "Sent CLEAR_SETTINGS_CACHE message");
return GENERIC_EXIT_OK;
}

LOG(VB_GENERAL, LOG_ERR, "Unable to connect to backend, settings "
"cache will not be cleared.");
return GENERIC_EXIT_CONNECT_ERROR;
}

static int SendEvent(const MythUtilCommandLineParser &cmdline)
{
return RawSendEvent(cmdline.toString("event"));
}

static int SendSystemEvent(const MythUtilCommandLineParser &cmdline)
{
return RawSendEvent(QString("SYSTEM_EVENT %1 SENDER %2")
.arg(cmdline.toString("systemevent"))
.arg(gCoreContext->GetHostName()));
}

static int Reschedule(const MythUtilCommandLineParser &cmdline)
{
if (gCoreContext->ConnectToMasterServer(false, false))
{
QStringList slist("RESCHEDULE_RECORDINGS -1");
if (gCoreContext->SendReceiveStringList(slist))
{
LOG(VB_GENERAL, LOG_ERR,
"Error sending reschedule command to master backend");
return GENERIC_EXIT_CONNECT_ERROR;
}

LOG(VB_GENERAL, LOG_INFO, "Reschedule command sent to master");
return GENERIC_EXIT_OK;
}

LOG(VB_GENERAL, LOG_ERR, "Cannot connect to master for reschedule");
return GENERIC_EXIT_CONNECT_ERROR;
}

static int ScanVideos(const MythUtilCommandLineParser &cmdline)
{
if (gCoreContext->ConnectToMasterServer(false, false))
{
gCoreContext->SendReceiveStringList(QStringList() << "SCAN_VIDEOS");
LOG(VB_GENERAL, LOG_INFO, "Requested video scan");
return GENERIC_EXIT_OK;
}

LOG(VB_GENERAL, LOG_ERR, "Cannot connect to master for video scan");
return GENERIC_EXIT_CONNECT_ERROR;
}

void registerBackendUtils(UtilMap &utilMap)
{
utilMap["clearcache"] = &ClearSettingsCache;
utilMap["event"] = &SendEvent;
utilMap["resched"] = &Reschedule;
utilMap["scanvideos"] = &ScanVideos;
utilMap["systemevent"] = &SendSystemEvent;
}

/* vim: set expandtab tabstop=4 shiftwidth=4: */
@@ -0,0 +1,5 @@
// local headers
#include "mythutil.h"

void registerBackendUtils(UtilMap &utilMap);

@@ -0,0 +1,124 @@
// libmyth* headers
#include "mythcorecontext.h"

// local headers
#include "commandlineparser.h"

MythUtilCommandLineParser::MythUtilCommandLineParser() :
MythCommandLineParser(MYTH_APPNAME_MYTHUTIL)
{ LoadArguments(); }

void MythUtilCommandLineParser::LoadArguments(void)
{
CommandLineArg::AllowOneOf( QList<CommandLineArg*>()
<< add("--copyfile", "copyfile", false,
"Copy a MythTV Storage Group file", "")
->SetGroup("File")
<< add("--gencutlist", "gencutlist", false,
"Copy the commercial skip list to the cutlist.", "")
->SetGroup("Recording Markup")
->SetRequires("chanid")
->SetRequires("starttime")
<< add("--getcutlist", "getcutlist", false,
"Display the current cutlist.", "")
->SetGroup("Recording Markup")
->SetRequires("chanid")
->SetRequires("starttime")
<< add("--setcutlist", "setcutlist", "",
"Set a new cutlist in the form:\n"
"#-#[,#-#]... (ie, 1-100,1520-3012,4091-5094)", "")
->SetGroup("Recording Markup")
->SetRequires("chanid")
->SetRequires("starttime")
<< add("--clearcutlist", "clearcutlist", false,
"Clear the cutlist.", "")
->SetGroup("Recording Markup")
->SetRequires("chanid")
->SetRequires("starttime")
<< add("--getskiplist", "getskiplist", false,
"Display the current commercial skip list.", "")
->SetGroup("Recording Markup")
->SetRequires("chanid")
->SetRequires("starttime")
<< add("--setskiplist", "setskiplist", "",
"Set a new commercial skip list in the form:\n"
"#-#[,#-#]... (ie, 1-100,1520-3012,4091-5094)", "")
->SetGroup("Recording Markup")
->SetRequires("chanid")
->SetRequires("starttime")
<< add("--clearskiplist", "clearskiplist", false,
"Clear the commercial skip list.", "")
->SetGroup("Recording Markup")
->SetRequires("chanid")
->SetRequires("starttime")
<< add("--resched", "resched", false,
"Trigger a run of the recording scheduler on the existing "
"master backend.",
"This command will connect to the master backend and trigger "
"a run of the recording scheduler. The call will return "
"immediately, however the scheduler run may take several "
"seconds to a minute or longer to complete.")
->SetGroup("Backend")
<< add("--scanvideos", "scanvideos", false,
"Trigger a rescan of media content in MythVideo.",
"This command will connect to the master backend and trigger "
"a run of the Video scanner. The call will return "
"immediately, however the scanner may take several seconds "
"to tens of minutes, depending on how much new or moved "
"content it has to hash, and how quickly the scanner can "
"access those files to do so. If enabled, this will also "
"trigger the bulk metadata scanner upon completion.")
->SetGroup("Backend")
<< add("--event", "event", "", "Send a backend event test message.", "")
->SetGroup("Backend")
<< add("--systemevent", "systemevent", "",
"Send a backend SYSTEM_EVENT test message.", "")
->SetGroup("Backend")
<< add("--clearcache", "clearcache", false,
"Trigger a cache clear on all connected MythTV systems.",
"This command will connect to the master backend and trigger "
"a cache clear event, which will subsequently be pushed to "
"all other connected programs. This event will clear the "
"local database settings cache used by each program, causing "
"options to be re-read from the database upon next use.")
->SetGroup("Backend")
<< add("--queuejob", "queuejob", "",
"Insert a new job into the JobQueue.",
"Schedule the specified job type (transcode, commflag, "
"metadata, userjob1, userjob2, userjob3, userjob4) to run "
"for the recording with the given chanid and starttime.")
->SetGroup("JobQueue")
->SetRequires("chanid")
->SetRequires("starttime")
<< add("--message", "message", false,
"Display a message on a frontend", "")
->SetGroup("Messaging")
<< add("--print-template", "printtemplate", false,
"Print the template to be sent to the frontend", "")
->SetGroup("Messaging")
);

add("--srcfile", "srcfile", "", "Source file URI", "")
->SetRequiredChildOf("copyfile");
add("--destfile", "destfile", "", "Destination file URI", "")
->SetRequiredChildOf("copyfile");

add("--udpport", "udpport", 6948, "(optional) UDP Port to send to", "")
->SetChildOf("message");
add("--bcastaddr", "bcastaddr", "127.0.0.1", "(optional) IP address to send to", "")
->SetChildOf("message");

// Generic Options used by more than one utility
addRecording();
addHelp();
addVersion();
addLogging();
allowExtras();
}

QString MythUtilCommandLineParser::GetHelpHeader(void) const
{
return "MythUtil is a command line utility application for MythTV.";
}

/* vim: set expandtab tabstop=4 shiftwidth=4: */
@@ -0,0 +1,18 @@
#ifndef COMMANDLINEPARSER_H_
#define COMMANDLINEPARSER_H_

#include <QString>

#include "mythcommandlineparser.h"

class MythUtilCommandLineParser : public MythCommandLineParser
{
public:
MythUtilCommandLineParser();
void LoadArguments(void);
protected:
QString GetHelpHeader(void) const;
};

#endif

@@ -0,0 +1,91 @@
// libmyth* headers
#include "exitcodes.h"
#include "mythlogging.h"
#include "ringbuffer.h"

// local headers
#include "mythutil.h"

static int CopyFile(const MythUtilCommandLineParser &cmdline)
{
int result = GENERIC_EXIT_OK;

if (cmdline.toString("srcfile").isEmpty())
{
LOG(VB_GENERAL, LOG_ERR, "Missing --srcfile option");
return GENERIC_EXIT_INVALID_CMDLINE;
}
QString src = cmdline.toString("srcfile");

if (cmdline.toString("destfile").isEmpty())
{
LOG(VB_GENERAL, LOG_ERR, "Missing --destfile option");
return GENERIC_EXIT_INVALID_CMDLINE;
}
QString dest = cmdline.toString("destfile");

LOG(VB_GENERAL, LOG_INFO, QString("Copying %1 to %2").arg(src).arg(dest));
RingBuffer *srcRB = RingBuffer::Create(src, false);
if (!srcRB)
{
LOG(VB_GENERAL, LOG_ERR, "ERROR, couldn't create Read RingBuffer");
return GENERIC_EXIT_NOT_OK;
}

if (!srcRB->IsOpen())
{
LOG(VB_GENERAL, LOG_ERR, "ERROR, srcRB is not open");
return GENERIC_EXIT_NOT_OK;
}

RingBuffer *destRB = RingBuffer::Create(dest, true);
if (!destRB)
{
LOG(VB_GENERAL, LOG_ERR, "ERROR, couldn't create Write RingBuffer");
delete srcRB;
return GENERIC_EXIT_NOT_OK;
}

if (!destRB->IsOpen())
{
LOG(VB_GENERAL, LOG_ERR, "ERROR, destRB is not open");
return GENERIC_EXIT_NOT_OK;
}

const int readSize = 2 * 1024 * 1024;
char buf[readSize];
bool ok = true;
int r;
int ret;
int written = 0;
while (ok && ((r = srcRB->Read(buf, readSize)) > 0))
{
ret = destRB->Write(buf, r);
if (ret < 0)
{
LOG(VB_GENERAL, LOG_ERR,
QString("ERROR, couldn't write at offset %1").arg(written));
ok = false;
}
else
written += ret;
}

LOG(VB_GENERAL, LOG_INFO,
QString("Wrote %1 bytes total").arg(written));

delete srcRB;
delete destRB;

if (!ok)
result = GENERIC_EXIT_NOT_OK;

return result;
}

void registerFileUtils(UtilMap &utilMap)
{
utilMap["copyfile"] = &CopyFile;
}

/* vim: set expandtab tabstop=4 shiftwidth=4: */
@@ -0,0 +1,4 @@
#include "mythutil.h"

void registerFileUtils(UtilMap &utilMap);

0 comments on commit 1b66c04

Please sign in to comment.
You can’t perform that action at this time.