Author: duncan
Date: Sun Mar 16 17:24:48 2008
New Revision: 10535
Log:
[ 1915730 ] Allow DVBStreamer live pause to use a remote streamer
Patch from Adam Charrett applied
Modified:
branches/rel-1-7/freevo/ChangeLog
branches/rel-1-7/freevo/src/tv/plugins/dvbstreamer/comms.py
branches/rel-1-7/freevo/src/tv/plugins/dvbstreamer/live_pause.py
branches/rel-1-7/freevo/src/tv/plugins/dvbstreamer/manager.py
branches/rel-1/freevo/ChangeLog
branches/rel-1/freevo/src/tv/plugins/dvbstreamer/comms.py
branches/rel-1/freevo/src/tv/plugins/dvbstreamer/live_pause.py
branches/rel-1/freevo/src/tv/plugins/dvbstreamer/manager.py
Modified: branches/rel-1-7/freevo/ChangeLog
==============================================================================
--- branches/rel-1-7/freevo/ChangeLog (original)
+++ branches/rel-1-7/freevo/ChangeLog Sun Mar 16 17:24:48 2008
@@ -16,11 +16,13 @@
== Release 1.7.7 (2008-03-23) ==
--------------------------------
+ * New atlantice skin (F#1907139)
* New DVD to disk back-up plug-in (F#1892278)
* New PDA control with feedback client and upd plug-in (F#1890855)
* New placement support when using xrandr (F#1869969)
* Updated cdbackup plug-in to add the year from cddb (F#1907065)
* Updated cd_burn plug-in to support play lists (F#1901175)
+ * Updated dvbstreamer to allow the live pause to use a remote server
(F#1915730)
* Updated dvdbackup to allow customized menus (F#1890499)
* Updated playlist to process "#EXTINF" comments in m3u files (F#1890203)
* Updated Russian translation (B#1889826)
Modified: branches/rel-1-7/freevo/src/tv/plugins/dvbstreamer/comms.py
==============================================================================
--- branches/rel-1-7/freevo/src/tv/plugins/dvbstreamer/comms.py (original)
+++ branches/rel-1-7/freevo/src/tv/plugins/dvbstreamer/comms.py Sun Mar 16
17:24:48 2008
@@ -30,32 +30,50 @@
#
# ----------------------------------------------------------------------- */
from socket import *
+import re
PRIMARY_SERVICE_FILTER='<Primary>'
+lssfs_re = re.compile(' (.*?) : (.*?) \((.*)\)')
class Controller:
- def __init__(self, host, adapter, username=None, password=None):
+ """
+ High level connection to a DVBStreamer daemon, uses a transitory connection
+ to process commands/requests.
+ """
+ def __init__(self, host, adapter, username=None, password=None,
transitory=True):
self.host = host
self.adapter = adapter
self.username = username
self.password = password
+ self.transitory = transitory
+ self.connection = None
+ self.my_ip = None
def execute_command(self, command, authenticate=False):
"""
Send a command to the dvbstreamer instance to execute,
first authorising if required.
"""
- ctrlcon = ControlConnection(self.host, self.adapter)
- ctrlcon.open()
- if authenticate:
- (ec, em, lines) = ctrlcon.send_command('auth %s %s' %
(self.username, self.password))
- if ec != 0:
- raise RuntimeError, 'failed to authenticate'
- result = ctrlcon.send_command(command)
- ctrlcon.close()
+ if self.transitory or self.connection is None:
+ ctrlcon = ControlConnection(self.host, self.adapter)
+ ctrlcon.open()
+ else:
+ ctrlcon = self.connection
+ try:
+ if authenticate:
+ (ec, em, lines) = ctrlcon.send_command('auth %s %s' %
(self.username, self.password))
+ if ec != 0:
+ raise RuntimeError, 'failed to authenticate'
+ result = ctrlcon.send_command(command)
+ self.my_ip = ctrlcon.my_ip
+ finally:
+ if self.transitory:
+ ctrlcon.close()
+ else:
+ self.connection = ctrlcon
return result
- def select_service(self, service):
+ def set_current_service(self, service):
"""
Select the primary service.
"""
@@ -63,6 +81,23 @@
if errcode != 0:
raise RuntimeError, errmsg
+
+ def get_current_service(self):
+ """
+ Retrieve the current primary service.
+ Returns a tuple containing service name and multiplex.
+ """
+ (errcode, errmsg, msg) = self.execute_command('current')
+ if errcode != 0:
+ raise RuntimeError, errmsg
+
+ m = re.match('Current Service : "(.+?)" \(.+?\) Multiplex: (.+)',
msg[0])
+ if m:
+ return (m.group(1), m.group(2))
+
+ return None
+
+
def set_servicefilter_mrl(self, service_filter, mrl):
"""
Set the MRL (Media Resource Locator) for a given service filter.
@@ -71,6 +106,22 @@
if errcode != 0:
raise RuntimeError, errmsg
+ def get_servicefilters(self):
+ """
+ Get a dictionary containing tuples of service and mrl for each
+ service filter.
+ """
+ (errcode, errmsg, msg) = self.execute_command('lssfs')
+ if errcode != 0:
+ raise RuntimeError, errmsg
+ result = {}
+ for line in msg:
+ m = lssfs_re.match(line)
+ if m:
+ result[m.group(1)] = (m.group(2), m.group(3))
+ return result
+
+
def get_services(self, mux=''):
"""
Get the list of services available on all or a specific multiplex.
@@ -140,38 +191,64 @@
def get_frontend_status(self):
"""
Get the frontend status of the set dvbstreamer instance.
+ Returns a tuple contain locked state, ber, signal strength %, snr % and
+ uncorrected block count.
"""
(errcode, errmsg, status) = self.execute_command('festatus')
if errcode != 0:
return None
- locked = status[0].find('Lock,') != -1
+ locked = status[0].find('Lock') != -1
line = status[1]
- equalsindex = line.find('= ') + 2
- spaceindex = line.find(' ', equalsindex)
- ber = int(line[equalsindex:spaceindex])
-
- equalsindex = line.find('= ',spaceindex) + 2
- spaceindex = line.find(' ', equalsindex)
- signal = int(line[equalsindex:spaceindex])
+ m = re.match('Signal Strength = ([0-9]+)% SNR = ([0-9]+)% BER =
([0-9a-f]+?) Uncorrected Blocks = ([0-9a-f]+)', line)
+ if m:
+ signal = int(m.group(1))
+ snr = int(m.group(2))
+ ber = int(m.group(3),16)
+ ucb = int(m.group(4),16)
+ else:
+ # Should we raise an exception?
+ signal = 0
+ snr = 0
+ ber = 0
+ ucb = 0
+
+ return (locked, ber, signal, snr, ucb)
- equalsindex = line.find('= ',spaceindex) + 2
- snr = int(line[equalsindex:])
+ def get_variable(self, var):
+ (errcode, errmsg, value) = self.execute_command('get ' + var)
+ if errcode != 0:
+ return None
+ return value
- return (locked, ber, signal, snr)
class ControlConnection:
+ """
+ Class implementing a connection to a DVBStreamer daemon.
+ """
def __init__(self, host, adapter):
+ """
+ Create a connection object to communicate with a DVBStreamer daemon.
+ """
self.host = host
self.adapter = adapter
self.opened = False
+ self.version = None
+ self.welcome_message = None
+ self.my_ip = None
def open(self):
+ """
+ Open the connection to the DVBStreamer daemon.
+ """
if self.opened:
return
self.socket = socket(AF_INET,SOCK_STREAM)
self.socket.connect((self.host, self.adapter + 54197))
+
+ self.my_ip = self.socket.getsockname()[0]
+
self.socket_file = self.socket.makefile('r+')
self.opened = True
(error_code, error_message, lines) = self.read_response()
@@ -185,12 +262,18 @@
return self.opened
def close(self):
+ """
+ Close the connection to the DVBStreamer daemon.
+ """
if self.opened:
self.socket_file.close()
self.socket.close()
self.opened = False
def send_command(self, command):
+ """
+ Send a command to the connection DVBStreamer daemon.
+ """
if not self.opened:
raise RuntimeError, 'not connected'
@@ -200,6 +283,11 @@
return self.read_response()
def read_response(self):
+ """
+ Read a response from the DVBStreamer deamon after a command has been
+ sent.
+ Returns a tuple of error code, error message and response lines.
+ """
more_lines = True
lines = []
error_code = -1
Modified: branches/rel-1-7/freevo/src/tv/plugins/dvbstreamer/live_pause.py
==============================================================================
--- branches/rel-1-7/freevo/src/tv/plugins/dvbstreamer/live_pause.py
(original)
+++ branches/rel-1-7/freevo/src/tv/plugins/dvbstreamer/live_pause.py Sun Mar
16 17:24:48 2008
@@ -331,7 +331,12 @@
if self.adapter_in_use != adapter:
self.adapter_in_use = adapter
try:
- self.manager.enable_udp_output(self.adapter_in_use)
+ if adapter.find(':') != -1:
+ my_ip = self.manager.controllers[adapter].my_ip
+ else:
+ my_ip = 'localhost'
+
+ self.manager.enable_udp_output(self.adapter_in_use, my_ip,
1234)
except:
_debug_('Failed to enable output! ' + traceback.format_exc())
@@ -533,7 +538,7 @@
def __osd_write(self, text):
if self.app:
- self.app.write('OSDWriteText$%s\n' % text)
+ self.app.write('OSDWriteText$ %s\n' % text)
def __draw_state_screen(self):
osd_obj = osd.get_singleton()
Modified: branches/rel-1-7/freevo/src/tv/plugins/dvbstreamer/manager.py
==============================================================================
--- branches/rel-1-7/freevo/src/tv/plugins/dvbstreamer/manager.py
(original)
+++ branches/rel-1-7/freevo/src/tv/plugins/dvbstreamer/manager.py Sun Mar
16 17:24:48 2008
@@ -39,16 +39,14 @@
def __init__(self, username, password):
self.username = username
self.password = password
- self.destip = 'localhost'
- self.destport = 1234
self.controllers = {}
- def get_udp_mrl(self):
+ def get_udp_mrl(self, ip_address, port):
"""
Get the mrl to use for dvbstreamer and xine.
"""
- return 'udp://%s:%d' %(self.destip, self.destport)
+ return 'udp://%s:%d' %(ip_address, port)
def get_file_mrl(self, filename):
@@ -58,11 +56,11 @@
return 'file://%s' % filename
- def enable_udp_output(self, adapter):
+ def enable_udp_output(self, adapter, ip_address, port):
"""
Enable UDP output to localhost:1234
"""
- self.set_mrl(adapter, self.get_udp_mrl())
+ self.set_mrl(adapter, self.get_udp_mrl(ip_address,port))
def enable_file_output(self, adapter, filename):
@@ -75,7 +73,7 @@
"""
Disable output from the specified dvbstreamer instance.
"""
- _debug_('Disabling output on adapter %d' % adapter)
+ _debug_('Disabling output on adapter %s' % adapter)
self.set_mrl(adapter, 'null://')
@@ -83,9 +81,9 @@
"""
Select a channel on the specified dvbstreamer instance.
"""
- _debug_('Selecting channel %s on adapter %d'%(channel, adapter))
+ _debug_('Selecting channel %s on adapter %s'%(channel, adapter))
controller = self.get_controller(adapter)
- controller.select_service(channel)
+ controller.set_current_service(channel)
def set_mrl(self, adapter, mrl):
@@ -102,6 +100,12 @@
"""
if adapter in self.controllers:
return self.controllers[adapter]
- controller = comms.Controller('localhost', adapter, self.username,
self.password)
+ if adapter.find(':') != -1:
+ ip_address,dvb_adapter = adapter.split(':',2)
+ dvb_adapter = int(dvb_adapter)
+ else:
+ ip_address = 'localhost'
+ dvb_adapter = int(adapter)
+ controller = comms.Controller(ip_address, dvb_adapter, self.username,
self.password)
self.controllers[adapter] = controller
return controller
Modified: branches/rel-1/freevo/ChangeLog
==============================================================================
--- branches/rel-1/freevo/ChangeLog (original)
+++ branches/rel-1/freevo/ChangeLog Sun Mar 16 17:24:48 2008
@@ -21,11 +21,13 @@
== Release 1.7.7 (2008-03-23) ==
--------------------------------
+ * New atlantice skin (F#1907139)
* New DVD to disk back-up plug-in (F#1892278)
* New PDA control with feedback client and upd plug-in (F#1890855)
* New placement support when using xrandr (F#1869969)
* Updated cdbackup plug-in to add the year from cddb (F#1907065)
* Updated cd_burn plug-in to support play lists (F#1901175)
+ * Updated dvbstreamer to allow the live pause to use a remote server
(F#1915730)
* Updated dvdbackup to allow customized menus (F#1890499)
* Updated playlist to process "#EXTINF" comments in m3u files (F#1890203)
* Updated Russian translation (B#1889826)
Modified: branches/rel-1/freevo/src/tv/plugins/dvbstreamer/comms.py
==============================================================================
--- branches/rel-1/freevo/src/tv/plugins/dvbstreamer/comms.py (original)
+++ branches/rel-1/freevo/src/tv/plugins/dvbstreamer/comms.py Sun Mar 16
17:24:48 2008
@@ -30,32 +30,50 @@
#
# ----------------------------------------------------------------------- */
from socket import *
+import re
PRIMARY_SERVICE_FILTER='<Primary>'
+lssfs_re = re.compile(' (.*?) : (.*?) \((.*)\)')
class Controller:
- def __init__(self, host, adapter, username=None, password=None):
+ """
+ High level connection to a DVBStreamer daemon, uses a transitory connection
+ to process commands/requests.
+ """
+ def __init__(self, host, adapter, username=None, password=None,
transitory=True):
self.host = host
self.adapter = adapter
self.username = username
self.password = password
+ self.transitory = transitory
+ self.connection = None
+ self.my_ip = None
def execute_command(self, command, authenticate=False):
"""
Send a command to the dvbstreamer instance to execute,
first authorising if required.
"""
- ctrlcon = ControlConnection(self.host, self.adapter)
- ctrlcon.open()
- if authenticate:
- (ec, em, lines) = ctrlcon.send_command('auth %s %s' %
(self.username, self.password))
- if ec != 0:
- raise RuntimeError, 'failed to authenticate'
- result = ctrlcon.send_command(command)
- ctrlcon.close()
+ if self.transitory or self.connection is None:
+ ctrlcon = ControlConnection(self.host, self.adapter)
+ ctrlcon.open()
+ else:
+ ctrlcon = self.connection
+ try:
+ if authenticate:
+ (ec, em, lines) = ctrlcon.send_command('auth %s %s' %
(self.username, self.password))
+ if ec != 0:
+ raise RuntimeError, 'failed to authenticate'
+ result = ctrlcon.send_command(command)
+ self.my_ip = ctrlcon.my_ip
+ finally:
+ if self.transitory:
+ ctrlcon.close()
+ else:
+ self.connection = ctrlcon
return result
- def select_service(self, service):
+ def set_current_service(self, service):
"""
Select the primary service.
"""
@@ -63,6 +81,23 @@
if errcode != 0:
raise RuntimeError, errmsg
+
+ def get_current_service(self):
+ """
+ Retrieve the current primary service.
+ Returns a tuple containing service name and multiplex.
+ """
+ (errcode, errmsg, msg) = self.execute_command('current')
+ if errcode != 0:
+ raise RuntimeError, errmsg
+
+ m = re.match('Current Service : "(.+?)" \(.+?\) Multiplex: (.+)',
msg[0])
+ if m:
+ return (m.group(1), m.group(2))
+
+ return None
+
+
def set_servicefilter_mrl(self, service_filter, mrl):
"""
Set the MRL (Media Resource Locator) for a given service filter.
@@ -71,6 +106,22 @@
if errcode != 0:
raise RuntimeError, errmsg
+ def get_servicefilters(self):
+ """
+ Get a dictionary containing tuples of service and mrl for each
+ service filter.
+ """
+ (errcode, errmsg, msg) = self.execute_command('lssfs')
+ if errcode != 0:
+ raise RuntimeError, errmsg
+ result = {}
+ for line in msg:
+ m = lssfs_re.match(line)
+ if m:
+ result[m.group(1)] = (m.group(2), m.group(3))
+ return result
+
+
def get_services(self, mux=''):
"""
Get the list of services available on all or a specific multiplex.
@@ -140,38 +191,64 @@
def get_frontend_status(self):
"""
Get the frontend status of the set dvbstreamer instance.
+ Returns a tuple contain locked state, ber, signal strength %, snr % and
+ uncorrected block count.
"""
(errcode, errmsg, status) = self.execute_command('festatus')
if errcode != 0:
return None
- locked = status[0].find('Lock,') != -1
+ locked = status[0].find('Lock') != -1
line = status[1]
- equalsindex = line.find('= ') + 2
- spaceindex = line.find(' ', equalsindex)
- ber = int(line[equalsindex:spaceindex])
-
- equalsindex = line.find('= ',spaceindex) + 2
- spaceindex = line.find(' ', equalsindex)
- signal = int(line[equalsindex:spaceindex])
+ m = re.match('Signal Strength = ([0-9]+)% SNR = ([0-9]+)% BER =
([0-9a-f]+?) Uncorrected Blocks = ([0-9a-f]+)', line)
+ if m:
+ signal = int(m.group(1))
+ snr = int(m.group(2))
+ ber = int(m.group(3),16)
+ ucb = int(m.group(4),16)
+ else:
+ # Should we raise an exception?
+ signal = 0
+ snr = 0
+ ber = 0
+ ucb = 0
+
+ return (locked, ber, signal, snr, ucb)
- equalsindex = line.find('= ',spaceindex) + 2
- snr = int(line[equalsindex:])
+ def get_variable(self, var):
+ (errcode, errmsg, value) = self.execute_command('get ' + var)
+ if errcode != 0:
+ return None
+ return value
- return (locked, ber, signal, snr)
class ControlConnection:
+ """
+ Class implementing a connection to a DVBStreamer daemon.
+ """
def __init__(self, host, adapter):
+ """
+ Create a connection object to communicate with a DVBStreamer daemon.
+ """
self.host = host
self.adapter = adapter
self.opened = False
+ self.version = None
+ self.welcome_message = None
+ self.my_ip = None
def open(self):
+ """
+ Open the connection to the DVBStreamer daemon.
+ """
if self.opened:
return
self.socket = socket(AF_INET,SOCK_STREAM)
self.socket.connect((self.host, self.adapter + 54197))
+
+ self.my_ip = self.socket.getsockname()[0]
+
self.socket_file = self.socket.makefile('r+')
self.opened = True
(error_code, error_message, lines) = self.read_response()
@@ -185,12 +262,18 @@
return self.opened
def close(self):
+ """
+ Close the connection to the DVBStreamer daemon.
+ """
if self.opened:
self.socket_file.close()
self.socket.close()
self.opened = False
def send_command(self, command):
+ """
+ Send a command to the connection DVBStreamer daemon.
+ """
if not self.opened:
raise RuntimeError, 'not connected'
@@ -200,6 +283,11 @@
return self.read_response()
def read_response(self):
+ """
+ Read a response from the DVBStreamer deamon after a command has been
+ sent.
+ Returns a tuple of error code, error message and response lines.
+ """
more_lines = True
lines = []
error_code = -1
Modified: branches/rel-1/freevo/src/tv/plugins/dvbstreamer/live_pause.py
==============================================================================
--- branches/rel-1/freevo/src/tv/plugins/dvbstreamer/live_pause.py
(original)
+++ branches/rel-1/freevo/src/tv/plugins/dvbstreamer/live_pause.py Sun Mar
16 17:24:48 2008
@@ -331,7 +331,12 @@
if self.adapter_in_use != adapter:
self.adapter_in_use = adapter
try:
- self.manager.enable_udp_output(self.adapter_in_use)
+ if adapter.find(':') != -1:
+ my_ip = self.manager.controllers[adapter].my_ip
+ else:
+ my_ip = 'localhost'
+
+ self.manager.enable_udp_output(self.adapter_in_use, my_ip,
1234)
except:
_debug_('Failed to enable output! ' + traceback.format_exc())
@@ -533,7 +538,7 @@
def __osd_write(self, text):
if self.app:
- self.app.write('OSDWriteText$%s\n' % text)
+ self.app.write('OSDWriteText$ %s\n' % text)
def __draw_state_screen(self):
osd_obj = osd.get_singleton()
Modified: branches/rel-1/freevo/src/tv/plugins/dvbstreamer/manager.py
==============================================================================
--- branches/rel-1/freevo/src/tv/plugins/dvbstreamer/manager.py (original)
+++ branches/rel-1/freevo/src/tv/plugins/dvbstreamer/manager.py Sun Mar 16
17:24:48 2008
@@ -39,16 +39,14 @@
def __init__(self, username, password):
self.username = username
self.password = password
- self.destip = 'localhost'
- self.destport = 1234
self.controllers = {}
- def get_udp_mrl(self):
+ def get_udp_mrl(self, ip_address, port):
"""
Get the mrl to use for dvbstreamer and xine.
"""
- return 'udp://%s:%d' %(self.destip, self.destport)
+ return 'udp://%s:%d' %(ip_address, port)
def get_file_mrl(self, filename):
@@ -58,11 +56,11 @@
return 'file://%s' % filename
- def enable_udp_output(self, adapter):
+ def enable_udp_output(self, adapter, ip_address, port):
"""
Enable UDP output to localhost:1234
"""
- self.set_mrl(adapter, self.get_udp_mrl())
+ self.set_mrl(adapter, self.get_udp_mrl(ip_address,port))
def enable_file_output(self, adapter, filename):
@@ -75,7 +73,7 @@
"""
Disable output from the specified dvbstreamer instance.
"""
- _debug_('Disabling output on adapter %d' % adapter)
+ _debug_('Disabling output on adapter %s' % adapter)
self.set_mrl(adapter, 'null://')
@@ -83,9 +81,9 @@
"""
Select a channel on the specified dvbstreamer instance.
"""
- _debug_('Selecting channel %s on adapter %d'%(channel, adapter))
+ _debug_('Selecting channel %s on adapter %s'%(channel, adapter))
controller = self.get_controller(adapter)
- controller.select_service(channel)
+ controller.set_current_service(channel)
def set_mrl(self, adapter, mrl):
@@ -102,6 +100,12 @@
"""
if adapter in self.controllers:
return self.controllers[adapter]
- controller = comms.Controller('localhost', adapter, self.username,
self.password)
+ if adapter.find(':') != -1:
+ ip_address,dvb_adapter = adapter.split(':',2)
+ dvb_adapter = int(dvb_adapter)
+ else:
+ ip_address = 'localhost'
+ dvb_adapter = int(adapter)
+ controller = comms.Controller(ip_address, dvb_adapter, self.username,
self.password)
self.controllers[adapter] = controller
return controller
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Freevo-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog