From 52613a0b9012e4fcbda124c91fb9830b5bd65939 Mon Sep 17 00:00:00 2001 From: Robert McNamara Date: Wed, 29 Jun 2011 21:04:57 -0700 Subject: [PATCH] Metadata: Support import of Myth-format metadata from an external file. Superior metadata re-import from an external file. Uses Myth's native metadata XML format. Looks for a file named the same as the video file, with a .mxml extension. This supports *all* our metadata natively, will reconnect any downloaded artwork found in the fanart/banner/coverart/etc. directories, and saves us having to do any re-lookup with the metadata source. If the images go missing but the video files and .mxml files are still present, the images will be redownloaded but that will be the only traffice with the metadata source. This also allows ambiguous titles to have a perfect match when being removed from and readded to the library. I'll add support for writing out the .mxml files upon metadata grab soon. --- .../libs/libmythmetadata/metadatacommon.cpp | 1 + .../libs/libmythmetadata/metadatadownload.cpp | 95 ++++++++++++++++++- .../libs/libmythmetadata/metadatadownload.h | 4 + 3 files changed, 98 insertions(+), 2 deletions(-) diff --git a/mythtv/libs/libmythmetadata/metadatacommon.cpp b/mythtv/libs/libmythmetadata/metadatacommon.cpp index fcc2adaf997..eef8c56e8ff 100644 --- a/mythtv/libs/libmythmetadata/metadatacommon.cpp +++ b/mythtv/libs/libmythmetadata/metadatacommon.cpp @@ -427,6 +427,7 @@ MetadataLookup* ParseMetadataMovieNFO(const QDomElement& item, PersonInfo info; info.name = actor.firstChildElement("name").text(); info.role = actor.firstChildElement("role").text(); + info.thumbnail = actor.firstChildElement("thumb").text(); people.insert(ACTOR, info); actor = actor.nextSiblingElement("actor"); } diff --git a/mythtv/libs/libmythmetadata/metadatadownload.cpp b/mythtv/libs/libmythmetadata/metadatadownload.cpp index ae2b1217d1d..aae5b2b0547 100644 --- a/mythtv/libs/libmythmetadata/metadatadownload.cpp +++ b/mythtv/libs/libmythmetadata/metadatadownload.cpp @@ -206,6 +206,70 @@ MetadataLookupList MetadataDownload::runGrabber(QString cmd, QStringList args, return list; } +MetadataLookupList MetadataDownload::readMXML(QString MXMLpath, + MetadataLookup* lookup, + bool passseas) +{ + MetadataLookupList list; + + VERBOSE(VB_GENERAL, QString("Matching MXML file found. " + "Parsing %1 for metadata...") + .arg(MXMLpath)); + + if (lookup->GetType() == VID) + { + QByteArray mxmlraw; + QDomElement item; + if (MXMLpath.startsWith("myth://")) + { + RemoteFile *rf = new RemoteFile(MXMLpath); + if (rf && rf->Open()) + { + bool loaded = rf->SaveAs(mxmlraw); + if (loaded) + { + QDomDocument doc; + if (doc.setContent(mxmlraw, true)) + { + lookup->SetStep(GETDATA); + QDomElement root = doc.documentElement(); + item = root.firstChildElement("item"); + } + else + VERBOSE(VB_GENERAL, QString("Corrupt or invalid MXML file.")); + } + rf->Close(); + } + + delete rf; + rf = NULL; + } + else + { + QFile file(MXMLpath); + if (file.open(QIODevice::ReadOnly)) + { + mxmlraw = file.readAll(); + QDomDocument doc; + if (doc.setContent(mxmlraw, true)) + { + lookup->SetStep(GETDATA); + QDomElement root = doc.documentElement(); + item = root.firstChildElement("item"); + } + else + VERBOSE(VB_GENERAL, QString("Corrupt or invalid MXML file.")); + file.close(); + } + } + + MetadataLookup *tmp = ParseMetadataItem(item, lookup, passseas); + list.append(tmp); + } + + return list; +} + MetadataLookupList MetadataDownload::readNFO(QString NFOpath, MetadataLookup* lookup) { @@ -308,9 +372,10 @@ MetadataLookupList MetadataDownload::handleMovie(MetadataLookup* lookup) { MetadataLookupList list; + QString mxml = getMXMLPath(lookup->GetFilename()); QString nfo = getNFOPath(lookup->GetFilename()); - if (nfo.isEmpty()) + if (mxml.isEmpty() && nfo.isEmpty()) { QString def_cmd = QDir::cleanPath(QString("%1/%2") .arg(GetShareDir()) @@ -342,7 +407,9 @@ MetadataLookupList MetadataDownload::handleMovie(MetadataLookup* lookup) } list = runGrabber(cmd, args, lookup); } - else + else if (!mxml.isEmpty()) + list = readMXML(mxml, lookup); + else if (!nfo.isEmpty()) list = readNFO(nfo, lookup); return list; @@ -421,6 +488,30 @@ MetadataLookupList MetadataDownload::handleVideoUndetermined( return list; } +QString MetadataDownload::getMXMLPath(QString filename) +{ + QString ret; + QString xmlname; + QUrl qurl(filename); + QString ext = QFileInfo(qurl.path()).suffix(); + xmlname = filename.left(filename.size() - ext.size()) + "mxml"; + + VERBOSE(VB_GENERAL, QString("MXMLName = %1 ").arg(xmlname)); + + if (xmlname.startsWith("myth://")) + { + if (RemoteFile::Exists(xmlname)) + ret = xmlname; + } + else + { + if (QFile::exists(xmlname)) + ret = xmlname; + } + + return ret; +} + QString MetadataDownload::getNFOPath(QString filename) { QString ret; diff --git a/mythtv/libs/libmythmetadata/metadatadownload.h b/mythtv/libs/libmythmetadata/metadatadownload.h index db73d827c66..a51aba7b6df 100644 --- a/mythtv/libs/libmythmetadata/metadatadownload.h +++ b/mythtv/libs/libmythmetadata/metadatadownload.h @@ -48,6 +48,7 @@ class META_PUBLIC MetadataDownload : public QThread void run(); + QString getMXMLPath(QString filename); QString getNFOPath(QString filename); private: @@ -63,6 +64,9 @@ class META_PUBLIC MetadataDownload : public QThread MetadataLookupList runGrabber(QString cmd, QStringList args, MetadataLookup* lookup, bool passseas = true); + MetadataLookupList readMXML(QString MXMLpath, + MetadataLookup* lookup, + bool passseas = true); MetadataLookupList readNFO(QString NFOpath, MetadataLookup* lookup); MetadataLookup* moreWork();