Author: schwardt
Date: Mon Feb 19 21:19:25 2007
New Revision: 2501
Added:
trunk/WIP/record/test/dvbchannelconfreader.py
Modified:
trunk/WIP/record/test/tuner.py
Log:
add preliminary support for dvb conf parser
Added: trunk/WIP/record/test/dvbchannelconfreader.py
==============================================================================
--- (empty file)
+++ trunk/WIP/record/test/dvbchannelconfreader.py Mon Feb 19 21:19:25 2007
@@ -0,0 +1,382 @@
+#!/usr/bin/python
+# -*- coding: iso-8859-1 -*-
+# -----------------------------------------------------------------------------
+# dvbconfigreader.py - Read channels.conf
+# -----------------------------------------------------------------------------
+# $Id$
+#
+# -----------------------------------------------------------------------------
+# kaa-record - A recording module
+# Copyright (C) 2007 S�nke Schwardt, Dirk Meyer
+#
+# First Edition: S�nke Schwardt <[EMAIL PROTECTED]>
+# Maintainer: S�nke Schwardt <[EMAIL PROTECTED]>
+#
+# Please see the file doc/CREDITS for a complete list of authors.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MER-
+# CHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# -----------------------------------------------------------------------------
+
+# python imports
+import re
+import sys
+import types
+import logging
+import traceback
+
+# get logging object
+log = logging.getLogger('record')
+
+class DVBChannel:
+ # TODO / FIXME add missing compare function
+ map_hierarchy = { 'default': 'AUTO',
+ '999': 'AUTO',
+ '0': 'NONE',
+ '1': '1',
+ '2': '2',
+ '4': '4' }
+
+ map_bandwidth = { 'default': 'AUTO',
+ '999': 'AUTO',
+ '6': '6_MHZ',
+ '7': '7_MHZ',
+ '8': '8_MHZ' }
+
+ map_transmissionmode = { 'default': 'AUTO',
+ '999': 'AUTO',
+ '2': '2K',
+ '8': '8K' }
+
+ map_guardinterval = { 'default': 'AUTO',
+ '999': 'AUTO',
+ '4': '1/4',
+ '8': '1/8',
+ '16': '1/16',
+ '32': '1/32' }
+
+ map_modulation = { 'default': 'AUTO',
+ '999': 'AUTO',
+ '16': 'QAM_16',
+ '32': 'QAM_32',
+ '64': 'QAM_64',
+ '128': 'QAM_128',
+ '256': 'QAM_256' }
+
+ map_fec = { 'default': 'AUTO',
+ '999': 'AUTO',
+ '0': 'NONE',
+ '12': '1/2',
+ '23': '2/3',
+ '34': '3/4',
+ '45': '4/5',
+ '56': '5/6',
+ '67': '6/7',
+ '78': '7/8',
+ '89': '8/9' }
+
+ map_inversion = { 'default': 'AUTO',
+ '999': 'AUTO',
+ '0': 'OFF',
+ '1': 'ON' }
+
+
+
+ def __init__(self, line):
+ self.re_dvbt =
re.compile('^.*?:\d+:([ICDMBTGY]\d+)+:T:\d+:\d+:\d+(=\w+)?(,\d+(=\w+)?)?(;\d+(=\w+)?(,\d+(=\w+)?)?)*:\d+:\d+:\d+:\d+:\d+:\d+')
+ self.re_dvbc =
re.compile('^.*?:\d+:([ICDMBTGY]\d+)+:C:\d+:\d+:\d+(=\w+)?(,\d+(=\w+)?)?(;\d+(=\w+)?(,\d+(=\w+)?)?)*:\d+:\d+:\d+:\d+:\d+:\d+')
+ self.re_dvbs =
re.compile('^.*?:\d+:[HV]([ICDMBTGY]\d+)*:S\d+(\.\d+)?[EeWw]:\d+:\d+:\d+(=\w+)?(,\d+(=\w+)?)?(;\d+(=\w+)?(,\d+(=\w+)?)?)*:\d+:\d+:\d+:\d+:\d+:\d+',
re.IGNORECASE)
+
+
+ self.config = { }
+ self.line = line.strip('\n')
+ self.cfgtype = None
+
+ if len(self.line) == 0:
+ self.cfgtype = 'COMMENT'
+ elif self.line[0] == '#':
+ self.cfgtype = 'COMMENT'
+ elif self.re_dvbt.match(line):
+ self.cfgtype = 'DVB-T'
+ elif self.re_dvbc.match(line):
+ self.cfgtype = 'DVB-C'
+ elif self.re_dvbs.match(line):
+ self.cfgtype = 'DVB-S'
+
+ if self.cfgtype == None:
+ log.error('failed to parse config line:\n%s' % self.line)
+ return None
+
+ if self.cfgtype == 'COMMENT':
+ return None
+
+ cells = self.line.split(':')
+
+ if ';' in cells[0]:
+ self.config['name'] = cells[0].split(';')[0]
+ self.config['bouquet'] = cells[0].split(';')[1]
+ else:
+ self.config['name'] = cells[0]
+ self.config['bouquet'] = ''
+
+ self.config['name'] = self.config['name'].replace('|', ':')
+ self.config['bouquet'] = self.config['bouquet'].replace('|', ':')
+ self.config['frequency'] = int(cells[1])
+
+ # get params
+ re_params = re.compile('([ICDMBTGYHV]\d*)',re.IGNORECASE)
+ for param in re_params.findall(cells[2].upper()):
+ if param[0]=='I':
+ self.config['inversion'] = param[1:]
+ if param[0]=='C':
+ self.config['code-rate-high-prio'] = param[1:]
+ if param[0]=='D':
+ self.config['code-rate-low-prio'] = param[1:]
+ if param[0]=='M':
+ self.config['modulation'] = param[1:]
+ if param[0]=='B':
+ self.config['bandwidth'] = param[1:]
+ if param[0]=='T':
+ self.config['transmission-mode'] = param[1:]
+ if param[0]=='G':
+ self.config['guard-interval'] = param[1:]
+ if param[0]=='Y':
+ self.config['hierarchy'] = param[1:]
+ if param[0]=='H':
+ self.config['horizontal_polarization'] = param[1:]
+ if param[0]=='V':
+ self.config['vertical_polarization'] = param[1:]
+ if param[0]=='R':
+ self.config['circular_polarization_right'] = param[1:]
+ if param[0]=='L':
+ self.config['circular_polarization_left'] = param[1:]
+
+ self.config['type'] = cells[3][0]
+ if len(cells[3]) > 1:
+ self.config['source'] = cells[3][1:]
+
+ self.config['symbolrate'] = cells[4]
+ self.config['vpid'] = cells[5]
+
+ self.config['apids'] = []
+ for i in cells[6].split(';'):
+ lst = []
+ for t in i.split(','):
+ if '=' in t:
+ lst.append( tuple(t.split('=')) )
+ else:
+ lst.append( ( t, '' ) )
+ self.config['apids'].extend(lst)
+
+ self.config['tpid'] = cells[7]
+ self.config['caid'] = cells[8]
+ self.config['sid'] = cells[9]
+ self.config['nid'] = cells[10]
+ self.config['tid'] = cells[11]
+ self.config['rid'] = cells[12]
+
+ if self.config['frequency'] > 0:
+ while self.config['frequency'] < 1000000:
+ self.config['frequency'] *= 1000
+
+ self.map_config( 'hierarchy', self.map_hierarchy )
+ self.map_config( 'bandwidth', self.map_bandwidth )
+ self.map_config( 'transmission-mode', self.map_transmissionmode )
+ self.map_config( 'guard-interval', self.map_guardinterval )
+ self.map_config( 'modulation', self.map_modulation )
+ self.map_config( 'code-rate-low-prio', self.map_fec )
+ self.map_config( 'code-rate-high-prio', self.map_fec )
+ self.map_config( 'inversion', self.map_inversion )
+
+
+ def map_config(self, key, keydict):
+ if not self.config.has_key( key ):
+ return
+ if self.config[ key ] in keydict.keys():
+ self.config[ key ] = keydict[ self.config[ key ] ]
+ else:
+ log.warn('failed to parse %s (%s) - using default %s',
+ key, self.config[key], keydict['default'])
+ self.config[key] = keydict[ 'default' ]
+
+
+ def __repr__(self):
+ return '<kaa.record.DVBChannel %s>' % self.config['name']
+
+
+ def __str__(self):
+ return '%s channel: %-25s [%-25s] (vpid=%s apids=%s)' \
+ % (self.cfgtype, self.config['name'], self.config['bouquet'],
+ self.config['vpid'], self.config['apids'])
+
+
+
+class DVBMultiplex:
+ def __init__(self, name, frequency):
+ self.name = name
+ self.frequency = frequency
+ self.chanlist = []
+
+
+ # TODO FIXME add missing compare functions
+ # TODO FIXME add __contains__, __getitem__, __setitem__
+
+ def add(self, chan):
+ if (chan.config['frequency'] != self.frequency):
+ return False
+ # TODO / FIXME check if channel is already present in multiplex
+ self.chanlist.append(chan)
+ return True
+
+
+ def remove(self, channame):
+ # TODO FIXME return value returns True if channel with channame
+ # was found and deleted otherwise False
+ self.chanlist = filter(lambda chan: chan.config['name'] == channame,
+ self.chanlist)
+ return True
+
+
+ def keys(self):
+ """ return names of known channels within this multiplex """
+ result = []
+ for chan in self.chanlist:
+ result.append(chan.config['name'])
+ return result
+
+
+ def __getitem__(self, key):
+ """
+ returns channel specified by integer (position) or by name.
+ if specified by name the first matching one is chosen.
+ """
+ if type(key) is types.IntType:
+ return self.chanlist[key]
+
+ if type(key) is types.StringType:
+ for chan in self.chanlist:
+ if chan.config['name'] == key:
+ return chan
+ raise KeyError()
+ raise TypeError()
+
+
+ def __repr__(self):
+ return '<kaa.record.DVBMultiplex: %s' % self.name
+
+ def __str__(self):
+ s = 'Multiplex: %-25s (f=%s)\n' % (self.name, self.frequency)
+ for chan in self.chanlist:
+ s += str(chan) + '\n'
+ return s + '\n'
+
+
+
+class DVBChannelConfReader:
+ def __init__(self, cfgname):
+ self.cfgtype = None
+ self.multiplexlist = [ ]
+
+ # read config
+ self.f = open(cfgname)
+ for line in self.f:
+ channel = DVBChannel(line)
+
+ if self.cfgtype == None:
+ self.cfgtype = channel.cfgtype
+ elif self.cfgtype is not channel.cfgtype:
+ if channel.cfgtype != 'COMMENT':
+ log.warn('Oops: mixed mode config file!')
+ log.warn('Drop: %s' % line.strip())
+ continue
+
+ for mplex in self.multiplexlist:
+ added = mplex.add( channel )
+ if added:
+ log.info('added channel %s to mplex %s',
+ channel.config['name'], mplex.name)
+ break
+ else:
+ mplex = DVBMultiplex( channel.config['frequency'],
+ channel.config['frequency'], )
+ mplex.add( channel )
+ self.multiplexlist.append(mplex)
+ log.info('added channel %s to new mplex %s',
+ channel.config['name'], mplex.name)
+
+
+ # TODO FIXME add missing __getitem__, __contains__
+ # get channel config by
+ # channelconfreader[MULTIPLEXNAME][CHANNELNAME] or
+ # channelconfreader[MULTIPLEXINDEX][CHANNELINDEX]
+
+ def keys(self):
+ """ return names of known multiplexes """
+ result = []
+ for mplex in self.multiplexlist:
+ result.append(mplex.name)
+ return result
+
+
+ def __getitem__(self, key):
+ """
+ returns multiplex specified by integer (position) or by name.
+ if specified by name the first matching one is chosen.
+ """
+ if type(key) is types.IntType:
+ return self.multiplexlist[key]
+
+ if type(key) is types.StringType:
+ for mplex in self.multiplexlist:
+ if mplex.name == key:
+ return mplex
+ raise KeyError()
+ raise TypeError()
+
+
+ def get_channel(self, key):
+ for mplex in self.multiplexlist:
+ if key in mplex.keys():
+ return mplex[key]
+ return None
+
+ def __str__(self):
+ s = 'MULTIPLEX LIST:\n'
+ s += '===============\n'
+ for mplex in self.multiplexlist:
+ s += str(mplex)
+ return s
+
+
+if __name__ == '__main__':
+ log = logging.getLogger()
+ for l in log.handlers:
+ log.removeHandler(l)
+ formatter = logging.Formatter('%(levelname)s %(module)s'+ \
+ '(%(lineno)s): %(message)s')
+ handler = logging.StreamHandler()
+ handler.setFormatter(formatter)
+ log.addHandler(handler)
+
+ logging.getLogger().setLevel(logging.DEBUG)
+ ccr = DVBChannelConfReader('test/dvbs.conf')
+ print ccr
+ print '---------------'
+ print 'find channel "n-tv":'
+ print ccr.get_channel('n-tv')
+ print '---------------'
+ print 'find channel "n-tv":'
+ print ccr.get_channel('n-tv').config
+
Modified: trunk/WIP/record/test/tuner.py
==============================================================================
--- trunk/WIP/record/test/tuner.py (original)
+++ trunk/WIP/record/test/tuner.py Mon Feb 19 21:19:25 2007
@@ -4,6 +4,7 @@
import gst
import sys
import time
+import dvbchannelconfreader
# import kaa.notifier and set mainloop to glib
import kaa.notifier
@@ -49,16 +50,31 @@
def tune(self, channel):
- # tuning to ZDF (hardcoded values! change them!)
- self._tuner.set_property("frequency", 562000000)
- self._tuner.set_property("inversion", 2)
- self._tuner.set_property("bandwidth", 0)
- self._tuner.set_property("code-rate-high-prio", 2)
- self._tuner.set_property("code-rate-low-prio", 0)
- self._tuner.set_property("constellation", 1)
- self._tuner.set_property("transmission-mode", 1)
- self._tuner.set_property("guard-interval", 2)
- self._tuner.set_property("hierarchy", 0)
+ if not channel:
+ print 'no channel given - FIXME'
+ sys.exit()
+
+ frontendtype = self._tuner.get_property('frontendtype')
+ if frontendtype == 0:
+ # TODO FIXME broken --> fixme
+ DVBS
+ elif frontendtype == 1:
+ # TODO FIXME broken --> fixme
+ DVBC
+ elif frontendtype == 2:
+ # TODO FIXME I have to fix parser and tuner! - they should use the
same keywords
+ channel.config['constellation'] = channel.config['modulation']
+
+ for cfgitem in [ 'frequency', 'inversion', 'bandwidth',
'code-rate-high-prio', 'code-rate-low-prio', 'constellation',
'transmission-mode', 'guard-interval', 'hierarchy' ]:
+ print '%s ==> %s' % (cfgitem, channel.config[ cfgitem ])
+ self._tuner.set_property( cfgitem, channel.config[ cfgitem ] )
+
+ elif frontendtype == 3:
+ # TODO FIXME broken --> fixme
+ ATSC
+ else:
+ print 'OH NO! Please fix this code!'
+
# tune to channel
self._tuner.emit("tune")
@@ -102,6 +118,17 @@
sink = mapping[pad.get_name()]
pad.link(sink.get_pad('sink'))
+if len(sys.argv) < 3:
+ print 'syntax: %s <channels.conf> <channelname>' % sys.argv[0]
+ sys.exit()
+
+ccr = dvbchannelconfreader.DVBChannelConfReader( sys.argv[1] )
+chan = ccr.get_channel( sys.argv[2] )
+if not chan:
+ print 'cannot find channel', sys.argv[2]
+ sys.exit()
+
+print chan.config
# create gstreamer pipline
pipeline = gst.Pipeline()
@@ -114,10 +141,13 @@
pipeline.add(c)
pipeline.set_state(gst.STATE_PLAYING)
+print 'using channel config of %s' % sys.argv[1]
+print 'and searching channel %s' % sys.argv[2]
+
# now the testing starts by tuning
-c.tune(None)
+c.tune(chan)
def create_recording(filename, *pids):
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Freevo-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog