void ManualSchedule::recordClicked(void) { QDateTime endts = m_startDateTime .addSecs(max(m_durationSpin->GetIntValue() * 60, 60)); if (m_channelList->GetCurrentPos() >= m_chanids.size()) { LOG(VB_GENERAL, LOG_ERR, "Channel out of range."); return; // this can happen if there are no channels.. } ProgramInfo p(m_titleEdit->GetText().trimmed(), m_chanids[m_channelList->GetCurrentPos()], m_startDateTime, endts); RecordingRule *record = new RecordingRule(); record->LoadByProgram(&p); record->m_searchType = kManualSearch; MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack(); ScheduleEditor *schededit = new ScheduleEditor(mainStack, record); if (schededit->Create()) { mainStack->AddScreen(schededit); connect(schededit, SIGNAL(ruleSaved(int)), SLOT(scheduleCreated(int))); } else delete schededit; }
void ViewScheduled::deleteRule() { MythUIButtonListItem *item = m_schedulesList->GetItemCurrent(); if (!item) return; ProgramInfo *pginfo = qVariantValue<ProgramInfo*>(item->GetData()); if (!pginfo) return; RecordingRule *record = new RecordingRule(); if (!record->LoadByProgram(pginfo)) { delete record; return; } QString message = tr("Delete '%1' %2 rule?").arg(record->m_title) .arg(toString(pginfo->GetRecordingRuleType())); MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack"); MythConfirmationDialog *okPopup = new MythConfirmationDialog(popupStack, message, true); okPopup->SetReturnEvent(this, "deleterule"); okPopup->SetData(qVariantFromValue(record)); if (okPopup->Create()) popupStack->AddScreen(okPopup); else delete okPopup; }
void LookerUpper::CopyRuleInetrefsToRecordings() { 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 && pginfo->GetInetRef().isEmpty()) { RecordingRule *rule = new RecordingRule(); rule->LoadByProgram(pginfo); if (!rule->m_inetref.isEmpty()) { QString msg = QString("%1").arg(pginfo->GetTitle()); if (!pginfo->GetSubtitle().isEmpty()) msg += QString(": %1").arg(pginfo->GetSubtitle()); msg += " has no inetref, but its recording rule does. Copying..."; LOG(VB_GENERAL, LOG_INFO, msg); pginfo->SaveInetRef(rule->m_inetref); delete rule; } delete pginfo; } } }
void ProgramRecPriority::edit(MythUIButtonListItem *item) { if (!item) return; ProgramRecPriorityInfo *pgRecInfo = item->GetData().value<ProgramRecPriorityInfo*>(); if (!pgRecInfo) return; RecordingRule *record = new RecordingRule(); record->m_recordID = pgRecInfo->GetRecordingRuleID(); if (record->m_searchType == kNoSearch) record->LoadByProgram(pgRecInfo); MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack(); ScheduleEditor *schededit = new ScheduleEditor(mainStack, record); if (schededit->Create()) { mainStack->AddScreen(schededit); connect(schededit, SIGNAL(ruleSaved(int)), SLOT(scheduleChanged(int))); connect(schededit, SIGNAL(ruleDeleted(int)), SLOT(scheduleChanged(int))); } else delete schededit; }
/** * \brief Creates a dialog for editing an override recording schedule */ void ScheduleCommon::MakeOverride(RecordingInfo *recinfo) { if (!recinfo || !recinfo->GetRecordingRuleID()) return; RecordingRule *recrule = new RecordingRule(); if (!recrule->LoadByProgram(static_cast<ProgramInfo*>(recinfo))) LOG(VB_GENERAL, LOG_ERR, "Failed to load by program info"); if (!recrule->MakeOverride()) { LOG(VB_GENERAL, LOG_ERR, "Failed to make Override"); delete recrule; return; } recrule->m_type = kOverrideRecord; MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack(); ScheduleEditor *schededit = new ScheduleEditor(mainStack, recrule); if (schededit->Create()) mainStack->AddScreen(schededit); else delete schededit; }
void ProgLister::ShowDeleteRuleMenu(void) { ProgramInfo *pi = GetCurrent(); if (!pi || !pi->GetRecordingRuleID()) return; RecordingRule *record = new RecordingRule(); if (!record->LoadByProgram(pi)) { delete record; return; } QString message = tr("Delete '%1' %2 rule?").arg(record->m_title) .arg(toString(pi->GetRecordingRuleType())); MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack"); MythConfirmationDialog *okPopup = new MythConfirmationDialog( popupStack, message, true); okPopup->SetReturnEvent(this, "deleterule"); okPopup->SetData(qVariantFromValue(record)); if (okPopup->Create()) popupStack->AddScreen(okPopup); else delete okPopup; }
/** * \brief Creates a dialog for editing an override recording schedule */ void ScheduleCommon::MakeOverride(RecordingInfo *recinfo, bool startActive) { if (!recinfo || !recinfo->GetRecordingRuleID()) return; RecordingRule *recrule = new RecordingRule(); if (!recrule->LoadByProgram(static_cast<ProgramInfo*>(recinfo))) VERBOSE(VB_IMPORTANT, QString("Failed to load by program info")); if (!recrule->MakeOverride()) { VERBOSE(VB_IMPORTANT, QString("Failed to make Override")); delete recrule; return; } if (startActive) recrule->m_type = kOverrideRecord; MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack(); ScheduleEditor *schededit = new ScheduleEditor(mainStack, recrule); if (schededit->Create()) mainStack->AddScreen(schededit); else delete schededit; }
DTC::RecRule* Dvr::GetRecordSchedule( uint nRecordId, QString sTemplate, int nRecordedId, int nChanId, QDateTime dStartTimeRaw, bool bMakeOverride ) { RecordingRule rule; QDateTime dStartTime = dStartTimeRaw.toUTC(); if (nRecordId > 0) { rule.m_recordID = nRecordId; if (!rule.Load()) throw QString("Record ID does not exist."); } else if (!sTemplate.isEmpty()) { if (!rule.LoadTemplate(sTemplate)) throw QString("Template does not exist."); } else if (nRecordedId > 0) // Loads from the Recorded/Recorded Program Table { // Despite the use of ProgramInfo, this only applies to Recordings. ProgramInfo recInfo(nRecordedId); if (!rule.LoadByProgram(&recInfo)) throw QString("Recording does not exist"); } else if (nChanId > 0 && dStartTime.isValid()) // Loads from Program Table, should NOT be used with recordings { // Despite the use of RecordingInfo, this only applies to programs in the // present or future, not to recordings? Confused yet? RecordingInfo::LoadStatus status; RecordingInfo info(nChanId, dStartTime, false, 0, &status); if (status != RecordingInfo::kFoundProgram) throw QString("Program does not exist."); RecordingRule *pRule = info.GetRecordingRule(); if (bMakeOverride && rule.m_type != kSingleRecord && rule.m_type != kOverrideRecord && rule.m_type != kDontRecord) pRule->MakeOverride(); rule = *pRule; } else { throw QString("Invalid request."); } DTC::RecRule *pRecRule = new DTC::RecRule(); FillRecRuleInfo( pRecRule, &rule ); return pRecRule; }
DTC::RecRuleList* Dvr::GetRecordScheduleList( int nStartIndex, int nCount ) { vector<ProgramInfo *> infoList; RemoteGetAllScheduledRecordings(infoList); // ---------------------------------------------------------------------- // Build Response // ---------------------------------------------------------------------- DTC::RecRuleList *pRecRules = new DTC::RecRuleList(); nStartIndex = min( nStartIndex, (int)infoList.size() ); nCount = (nCount > 0) ? min( nCount, (int)infoList.size() ) : infoList.size(); int nEndIndex = min((nStartIndex + nCount), (int)infoList.size() ); for( int n = nStartIndex; n < nEndIndex; n++) { RecordingRule *rule = new RecordingRule(); ProgramInfo *pInfo = infoList[ n ]; rule->LoadByProgram(pInfo); if (pInfo != NULL) { DTC::RecRule *pRecRule = pRecRules->AddNewRecRule(); FillRecRuleInfo( pRecRule, rule ); delete rule; delete pInfo; } } // ---------------------------------------------------------------------- pRecRules->setStartIndex ( nStartIndex ); pRecRules->setCount ( nCount ); pRecRules->setTotalAvailable( infoList.size() ); pRecRules->setAsOf ( QDateTime::currentDateTime() ); pRecRules->setVersion ( MYTH_BINARY_VERSION ); pRecRules->setProtoVer ( MYTH_PROTO_VERSION ); return pRecRules; }
LookupType GuessLookupType(ProgramInfo *pginfo) { LookupType ret = kUnknownVideo; QString catType = pginfo->GetCategoryType(); if (catType.isEmpty()) catType = pginfo->QueryCategoryType(); if ((!pginfo->GetSubtitle().isEmpty() || pginfo->GetEpisode() > 0) && (catType == "series" || catType == "tvshow" || catType == "show")) ret = kProbableTelevision; else if (catType == "movie" || catType == "film") ret = kProbableMovie; else if (pginfo->GetSeason() > 0 || pginfo->GetEpisode() > 0 || !pginfo->GetSubtitle().isEmpty()) ret = kProbableTelevision; else { // Before committing to something being a movie, we // want to check its rule. If the rule has a season // or episode number, but the recording doesn't, // and the rec doesn't have a subtitle, this is a // generic recording. If neither the rule nor the // recording have an inetref, season, episode, or // subtitle, it's *probably* a movie. If it's some // weird combination of both, we've got to try everything. RecordingRule *rule = new RecordingRule(); rule->LoadByProgram(pginfo); int ruleepisode = rule->m_episode; delete rule; if (ruleepisode == 0 && pginfo->GetEpisode() == 0 && pginfo->GetSubtitle().isEmpty()) ret = kProbableMovie; else if (ruleepisode > 0 && pginfo->GetSubtitle().isEmpty()) ret = kProbableGenericTelevision; else ret = kUnknownVideo; } return ret; }
void LookerUpper::customEvent(QEvent *levent) { if (levent->type() == MetadataFactoryMultiResult::kEventType) { MetadataFactoryMultiResult *mfmr = dynamic_cast<MetadataFactoryMultiResult*>(levent); if (!mfmr) return; MetadataLookupList list = mfmr->results; if (list.count() > 1) { int yearindex = -1; for (int p = 0; p != list.size(); ++p) { ProgramInfo *pginfo = list[p]->GetData().value<ProgramInfo *>(); if (pginfo && !pginfo->GetSeriesID().isEmpty() && pginfo->GetSeriesID() == (list[p])->GetTMSref()) { MetadataLookup *lookup = list[p]; if (lookup->GetSubtype() != kProbableGenericTelevision) pginfo->SaveSeasonEpisode(lookup->GetSeason(), lookup->GetEpisode()); pginfo->SaveInetRef(lookup->GetInetref()); m_busyRecList.removeAll(pginfo); return; } else if (pginfo && pginfo->GetYearOfInitialRelease() != 0 && (list[p])->GetYear() != 0 && pginfo->GetYearOfInitialRelease() == (list[p])->GetYear()) { if (yearindex != -1) { LOG(VB_GENERAL, LOG_INFO, "Multiple results matched on year. No definite " "match could be found."); m_busyRecList.removeAll(pginfo); return; } else { LOG(VB_GENERAL, LOG_INFO, "Matched from multiple results based on year. "); yearindex = p; } } } if (yearindex > -1) { MetadataLookup *lookup = list[yearindex]; ProgramInfo *pginfo = lookup->GetData().value<ProgramInfo *>(); if (lookup->GetSubtype() != kProbableGenericTelevision) pginfo->SaveSeasonEpisode(lookup->GetSeason(), lookup->GetEpisode()); pginfo->SaveInetRef(lookup->GetInetref()); m_busyRecList.removeAll(pginfo); return; } LOG(VB_GENERAL, LOG_INFO, "Unable to match this title, too many possible matches. " "You may wish to manually set the season, episode, and " "inetref in the 'Watch Recordings' screen."); ProgramInfo *pginfo = list[0]->GetData().value<ProgramInfo *>(); if (pginfo) { m_busyRecList.removeAll(pginfo); } } } else if (levent->type() == MetadataFactorySingleResult::kEventType) { MetadataFactorySingleResult *mfsr = dynamic_cast<MetadataFactorySingleResult*>(levent); if (!mfsr) return; MetadataLookup *lookup = mfsr->result; if (!lookup) return; ProgramInfo *pginfo = lookup->GetData().value<ProgramInfo *>(); // This null check could hang us as this pginfo would then never be // removed if (!pginfo) return; LOG(VB_GENERAL, LOG_DEBUG, "I found the following data:"); LOG(VB_GENERAL, LOG_DEBUG, QString(" Input Title: %1").arg(pginfo->GetTitle())); LOG(VB_GENERAL, LOG_DEBUG, QString(" Input Sub: %1").arg(pginfo->GetSubtitle())); LOG(VB_GENERAL, LOG_DEBUG, QString(" Title: %1").arg(lookup->GetTitle())); LOG(VB_GENERAL, LOG_DEBUG, QString(" Subtitle: %1").arg(lookup->GetSubtitle())); LOG(VB_GENERAL, LOG_DEBUG, QString(" Season: %1").arg(lookup->GetSeason())); LOG(VB_GENERAL, LOG_DEBUG, QString(" Episode: %1").arg(lookup->GetEpisode())); LOG(VB_GENERAL, LOG_DEBUG, QString(" Inetref: %1").arg(lookup->GetInetref())); LOG(VB_GENERAL, LOG_DEBUG, QString(" User Rating: %1").arg(lookup->GetUserRating())); if (lookup->GetSubtype() != kProbableGenericTelevision) pginfo->SaveSeasonEpisode(lookup->GetSeason(), lookup->GetEpisode()); pginfo->SaveInetRef(lookup->GetInetref()); if (m_updaterules) { RecordingRule *rule = new RecordingRule(); if (rule) { rule->LoadByProgram(pginfo); if (rule->m_inetref.isEmpty() && (rule->m_searchType == kNoSearch)) { rule->m_inetref = lookup->GetInetref(); } rule->m_season = lookup->GetSeason(); rule->m_episode = lookup->GetEpisode(); rule->Save(); delete rule; } } if (m_updateartwork) { ArtworkMap map = lookup->GetDownloads(); SetArtwork(lookup->GetInetref(), lookup->GetIsCollection() ? 0 : lookup->GetSeason(), gCoreContext->GetMasterHostName(), map); } 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 = lookup->GetData().value<ProgramInfo *>(); // This null check could hang us as this pginfo would then never be removed if (!pginfo) return; m_busyRecList.removeAll(pginfo); } }
void ProgDetails::loadPage(void) { MSqlQuery query(MSqlQuery::InitCon()); QString category_type, showtype, year, syndicatedEpisodeNum; QString rating, colorcode, title_pronounce; float stars = 0.0; int partnumber = 0, parttotal = 0; int audioprop = 0, videoprop = 0, subtype = 0, generic = 0; bool recorded = false; RecordingRule* record = nullptr; if (m_progInfo.GetRecordingRuleID()) { record = new RecordingRule(); record->LoadByProgram(&m_progInfo); } if (m_progInfo.GetFilesize()) recorded = true; QString ptable = recorded ? "recordedprogram" : "program"; if (m_progInfo.GetScheduledEndTime() != m_progInfo.GetScheduledStartTime()) { query.prepare(QString("SELECT category_type, airdate, stars," " partnumber, parttotal, audioprop+0, videoprop+0," " subtitletypes+0, syndicatedepisodenumber, generic," " showtype, colorcode, title_pronounce" " FROM %1 WHERE chanid = :CHANID AND" " starttime = :STARTTIME ;").arg(ptable)); query.bindValue(":CHANID", m_progInfo.GetChanID()); query.bindValue(":STARTTIME", m_progInfo.GetScheduledStartTime()); if (query.exec() && query.next()) { category_type = query.value(0).toString(); year = query.value(1).toString(); stars = query.value(2).toFloat(); partnumber = query.value(3).toInt(); parttotal = query.value(4).toInt(); audioprop = query.value(5).toInt(); videoprop = query.value(6).toInt(); subtype = query.value(7).toInt(); syndicatedEpisodeNum = query.value(8).toString(); generic = query.value(9).toInt(); showtype = query.value(10).toString(); colorcode = query.value(11).toString(); title_pronounce = query.value(12).toString(); } else if (!query.isActive()) MythDB::DBError("ProgDetails", query); rating = getRatings( recorded, m_progInfo.GetChanID(), m_progInfo.GetScheduledStartTime()); } if (category_type.isEmpty() && !m_progInfo.GetProgramID().isEmpty()) { QString prefix = m_progInfo.GetProgramID().left(2); if (prefix == "MV") category_type = "movie"; else if (prefix == "EP") category_type = "series"; else if (prefix == "SP") category_type = "sports"; else if (prefix == "SH") category_type = "tvshow"; } addItem(tr("Title"), m_progInfo.toString(ProgramInfo::kTitleSubtitle, " - "), ProgInfoList::kLevel1); addItem(tr("Title Pronounce"), title_pronounce, ProgInfoList::kLevel2); QString s = m_progInfo.GetDescription(); QString attr; if (partnumber > 0) attr += tr("Part %1 of %2, ").arg(partnumber).arg(parttotal); if (!rating.isEmpty() && rating != "NR") attr += rating + ", "; if (category_type == "movie") { if (!year.isEmpty()) attr += year + ", "; /* see #7810, was hardcoded to 4 star system, when every theme * uses 10 stars / 5 stars with half stars */ if (stars > 0.0f) attr += tr("%n star(s)", "", roundf(stars * 10.0f)) + ", "; } if (!colorcode.isEmpty()) attr += colorcode + ", "; if (audioprop & AUD_MONO) attr += tr("Mono") + ", "; if (audioprop & AUD_STEREO) attr += tr("Stereo") + ", "; if (audioprop & AUD_SURROUND) attr += tr("Surround Sound") + ", "; if (audioprop & AUD_DOLBY) attr += tr("Dolby Sound") + ", "; if (audioprop & AUD_HARDHEAR) attr += tr("Audio for Hearing Impaired") + ", "; if (audioprop & AUD_VISUALIMPAIR) attr += tr("Audio for Visually Impaired") + ", "; if (videoprop & VID_HDTV) attr += tr("HDTV") + ", "; if (videoprop & VID_WIDESCREEN) attr += tr("Widescreen") + ", "; if (videoprop & VID_AVC) attr += tr("AVC/H.264") + ", "; if (videoprop & VID_720) attr += tr("720p Resolution") + ", "; if (videoprop & VID_1080) attr += tr("1080i/p Resolution") + ", "; if (videoprop & VID_DAMAGED) attr += tr("Damaged") + ", "; if (subtype & SUB_HARDHEAR) attr += tr("CC","Closed Captioned") + ", "; if (subtype & SUB_NORMAL) attr += tr("Subtitles Available") + ", "; if (subtype & SUB_ONSCREEN) attr += tr("Subtitled") + ", "; if (subtype & SUB_SIGNED) attr += tr("Deaf Signing") + ", "; if (generic && category_type == "series") attr += tr("Unidentified Episode") + ", "; else if (m_progInfo.IsRepeat()) attr += tr("Repeat") + ", "; if (!attr.isEmpty()) { attr.truncate(attr.lastIndexOf(',')); s += " (" + attr + ")"; } addItem(tr("Description"), s, ProgInfoList::kLevel1); QString actors, directors, producers, execProducers; QString writers, guestStars, hosts, adapters; QString presenters, commentators, guests; if (m_progInfo.GetScheduledEndTime() != m_progInfo.GetScheduledStartTime()) { if (recorded) query.prepare("SELECT role,people.name FROM recordedcredits" " AS credits" " LEFT JOIN people ON credits.person = people.person" " WHERE credits.chanid = :CHANID" " AND credits.starttime = :STARTTIME" " ORDER BY role;"); else query.prepare("SELECT role,people.name FROM credits" " LEFT JOIN people ON credits.person = people.person" " WHERE credits.chanid = :CHANID" " AND credits.starttime = :STARTTIME" " ORDER BY role;"); query.bindValue(":CHANID", m_progInfo.GetChanID()); query.bindValue(":STARTTIME", m_progInfo.GetScheduledStartTime()); if (query.exec() && query.size() > 0) { QStringList plist; QString rstr, role, pname; while(query.next()) { role = query.value(0).toString(); /* The people.name column uses utf8_bin collation. * Qt-MySQL drivers use QVariant::ByteArray for string-type * MySQL fields marked with the BINARY attribute (those using a * *_bin collation) and QVariant::String for all others. * Since QVariant::toString() uses QString::fromAscii() * (through QVariant::convert()) when the QVariant's type is * QVariant::ByteArray, we have to use QString::fromUtf8() * explicitly to prevent corrupting characters. * The following code should be changed to use the simpler * toString() approach, as above, if we do a DB update to * coalesce the people.name values that differ only in case and * change the collation to utf8_general_ci, to match the * majority of other columns, or we'll have the same problem in * reverse. */ pname = QString::fromUtf8(query.value(1) .toByteArray().constData()); if (rstr != role) { if (rstr == "actor") actors = plist.join(", "); else if (rstr == "director") directors = plist.join(", "); else if (rstr == "producer") producers = plist.join(", "); else if (rstr == "executive_producer") execProducers = plist.join(", "); else if (rstr == "writer") writers = plist.join(", "); else if (rstr == "guest_star") guestStars = plist.join(", "); else if (rstr == "host") hosts = plist.join(", "); else if (rstr == "adapter") adapters = plist.join(", "); else if (rstr == "presenter") presenters = plist.join(", "); else if (rstr == "commentator") commentators = plist.join(", "); else if (rstr == "guest") guests = plist.join(", "); rstr = role; plist.clear(); } plist.append(pname); } if (rstr == "actor") actors = plist.join(", "); else if (rstr == "director") directors = plist.join(", "); else if (rstr == "producer") producers = plist.join(", "); else if (rstr == "executive_producer") execProducers = plist.join(", "); else if (rstr == "writer") writers = plist.join(", "); else if (rstr == "guest_star") guestStars = plist.join(", "); else if (rstr == "host") hosts = plist.join(", "); else if (rstr == "adapter") adapters = plist.join(", "); else if (rstr == "presenter") presenters = plist.join(", "); else if (rstr == "commentator") commentators = plist.join(", "); else if (rstr == "guest") guests = plist.join(", "); } } addItem(tr("Actors"), actors, ProgInfoList::kLevel1); addItem(tr("Guest Star"), guestStars, ProgInfoList::kLevel1); addItem(tr("Guest"), guests, ProgInfoList::kLevel1); addItem(tr("Host"), hosts, ProgInfoList::kLevel1); addItem(tr("Presenter"), presenters, ProgInfoList::kLevel1); addItem(tr("Commentator"), commentators, ProgInfoList::kLevel1); addItem(tr("Director"), directors, ProgInfoList::kLevel1); addItem(tr("Producer"), producers, ProgInfoList::kLevel2); addItem(tr("Executive Producer"), execProducers, ProgInfoList::kLevel2); addItem(tr("Writer"), writers, ProgInfoList::kLevel2); addItem(tr("Adapter"), adapters, ProgInfoList::kLevel2); addItem(tr("Category"), m_progInfo.GetCategory(), ProgInfoList::kLevel1); query.prepare("SELECT genre FROM programgenres " "WHERE chanid = :CHANID AND starttime = :STARTTIME " "AND relevance > 0 ORDER BY relevance;"); query.bindValue(":CHANID", m_progInfo.GetChanID()); query.bindValue(":STARTTIME", m_progInfo.GetScheduledStartTime()); if (query.exec()) { s.clear(); while (query.next()) { if (!s.isEmpty()) s += ", "; s += query.value(0).toString(); } addItem(tr("Genre"), s, ProgInfoList::kLevel1); } s.clear(); if (!category_type.isEmpty()) { s = category_type; if (!m_progInfo.GetSeriesID().isEmpty()) s += " (" + m_progInfo.GetSeriesID() + ")"; if (!showtype.isEmpty()) s += " " + showtype; } addItem(tr("Type", "category_type"), s, ProgInfoList::kLevel1); s.clear(); if (m_progInfo.GetSeason() > 0) s = QString::number(m_progInfo.GetSeason()); addItem(tr("Season"), s, ProgInfoList::kLevel1); s.clear(); if (m_progInfo.GetEpisode() > 0) { if (m_progInfo.GetEpisodeTotal() > 0) s = tr("%1 of %2").arg(m_progInfo.GetEpisode()) .arg(m_progInfo.GetEpisodeTotal()); else s = QString::number(m_progInfo.GetEpisode()); } addItem(tr("Episode"), s, ProgInfoList::kLevel1); addItem(tr("Syndicated Episode Number"), syndicatedEpisodeNum, ProgInfoList::kLevel1); s.clear(); if (m_progInfo.GetOriginalAirDate().isValid() && category_type != "movie") { s = MythDate::toString(m_progInfo.GetOriginalAirDate(), MythDate::kDateFull | MythDate::kAddYear); } addItem(tr("Original Airdate"), s, ProgInfoList::kLevel1); addItem(tr("Program ID"), m_progInfo.GetProgramID(), ProgInfoList::kLevel1); // Begin MythTV information not found in the listings info QDateTime statusDate; if (m_progInfo.GetRecordingStatus() == RecStatus::WillRecord || m_progInfo.GetRecordingStatus() == RecStatus::Pending) statusDate = m_progInfo.GetScheduledStartTime(); RecordingType rectype = kSingleRecord; // avoid kNotRecording RecStatus::Type recstatus = m_progInfo.GetRecordingStatus(); if (recstatus == RecStatus::PreviousRecording || recstatus == RecStatus::NeverRecord || recstatus == RecStatus::Unknown) { query.prepare("SELECT recstatus, starttime " "FROM oldrecorded WHERE duplicate > 0 AND " "future = 0 AND " "((programid <> '' AND programid = :PROGRAMID) OR " " (title <> '' AND title = :TITLE AND " " subtitle <> '' AND subtitle = :SUBTITLE AND " " description <> '' AND description = :DECRIPTION));"); query.bindValue(":PROGRAMID", m_progInfo.GetProgramID()); query.bindValue(":TITLE", m_progInfo.GetTitle()); query.bindValue(":SUBTITLE", m_progInfo.GetSubtitle()); query.bindValue(":DECRIPTION", m_progInfo.GetDescription()); if (!query.exec()) { MythDB::DBError("showDetails", query); } else if (query.next()) { if (recstatus == RecStatus::Unknown) recstatus = RecStatus::Type(query.value(0).toInt()); if (recstatus == RecStatus::PreviousRecording || recstatus == RecStatus::NeverRecord || recstatus == RecStatus::Recorded) { statusDate = MythDate::as_utc(query.value(1).toDateTime()); } } } if (recstatus == RecStatus::Unknown) { if (recorded) { recstatus = RecStatus::Recorded; statusDate = m_progInfo.GetScheduledStartTime(); } else { // re-enable "Not Recording" status text rectype = m_progInfo.GetRecordingRuleType(); } } s = RecStatus::toString(recstatus, rectype); if (statusDate.isValid()) s += " " + MythDate::toString(statusDate, MythDate::kDateFull | MythDate::kAddYear); addItem(tr("MythTV Status"), s, ProgInfoList::kLevel1); QString recordingRule; QString lastRecorded; QString nextRecording; QString averageTimeShift; QString watchListScore; QString watchListStatus; QString searchPhrase; if (m_progInfo.GetRecordingRuleID()) { recordingRule = QString("%1, ").arg(m_progInfo.GetRecordingRuleID()); if (m_progInfo.GetRecordingRuleType() != kNotRecording) recordingRule += toString(m_progInfo.GetRecordingRuleType()); if (!(record->m_title.isEmpty())) recordingRule += QString(" \"%2\"").arg(record->m_title); query.prepare("SELECT last_record, next_record, avg_delay " "FROM record WHERE recordid = :RECORDID"); query.bindValue(":RECORDID", m_progInfo.GetRecordingRuleID()); if (query.exec() && query.next()) { if (query.value(0).toDateTime().isValid()) lastRecorded = MythDate::toString( MythDate::as_utc(query.value(0).toDateTime()), MythDate::kDateFull | MythDate::kAddYear); if (query.value(1).toDateTime().isValid()) nextRecording = MythDate::toString( MythDate::as_utc(query.value(1).toDateTime()), MythDate::kDateFull | MythDate::kAddYear); if (query.value(2).toInt() > 0) averageTimeShift = tr("%n hour(s)", "", query.value(2).toInt()); } if (recorded) { if (m_progInfo.GetRecordingPriority2() > 0) watchListScore = QString::number(m_progInfo.GetRecordingPriority2()); if (m_progInfo.GetRecordingPriority2() < 0) { switch (m_progInfo.GetRecordingPriority2()) { case wlExpireOff: watchListStatus = tr("Auto-expire off"); break; case wlWatched: watchListStatus = tr("Marked as 'watched'"); break; case wlEarlier: watchListStatus = tr("Not the earliest episode"); break; case wlDeleted: watchListStatus = tr("Recently deleted episode"); break; } } } if (record->m_searchType != kManualSearch && record->m_description != m_progInfo.GetDescription()) searchPhrase = record->m_description; } addItem(tr("Recording Rule"), recordingRule, ProgInfoList::kLevel1); addItem(tr("Search Phrase"), searchPhrase, ProgInfoList::kLevel1); s.clear(); if (m_progInfo.GetFindID()) { QDateTime fdate(QDate(1970, 1, 1),QTime(12,0,0)); fdate = fdate.addDays((int)m_progInfo.GetFindID() - 719528); s = QString("%1 (%2)").arg(m_progInfo.GetFindID()) .arg(MythDate::toString( fdate, MythDate::kDateFull | MythDate::kAddYear)); } addItem(tr("Find ID"), s, ProgInfoList::kLevel2); addItem(tr("Last Recorded"), lastRecorded, ProgInfoList::kLevel2); addItem(tr("Next Recording"), nextRecording, ProgInfoList::kLevel2); addItem(tr("Average Time Shift"), averageTimeShift, ProgInfoList::kLevel2); addItem(tr("Watch List Score"), watchListScore, ProgInfoList::kLevel2); addItem(tr("Watch List Status"), watchListStatus, ProgInfoList::kLevel2); QString recordingHost; QString recordingInput; QString recordedFilename; QString recordedFileSize; QString recordingGroup; QString storageGroup; QString playbackGroup; QString recordingProfile; recordingHost = m_progInfo.GetHostname(); recordingInput = m_progInfo.GetInputName(); if (recorded) { recordedFilename = m_progInfo.GetBasename(); recordedFileSize = QString("%1 ") .arg(m_progInfo.GetFilesize()/((double)(1<<30)),0,'f',2); recordedFileSize += tr("GB", "GigaBytes"); query.prepare("SELECT profile FROM recorded" " WHERE chanid = :CHANID" " AND starttime = :STARTTIME;"); query.bindValue(":CHANID", m_progInfo.GetChanID()); query.bindValue(":STARTTIME", m_progInfo.GetRecordingStartTime()); if (query.exec() && query.next()) { recordingProfile = m_progInfo.i18n(query.value(0).toString()); } recordingGroup = m_progInfo.i18n(m_progInfo.GetRecordingGroup()); storageGroup = m_progInfo.i18n(m_progInfo.GetStorageGroup()); playbackGroup = m_progInfo.i18n(m_progInfo.GetPlaybackGroup()); } else if (m_progInfo.GetRecordingRuleID()) { recordingProfile = record->m_recProfile; } addItem(tr("Recording Host"), recordingHost, ProgInfoList::kLevel2); addItem(tr("Recording Input"), recordingInput, ProgInfoList::kLevel2); addItem(tr("Recorded File Name"), recordedFilename, ProgInfoList::kLevel1); addItem(tr("Recorded File Size"), recordedFileSize, ProgInfoList::kLevel1); addItem(tr("Recording Profile"), recordingProfile, ProgInfoList::kLevel2); addItem(tr("Recording Group"), recordingGroup, ProgInfoList::kLevel1); addItem(tr("Storage Group"), storageGroup, ProgInfoList::kLevel2); addItem(tr("Playback Group"), playbackGroup, ProgInfoList::kLevel2); PowerPriorities(ptable); delete record; }
void ProgDetails::loadPage(void) { loadHTML(); MSqlQuery query(MSqlQuery::InitCon()); QString fullDateFormat = gCoreContext->GetSetting("DateFormat", "M/d/yyyy"); if (!fullDateFormat.contains("yyyy")) fullDateFormat += " yyyy"; QString category_type, showtype, year, epinum, rating, colorcode, title_pronounce; float stars = 0.0; int partnumber = 0, parttotal = 0; int audioprop = 0, videoprop = 0, subtype = 0, generic = 0; bool recorded = false; RecordingRule* record = NULL; if (m_progInfo.GetRecordingRuleID()) { record = new RecordingRule(); record->LoadByProgram(&m_progInfo); } if (m_progInfo.GetFilesize()) recorded = true; if (m_progInfo.GetScheduledEndTime() != m_progInfo.GetScheduledStartTime()) { QString ptable = "program"; if (recorded) ptable = "recordedprogram"; query.prepare(QString("SELECT category_type, airdate, stars," " partnumber, parttotal, audioprop+0, videoprop+0," " subtitletypes+0, syndicatedepisodenumber, generic," " showtype, colorcode, title_pronounce" " FROM %1 WHERE chanid = :CHANID AND" " starttime = :STARTTIME ;").arg(ptable)); query.bindValue(":CHANID", m_progInfo.GetChanID()); query.bindValue(":STARTTIME", m_progInfo.GetScheduledStartTime()); if (query.exec() && query.next()) { category_type = query.value(0).toString(); year = query.value(1).toString(); stars = query.value(2).toDouble(); partnumber = query.value(3).toInt(); parttotal = query.value(4).toInt(); audioprop = query.value(5).toInt(); videoprop = query.value(6).toInt(); subtype = query.value(7).toInt(); epinum = query.value(8).toString(); generic = query.value(9).toInt(); showtype = query.value(10).toString(); colorcode = query.value(11).toString(); title_pronounce = query.value(12).toString(); } else if (!query.isActive()) MythDB::DBError("ProgDetails", query); rating = getRatings( recorded, m_progInfo.GetChanID(), m_progInfo.GetScheduledStartTime()); } if (category_type.isEmpty() && !m_progInfo.GetProgramID().isEmpty()) { QString prefix = m_progInfo.GetProgramID().left(2); if (prefix == "MV") category_type = "movie"; else if (prefix == "EP") category_type = "series"; else if (prefix == "SP") category_type = "sports"; else if (prefix == "SH") category_type = "tvshow"; } addItem("TITLE", tr("Title"), m_progInfo.toString(ProgramInfo::kTitleSubtitle, " - ")); addItem("TITLE_PRONOUNCE", tr("Title Pronounce"), title_pronounce); QString s = m_progInfo.GetDescription(); QString attr; if (partnumber > 0) attr += QString(tr("Part %1 of %2, ")).arg(partnumber).arg(parttotal); if (!rating.isEmpty() && rating != "NR") attr += rating + ", "; if (category_type == "movie") { if (!year.isEmpty()) attr += year + ", "; if (stars > 0.0) attr += tr("%n star(s)", "", (int) (stars * 4.0)) + ", "; } if (!colorcode.isEmpty()) attr += colorcode + ", "; if (audioprop & AUD_MONO) attr += tr("Mono") + ", "; if (audioprop & AUD_STEREO) attr += tr("Stereo") + ", "; if (audioprop & AUD_SURROUND) attr += tr("Surround Sound") + ", "; if (audioprop & AUD_DOLBY) attr += tr("Dolby Sound") + ", "; if (audioprop & AUD_HARDHEAR) attr += tr("Audio for Hearing Impaired") + ", "; if (audioprop & AUD_VISUALIMPAIR) attr += tr("Audio for Visually Impaired") + ", "; if (videoprop & VID_HDTV) attr += tr("HDTV") + ", "; if (videoprop & VID_WIDESCREEN) attr += tr("Widescreen") + ", "; if (videoprop & VID_AVC) attr += tr("AVC/H.264") + ", "; if (videoprop & VID_720) attr += tr("720p Resolution") + ", "; if (videoprop & VID_1080) attr += tr("1080i/p Resolution") + ", "; if (subtype & SUB_HARDHEAR) attr += tr("CC","Closed Captioned") + ", "; if (subtype & SUB_NORMAL) attr += tr("Subtitles Available") + ", "; if (subtype & SUB_ONSCREEN) attr += tr("Subtitled") + ", "; if (subtype & SUB_SIGNED) attr += tr("Deaf Signing") + ", "; if (generic && category_type == "series") attr += tr("Unidentified Episode") + ", "; else if (m_progInfo.IsRepeat()) attr += tr("Repeat") + ", "; if (!attr.isEmpty()) { attr.truncate(attr.lastIndexOf(',')); s += " (" + attr + ")"; } addItem("DESCRIPTION", tr("Description"), s); s.clear(); if (!m_progInfo.GetCategory().isEmpty()) { s = m_progInfo.GetCategory(); query.prepare("SELECT genre FROM programgenres " "WHERE chanid = :CHANID AND starttime = :STARTTIME " "AND relevance > 0 ORDER BY relevance;"); query.bindValue(":CHANID", m_progInfo.GetChanID()); query.bindValue(":STARTTIME", m_progInfo.GetScheduledStartTime()); if (query.exec()) { while (query.next()) s += ", " + query.value(0).toString(); } } addItem("CATEGORY", tr("Category"), s); s.clear(); if (!category_type.isEmpty()) { s = category_type; if (!m_progInfo.GetSeriesID().isEmpty()) s += " (" + m_progInfo.GetSeriesID() + ")"; if (!showtype.isEmpty()) s += " " + showtype; } addItem("CATEGORY_TYPE", tr("Type", "category_type"), s); addItem("EPISODE", tr("Episode Number"), epinum); s.clear(); if (m_progInfo.GetOriginalAirDate().isValid() && category_type != "movie") { s = m_progInfo.GetOriginalAirDate().toString(fullDateFormat); } addItem("ORIGINAL_AIRDATE", tr("Original Airdate"), s); addItem("PROGRAMID", tr("Program ID"), m_progInfo.GetProgramID()); QString actors, directors, producers, execProducers; QString writers, guestStars, hosts, adapters; QString presenters, commentators, guests; if (m_progInfo.GetScheduledEndTime() != m_progInfo.GetScheduledStartTime()) { if (recorded) query.prepare("SELECT role,people.name FROM recordedcredits" " AS credits" " LEFT JOIN people ON credits.person = people.person" " WHERE credits.chanid = :CHANID" " AND credits.starttime = :STARTTIME" " ORDER BY role;"); else query.prepare("SELECT role,people.name FROM credits" " LEFT JOIN people ON credits.person = people.person" " WHERE credits.chanid = :CHANID" " AND credits.starttime = :STARTTIME" " ORDER BY role;"); query.bindValue(":CHANID", m_progInfo.GetChanID()); query.bindValue(":STARTTIME", m_progInfo.GetScheduledStartTime()); if (query.exec() && query.size() > 0) { QStringList plist; QString rstr, role, pname; while(query.next()) { role = query.value(0).toString(); /* The people.name column uses utf8_bin collation. * Qt-MySQL drivers use QVariant::ByteArray for string-type * MySQL fields marked with the BINARY attribute (those using a * *_bin collation) and QVariant::String for all others. * Since QVariant::toString() uses QString::fromAscii() * (through QVariant::convert()) when the QVariant's type is * QVariant::ByteArray, we have to use QString::fromUtf8() * explicitly to prevent corrupting characters. * The following code should be changed to use the simpler * toString() approach, as above, if we do a DB update to * coalesce the people.name values that differ only in case and * change the collation to utf8_general_ci, to match the * majority of other columns, or we'll have the same problem in * reverse. */ pname = QString::fromUtf8(query.value(1) .toByteArray().constData()); if (rstr != role) { if (rstr == "actor") actors = plist.join(", "); else if (rstr == "director") directors = plist.join(", "); else if (rstr == "producer") producers = plist.join(", "); else if (rstr == "executive_producer") execProducers = plist.join(", "); else if (rstr == "writer") writers = plist.join(", "); else if (rstr == "guest_star") guestStars = plist.join(", "); else if (rstr == "host") hosts = plist.join(", "); else if (rstr == "adapter") adapters = plist.join(", "); else if (rstr == "presenter") presenters = plist.join(", "); else if (rstr == "commentator") commentators = plist.join(", "); else if (rstr == "guest") guests = plist.join(", "); rstr = role; plist.clear(); } plist.append(pname); } if (rstr == "actor") actors = plist.join(", "); else if (rstr == "director") directors = plist.join(", "); else if (rstr == "producer") producers = plist.join(", "); else if (rstr == "executive_producer") execProducers = plist.join(", "); else if (rstr == "writer") writers = plist.join(", "); else if (rstr == "guest_star") guestStars = plist.join(", "); else if (rstr == "host") hosts = plist.join(", "); else if (rstr == "adapter") adapters = plist.join(", "); else if (rstr == "presenter") presenters = plist.join(", "); else if (rstr == "commentator") commentators = plist.join(", "); else if (rstr == "guest") guests = plist.join(", "); } } addItem("ACTORS", tr("Actors"), actors); addItem("DIRECTOR", tr("Director"), directors); addItem("PRODUCER", tr("Producer"), producers); addItem("EXECUTIVE_PRODUCER", tr("Executive Producer"), execProducers); addItem("WRITER", tr("Writer"), writers); addItem("GUEST_STAR", tr("Guest Star"), guestStars); addItem("HOST", tr("Host"), hosts); addItem("ADAPTER", tr("Adapter"), adapters); addItem("PRESENTER", tr("Presenter"), presenters); addItem("COMMENTATOR", tr("Commentator"), commentators); addItem("GUEST", tr("Guest"), guests); // Begin MythTV information not found in the listings info // msg += "<br>"; QDateTime statusDate; if (m_progInfo.GetRecordingStatus() == rsWillRecord) statusDate = m_progInfo.GetScheduledStartTime(); RecordingType rectype = kSingleRecord; // avoid kNotRecording RecStatusType recstatus = m_progInfo.GetRecordingStatus(); if (recstatus == rsPreviousRecording || recstatus == rsNeverRecord || recstatus == rsUnknown) { query.prepare("SELECT recstatus, starttime " "FROM oldrecorded WHERE duplicate > 0 AND " "future = 0 AND " "((programid <> '' AND programid = :PROGRAMID) OR " " (title <> '' AND title = :TITLE AND " " subtitle <> '' AND subtitle = :SUBTITLE AND " " description <> '' AND description = :DECRIPTION));"); query.bindValue(":PROGRAMID", m_progInfo.GetProgramID()); query.bindValue(":TITLE", m_progInfo.GetTitle()); query.bindValue(":SUBTITLE", m_progInfo.GetSubtitle()); query.bindValue(":DECRIPTION", m_progInfo.GetDescription()); if (!query.exec()) { MythDB::DBError("showDetails", query); } else if (query.next()) { if (recstatus == rsUnknown) recstatus = RecStatusType(query.value(0).toInt()); if (recstatus == rsPreviousRecording || recstatus == rsNeverRecord || recstatus == rsRecorded) { statusDate = query.value(1).toDateTime(); } } } if (recstatus == rsUnknown) { if (recorded) { recstatus = rsRecorded; statusDate = m_progInfo.GetScheduledStartTime(); } else { // re-enable "Not Recording" status text rectype = m_progInfo.GetRecordingRuleType(); } } s = toString(recstatus, rectype); if (statusDate.isValid()) s += " " + statusDate.toString(fullDateFormat); addItem("MYTHTV_STATUS", QString("MythTV " + tr("Status")), s); QString recordingRule; QString lastRecorded; QString nextRecording; QString averageTimeShift; QString watchListScore; QString watchListStatus; QString searchPhrase; if (m_progInfo.GetRecordingRuleID()) { recordingRule = QString("%1, ").arg(m_progInfo.GetRecordingRuleID()); if (m_progInfo.GetRecordingRuleType() != kNotRecording) recordingRule += toString(m_progInfo.GetRecordingRuleType()); if (!(record->m_title.isEmpty())) recordingRule += QString(" \"%2\"").arg(record->m_title); query.prepare("SELECT last_record, next_record, avg_delay " "FROM record WHERE recordid = :RECORDID"); query.bindValue(":RECORDID", m_progInfo.GetRecordingRuleID()); if (query.exec() && query.next()) { if (query.value(0).toDateTime().isValid()) lastRecorded = query.value(0).toDateTime().toString(fullDateFormat); if (query.value(1).toDateTime().isValid()) nextRecording = query.value(1).toDateTime().toString(fullDateFormat); if (query.value(2).toInt() > 0) averageTimeShift = tr("%n hour(s)", "", query.value(2).toInt()); } if (recorded) { if (m_progInfo.GetRecordingPriority2() > 0) watchListScore = QString::number(m_progInfo.GetRecordingPriority2()); if (m_progInfo.GetRecordingPriority2() < 0) { switch (m_progInfo.GetRecordingPriority2()) { case wlExpireOff: watchListStatus = tr("Auto-expire off"); break; case wlWatched: watchListStatus = tr("Marked as 'watched'"); break; case wlEarlier: watchListStatus = tr("Not the earliest episode"); break; case wlDeleted: watchListStatus = tr("Recently deleted episode"); break; } } } if (record->m_searchType != kManualSearch && record->m_description != m_progInfo.GetDescription()) { searchPhrase = record->m_description .replace("<", "<").replace(">", ">").replace("\n", " "); } } addItem("RECORDING_RULE", tr("Recording Rule"), recordingRule); addItem("LAST_RECORDED", tr("Last Recorded"), lastRecorded); addItem("NEXT_RECORDING", tr("Next Recording"), nextRecording); addItem("AVERAGE_TIME_SHIFT", tr("Average Time Shift"), averageTimeShift); addItem("WATCH_LIST_SCORE", tr("Watch List Score"), watchListScore); addItem("WATCH_LIST_STATUS", tr("Watch List Status"), watchListStatus); addItem("SEARCH_PHRASE", tr("Search Phrase"), searchPhrase); s.clear(); if (m_progInfo.GetFindID()) { QDate fdate(1970, 1, 1); fdate = fdate.addDays((int)m_progInfo.GetFindID() - 719528); s = QString("%1 (%2)").arg(m_progInfo.GetFindID()) .arg(fdate.toString(fullDateFormat)); } addItem("FINDID", tr("Find ID"), s); QString recordingHost; QString recordedFilename; QString recordedFileSize; QString recordingGroup; QString storageGroup; QString playbackGroup; QString recordingProfile; if (recorded) { recordingHost = m_progInfo.GetHostname(); recordedFilename = m_progInfo.GetBasename(); recordedFileSize = QString("%1 ") .arg(m_progInfo.GetFilesize()/((double)(1<<30)),0,'f',2); recordedFileSize += tr("GB", "GigaBytes"); query.prepare("SELECT profile FROM recorded" " WHERE chanid = :CHANID" " AND starttime = :STARTTIME;"); query.bindValue(":CHANID", m_progInfo.GetChanID()); query.bindValue(":STARTTIME", m_progInfo.GetRecordingStartTime()); if (query.exec() && query.next()) { recordingProfile = m_progInfo.i18n(query.value(0).toString()); } recordingGroup = m_progInfo.i18n(m_progInfo.GetRecordingGroup()); storageGroup = m_progInfo.i18n(m_progInfo.GetStorageGroup()); playbackGroup = m_progInfo.i18n(m_progInfo.GetPlaybackGroup()); } else if (m_progInfo.GetRecordingRuleID()) { recordingProfile = record->m_recProfile; } addItem("RECORDING_HOST", tr("Recording Host"), recordingHost); addItem("RECORDED_FILE_NAME", tr("Recorded File Name"), recordedFilename); addItem("RECORDED_FILE_SIZE", tr("Recorded File Size"), recordedFileSize); addItem("RECORDING_PROFILE", tr("Recording Profile"), recordingProfile); addItem("RECORDING_GROUP", tr("Recording Group"), recordingGroup); addItem("STORAGE_GROUP", tr("Storage Group"), storageGroup); addItem("PLAYBACK_GROUP", tr("Playback Group"), playbackGroup); m_page[m_currentPage] = m_html.join("\n"); delete record; }