1 from enigma import ePicLoad, eTimer, getDesktop
3 from Screens.Screen import Screen
4 from Components.AVSwitch import AVSwitch
5 from Components.config import config
6 from Components.Pixmap import Pixmap
7 from Components.ActionMap import ActionMap
9 from FTPDownloader import FTPDownloader
10 from twisted.web.client import HTTPDownloader
11 from twisted.internet import reactor
12 from urlparse import urlparse, urlunparse
14 def _parse(url, defaultPort = None):
16 parsed = urlparse(url)
18 path = urlunparse(('','')+parsed[2:])
20 if defaultPort is None:
28 host, port = parsed[1], defaultPort
31 username, host = host.split('@')
33 username, password = username.split(':')
41 host, port = host.split(':')
47 return scheme, host, port, path, username, password
49 def download(url, file, contextFactory = None, *args, **kwargs):
51 """Download a remote file from http(s) or ftp.
53 @param file: path to file on filesystem, or file-like object.
55 See HTTPDownloader to see what extra args can be passed if remote file
56 is accessible via http or https. Both Backends should offer supportPartial.
58 scheme, host, port, path, username, password = _parse(url)
61 if not (username and password):
62 username = 'anonymous'
63 password = 'my@email.com'
65 client = FTPDownloader(
75 return client.deferred
77 # We force username and password here as we lack a satisfying input method
78 if username and password:
79 from base64 import encodestring
81 # twisted will crash if we don't rewrite this ;-)
82 url = scheme + '://' + host + ':' + str(port) + path
84 basicAuth = encodestring("%s:%s" % (username, password))
85 authHeader = "Basic " + basicAuth.strip()
86 AuthHeaders = {"Authorization": authHeader}
88 if kwargs.has_key("headers"):
89 kwargs["headers"].update(AuthHeaders)
91 kwargs["headers"] = AuthHeaders
93 factory = HTTPDownloader(url, file, *args, **kwargs)
95 from twisted.internet import ssl
96 if contextFactory is None:
97 contextFactory = ssl.ClientContextFactory()
98 reactor.connectSSL(host, port, factory, contextFactory)
100 reactor.connectTCP(host, port, factory)
102 return factory.deferred
104 class PictureScreen(Screen):
106 processing = False # if fetching or converting is active
108 def __init__(self, session,title,filename, slideshowcallback = None,args=0):
109 self.slideshowcallback=slideshowcallback
110 self.screentitle = title
111 self.filename = filename
113 size_w = getDesktop(0).size().width()
114 size_h = getDesktop(0).size().height()
116 <screen position="0,0" size="%i,%i" title="%s" flags=\"wfNoBorder\">
117 <widget name="pixmap" position="0,0" size="%i,%i" backgroundColor=\"black\"/>
118 </screen>""" % (size_w,size_h,filename,size_w,size_h)
119 Screen.__init__(self, session)
121 self.picload = ePicLoad()
122 self.picload.PictureData.get().append(self.setPictureCB)
123 sc = AVSwitch().getFramebufferScale()
124 self.picload.setPara((size_w, size_h, sc[0], sc[1], False, 1, '#ff000000'))
125 self["pixmap"] = Pixmap()
129 self["actions"] = ActionMap(["WizardActions", "DirectionActions","ChannelSelectBaseActions","ShortcutActions"],
133 "green": self.AutoReloaderSwitch,
134 "yellow": self.pause,
139 self.onLayoutFinish.append(self.do)
141 def AutoReloaderSwitch(self):
142 if self.filename.startswith(("http://", "https://", "ftp://")):
143 if not self.autoreload:
144 self.autoreload = True
147 self.autoreload = False
151 self.slideshowcallback()
152 self.closetimer.start(int(config.plugins.pictureviewer.slideshowtime.value))
157 elif self.filename.startswith(("http://", "https://", "ftp://")):
158 self.fetchFile(self.filename)
160 self.sourcefile = self.filename
161 self.setPicture(self.filename)
169 if os.path.exists("/tmp/loadedfile"):
170 os.remove("/tmp/loadedfile")
174 def fetchFile(self, url):
175 self.processing = True
176 self.setTitle("loading File")
177 print "fetching URL", url
178 self.sourcefile = "/tmp/loadedfile"
179 download(url, self.sourcefile).addCallback(self.fetchFinished).addErrback(self.fetchFailed)
181 def fetchFailed(self,string):
182 print "fetch failed", string
183 self.setTitle("fetch failed: "+string)
185 def fetchFinished(self,string):
186 print "fetching finished"
187 self.setPicture(self.sourcefile)
189 def setPicture(self, string):
191 self.setTitle(self.screentitle)
193 self.setTitle(_("pause") + ":" + self.screentitle)
194 self.picload.startDecode(string)
196 def setPictureCB(self, picInfo = None):
197 ptr = self.picload.getData()
199 self["pixmap"].instance.setPixmap(ptr.__deref__())
200 self.processing = False
202 if self.autoreload is True:
205 elif self.slideshowcallback is not None:
206 self.closetimer = eTimer()
207 self.closetimer.timeout.get().append(self.slideshowcallback)
208 print "waiting", config.plugins.pictureviewer.slideshowtime.value, "seconds for next picture"
210 self.closetimer.start(int(config.plugins.pictureviewer.slideshowtime.value))
213 if not self.slideshowcallback:
216 self.closetimer.stop()
219 self.setTitle(_("pause") + ":" + self.filename.split("/")[-1])
223 self.setTitle(self.filename.split("/")[-1])
224 self.slideshowcallback()
225 self.closetimer.start(int(config.plugins.pictureviewer.slideshowtime.value))
228 if not self.slideshowcallback:
231 self.closetimer.stop()
233 self.slideshowcallback(prev = True)
236 if not self.slideshowcallback:
239 self.closetimer.stop()
241 self.slideshowcallback()