Permalink
Browse files

Make a best guess effort to automate the insertion of xmltvids

If mythfilldatabase don't find the xmltvid in channeldata::handleChannels, it will try to match the callsign already in the channel table (coming from the channel scan), and the one coming from the xmltv file. Most of the time, this match is sufficient to update the xmltvid field.

  With this patch, people will be able:

   1/ First step: do the channel scan.

   2/ Second step: update xmltvid field and program with a
      mythfilldatabase --update --source n file.xmltv

Fixes #9417

Signed-off-by: Stuart Morgan <smorgan@mythtv.org>
  • Loading branch information...
lo92fr authored and stuartm committed Nov 22, 2012
1 parent 1b677bf commit b7a1bd237e16c7653f34a2826eef14f841ef4e7b
@@ -2097,6 +2097,8 @@ IPTVTuningData ChannelUtil::GetIPTVTuningData(uint chanid)
return tuning;
}
// TODO This should be modified to load a complete channelinfo object including
// all fields from the database
ChannelInfoList ChannelUtil::GetChannelsInternal(
uint sourceid, bool vis_only, bool include_disconnected,
const QString &grp, uint changrpid)
@@ -2109,7 +2111,8 @@ ChannelInfoList ChannelUtil::GetChannelsInternal(
"SELECT channum, callsign, channel.chanid, "
" atsc_major_chan, atsc_minor_chan, "
" name, icon, mplexid, visible, "
" channel.sourceid, cardinput.cardid, channelgroup.grpid "
" channel.sourceid, cardinput.cardid, channelgroup.grpid, "
" xmltvid "
"FROM channel "
"LEFT JOIN channelgroup ON channel.chanid = channelgroup.chanid "
" %1 JOIN cardinput ON cardinput.sourceid = channel.sourceid "
@@ -2168,6 +2171,8 @@ ChannelInfoList ChannelUtil::GetChannelsInternal(
query.value(11).toUInt(), /* cardid */
query.value(10).toUInt()); /* grpid */
chan.xmltvid = query.value(12).toString(); /* xmltvid */
list.push_back(chan);
}
@@ -58,23 +58,23 @@ static void get_atsc_stuff(QString channum, int sourceid, int freqid,
bool ChannelData::insert_chan(uint sourceid)
{
bool insert_channels = channel_updates;
bool insert_channels = m_channelUpdates;
if (!insert_channels)
{
bool isEncoder, isUnscanable;
bool isCableCard = SourceUtil::IsCableCardPresent(sourceid);
if (cardtype.isEmpty())
if (m_cardType.isEmpty())
{
isEncoder = SourceUtil::IsEncoder(sourceid);
isUnscanable = SourceUtil::IsUnscanable(sourceid);
}
else
{
isEncoder = CardUtil::IsEncoder(cardtype);
isUnscanable = CardUtil::IsUnscanable(cardtype);
isEncoder = CardUtil::IsEncoder(m_cardType);
isUnscanable = CardUtil::IsUnscanable(m_cardType);
}
insert_channels = (isCableCard || isEncoder || isUnscanable) &&
!remove_new_channels;
!m_removeNewChannels;
}
return insert_channels;
@@ -84,25 +84,12 @@ bool ChannelData::insert_chan(uint sourceid)
unsigned int ChannelData::promptForChannelUpdates(
ChannelInfoList::iterator chaninfo, unsigned int chanid)
{
if (chanid == 0)
{
// Default is 0 to allow rapid skipping of many channels,
// in some xmltv outputs there may be over 100 channel, but
// only 10 or so that are available in each area.
chanid = getResponse(QObject::tr("Choose a channel ID (positive integer) "), "0")
.toUInt();
// If we wish to skip this channel, use the default 0 and return.
if (chanid == 0)
return(0);
}
(*chaninfo).name = getResponse(QObject::tr("Choose a channel name (any string, "
"long version) "),(*chaninfo).name);
(*chaninfo).callsign = getResponse(QObject::tr("Choose a channel callsign (any string, "
"short version) "),(*chaninfo).callsign);
if (channel_preset)
if (m_channelPreset)
{
(*chaninfo).channum = getResponse(QObject::tr("Choose a channel preset (0..999) "),
(*chaninfo).channum);
@@ -130,8 +117,55 @@ unsigned int ChannelData::promptForChannelUpdates(
return(chanid);
}
QString ChannelData::normalizeChannelKey(const QString &chanName) const
{
QString result = chanName;
// Lowercase
result = result.toLower();
// Strip all whitespace
result = result.replace(" ", "");
return result;
}
QHash<QString, ChannelInfo> ChannelData::channelList(int sourceId)
{
QHash<QString, ChannelInfo> retList;
ChannelInfoList channelList = ChannelUtil::GetChannels(sourceId, true,
"chanid");
ChannelInfoList::iterator it = channelList.begin();
for ( ; it != channelList.end(); ++it)
{
QString chanName = (*it).name;
QString key = normalizeChannelKey(chanName);
retList[key] = (*it);
}
return retList;
}
ChannelInfo ChannelData::FindMatchingChannel(const ChannelInfo &chanInfo,
QHash<QString, ChannelInfo> existingChannels) const
{
QHash<QString, ChannelInfo>::iterator it;
for (it = existingChannels.begin(); it != existingChannels.end(); ++it)
{
if ((*it).xmltvid == chanInfo.xmltvid)
return (*it);
}
QString searchKey = normalizeChannelKey(chanInfo.name);
ChannelInfo existChan = existingChannels.value(searchKey);
return existChan;
}
void ChannelData::handleChannels(int id, ChannelInfoList *chanlist)
{
QHash<QString, ChannelInfo> existingChannels = channelList(id);
QString fileprefix = SetupIconCacheDirectory();
QDir::setCurrent(fileprefix);
@@ -141,6 +175,9 @@ void ChannelData::handleChannels(int id, ChannelInfoList *chanlist)
ChannelInfoList::iterator i = chanlist->begin();
for (; i != chanlist->end(); ++i)
{
if ((*i).xmltvid.isEmpty())
continue;
QString localfile;
if (!(*i).icon.isEmpty())
@@ -191,78 +228,62 @@ void ChannelData::handleChannels(int id, ChannelInfoList *chanlist)
}
}
}
query.prepare(
"SELECT chanid, name, callsign, channum, "
" finetune, icon, freqid, tvformat "
"FROM channel "
"WHERE xmltvid = :XMLTVID AND "
" sourceid = :SOURCEID");
query.bindValue(":XMLTVID", (*i).xmltvid);
query.bindValue(":SOURCEID", id);
if (!query.exec())
{
MythDB::DBError("handleChannels", query);
}
else if (query.next())
ChannelInfo dbChan = FindMatchingChannel(*i, existingChannels);
if (dbChan.chanid > 0) // Channel exists, updating
{
uint chanid = query.value(0).toUInt();
if (interactive)
LOG(VB_XMLTV, LOG_NOTICE,
QString("Match found for xmltvid %1 to channel %2 (%3)")
.arg((*i).xmltvid).arg(dbChan.name).arg(dbChan.chanid));
if (m_interactive)
{
QString name = query.value(1).toString();
QString callsign = query.value(2).toString();
QString chanstr = query.value(3).toString();
int finetune = query.value(4).toInt();
QString icon = query.value(5).toString();
QString freqid = query.value(6).toString();
QString tvformat = query.value(7).toString();
cout << "### " << endl;
cout << "### Existing channel found" << endl;
cout << "### " << endl;
cout << "### xmltvid = "
<< (*i).xmltvid.toLocal8Bit().constData() << endl;
<< (*i).xmltvid.toLocal8Bit().constData() << endl;
cout << "### chanid = "
<< chanid << endl;
<< dbChan.chanid << endl;
cout << "### name = "
<< name.toLocal8Bit().constData() << endl;
<< dbChan.name.toLocal8Bit().constData() << endl;
cout << "### callsign = "
<< callsign.toLocal8Bit().constData() << endl;
<< dbChan.callsign.toLocal8Bit().constData() << endl;
cout << "### channum = "
<< chanstr.toLocal8Bit().constData() << endl;
if (channel_preset)
<< dbChan.channum.toLocal8Bit().constData() << endl;
if (m_channelPreset)
{
cout << "### freqid = "
<< freqid.toLocal8Bit().constData() << endl;
<< dbChan.freqid.toLocal8Bit().constData() << endl;
}
cout << "### finetune = "
<< finetune << endl;
<< dbChan.finetune << endl;
cout << "### tvformat = "
<< tvformat.toLocal8Bit().constData() << endl;
<< dbChan.tvformat.toLocal8Bit().constData() << endl;
cout << "### icon = "
<< icon.toLocal8Bit().constData() << endl;
<< dbChan.icon.toLocal8Bit().constData() << endl;
cout << "### " << endl;
(*i).name = name;
(*i).callsign = callsign;
(*i).channum = chanstr;
(*i).finetune = finetune;
(*i).freqid = freqid;
(*i).tvformat = tvformat;
// The only thing the xmltv data supplies here is the icon
(*i).name = dbChan.name;
(*i).callsign = dbChan.callsign;
(*i).channum = dbChan.channum;
(*i).finetune = dbChan.finetune;
(*i).freqid = dbChan.freqid;
(*i).tvformat = dbChan.tvformat;
promptForChannelUpdates(i, chanid);
promptForChannelUpdates(i, dbChan.chanid);
if ((*i).callsign.isEmpty())
(*i).callsign = QString::number(chanid);
if (name != (*i).name ||
callsign != (*i).callsign ||
chanstr != (*i).channum ||
finetune != (*i).finetune ||
freqid != (*i).freqid ||
icon != localfile ||
tvformat != (*i).tvformat)
(*i).callsign = dbChan.name;
if (dbChan.name != (*i).name ||
dbChan.callsign != (*i).callsign ||
dbChan.channum != (*i).channum ||
dbChan.finetune != (*i).finetune ||
dbChan.freqid != (*i).freqid ||
dbChan.icon != localfile ||
dbChan.tvformat != (*i).tvformat)
{
MSqlQuery subquery(MSqlQuery::InitCon());
subquery.prepare("UPDATE channel SET chanid = :CHANID, "
@@ -272,7 +293,7 @@ void ChannelData::handleChannels(int id, ChannelInfoList *chanlist)
"tvformat = :TVFORMAT "
" WHERE xmltvid = :XMLTVID "
"AND sourceid = :SOURCEID;");
subquery.bindValue(":CHANID", chanid);
subquery.bindValue(":CHANID", dbChan.chanid);
subquery.bindValue(":NAME", (*i).name);
subquery.bindValue(":CALLSIGN", (*i).callsign);
subquery.bindValue(":CHANNUM", (*i).channum);
@@ -301,15 +322,34 @@ void ChannelData::handleChannels(int id, ChannelInfoList *chanlist)
cout << "### " << endl;
}
}
else
else if ((dbChan.icon != localfile) ||
(dbChan.xmltvid != (*i).xmltvid))
{
if (!non_us_updating && !localfile.isEmpty())
LOG(VB_XMLTV, LOG_NOTICE, QString("Updating channel %1 (%2)")
.arg(dbChan.name).arg(dbChan.chanid));
if (!m_nonUSUpdating && !localfile.isEmpty())
{
MSqlQuery subquery(MSqlQuery::InitCon());
subquery.prepare("UPDATE channel SET icon = :ICON WHERE "
"chanid = :CHANID;");
subquery.bindValue(":ICON", localfile);
subquery.bindValue(":CHANID", chanid);
subquery.bindValue(":CHANID", dbChan.chanid);
if (!subquery.exec())
MythDB::DBError("Channel icon change", subquery);
}
else
{
if (localfile.isEmpty())
localfile = dbChan.icon;
MSqlQuery subquery(MSqlQuery::InitCon());
subquery.prepare("UPDATE channel SET icon = :ICON "
", xmltvid:= :XMLTVID WHERE "
"chanid = :CHANID;");
subquery.bindValue(":ICON", localfile);
subquery.bindValue(":XMLTVID", (*i).xmltvid);
subquery.bindValue(":CHANID", dbChan.chanid);
if (!subquery.exec())
MythDB::DBError("Channel icon change", subquery);
@@ -322,7 +362,7 @@ void ChannelData::handleChannels(int id, ChannelInfoList *chanlist)
long long freq = 0;
get_atsc_stuff((*i).channum, id, (*i).freqid.toInt(), major, minor, freq);
if (interactive && ((minor == 0) || (freq > 0)))
if (m_interactive && ((minor == 0) || (freq > 0)))
{
cout << "### " << endl;
cout << "### New channel found" << endl;
@@ -333,7 +373,7 @@ void ChannelData::handleChannels(int id, ChannelInfoList *chanlist)
<< (*i).callsign.toLocal8Bit().constData() << endl;
cout << "### channum = "
<< (*i).channum.toLocal8Bit().constData() << endl;
if (channel_preset)
if (m_channelPreset)
{
cout << "### freqid = "
<< (*i).freqid.toLocal8Bit().constData() << endl;
@@ -377,7 +417,7 @@ void ChannelData::handleChannels(int id, ChannelInfoList *chanlist)
cout << "### " << endl;
}
}
else if (!non_us_updating && ((minor == 0) || (freq > 0)))
else if (!m_nonUSUpdating && ((minor == 0) || (freq > 0)))
{
// We only do this if we are not asked to skip it with the
// --updating flag.
@@ -413,7 +453,7 @@ void ChannelData::handleChannels(int id, ChannelInfoList *chanlist)
if (chanid > 0)
{
QString cstr = QString((*i).channum);
if(channel_preset && cstr.isEmpty())
if(m_channelPreset && cstr.isEmpty())
cstr = QString::number(chanid % 1000);
bool retval = ChannelUtil::CreateChannel(
@@ -11,23 +11,28 @@ class ChannelData
{
public:
ChannelData() :
interactive(false), non_us_updating(false),
channel_preset(false), channel_updates(false),
remove_new_channels(false), filter_new_channels(true) {}
m_interactive(false), m_nonUSUpdating(false),
m_channelPreset(false), m_channelUpdates(false),
m_removeNewChannels(false), m_filterNewChannels(true) {}
bool insert_chan(uint sourceid);
void handleChannels(int id, ChannelInfoList *chanlist);
unsigned int promptForChannelUpdates(
ChannelInfoList::iterator chaninfo, unsigned int chanid);
unsigned int promptForChannelUpdates(ChannelInfoList::iterator chaninfo,
unsigned int chanid);
ChannelInfo FindMatchingChannel(const ChannelInfo &chanInfo,
QHash<QString, ChannelInfo> existingChannels) const;
QHash<QString, ChannelInfo> channelList(int sourceId);
QString normalizeChannelKey(const QString &chanName) const;
public:
bool interactive;
bool non_us_updating;
bool channel_preset;
bool channel_updates;
bool remove_new_channels;
bool filter_new_channels;
QString cardtype;
bool m_interactive;
bool m_nonUSUpdating;
bool m_channelPreset;
bool m_channelUpdates;
bool m_removeNewChannels;
bool m_filterNewChannels;
QString m_cardType;
};
#endif // _CHANNELDATA_H_
Oops, something went wrong.

0 comments on commit b7a1bd2

Please sign in to comment.