diff --git a/mythplugins/mytharchive/mytharchive/thumbfinder.cpp b/mythplugins/mytharchive/mytharchive/thumbfinder.cpp index d2bcdf56d1..25b3829237 100644 --- a/mythplugins/mytharchive/mytharchive/thumbfinder.cpp +++ b/mythplugins/mytharchive/mytharchive/thumbfinder.cpp @@ -159,6 +159,8 @@ bool ThumbFinder::Create(void) connect(m_frameButton, SIGNAL(Clicked()), this, SLOT(updateThumb())); + m_seekAmountText->SetText(SeekAmounts[m_currentSeek].name); + BuildFocusList(); SetFocusWidget(m_imageGrid); @@ -274,6 +276,12 @@ void ThumbFinder::loadCutList() delete progInfo; } + if (m_deleteMap.isEmpty()) + { + LOG(VB_GENERAL, LOG_ERR, "ThumbFinder::loadCutList: Got an empty delete map"); + return; + } + // if the first mark is a end mark then add the start mark at the beginning frm_dir_map_t::const_iterator it = m_deleteMap.begin(); if (it.value() == MARK_CUT_END) diff --git a/mythtv/bindings/perl/MythTV.pm b/mythtv/bindings/perl/MythTV.pm index 188fcc0080..db196ecdd2 100644 --- a/mythtv/bindings/perl/MythTV.pm +++ b/mythtv/bindings/perl/MythTV.pm @@ -372,6 +372,8 @@ EOF $self->{'db_user'}, $self->{'db_pass'}) or die "Cannot connect to database: $!\n\n"; + $self->{'dbh'}->do("SET SESSION sql_mode = ''") + or die "Can't set sql_mode: $!\n\n"; $self->{'dbh'}->do("SET time_zone = 'Etc/UTC'") or die "Can't set timezone: $!\n\n"; diff --git a/mythtv/bindings/python/MythTV/dataheap.py b/mythtv/bindings/python/MythTV/dataheap.py index 859e060112..4de3085423 100644 --- a/mythtv/bindings/python/MythTV/dataheap.py +++ b/mythtv/bindings/python/MythTV/dataheap.py @@ -283,7 +283,7 @@ class Recorded( CMPRecord, DBDataWrite ): 'commflagged':0, 'recgroup':'Default', 'seriesid':'', 'programid':'', 'lastmodified':'CURRENT_TIMESTAMP', 'filesize':0, 'stars':0, 'previouslyshown':0, - 'preserve':0, 'bookmarkupdate':0, + 'preserve':0, 'bookmarkupdate':None, 'findid':0, 'deletepending':0, 'transcoder':0, 'timestretch':1, 'recpriority':0, 'playgroup':'Default', 'profile':'No', 'duplicate':1, 'transcoded':0, diff --git a/mythtv/libs/libmythbase/lcddevice.cpp b/mythtv/libs/libmythbase/lcddevice.cpp index f3924d912d..1ee9964351 100644 --- a/mythtv/libs/libmythbase/lcddevice.cpp +++ b/mythtv/libs/libmythbase/lcddevice.cpp @@ -77,6 +77,7 @@ LCD::LCD() connect(m_retryTimer, SIGNAL(timeout()), this, SLOT(restartConnection())); connect(m_LEDTimer, SIGNAL(timeout()), this, SLOT(outputLEDs())); + connect(this, &LCD::sendToServer, this, &LCD::sendToServerSlot, Qt::QueuedConnection); } bool LCD::m_enabled = false; @@ -204,13 +205,20 @@ bool LCD::connectToHost(const QString &lhostname, unsigned int lport) return m_connected; } -void LCD::sendToServer(const QString &someText) +void LCD::sendToServerSlot(const QString &someText) { QMutexLocker locker(&m_socketLock); if (!m_socket || !m_lcdReady) return; + if (m_socket->thread() != QThread::currentThread()) + { + LOG(VB_GENERAL, LOG_ERR, + "Sending to LCDServer from wrong thread."); + return; + } + // Check the socket, make sure the connection is still up if (QAbstractSocket::ConnectedState != m_socket->state()) { diff --git a/mythtv/libs/libmythbase/lcddevice.h b/mythtv/libs/libmythbase/lcddevice.h index b6346ecf6a..c3247b4c93 100644 --- a/mythtv/libs/libmythbase/lcddevice.h +++ b/mythtv/libs/libmythbase/lcddevice.h @@ -293,10 +293,13 @@ class MBASE_PUBLIC LCD : public QObject void restartConnection(); // Try to re-establish the connection to // LCDServer every 10 seconds void outputLEDs(); + void sendToServerSlot(const QString &someText); + +signals: + void sendToServer(const QString &someText); private: bool startLCDServer(void); - void sendToServer(const QString &someText); void init(); void handleKeyPress(const QString &keyPressed); QString quotedString(const QString &string); diff --git a/mythtv/libs/libmythbase/loggingserver.cpp b/mythtv/libs/libmythbase/loggingserver.cpp index 4ebb705f62..15aafa2ef1 100644 --- a/mythtv/libs/libmythbase/loggingserver.cpp +++ b/mythtv/libs/libmythbase/loggingserver.cpp @@ -722,7 +722,7 @@ void DBLoggerThread::run(void) if (!item) continue; - if (item->message()[0] != '\0') + if (item->message()[0] != QChar('\0')) { qLock.unlock(); bool logged = m_logger->logqmsg(*query, item); diff --git a/mythtv/libs/libmythtv/deletemap.cpp b/mythtv/libs/libmythtv/deletemap.cpp index 1be1a02897..adf06c2f11 100644 --- a/mythtv/libs/libmythtv/deletemap.cpp +++ b/mythtv/libs/libmythtv/deletemap.cpp @@ -489,7 +489,8 @@ void DeleteMap::NewCut(uint64_t frame) { LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Deleting bounded marker: %1").arg(otherframe)); - Delete(otherframe); + it = m_deleteMap.erase(it); + m_changed = true; } } } diff --git a/mythtv/libs/libmythtv/eitfixup.cpp b/mythtv/libs/libmythtv/eitfixup.cpp index 6c664c92ad..28b9816cc2 100644 --- a/mythtv/libs/libmythtv/eitfixup.cpp +++ b/mythtv/libs/libmythtv/eitfixup.cpp @@ -2658,8 +2658,10 @@ void EITFixUp::FixGreekEIT(DBEventEIT &event) const bool ok; uint y = tmpRegEx.cap(1).toUInt(&ok); if (ok) + { event.originalairdate = QDate(y, 1, 1); event.description.replace(tmpRegEx, ""); + } } // Remove white spaces event.description = event.description.trimmed(); diff --git a/mythtv/libs/libmythtv/eithelper.cpp b/mythtv/libs/libmythtv/eithelper.cpp index 5b66988766..1369cab6c3 100644 --- a/mythtv/libs/libmythtv/eithelper.cpp +++ b/mythtv/libs/libmythtv/eithelper.cpp @@ -1085,16 +1085,17 @@ static void init_fixup(FixupMap &fix) fix[ (long long)i << 32 | 2U << 16] = EITFixUp::kFixUK; fix[ 2059LL << 32 | 2U << 16] = EITFixUp::kFixUK; fix[ 2061LL << 32 | 2U << 16] = EITFixUp::kFixUK; - fix[ 2063LL << 32 | 2U << 16] = EITFixUp::kFixUK; - fix[ 2064LL << 32 | 2U << 16] = EITFixUp::kFixUK; - fix[ 2066LL << 32 | 2U << 16] = EITFixUp::kFixUK; - fix[ 2068LL << 32 | 2U << 16] = EITFixUp::kFixUK; - fix[ 2069LL << 32 | 2U << 16] = EITFixUp::kFixUK; + for (int i = 2063; i <= 2069; ++i) + fix[ (long long)i << 32 | 2U << 16] = EITFixUp::kFixUK; + fix[ 2071LL << 32 | 2U << 16] = EITFixUp::kFixUK; fix[ 2076LL << 32 | 2U << 16] = EITFixUp::kFixUK; fix[ 2081LL << 32 | 2U << 16] = EITFixUp::kFixUK; - fix[ 2089LL << 32 | 2U << 16] = EITFixUp::kFixUK; - fix[ 2096LL << 32 | 2U << 16] = EITFixUp::kFixUK | EITFixUp::kFixHTML; - fix[ 2107LL << 32 | 2U << 16] = EITFixUp::kFixUK; + for (int i = 2089; i <= 2092; ++i) + fix[ (long long)i << 32 | 2U << 16] = EITFixUp::kFixUK; + for (int i = 2094; i <= 2099; ++i) + fix[ (long long)i << 32 | 2U << 16] = EITFixUp::kFixUK; + for (int i = 2102; i <= 2110; ++i) + fix[ (long long)i << 32 | 2U << 16] = EITFixUp::kFixUK; fix[ 2112LL << 32 | 2U << 16] = EITFixUp::kFixUK; fix[ 2116LL << 32 | 2U << 16] = EITFixUp::kFixUK; fix[ 2301LL << 32 | 2U << 16] = EITFixUp::kFixUK | EITFixUp::kFixHTML; diff --git a/mythtv/libs/libmythtv/iptvtuningdata.h b/mythtv/libs/libmythtv/iptvtuningdata.h index c5a3c2ea87..111052d6b9 100644 --- a/mythtv/libs/libmythtv/iptvtuningdata.h +++ b/mythtv/libs/libmythtv/iptvtuningdata.h @@ -97,7 +97,7 @@ class MTV_PUBLIC IPTVTuningData const QUrl u = GetDataURL(); if (IsHLS()) return QString("%1(%2)").arg(u.toString()).arg(GetBitrate(0)); - if (IsHTTPTS()) + if (IsHTTPTS() || IsRTSP()) return QString("%1").arg(u.toString()); return QString("%1:%2:%3") .arg(u.host()).arg(u.userInfo()).arg(u.port()).toLower(); diff --git a/mythtv/libs/libmythtv/mythavutil.cpp b/mythtv/libs/libmythtv/mythavutil.cpp index afed323917..c69c4d279e 100644 --- a/mythtv/libs/libmythtv/mythavutil.cpp +++ b/mythtv/libs/libmythtv/mythavutil.cpp @@ -9,6 +9,7 @@ #include "mythframe.h" #include "mythavutil.h" #include "mythcorecontext.h" +#include "mythconfig.h" extern "C" { #include "libswscale/swscale.h" #include "libavfilter/avfilter.h" @@ -161,8 +162,20 @@ int MythAVCopy::Copy(AVPicture *dst, AVPixelFormat dst_pix_fmt, return frameout.size; } + int new_width = width; +#if ARCH_ARM + // The ARM build of FFMPEG has a bug that if sws_scale is + // called with source and dest sizes the same, and + // formats as shown below, it causes a bus error and the + // application core dumps. To avoid this I make a -1 + // difference in the new width, causing it to bypass + // the code optimization which is failing. + if (pix_fmt == AV_PIX_FMT_YUV420P + && dst_pix_fmt == AV_PIX_FMT_BGRA) + new_width = width - 1; +#endif d->swsctx = sws_getCachedContext(d->swsctx, width, height, pix_fmt, - width, height, dst_pix_fmt, + new_width, height, dst_pix_fmt, SWS_FAST_BILINEAR, NULL, NULL, NULL); if (d->swsctx == NULL) { diff --git a/mythtv/libs/libmythupnp/mythxmlclient.cpp b/mythtv/libs/libmythupnp/mythxmlclient.cpp index 45d7497fd9..c6fe011338 100644 --- a/mythtv/libs/libmythupnp/mythxmlclient.cpp +++ b/mythtv/libs/libmythupnp/mythxmlclient.cpp @@ -115,7 +115,9 @@ UPnPResultCode MythXMLClient::GetConnectionInfo( const QString &sPin, DatabasePa if (( nErrCode == UPnPResult_HumanInterventionRequired ) || ( nErrCode == UPnPResult_ActionNotAuthorized ) || - ( nErrCode == 501 )) + ( nErrCode == 501 ) || + // Not Authorized is generating invalid xml these days + nErrCode == UPnPResult_MythTV_XmlParseError ) { // Service calls no longer return UPnPResult codes, // convert standard 501 to UPnPResult code for now. diff --git a/mythtv/libs/libmythupnp/soapclient.cpp b/mythtv/libs/libmythupnp/soapclient.cpp index 4940e13d94..16748cf33e 100644 --- a/mythtv/libs/libmythupnp/soapclient.cpp +++ b/mythtv/libs/libmythupnp/soapclient.cpp @@ -267,9 +267,11 @@ QDomDocument SOAPClient::SendSOAPRequest(const QString &sMethod, list.clear(); QDomDocument doc; + int ErrLineNum = 0; - if (!doc.setContent(sXml, true, &sErrDesc, &nErrCode)) + if (!doc.setContent(sXml, true, &sErrDesc, &ErrLineNum)) { + nErrCode = UPnPResult_MythTV_XmlParseError; LOG(VB_UPNP, LOG_ERR, QString("SendSOAPRequest( %1 ) - Invalid response from %2") .arg(sMethod).arg(url.toString()) + diff --git a/mythtv/libs/libmythupnp/ssdp.cpp b/mythtv/libs/libmythupnp/ssdp.cpp index cf54274220..d89e009bde 100644 --- a/mythtv/libs/libmythupnp/ssdp.cpp +++ b/mythtv/libs/libmythupnp/ssdp.cpp @@ -624,6 +624,10 @@ bool SSDP::ProcessSearchResponse( const QStringMap &headers ) if (nPos < 0) return false; + // Ignore link local ip addresses + if (sDescURL.startsWith("http://[fe80::",Qt::CaseInsensitive)) + return false; + if ((nPos = sCache.indexOf("=", nPos)) < 0) return false; diff --git a/mythtv/libs/libmythupnp/upnp.h b/mythtv/libs/libmythupnp/upnp.h index 4b0457f4e8..acc2bd9ff7 100644 --- a/mythtv/libs/libmythupnp/upnp.h +++ b/mythtv/libs/libmythupnp/upnp.h @@ -80,6 +80,7 @@ typedef enum UPnPResult_MS_AccessDenied = 801, UPnPResult_MythTV_NoNamespaceGiven = 32001, + UPnPResult_MythTV_XmlParseError = 32002, } UPnPResultCode; diff --git a/mythtv/programs/mythfilldatabase/channeldata.cpp b/mythtv/programs/mythfilldatabase/channeldata.cpp index c0ee522b65..9825c4e8d4 100644 --- a/mythtv/programs/mythfilldatabase/channeldata.cpp +++ b/mythtv/programs/mythfilldatabase/channeldata.cpp @@ -128,27 +128,31 @@ QString ChannelData::normalizeChannelKey(const QString &chanName) const return result; } -QHash<QString, ChannelInfo> ChannelData::channelList(int sourceId) +ChannelList ChannelData::channelList(int sourceId) { - QHash<QString, ChannelInfo> retList; + ChannelList retList; - ChannelInfoList channelList = ChannelUtil::GetChannels(sourceId, false); + uint avail = 0; + ChannelInfoList channelList = ChannelUtil::LoadChannels(0, 0, avail, false, + ChannelUtil::kChanOrderByChanNum, + ChannelUtil::kChanGroupByChanid, + sourceId); ChannelInfoList::iterator it = channelList.begin(); for ( ; it != channelList.end(); ++it) { QString chanName = (*it).name; QString key = normalizeChannelKey(chanName); - retList[key] = (*it); + retList.insert(key, *it); } return retList; } ChannelInfo ChannelData::FindMatchingChannel(const ChannelInfo &chanInfo, - QHash<QString, ChannelInfo> existingChannels) const + ChannelList existingChannels) const { - QHash<QString, ChannelInfo>::iterator it; + ChannelList::iterator it; for (it = existingChannels.begin(); it != existingChannels.end(); ++it) { if ((*it).xmltvid == chanInfo.xmltvid) @@ -158,6 +162,27 @@ ChannelInfo ChannelData::FindMatchingChannel(const ChannelInfo &chanInfo, QString searchKey = normalizeChannelKey(chanInfo.name); ChannelInfo existChan = existingChannels.value(searchKey); + if (existChan.chanid < 1) + { + // Check if it is ATSC + int chansep = chanInfo.channum.indexOf(QRegExp("\\D")); + if (chansep > 0) + { + // Populate xmltvid for scanned ATSC channels + uint major = chanInfo.channum.left(chansep).toInt(); + uint minor = chanInfo.channum.right + (chanInfo.channum.length() - (chansep + 1)).toInt(); + + for (it = existingChannels.begin(); + it != existingChannels.end(); ++it) + { + if ((*it).atsc_major_chan == major && + (*it).atsc_minor_chan == minor) + return (*it); + } + } + } + return existChan; } @@ -169,7 +194,7 @@ void ChannelData::handleChannels(int id, ChannelInfoList *chanlist) return; } - QHash<QString, ChannelInfo> existingChannels = channelList(id); + ChannelList existingChannels = channelList(id); QString fileprefix = SetupIconCacheDirectory(); QDir::setCurrent(fileprefix); diff --git a/mythtv/programs/mythfilldatabase/channeldata.h b/mythtv/programs/mythfilldatabase/channeldata.h index 978ec8c77b..af0aa1c04d 100644 --- a/mythtv/programs/mythfilldatabase/channeldata.h +++ b/mythtv/programs/mythfilldatabase/channeldata.h @@ -7,6 +7,8 @@ // libmythtv #include "channelinfo.h" +using ChannelList = QMultiHash<QString, ChannelInfo>; + class ChannelData { public: @@ -21,8 +23,8 @@ class ChannelData unsigned int chanid); ChannelInfo FindMatchingChannel(const ChannelInfo &chanInfo, - QHash<QString, ChannelInfo> existingChannels) const; - QHash<QString, ChannelInfo> channelList(int sourceId); + ChannelList existingChannels) const; + ChannelList channelList(int sourceId); QString normalizeChannelKey(const QString &chanName) const; public: diff --git a/mythtv/programs/mythfilldatabase/xmltvparser.cpp b/mythtv/programs/mythfilldatabase/xmltvparser.cpp index 62a3a13820..21bf5b8324 100644 --- a/mythtv/programs/mythfilldatabase/xmltvparser.cpp +++ b/mythtv/programs/mythfilldatabase/xmltvparser.cpp @@ -131,82 +131,107 @@ static void fromXMLTVDate(QString ×tr, QDateTime &dt) return; } - QStringList split = timestr.split(" "); + QStringList split = timestr.split(" ", QString::SkipEmptyParts); QString ts = split[0]; - QDateTime tmpDT; - tmpDT.setTimeSpec(Qt::LocalTime); - - // UTC/GMT, just strip - if (ts.endsWith('Z')) - ts.truncate(ts.length()-1); - - if (ts.length() == 14) - { - tmpDT = QDateTime::fromString(ts, "yyyyMMddHHmmss"); - } - else if (ts.length() == 12) - { - tmpDT = QDateTime::fromString(ts, "yyyyMMddHHmm"); - } - else if (ts.length() == 8) - { - tmpDT = QDateTime::fromString(ts, "yyyyMMdd"); - } - else if (ts.length() == 6) + QDate tmpDate; + QTime tmpTime; + QString tzoffset; + + // Process the TZ offset (if any) + if (split.size() > 1) { - tmpDT = QDateTime::fromString(ts, "yyyyMM"); + tzoffset = split[1]; + // These shouldn't be required and they aren't ISO 8601 but the + // xmltv spec mentions these and just these so handle them just in + // case + if (tzoffset == "GMT" || tzoffset == "UTC") + tzoffset = "+0000"; + else if (tzoffset == "BST") + tzoffset = "+0100"; } - else if (ts.length() == 4) + else { - tmpDT = QDateTime::fromString(ts, "yyyy"); + // We will accept a datetime with a trailing Z as being explicit + if (ts.endsWith('Z')) + { + tzoffset = "+0000"; + ts.truncate(ts.length()-1); + } + else + { + tzoffset = "+0000"; + static bool warned_once_on_implicit_utc = false; + if (!warned_once_on_implicit_utc) + { + LOG(VB_XMLTV, LOG_WARNING, "No explicit time zone found, " + "guessing implicit UTC! Please consider enhancing " + "the guide source to provide explicit UTC or local " + "time instead."); + warned_once_on_implicit_utc = true; + } + } } - if (!tmpDT.isValid()) + // Process the date part + QString tsDate = ts.left(8); + if (tsDate.length() == 8) + tmpDate = QDate::fromString(tsDate, "yyyyMMdd"); + else if (tsDate.length() == 6) + tmpDate = QDate::fromString(tsDate, "yyyyMM"); + else if (tsDate.length() == 4) + tmpDate = QDate::fromString(tsDate, "yyyy"); + if (!tmpDate.isValid()) { - LOG(VB_GENERAL, LOG_ERR, - QString("Ignoring unknown timestamp format: %1") - .arg(ts)); + LOG(VB_XMLTV, LOG_ERR, + QString("Invalid datetime (date) in XMLTV data, ignoring: %1") + .arg(timestr)); return; } - - if (split.size() > 1) + + // Process the time part (if any) + if (ts.length() > 8) { - QString tmp = split[1].trimmed(); - - // These shouldn't be required and they aren't ISO 8601 but the - // xmltv spec mentions these and just these so handle them just in - // case - if (tmp == "GMT" || tmp == "UTC") - tmp = "+0000"; - else if (tmp == "BST") - tmp = "+0100"; - - // While this seems like a hack, it's better than what was done before - QString isoDateString = QString("%1 %2").arg(tmpDT.toString(Qt::ISODate)) - .arg(tmp); - // Work around Qt bug where zero offset dates are flagged as LocalTime - tmpDT = QDateTime::fromString(isoDateString, Qt::ISODate); - if (tmpDT.timeSpec() == Qt::LocalTime) - tmpDT.setTimeSpec(Qt::UTC); - dt = tmpDT.toUTC(); + QString tsTime = ts.mid(8); + if (tsTime.length() == 6) + tmpTime = QTime::fromString(tsTime, "HHmmss"); + else if (tsTime.length() == 4) + tmpTime = QTime::fromString(tsTime, "HHmm"); + else if (tsTime.length() == 2) + tmpTime = QTime::fromString(tsTime, "HH"); + if (!tmpTime.isValid()) + { + // Time part exists, but is (somehow) invalid + LOG(VB_XMLTV, LOG_ERR, + QString("Invalid datetime (time) in XMLTV data, ignoring: %1") + .arg(timestr)); + return; + } } - - if (!dt.isValid()) - { - static bool warned_once_on_implicit_utc = false; - if (!warned_once_on_implicit_utc) + + QDateTime tmpDT = QDateTime(tmpDate, tmpTime, Qt::UTC); + if (!tmpDT.isValid()) { - LOG(VB_XMLTV, LOG_ERR, "No explicit time zone found, " - "guessing implicit UTC! Please consider enhancing " - "the guide source to provice explicit UTC or local " - "time instead."); - warned_once_on_implicit_utc = true; + LOG(VB_XMLTV, LOG_ERR, + QString("Invalid datetime (combination of date/time) " + "in XMLTV data, ignoring: %1").arg(timestr)); + return; } - dt = tmpDT; + + // While this seems like a hack, it's better than what was done before + QString isoDateString = tmpDT.toString(Qt::ISODate); + if (isoDateString.endsWith('Z')) // Should always be Z, but ... + isoDateString.truncate(isoDateString.length()-1); + isoDateString += tzoffset; + dt = QDateTime::fromString(isoDateString, Qt::ISODate).toUTC(); + + if (!dt.isValid()) + { + LOG(VB_XMLTV, LOG_ERR, + QString("Invalid datetime (zone offset) in XMLTV data, " + "ignoring: %1").arg(timestr)); + return; } - dt.setTimeSpec(Qt::UTC); - timestr = MythDate::toString(dt, MythDate::kFilename); } @@ -277,8 +302,7 @@ static void parseAudio(QDomElement &element, ProgInfo *pginfo) ProgInfo *XMLTVParser::parseProgram(QDomElement &element) { - QString uniqueid, season, episode, totalepisodes; - int dd_progid_done = 0; + QString programid, season, episode, totalepisodes; ProgInfo *pginfo = new ProgInfo(); QString text = element.attribute("start", ""); @@ -451,8 +475,11 @@ ProgInfo *XMLTVParser::parseProgram(QDomElement &element) int idx = episodenum.indexOf('.'); if (idx != -1) episodenum.remove(idx, 1); - pginfo->programId = episodenum; - dd_progid_done = 1; + programid = episodenum; + /* Only EPisodes and SHows are part of a series for SD */ + if (programid.startsWith(QString("EP")) || + programid.startsWith(QString("SH"))) + pginfo->seriesId = QString("EP") + programid.mid(2,8); } else if (info.attribute("system") == "xmltv_ns") { @@ -462,6 +489,7 @@ ProgInfo *XMLTVParser::parseProgram(QDomElement &element) totalepisodes = episode.section('/',1,1).trimmed(); episode = episode.section('/',0,0).trimmed(); season = episodenum.section('.',0,0).trimmed(); + season = season.section('/',0,0).trimmed(); QString part(episodenum.section('.',2,2)); QString partnumber(part.section('/',0,0).trimmed()); QString parttotal(part.section('/',1,1).trimmed()); @@ -549,22 +577,20 @@ ProgInfo *XMLTVParser::parseProgram(QDomElement &element) && ProgramInfo::kCategorySeries != pginfo->categoryType) pginfo->airdate = current_year; - /* Let's build ourself a programid */ - QString programid; + if (programid.isEmpty()) + { - if (ProgramInfo::kCategoryMovie == pginfo->categoryType) - programid = "MV"; - else if (ProgramInfo::kCategorySeries == pginfo->categoryType) - programid = "EP"; - else if (ProgramInfo::kCategorySports == pginfo->categoryType) - programid = "SP"; - else - programid = "SH"; + /* Let's build ourself a programid */ + + if (ProgramInfo::kCategoryMovie == pginfo->categoryType) + programid = "MV"; + else if (ProgramInfo::kCategorySeries == pginfo->categoryType) + programid = "EP"; + else if (ProgramInfo::kCategorySports == pginfo->categoryType) + programid = "SP"; + else + programid = "SH"; - if (!uniqueid.isEmpty()) // we already have a unique id ready for use - programid.append(uniqueid); - else - { QString seriesid = QString::number(ELFHash(pginfo->title.toUtf8())); pginfo->seriesId = seriesid; programid.append(seriesid); @@ -602,8 +628,8 @@ ProgInfo *XMLTVParser::parseProgram(QDomElement &element) programid.clear(); } } - if (dd_progid_done == 0) - pginfo->programId = programid; + + pginfo->programId = programid; return pginfo; } @@ -662,7 +688,21 @@ bool XMLTVParser::parseFile( { ProgInfo *pginfo = parseProgram(e); - if (pginfo->startts == pginfo->endts) + if (!(pginfo->starttime.isValid())) + { + LOG(VB_GENERAL, LOG_WARNING, QString("Invalid programme (%1), " + "invalid start time, " + "skipping") + .arg(pginfo->title)); + } + else if (pginfo->channel.isEmpty()) + { + LOG(VB_GENERAL, LOG_WARNING, QString("Invalid programme (%1), " + "missing channel, " + "skipping") + .arg(pginfo->title)); + } + else if (pginfo->startts == pginfo->endts) { LOG(VB_GENERAL, LOG_WARNING, QString("Invalid programme (%1), " "identical start and end " @@ -712,4 +752,3 @@ bool XMLTVParser::parseFile( return true; } - diff --git a/mythtv/programs/mythfrontend/proglist.cpp b/mythtv/programs/mythfrontend/proglist.cpp index 37e4506130..ebd94c18a1 100644 --- a/mythtv/programs/mythfrontend/proglist.cpp +++ b/mythtv/programs/mythfrontend/proglist.cpp @@ -960,11 +960,11 @@ void ProgLister::FillViewList(const QString &view) m_viewTextList.push_back(tr("All")); m_viewList.push_back("= 0.0"); m_viewTextList.push_back(tr("Unrated")); - m_viewList.push_back(QString("= 10.0")); + m_viewList.push_back(QString(">= %1").arg((10 - 0.5) / 10.0 - 0.001)); m_viewTextList.push_back(tr("%n star(s)", "", 10)); for (int i = 9; i > 0; i--) { - float stars = i / 10.0; + float stars = (i - 0.5 ) / 10.0 - 0.001; m_viewList.push_back(QString(">= %1").arg(stars)); m_viewTextList.push_back(tr("%n star(s) and above", "", i)); }