Package elisa :: Package plugins :: Package gstreamer :: Module gst_metadata

Source Code for Module elisa.plugins.gstreamer.gst_metadata

  1  # -*- coding: utf-8 -*- 
  2  # Moovida - Home multimedia server 
  3  # Copyright (C) 2006-2009 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 Moovida with Fluendo's plugins. 
 11  # 
 12  # The GPL part of Moovida is also available under a commercial licensing 
 13  # agreement from Fluendo. 
 14  # See "LICENSE.Moovida" in the root directory of this distribution package 
 15  # for details on that license. 
 16  # 
 17  # Authors: Alessandro Decina <alessandro@fluendo.com> 
 18   
 19  import gobject 
 20  gobject.threads_init() 
 21  import os 
 22   
 23  from twisted.internet import defer, reactor 
 24  from twisted.python import failure 
 25   
 26  from elisa.core.components.metadata_provider import MetadataProvider, \ 
 27          MetadataError 
 28  from elisa.core.media_uri import unquote 
 29  from elisa.core.component import InitializeFailure 
 30   
 31  from elisa.plugins.gstreamer.request import RequestQueue 
 32  from elisa.plugins.gstreamer.pipeline import GstMetadataPipeline, \ 
 33          media_type_keys, thumbnail_keys, \ 
 34          supported_keys, get_thumbnail_location 
 35   
 36  supported_schemes = ['file', 'http'] 
 37   
38 -class UriError(MetadataError):
39 pass
40
41 -def able_to_handle(supported_schemes, supported_keys, metadata):
42 uri = metadata.get('uri') 43 if not uri or uri.scheme not in supported_schemes: 44 return False 45 46 keys = set(metadata.keys()) 47 if uri.scheme == 'file' and os.path.isdir(uri.path) and \ 48 keys != media_type_keys: 49 return False 50 51 request_keys = supported_keys.intersection(metadata.keys()) 52 request_empty_keys = \ 53 [key for key in request_keys if metadata[key] is None] 54 55 if request_empty_keys: 56 return True 57 58 return False
59
60 -class GstMetadata(MetadataProvider):
61 - def __init__(self, next_interval=0.00):
62 super(GstMetadata, self).__init__() 63 self._pipeline = GstMetadataPipeline() 64 self._uri_cache = {} 65 self._requests = RequestQueue() 66 self._running = False 67 self._process_next_call = None 68 self._process_next_interval = next_interval 69 self._failed_uris = {}
70
71 - def clean(self):
72 if self._process_next_call is not None: 73 self._process_next_call.cancel() 74 self._process_next_call = None 75 self._pipeline.clean() 76 77 return super(GstMetadata, self).clean()
78
79 - def initialize(self, retself=True):
80 try: 81 self._pipeline.initialize() 82 except Exception, exc: 83 msg = "Could not initialize the Pipeline: %s" % exc 84 raise InitializeFailure(msg) 85 86 if retself: 87 return defer.succeed(self) 88 89 return defer.succeed(None)
90
91 - def _reset(self):
92 # timestamps used for logging purposes 93 pass
94
95 - def get_rank(self):
96 return 10
97
98 - def able_to_handle(self, metadata):
101
102 - def get_metadata(self, metadata):
103 blacklist_value = self._failed_uris.get(unicode(metadata['uri'])) 104 105 keys = set(metadata.keys()) 106 107 if keys == thumbnail_keys: 108 if blacklist_value == 'thumbnail-failed': 109 return defer.fail(UriError()) 110 111 location = get_thumbnail_location(metadata['uri']) 112 if os.path.exists(location): 113 stat = os.stat(location) 114 if stat.st_size != 0: 115 self.debug('thumbnail cached %s' % location) 116 metadata['thumbnail'] = location 117 return defer.succeed(metadata) 118 119 if keys == media_type_keys and blacklist_value == 'media-type-failed': 120 return defer.fail(UriError()) 121 122 dfr = self._requests.enqueue(metadata) 123 if not self._running: 124 self._running = True 125 self._process_next() 126 127 return dfr
128
129 - def _cancel_request(self, request_id):
130 request.cancelled = True
131
132 - def set_process_interval(self, value):
133 self._process_next_interval = value
134
135 - def _process_next(self):
136 if self._process_next_call is not None: 137 return 138 139 self._process_next_call = \ 140 reactor.callLater(self._process_next_interval, 141 self._process_next_real)
142
143 - def _process_next_real(self):
144 self._process_next_call = None 145 146 try: 147 request = self._requests.dequeue() 148 except IndexError: 149 self._running = False 150 self.debug('metadata queue empty') 151 152 return 153 154 self.debug('getting metadata %s, queue length %d' % 155 (request.metadata, len(self._requests))) 156 157 metadata_defer = None 158 uri = request.metadata['uri'] 159 # FIXME uri.path should probably be unquoted inside MediaUri 160 if uri.scheme == 'file' and os.path.isdir(unquote(uri.path)): 161 request.metadata['file_type'] = 'directory' 162 metadata_defer = defer.succeed(request.metadata) 163 else: 164 try: 165 metadata_defer = self._pipeline.get_metadata(request.metadata) 166 except: 167 error = failure.Failure() 168 metadata_defer = defer.fail(error) 169 170 metadata_defer.addCallbacks(self._done, self._failed, 171 callbackArgs=(request,), errbackArgs=(request,))
172
173 - def _done(self, metadata, request):
174 self._process_next() 175 # NOTE: this can't be called from the streaming thread 176 self._reset() 177 178 request.defer.callback(metadata)
179
180 - def _failed(self, failure, request):
181 self._process_next() 182 self._reset() 183 184 keys = set(request.metadata) 185 if keys == thumbnail_keys: 186 blacklist_value = 'thumbnail-failed' 187 else: 188 blacklist_value = 'media-type-failed' 189 190 self._failed_uris[unicode(request.metadata['uri'])] = blacklist_value 191 192 request.defer.errback(failure)
193
194 -class GstMetadataFast(MetadataProvider):
195 - def __init__(self):
196 super(GstMetadataFast, self).__init__() 197 self.media_type_provider = GstMetadata(0.05) 198 self.metadata_provider = GstMetadata()
199
200 - def initialize(self):
201 dfr1 = self.media_type_provider.initialize() 202 dfr2 = self.metadata_provider.initialize() 203 204 dfr = defer.DeferredList([dfr1, dfr2], fireOnOneErrback=True) 205 dfr.addCallback(lambda result: self) 206 207 return dfr
208
209 - def clean(self):
210 dfr1 = self.media_type_provider.clean() 211 dfr2 = self.metadata_provider.clean() 212 213 dfr = defer.DeferredList([dfr1, dfr2], fireOnOneErrback=True) 214 215 def parent_clean(result): 216 return super(GstMetadataFast, self).clean()
217 218 dfr.addCallbacks(parent_clean) 219 220 return dfr
221
222 - def get_rank(self):
223 return 10
224
225 - def able_to_handle(self, metadata):
226 return able_to_handle(supported_schemes, 227 supported_keys, metadata)
228
229 - def set_process_interval(self, value):
230 return self.metadata_provider.set_process_interval(value)
231
232 - def get_metadata(self, metadata):
233 req_keys = set(metadata.keys()) 234 if req_keys == media_type_keys: 235 return self.media_type_provider.get_metadata(metadata) 236 237 return self.metadata_provider.get_metadata(metadata)
238