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 ProgramRecPriority::countMatches() { m_listMatch.clear(); m_conMatch.clear(); m_nowMatch.clear(); m_recMatch.clear(); ProgramList schedList; LoadFromScheduler(schedList); QDateTime now = MythDate::current(); ProgramList::const_iterator it = schedList.begin(); for (; it != schedList.end(); ++it) { const RecStatus::Type recstatus = (**it).GetRecordingStatus(); const uint recordid = (**it).GetRecordingRuleID(); if ((**it).GetRecordingEndTime() > now && recstatus != RecStatus::NotListed) { m_listMatch[recordid]++; if (recstatus == RecStatus::Conflict || recstatus == RecStatus::Offline) m_conMatch[recordid]++; else if (recstatus == RecStatus::WillRecord) m_recMatch[recordid]++; else if (recstatus == RecStatus::Recording) { m_nowMatch[recordid]++; m_recMatch[recordid]++; } } } }
void Bank::createFromXml( istringstream& is, ProgramList& list ) { Document doc; try { doc.Parse( is.str(), true ); Node* moduleNode = doc.FirstChild( "Module", false ); if( moduleNode != NULL ) { Program* program = new Program(); createFromXml( is, *program ); list.push_back( program ); } else { Iterator< Element > it( "Program" ); for( it = it.begin( &doc ); it != it.end(); it++ ) { Program* program = new Program(); Element* programElement = it.Get(); readProgram( programElement, program ); list.push_back( program ); } } } catch( const exception& e ) { TRACE( e.what() ); } }
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->m_recordID = pginfo->GetRecordingRuleID(); rule->Load(); 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 LookerUpper::HandleAllRecordings(bool updaterules) { QMap< QString, ProgramInfo* > recMap; QMap< QString, uint32_t > inUseMap = ProgramInfo::QueryInUseMap(); QMap< QString, bool > isJobRunning = ProgramInfo::QueryJobsRunning(JOB_COMMFLAG); m_updaterules = updaterules; 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->GetRecordingGroup() != "Deleted") && (pginfo->GetRecordingGroup() != "LiveTV") && (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()); LOG(VB_GENERAL, LOG_INFO, msg); m_busyRecList.append(pginfo); m_metadataFactory->Lookup(pginfo, true, false, false); } else delete pginfo; } }
OnsetDetector::ProgramList OnsetDetector::getPrograms() const { ProgramList programs; programs.push_back(""); programs.push_back("General purpose"); programs.push_back("Soft onsets"); programs.push_back("Percussive onsets"); return programs; }
TemplateDetector::ProgramList TemplateDetector::getPrograms() const { ProgramList list; list.push_back("blow1"); list.push_back("blow2"); // If you have no programs, return an empty list (or simply don't // implement this function or getCurrentProgram/selectProgram) return list; }
PluginHostAdapter::ProgramList PluginHostAdapter::getPrograms() const { ProgramList list; for (unsigned int i = 0; i < m_descriptor->programCount; ++i) { list.push_back(m_descriptor->programs[i]); } return list; }
ProgramList MidiDevice::getPrograms(const MidiBank &bank) const { ProgramList programs; for (ProgramList::const_iterator it = m_programList.begin(); it != m_programList.end(); ++it) { if (it->getBank() == bank) programs.push_back(*it); } return programs; }
ProgramList MidiProgramsEditor::getBankSubset(const MidiBank &bank) { ProgramList program; ProgramList::iterator it; for (it = m_programList.begin(); it != m_programList.end(); ++it) { if (it->getBank() == bank) program.push_back(*it); } return program; }
bool GetProgramDetailList( QDateTime &nextRecordingStart, bool *hasConflicts, ProgramDetailList *list) { nextRecordingStart = QDateTime(); bool dummy; bool *conflicts = (hasConflicts) ? hasConflicts : &dummy; ProgramList progList; if (!LoadFromScheduler(progList, *conflicts)) return false; // find the earliest scheduled recording ProgramList::const_iterator it = progList.begin(); for (; it != progList.end(); ++it) { if (((*it)->GetRecordingStatus() == rsWillRecord) && (nextRecordingStart.isNull() || nextRecordingStart > (*it)->GetRecordingStartTime())) { nextRecordingStart = (*it)->GetRecordingStartTime(); } } if (!list) return true; // save the details of the earliest recording(s) for (it = progList.begin(); it != progList.end(); ++it) { if (((*it)->GetRecordingStatus() == rsWillRecord) && ((*it)->GetRecordingStartTime() == nextRecordingStart)) { ProgramDetail prog; prog.channame = (*it)->GetChannelName(); prog.title = (*it)->GetTitle(); prog.subtitle = (*it)->GetSubtitle(); prog.startTime = (*it)->GetRecordingStartTime(); prog.endTime = (*it)->GetRecordingEndTime(); list->push_back(prog); } } return true; }
DTC::Program* Guide::GetProgramDetails( int nChanId, const QDateTime &dtStartTime ) { if (!dtStartTime.isValid()) throw( "StartTime is invalid" ); // ---------------------------------------------------------------------- // -=>TODO: Add support for getting Recorded Program Info // ---------------------------------------------------------------------- // Build add'l SQL statement for Program Listing MSqlBindings bindings; QString sSQL = "WHERE program.chanid = :ChanId " "AND program.starttime = :StartTime "; bindings[":ChanId" ] = nChanId; bindings[":StartTime"] = dtStartTime; // Get all Pending Scheduled Programs ProgramList schedList; bool hasConflicts; LoadFromScheduler(schedList, hasConflicts); // ---------------------------------------------------------------------- ProgramList progList; LoadFromProgram( progList, sSQL, bindings, schedList, false ); if ( progList.size() == 0) throw( "Error Reading Program Info" ); // Build Response DTC::Program *pProgram = new DTC::Program(); ProgramInfo *pInfo = progList[ 0 ]; FillProgramInfo( pProgram, pInfo, true ); return pProgram; }
void MidiDevice::mergeProgramList(const ProgramList &programList) { ProgramList::const_iterator it; ProgramList::iterator oIt; bool clash = false; for (it = programList.begin(); it != programList.end(); ++it) { for (oIt = m_programList.begin(); oIt != m_programList.end(); ++oIt) { if (*it == *oIt) { clash = true; break; } } if (clash == false) addProgram(*it); else clash = false; } }
DTC::ProgramGuide *Guide::GetProgramGuide( const QDateTime &rawStartTime , const QDateTime &rawEndTime , bool bDetails, int nChannelGroupId, int nStartIndex, int nCount) { if (!rawStartTime.isValid()) throw( "StartTime is invalid" ); if (!rawEndTime.isValid()) throw( "EndTime is invalid" ); QDateTime dtStartTime = rawStartTime.toUTC(); QDateTime dtEndTime = rawEndTime.toUTC(); if (dtEndTime < dtStartTime) throw( "EndTime is before StartTime"); if (nStartIndex <= 0) nStartIndex = 0; if (nCount <= 0) nCount = 20000; // ---------------------------------------------------------------------- // Load the channel list // ---------------------------------------------------------------------- uint nTotalAvailable = 0; ChannelInfoList chanList = ChannelUtil::LoadChannels(nStartIndex, nCount, nTotalAvailable, true, ChannelUtil::kChanOrderByChanNum, ChannelUtil::kChanGroupByCallsign, 0, nChannelGroupId); // ---------------------------------------------------------------------- // Build SQL statement for Program Listing // ---------------------------------------------------------------------- ProgramList schedList; MSqlBindings bindings; QString sWhere = "program.chanid = :CHANID " "AND program.endtime >= :STARTDATE " "AND program.starttime < :ENDDATE " "AND program.starttime >= :STARTDATELIMIT " "AND program.manualid = 0"; // Omit 'manual' recordings scheds QString sGroupBy = "program.starttime, channel.channum," "channel.callsign, program.title"; QString sOrderBy = "program.starttime"; bindings[":STARTDATE" ] = dtStartTime; bindings[":STARTDATELIMIT"] = dtStartTime.addDays(-1); bindings[":ENDDATE" ] = dtEndTime; // ---------------------------------------------------------------------- // Get all Pending Scheduled Programs // ---------------------------------------------------------------------- // NOTE: Fetching this information directly from the schedule is // significantly faster than using ProgramInfo::LoadFromScheduler() Scheduler *scheduler = dynamic_cast<Scheduler*>(gCoreContext->GetScheduler()); if (scheduler) scheduler->GetAllPending(schedList); // ---------------------------------------------------------------------- // Build Response // ---------------------------------------------------------------------- DTC::ProgramGuide *pGuide = new DTC::ProgramGuide(); ChannelInfoList::iterator chan_it; for (chan_it = chanList.begin(); chan_it != chanList.end(); ++chan_it) { // Create ChannelInfo Object DTC::ChannelInfo *pChannel = NULL; pChannel = pGuide->AddNewChannel(); FillChannelInfo( pChannel, (*chan_it), bDetails ); // Load the list of programmes for this channel ProgramList progList; bindings[":CHANID"] = (*chan_it).chanid; LoadFromProgram( progList, sWhere, sOrderBy, sOrderBy, bindings, schedList ); // Create Program objects and add them to the channel object ProgramList::iterator progIt; for( progIt = progList.begin(); progIt != progList.end(); ++progIt) { DTC::Program *pProgram = pChannel->AddNewProgram(); FillProgramInfo( pProgram, *progIt, false, bDetails, false ); // No cast info } } // ---------------------------------------------------------------------- pGuide->setStartTime ( dtStartTime ); pGuide->setEndTime ( dtEndTime ); pGuide->setDetails ( bDetails ); pGuide->setStartIndex ( nStartIndex ); pGuide->setCount ( chanList.size() ); pGuide->setTotalAvailable( nTotalAvailable ); pGuide->setAsOf ( MythDate::current() ); pGuide->setVersion ( MYTH_BINARY_VERSION ); pGuide->setProtoVer ( MYTH_PROTO_VERSION ); return pGuide; }
void MIDIInstrumentParameterPanel::updateProgramComboBox() { RG_DEBUG << "updateProgramComboBox()"; if (!getSelectedInstrument()) return; MidiDevice *md = dynamic_cast<MidiDevice *>(getSelectedInstrument()->getDevice()); if (!md) { std::cerr << "WARNING: MIDIInstrumentParameterPanel::updateProgramComboBox(): No MidiDevice for Instrument " << getSelectedInstrument()->getId() << '\n'; return; } RG_DEBUG << "updateProgramComboBox(): variation type is " << md->getVariationType(); MidiBank bank = getSelectedInstrument()->getProgram().getBank(); ProgramList programs = md->getPrograms0thVariation(getSelectedInstrument()->isPercussion(), bank); // Remove the programs that have no name. programs.erase(std::remove_if(programs.begin(), programs.end(), MIDIInstrumentParameterPanel::hasNoName), programs.end()); // If we've got programs, show the Program widgets. // Why not "show = (programs.size()>1)"? Because that would hide the // program checkbox which would take away the user's ability to // enable/disable program changes. If we do away with the checkbox // in the future, we should re-evaluate this decision. bool show = !programs.empty(); m_programLabel->setVisible(show); m_programCheckBox->setVisible(show); m_programComboBox->setVisible(show); int currentProgram = -1; // Compute the current program. for (unsigned i = 0; i < programs.size(); ++i) { // If the program change is the same... if (getSelectedInstrument()->getProgram().getProgram() == programs[i].getProgram()) { currentProgram = i; break; } } // If the programs have changed, we need to repopulate the combobox. if (!partialCompareWithName(programs, m_programs)) { // Update the cache. m_programs = programs; // Copy from m_programs to m_programComboBox. m_programComboBox->clear(); for (unsigned i = 0; i < m_programs.size(); ++i) { m_programComboBox->addItem(QObject::tr("%1. %2") .arg(m_programs[i].getProgram() + 1) .arg(QObject::tr(m_programs[i].getName().c_str()))); } } m_programComboBox->setEnabled(getSelectedInstrument()->sendsProgramChange()); #if 0 // ??? This is a pretty nifty idea, but unfortunately, it requires // that we maintain a bogus combobox entry. For now, we'll go // with the simpler "unselected" approach. // If the current program was not found... if (currentProgram < 0 && !m_programs.empty()) { // Format program change and add to combobox. MidiByte programChange = getSelectedInstrument()->getProgram().getProgram(); m_programComboBox.addItem(QString::number(programChange + 1)); currentProgram = programs.size(); } #endif // Display the current program. m_programComboBox->setCurrentIndex(currentProgram); }
void MIDIInstrumentParameterPanel::updateVariationComboBox() { RG_DEBUG << "updateVariationComboBox() begin..."; if (!getSelectedInstrument()) return; MidiDevice *md = dynamic_cast<MidiDevice *>(getSelectedInstrument()->getDevice()); if (!md) { std::cerr << "WARNING: MIDIInstrumentParameterPanel::updateVariationComboBox(): No MidiDevice for Instrument " << getSelectedInstrument()->getId() << '\n'; return; } RG_DEBUG << "updateVariationComboBox(): Variation type is " << md->getVariationType(); if (md->getVariationType() == MidiDevice::NoVariations) { showVariation(false); return; } // Get the variations. bool useMSB = (md->getVariationType() == MidiDevice::VariationFromMSB); MidiByteList variationBanks; if (useMSB) { MidiByte lsb = getSelectedInstrument()->getLSB(); variationBanks = md->getDistinctMSBs(getSelectedInstrument()->isPercussion(), lsb); RG_DEBUG << "updateVariationComboBox(): Have " << variationBanks.size() << " variations for LSB " << lsb; } else { MidiByte msb = getSelectedInstrument()->getMSB(); variationBanks = md->getDistinctLSBs(getSelectedInstrument()->isPercussion(), msb); RG_DEBUG << "updateVariationComboBox(): Have " << variationBanks.size() << " variations for MSB " << msb; } // Convert variationBanks to a ProgramList. ProgramList variations; // For each variation for (size_t i = 0; i < variationBanks.size(); ++i) { // Assemble the program for the variation. MidiBank bank; if (useMSB) { bank = MidiBank(getSelectedInstrument()->isPercussion(), variationBanks[i], getSelectedInstrument()->getLSB()); } else { bank = MidiBank(getSelectedInstrument()->isPercussion(), getSelectedInstrument()->getMSB(), variationBanks[i]); } MidiProgram program(bank, getSelectedInstrument()->getProgramChange()); // Skip any programs without names. if (md->getProgramName(program) == "") continue; variations.push_back(program); } // Compute the current variation. // ??? This might be combined into the previous for loop. int currentVariation = -1; // For each variation for (size_t i = 0; i < variations.size(); ++i) { if (getSelectedInstrument()->getProgram().partialCompare(variations[i])) { currentVariation = i; break; } } // If the variations have changed, repopulate the combobox. if (!partialCompareWithName(variations, m_variations)) { RG_DEBUG << "updateVariationComboBox(): Repopulating the combobox"; // Update the cache. m_variations = variations; // Copy from m_variations to m_variationComboBox. m_variationComboBox->clear(); for (size_t i = 0; i < m_variations.size(); ++i) { std::string programName = md->getProgramName(m_variations[i]); // Pick the correct bank number. MidiBank bank = m_variations[i].getBank(); MidiByte variationBank = useMSB ? bank.getMSB() : bank.getLSB(); m_variationComboBox->addItem(QObject::tr("%1. %2") .arg(variationBank) .arg(QObject::tr(programName.c_str()))); } } // Display the current variation. m_variationComboBox->setCurrentIndex(currentVariation); // Show the variation widgets in either of two cases: // 1. More than one variation is available for this program. // 2. The variation was not in the Device and there is a variation // to choose from. showVariation(m_variations.size() > 1 || (currentVariation == -1 && !m_variations.empty())); m_variationComboBox->setEnabled(getSelectedInstrument()->sendsBankSelect()); }
void LookerUpper::HandleAllArtwork(bool aggressive) { m_updateartwork = true; if (aggressive) m_updaterules = true; // First, handle all recording rules w/ inetrefs vector<ProgramInfo *> recordingList; RemoteGetAllScheduledRecordings(recordingList); int maxartnum = 3; for( int n = 0; n < (int)recordingList.size(); n++) { ProgramInfo *pginfo = new ProgramInfo(*(recordingList[n])); bool dolookup = true; if (pginfo->GetInetRef().isEmpty()) dolookup = false; if (dolookup || aggressive) { ArtworkMap map = GetArtwork(pginfo->GetInetRef(), pginfo->GetSeason(), true); if (map.isEmpty() || (aggressive && map.count() < maxartnum)) { QString msg = QString("Looking up artwork for recording rule: %1 %2") .arg(pginfo->GetTitle()) .arg(pginfo->GetSubtitle()); LOG(VB_GENERAL, LOG_INFO, msg); m_busyRecList.append(pginfo); m_metadataFactory->Lookup(pginfo, true, true, true); continue; } } delete pginfo; } // Now, Attempt to fill in the gaps for recordings 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])); bool dolookup = true; LookupType type = GuessLookupType(pginfo); if (type == kProbableMovie) maxartnum = 2; if ((!aggressive && type == kProbableGenericTelevision) || pginfo->GetRecordingGroup() == "Deleted" || pginfo->GetRecordingGroup() == "LiveTV") dolookup = false; if (dolookup || aggressive) { ArtworkMap map = GetArtwork(pginfo->GetInetRef(), pginfo->GetSeason(), true); if (map.isEmpty() || (aggressive && map.count() < maxartnum)) { QString msg = QString("Looking up artwork for recording: %1 %2") .arg(pginfo->GetTitle()) .arg(pginfo->GetSubtitle()); LOG(VB_GENERAL, LOG_INFO, msg); m_busyRecList.append(pginfo); m_metadataFactory->Lookup(pginfo, true, true, aggressive); continue; } } delete pginfo; } }
void MIDIInstrumentParameterPanel::slotSelectBank(int index) { RG_DEBUG << "slotSelectBank() begin..."; if (!getSelectedInstrument()) return; MidiDevice *md = dynamic_cast<MidiDevice *>(getSelectedInstrument()->getDevice()); if (!md) { std::cerr << "WARNING: MIDIInstrumentParameterPanel::slotSelectBank(): No MidiDevice for Instrument " << getSelectedInstrument()->getId() << '\n'; return; } const MidiBank &bank = m_banks[index]; bool change = false; if (md->getVariationType() != MidiDevice::VariationFromLSB) { if (getSelectedInstrument()->getLSB() != bank.getLSB()) { getSelectedInstrument()->setLSB(bank.getLSB()); change = true; } } if (md->getVariationType() != MidiDevice::VariationFromMSB) { if (getSelectedInstrument()->getMSB() != bank.getMSB()) { getSelectedInstrument()->setMSB(bank.getMSB()); change = true; } } // If no change, bail. if (!change) return; // Make sure the Instrument is valid WRT the Device. // If the current bank/program is not valid for this device, fix it. if (!getSelectedInstrument()->isProgramValid()) { // If we're not in variations mode... if (md->getVariationType() == MidiDevice::NoVariations) { // ...go with the first program ProgramList programList = md->getPrograms(bank); if (!programList.empty()) { // Switch to the first program in this bank. getSelectedInstrument()->setProgram(programList.front()); } else { // No programs for this bank. Just go with 0. getSelectedInstrument()->setProgramChange(0); } } else { // We're in variations mode... // This is the three-comboboxes (bank/program/variation) case. // It's an extremely difficult case to handle, so we're just // going to punt and give them the first program/variation in // the bank they just selected. // Get the variation bank list for this bank BankList bankList; if (md->getVariationType() == MidiDevice::VariationFromMSB) { bankList = md->getBanksByLSB( getSelectedInstrument()->isPercussion(), bank.getLSB()); } else { bankList = md->getBanksByMSB( getSelectedInstrument()->isPercussion(), bank.getMSB()); } if (!bankList.empty()) { // Pick the first bank MidiBank firstBank = bankList.front(); // Get the program list ProgramList programList = md->getPrograms(firstBank); if (!programList.empty()) { // Pick the first program getSelectedInstrument()->setProgram(programList.front()); } } // To make the above more complex, we could consider the // case where the Program Change happens to be valid for // some variation bank in the newly selected bank. Then // go with the 0th variation bank that has that program // change. But I think this is complicated enough. } } getSelectedInstrument()->sendChannelSetup(); // This is why changed() isn't called within // the setters. If it were, then each of the above changes would // result in a change notification going out. Worst case, that // would be three change notifications and the first two would be // sent when the Instrument was in an inconsistent state. // Rule: Avoid sending change notifications from setters. // Why? It reduces the number of notifications which improves // performance. It avoids sending notifications when an object's // state is inconsistent. It avoids endless loops. getSelectedInstrument()->changed(); }
void MidiProgramsEditor::populate(QTreeWidgetItem* item) { RG_DEBUG << "MidiProgramsEditor::populate\n"; MidiBankTreeWidgetItem* bankItem = dynamic_cast<MidiBankTreeWidgetItem*>(item); if (!bankItem) { RG_DEBUG << "MidiProgramsEditor::populate : not a bank item - returning\n"; return ; } DeviceId deviceId = bankItem->getDeviceId(); m_device = m_bankEditor->getMidiDevice(deviceId); if (!m_device) return ; setEnabled(true); setBankName(item->text(0)); RG_DEBUG << "MidiProgramsEditor::populate : bankItem->getBank = " << bankItem->getBank() << endl; m_currentBank = &(m_bankList[bankItem->getBank()]); // m_device->getBankByIndex(bankItem->getBank()); blockAllSignals(true); // set the bank values m_percussion->setChecked(m_currentBank->isPercussion()); m_msb->setValue(m_currentBank->getMSB()); m_lsb->setValue(m_currentBank->getLSB()); m_oldBank = *m_currentBank; // Librarian details // m_librarian->setText(strtoqstr(m_device->getLibrarianName())); m_librarianEmail->setText(strtoqstr(m_device->getLibrarianEmail())); ProgramList programSubset = getBankSubset(*m_currentBank); ProgramList::iterator it; QPixmap noKeyPixmap, keyPixmap; IconLoader il; noKeyPixmap = il.loadPixmap("key-white"); keyPixmap = il.loadPixmap("key-green"); bool haveKeyMappings = m_device->getKeyMappings().size() > 0; for (unsigned int i = 0; i < (unsigned int)m_names.size(); i++) { m_names[i]->clear(); getKeyMapButton(i)->setEnabled(haveKeyMappings); getKeyMapButton(i)->setIcon(QIcon(noKeyPixmap)); // QToolTip::remove // ( getKeyMapButton(i) ); getKeyMapButton(i)->setToolTip(QString("")); //@@@ Usefull ? getKeyMapButton(i)->setMaximumHeight( 12 ); for (it = programSubset.begin(); it != programSubset.end(); ++it) { if (it->getProgram() == i) { // zero in on "Harpsichord" vs. "Coupled Harpsichord to cut down // on noise (0-based) // if (i == 6) std::cout << "it->getName(): " << it->getName() << std::endl; QString programName = strtoqstr(it->getName()); m_completions << programName; m_names[i]->setText(programName); if (m_device->getKeyMappingForProgram(*it)) { getKeyMapButton(i)->setIcon(QIcon(keyPixmap)); getKeyMapButton(i)->setToolTip (tr("Key Mapping: %1") .arg(strtoqstr(m_device->getKeyMappingForProgram(*it)->getName()))); } break; } } // show start of label m_names[i]->setCursorPosition(0); } blockAllSignals(false); }
void StatusBox::doScheduleStatus() { if (m_iconState) m_iconState->DisplayState("schedule"); m_logList->Reset(); QString helpmsg(tr("Schedule Status shows current statistics " "from the scheduler.")); if (m_helpText) m_helpText->SetText(helpmsg); if (m_justHelpText) m_justHelpText->SetText(helpmsg); MSqlQuery query(MSqlQuery::InitCon()); query.prepare("SELECT COUNT(*) FROM record WHERE search = 0"); if (query.exec() && query.next()) { QString rules = tr("%n standard rule(s) (is) defined", "", query.value(0).toInt()); AddLogLine(rules, helpmsg); } else { MythDB::DBError("StatusBox::doScheduleStatus()", query); return; } query.prepare("SELECT COUNT(*) FROM record WHERE search > 0"); if (query.exec() && query.next()) { QString rules = tr("%n search rule(s) are defined", "", query.value(0).toInt()); AddLogLine(rules, helpmsg); } else { MythDB::DBError("StatusBox::doScheduleStatus()", query); return; } QMap<RecStatusType, int> statusMatch; QMap<RecStatusType, QString> statusText; QMap<int, int> sourceMatch; QMap<int, QString> sourceText; QMap<int, int> inputMatch; QMap<int, QString> inputText; QString tmpstr; int maxSource = 0; int maxInput = 0; int lowerpriority = 0; int hdflag = 0; query.prepare("SELECT MAX(sourceid) FROM videosource"); if (query.exec()) { if (query.next()) maxSource = query.value(0).toInt(); } query.prepare("SELECT sourceid,name FROM videosource"); if (query.exec()) { while (query.next()) sourceText[query.value(0).toInt()] = query.value(1).toString(); } query.prepare("SELECT MAX(cardinputid) FROM cardinput"); if (query.exec()) { if (query.next()) maxInput = query.value(0).toInt(); } query.prepare("SELECT cardinputid,cardid,inputname,displayname " "FROM cardinput"); if (query.exec()) { while (query.next()) { if (!query.value(3).toString().isEmpty()) inputText[query.value(0).toInt()] = query.value(3).toString(); else inputText[query.value(0).toInt()] = QString("%1: %2") .arg(query.value(1).toInt()) .arg(query.value(2).toString()); } } ProgramList schedList; LoadFromScheduler(schedList); tmpstr = tr("%n matching showing(s)", "", schedList.size()); AddLogLine(tmpstr, helpmsg); ProgramList::const_iterator it = schedList.begin(); for (; it != schedList.end(); ++it) { const ProgramInfo *s = *it; const RecStatusType recstatus = s->GetRecordingStatus(); if (statusMatch[recstatus] < 1) { statusText[recstatus] = toString( recstatus, s->GetRecordingRuleType()); } ++statusMatch[recstatus]; if (recstatus == rsWillRecord || recstatus == rsRecording) { ++sourceMatch[s->GetSourceID()]; ++inputMatch[s->GetInputID()]; if (s->GetRecordingPriority2() < 0) ++lowerpriority; if (s->GetVideoProperties() & VID_HDTV) ++hdflag; } } #define ADD_STATUS_LOG_LINE(rtype, fstate) \ do { \ if (statusMatch[rtype] > 0) \ { \ tmpstr = QString("%1 %2").arg(statusMatch[rtype]) \ .arg(statusText[rtype]); \ AddLogLine(tmpstr, helpmsg, tmpstr, tmpstr, fstate);\ } \ } while (0) ADD_STATUS_LOG_LINE(rsRecording, ""); ADD_STATUS_LOG_LINE(rsWillRecord, ""); ADD_STATUS_LOG_LINE(rsConflict, "error"); ADD_STATUS_LOG_LINE(rsTooManyRecordings, "warning"); ADD_STATUS_LOG_LINE(rsLowDiskSpace, "warning"); ADD_STATUS_LOG_LINE(rsLaterShowing, "warning"); ADD_STATUS_LOG_LINE(rsNotListed, "warning"); QString willrec = statusText[rsWillRecord]; if (lowerpriority > 0) { tmpstr = QString("%1 %2 %3").arg(lowerpriority).arg(willrec) .arg(tr("with lower priority")); AddLogLine(tmpstr, helpmsg, tmpstr, tmpstr, "warning"); } if (hdflag > 0) { tmpstr = QString("%1 %2 %3").arg(hdflag).arg(willrec) .arg(tr("marked as HDTV")); AddLogLine(tmpstr, helpmsg); } int i; for (i = 1; i <= maxSource; ++i) { if (sourceMatch[i] > 0) { tmpstr = QString("%1 %2 %3 %4 \"%5\"") .arg(sourceMatch[i]).arg(willrec) .arg(tr("from source")).arg(i).arg(sourceText[i]); AddLogLine(tmpstr, helpmsg); } } for (i = 1; i <= maxInput; ++i) { if (inputMatch[i] > 0) { tmpstr = QString("%1 %2 %3 %4 \"%5\"") .arg(inputMatch[i]).arg(willrec) .arg(tr("on input")).arg(i).arg(inputText[i]); AddLogLine(tmpstr, helpmsg); } } }
DTC::ProgramGuide *Guide::GetProgramGuide( const QDateTime &rawStartTime , const QDateTime &rawEndTime , int nStartChanId, int nNumChannels, bool bDetails, int nChannelGroupId ) { if (!rawStartTime.isValid()) throw( "StartTime is invalid" ); if (!rawEndTime.isValid()) throw( "EndTime is invalid" ); QDateTime dtStartTime = rawStartTime.toUTC(); QDateTime dtEndTime = rawEndTime.toUTC(); if (dtEndTime < dtStartTime) throw( "EndTime is before StartTime"); if (nNumChannels == 0) nNumChannels = SHRT_MAX; // ---------------------------------------------------------------------- // Find the ending channel Id // ---------------------------------------------------------------------- int nEndChanId = nStartChanId; MSqlQuery query(MSqlQuery::InitCon()); query.prepare( "SELECT chanid FROM channel WHERE (chanid >= :STARTCHANID )" " ORDER BY chanid LIMIT :NUMCHAN" ); query.bindValue(":STARTCHANID", nStartChanId ); query.bindValue(":NUMCHAN" , nNumChannels ); if (!query.exec()) MythDB::DBError("Select ChanId", query); query.first(); nStartChanId = query.value(0).toInt(); query.last(); nEndChanId = query.value(0).toInt(); // ---------------------------------------------------------------------- // Build SQL statement for Program Listing // ---------------------------------------------------------------------- ProgramList progList; ProgramList schedList; MSqlBindings bindings; // lpad is to allow natural sorting of numbers QString sSQL; if (nChannelGroupId > 0) { sSQL = "LEFT JOIN channelgroup ON program.chanid = channelgroup.chanid " "WHERE channelgroup.grpid = :CHANGRPID AND "; bindings[":CHANGRPID" ] = nChannelGroupId; } else sSQL = "WHERE "; sSQL += "visible != 0 " "AND program.chanid >= :StartChanId " "AND program.chanid <= :EndChanId " "AND program.endtime >= :StartDate " "AND program.starttime <= :EndDate " "AND program.manualid = 0 " // Exclude programmes created purely for 'manual' recording schedules "ORDER BY LPAD(CAST(channum AS UNSIGNED), 10, 0), " " LPAD(channum, 10, 0), " " callsign, " " LPAD(program.chanid, 10, 0), " " program.starttime "; bindings[":StartChanId"] = nStartChanId; bindings[":EndChanId" ] = nEndChanId; bindings[":StartDate" ] = dtStartTime; bindings[":EndDate" ] = dtEndTime; // ---------------------------------------------------------------------- // Get all Pending Scheduled Programs // ---------------------------------------------------------------------- bool hasConflicts; LoadFromScheduler(schedList, hasConflicts); // ---------------------------------------------------------------------- LoadFromProgram( progList, sSQL, bindings, schedList ); // ---------------------------------------------------------------------- // Build Response // ---------------------------------------------------------------------- DTC::ProgramGuide *pGuide = new DTC::ProgramGuide(); int nChanCount = 0; uint nCurChanId = 0; DTC::ChannelInfo *pChannel = NULL; QString sCurCallsign; uint nSkipChanId = 0; for( uint n = 0; n < progList.size(); n++) { ProgramInfo *pInfo = progList[ n ]; if ( nSkipChanId == pInfo->GetChanID()) continue; if ( nCurChanId != pInfo->GetChanID() ) { nChanCount++; nCurChanId = pInfo->GetChanID(); // Filter out channels with the same callsign, keeping just the // first seen if (sCurCallsign == pInfo->GetChannelSchedulingID()) { nSkipChanId = pInfo->GetChanID(); continue; } pChannel = pGuide->AddNewChannel(); FillChannelInfo( pChannel, pInfo->GetChanID(), bDetails ); sCurCallsign = pChannel->CallSign(); } DTC::Program *pProgram = pChannel->AddNewProgram(); FillProgramInfo( pProgram, pInfo, false, bDetails, false ); // No cast info } // ---------------------------------------------------------------------- pGuide->setStartTime ( dtStartTime ); pGuide->setEndTime ( dtEndTime ); pGuide->setStartChanId ( nStartChanId ); pGuide->setEndChanId ( nEndChanId ); pGuide->setNumOfChannels( nChanCount ); pGuide->setDetails ( bDetails ); pGuide->setCount ( progList.size()); pGuide->setAsOf ( MythDate::current() ); pGuide->setVersion ( MYTH_BINARY_VERSION ); pGuide->setProtoVer ( MYTH_PROTO_VERSION ); return pGuide; }
DTC::ProgramList* Guide::GetProgramList(int nStartIndex, int nCount, const QDateTime& rawStartTime, const QDateTime& rawEndTime, int nChanId, const QString& sTitleFilter, const QString& sCategoryFilter, const QString& sPersonFilter, const QString& sKeywordFilter, bool bOnlyNew, bool bDetails, const QString &sSort, bool bDescending) { if (!rawStartTime.isNull() && !rawStartTime.isValid()) throw( "StartTime is invalid" ); if (!rawEndTime.isNull() && !rawEndTime.isValid()) throw( "EndTime is invalid" ); QDateTime dtStartTime = rawStartTime; QDateTime dtEndTime = rawEndTime; if (!rawEndTime.isNull() && dtEndTime < dtStartTime) throw( "EndTime is before StartTime"); MSqlQuery query(MSqlQuery::InitCon()); // ---------------------------------------------------------------------- // Build SQL statement for Program Listing // ---------------------------------------------------------------------- ProgramList progList; ProgramList schedList; MSqlBindings bindings; QString sSQL; if (!sPersonFilter.isEmpty()) { sSQL = ", people, credits " // LEFT JOIN "WHERE people.name LIKE :PersonFilter " "AND credits.person = people.person " "AND program.chanid = credits.chanid " "AND program.starttime = credits.starttime AND "; bindings[":PersonFilter"] = QString("%%1%").arg(sPersonFilter); } else sSQL = "WHERE "; sSQL += "visible != 0 AND program.manualid = 0 "; // Exclude programmes created purely for 'manual' recording schedules if (nChanId < 0) nChanId = 0; if (nChanId > 0) { sSQL += "AND program.chanid = :ChanId "; bindings[":ChanId"] = nChanId; } if (dtStartTime.isNull()) dtStartTime = QDateTime::currentDateTimeUtc(); sSQL += " AND program.endtime >= :StartDate "; bindings[":StartDate"] = dtStartTime; if (!dtEndTime.isNull()) { sSQL += "AND program.starttime <= :EndDate "; bindings[":EndDate"] = dtEndTime; } if (!sTitleFilter.isEmpty()) { sSQL += "AND program.title LIKE :Title "; bindings[":Title"] = QString("%%1%").arg(sTitleFilter); } if (!sCategoryFilter.isEmpty()) { sSQL += "AND program.category LIKE :Category "; bindings[":Category"] = sCategoryFilter; } if (!sKeywordFilter.isEmpty()) { sSQL += "AND (program.title LIKE :Keyword1 " "OR program.subtitle LIKE :Keyword2 " "OR program.description LIKE :Keyword3) "; QString filter = QString("%%1%").arg(sKeywordFilter); bindings[":Keyword1"] = filter; bindings[":Keyword2"] = filter; bindings[":Keyword3"] = filter; } if (sSort == "starttime") sSQL += "ORDER BY program.starttime "; else if (sSort == "title") sSQL += "ORDER BY program.title "; else if (sSort == "channel") sSQL += "ORDER BY channel.channum "; else if (sSort == "duration") sSQL += "ORDER BY (program.endtime - program.starttime) "; else sSQL += "ORDER BY program.starttime "; if (bDescending) sSQL += "DESC "; else sSQL += "ASC "; // ---------------------------------------------------------------------- // Get all Pending Scheduled Programs // ---------------------------------------------------------------------- bool hasConflicts; LoadFromScheduler(schedList, hasConflicts); // ---------------------------------------------------------------------- uint nTotalAvailable = 0; LoadFromProgram( progList, sSQL, bindings, schedList, (uint)nStartIndex, (uint)nCount, nTotalAvailable); // ---------------------------------------------------------------------- // Build Response // ---------------------------------------------------------------------- DTC::ProgramList *pPrograms = new DTC::ProgramList(); nCount = (int)progList.size(); int nEndIndex = (int)progList.size(); for( int n = 0; n < nEndIndex; n++) { ProgramInfo *pInfo = progList[ n ]; DTC::Program *pProgram = pPrograms->AddNewProgram(); FillProgramInfo( pProgram, pInfo, true, bDetails, false ); // No cast info, loading this takes far too long } // ---------------------------------------------------------------------- pPrograms->setStartIndex ( nStartIndex ); pPrograms->setCount ( nCount ); pPrograms->setTotalAvailable( nTotalAvailable ); pPrograms->setAsOf ( MythDate::current() ); pPrograms->setVersion ( MYTH_BINARY_VERSION ); pPrograms->setProtoVer ( MYTH_PROTO_VERSION ); return pPrograms; }
DTC::ProgramList* Dvr::GetRecordedList( bool bDescending, int nStartIndex, int nCount, const QString &sTitleRegEx, const QString &sRecGroup, const QString &sStorageGroup ) { QMap< QString, ProgramInfo* > recMap; if (gCoreContext->GetScheduler()) recMap = gCoreContext->GetScheduler()->GetRecording(); QMap< QString, uint32_t > inUseMap = ProgramInfo::QueryInUseMap(); QMap< QString, bool > isJobRunning= ProgramInfo::QueryJobsRunning(JOB_COMMFLAG); ProgramList progList; int desc = 1; if (bDescending) desc = -1; LoadFromRecorded( progList, false, inUseMap, isJobRunning, recMap, desc ); QMap< QString, ProgramInfo* >::iterator mit = recMap.begin(); for (; mit != recMap.end(); mit = recMap.erase(mit)) delete *mit; // ---------------------------------------------------------------------- // Build Response // ---------------------------------------------------------------------- DTC::ProgramList *pPrograms = new DTC::ProgramList(); int nAvailable = 0; int nMax = (nCount > 0) ? nCount : progList.size(); nAvailable = 0; nCount = 0; QRegExp rTitleRegEx = QRegExp(sTitleRegEx, Qt::CaseInsensitive); for( unsigned int n = 0; n < progList.size(); n++) { ProgramInfo *pInfo = progList[ n ]; if (pInfo->IsDeletePending() || (!sTitleRegEx.isEmpty() && !pInfo->GetTitle().contains(rTitleRegEx)) || (!sRecGroup.isEmpty() && sRecGroup != pInfo->GetRecordingGroup()) || (!sStorageGroup.isEmpty() && sStorageGroup != pInfo->GetStorageGroup())) continue; if ((nAvailable < nStartIndex) || (nCount >= nMax)) { ++nAvailable; continue; } ++nAvailable; ++nCount; DTC::Program *pProgram = pPrograms->AddNewProgram(); FillProgramInfo( pProgram, pInfo, true ); } // ---------------------------------------------------------------------- pPrograms->setStartIndex ( nStartIndex ); pPrograms->setCount ( nCount ); pPrograms->setTotalAvailable( nAvailable ); pPrograms->setAsOf ( MythDate::current() ); pPrograms->setVersion ( MYTH_BINARY_VERSION ); pPrograms->setProtoVer ( MYTH_PROTO_VERSION ); return pPrograms; }
void ViewScheduled::FillList() { m_schedulesList->Reset(); MythUIText *norecordingText = dynamic_cast<MythUIText*> (GetChild("norecordings_info")); if (norecordingText) norecordingText->SetVisible(m_recList.empty()); if (m_recList.empty()) return; ProgramList plist; if (!m_recgroupList.contains(m_currentGroup)) m_currentGroup = m_defaultGroup; plist = m_recgroupList[m_currentGroup]; ProgramList::iterator pit = plist.begin(); while (pit != plist.end()) { ProgramInfo *pginfo = *pit; if (!pginfo) { ++pit; continue; } QString state; const RecStatusType recstatus = pginfo->GetRecordingStatus(); if (recstatus == rsRecording) state = "running"; else if (recstatus == rsConflict || recstatus == rsOffLine || recstatus == rsTunerBusy || recstatus == rsFailed || recstatus == rsAborted || recstatus == rsMissed) state = "error"; else if (recstatus == rsWillRecord) { if ((m_curcard == 0 && m_curinput == 0) || pginfo->GetCardID() == m_curcard || pginfo->GetInputID() == m_curinput) { if (pginfo->GetRecordingPriority2() < 0) state = "warning"; else state = "normal"; } } else if (recstatus == rsRepeat || recstatus == rsOtherShowing || recstatus == rsNeverRecord || recstatus == rsDontRecord || (recstatus != rsDontRecord && recstatus <= rsEarlierShowing)) state = "disabled"; else state = "warning"; MythUIButtonListItem *item = new MythUIButtonListItem(m_schedulesList,"", qVariantFromValue(pginfo)); InfoMap infoMap; pginfo->ToMap(infoMap); item->SetTextFromMap(infoMap, state); QString rating = QString::number(pginfo->GetStars(10)); item->DisplayState(rating, "ratingstate"); item->DisplayState(state, "status"); ++pit; } MythUIText *statusText = dynamic_cast<MythUIText*>(GetChild("status")); if (statusText) { if (m_conflictBool) { // Find first conflict and store in m_conflictDate field ProgramList::const_iterator it = plist.begin(); for (; it != plist.end(); ++it) { ProgramInfo &p = **it; if (p.GetRecordingStatus() == rsConflict) { m_conflictDate = p.GetRecordingStartTime().date(); break; } } // figure out caption based on m_conflictDate QString cstring = tr("Time Conflict"); QDate now = QDate::currentDate(); int daysToConflict = now.daysTo(m_conflictDate); if (daysToConflict == 0) cstring = tr("Conflict Today"); else if (daysToConflict > 0) cstring = QString(tr("Conflict %1")) .arg(m_conflictDate.toString(m_dateFormat)); statusText->SetText(cstring); } else statusText->SetText(tr("No Conflicts")); } MythUIText *filterText = dynamic_cast<MythUIText*>(GetChild("filter")); if (filterText) { if (m_showAll) filterText->SetText(tr("All")); else filterText->SetText(tr("Important")); } }
void ViewScheduled::LoadList(bool useExistingData) { if (m_inFill) return; m_inFill = true; MythUIButtonListItem *currentItem = m_schedulesList->GetItemCurrent(); QString callsign; QDateTime startts, recstartts; if (currentItem) { ProgramInfo *currentpginfo = qVariantValue<ProgramInfo*> (currentItem->GetData()); if (currentpginfo) { callsign = currentpginfo->GetChannelSchedulingID(); startts = currentpginfo->GetScheduledStartTime(); recstartts = currentpginfo->GetRecordingStartTime(); } } QDateTime now = QDateTime::currentDateTime(); QMap<int, int> toomanycounts; m_schedulesList->Reset(); if (m_groupList) m_groupList->Reset(); m_recgroupList.clear(); if (!useExistingData) LoadFromScheduler(m_recList, m_conflictBool); ProgramList::iterator pit = m_recList.begin(); QString currentDate; m_recgroupList[m_defaultGroup] = ProgramList(false); m_recgroupList[m_defaultGroup].setAutoDelete(false); while (pit != m_recList.end()) { ProgramInfo *pginfo = *pit; const RecStatusType recstatus = pginfo->GetRecordingStatus(); if ((pginfo->GetRecordingEndTime() >= now || pginfo->GetScheduledEndTime() >= now) && (m_showAll || recstatus <= rsWillRecord || recstatus == rsDontRecord || (recstatus == rsTooManyRecordings && ++toomanycounts[pginfo->GetRecordingRuleID()] <= 1) || (recstatus > rsTooManyRecordings && recstatus != rsRepeat && recstatus != rsNeverRecord))) { m_cardref[pginfo->GetCardID()]++; if (pginfo->GetCardID() > m_maxcard) m_maxcard = pginfo->GetCardID(); m_inputref[pginfo->GetInputID()]++; if (pginfo->GetInputID() > m_maxinput) m_maxinput = pginfo->GetInputID(); QDate date = (pginfo->GetRecordingStartTime()).date(); m_recgroupList[date].push_back(pginfo); m_recgroupList[date].setAutoDelete(false); m_recgroupList[m_defaultGroup].push_back(pginfo); ++pit; } else { pit = m_recList.erase(pit); continue; } } if (m_groupList) { QString label; QMap<QDate,ProgramList>::iterator dateit = m_recgroupList.begin(); while (dateit != m_recgroupList.end()) { if (dateit.key().isNull()) label = tr("All"); else label = dateit.key().toString(m_dateFormat); new MythUIButtonListItem(m_groupList, label, qVariantFromValue(dateit.key())); ++dateit; } if (!m_recgroupList.contains(m_currentGroup)) m_groupList->SetValueByData(qVariantFromValue(m_currentGroup)); } FillList(); // Restore position after a list update if (!callsign.isEmpty()) { ProgramList plist; if (!m_recgroupList.contains(m_currentGroup)) m_currentGroup = m_defaultGroup; plist = m_recgroupList[m_currentGroup]; int listPos = ((int) plist.size()) - 1; int i; for (i = listPos; i >= 0; --i) { ProgramInfo *pginfo = plist[i]; if (callsign == pginfo->GetChannelSchedulingID() && startts == pginfo->GetScheduledStartTime()) { listPos = i; break; } else if (recstartts <= pginfo->GetRecordingStartTime()) listPos = i; } m_schedulesList->SetItemCurrent(listPos); } m_inFill = false; m_needFill = false; }
DTC::ProgramGuide *Guide::GetProgramGuide( const QDateTime &dtStartTime , const QDateTime &dtEndTime , int nStartChanId, int nNumChannels, bool bDetails ) { if (!dtStartTime.isValid()) throw( "StartTime is invalid" ); if (!dtEndTime.isValid()) throw( "EndTime is invalid" ); if (dtEndTime < dtStartTime) throw( "EndTime is before StartTime"); if (nNumChannels == 0) nNumChannels = 1; if (nNumChannels == -1) nNumChannels = SHRT_MAX; // ---------------------------------------------------------------------- // Find the ending channel Id // ---------------------------------------------------------------------- int nEndChanId = nStartChanId; MSqlQuery query(MSqlQuery::InitCon()); query.prepare( "SELECT chanid FROM channel WHERE (chanid >= :STARTCHANID )" " ORDER BY chanid LIMIT :NUMCHAN" ); query.bindValue(":STARTCHANID", nStartChanId ); query.bindValue(":NUMCHAN" , nNumChannels ); if (!query.exec()) MythDB::DBError("Select ChanId", query); query.first(); nStartChanId = query.value(0).toInt(); query.last(); nEndChanId = query.value(0).toInt(); // ---------------------------------------------------------------------- // Build SQL statement for Program Listing // ---------------------------------------------------------------------- ProgramList progList; ProgramList schedList; MSqlBindings bindings; QString sSQL = "WHERE program.chanid >= :StartChanId " "AND program.chanid <= :EndChanId " "AND program.endtime >= :StartDate " "AND program.starttime <= :EndDate " "GROUP BY program.starttime, channel.channum, " "channel.callsign, program.title " "ORDER BY program.chanid "; bindings[":StartChanId"] = nStartChanId; bindings[":EndChanId" ] = nEndChanId; bindings[":StartDate" ] = dtStartTime; bindings[":EndDate" ] = dtEndTime; // ---------------------------------------------------------------------- // Get all Pending Scheduled Programs // ---------------------------------------------------------------------- bool hasConflicts; LoadFromScheduler(schedList, hasConflicts); // ---------------------------------------------------------------------- LoadFromProgram( progList, sSQL, bindings, schedList, false ); // ---------------------------------------------------------------------- // Build Response // ---------------------------------------------------------------------- DTC::ProgramGuide *pGuide = new DTC::ProgramGuide(); int nChanCount = 0; uint nCurChanId = 0; DTC::ChannelInfo *pChannel = NULL; for( uint n = 0; n < progList.size(); n++) { ProgramInfo *pInfo = progList[ n ]; if ( nCurChanId != pInfo->GetChanID() ) { nChanCount++; nCurChanId = pInfo->GetChanID(); pChannel = pGuide->AddNewChannel(); FillChannelInfo( pChannel, pInfo, bDetails ); } DTC::Program *pProgram = pChannel->AddNewProgram(); FillProgramInfo( pProgram, pInfo, false, bDetails ); } // ---------------------------------------------------------------------- pGuide->setStartTime ( dtStartTime ); pGuide->setEndTime ( dtEndTime ); pGuide->setStartChanId ( nStartChanId ); pGuide->setEndChanId ( nEndChanId ); pGuide->setNumOfChannels( nChanCount ); pGuide->setDetails ( bDetails ); pGuide->setCount ( progList.size()); pGuide->setAsOf ( QDateTime::currentDateTime() ); pGuide->setVersion ( MYTH_BINARY_VERSION ); pGuide->setProtoVer ( MYTH_PROTO_VERSION ); return pGuide; }
/** \brief Fills RecordingInfo for the program that airs at * "desiredts" on "chanid". * \param chanid %Channel ID on which to search for program. * \param desiredts Date and Time for which we desire the program. * \param genUnknown Generate a full entry for live-tv if unknown * \param maxHours Clamp the maximum time to X hours from dtime. * \return LoadStatus describing what happened. */ RecordingInfo::RecordingInfo( uint _chanid, const QDateTime &desiredts, bool genUnknown, uint maxHours, LoadStatus *status) : oldrecstatus(rsUnknown), savedrecstatus(rsUnknown), future(false), schedorder(0), mplexid(0), desiredrecstartts(), desiredrecendts(), record(NULL) { ProgramList schedList; ProgramList progList; MSqlBindings bindings; QString querystr = "WHERE program.chanid = :CHANID AND " " program.starttime < :STARTTS1 AND " " program.endtime > :STARTTS2 "; bindings[":CHANID"] = QString::number(_chanid); QDateTime query_startts = desiredts.addSecs(50 - desiredts.time().second()); bindings[":STARTTS1"] = query_startts; bindings[":STARTTS2"] = query_startts; ::LoadFromScheduler(schedList); LoadFromProgram(progList, querystr, bindings, schedList); if (!progList.empty()) { ProgramInfo *pginfo = progList[0]; if (maxHours > 0) { if (desiredts.secsTo( pginfo->GetScheduledEndTime()) > (int)maxHours * 3600) { pginfo->SetScheduledEndTime(desiredts.addSecs(maxHours * 3600)); pginfo->SetRecordingEndTime(pginfo->GetScheduledEndTime()); } } *this = *pginfo; if (status) *status = kFoundProgram; return; } recstartts = startts = desiredts; recendts = endts = desiredts; lastmodified = desiredts; MSqlQuery query(MSqlQuery::InitCon()); query.prepare("SELECT chanid, channum, callsign, name, " "commmethod, outputfilters " "FROM channel " "WHERE chanid = :CHANID"); query.bindValue(":CHANID", _chanid); if (!query.exec()) { MythDB::DBError("Loading Program overlapping a datetime", query); if (status) *status = kNoProgram; return; } if (!query.next()) { if (status) *status = kNoProgram; return; } chanid = query.value(0).toUInt(); chanstr = query.value(1).toString(); chansign = query.value(2).toString(); channame = query.value(3).toString(); programflags &= ~FL_CHANCOMMFREE; programflags |= (query.value(4).toInt() == COMM_DETECT_COMMFREE) ? FL_CHANCOMMFREE : 0; chanplaybackfilters = query.value(5).toString(); { QMutexLocker locker(&staticDataLock); if (unknownTitle.isEmpty()) unknownTitle = gCoreContext->GetSetting("UnknownTitle"); title = unknownTitle; title.detach(); } if (!genUnknown) { if (status) *status = kFakedZeroMinProgram; return; } // Round endtime up to the next half-hour. endts = QDateTime( endts.date(), QTime(endts.time().hour(), endts.time().minute() / kUnknownProgramLength * kUnknownProgramLength), Qt::UTC); endts = endts.addSecs(kUnknownProgramLength * 60); // if under a minute, bump it up to the next half hour if (startts.secsTo(endts) < 60) endts = endts.addSecs(kUnknownProgramLength * 60); recendts = endts; // Find next program starttime bindings.clear(); QDateTime nextstart = startts; querystr = "WHERE program.chanid = :CHANID AND " " program.starttime > :STARTTS " "GROUP BY program.starttime ORDER BY program.starttime LIMIT 1 "; bindings[":CHANID"] = QString::number(_chanid); bindings[":STARTTS"] = desiredts.addSecs(50 - desiredts.time().second()); LoadFromProgram(progList, querystr, bindings, schedList); if (!progList.empty()) nextstart = (*progList.begin())->GetScheduledStartTime(); if (nextstart > startts && nextstart < recendts) recendts = endts = nextstart; if (status) *status = kFakedLiveTVProgram; desiredrecstartts = startts; desiredrecendts = endts; }
void TVBrowseHelper::GetNextProgramDB( BrowseDirection direction, InfoMap &infoMap) const { uint chanid = infoMap["chanid"].toUInt(); if (!chanid) { LOG(VB_GENERAL, LOG_ERR, LOC + "GetNextProgramDB() requires a chanid"); return; } int chandir = -1; switch (direction) { case BROWSE_UP: chandir = CHANNEL_DIRECTION_UP; break; case BROWSE_DOWN: chandir = CHANNEL_DIRECTION_DOWN; break; case BROWSE_FAVORITE: chandir = CHANNEL_DIRECTION_FAVORITE; break; } if (chandir != -1) { chanid = ChannelUtil::GetNextChannel( db_all_visible_channels, chanid, 0 /*mplexid_restriction*/, chandir, true /*skip non visible*/, true /*skip same callsign*/); } infoMap["chanid"] = QString::number(chanid); infoMap["channum"] = db_chanid_to_channum[chanid]; QDateTime nowtime = QDateTime::currentDateTime(); QDateTime latesttime = nowtime.addSecs(6*60*60); QDateTime browsetime = QDateTime::fromString( infoMap["dbstarttime"], Qt::ISODate); MSqlBindings bindings; bindings[":CHANID"] = chanid; bindings[":NOWTS"] = nowtime; bindings[":LATESTTS"] = latesttime; bindings[":BROWSETS"] = browsetime; bindings[":BROWSETS2"] = browsetime; QString querystr = " WHERE program.chanid = :CHANID "; switch (direction) { case BROWSE_LEFT: querystr += " AND program.endtime <= :BROWSETS " " AND program.endtime > :NOWTS "; break; case BROWSE_RIGHT: querystr += " AND program.starttime > :BROWSETS " " AND program.starttime < :LATESTTS "; break; default: querystr += " AND program.starttime <= :BROWSETS " " AND program.endtime > :BROWSETS2 "; }; ProgramList progList; ProgramList dummySched; LoadFromProgram(progList, querystr, bindings, dummySched); if (progList.empty()) { infoMap["dbstarttime"] = ""; return; } const ProgramInfo *prog = (direction == BROWSE_LEFT) ? progList[progList.size() - 1] : progList[0]; infoMap["dbstarttime"] = prog->GetScheduledStartTime(ISODate); }
void ViewScheduled::FillList() { m_schedulesList->Reset(); MythUIText *norecordingText = dynamic_cast<MythUIText*> (GetChild("norecordings_info")); if (norecordingText) norecordingText->SetVisible(m_recList.empty()); if (m_recList.empty()) return; ProgramList plist; if (!m_recgroupList.contains(m_currentGroup)) m_currentGroup = m_defaultGroup; plist = m_recgroupList[m_currentGroup]; ProgramList::iterator pit = plist.begin(); while (pit != plist.end()) { ProgramInfo *pginfo = *pit; if (!pginfo) { ++pit; continue; } QString state; const RecStatus::Type recstatus = pginfo->GetRecordingStatus(); if (recstatus == RecStatus::Recording || recstatus == RecStatus::Tuning) state = "running"; else if (recstatus == RecStatus::Conflict || recstatus == RecStatus::Offline || recstatus == RecStatus::TunerBusy || recstatus == RecStatus::Failed || recstatus == RecStatus::Failing || recstatus == RecStatus::Aborted || recstatus == RecStatus::Missed) state = "error"; else if (recstatus == RecStatus::WillRecord || recstatus == RecStatus::Pending) { if (m_curinput == 0 || pginfo->GetInputID() == m_curinput) { if (pginfo->GetRecordingPriority2() < 0) state = "warning"; else state = "normal"; } } else if (recstatus == RecStatus::Repeat || recstatus == RecStatus::NeverRecord || recstatus == RecStatus::DontRecord || (recstatus != RecStatus::DontRecord && recstatus <= RecStatus::EarlierShowing)) state = "disabled"; else state = "warning"; MythUIButtonListItem *item = new MythUIButtonListItem(m_schedulesList,"", qVariantFromValue(pginfo)); InfoMap infoMap; pginfo->ToMap(infoMap); item->SetTextFromMap(infoMap, state); QString rating = QString::number(pginfo->GetStars(10)); item->DisplayState(rating, "ratingstate"); item->DisplayState(state, "status"); ++pit; } MythUIText *statusText = dynamic_cast<MythUIText*>(GetChild("status")); if (statusText) { if (m_conflictBool) { // Find first conflict and store in m_conflictDate field ProgramList::const_iterator it = plist.begin(); for (; it != plist.end(); ++it) { ProgramInfo &p = **it; if (p.GetRecordingStatus() == RecStatus::Conflict) { m_conflictDate = p.GetRecordingStartTime() .toLocalTime().date(); break; } } // TODO: This can be templated instead of hardcoding // Conflict/No Conflict QString cstring = tr("Conflict %1") .arg(MythDate::toString(m_conflictDate, MythDate::kDateFull | MythDate::kSimplify)); statusText->SetText(cstring); } else statusText->SetText(tr("No Conflicts")); } MythUIText *filterText = dynamic_cast<MythUIText*>(GetChild("filter")); if (filterText) { if (m_showAll) filterText->SetText(tr("All")); else filterText->SetText(tr("Important")); } }