[rhythmbox] Update Coherence UPNP plugin
- From: Bastien Nocera <hadess src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [rhythmbox] Update Coherence UPNP plugin
- Date: Tue, 8 Sep 2009 10:13:59 +0000 (UTC)
commit 82672e4aff9b710d382eb405d0ebaaa9272b8e50
Author: Bastien Nocera <hadess hadess net>
Date: Tue Sep 8 11:13:14 2009 +0100
Update Coherence UPNP plugin
from the upstream SVN
plugins/coherence/upnp_coherence/MediaPlayer.py | 131 ++++++++++---
plugins/coherence/upnp_coherence/MediaStore.py | 91 +++++++--
plugins/coherence/upnp_coherence/__init__.py | 249 ++++++++++++++++++-----
3 files changed, 369 insertions(+), 102 deletions(-)
---
diff --git a/plugins/coherence/upnp_coherence/MediaPlayer.py b/plugins/coherence/upnp_coherence/MediaPlayer.py
index 0207421..d90b5f4 100644
--- a/plugins/coherence/upnp_coherence/MediaPlayer.py
+++ b/plugins/coherence/upnp_coherence/MediaPlayer.py
@@ -3,14 +3,17 @@
# Copyright 2008, Frank Scholz <coherence beebits net>
+import os.path
import urllib
+from twisted.python import failure
+
import rhythmdb
from coherence.upnp.core.soap_service import errorCode
from coherence.upnp.core import DIDLLite
-import coherence.extern.louie as louie
+import louie
from coherence.extern.simple_plugin import Plugin
@@ -27,17 +30,22 @@ class RhythmboxPlayer(log.Loggable):
implements = ['MediaRenderer']
vendor_value_defaults = {'RenderingControl': {'A_ARG_TYPE_Channel':'Master'},
- 'AVTransport': {'A_ARG_TYPE_SeekMode':('ABS_TIME','REL_TIME')}}
+ 'AVTransport': {'A_ARG_TYPE_SeekMode':('ABS_TIME','REL_TIME','TRACK_NR')}}
vendor_range_defaults = {'RenderingControl': {'Volume': {'maximum':100}}}
def __init__(self, device, **kwargs):
self.warning("__init__ RhythmboxPlayer %r", kwargs)
self.shell = kwargs['shell']
self.server = device
+ self.rb_mediaserver = kwargs['rb_mediaserver']
self.player = None
+ self.entry = None
self.metadata = None
- self.name = "Rhythmbox on %s" % self.server.coherence.hostname
+ try:
+ self.name = kwargs['name']
+ except KeyError:
+ self.name = "Rhythmbox on %s" % self.server.coherence.hostname
self.player = self.shell.get_player()
louie.send('Coherence.UPnP.Backend.init_completed', None, backend=self)
@@ -55,11 +63,13 @@ class RhythmboxPlayer(log.Loggable):
def volume_changed(self, player, parameter):
self.volume = self.player.props.volume
+ self.info('volume_changed to %r', self.volume)
if self.volume > 0:
rcs_id = self.server.connection_manager_server.lookup_rcs_id(self.current_connection_id)
self.server.rendering_control_server.set_variable(rcs_id, 'Volume', self.volume*100)
def playing_song_changed(self, player, entry):
+ self.info("playing_song_changed %r", entry)
if self.server != None:
connection_id = self.server.connection_manager_server.lookup_avt_id(self.current_connection_id)
if entry == None:
@@ -69,7 +79,7 @@ class RhythmboxPlayer(log.Loggable):
self.metadata = None
self.duration = None
else:
- self.id = self.shell.props.db.entry_get (entry, rhythmdb.PROP_ENTRY_ID)
+ id = self.shell.props.db.entry_get (entry, rhythmdb.PROP_ENTRY_ID)
bitrate = self.shell.props.db.entry_get(entry, rhythmdb.PROP_BITRATE) * 1024 / 8
# Duration is in HH:MM:SS format
seconds = self.shell.props.db.entry_get(entry, rhythmdb.PROP_DURATION)
@@ -86,41 +96,62 @@ class RhythmboxPlayer(log.Loggable):
size = self.shell.props.db.entry_get(entry, rhythmdb.PROP_FILE_SIZE)
# create item
- item = DIDLLite.MusicTrack(self.id + TRACK_COUNT)
+ item = DIDLLite.MusicTrack(id + TRACK_COUNT,'101')
item.album = self.shell.props.db.entry_get(entry, rhythmdb.PROP_ALBUM)
item.artist = self.shell.props.db.entry_get(entry, rhythmdb.PROP_ARTIST)
item.genre = self.shell.props.db.entry_get(entry, rhythmdb.PROP_GENRE)
item.originalTrackNumber = str(self.shell.props.db.entry_get (entry, rhythmdb.PROP_TRACK_NUMBER))
item.title = self.shell.props.db.entry_get(entry, rhythmdb.PROP_TITLE) # much nicer if it was entry.title
- item.res = []
+ cover = self.shell.props.db.entry_request_extra_metadata(entry, "rb:coverArt-uri")
+ if cover != None:
+ _,ext = os.path.splitext(cover)
+ item.albumArtURI = ''.join((self.server.coherence.urlbase+str(self.rb_mediaserver.uuid)[5:]+'/'+ str(int(id) + TRACK_COUNT),'?cover',ext))
- uri = self.shell.props.db.entry_get(entry, rhythmdb.PROP_LOCATION)
- if uri.startswith("file://"):
- location = unicode(urllib.unquote(uri[len("file://"):]))
+ item.res = []
- # add a fake resource for the moment
- res = DIDLLite.Resource(location, 'http-get:*:%s:*' % mimetype)
- if size > 0:
- res.size = size
- if self.duration > 0:
- res.duration = self.duration
- if bitrate > 0:
- res.bitrate = str(bitrate)
- item.res.append(res)
+ location = self.shell.props.db.entry_get(entry, rhythmdb.PROP_LOCATION)
+ if location.startswith("file://"):
+ location = unicode(urllib.unquote(location[len("file://"):]))
+
+ uri = ''.join((self.server.coherence.urlbase+str(self.rb_mediaserver.uuid)[5:]+'/'+ str(int(id) + TRACK_COUNT)))
+
+ res = DIDLLite.Resource(uri, 'http-get:*:%s:*' % mimetype)
+ if size > 0:
+ res.size = size
+ if self.duration > 0:
+ res.duration = self.duration
+ if bitrate > 0:
+ res.bitrate = str(bitrate)
+ item.res.append(res)
+
+ # add internal resource
+ res = DIDLLite.Resource('track-%d' % id, 'rhythmbox:%s:%s:*' % (self.server.coherence.hostname, mimetype))
+ if size > 0:
+ res.size = size
+ if self.duration > 0:
+ res.duration = str(self.duration)
+ if bitrate > 0:
+ res.bitrate = str(bitrate)
+ item.res.append(res)
elt = DIDLLite.DIDLElement()
elt.addItem(item)
self.metadata = elt.toString()
self.entry = entry
if self.server != None:
+ self.server.av_transport_server.set_variable(connection_id, 'CurrentTrackURI',uri)
+ self.server.av_transport_server.set_variable(connection_id, 'AVTransportURI',uri)
self.server.av_transport_server.set_variable(connection_id, 'AVTransportURIMetaData',self.metadata)
self.server.av_transport_server.set_variable(connection_id, 'CurrentTrackMetaData',self.metadata)
+ self.info("playing_song_changed %r", self.metadata)
if self.server != None:
+ self.server.av_transport_server.set_variable(connection_id, 'CurrentTransportActions','PLAY,STOP,PAUSE,SEEK,NEXT,PREVIOUS')
self.server.av_transport_server.set_variable(connection_id, 'RelativeTimePosition', '00:00:00')
self.server.av_transport_server.set_variable(connection_id, 'AbsoluteTimePosition', '00:00:00')
def playing_changed(self, player, state):
+ self.info("playing_changed", state)
if state is True:
transport_state = 'PLAYING'
else:
@@ -138,8 +169,10 @@ class RhythmboxPlayer(log.Loggable):
except:
duration = None
self.update_position(position,duration)
+ self.info("playing_changed %r %r ", position, duration)
def elapsed_changed(self, player, time):
+ self.info("elapsed_changed %r %r", player, time)
try:
duration = player.get_playing_song_duration()
except:
@@ -148,6 +181,8 @@ class RhythmboxPlayer(log.Loggable):
def update(self, state):
+ self.info("update %r", state)
+
if state in ('STOPPED','READY'):
transport_state = 'STOPPED'
if state == 'PLAYING':
@@ -165,9 +200,11 @@ class RhythmboxPlayer(log.Loggable):
def update_position(self, position,duration):
+ self.info("update_position %r %r", position,duration)
+
if self.server != None:
connection_id = self.server.connection_manager_server.lookup_avt_id(self.current_connection_id)
- self.server.av_transport_server.set_variable(connection_id, 'CurrentTrack', 0)
+ self.server.av_transport_server.set_variable(connection_id, 'CurrentTrack', 1)
if position is not None:
m,s = divmod( position, 60)
@@ -189,6 +226,7 @@ class RhythmboxPlayer(log.Loggable):
if self.duration is None:
if self.metadata is not None:
+ self.info("update_position %r", self.metadata)
elt = DIDLLite.DIDLElement.fromString(self.metadata)
for item in elt:
for res in item.findall('res'):
@@ -202,6 +240,7 @@ class RhythmboxPlayer(log.Loggable):
self.duration = duration
def load( self, uri, metadata):
+ self.info("player load %r %r", uri, metadata)
#self.shell.load_uri(uri,play=False)
self.duration = None
self.metadata = metadata
@@ -221,13 +260,16 @@ class RhythmboxPlayer(log.Loggable):
self.entry = self.shell.props.db.entry_lookup_by_id(int(uri[6:]))
else:
self.entry = self.shell.props.db.entry_lookup_by_location(uri)
+ self.info("check for entry %r %r %r", self.entry,item.server_uuid,uri)
if self.entry == None:
if item.server_uuid is not None:
entry_type = self.shell.props.db.entry_register_type("CoherenceUpnp:" + item.server_uuid)
self.entry = self.shell.props.db.entry_new(entry_type, uri)
+ self.info("create new entry %r", self.entry)
else:
entry_type = self.shell.props.db.entry_register_type("CoherencePlayer")
self.entry = self.shell.props.db.entry_new(entry_type, uri)
+ self.info("load and check for entry %r", self.entry)
duration = None
size = None
@@ -281,7 +323,7 @@ class RhythmboxPlayer(log.Loggable):
self.metadata = metadata
connection_id = self.server.connection_manager_server.lookup_avt_id(self.current_connection_id)
- self.server.av_transport_server.set_variable(connection_id, 'CurrentTransportActions','Play,Stop,Pause,Seek')
+ self.server.av_transport_server.set_variable(connection_id, 'CurrentTransportActions','PLAY,STOP,PAUSE,SEEK,NEXT,PREVIOUS')
self.server.av_transport_server.set_variable(connection_id, 'NumberOfTracks',1)
self.server.av_transport_server.set_variable(connection_id, 'CurrentTrackURI',uri)
self.server.av_transport_server.set_variable(connection_id, 'AVTransportURI',uri)
@@ -297,6 +339,8 @@ class RhythmboxPlayer(log.Loggable):
self.play()
def stop(self):
+ self.info("player stop")
+
self.player.stop()
self.playing = False
#self.server.av_transport_server.set_variable( \
@@ -304,8 +348,13 @@ class RhythmboxPlayer(log.Loggable):
# 'TransportState', 'STOPPED')
def play(self):
+ self.info("player play")
+
if self.playing == False:
- self.player.play_entry(self.entry)
+ if self.entry:
+ self.player.play_entry(self.entry)
+ else:
+ self.player.playpause()
self.playing = True
else:
self.player.playpause()
@@ -321,10 +370,10 @@ class RhythmboxPlayer(log.Loggable):
def seek(self, location, old_state):
"""
- @param location: simple number = time to seek to, in seconds
- +nL = relative seek forward n seconds
+ @param location: +nL = relative seek forward n seconds
-nL = relative seek backwards n seconds
"""
+ self.info("player seek %r", location)
self.player.seek(location)
self.server.av_transport_server.set_variable(0, 'TransportState', old_state)
@@ -347,9 +396,11 @@ class RhythmboxPlayer(log.Loggable):
def get_volume(self):
self.volume = self.player.get_volume()
+ self.info("get_volume %r", self.volume)
return self.volume * 100
def set_volume(self, volume):
+ self.info("set_volume %r", volume)
volume = int(volume)
if volume < 0:
volume=0
@@ -385,6 +436,16 @@ class RhythmboxPlayer(log.Loggable):
self.play()
return {}
+ def upnp_Previous(self, *args, **kwargs):
+ InstanceID = int(kwargs['InstanceID'])
+ self.player.do_previous()
+ return {}
+
+ def upnp_Next(self, *args, **kwargs):
+ InstanceID = int(kwargs['InstanceID'])
+ self.player.do_next()
+ return {}
+
def upnp_Pause(self, *args, **kwargs):
InstanceID = int(kwargs['InstanceID'])
self.pause()
@@ -400,11 +461,31 @@ class RhythmboxPlayer(log.Loggable):
Unit = kwargs['Unit']
Target = kwargs['Target']
if Unit in ['ABS_TIME','REL_TIME']:
- old_state = self.server.av_transport_server.get_variable(0, 'TransportState')
+ old_state = self.server.av_transport_server.get_variable('TransportState').value
self.server.av_transport_server.set_variable(0, 'TransportState', 'TRANSITIONING')
+
+ sign = 1
+ if Target[0] == '+':
+ Target = Target[1:]
+ if Target[0] == '-':
+ Target = Target[1:]
+ sign = -1
h,m,s = Target.split(':')
seconds = int(h)*3600 + int(m)*60 + int(s)
- self.seek(seconds, old_state)
+
+ if Unit == 'ABS_TIME':
+ position = self.player.get_playing_time()
+ self.seek(seconds-position, old_state)
+ elif Unit == 'REL_TIME':
+ self.seek(seconds*sign, old_state)
+ return {}
+
+ def upnp_Next(self,*args,**kwargs):
+ self.player.do_next()
+ return {}
+
+ def upnp_Previous(self,*args,**kwargs):
+ self.player.do_previous()
return {}
def upnp_SetAVTransportURI(self, *args, **kwargs):
diff --git a/plugins/coherence/upnp_coherence/MediaStore.py b/plugins/coherence/upnp_coherence/MediaStore.py
index 959fa49..0915f5d 100644
--- a/plugins/coherence/upnp_coherence/MediaStore.py
+++ b/plugins/coherence/upnp_coherence/MediaStore.py
@@ -4,9 +4,13 @@
# Copyright 2007, James Livingston <doclivingston gmail com>
# Copyright 2007, Frank Scholz <coherence beebits net>
+import os.path
import rhythmdb
-import coherence.extern.louie as louie
+import louie
import urllib
+
+from coherence import __version_info__
+
from coherence.upnp.core import DIDLLite
from coherence.backend import BackendItem, BackendStore
@@ -27,14 +31,14 @@ class Container(BackendItem):
logCategory = 'rb_media_store'
- def __init__(self, id, parent_id, name, children_callback=None):
+ def __init__(self, id, parent_id, name, children_callback=None,store=None,play_container=False):
self.id = id
self.parent_id = parent_id
self.name = name
self.mimetype = 'directory'
- self.item = DIDLLite.Container(id, parent_id,self.name)
+ self.store = store
+ self.play_container = play_container
self.update_id = 0
- self.item.childCount = 0
if children_callback != None:
self.children = children_callback
else:
@@ -42,7 +46,6 @@ class Container(BackendItem):
def add_child(self, child):
self.children.append(child)
- self.item.childCount += 1
def get_children(self,start=0,request_count=0):
if callable(self.children):
@@ -60,8 +63,13 @@ class Container(BackendItem):
return len(self.get_children())
def get_item(self, parent_id=None):
- self.item.childCount = self.get_child_count()
- return self.item
+ item = DIDLLite.Container(self.id,self.parent_id,self.name)
+ item.childCount = self.get_child_count()
+ if self.store and self.play_container == True:
+ if item.childCount > 0:
+ res = DIDLLite.PlayContainerResource(self.store.server.uuid,cid=self.get_id(),fid=str(TRACK_COUNT + int(self.get_children()[0].get_id())))
+ item.res.append(res)
+ return item
def get_name(self):
return self.name
@@ -115,6 +123,11 @@ class Album(BackendItem):
def get_item(self, parent_id = AUDIO_ALBUM_CONTAINER_ID):
item = DIDLLite.MusicAlbum(self.id, parent_id, self.title)
+
+ if __version_info__ >= (0,6,4):
+ if self.get_child_count() > 0:
+ res = DIDLLite.PlayContainerResource(self.store.server.uuid,cid=self.get_id(),fid=str(TRACK_COUNT+int(self.get_children()[0].get_id())))
+ item.res.append(res)
return item
def get_id(self):
@@ -139,11 +152,22 @@ class Artist(BackendItem):
query = self.store.db.query_new()
self.store.db.query_append(query,[rhythmdb.QUERY_PROP_EQUALS, rhythmdb.PROP_TYPE, self.store.db.entry_type_get_by_name('song')],
[rhythmdb.QUERY_PROP_EQUALS, rhythmdb.PROP_ARTIST, self.name])
- qm = self.store.db.query_model_new(query)
- self.store.db.do_full_query_async_parsed(qm, query)
+ self.tracks_per_artist_query = self.store.db.query_model_new(query)
+ self.store.db.do_full_query_async_parsed(self.tracks_per_artist_query, query)
self.albums_per_artist_query = self.store.db.property_model_new(rhythmdb.PROP_ALBUM)
- self.albums_per_artist_query.props.query_model = qm
+ self.albums_per_artist_query.props.query_model = self.tracks_per_artist_query
+
+ def get_artist_all_tracks(self,id):
+ children = []
+
+ def collate (model, path, iter):
+ id = model.get(iter, 0)[0]
+ print id
+ children.append(Track(self.store,id,self.id))
+
+ self.tracks_per_artist_query.foreach(collate)
+ return children
def get_children(self,start=0,request_count=0):
children = []
@@ -161,6 +185,16 @@ class Artist(BackendItem):
self.albums_per_artist_query.foreach(collate)
+ if len(children):
+ all_id = 'artist_all_tracks_%d' % (self.id)
+ if all_id not in self.store.containers:
+ self.store.containers[all_id] = \
+ Container( all_id, self.id, 'All tracks of %s' % self.name,
+ children_callback=self.get_artist_all_tracks,
+ store=self.store,play_container=True)
+
+ children.insert(0,self.store.containers[all_id])
+
if request_count == 0:
return children[start:]
else:
@@ -240,9 +274,12 @@ class Track(BackendItem):
item.originalTrackNumber = str(self.store.db.entry_get (entry, rhythmdb.PROP_TRACK_NUMBER))
item.title = self.store.db.entry_get(entry, rhythmdb.PROP_TITLE) # much nicer if it was entry.title
- #cover = self.store.db.entry_request_extra_metadata(entry, "rb:coverArt")
+ cover = self.store.db.entry_request_extra_metadata(entry, "rb:coverArt-uri")
#self.warning("cover for %r is %r", item.title, cover)
- #item.albumArtURI = ## can we somehow store art in the upnp share??
+ if cover != None:
+ _,ext = os.path.splitext(cover)
+ item.albumArtURI = ''.join((self.get_url(),'?cover',ext))
+
# add http resource
res = DIDLLite.Resource(self.get_url(), 'http-get:*:%s:*' % mimetype)
@@ -280,22 +317,28 @@ class Track(BackendItem):
if entry is None:
entry = self.store.db.entry_lookup_by_id (self.id)
uri = self.store.db.entry_get(entry, rhythmdb.PROP_LOCATION)
- self.warning("Track get_path uri = %r", uri)
+ self.info("Track get_path uri = %r", uri)
location = None
if uri.startswith("file://"):
location = unicode(urllib.unquote(uri[len("file://"):]))
- self.warning("Track get_path location = %r", location)
+ self.info("Track get_path location = %r", location)
return location
+ def get_cover(self):
+ entry = self.store.db.entry_lookup_by_id(self.id)
+ cover = self.store.db.entry_request_extra_metadata(entry, "rb:coverArt-uri")
+ return cover
+
+
class MediaStore(BackendStore):
logCategory = 'rb_media_store'
implements = ['MediaServer']
def __init__(self, server, **kwargs):
+ BackendStore.__init__(self,server,**kwargs)
self.warning("__init__ MediaStore %r", kwargs)
- self.server = server
self.db = kwargs['db']
self.plugin = kwargs['plugin']
@@ -304,8 +347,6 @@ class MediaStore(BackendStore):
'6': lambda : self.get_by_id(AUDIO_ARTIST_CONTAINER_ID), # all artists
})
- self.update_id = 0
-
self.next_id = CONTAINER_COUNT
self.albums = None
self.artists = None
@@ -315,7 +356,10 @@ class MediaStore(BackendStore):
if( len(self.urlbase) > 0 and self.urlbase[len(self.urlbase)-1] != '/'):
self.urlbase += '/'
- self.name = "Rhythmbox on %s" % self.server.coherence.hostname
+ try:
+ self.name = kwargs['name']
+ except KeyError:
+ self.name = "Rhythmbox on %s" % self.server.coherence.hostname
query = self.db.query_new()
self.info(query)
@@ -335,7 +379,8 @@ class MediaStore(BackendStore):
self.containers[AUDIO_ALL_CONTAINER_ID] = \
Container( AUDIO_ALL_CONTAINER_ID,ROOT_CONTAINER_ID, 'All tracks',
- children_callback=self.children_tracks)
+ children_callback=self.children_tracks,
+ store=self,play_container=True)
self.containers[ROOT_CONTAINER_ID].add_child(self.containers[AUDIO_ALL_CONTAINER_ID])
self.containers[AUDIO_ALBUM_CONTAINER_ID] = \
@@ -353,6 +398,12 @@ class MediaStore(BackendStore):
def get_by_id(self,id):
self.info("looking for id %r", id)
+ if isinstance(id, basestring) and id.startswith('artist_all_tracks_'):
+ try:
+ return self.containers[id]
+ except:
+ return None
+
id = id.split('@',1)
item_id = id[0]
item_id = int(item_id)
@@ -424,8 +475,6 @@ class MediaStore(BackendStore):
def children_artists(self,parent_id):
artists = []
- self.info('children_artists')
-
def collate (model, path, iter):
name = model.get(iter, 0)[0]
priority = model.get(iter, 1)[0]
diff --git a/plugins/coherence/upnp_coherence/__init__.py b/plugins/coherence/upnp_coherence/__init__.py
index 669d69e..ca1d1ba 100644
--- a/plugins/coherence/upnp_coherence/__init__.py
+++ b/plugins/coherence/upnp_coherence/__init__.py
@@ -10,20 +10,52 @@
import rhythmdb, rb
import gobject, gtk
-import coherence.extern.louie as louie
+import gconf
-from coherence import log
+import louie
-# For the icon
-import os.path, urllib, gtk.gdk
+from coherence import log
-class CoherencePlugin(rb.Plugin,log.Loggable):
+# for the icon
+import os.path, urllib, gnomevfs, gtk.gdk
+
+# the gconf configuration
+gconf_keys = {
+ 'port': "/apps/rhythmbox/plugins/coherence/port",
+ 'interface': "/apps/rhythmbox/plugins/coherence/interface",
+ # DMS
+ 'dms_uuid': "/apps/rhythmbox/plugins/coherence/dms/uuid",
+ 'dms_active': "/apps/rhythmbox/plugins/coherence/dms/active",
+ 'dms_version': "/apps/rhythmbox/plugins/coherence/dms/version",
+ 'dms_name': "/apps/rhythmbox/plugins/coherence/dms/name",
+ # DMR
+ 'dmr_uuid': "/apps/rhythmbox/plugins/coherence/dmr/uuid",
+ 'dmr_active': "/apps/rhythmbox/plugins/coherence/dmr/active",
+ 'dmr_version': "/apps/rhythmbox/plugins/coherence/dmr/version",
+ 'dmr_name': "/apps/rhythmbox/plugins/coherence/dmr/name",
+ # DMC
+ 'dmc_active': "/apps/rhythmbox/plugins/coherence/dmc/active",
+}
+
+class CoherencePlugin(rb.Plugin, log.Loggable):
logCategory = 'rb_coherence_plugin'
def __init__(self):
rb.Plugin.__init__(self)
self.coherence = None
+ self.config = gconf.client_get_default()
+
+ if self.config.get(gconf_keys['dmc_active']) is None:
+ # key not yet found represented by "None"
+ self._set_defaults()
+
+ def _set_defaults(self):
+ for a in ('r', 's'):
+ self.config.set_bool(gconf_keys['dm%s_active' % a], True)
+ self.config.set_int(gconf_keys['dm%s_version' % a], 2)
+
+ self.config.set_bool(gconf_keys['dmc_active'], True)
def activate(self, shell):
from twisted.internet import gtk2reactor
@@ -47,72 +79,112 @@ class CoherencePlugin(rb.Plugin,log.Loggable):
face_path = os.path.join(os.path.expanduser('~'), ".face")
if os.path.exists(face_path):
url = "file://" + urllib.pathname2url(face_path)
- try:
- import gio
- f = gio.File(url)
- fi = f.query_info(gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE)
- ctype = fi.get_attribute_string(gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE)
- mimetype = gio.content_type_get_mime_type(ctype)
- except:
- import gnomevfs
- mimetype = gnomevfs.get_mime_type(url)
-
+ mimetype = gnomevfs.get_mime_type(url)
pixbuf = gtk.gdk.pixbuf_new_from_file(face_path)
width = "%s" % pixbuf.get_width()
height = "%s" % pixbuf.get_height()
depth = '24'
the_icon = {
- 'url':url,
- 'mimetype':mimetype,
- 'width':width,
- 'height':height,
- 'depth':depth
+ 'url': url,
+ 'mimetype': mimetype,
+ 'width': width,
+ 'height': height,
+ 'depth': depth
}
- else:
- the_icon = None
- # create our own media server
- from coherence.upnp.devices.media_server import MediaServer
- from MediaStore import MediaStore
- if the_icon:
- server = MediaServer(self.coherence, MediaStore, no_thread_needed=True, db=self.shell.props.db, plugin=self, icon=the_icon)
- else:
- server = MediaServer(self.coherence, MediaStore, no_thread_needed=True, db=self.shell.props.db, plugin=self)
+ if self.config.get_bool(gconf_keys['dms_active']):
+ # create our own media server
+ from coherence.upnp.devices.media_server import MediaServer
+ from MediaStore import MediaStore
- self.uuid = str(server.uuid)
+ kwargs = {
+ 'version': self.config.get_int(gconf_keys['dms_version']),
+ 'no_thread_needed': True,
+ 'db': self.shell.props.db,
+ 'plugin': self}
+
+ if the_icon:
+ kwargs['icon'] = the_icon
- if self.coherence_version >= (0,5,2):
+ dms_uuid = self.config.get_string(gconf_keys['dms_uuid'])
+ if dms_uuid:
+ kwargs['uuid'] = dms_uuid
+
+ name = self.config.get_string(gconf_keys['dms_name'])
+ if name:
+ kwargs['name'] = name
+
+ self.server = MediaServer(self.coherence, MediaStore, **kwargs)
+
+ if dms_uuid is None:
+ self.config.set_string(gconf_keys['dms_uuid'], str(self.server.uuid))
+
+ self.warning("Media Store available with UUID %s" % str(self.server.uuid))
+
+ if self.config.get_bool(gconf_keys['dmr_active']):
# create our own media renderer
# but only if we have a matching Coherence package installed
- from coherence.upnp.devices.media_renderer import MediaRenderer
- from MediaPlayer import RhythmboxPlayer
- if the_icon:
- MediaRenderer(self.coherence, RhythmboxPlayer, no_thread_needed=True, shell=self.shell, icon=the_icon)
+ if self.coherence_version < (0, 5, 2):
+ print "activation faild. Coherence is older than version 0.5.2"
else:
- MediaRenderer(self.coherence, RhythmboxPlayer, no_thread_needed=True, shell=self.shell)
+ from coherence.upnp.devices.media_renderer import MediaRenderer
+ from MediaPlayer import RhythmboxPlayer
+ kwargs = {
+ "version": self.config.get_int(gconf_keys['dmr_version']),
+ "no_thread_needed": True,
+ "shell": self.shell,
+ 'rb_mediaserver': self.server,
+ }
+
+ if the_icon:
+ kwargs['icon'] = the_icon
- # watch for media servers
- louie.connect(self.detected_media_server,
- 'Coherence.UPnP.ControlPoint.MediaServer.detected',
- louie.Any)
- louie.connect(self.removed_media_server,
- 'Coherence.UPnP.ControlPoint.MediaServer.removed',
- louie.Any)
+ dmr_uuid = self.config.get_string(gconf_keys['dmr_uuid'])
+ if dmr_uuid:
+ kwargs['uuid'] = dmr_uuid
+
+ name = self.config.get_string(gconf_keys['dmr_name'])
+ if name:
+ kwargs['name'] = name
+
+ self.renderer = MediaRenderer(self.coherence,
+ RhythmboxPlayer, **kwargs)
+
+ if dmr_uuid is None:
+ self.config.set_string(gconf_keys['dmr_uuid'], str(self.renderer.uuid))
+
+ self.warning("Media Renderer available with UUID %s" % str(self.renderer.uuid))
+
+ if self.config.get_bool(gconf_keys['dmc_active']):
+ self.warning("start looking for media servers")
+ # watch for media servers
+ louie.connect(self.detected_media_server,
+ 'Coherence.UPnP.ControlPoint.MediaServer.detected',
+ louie.Any)
+ louie.connect(self.removed_media_server,
+ 'Coherence.UPnP.ControlPoint.MediaServer.removed',
+ louie.Any)
def deactivate(self, shell):
- print "coherence UPnP plugin deactivated"
+ self.info("Coherence UPnP plugin deactivated")
if self.coherence is None:
return
self.coherence.shutdown()
- louie.disconnect(self.detected_media_server,
- 'Coherence.UPnP.ControlPoint.MediaServer.detected',
- louie.Any)
- louie.disconnect(self.removed_media_server,
- 'Coherence.UPnP.ControlPoint.MediaServer.removed',
- louie.Any)
+ try:
+ louie.disconnect(self.detected_media_server,
+ 'Coherence.UPnP.ControlPoint.MediaServer.detected',
+ louie.Any)
+ except louie.error.DispatcherKeyError:
+ pass
+ try:
+ louie.disconnect(self.removed_media_server,
+ 'Coherence.UPnP.ControlPoint.MediaServer.removed',
+ louie.Any)
+ except louie.error.DispatcherKeyError:
+ pass
del self.shell
del self.coherence
@@ -148,26 +220,35 @@ class CoherencePlugin(rb.Plugin,log.Loggable):
'controlpoint': 'yes',
'plugins': {},
}
+
+ serverport = self.config.get_int(gconf_keys['port'])
+ if serverport:
+ coherence_config['serverport'] = serverport
+
+ interface = self.config.get_string(gconf_keys['interface'])
+ if interface:
+ coherence_config['interface'] = interface
+
coherence_instance = Coherence(coherence_config)
return coherence_instance
def removed_media_server(self, udn):
- print "upnp server went away %s" % udn
+ self.info("upnp server went away %s" % udn)
if self.sources.has_key(udn):
self.sources[udn].delete_thyself()
del self.sources[udn]
def detected_media_server(self, client, udn):
- print "found upnp server %s (%s)" % (client.device.get_friendly_name(), udn)
- self.warning("found upnp server %s (%s)" % (client.device.get_friendly_name(), udn))
- if client.device.get_id() == self.uuid:
+ self.info("found upnp server %s (%s)" % (client.device.get_friendly_name(), udn))
+ if self.server and client.device.get_id() == str(self.server.uuid):
""" don't react on our own MediaServer"""
return
db = self.shell.props.db
- group = rb.rb_source_group_get_by_name ("shared")
- entry_type = db.entry_register_type("CoherenceUpnp:" + client.device.get_id()[5:])
+ group = rb.rb_source_group_get_by_name("shared")
+ entry_type = db.entry_register_type("CoherenceUpnp:%s" %
+ client.device.get_id()[5:])
from UpnpSource import UpnpSource
source = gobject.new (UpnpSource,
@@ -181,3 +262,59 @@ class CoherencePlugin(rb.Plugin,log.Loggable):
self.sources[udn] = source
self.shell.append_source (source, None)
+
+ def create_configure_dialog(self, dialog=None):
+ if dialog is None:
+
+ def store_config(dialog,port_spinner,interface_entry):
+ port = port_spinner.get_value_as_int()
+ self.config.set_int(gconf_keys['port'],port)
+ interface = interface_entry.get_text()
+ if len(interface) != 0:
+ self.config.set_string(gconf_keys['interface'],interface)
+ dialog.hide()
+
+ dialog = gtk.Dialog(title='DLNA/UPnP Configuration',
+ parent=None,flags=0,buttons=None)
+ dialog.set_default_size(400,350)
+
+ table = gtk.Table(rows=2, columns=2, homogeneous=True)
+ dialog.vbox.pack_start(table, False, False, 0)
+
+ label = gtk.Label("Port :")
+ label.set_alignment(0,0.5)
+ table.attach(label, 0, 1, 0, 1)
+
+ value = 0
+ if self.config.get_int(gconf_keys['port']) != None:
+ value = self.config.get_int(gconf_keys['port'])
+ adj = gtk.Adjustment(value, 0, 65535, 1, 100, 0)
+ port_spinner = gtk.SpinButton(adj, 0, 0)
+ port_spinner.set_wrap(True)
+ port_spinner.set_numeric(True)
+ table.attach(port_spinner, 1, 2, 0, 1,
+ xoptions=gtk.FILL|gtk.EXPAND,yoptions=gtk.FILL|gtk.EXPAND,xpadding=5,ypadding=5)
+
+ label = gtk.Label("Interface :")
+ label.set_alignment(0,0.5)
+ table.attach(label, 0, 1, 1, 2)
+ interface_entry = gtk.Entry()
+ interface_entry.set_max_length(16)
+ if self.config.get_string(gconf_keys['interface']) != None:
+ interface_entry.set_text(self.config.get_string(gconf_keys['interface']))
+ else:
+ interface_entry.set_text('')
+ table.attach(interface_entry, 1, 2, 1, 2,
+ xoptions=gtk.FILL|gtk.EXPAND,yoptions=gtk.FILL|gtk.EXPAND,xpadding=5,ypadding=5)
+
+ button = gtk.Button(stock=gtk.STOCK_CANCEL)
+ dialog.action_area.pack_start(button, True, True, 5)
+ button.connect("clicked", lambda w: dialog.hide())
+ button = gtk.Button(stock=gtk.STOCK_OK)
+ button.connect("clicked", lambda w: store_config(dialog,port_spinner,interface_entry))
+ dialog.action_area.pack_start(button, True, True, 5)
+ dialog.show_all()
+
+
+ dialog.present()
+ return dialog
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]