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
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
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
00324
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
00393 if (!pginfo)
00394 return;
00395
00396 m_busyRecList.removeAll(pginfo);
00397 }
00398 }