Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add a MythMetdataLookup program.

This program should be thought of as a companion job to records like mythcommflag or mythtranscode.  It takes programs as an input, performs a lookup online, and then sets various pieces of metadata on a successful return.

For now, it can be run in one of two ways:

./mythmetadatalookup

Will cycle through your entire list of recordings, look them up online, and if matches are found it will set:

* For Movies: Inetref
* For Television: Inetref, Season, and Episode

This mode will not re-run a lookup on a movie that already has an inetref, or a television show that already has inetref, season, and episode.

It can also be run as:

./mythmetadatalookup --chanid 12345 --starttime 07-02-2011T19:30:00

(using any supported date-time format)

Which will unequivocally look up a valid program from that chanid and starttime.

Though this program will work and set correct values in the recorded table, to really show its worth it relies on:

* Themes to be updated to show the season and episode values when relevant
* Recording rule editor changes to allow inetref to be set on recording rules, so that they propagate to the recordings (so that you can set the inetref for "Castle" to TVDB's inetref for "Castle (2009)" and have all your lookups work thereafter)

I will also possibly add a mode later that is a little more "promiscuous" and overrides existing program info values-- say you get a generic episode that you really needed, you could theoretically change the subtitle in the UI and run a lookup on it to get correct, full metadata.  I need to think about how best to accomplish this.
  • Loading branch information...
commit 913f0d8436f6bdd6edb7542112d041a943076264 1 parent 9bdd46b
Robert McNamara authored
View
1  mythtv/programs/mythmetadatalookup/.gitignore
@@ -0,0 +1 @@
+mythfillnetvision
View
136 mythtv/programs/mythmetadatalookup/lookup.cpp
@@ -0,0 +1,136 @@
+#include <vector>
+
+#include <QList>
+
+#include "programinfo.h"
+#include "mythlogging.h"
+#include "jobqueue.h"
+
+#include "lookup.h"
+
+LookerUpper::LookerUpper() :
+ m_busyRecList(QList<ProgramInfo*>())
+{
+ m_metadataFactory = new MetadataFactory(this);
+}
+
+LookerUpper::~LookerUpper()
+{
+}
+
+bool LookerUpper::StillWorking()
+{
+ if (m_metadataFactory->IsRunning() ||
+ m_busyRecList.count())
+ {
+ return true;
+ }
+
+ return false;
+}
+
+void LookerUpper::HandleSingleRecording(const uint chanid,
+ const QDateTime starttime)
+{
+ ProgramInfo *pginfo = new ProgramInfo(chanid, starttime);
+
+ if (!pginfo)
+ {
+ VERBOSE(VB_IMPORTANT, "No valid program info for supplied chanid/starttime");
+ return;
+ }
+
+ m_busyRecList.append(pginfo);
+ m_metadataFactory->Lookup(pginfo, false, false);
+}
+
+void LookerUpper::HandleAllRecordings()
+{
+ QMap< QString, ProgramInfo* > recMap;
+ QMap< QString, uint32_t > inUseMap = ProgramInfo::QueryInUseMap();
+ QMap< QString, bool > isJobRunning = ProgramInfo::QueryJobsRunning(JOB_COMMFLAG);
+
+ ProgramList progList;
+
+ LoadFromRecorded( progList, false, inUseMap, isJobRunning, recMap, -1 );
+
+ for( int n = 0; n < (int)progList.size(); n++)
+ {
+ ProgramInfo *pginfo = new ProgramInfo(*(progList[n]));
+ if (pginfo->GetInetRef().isEmpty() ||
+ (!pginfo->GetSubtitle().isEmpty() &&
+ (pginfo->GetSeason() == 0) &&
+ (pginfo->GetEpisode() == 0)))
+ {
+ QString msg = QString("Looking up: %1 %2").arg(pginfo->GetTitle())
+ .arg(pginfo->GetSubtitle());
+ VERBOSE(VB_IMPORTANT, msg);
+
+ m_busyRecList.append(pginfo);
+ m_metadataFactory->Lookup(pginfo, false, false);
+ }
+ }
+}
+
+void LookerUpper::customEvent(QEvent *levent)
+{
+ if (levent->type() == MetadataFactoryMultiResult::kEventType)
+ {
+ VERBOSE(VB_IMPORTANT, "Got a multiresult.");
+ // We shouldn't get any of these. If we do, metadataFactory->Lookup
+ // was called with the wrong arguments.
+ }
+ else if (levent->type() == MetadataFactorySingleResult::kEventType)
+ {
+ MetadataFactorySingleResult *mfsr = dynamic_cast<MetadataFactorySingleResult*>(levent);
+
+ if (!mfsr)
+ return;
+
+ MetadataLookup *lookup = mfsr->result;
+
+ if (!lookup)
+ return;
+
+ ProgramInfo *pginfo = qVariantValue<ProgramInfo *>(lookup->GetData());
+
+ // This null check could hang us as this pginfo would then never be removed
+ if (!pginfo)
+ return;
+
+ VERBOSE(VB_GENERAL|VB_EXTRA, QString("I found the following data:"));
+ VERBOSE(VB_GENERAL|VB_EXTRA, QString(" Input Title: %1").arg(pginfo->GetTitle()));
+ VERBOSE(VB_GENERAL|VB_EXTRA, QString(" Input Sub: %1").arg(pginfo->GetSubtitle()));
+ VERBOSE(VB_GENERAL|VB_EXTRA, QString(" Title: %1").arg(lookup->GetTitle()));
+ VERBOSE(VB_GENERAL|VB_EXTRA, QString(" Subtitle: %1").arg(lookup->GetSubtitle()));
+ VERBOSE(VB_GENERAL|VB_EXTRA, QString(" Season: %1").arg(lookup->GetSeason()));
+ VERBOSE(VB_GENERAL|VB_EXTRA, QString(" Episode: %1").arg(lookup->GetEpisode()));
+ VERBOSE(VB_GENERAL|VB_EXTRA, QString(" Inetref: %1").arg(lookup->GetInetref()));
+ VERBOSE(VB_GENERAL|VB_EXTRA, QString(" User Rating: %1").arg(lookup->GetUserRating()));
+
+ pginfo->SaveSeasonEpisode(lookup->GetSeason(), lookup->GetEpisode());
+ pginfo->SaveInetRef(lookup->GetInetref());
+
+ m_busyRecList.removeAll(pginfo);
+ }
+ else if (levent->type() == MetadataFactoryNoResult::kEventType)
+ {
+ MetadataFactoryNoResult *mfnr = dynamic_cast<MetadataFactoryNoResult*>(levent);
+
+ if (!mfnr)
+ return;
+
+ MetadataLookup *lookup = mfnr->result;
+
+ if (!lookup)
+ return;
+
+ ProgramInfo *pginfo = qVariantValue<ProgramInfo *>(lookup->GetData());
+
+ // This null check could hang us as this pginfo would then never be removed
+ if (!pginfo)
+ return;
+
+ m_busyRecList.removeAll(pginfo);
+ }
+}
View
30 mythtv/programs/mythmetadatalookup/lookup.h
@@ -0,0 +1,30 @@
+#ifndef LOOKUP_H_
+#define LOOKUP_H_
+
+#include <QObject>
+#include <QList>
+
+#include "programinfo.h"
+#include "metadatafactory.h"
+
+class LookerUpper : public QObject
+{
+ public:
+ LookerUpper();
+ ~LookerUpper();
+
+ bool StillWorking();
+
+ void HandleSingleRecording(const uint chanid,
+ const QDateTime starttime);
+ void HandleAllRecordings();
+
+ private:
+ void customEvent(QEvent *event);
+
+ MetadataFactory *m_metadataFactory;
+
+ QList<ProgramInfo*> m_busyRecList;
+};
+
+#endif //LOOKUP_H_
View
137 mythtv/programs/mythmetadatalookup/main.cpp
@@ -0,0 +1,137 @@
+// C headers
+#include <unistd.h>
+
+// C++ headers
+#include <iostream>
+using namespace std;
+
+// Qt headers
+#include <QCoreApplication>
+#include <QEventLoop>
+
+// libmyth headers
+#include "exitcodes.h"
+#include "mythcontext.h"
+#include "mythdb.h"
+#include "mythversion.h"
+#include "util.h"
+#include "mythtranslation.h"
+#include "mythconfig.h"
+#include "mythcommandlineparser.h"
+#include "mythlogging.h"
+
+#include "lookup.h"
+
+class MPUBLIC MythMetadataLookupCommandLineParser : public MythCommandLineParser
+{
+ public:
+ MythMetadataLookupCommandLineParser();
+ void LoadArguments(void);
+};
+
+MythMetadataLookupCommandLineParser::MythMetadataLookupCommandLineParser() :
+ MythCommandLineParser("mythmetadatalookup")
+{ LoadArguments(); }
+
+void MythMetadataLookupCommandLineParser::LoadArguments(void)
+{
+ addHelp();
+ addVersion();
+ addVerbose();
+ addRecording();
+ addLogging();
+
+ add("--refresh-all", "refresh-all", false,
+ "Refresh all recorded programs and recording rules metadata", "");
+}
+
+int main(int argc, char *argv[])
+{
+ MythMetadataLookupCommandLineParser 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;
+ }
+
+ QCoreApplication a(argc, argv);
+ QCoreApplication::setApplicationName("mythmetadatalookup");
+
+ int retval;
+ if ((retval = cmdline.ConfigureLogging()) != GENERIC_EXIT_OK)
+ return retval;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Don't listen to console input
+ close(0);
+
+ gContext = new MythContext(MYTH_BINARY_VERSION);
+ if (!gContext->Init(false))
+ {
+ VERBOSE(VB_IMPORTANT, "Failed to init MythContext, exiting.");
+ delete gContext;
+ return GENERIC_EXIT_NO_MYTHCONTEXT;
+ }
+
+ bool refreshall = cmdline.toBool("refresh-all");
+ bool usedchanid = cmdline.toBool("chanid");
+ bool usedstarttime = cmdline.toBool("starttime");
+
+ uint chanid = cmdline.toUInt("chanid");
+ QString startstring = cmdline.toString("starttime");
+ QDateTime starttime = myth_dt_from_string(startstring);
+
+ if (refreshall && (usedchanid || usedstarttime))
+ {
+ VERBOSE(VB_IMPORTANT, "--refresh-all must not be accompanied by "
+ "--chanid or --starttime");
+ return GENERIC_EXIT_INVALID_CMDLINE;
+ }
+
+ if (!refreshall && !(usedchanid && usedstarttime))
+ {
+ VERBOSE(VB_IMPORTANT, "--chanid and --starttime must be used together.");
+ return GENERIC_EXIT_INVALID_CMDLINE;
+ }
+
+ if (!refreshall && !usedchanid && !usedstarttime)
+ {
+ refreshall = true;
+ }
+
+ myth_nice(19);
+
+ MythTranslation::load("mythfrontend");
+
+ LookerUpper *lookup = new LookerUpper();
+
+ if (refreshall)
+ lookup->HandleAllRecordings();
+ else
+ lookup->HandleSingleRecording(chanid, starttime);
+
+ while (lookup->StillWorking())
+ {
+ sleep(1);
+ qApp->processEvents();
+ }
+
+ delete lookup;
+ delete gContext;
+
+ VERBOSE(VB_IMPORTANT, "MythMetadataLookup run complete.");
+
+ return GENERIC_EXIT_OK;
+}
View
19 mythtv/programs/mythmetadatalookup/mythmetadatalookup.pro
@@ -0,0 +1,19 @@
+include ( ../../settings.pro )
+include ( ../../version.pro )
+include ( ../programs-libs.pro )
+
+QT += network xml sql
+
+TEMPLATE = app
+CONFIG += thread
+CONFIG -= moc
+TARGET = mythmetadatalookup
+target.path = $${PREFIX}/bin
+INSTALLS = target
+
+QMAKE_CLEAN += $(TARGET)
+
+# Input
+HEADERS += lookup.h
+SOURCES += main.cpp lookup.cpp
+
View
1  mythtv/programs/programs.pro
@@ -13,6 +13,7 @@ using_frontend {
using_backend {
SUBDIRS += mythbackend mythfilldatabase mythtv-setup scripts
+ SUBDIRS += mythmetadatalookup
}
using_mythtranscode: SUBDIRS += mythtranscode
Please sign in to comment.
Something went wrong with that request. Please try again.