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

Reply via email to