MythTV  0.26-pre
lookup.cpp
Go to the documentation of this file.
00001 #include <vector>
00002 
00003 #include <QList>
00004 
00005 #include "programinfo.h"
00006 #include "recordingrule.h"
00007 #include "mythlogging.h"
00008 #include "jobqueue.h"
00009 #include "remoteutil.h"
00010 
00011 #include "metadataimagehelper.h"
00012 
00013 #include "lookup.h"
00014 
00015 LookerUpper::LookerUpper() :
00016     m_busyRecList(QList<ProgramInfo*>()),
00017     m_updaterules(false), m_updateartwork(false)
00018 {
00019     m_metadataFactory = new MetadataFactory(this);
00020 }
00021 
00022 LookerUpper::~LookerUpper()
00023 {
00024     while (!m_busyRecList.isEmpty())
00025         delete m_busyRecList.takeFirst();
00026 }
00027 
00028 bool LookerUpper::StillWorking()
00029 {
00030     if (m_metadataFactory->IsRunning() ||
00031         m_busyRecList.count())
00032     {
00033         return true;
00034     }
00035 
00036     return false;
00037 }
00038 
00039 void LookerUpper::HandleSingleRecording(const uint chanid,
00040                                         const QDateTime starttime,
00041                                         bool updaterules)
00042 {
00043     ProgramInfo *pginfo = new ProgramInfo(chanid, starttime);
00044 
00045     if (!pginfo)
00046     {
00047         LOG(VB_GENERAL, LOG_ERR,
00048             "No valid program info for supplied chanid/starttime");
00049         return;
00050     }
00051 
00052     m_updaterules = updaterules;
00053 
00054     m_busyRecList.append(pginfo);
00055     m_metadataFactory->Lookup(pginfo, false, false, false);
00056 }
00057 
00058 void LookerUpper::HandleAllRecordings(bool updaterules)
00059 {
00060     QMap< QString, ProgramInfo* > recMap;
00061     QMap< QString, uint32_t > inUseMap = ProgramInfo::QueryInUseMap();
00062     QMap< QString, bool > isJobRunning = ProgramInfo::QueryJobsRunning(JOB_COMMFLAG);
00063 
00064     m_updaterules = updaterules;
00065 
00066     ProgramList progList;
00067 
00068     LoadFromRecorded( progList, false, inUseMap, isJobRunning, recMap, -1 );
00069 
00070     for( int n = 0; n < (int)progList.size(); n++)
00071     {
00072         ProgramInfo *pginfo = new ProgramInfo(*(progList[n]));
00073         if ((pginfo->GetRecordingGroup() != "Deleted") &&
00074             (pginfo->GetRecordingGroup() != "LiveTV") &&
00075             (pginfo->GetInetRef().isEmpty() ||
00076             (!pginfo->GetSubtitle().isEmpty() &&
00077             (pginfo->GetSeason() == 0) &&
00078             (pginfo->GetEpisode() == 0))))
00079         {
00080             QString msg = QString("Looking up: %1 %2").arg(pginfo->GetTitle())
00081                                            .arg(pginfo->GetSubtitle());
00082             LOG(VB_GENERAL, LOG_INFO, msg);
00083 
00084             m_busyRecList.append(pginfo);
00085             m_metadataFactory->Lookup(pginfo, false, false, false);
00086         }
00087         else
00088             delete pginfo;
00089     }
00090 }
00091 
00092 void LookerUpper::HandleAllRecordingRules()
00093 {
00094     m_updaterules = true;
00095 
00096     vector<ProgramInfo *> recordingList;
00097 
00098     RemoteGetAllScheduledRecordings(recordingList);
00099 
00100     for( int n = 0; n < (int)recordingList.size(); n++)
00101     {
00102         ProgramInfo *pginfo = new ProgramInfo(*(recordingList[n]));
00103         if (pginfo->GetInetRef().isEmpty())
00104         {
00105             QString msg = QString("Looking up: %1 %2").arg(pginfo->GetTitle())
00106                                            .arg(pginfo->GetSubtitle());
00107             LOG(VB_GENERAL, LOG_INFO, msg);
00108 
00109             m_busyRecList.append(pginfo);
00110             m_metadataFactory->Lookup(pginfo, false, false, true);
00111         }
00112         else
00113             delete pginfo;
00114     }
00115 }
00116 
00117 void LookerUpper::HandleAllArtwork(bool aggressive)
00118 {
00119     m_updateartwork = true;
00120 
00121     if (aggressive)
00122         m_updaterules = true;
00123 
00124     // First, handle all recording rules w/ inetrefs
00125     vector<ProgramInfo *> recordingList;
00126 
00127     RemoteGetAllScheduledRecordings(recordingList);
00128     int maxartnum = 3;
00129 
00130     for( int n = 0; n < (int)recordingList.size(); n++)
00131     {
00132         ProgramInfo *pginfo = new ProgramInfo(*(recordingList[n]));
00133         bool dolookup = true;
00134 
00135         if (pginfo->GetInetRef().isEmpty())
00136             dolookup = false;
00137         if (dolookup || aggressive)
00138         {
00139             ArtworkMap map = GetArtwork(pginfo->GetInetRef(), pginfo->GetSeason(), true);
00140             if (map.isEmpty() || (aggressive && map.count() < maxartnum))
00141             {
00142                 QString msg = QString("Looking up artwork for recording rule: %1 %2")
00143                                                .arg(pginfo->GetTitle())
00144                                                .arg(pginfo->GetSubtitle());
00145                 LOG(VB_GENERAL, LOG_INFO, msg);
00146 
00147                 m_busyRecList.append(pginfo);
00148                 m_metadataFactory->Lookup(pginfo, false, true, true);
00149                 continue;
00150             }
00151         }
00152         delete pginfo;
00153     }
00154 
00155     // Now, Attempt to fill in the gaps for recordings
00156     QMap< QString, ProgramInfo* > recMap;
00157     QMap< QString, uint32_t > inUseMap = ProgramInfo::QueryInUseMap();
00158     QMap< QString, bool > isJobRunning = ProgramInfo::QueryJobsRunning(JOB_COMMFLAG);
00159 
00160     ProgramList progList;
00161 
00162     LoadFromRecorded( progList, false, inUseMap, isJobRunning, recMap, -1 );
00163 
00164     for( int n = 0; n < (int)progList.size(); n++)
00165     {
00166         ProgramInfo *pginfo = new ProgramInfo(*(progList[n]));
00167 
00168         bool dolookup = true;
00169 
00170         LookupType type = GuessLookupType(pginfo);
00171 
00172         if (type == kProbableMovie)
00173            maxartnum = 2;
00174 
00175         if ((!aggressive && type == kProbableGenericTelevision) ||
00176              pginfo->GetRecordingGroup() == "Deleted" ||
00177              pginfo->GetRecordingGroup() == "LiveTV")
00178             dolookup = false;
00179         if (dolookup || aggressive)
00180         {
00181             ArtworkMap map = GetArtwork(pginfo->GetInetRef(), pginfo->GetSeason(), true);
00182             if (map.isEmpty() || (aggressive && map.count() < maxartnum))
00183             {
00184                QString msg = QString("Looking up artwork for recording: %1 %2")
00185                                            .arg(pginfo->GetTitle())
00186                                            .arg(pginfo->GetSubtitle());
00187                 LOG(VB_GENERAL, LOG_INFO, msg);
00188 
00189                 m_busyRecList.append(pginfo);
00190                 m_metadataFactory->Lookup(pginfo, false, true, aggressive);
00191                 continue;
00192             }
00193         }
00194         delete pginfo;
00195     }
00196 
00197 }
00198 
00199 void LookerUpper::CopyRuleInetrefsToRecordings()
00200 {
00201     QMap< QString, ProgramInfo* > recMap;
00202     QMap< QString, uint32_t > inUseMap = ProgramInfo::QueryInUseMap();
00203     QMap< QString, bool > isJobRunning = ProgramInfo::QueryJobsRunning(JOB_COMMFLAG);
00204 
00205     ProgramList progList;
00206 
00207     LoadFromRecorded( progList, false, inUseMap, isJobRunning, recMap, -1 );
00208 
00209     for( int n = 0; n < (int)progList.size(); n++)
00210     {
00211         ProgramInfo *pginfo = new ProgramInfo(*(progList[n]));
00212         if (pginfo && pginfo->GetInetRef().isEmpty())
00213         {
00214             RecordingRule *rule = new RecordingRule();
00215             rule->m_recordID = pginfo->GetRecordingRuleID();
00216             rule->Load();
00217             if (!rule->m_inetref.isEmpty())
00218             {
00219                 QString msg = QString("%1").arg(pginfo->GetTitle());
00220                 if (!pginfo->GetSubtitle().isEmpty())
00221                     msg += QString(": %1").arg(pginfo->GetSubtitle());
00222                 msg += " has no inetref, but its recording rule does. Copying...";
00223                 LOG(VB_GENERAL, LOG_INFO, msg);
00224                 pginfo->SaveInetRef(rule->m_inetref);
00225             }
00226             delete rule;
00227         }
00228         delete pginfo;
00229     }
00230 }
00231 
00232 void LookerUpper::customEvent(QEvent *levent)
00233 {
00234     if (levent->type() == MetadataFactoryMultiResult::kEventType)
00235     {
00236         MetadataFactoryMultiResult *mfmr = dynamic_cast<MetadataFactoryMultiResult*>(levent);
00237 
00238         if (!mfmr)
00239             return;
00240 
00241         MetadataLookupList list = mfmr->results;
00242 
00243         if (list.count() > 1)
00244         {
00245             int yearindex = -1;
00246 
00247             for (int p = 0; p != list.size(); ++p)
00248             {
00249                 ProgramInfo *pginfo = qVariantValue<ProgramInfo *>(list[p]->GetData());
00250 
00251                 if (pginfo && !pginfo->GetSeriesID().isEmpty() &&
00252                     pginfo->GetSeriesID() == (list[p])->GetTMSref())
00253                 {
00254                     MetadataLookup *lookup = list.takeAt(p);
00255                     if (!lookup->GetSubtype() == kProbableGenericTelevision)
00256                         pginfo->SaveSeasonEpisode(lookup->GetSeason(), lookup->GetEpisode());
00257                     pginfo->SaveInetRef(lookup->GetInetref());
00258                     m_busyRecList.removeAll(pginfo);
00259                     qDeleteAll(list);
00260                     return;
00261                 }
00262                 else if (pginfo && pginfo->GetYearOfInitialRelease() != 0 &&
00263                          (list[p])->GetYear() != 0 &&
00264                          pginfo->GetYearOfInitialRelease() == (list[p])->GetYear())
00265                 {
00266                     if (yearindex != -1)
00267                     {
00268                         LOG(VB_GENERAL, LOG_INFO, "Multiple results matched on year. No definite "
00269                                       "match could be found.");
00270                         m_busyRecList.removeAll(pginfo);
00271                         qDeleteAll(list);
00272                         return;
00273                     }
00274                     else
00275                     {
00276                         LOG(VB_GENERAL, LOG_INFO, "Matched from multiple results based on year. ");
00277                         yearindex = p;
00278                     }
00279                 }
00280             }
00281 
00282             if (yearindex > -1)
00283             {
00284                 MetadataLookup *lookup = list.takeAt(yearindex);
00285                 ProgramInfo *pginfo = qVariantValue<ProgramInfo *>(lookup->GetData());
00286                 if (!lookup->GetSubtype() == kProbableGenericTelevision)
00287                     pginfo->SaveSeasonEpisode(lookup->GetSeason(), lookup->GetEpisode());
00288                 pginfo->SaveInetRef(lookup->GetInetref());
00289                 m_busyRecList.removeAll(pginfo);
00290                 qDeleteAll(list);
00291                 return;
00292             }
00293 
00294             LOG(VB_GENERAL, LOG_INFO, "Unable to match this title, too many possible matches. "
00295                                       "You may wish to manually set the season, episode, and "
00296                                       "inetref in the 'Watch Recordings' screen.");
00297 
00298             ProgramInfo *pginfo = qVariantValue<ProgramInfo *>(list.takeFirst()->GetData());
00299 
00300             qDeleteAll(list);
00301 
00302             if (pginfo)
00303             {
00304                 m_busyRecList.removeAll(pginfo);
00305             }
00306         }
00307     }
00308     else if (levent->type() == MetadataFactorySingleResult::kEventType)
00309     {
00310         MetadataFactorySingleResult *mfsr =
00311             dynamic_cast<MetadataFactorySingleResult*>(levent);
00312 
00313         if (!mfsr)
00314             return;
00315 
00316         MetadataLookup *lookup = mfsr->result;
00317 
00318         if (!lookup)
00319             return;
00320 
00321         ProgramInfo *pginfo = qVariantValue<ProgramInfo *>(lookup->GetData());
00322 
00323         // This null check could hang us as this pginfo would then never be
00324         // removed
00325         if (!pginfo)
00326             return;
00327 
00328         LOG(VB_GENERAL, LOG_DEBUG, "I found the following data:");
00329         LOG(VB_GENERAL, LOG_DEBUG,
00330             QString("        Input Title: %1").arg(pginfo->GetTitle()));
00331         LOG(VB_GENERAL, LOG_DEBUG,
00332             QString("        Input Sub:   %1").arg(pginfo->GetSubtitle()));
00333         LOG(VB_GENERAL, LOG_DEBUG,
00334             QString("        Title:       %1").arg(lookup->GetTitle()));
00335         LOG(VB_GENERAL, LOG_DEBUG,
00336             QString("        Subtitle:    %1").arg(lookup->GetSubtitle()));
00337         LOG(VB_GENERAL, LOG_DEBUG,
00338             QString("        Season:      %1").arg(lookup->GetSeason()));
00339         LOG(VB_GENERAL, LOG_DEBUG,
00340             QString("        Episode:     %1").arg(lookup->GetEpisode()));
00341         LOG(VB_GENERAL, LOG_DEBUG,
00342             QString("        Inetref:     %1").arg(lookup->GetInetref()));
00343         LOG(VB_GENERAL, LOG_DEBUG,
00344             QString("        User Rating: %1").arg(lookup->GetUserRating()));
00345 
00346         if (!lookup->GetSubtype() == kProbableGenericTelevision)
00347             pginfo->SaveSeasonEpisode(lookup->GetSeason(), lookup->GetEpisode());
00348         pginfo->SaveInetRef(lookup->GetInetref());
00349 
00350         if (m_updaterules)
00351         {
00352             RecordingRule *rule = new RecordingRule();
00353             if (rule)
00354             {
00355                 rule->LoadByProgram(pginfo);
00356                 if (rule->m_inetref.isEmpty() &&
00357                     (rule->m_searchType == kNoSearch))
00358                 {
00359                     rule->m_inetref = lookup->GetInetref();
00360                 }
00361                 rule->m_season = lookup->GetSeason();
00362                 rule->m_episode = lookup->GetEpisode();
00363                 rule->Save();
00364 
00365                 delete rule;
00366             }
00367         }
00368 
00369         if (m_updateartwork)
00370         {
00371             ArtworkMap map = lookup->GetDownloads();
00372             SetArtwork(lookup->GetInetref(), lookup->GetSeason(),
00373                        gCoreContext->GetMasterHostName(), map);
00374         }
00375 
00376         m_busyRecList.removeAll(pginfo);
00377     }
00378     else if (levent->type() == MetadataFactoryNoResult::kEventType)
00379     {
00380         MetadataFactoryNoResult *mfnr = dynamic_cast<MetadataFactoryNoResult*>(levent);
00381 
00382         if (!mfnr)
00383             return;
00384 
00385         MetadataLookup *lookup = mfnr->result;
00386 
00387         if (!lookup)
00388             return;
00389 
00390         ProgramInfo *pginfo = qVariantValue<ProgramInfo *>(lookup->GetData());
00391 
00392         // This null check could hang us as this pginfo would then never be removed
00393         if (!pginfo)
00394             return;
00395 
00396         m_busyRecList.removeAll(pginfo);
00397     }
00398 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends