The question of how to merge multiple lineups seems to come up on a semi-regular basis. It's certainly one that I've had to deal with from time to time as Comcast and Zap2it play partial information games with my local channel roster.
This time around I decided to modularized my solution a bit further to make it more robust, flexible and easier for other folks to use.
Zap2it carries two incomplete lineups for my cable provider. The "analog cable" one is missing three channels which I get.
The "digital cable" one includes data for those three, along with many more that I don't get, but is missing a couple others.
I'm pretty sure that in both cases the missing channels are just dumb data entry errors. (BTW - For those who are all atwitter about the coming demise of the zap2it service, please note that the data source doesn't really have any bearing on the mechanics here. The same techniques can be applied whatever your upstream sources are.)
The setup works like this.
- On the Zap2it site I have two lineups, with the second one reduced to just the channel listings missing from the first one.
- In mythtv-setup I setup two "video sources", one for each lineup. Only the primary is associated with the capture card inputs under "input connections".
- Video source 1 is the "right" one for my cable service and provides most of my listings.
- Video source 2 is the "digital cable" option from the same provider, it only provides listings for the three missing channels.
- When the grabber is run mythfilldatabase downloads both sets of data and the script copies the data from the secondary lineup to fill in the gaps in the primary.
The main utility is this script which I call "
/usr/local/bin/copy_channel.sh". It handles all the details of inserting/replacing the lineup for one channel with the one from another. In non-North American contexts you may need to make other adjustments to the values inserted into the channel table.
Code:
#!/bin/bash
fatal () {
echo "Error: $* in copy_channel.sh"
exit 1
}
[ $# -ne 2 ] && fatal "Invalid argument count"
from_chanid=$1
to_chanid=$2
[ -z "$from_chanid" ] && fatal "Invalid source channel id"
[ "$from_chanid" -le 1000 ] && fatal "Invalid source channel id"
[ -z "$to_chanid" ] && fatal "Invalid destination channel id"
[ "$to_chanid" -le 1000 ] && fatal "Invalid destination channel id"
[ "$from_chanid" = "$to_chanid" ] && fatal "Identical channel ids"
to_sourceid=$(expr $to_chanid / 1000)
to_channum=$(expr $to_chanid % 1000)
to_freqid=$to_channum
to_atsc_major_chan=$to_channum
[ "$to_sourceid" -le 0 ] && fatal "Invalid source id"
[ "$to_channum" -le 0 ] && fatal "Invalid channel number"
echo "Copying data for channid $from_chanid to $to_chanid"
echo "Destination sourceid=$to_sourceid channum=$to_channum"
# You really only need to copy the channel table data over once, but
# it shouldn't hurt anything to do it every time. I could probably
# make this smarter about that...
mysql -u root mythconverg <<EOF
delete from channel
where chanid = '$to_chanid';
insert into channel
(select '$to_chanid', '$to_channum', '$to_freqid', '$to_sourceid',
callsign, name, icon, finetune, videofilters, xmltvid,
recpriority, contrast, brightness, colour, hue, tvformat,
commfree, '1', outputfilters, useonairguide, mplexid,
serviceid, atscsrcid, tmoffset, '$to_atsc_major_chan', atsc_minor_chan
from channel
where chanid = '$from_chanid');
delete from program
where chanid = '$to_chanid';
insert into program
(select '$to_chanid', starttime, endtime, title, subtitle, description,
category, category_type, airdate, stars, previouslyshown,
title_pronounce, stereo, subtitled, hdtv, closecaptioned,
partnumber, parttotal, seriesid, originalairdate, showtype,
colorcode, syndicatedepisodenumber, programid, manualid,
generic, listingsource, first, last
from program
where chanid = '$from_chanid');
delete from credits
where chanid = '$to_chanid';
insert into credits
(select person, '$to_chanid', starttime, role
from credits
where chanid = '$from_chanid');
delete from programgenres
where chanid = '$to_chanid';
insert into programgenres
(select '$to_chanid', starttime, relevance, genre
from programgenres
where chanid = '$from_chanid');
delete from programrating
where chanid = '$to_chanid';
insert into programrating
(select '$to_chanid', starttime, system, rating
from programrating
where chanid = '$from_chanid');
commit;
EOF
# This only needs to be done once at the end.
#/usr/bin/mythbackend --resched
The second piece is this script which I call "
/usr/local/bin/update_database.sh" and use as a wrapper for mythfilldatabase. It deals with issues like logging, making sure that mythfilldatabase is
always run as the mythtv user, and doing any merging. You can find the appropriate chanids to use by browsing the channel table in the database.
Code:
#!/bin/bash
fatal () {
echo "Error! $*"
exit 1
}
LOG_FILE="/var/log/mythtv/update_database.log"
mv -f $LOG_FILE $LOG_FILE.old
exec >$LOG_FILE 2>&1
fill_options="$*"
case $(id -nu) in
root)
su - mythtv -c "nice /usr/bin/mythfilldatabase $fill_options"
result=$?
;;
mythtv)
nice /usr/bin/mythfilldatabase $fill_options
result=$?
;;
*)
fatal "You must run this script at mythtv or root!"
;;
esac
sleep 5 # Give the DB time to settle.
# We can add as many mappings here as needed.
echo ; echo "Merging ESPNCL" ; echo
/usr/local/bin/copy_channel.sh 2048 1048
echo ; echo "Merging AZNTV" ; echo
/usr/local/bin/copy_channel.sh 2251 1098
echo ; echo "Merging BET" ; echo
/usr/local/bin/copy_channel.sh 2099 1099
echo
# This only needs to be done once at the end.
/usr/bin/mythbackend --resched
echo
echo "Database update completed"
exit $result