63
63
def requestFinished(self, result):
64
64
""" self.connection is set in utils.ReverseProxyResource.render """
65
self.info("ProxyStream requestFinished",result)
65
self.info("ProxyStream requestFinished:",result)
66
66
if hasattr(self,'connection'):
67
67
self.connection.transport.loseConnection()
79
79
if self.stream_url is None:
81
81
web_url = "http://%s%s" % (self.host,self.path)
82
#print "web_url", web_url
82
self.info("Web_url: %s" % web_url)
84
84
def got_real_urls(real_urls):
85
got_real_url(real_urls[0])
85
if len(real_urls) == 0:
86
self.warning('Unable to retrieve any URL for video stream')
87
return self.requestFinished(None)
89
got_real_url(real_urls[0])
87
91
def got_real_url(real_url):
88
92
self.info("Real URL is %s" % real_url)
89
93
self.stream_url = real_url
90
94
if self.stream_url is None:
91
self.warning('Error to retrieve URL - inconsistent web page')
95
self.warning('Unable to retrieve URL - inconsistent web page')
92
96
return self.requestFinished(None) #FIXME
93
97
self.stream_url = self.stream_url.encode('ascii', 'strict')
94
98
self.resetUri(self.stream_url)
208
212
self.warning("Unsupported Proxy Mode: %s" % self.proxy_mode)
209
213
return self.requestFinished(None)
215
def getMimetype(self):
216
type = MPEG4_MIMETYPE
217
if self.mimetype is not None:
211
222
def renderFile(self,request,filepath):
212
223
self.info('Cache file available %r %r ' %(request, filepath))
213
224
downloadedFile = utils.StaticFile(filepath, self.mimetype)
214
downloadedFile.type = MPEG4_MIMETYPE
225
downloadedFile.type = self.getMimetype()
215
226
downloadedFile.encoding = None
216
227
return downloadedFile.render(request)
227
238
self.info("Render file", filepath, self.filesize, filesize, buffer_size)
228
239
bufferFile = utils.BufferFile(filepath, self.filesize, MPEG4_MIMETYPE)
229
bufferFile.type = MPEG4_MIMETYPE
230
#bufferFile.type = 'video/mpeg'
240
bufferFile.type = self.getMimetype()
231
241
bufferFile.encoding = None
233
243
return bufferFile.render(request)
353
364
self.item.description = self.description
354
365
self.item.date = self.date
356
if hasattr(self.parent, 'cover'):
357
self.item.albumArtURI = self.parent.cover
367
# extract thumbnail from youtube entry
368
# we take the last one, hoping this is the bigger one
370
for image in self.youtube_entry.media.thumbnail:
371
thumbnail_url = image.url
372
if thumbnail_url is not None:
373
self.item.albumArtURI = thumbnail_url
359
375
res = DIDLLite.Resource(self.url, 'http-get:*:%s:*' % self.mimetype)
360
376
res.duration = self.duration
377
393
implements = ['MediaServer']
395
description = ('Youtube', 'connects to the YouTube service and exposes the standard feeds (public) and the uploads/favorites/playlists/subscriptions of a given user.', None)
397
options = [{'option':'name', 'text':'Server Name:', 'type':'string','default':'my media','help': 'the name under this MediaServer shall show up with on other UPnP clients'},
398
{'option':'version','text':'UPnP Version:','type':'int','default':2,'enum': (2,1),'help': 'the highest UPnP version this MediaServer shall support','level':'advance'},
399
{'option':'uuid','text':'UUID Identifier:','type':'string','help':'the unique (UPnP) identifier for this MediaServer, usually automatically set','level':'advance'},
400
{'option':'refresh','text':'Refresh period','type':'string'},
401
{'option':'login','text':'User ID:','type':'string','group':'User Account'},
402
{'option':'password','text':'Password:','type':'string','group':'User Account'},
403
{'option':'location','text':'Locale:','type':'string'},
404
{'option':'quality','text':'Video quality:','type':'string', 'default':'sd','enum': ('sd','hd')},
405
{'option':'standard_feeds','text':'Include standard feeds:','type':'bool', 'default': True},
406
{'option':'proxy_mode','text':'Proxy mode:','type':'string', 'enum': ('redirect','proxy','cache','buffered')},
407
{'option':'buffer_size','text':'Buffering size:','type':'int'},
408
{'option':'cache_directory','text':'Cache directory:','type':'dir', 'group':'Cache'},
409
{'option':'cache_maxsize','text':'Cache max size:','type':'int', 'group':'Cache'},
379
412
def __init__(self, server, **kwargs):
380
413
AbstractBackendStore.__init__(self, server, **kwargs)
427
460
self.init_completed()
430
462
def __repr__(self):
431
return str(self.__class__).split('.')[-1]
463
return self.__class__.__name__
434
465
def appendFeed( self, name, feed_uri, parent):
435
466
item = LazyContainer(parent, name, None, self.refresh, self.retrieveFeedItems, feed_uri=feed_uri)
436
467
parent.add_child(item, external_id=feed_uri)