Package elisa :: Package plugins :: Package good :: Package audiocd :: Module audiocd_media
[hide private]
[frames] | no frames]

Source Code for Module elisa.plugins.good.audiocd.audiocd_media

  1  # -*- coding: utf-8 -*- 
  2  # Elisa - Home multimedia server 
  3  # Copyright (C) 2006-2008 Fluendo Embedded S.L. (www.fluendo.com). 
  4  # All rights reserved. 
  5  # 
  6  # This file is available under one of two license agreements. 
  7  # 
  8  # This file is licensed under the GPL version 3. 
  9  # See "LICENSE.GPL" in the root of this distribution including a special 
 10  # exception to use Elisa with Fluendo's plugins. 
 11  # 
 12  # The GPL part of Elisa is also available under a commercial licensing 
 13  # agreement from Fluendo. 
 14  # See "LICENSE.Elisa" in the root directory of this distribution package 
 15  # for details on that license. 
 16   
 17   
 18  __maintainer__ = 'Benjamin Kampmann <benjamin@fluendo.com>' 
 19   
 20   
 21  from elisa.base_components.media_provider import MediaProvider 
 22  from elisa.core.media_uri import quote, MediaUri 
 23  from elisa.core.bus.bus_message import MediaLocation 
 24  from elisa.core import common 
 25   
 26  from elisa.extern.translation import gettexter, N_ 
 27  T_ = gettexter('elisa-audiocd') 
 28   
 29  import pygst 
 30  pygst.require('0.10') 
 31  import gst 
 32   
 33  import os, re 
 34   
 35  from twisted.internet import defer, threads 
 36   
37 -class NoCDFoundError(Exception):
38 pass
39
40 -class AudiocdMedia(MediaProvider):
41 """ 42 This class implements the AudioCD support 43 """ 44 name = "audiocd" 45
46 - def __init__(self):
47 MediaProvider.__init__(self) 48 self._discid = "" 49 self._tracks = {}
50
51 - def _bus_message_received(self, msg, sender):
52 if msg.fstype == 'cdda': 53 if msg.action == MediaLocation.ActionType.LOCATION_ADDED: 54 self.debug("AudioCD found at %s" % msg.name) 55 elif msg.action == MediaLocation.ActionType.LOCATION_REMOVED: 56 self.debug("AudioCD removed") 57 self._discid = "" 58 self._tracks = {}
59
60 - def initialize(self):
63
65 return []
66
68 return {'cdda':0}
69
70 - def _blocking_get_media_type(self, uri):
71 file_type = 'audio' 72 mime_type = '' 73 if self._blocking_is_directory(uri): 74 file_type = 'directory' 75 76 return {'file_type': file_type, 'mime_type': mime_type}
77
78 - def _blocking_is_directory(self, uri):
79 return uri.host == '' and uri.parent.path == '/'
80
81 - def _blocking_has_children_with_types(self, uri, media_types):
82 has_children = False 83 if self._blocking_is_directory(uri): 84 has_children = len(set(['audio', 85 'directory']).intersection(media_types)) > 0 86 return has_children
87
88 - def get_direct_children(self, uri, l):
89 d = threads.deferToThread(self._blocking_get_direct_children, uri, l) 90 return d
91
92 - def _blocking_get_direct_children(self, uri, list_of_children):
93 """ 94 retrieve the children of uri and fills list 95 96 @param uri: the URI to analyze 97 @type uri: L{elisa.core.media_uri.MediaUri} 98 @param list_of_children: List where the children will be appended 99 @type list_of_children: list 100 101 @raise NoCDFoundError : when no CD is to be found 102 """ 103 104 path = uri 105 if self._blocking_is_directory(uri): 106 # only if it's a 'dir' 107 try: 108 import musicbrainz2.disc as mbdisc 109 import musicbrainz2.webservice as mbws 110 try: 111 disc = mbdisc.readDisc() 112 except mbdisc.DiscError, e: 113 return list_of_children 114 except ImportError, e: 115 self.warning("Could not lookup the CD online. If you want to" 116 " you have to install the python musicbrainz" 117 " library. Doing a local lookup instead") 118 return self._local_lookup(list_of_children) 119 # FIXME: is this still needed? 120 if self._discid == disc.id: 121 # we gave the children already 122 return list_of_children 123 124 self._discid = disc.id # set the discid 125 self.debug("the disc-id is: %s " % disc.id) 126 127 # refresh the tracks-cache 128 self._tracks = {} 129 try: 130 service = mbws.WebService() 131 query = mbws.Query(service) 132 filter = mbws.ReleaseFilter(discId=disc.getId()) 133 results = query.getReleases(filter) 134 if len(results) == 0: 135 raise NoCDFoundError() 136 137 selectedRelease = results[0].release 138 inc = mbws.ReleaseIncludes(artist=True, 139 tracks=True, 140 releaseEvents=True) 141 release = query.getReleaseById(selectedRelease.getId(), inc) 142 album = release.title 143 artist = release.artist.getUniqueName() 144 self.info("Found CD in Musicbrainz: %s - %s" % 145 (artist, album)) 146 isSingleArtist = release.isSingleArtistRelease() 147 148 i = 1 149 for track in release.tracks: 150 if not isSingleArtist: 151 artist = track.artist.name 152 153 title = artist + ' - ' + track.title 154 self.debug( "Processing the Track: %s" % track) 155 (minutes, seconds) = track.getDurationSplit() 156 i+=1 157 child_uri = MediaUri("cdda://%2d" % i) 158 child_uri.label = "%s (%d:%02d)" % (title, minutes, 159 seconds) 160 self._tracks[i] = (child_uri,album,artist) 161 162 except (mbws.WebServiceError, NoCDFoundError): 163 # FIXME: raise exception ? 164 self.warning("Could not look up the CD, reading it without " 165 "meta informations") 166 index = 1 167 for (offset, length) in disc.tracks: 168 child_uri = MediaUri("cdda://%s" % index) 169 child_uri.label = T_(N_("Track %d"), index) 170 self._tracks[index] = (child_uri,None,None) 171 index += 1 172 173 for track, album, artist in self._tracks.itervalues(): 174 list_of_children.append((track, 175 {'album' : album, 'artist': artist})) 176 177 return list_of_children
178
179 - def _local_lookup(self, list):
180 pipe = gst.element_factory_make('playbin') 181 pipe.set_property('uri', 'cdda://') 182 183 def got_tags(bus, mes, list): 184 if mes.type == gst.MESSAGE_TAG: 185 pipe.set_state(gst.STATE_NULL) 186 tl = mes.parse_tag() 187 if 'track-count' in tl.keys(): 188 tracks = int(tl['track-count']) 189 if tracks > 0: 190 i = 1 191 while i <= tracks: 192 uri = MediaUri('cdda://%s' % i) 193 uri.label = T_(N_("Track %s"), i) 194 list.append((uri, {})) 195 self._tracks[i] = (uri, None, None) 196 i += 1
197 198 # connect to bus message 199 pipe.get_bus().connect("message", got_tags, list) 200 pipe.get_bus().add_signal_watch() 201 202 pipe.set_state(gst.STATE_PAUSED) 203 # FIXME: block here? 204 return list
205
206 - def next_location(self, uri, root=None):
207 return threads.deferToThread(self._blocking_next_location, uri)
208
209 - def _blocking_next_location(self, uri):
210 next_uri = None 211 212 if self._blocking_is_directory(uri): 213 next_track = 1 214 else: 215 track = int(uri.host) 216 next_track = track +1 217 218 219 if self._tracks.has_key(next_track): 220 next_uri = self._tracks[next_track][0] 221 222 return next_uri
223
224 - def previous_location(self, uri):
225 return threads.deferToThread(self._blocking_previous_location, uri)
226
227 - def _blocking_previous_location(self, uri):
228 if self._is_directory(uri): 229 return None 230 231 prev_uri = None 232 track = int(uri.host) 233 prev_track = track - 1 234 235 if self._tracks.has_key(prev_track): 236 prev_uri = self._tracks[prev_track][0] 237 return prev_uri
238 239
240 - def uri_is_monitorable(self, uri):
241 return False
242
243 - def uri_is_monitored(self, uri):
244 return False
245 246 247 if __name__ == "__main__": 248 249 m = AudiocdMedia() 250 251 uri = MediaUri(u'cdda://') 252 print "is it a dir? %s" % m._is_directory(uri) 253 print "so what type is it? %s" % m.get_media_type(uri) 254 uri = MediaUri(u'cdda://1?label=Track2') 255 print "path is: %s. and host is %s" % (uri.path,uri.host) 256 print "is it a dir? %s" % m._is_directory(uri) 257 print "so what type is it? %s" % m.get_media_type(uri) 258 uri = MediaUri(u'cdda:///dev/hda/Trackly') 259 print "is it a dir? %s" % m._is_directory(uri) 260 print "so what type is it? %s" % m.get_media_type(uri) 261 uri = MediaUri(u'cdda:///dev/hda/0?label=Track2') 262 print "is it a dir? %s" % m._is_directory(uri) 263 print "so what type is it? %s" % m.get_media_type(uri) 264