home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / lib / rhythmbox / plugins / upnp_coherence / MediaPlayer.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-04-20  |  15.6 KB  |  463 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. import urllib
  5. import rhythmdb
  6. from coherence.upnp.core.soap_service import errorCode
  7. from coherence.upnp.core import DIDLLite
  8. import coherence.extern.louie as louie
  9. from coherence.extern.simple_plugin import Plugin
  10. from coherence import log
  11. TRACK_COUNT = 1000000
  12.  
  13. class RhythmboxPlayer(log.Loggable):
  14.     ''' a backend to the Rhythmbox
  15.  
  16.     '''
  17.     logCategory = 'rb_media_renderer'
  18.     implements = [
  19.         'MediaRenderer']
  20.     vendor_value_defaults = {
  21.         'RenderingControl': {
  22.             'A_ARG_TYPE_Channel': 'Master' },
  23.         'AVTransport': {
  24.             'A_ARG_TYPE_SeekMode': ('ABS_TIME', 'REL_TIME') } }
  25.     vendor_range_defaults = {
  26.         'RenderingControl': {
  27.             'Volume': {
  28.                 'maximum': 100 } } }
  29.     
  30.     def __init__(self, device, **kwargs):
  31.         self.warning('__init__ RhythmboxPlayer %r', kwargs)
  32.         self.shell = kwargs['shell']
  33.         self.server = device
  34.         self.player = None
  35.         self.metadata = None
  36.         self.name = 'Rhythmbox on %s' % self.server.coherence.hostname
  37.         self.player = self.shell.get_player()
  38.         louie.send('Coherence.UPnP.Backend.init_completed', None, backend = self)
  39.         self.playing = False
  40.         self.state = None
  41.         self.duration = None
  42.         self.volume = 1
  43.         self.muted_volume = None
  44.         self.view = []
  45.         self.tags = { }
  46.  
  47.     
  48.     def __repr__(self):
  49.         return str(self.__class__).split('.')[-1]
  50.  
  51.     
  52.     def volume_changed(self, player, parameter):
  53.         self.volume = self.player.props.volume
  54.         if self.volume > 0:
  55.             rcs_id = self.server.connection_manager_server.lookup_rcs_id(self.current_connection_id)
  56.             self.server.rendering_control_server.set_variable(rcs_id, 'Volume', self.volume * 100)
  57.         
  58.  
  59.     
  60.     def playing_song_changed(self, player, entry):
  61.         if self.server != None:
  62.             connection_id = self.server.connection_manager_server.lookup_avt_id(self.current_connection_id)
  63.         
  64.         if entry == None:
  65.             self.update('STOPPED')
  66.             self.playing = False
  67.             self.metadata = None
  68.             self.duration = None
  69.         else:
  70.             self.id = self.shell.props.db.entry_get(entry, rhythmdb.PROP_ENTRY_ID)
  71.             bitrate = self.shell.props.db.entry_get(entry, rhythmdb.PROP_BITRATE) * 1024 / 8
  72.             seconds = self.shell.props.db.entry_get(entry, rhythmdb.PROP_DURATION)
  73.             hours = seconds / 3600
  74.             seconds = seconds - hours * 3600
  75.             minutes = seconds / 60
  76.             seconds = seconds - minutes * 60
  77.             self.duration = '%02d:%02d:%02d' % (hours, minutes, seconds)
  78.             mimetype = self.shell.props.db.entry_get(entry, rhythmdb.PROP_MIMETYPE)
  79.             if mimetype == 'application/x-id3':
  80.                 mimetype = 'audio/mpeg'
  81.             
  82.             size = self.shell.props.db.entry_get(entry, rhythmdb.PROP_FILE_SIZE)
  83.             item = DIDLLite.MusicTrack(self.id + TRACK_COUNT)
  84.             item.album = self.shell.props.db.entry_get(entry, rhythmdb.PROP_ALBUM)
  85.             item.artist = self.shell.props.db.entry_get(entry, rhythmdb.PROP_ARTIST)
  86.             item.genre = self.shell.props.db.entry_get(entry, rhythmdb.PROP_GENRE)
  87.             item.originalTrackNumber = str(self.shell.props.db.entry_get(entry, rhythmdb.PROP_TRACK_NUMBER))
  88.             item.title = self.shell.props.db.entry_get(entry, rhythmdb.PROP_TITLE)
  89.             item.res = []
  90.             uri = self.shell.props.db.entry_get(entry, rhythmdb.PROP_LOCATION)
  91.             if uri.startswith('file://'):
  92.                 location = unicode(urllib.unquote(uri[len('file://'):]))
  93.                 res = DIDLLite.Resource(location, 'http-get:*:%s:*' % mimetype)
  94.                 if size > 0:
  95.                     res.size = size
  96.                 
  97.                 if self.duration > 0:
  98.                     res.duration = self.duration
  99.                 
  100.                 if bitrate > 0:
  101.                     res.bitrate = str(bitrate)
  102.                 
  103.                 item.res.append(res)
  104.             
  105.             elt = DIDLLite.DIDLElement()
  106.             elt.addItem(item)
  107.             self.metadata = elt.toString()
  108.             self.entry = entry
  109.             if self.server != None:
  110.                 self.server.av_transport_server.set_variable(connection_id, 'AVTransportURIMetaData', self.metadata)
  111.                 self.server.av_transport_server.set_variable(connection_id, 'CurrentTrackMetaData', self.metadata)
  112.             
  113.         if self.server != None:
  114.             self.server.av_transport_server.set_variable(connection_id, 'RelativeTimePosition', '00:00:00')
  115.             self.server.av_transport_server.set_variable(connection_id, 'AbsoluteTimePosition', '00:00:00')
  116.         
  117.  
  118.     
  119.     def playing_changed(self, player, state):
  120.         if state is True:
  121.             transport_state = 'PLAYING'
  122.         elif self.playing is False:
  123.             transport_state = 'STOPPED'
  124.         else:
  125.             transport_state = 'PAUSED_PLAYBACK'
  126.         self.update(transport_state)
  127.         
  128.         try:
  129.             position = player.get_playing_time()
  130.         except:
  131.             position = None
  132.  
  133.         
  134.         try:
  135.             duration = player.get_playing_song_duration()
  136.         except:
  137.             duration = None
  138.  
  139.         self.update_position(position, duration)
  140.  
  141.     
  142.     def elapsed_changed(self, player, time):
  143.         
  144.         try:
  145.             duration = player.get_playing_song_duration()
  146.         except:
  147.             duration = None
  148.  
  149.         self.update_position(time, duration)
  150.  
  151.     
  152.     def update(self, state):
  153.         if state in ('STOPPED', 'READY'):
  154.             transport_state = 'STOPPED'
  155.         
  156.         if state == 'PLAYING':
  157.             transport_state = 'PLAYING'
  158.         
  159.         if state == 'PAUSED_PLAYBACK':
  160.             transport_state = 'PAUSED_PLAYBACK'
  161.         
  162.         if self.state != transport_state:
  163.             self.state = transport_state
  164.             if self.server != None:
  165.                 connection_id = self.server.connection_manager_server.lookup_avt_id(self.current_connection_id)
  166.                 self.server.av_transport_server.set_variable(connection_id, 'TransportState', transport_state)
  167.             
  168.         
  169.  
  170.     
  171.     def update_position(self, position, duration):
  172.         if self.server != None:
  173.             connection_id = self.server.connection_manager_server.lookup_avt_id(self.current_connection_id)
  174.             self.server.av_transport_server.set_variable(connection_id, 'CurrentTrack', 0)
  175.         
  176.         if position is not None:
  177.             (m, s) = divmod(position, 60)
  178.             (h, m) = divmod(m, 60)
  179.             if self.server != None:
  180.                 self.server.av_transport_server.set_variable(connection_id, 'RelativeTimePosition', '%02d:%02d:%02d' % (h, m, s))
  181.                 self.server.av_transport_server.set_variable(connection_id, 'AbsoluteTimePosition', '%02d:%02d:%02d' % (h, m, s))
  182.             
  183.         
  184.         if duration <= 0:
  185.             duration = None
  186.         
  187.         if duration is not None:
  188.             (m, s) = divmod(duration, 60)
  189.             (h, m) = divmod(m, 60)
  190.             if self.server != None:
  191.                 self.server.av_transport_server.set_variable(connection_id, 'CurrentTrackDuration', '%02d:%02d:%02d' % (h, m, s))
  192.                 self.server.av_transport_server.set_variable(connection_id, 'CurrentMediaDuration', '%02d:%02d:%02d' % (h, m, s))
  193.             
  194.             if self.duration is None:
  195.                 if self.metadata is not None:
  196.                     elt = DIDLLite.DIDLElement.fromString(self.metadata)
  197.                     for item in elt:
  198.                         for res in item.findall('res'):
  199.                             res.attrib['duration'] = '%d:%02d:%02d' % (h, m, s)
  200.                         
  201.                     
  202.                     self.metadata = elt.toString()
  203.                     if self.server != None:
  204.                         self.server.av_transport_server.set_variable(connection_id, 'AVTransportURIMetaData', self.metadata)
  205.                         self.server.av_transport_server.set_variable(connection_id, 'CurrentTrackMetaData', self.metadata)
  206.                     
  207.                 
  208.                 self.duration = duration
  209.             
  210.         
  211.  
  212.     
  213.     def load(self, uri, metadata):
  214.         self.duration = None
  215.         self.metadata = metadata
  216.         self.tags = { }
  217.         was_playing = self.playing
  218.         if was_playing == True:
  219.             self.stop()
  220.         
  221.         if len(metadata) > 0:
  222.             elt = DIDLLite.DIDLElement.fromString(metadata)
  223.             if elt.numItems() == 1:
  224.                 item = elt.getItems()[0]
  225.                 if uri.startswith('track-'):
  226.                     self.entry = self.shell.props.db.entry_lookup_by_id(int(uri[6:]))
  227.                 else:
  228.                     self.entry = self.shell.props.db.entry_lookup_by_location(uri)
  229.                 if self.entry == None:
  230.                     if item.server_uuid is not None:
  231.                         entry_type = self.shell.props.db.entry_register_type('CoherenceUpnp:' + item.server_uuid)
  232.                         self.entry = self.shell.props.db.entry_new(entry_type, uri)
  233.                     else:
  234.                         entry_type = self.shell.props.db.entry_register_type('CoherencePlayer')
  235.                         self.entry = self.shell.props.db.entry_new(entry_type, uri)
  236.                 
  237.                 duration = None
  238.                 size = None
  239.                 bitrate = None
  240.                 for res in item.res:
  241.                     if res.data == uri:
  242.                         duration = res.duration
  243.                         size = res.size
  244.                         bitrate = res.bitrate
  245.                         break
  246.                         continue
  247.                 
  248.                 self.shell.props.db.set(self.entry, rhythmdb.PROP_TITLE, item.title)
  249.                 
  250.                 try:
  251.                     if item.artist is not None:
  252.                         self.shell.props.db.set(self.entry, rhythmdb.PROP_ARTIST, item.artist)
  253.                 except AttributeError:
  254.                     pass
  255.  
  256.                 
  257.                 try:
  258.                     if item.album is not None:
  259.                         self.shell.props.db.set(self.entry, rhythmdb.PROP_ALBUM, item.album)
  260.                 except AttributeError:
  261.                     pass
  262.  
  263.                 
  264.                 try:
  265.                     self.info('%r %r', item.title, item.originalTrackNumber)
  266.                     if item.originalTrackNumber is not None:
  267.                         self.shell.props.db.set(self.entry, rhythmdb.PROP_TRACK_NUMBER, int(item.originalTrackNumber))
  268.                 except AttributeError:
  269.                     pass
  270.  
  271.                 if duration is not None:
  272.                     (h, m, s) = duration.split(':')
  273.                     seconds = int(h) * 3600 + int(m) * 60 + int(s)
  274.                     self.info('%r %r:%r:%r %r', duration, h, m, s, seconds)
  275.                     self.shell.props.db.set(self.entry, rhythmdb.PROP_DURATION, seconds)
  276.                 
  277.                 if size is not None:
  278.                     self.shell.props.db.set(self.entry, rhythmdb.PROP_FILE_SIZE, int(size))
  279.                 
  280.             
  281.         elif uri.startswith('track-'):
  282.             self.entry = self.shell.props.db.entry_lookup_by_id(int(uri[6:]))
  283.         else:
  284.             entry_type = self.shell.props.db.entry_register_type('CoherencePlayer')
  285.             self.entry = self.shell.props.db.entry_new(entry_type, uri)
  286.         self.playing = False
  287.         self.metadata = metadata
  288.         connection_id = self.server.connection_manager_server.lookup_avt_id(self.current_connection_id)
  289.         self.server.av_transport_server.set_variable(connection_id, 'CurrentTransportActions', 'Play,Stop,Pause,Seek')
  290.         self.server.av_transport_server.set_variable(connection_id, 'NumberOfTracks', 1)
  291.         self.server.av_transport_server.set_variable(connection_id, 'CurrentTrackURI', uri)
  292.         self.server.av_transport_server.set_variable(connection_id, 'AVTransportURI', uri)
  293.         self.server.av_transport_server.set_variable(connection_id, 'AVTransportURIMetaData', metadata)
  294.         self.server.av_transport_server.set_variable(connection_id, 'CurrentTrackURI', uri)
  295.         self.server.av_transport_server.set_variable(connection_id, 'CurrentTrackMetaData', metadata)
  296.         if was_playing == True:
  297.             self.play()
  298.         
  299.  
  300.     
  301.     def start(self, uri):
  302.         self.load(uri)
  303.         self.play()
  304.  
  305.     
  306.     def stop(self):
  307.         self.player.stop()
  308.         self.playing = False
  309.  
  310.     
  311.     def play(self):
  312.         if self.playing == False:
  313.             self.player.play_entry(self.entry)
  314.             self.playing = True
  315.         else:
  316.             self.player.playpause()
  317.  
  318.     
  319.     def pause(self):
  320.         self.player.pause()
  321.  
  322.     
  323.     def seek(self, location, old_state):
  324.         '''
  325.         @param location:    simple number = time to seek to, in seconds
  326.                             +nL = relative seek forward n seconds
  327.                             -nL = relative seek backwards n seconds
  328.         '''
  329.         self.player.seek(location)
  330.         self.server.av_transport_server.set_variable(0, 'TransportState', old_state)
  331.  
  332.     
  333.     def mute(self):
  334.         self.muted_volume = self.volume
  335.         self.player.set_volume(0)
  336.         rcs_id = self.server.connection_manager_server.lookup_rcs_id(self.current_connection_id)
  337.         self.server.rendering_control_server.set_variable(rcs_id, 'Mute', 'True')
  338.  
  339.     
  340.     def unmute(self):
  341.         if self.muted_volume is not None:
  342.             self.player.set_volume(self.muted_volume)
  343.             self.muted_volume = None
  344.         
  345.         self.player.set_mute(False)
  346.         rcs_id = self.server.connection_manager_server.lookup_rcs_id(self.current_connection_id)
  347.         self.server.rendering_control_server.set_variable(rcs_id, 'Mute', 'False')
  348.  
  349.     
  350.     def get_mute(self):
  351.         return self.player.get_mute()
  352.  
  353.     
  354.     def get_volume(self):
  355.         self.volume = self.player.get_volume()
  356.         return self.volume * 100
  357.  
  358.     
  359.     def set_volume(self, volume):
  360.         volume = int(volume)
  361.         if volume < 0:
  362.             volume = 0
  363.         
  364.         if volume > 100:
  365.             volume = 100
  366.         
  367.         self.player.set_volume(float(volume / 100))
  368.  
  369.     
  370.     def upnp_init(self):
  371.         (self.player.connect('playing-song-changed', self.playing_song_changed),)
  372.         self.player.connect('playing-changed', self.playing_changed)
  373.         self.player.connect('elapsed-changed', self.elapsed_changed)
  374.         self.player.connect('notify::volume', self.volume_changed)
  375.         self.current_connection_id = None
  376.         self.server.connection_manager_server.set_variable(0, 'SinkProtocolInfo', [
  377.             'rhythmbox:%s:audio/mpeg:*' % self.server.coherence.hostname,
  378.             'http-get:*:audio/mpeg:*'], default = True)
  379.         self.server.av_transport_server.set_variable(0, 'TransportState', 'NO_MEDIA_PRESENT', default = True)
  380.         self.server.av_transport_server.set_variable(0, 'TransportStatus', 'OK', default = True)
  381.         self.server.av_transport_server.set_variable(0, 'CurrentPlayMode', 'NORMAL', default = True)
  382.         self.server.av_transport_server.set_variable(0, 'CurrentTransportActions', '', default = True)
  383.         self.server.rendering_control_server.set_variable(0, 'Volume', self.get_volume())
  384.         self.server.rendering_control_server.set_variable(0, 'Mute', self.get_mute())
  385.  
  386.     
  387.     def upnp_Play(self, *args, **kwargs):
  388.         InstanceID = int(kwargs['InstanceID'])
  389.         Speed = int(kwargs['Speed'])
  390.         self.play()
  391.         return { }
  392.  
  393.     
  394.     def upnp_Pause(self, *args, **kwargs):
  395.         InstanceID = int(kwargs['InstanceID'])
  396.         self.pause()
  397.         return { }
  398.  
  399.     
  400.     def upnp_Stop(self, *args, **kwargs):
  401.         InstanceID = int(kwargs['InstanceID'])
  402.         self.stop()
  403.         return { }
  404.  
  405.     
  406.     def upnp_Seek(self, *args, **kwargs):
  407.         InstanceID = int(kwargs['InstanceID'])
  408.         Unit = kwargs['Unit']
  409.         Target = kwargs['Target']
  410.         if Unit in ('ABS_TIME', 'REL_TIME'):
  411.             old_state = self.server.av_transport_server.get_variable(0, 'TransportState')
  412.             self.server.av_transport_server.set_variable(0, 'TransportState', 'TRANSITIONING')
  413.             (h, m, s) = Target.split(':')
  414.             seconds = int(h) * 3600 + int(m) * 60 + int(s)
  415.             self.seek(seconds, old_state)
  416.         
  417.         return { }
  418.  
  419.     
  420.     def upnp_SetAVTransportURI(self, *args, **kwargs):
  421.         InstanceID = int(kwargs['InstanceID'])
  422.         CurrentURI = kwargs['CurrentURI']
  423.         CurrentURIMetaData = kwargs['CurrentURIMetaData']
  424.         local_protocol_infos = self.server.connection_manager_server.get_variable('SinkProtocolInfo').value.split(',')
  425.         if len(CurrentURIMetaData) == 0:
  426.             self.load(CurrentURI, CurrentURIMetaData)
  427.             return { }
  428.         elt = DIDLLite.DIDLElement.fromString(CurrentURIMetaData)
  429.         if elt.numItems() == 1:
  430.             item = elt.getItems()[0]
  431.             res = item.res.get_matching(local_protocol_infos, protocol_type = 'rhythmbox')
  432.             if len(res) == 0:
  433.                 res = item.res.get_matching(local_protocol_infos)
  434.             
  435.             if len(res) > 0:
  436.                 res = res[0]
  437.                 (remote_protocol, remote_network, remote_content_format, _) = res.protocolInfo.split(':')
  438.                 self.load(res.data, CurrentURIMetaData)
  439.                 return { }
  440.         
  441.         return failure.Failure(errorCode(714))
  442.  
  443.     
  444.     def upnp_SetMute(self, *args, **kwargs):
  445.         InstanceID = int(kwargs['InstanceID'])
  446.         Channel = kwargs['Channel']
  447.         DesiredMute = kwargs['DesiredMute']
  448.         if DesiredMute in ('TRUE', 'True', 'true', '1', 'Yes', 'yes'):
  449.             self.mute()
  450.         else:
  451.             self.unmute()
  452.         return { }
  453.  
  454.     
  455.     def upnp_SetVolume(self, *args, **kwargs):
  456.         InstanceID = int(kwargs['InstanceID'])
  457.         Channel = kwargs['Channel']
  458.         DesiredVolume = int(kwargs['DesiredVolume'])
  459.         self.set_volume(DesiredVolume)
  460.         return { }
  461.  
  462.  
  463.