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...
1 parent 8e043a2 commit 1b66c042236478d09c98d1b6cefa3d42717d4126 @cpinkham cpinkham committed Oct 8, 2011
@@ -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);
+
Oops, something went wrong. Retry.

0 comments on commit 1b66c04

Please sign in to comment.