#!/usr/bin/env python import subprocess import sys import time """ Shuts down VDR, performs a scan, then updates VDR's channels.conf with Freeview numbering. """ INVOKE_RCD = "invoke-rc.d vdr" STOP_VDR = INVOKE_RCD + " stop" START_VDR = INVOKE_RCD + " start" SCAN_COMMAND = "scan -q -o vdr -e 4 -u " \ + "/usr/share/doc/dvb-utils/examples/scan/dvb-t/uk-Rowridge" VDR_CHANNELS_FILE = "/var/lib/vdr/channels.conf" OUTPUT_FILE = VDR_CHANNELS_FILE def scan(): """ Runs SCAN_COMMAND and returns result as a list of lines. """ print "Scanning" scan_proc = subprocess.Popen(SCAN_COMMAND, 0, None, None, subprocess.PIPE, None, None, False, True) result = scan_proc.wait() if result: raise Exception("scan failed with exit code %d" % result) return scan_proc.stdout.readlines() def load_channels_as_lines(filename): fp = file(filename, 'r') lines = fp.readlines() fp.close() return lines def lines_to_dict(lines): """ Processes the lines and creates a dictionary keyed by channel name. Each value is [line, channel_number]. """ dict = {} number = 1 for l in lines: if l.startswith(':@'): number = int(l[2:].rstrip()) else: name = l.split(':', 1)[0] if ';' in name: name = name.split(';', 1)[0] dict[name] = [l, number] number += 1 return dict def dict_to_sorted_lines(dict): """ Convert the dictionary back to lines, including :@n where necessary, all in the correct order. """ # Create an intermediate list of [line, channel_number] for sorting sortable = [] for v in dict.values(): sortable.append(v) sortable.sort(key = lambda x: x[1]) # Now generate lines in output format number = -1 lines = [] for l in sortable: if l[1] != number: number = l[1] lines.append(":@%d\n" % number) lines.append(l[0]) number += 1 return lines def renumber_old_from_new(old, new): """ For each entry in the old dict, this looks up the same channel name in the new dict and replaces the old channel number with the new one, but preserves all the other details from old. No return value; alters old in place. """ for [k, old_val] in old.items(): new_val = new.get(k) if new_val: old_val[1] = new_val[1] def generate_new_lines(): """ Call the various other functions to generate a nice new list of lines to save as VDR's channels.conf. """ scan_lines = scan() vdr_lines = load_channels_as_lines(VDR_CHANNELS_FILE) scan_dict = lines_to_dict(scan_lines) vdr_dict = lines_to_dict(vdr_lines) renumber_old_from_new(vdr_dict, scan_dict) return dict_to_sorted_lines(vdr_dict) def main(): start_stop_vdr = "-s" in sys.argv if start_stop_vdr: print "Stopping VDR" subprocess.call(STOP_VDR.split()) print "Pausing" time.sleep(5) new_lines = generate_new_lines() fp = file(OUTPUT_FILE, 'w') fp.writelines(new_lines) fp.close() if start_stop_vdr: print "Starting VDR" subprocess.call(START_VDR.split()) if __name__ == '__main__': main()