Author: dmeyer
Date: Fri Nov 23 17:24:54 2007
New Revision: 2907

Log:
first draft of kaa.record3

Added:
   trunk/WIP/record3/
   trunk/WIP/record3/setup.py
   trunk/WIP/record3/src/
   trunk/WIP/record3/src/__init__.py
   trunk/WIP/record3/src/const.py
   trunk/WIP/record3/src/core.py
   trunk/WIP/record3/src/device.py
   trunk/WIP/record3/src/dvb.py
   trunk/WIP/record3/src/stream.py
   trunk/WIP/record3/test/
   trunk/WIP/record3/test/record.py

Added: trunk/WIP/record3/setup.py
==============================================================================
--- (empty file)
+++ trunk/WIP/record3/setup.py  Fri Nov 23 17:24:54 2007
@@ -0,0 +1,13 @@
+# python imports
+import sys
+
+try:
+    # kaa base imports
+    from kaa.distribution.core import Extension, setup
+except ImportError:
+    print 'kaa.base not installed'
+    sys.exit(1)
+
+setup(module      = 'record3',
+      version     = '0.1'
+)

Added: trunk/WIP/record3/src/__init__.py
==============================================================================
--- (empty file)
+++ trunk/WIP/record3/src/__init__.py   Fri Nov 23 17:24:54 2007
@@ -0,0 +1,3 @@
+from core import get_device
+from stream import Recording
+

Added: trunk/WIP/record3/src/const.py
==============================================================================
--- (empty file)
+++ trunk/WIP/record3/src/const.py      Fri Nov 23 17:24:54 2007
@@ -0,0 +1,3 @@
+TYPE_DVB_S = 'DVB-S'
+TYPE_DVB_C = 'DVB-C'
+TYPE_DVB_T = 'DVB-T'

Added: trunk/WIP/record3/src/core.py
==============================================================================
--- (empty file)
+++ trunk/WIP/record3/src/core.py       Fri Nov 23 17:24:54 2007
@@ -0,0 +1,30 @@
+import os
+import kaa.ioctl as ioctl
+
+from dvb import DVB_T
+
+_devices = None
+
+def get_devices():
+    global _devices
+    if _devices is not None:
+        return _devices
+    _devices = {}
+    for adapter in range(5):
+        frontend = '/dev/dvb/adapter%s/frontend0' % adapter
+        if not os.path.exists(frontend):
+            continue
+        # read frontend0 for aditional information
+        INFO_ST = '128s10i'
+        val = ioctl.pack( INFO_ST, "", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 )
+        devfd = os.open(frontend, os.O_TRUNC)
+        r = ioctl.ioctl(devfd, ioctl.IOR('o', 61, INFO_ST), val)
+        os.close(devfd)
+        val = ioctl.unpack( INFO_ST, r )
+        name = val[0].strip()
+        if val[1] == 2:
+            _devices['dvb%s' % adapter] = DVB_T(adapter)
+    return _devices
+
+def get_device(device):
+    return get_devices().get(device)

Added: trunk/WIP/record3/src/device.py
==============================================================================
--- (empty file)
+++ trunk/WIP/record3/src/device.py     Fri Nov 23 17:24:54 2007
@@ -0,0 +1,32 @@
+class Device(object):
+
+    def __init__(self):
+        self.channels = {}
+
+    def get_channel(self, name):
+        return self.channels.get(name)
+
+    def add_channel(self, name, tuning_data, access_data):
+        self.channels[name] = tuning_data, access_data
+
+    def get_channels(self):
+        result = {}
+        for name, (tuning_data, access_data) in self.channels.items():
+            if not str(tuning_data) in result:
+                result[str(tuning_data)] = []
+            result[str(tuning_data)].append(name)
+        return result.values()
+
+    def read_channels_conf(self, filename):
+        for line in open(filename).readlines():
+            self.add_channel(*self._read_channels_conf_line(line.strip()))
+
+    def add(self, channel, sink):
+        raise NotImplementedError
+
+    def remove(self, channel, sink):
+        raise NotImplementedError
+
+    def _read_channels_conf_line(self, line):
+        raise NotImplementedError
+

Added: trunk/WIP/record3/src/dvb.py
==============================================================================
--- (empty file)
+++ trunk/WIP/record3/src/dvb.py        Fri Nov 23 17:24:54 2007
@@ -0,0 +1,155 @@
+import pygst
+pygst.require('0.10')
+import gst
+import gobject
+
+import const
+import device
+
+class DVB(device.Device):
+
+    def __init__(self, adapter):
+        device.Device.__init__(self)
+        # create pipeline
+        self._pipeline = gst.Pipeline()
+        self._pipeline.get_bus().add_watch(self._bus_event)
+        self._dvbbin = gst.element_factory_make("dvbbasebin")
+        self._dvbbin.set_property('adapter', adapter)
+        self._dvbbin.connect("pad-added", self._pad_added)
+        self._dvbbin.connect("pad-removed", self._pad_removed)
+        self._pipeline.add(self._dvbbin)
+        self._streams = {}
+        self._tuning_data = None
+
+
+    def add(self, channel, sink):
+        # get tuning data and tune to specific frequency
+        tuning_data, access_data = self.get_channel(channel)
+        if self._tuning_data != tuning_data:
+            # FIXME: does not work when already tuned!
+            print '>>> tune to', tuning_data
+            for var, value in tuning_data.items():
+                self._dvbbin.set_property(var, value)
+            self._tuning_data = tuning_data
+        sid = str(access_data.get('sid'))
+
+        # start pipeline
+        if not self._streams:
+            self._pipeline.set_state(gst.STATE_PLAYING);
+
+        # create pipeline (tee) for channel if needed
+        if not sid in self._streams:
+            print 'create sid pipeline'
+            tee = gst.element_factory_make('tee')
+            tee.set_state(gst.STATE_PLAYING)
+            self._pipeline.add(tee)
+            self._streams[sid] = ( tee, [] )
+            self._dvbbin.set_property('program-numbers', 
':'.join(self._streams.keys()))
+
+        # add sink to sid pipeline
+        print 'start', sid, sink
+        sink.set_state(gst.STATE_PLAYING)
+        self._pipeline.add(sink)
+        tee, streams = self._streams[sid]
+        pad = tee.get_request_pad('src%d')
+        pad.link(sink.get_pad('sink'))
+        streams.append(sink)
+
+
+    def remove(self, channel, sink):
+        sid = str(self.get_channel(channel)[1].get('sid'))
+        pad = sink.get_pad('sink').get_peer()
+        tee, streams = self._streams[sid]
+        # remove sink from pipeline and tee
+        print 'remove', sink
+        streams.remove(sink)
+        sink.set_state(gst.STATE_NULL)
+        self._pipeline.remove(sink)
+        pad.unlink(sink.get_pad('sink'))
+        tee.remove_pad(pad)
+        if len(streams):
+            return
+        print 'last sink, remove sid', sid
+        del self._streams[sid]
+        self._dvbbin.set_property('program-numbers', 
':'.join(self._streams.keys()))
+        self._pipeline.remove(tee)
+        tee.set_state(gst.STATE_NULL)
+        if len(self._streams.keys()):
+            return
+        print 'last channel, stop dvbbin'
+        self._dvbbin.set_state(gst.STATE_NULL)
+
+
+    def _bus_event(self, bus, message):
+        t = message.type
+        if t == gst.MESSAGE_ERROR:
+            err, debug = message.parse_error()
+            print "Error: %s" % err, debug
+            return True
+        if t == gst.MESSAGE_STATE_CHANGED:
+            print message
+            if message.parse_state_changed()[1] == gst.STATE_PLAYING:
+                print '%s PLAYING' % message.src
+            if message.parse_state_changed()[1] == gst.STATE_NULL:
+                print '%s STOPPED' % message.src
+            return True
+        print message
+        return True
+
+
+    def _pad_added(self, bin, pad):
+        sid = pad.get_name().split('_')[-1]
+        print self._streams
+        print 'PAD:', pad
+        print 'PADNAME:',pad.get_name()
+        print 'PADCAPS:',pad.get_caps()
+        print 'SINK:', self._streams[sid]
+        pad.link(self._streams[sid][0].get_pad('sink'))
+        return True
+
+
+    def _pad_removed(self, bin, pad):
+        print 'STOP', pad, pad.get_peer()
+
+
+class DVB_S(DVB):
+    type = const.TYPE_DVB_S
+
+    def _read_channels_conf_line(self, line):
+        name, frequency, polarity, unknown, symbol_rate, \
+              pid1, pid2, sid = line.strip().split(':')
+        tuning_data = {
+            'frequency': int(frequency) * 1000,
+            'polarity': polarity,
+            'symbol_rate': int(symbol_rate)
+        }
+        return name, tuning_data, dict(sid=sid)
+
+
+class DVB_T(DVB):
+    type = const.TYPE_DVB_T
+
+    _BANDWIDTH = [ '8', '7', '6', 'AUTO' ]
+    _GUARD = [ '32', '16', '8', '4', 'AUTO' ]
+    _CODE = [ '1_2', '2_3', '3_4', '4_5', '5_6', '6_7', '7_8', '8_9', 'AUTO' ]
+    _QUAM = [ 'QPSK', '16', '32', '64', '128', '256', 'AUTO' ]
+    _TRANS = [ '2K', '8K', 'AUTO' ]
+    _HIERARCHY = [ 'NONE', '1', '2', '4', 'AUTO' ]
+    _INVERSION = [ 'OFF', 'ON', 'AUTO' ]
+
+    def _read_channels_conf_line(self, line):
+        name, frequency, inversion, bandwidth, code_rate_lq, code_rate_hq, \
+              quam, transmission_mode, guard, hierarchy, \
+              pid1, pid2, sid = line.strip().split(':')
+        tuning_data = {
+            'frequency': int(frequency),
+            'bandwidth': self._BANDWIDTH.index(bandwidth.split('_')[1]),
+            'guard': self._GUARD.index(guard.split('_')[-1]),
+            'code-rate-lp': self._CODE.index(code_rate_lq[4:]),
+            'code-rate-hp': self._CODE.index(code_rate_hq[4:]),\
+            'modulation': self._QUAM.index(quam[4:]),
+            'trans-mode': self._TRANS.index(transmission_mode.split('_')[-1]),
+            'hierarchy': self._HIERARCHY.index(hierarchy.split('_')[-1]),
+            'inversion': self._INVERSION.index(inversion.split('_')[-1])
+        }
+        return name, tuning_data, dict(sid=sid)

Added: trunk/WIP/record3/src/stream.py
==============================================================================
--- (empty file)
+++ trunk/WIP/record3/src/stream.py     Fri Nov 23 17:24:54 2007
@@ -0,0 +1,26 @@
+import pygst
+pygst.require('0.10')
+import gst
+
+class Stream(object):
+
+    def __init__(self, device, channel, sink):
+        self._device = device
+        self._channel = channel
+        self._sink = sink
+
+    def start(self):
+        self._device.add(self._channel, self._sink)
+
+    def stop(self):
+        self._device.remove(self._channel, self._sink)
+        self._device = None
+        self._sink = None
+
+
+class Recording(Stream):
+
+    def __init__(self, device, channel, filename):
+        sink = gst.element_factory_make('filesink')
+        sink.set_property('location', filename)
+        super(Recording,self).__init__(device, channel, sink)

Added: trunk/WIP/record3/test/record.py
==============================================================================
--- (empty file)
+++ trunk/WIP/record3/test/record.py    Fri Nov 23 17:24:54 2007
@@ -0,0 +1,21 @@
+import kaa.notifier
+import kaa.record3
+
+kaa.notifier.init('gtk')
+
+dvb = kaa.record3.get_device('dvb0')
+dvb.read_channels_conf('/home/dmeyer/channels.conf')
+print dvb.get_channels()
+
+r1 = kaa.record3.Recording(dvb, 'Das Erste', 'ARD.ts')
+r2 = kaa.record3.Recording(dvb, 'Das Erste', 'ARD2.ts')
+
+kaa.notifier.OneShotTimer(r1.start).start(0)
+kaa.notifier.OneShotTimer(r2.start).start(2)
+# kaa.notifier.OneShotTimer(r3.start, dvb).start(10)
+kaa.notifier.OneShotTimer(r1.stop).start(5)
+kaa.notifier.OneShotTimer(r2.stop).start(7)
+# kaa.notifier.OneShotTimer(r3.stop).start(20)
+kaa.notifier.OneShotTimer(kaa.notifier.shutdown).start(15)
+
+kaa.notifier.loop()

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Freevo-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog

Reply via email to