Skip to content

Commit

Permalink
Add a MythMetdataLookup program.
Browse files Browse the repository at this point in the history
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
Robert McNamara committed Jul 3, 2011
1 parent 9bdd46b commit 913f0d8
Show file tree
Hide file tree
Showing 6 changed files with 324 additions and 0 deletions.
1 change: 1 addition & 0 deletions mythtv/programs/mythmetadatalookup/.gitignore
@@ -0,0 +1 @@
mythfillnetvision
136 changes: 136 additions & 0 deletions 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);
}
}
30 changes: 30 additions & 0 deletions 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_
137 changes: 137 additions & 0 deletions 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;
}
19 changes: 19 additions & 0 deletions 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

1 change: 1 addition & 0 deletions mythtv/programs/programs.pro
Expand Up @@ -13,6 +13,7 @@ using_frontend {

using_backend {
SUBDIRS += mythbackend mythfilldatabase mythtv-setup scripts
SUBDIRS += mythmetadatalookup
}

using_mythtranscode: SUBDIRS += mythtranscode

0 comments on commit 913f0d8

Please sign in to comment.