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