summaryrefslogtreecommitdiffstats
path: root/abs/core/LinHES-config/autocard.py
diff options
context:
space:
mode:
Diffstat (limited to 'abs/core/LinHES-config/autocard.py')
-rw-r--r--abs/core/LinHES-config/autocard.py503
1 files changed, 458 insertions, 45 deletions
diff --git a/abs/core/LinHES-config/autocard.py b/abs/core/LinHES-config/autocard.py
index eda2286..3d11fe0 100644
--- a/abs/core/LinHES-config/autocard.py
+++ b/abs/core/LinHES-config/autocard.py
@@ -11,16 +11,95 @@ import string
import glob
from string import letters
from string import digits
+from xml.dom.minidom import parseString
+import errno, fcntl
+import urllib2,urllib
+#from httplib import HTTP
+#from urlparse import urlparse
+#http://code.activestate.com/recipes/576891/
+
+
+
+
+
+class ApplicationLock:
+ '''
+ Ensures application is running only once, by using a lock file.
+
+ Ensure call to lock works. Then call unlock at program exit.
+
+ You cannot read or write to the lock file, but for some reason you can
+ remove it. Once removed, it is still in a locked state somehow. Another
+ application attempting to lock against the file will fail, even though
+ the directory listing does not show the file. Mysterious, but we are glad
+ the lock integrity is upheld in such a case.
+
+ Instance variables:
+ lockfile -- Full path to lock file
+ lockfd -- File descriptor of lock file exclusively locked
+ '''
+ def __init__ (self, lockfile):
+ self.lockfile = lockfile
+ self.lockfd = None
+
+ def lock (self):
+ '''
+ Creates and holds on to the lock file with exclusive access.
+ Returns True if lock successful, False if it is not, and raises
+ an exception upon operating system errors encountered creating the
+ lock file.
+ '''
+ try:
+ #
+ # Create or else open and trucate lock file, in read-write mode.
+ #
+ # A crashed app might not delete the lock file, so the
+ # os.O_CREAT | os.O_EXCL combination that guarantees
+ # atomic create isn't useful here. That is, we don't want to
+ # fail locking just because the file exists.
+ #
+ # Could use os.O_EXLOCK, but that doesn't exist yet in my Python
+ #
+ self.lockfd = os.open (self.lockfile,
+ os.O_TRUNC | os.O_CREAT | os.O_RDWR)
+
+ # Acquire exclusive lock on the file, but don't block waiting for it
+ fcntl.flock (self.lockfd, fcntl.LOCK_EX | fcntl.LOCK_NB)
+
+ # Writing to file is pointless, nobody can see it
+ os.write (self.lockfd, "My Lockfile")
+
+ return True
+ except (OSError, IOError), e:
+ # Lock cannot be acquired is okay, everything else reraise exception
+ if e.errno in (errno.EACCES, errno.EAGAIN):
+ return False
+ else:
+ raise
+
+ def unlock (self):
+ try:
+ # FIRST unlink file, then close it. This way, we avoid file
+ # existence in an unlocked state
+ os.unlink (self.lockfile)
+ # Just in case, let's not leak file descriptors
+ os.close (self.lockfd)
+ except (OSError, IOError), e:
+ # Ignore error destroying lock file. See class doc about how
+ # lockfile can be erased and everything still works normally.
+ pass
+#------- START OF TUNER CLASSES-----------
class v4l_tuners():
def __init__(self, device):
self.device = device
self.full_attribs = self.find_full_attribs()
self.full_udev_attribs = self.find_full_udev_attribs()
- self.description = self.find_description()
+ self.description,self.driver = self.find_description()
self.udev_props = self.parse_full_udev()
self.tuner_hash = self.find_tuner_hash()
self.udev_rule = self.create_udev_rule()
+ #self.staticdevice is set in create_udev_rule
def find_full_attribs(self):
cmd = 'v4l2-ctl -D -d' + self.device
@@ -46,7 +125,7 @@ class v4l_tuners():
if pos >=0:
splitline= line.split(':',1)
Businfo=splitline[1].strip()
- return Cardtype
+ return Cardtype,Driver
def parse_full_udev(self):
udev_props = []
@@ -97,6 +176,11 @@ class v4l_tuners():
return True
return False
+ def is_mpeg(self):
+ if self.driver in ["ivtv","saa7164[0]","saa7164"]:
+ return True
+ return False
+
def find_tuner_hash(self):
#tuner hash will be driven by card_type pci id and index
i=''
@@ -134,8 +218,72 @@ class v4l_tuners():
#DRIVERS=="ivtv", ATTR{name}=="ivtv? encoder MPG", KERNELS=="0000:08:09.0" SYMLINK+="myth/aivtv2"
line = ','.join(self.udev_props)
line += ' SYMLINK+="vstatic/%s"' %(self.get_tuner_hash())
+ self.staticdevice = "/dev/vstatic/%s" %(self.get_tuner_hash())
return self.escapeSpecialCharacters(line,'[]')
+ def card_mpeg_values(self):
+ values = {
+ 'CardType' : 'MPEG' ,
+ 'VideoDevice' : self.staticdevice,
+ 'Defaultinput' : 'Television',
+ 'HostName' : self.localhostname,
+ 'dvb_wait_for_seqstart' :'1',
+ 'signal_timeout' :'1000',
+ 'channel_timeout' :'12000',
+ 'diseqcid' :'NULL',
+ 'dvb_eitscan' :'1'
+ }
+
+ return values
+
+ def card_hdpvr_values(self):
+ values = {
+ 'CardType' : 'HDPVR' ,
+ 'VideoDevice' : self.staticdevice,
+ 'Defaultinput' : 'Television',
+ 'HostName' : self.localhostname,
+ 'dvb_wait_for_seqstart' :'1',
+ 'signal_timeout' :'1000',
+ 'channel_timeout' :'12000',
+ 'diseqcid' :'NULL',
+ 'dvb_eitscan' :'1'
+ }
+ return values
+
+ def do_insert(self,values):
+ try:
+ header = { 'User-Agent' : "autocard" }
+ url="http://127.0.0.1:6544/Capture/AddCaptureCard/"
+ data = urllib.urlencode(values)
+ req = urllib2.Request(url, data, header)
+ self.response = urllib2.urlopen(req)
+ except:
+ print " **Insert of %s failed" %self.staticdevice
+
+ def insert_myth(self,myth_tuner_list):
+ #check if tuner is already in the db
+ if self.staticdevice in myth_tuner_list:
+ print " *%s %s already in mythdb" %(self.get_card_type(),self.staticdevice)
+ else:
+ #determine values to use based on card type
+ print " Inserting %s" %self.staticdevice
+ if self.is_hdpvr() == True:
+ values = self.card_hdpvr_values()
+ self.do_insert(values)
+ elif self.is_mpeg() == True:
+ values = self.card_mpeg_values()
+ self.do_insert(values)
+ else:
+ print " Unknown V4l type, not adding to myth database"
+ return
+
+ def set_hostname(self,hostname):
+ self.localhostname = hostname
+
+ def set_tuner_index(self,index):
+ #only used by dvb, but here to be complete
+ self.tuner_index = index
+
def get_dev_node(self):
return self.device
@@ -148,6 +296,8 @@ class v4l_tuners():
def get_card_type(self):
if self.is_hdpvr() == True :
rc = "v4l_hdpvr"
+ elif self.is_mpeg() == True:
+ rc = "v4l_mpeg"
else:
rc = "v4l"
return rc
@@ -164,18 +314,61 @@ class v4l_tuners():
def get_udev_rule(self):
return self.udev_rule
-#-----
+ def get_static_device(self):
+ return self.staticdevice
+#-----
class hdhr_tuners():
def __init__(self, device):
self.device = device
self.description = self.find_description()
+ self.staticdevice = device
def find_description(self):
- command = '/usr/bin/hdhomerun_config %s get /sys/model' %self.device
+ command = '/usr/bin/hdhomerun_config %s get /sys/hwmodel' %self.device
results=os.popen(command,'r')
return results.readline().strip()
+ def insert_myth(self,hdhr_list):
+ if self.device in hdhr_list:
+ print " *hdhr %s already in mythtdb" %self.device
+ else:
+ print " Inserting HDHR %s" %self.device
+ self.do_insert()
+ pass
+
+ def do_insert(self):
+ try:
+ header = { 'User-Agent' : "autocard" }
+ url="http://127.0.0.1:6544/Capture/AddCaptureCard/"
+ values = self.card_hdhr_values()
+ data = urllib.urlencode(values)
+ req = urllib2.Request(url, data, header)
+ self.response = urllib2.urlopen(req)
+ except:
+ print " **Insert of %s failed" %self.device
+
+ def card_hdhr_values(self):
+ values = {
+ 'CardType' : 'HDHOMERUN' ,
+ 'VideoDevice' : self.device,
+ 'Defaultinput' : 'Television',
+ 'HostName' : self.localhostname,
+ 'dvb_wait_for_seqstart' :'1',
+ 'signal_timeout' :'1000',
+ 'channel_timeout' :'3000',
+ 'diseqcid' :'NULL',
+ 'dvb_eitscan' :'1'
+ }
+ return values
+
+ def set_hostname(self,hostname):
+ self.localhostname = hostname
+
+ def set_tuner_index(self,index):
+ #only used by dvb, but here to be complete
+ self.tuner_index = index
+
def get_dev_node(self):
return self.device
@@ -187,17 +380,26 @@ class hdhr_tuners():
def get_udev_rule(self):
return
-#----------
+
+ def get_tuner_hash(self):
+ return self.device
+
+ def get_static_device(self):
+ return self.staticdevice
+#-----
class dvb_tuners():
def __init__(self, device):
self.device = device
+ self.tuner_index = 1
self.dvb_number = self.find_dvb_number()
self.description = self.find_description()
self.full_udev_attribs = self.find_full_udev_attribs()
self.udev_props = self.parse_full_udev()
self.tuner_hash = self.find_tuner_hash()
self.udev_rule = self.create_udev_rule()
+ #self.staticdevice is set in create_udev_rule
+
def find_description(self):
@@ -259,37 +461,26 @@ class dvb_tuners():
else:
new_udev_props.append(item)
udev_props = new_udev_props
-
-
return udev_props
-
def find_tuner_hash(self):
#tuner hash will be driven by card_type pci id and index
i=''
k=''
tuner_hash=''
card_type = self.get_card_type()
- if card_type == "v4l_hdpvr":
- for index, item in enumerate(self.udev_props):
- if item.startswith("ATTRS{serial}=="):
- hex_serial=item.split("==")[1].strip('''"''')
- serial = int(hex_serial, 16)
- tuner_hash="hdpvr_%s" %serial
-
- else:
- for index, item in enumerate(self.udev_props):
- if item.startswith("KERNELS=="):
- k=item.split("==")[1].strip('''"''')
- k=k.replace(":", "_")
- k=k.replace("0", "")
- k=k.replace(".", "")
- if item.startswith("ATTR{index}=="):
- i=item.split("==")[1].strip('''"''')
+ for index, item in enumerate(self.udev_props):
+ if item.startswith("KERNELS=="):
+ k=item.split("==")[1].strip('''"''')
+ k=k.replace(":", "_")
+ k=k.replace("0", "")
+ k=k.replace(".", "")
- tuner_hash="%s%s%s" %(card_type,k,i)
+ if item.startswith("ATTR{index}=="):
+ i=item.split("==")[1].strip('''"''')
+ tuner_hash="%s%s%s" %(card_type,k,i)
return tuner_hash
def escapeSpecialCharacters ( self, text, characters ):
@@ -298,11 +489,52 @@ class dvb_tuners():
return text
def create_udev_rule(self):
- #ACTION=="add",KERNEL=="dvb?.frontend?",SUBSYSTEM=="dvb",SUBSYSTEMS=="pci",DRIVERS=="saa7164",KERNELS=="0000:05:00.0",RUN+="/tmp/udev_link.sh dvb_5 $env{DEVNAME}"
line = ','.join(self.udev_props)
line += ' RUN+="/usr/MythVantage/bin/udev_link.sh %s $env{DEVNAME} "' %(self.get_tuner_hash())
+ self.staticdevice = "/dev/dvb/adapter_static_%s_%s/frontend0" %(self.get_tuner_hash(),self.tuner_index)
return self.escapeSpecialCharacters(line,'[]')
+ def insert_myth(self,myth_tuner_list):
+ if self.staticdevice in myth_tuner_list:
+ print " *dvb %s already in mythtdb" %self.staticdevice
+ else:
+ print " Inserting DVB Tuner %s" %self.staticdevice
+ self.do_insert()
+ pass
+
+ def do_insert(self):
+ try:
+ header = { 'User-Agent' : "autocard" }
+ url="http://127.0.0.1:6544/Capture/AddCaptureCard/"
+ values = self.card_dvb_values()
+ data = urllib.urlencode(values)
+ req = urllib2.Request(url, data, header)
+ self.response = urllib2.urlopen(req)
+ except:
+ print " **Insert of %s failed" %self.staticdevice
+
+ def card_dvb_values(self):
+ values = {
+ 'CardType' : 'DVB' ,
+ 'VideoDevice' : self.staticdevice,
+ 'Defaultinput' : 'Television',
+ 'HostName' : self.localhostname,
+ 'dvb_wait_for_seqstart' :'1',
+ 'signal_timeout' :'1000',
+ 'channel_timeout' :'12000',
+ 'diseqcid' :'NULL',
+ 'dvb_eitscan' :'1'
+ }
+ return values
+
+ def set_tuner_index(self,index):
+ self.tuner_index = index
+ self.tuner_hash = self.find_tuner_hash()
+ self.udev_rule = self.create_udev_rule()
+
+ def set_hostname(self,hostname):
+ self.localhostname = hostname
+
def get_dev_node(self):
return self.device
@@ -320,9 +552,32 @@ class dvb_tuners():
def get_udev_rule(self):
return self.udev_rule
-#------------
-
+ def get_static_device(self):
+ return self.staticdevice
+
+#------------------END TUNER CLASSES-----------------------
+
+#------------------START OF TUNER GATHERING-----------------
+def find_hdhr_tuner(hdhrdevice):
+ htuner_list=[]
+ command="/usr/bin/hdhomerun_config %s get /tuner%s/status"
+ #loop over 4 possible tuners
+ for i in range(4):
+ c=command %(hdhrdevice,i)
+ results=os.popen(c,'r')
+ lines=results.readlines()
+ try:
+ #if the first line starts with error, assume it's not a tuner and
+ #there are no more tuners for this device.
+ if lines[0].strip().startswith("ERROR"):
+ break
+ else:
+ t="%s-%s" %(hdhrdevice,i)
+ htuner_list.append(t)
+ except:
+ pass
+ return htuner_list
def gather_hdhr(tuner_list):
command="/usr/bin/hdhomerun_config --discover"
@@ -333,8 +588,10 @@ def gather_hdhr(tuner_list):
print "HDHOMERUN not detected"
else:
for line in lines:
- hdrdevice=line.strip().split()[2]
- tuner_list.append(hdhr_tuners(hdrdevice))
+ hdhrdevice=line.strip().split()[2]
+ tuners = find_hdhr_tuner(hdhrdevice)
+ for t in tuners:
+ tuner_list.append(hdhr_tuners(t))
except:
print "Error finding HDHOMERUN"
return tuner_list
@@ -360,7 +617,6 @@ def gather_v4l(tuner_list):
print "no v4l cards found"
return tuner_list
-
def gather_dvb(tuner_list):
try:
filelist = os.listdir('/dev/dvb/')
@@ -376,7 +632,7 @@ def gather_dvb(tuner_list):
except:
print "no dvb cards found"
return tuner_list
-
+#------------------END OF TUNER GATHERING-----------------
def gather_tuners():
@@ -385,8 +641,17 @@ def gather_tuners():
tuner_list = gather_v4l(tuner_list)
tuner_list = gather_dvb(tuner_list)
#tuner_list = gather_ceton(tuner_list)
+ #set the number of times we have seen a specific tuner_hash
+ #This will be used by dvb when tuner_hashs conflict
+ tuner_count = {}
+ for i in tuner_list:
+ th = i.get_tuner_hash()
+ if th in tuner_count:
+ tuner_count[th] += 1
+ else:
+ tuner_count[th] = 1
+ i.set_tuner_index(tuner_count[th])
- #for i in tuner_list:
#if i.get_card_type() == "hdhr":
#pass
#print "hdhr : %s " %(i.get_dev_node())
@@ -429,6 +694,16 @@ def gather_tuners():
#print i
return tuner_list
+def trigger_udev():
+ print "Reloading udev rules"
+ command = '/usr/bin/udevadm control --reload'
+ results=os.popen(command,'r')
+
+ print "Triggering udev events"
+ command = '/usr/bin/udevadm trigger'
+ results=os.popen(command,'r')
+
+
def write_udev_file(rule_list):
udevfile = '/etc/udev/rules.d/99-mv-persistent-video.rules'
@@ -443,6 +718,7 @@ def write_udev_file(rule_list):
f.close()
except:
print "Error creating %s" %udevfile
+ trigger_udev()
def write_udev_map(tuner_list):
udevfile = '/etc/udev/mv-persistent-video.description'
@@ -455,21 +731,27 @@ def write_udev_map(tuner_list):
for i in tuner_list:
if i.get_card_type() == "hdhr":
pass
- line="hdhr:%s:%s" %(i.get_description(),i.get_dev_node())
+ line="hdhr:%s:%s" %(i.get_description(),i.get_static_device())
+ f.write(line)
+ f.write("\n")
+ elif i.get_card_type() == "v4l_mpeg":
+ pass
+ line="V4L_mpeg:%s: %s " %(i.get_description(),i.get_static_device())
f.write(line)
f.write("\n")
elif i.get_card_type() == "v4l":
pass
- line="V4L:%s:/dev/vstatic/%s " %(i.get_description(),i.get_tuner_hash())
+ line="V4L:%s:%s " %(i.get_description(),i.get_static_device())
f.write(line)
f.write("\n")
elif i.get_card_type() == "v4l_hdpvr":
pass
- line="hdpvr:%s:/dev/vstatic/%s " %(i.get_description(),i.get_tuner_hash())
+ #line="hdpvr:%s:/dev/vstatic/%s " %(i.get_description(),i.get_tuner_hash())
+ line="hdpvr:%s: %s " %(i.get_description(),i.get_static_device())
f.write(line)
f.write("\n")
elif i.get_card_type() == "dvb":
- line="dvb:%s:/dev/dvb/adapter_static_%s " %(i.get_description(),i.get_tuner_hash())
+ line="dvb:%s: %s " %(i.get_description(),i.get_static_device())
f.write(line)
f.write("\n")
elif i.get_card_type() == "ceton":
@@ -485,26 +767,157 @@ def write_udev_map(tuner_list):
print "Error creating %s" %udevfile
f.close()
+def checkURL(url):
+ try:
+ connection = urllib2.urlopen(url,None,3)
+ code=connection.getcode()
+ connection.close()
+ if code == 200:
+ rc=0
+ #except urllib2.HTTPError, e:
+ except:
+ rc=1
+ return rc
+def getURL(url):
+ dom = None
+ try:
+ connection = urllib2.urlopen(url,None,3)
+ data = connection.read()
+ connection.close()
+ dom = parseString(data)
+ #except urllib2.HTTPError, e:
+ except:
+ pass
+ return dom
+
+def find_hdhr_in_use():
+ hdhr_list = []
+ url='http://127.0.0.1:6544/Capture/GetCaptureCardList?CardType=HDHOMERUN'
+ data = getURL(url)
+
+ if data:
+ xmlTags = data.getElementsByTagName('VideoDevice')
+ for i in xmlTags:
+ xmlTag=i.toxml()
+ xmlData=xmlTag.replace('<VideoDevice>','').replace('</VideoDevice>','')
+ hdhr_list.append(xmlData)
+ return hdhr_list
+
+def find_in_use_card_list():
+ in_use_tuner_list=[]
+ url='http://127.0.0.1:6544/Capture/GetCaptureCardList?HostName=%s' %localhostname
+ data = getURL(url)
+
+ if data:
+ xmlTags = data.getElementsByTagName('VideoDevice')
+ for i in xmlTags:
+ xmlTag=i.toxml()
+ xmlData=xmlTag.replace('<VideoDevice>','').replace('</VideoDevice>','')
+ in_use_tuner_list.append(xmlData)
+ return in_use_tuner_list
+
+def usuage():
+ help='''
+ Autocard.py is a program that will take the guess work out of setting up tuner/capture cards.
+ There are 4 options:
+ help : This help screen
+ print: Will find and printout any detected capture cards, including network based tuners like the hdhomerun_config
+ udev : This option creates a set of static device nodes for the local capture cards.
+ Rules are based on pci/usb path so moving the card into a different expansion slot will nullify the udev rule
+ HDPVR devices use the serial number as the primary key for the udev rule_list
+
+ insertdb : This option will insert any detected cards into the MythTV database using the static device generated by udev.
+ This option will also generate udev rules. Tuners that are already defined will not be readded.
+
+ all : The same as using print udev insertdb
+
+
+ EX:
+ autocard.py print
+ autocard.py insertdb
+ '''
+ print help
def main(argv):
- tuner_list = gather_tuners()
- rule_list = []
+ listcards = False
+ udev = False
+ insertdb = False
- for i in tuner_list:
- rule_list.append(i.get_udev_rule())
+ if argv==[] or "help" in argv:
+ usuage()
+ sys.exit(0)
- write_udev_file(rule_list)
- write_udev_map(tuner_list)
+ if "print" in argv:
+ listcards = True
+ if "udev" in argv:
+ udev = True
+ if "insertdb" in argv:
+ insertdb = True
+ udev = True
+ if "all" in argv:
+ udev = True
+ insertdb = True
+ listcards = True
+ tuner_list = gather_tuners()
+ rule_list = []
+ for i in tuner_list:
+ #setting the hostname for each tuner
+ i.set_hostname(localhostname)
+ rule_list.append(i.get_udev_rule())
+ if listcards == True:
+ print i.get_card_type()
+ print "----------------"
+ print "\t" , i.get_description()
+ print "\t" , i.get_static_device()
-if __name__ == "__main__":
- main(sys.argv[1:])
+ print("Writing out tuner map")
+ write_udev_map(tuner_list)
+
+ if udev == True:
+ print("Writing out udev rules")
+ write_udev_file(rule_list)
+
+ if insertdb == True:
+ be_ready = False
+ i = 0
+ while i < 10 or be_ready :
+ if checkURL('http://127.0.0.1:6544') == 0:
+ be_ready = True
+ break
+ i = i + 1
+ print "Waiting for MythTV backend connection: %s/10" %i
+
+ time.sleep(5)
+
+ if be_ready == True :
+ #find all HDHR
+ in_use_hdhr_list = find_hdhr_in_use()
+ #find other cards local
+ in_use_local_card_list = find_in_use_card_list()
+ print "Adding cards to mythtv database"
+ for i in tuner_list:
+ if i.get_card_type() == "hdhr":
+ i.insert_myth(in_use_hdhr_list)
+ else:
+ i.insert_myth(in_use_local_card_list)
+
+if __name__ == "__main__":
+ localhostname = socket.gethostname()
+ applock = ApplicationLock ('/var/run/autocard.lock')
+ if (applock.lock ()):
+ #print ("Obtained lock")
+ main(sys.argv[1:])
+ #print ("Unlocking")
+ applock.unlock ()
+ else:
+ print ("Unable to obtain lock, exiting")