fixed typo
[enigma2-plugins.git] / webcamviewer / src / PictureScreen.py
1 from enigma import ePicLoad, eTimer, getDesktop
2
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
8
9 from FTPDownloader import FTPDownloader
10 from twisted.web.client import HTTPDownloader
11 from twisted.internet import reactor
12 from urlparse import urlparse, urlunparse
13
14 def _parse(url, defaultPort = None):
15         url = url.strip()
16         parsed = urlparse(url)
17         scheme = parsed[0]
18         path = urlunparse(('','')+parsed[2:])
19
20         if defaultPort is None:
21                 if scheme == 'https':
22                         defaultPort = 443
23                 elif scheme == 'ftp':
24                         defaultPort = 21
25                 else:
26                         defaultPort = 80
27
28         host, port = parsed[1], defaultPort
29
30         if '@' in host:
31                 username, host = host.split('@')
32                 if ':' in username:
33                         username, password = username.split(':')
34                 else:
35                         password = ""
36         else:
37                 username = ""
38                 password = ""
39
40         if ':' in host:
41                 host, port = host.split(':')
42                 port = int(port)
43
44         if path == "":
45                 path = "/"
46
47         return scheme, host, port, path, username, password
48
49 def download(url, file, contextFactory = None, *args, **kwargs):
50
51         """Download a remote file from http(s) or ftp.
52
53         @param file: path to file on filesystem, or file-like object.
54
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.
57         """
58         scheme, host, port, path, username, password = _parse(url)
59
60         if scheme == 'ftp':
61                 if not (username and password):
62                         username = 'anonymous'
63                         password = 'my@email.com'
64
65                 client = FTPDownloader(
66                         host,
67                         port,
68                         path,
69                         file,
70                         username,
71                         password,
72                         *args,
73                         **kwargs
74                 )
75                 return client.deferred
76
77         # We force username and password here as we lack a satisfying input method
78         if username and password:
79                 from base64 import encodestring
80
81                 # twisted will crash if we don't rewrite this ;-)
82                 url = scheme + '://' + host + ':' + str(port) + path
83
84                 basicAuth = encodestring("%s:%s" % (username, password))
85                 authHeader = "Basic " + basicAuth.strip()
86                 AuthHeaders = {"Authorization": authHeader}
87
88                 if kwargs.has_key("headers"):
89                         kwargs["headers"].update(AuthHeaders)
90                 else:
91                         kwargs["headers"] = AuthHeaders
92
93         factory = HTTPDownloader(url, file, *args, **kwargs)
94         if scheme == 'https':
95                 from twisted.internet import ssl
96                 if contextFactory is None:
97                         contextFactory = ssl.ClientContextFactory()
98                 reactor.connectSSL(host, port, factory, contextFactory)
99         else:
100                 reactor.connectTCP(host, port, factory)
101
102         return factory.deferred
103
104 class PictureScreen(Screen):
105         skin = ""
106         processing = False # if fetching or converting is active
107         autoreload = False
108         def __init__(self, session,title,filename, slideshowcallback = None,args=0):
109                 self.slideshowcallback=slideshowcallback
110                 self.screentitle = title
111                 self.filename = filename
112
113                 size_w = getDesktop(0).size().width()
114                 size_h = getDesktop(0).size().height()
115                 self.skin = """
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)
120
121                 self.picload = ePicLoad()
122                 self.picload_conn = self.picload.PictureData.connect(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()
126
127                 self.paused = False
128
129                 self["actions"] = ActionMap(["WizardActions", "DirectionActions","ChannelSelectBaseActions","ShortcutActions"],
130                         {
131                          "ok": self.do,
132                          "back": self.exit,
133                          "green": self.AutoReloaderSwitch,
134                          "yellow": self.pause,
135                          "red": self.prev,
136                          "blue": self.next,
137                          }, -1)
138
139                 self.onLayoutFinish.append(self.do)
140
141         def AutoReloaderSwitch(self):
142                 if self.filename.startswith(("http://", "https://", "ftp://")):
143                         if not self.autoreload:
144                                 self.autoreload = True
145                                 self.do()
146                         else:
147                                 self.autoreload = False
148
149                 if self.paused:
150                         self.paused = False
151                         self.slideshowcallback()
152                         self.closetimer.start(int(config.plugins.pictureviewer.slideshowtime.value))
153
154         def do(self):
155                 if self.processing:
156                         pass
157                 elif self.filename.startswith(("http://", "https://", "ftp://")):
158                         self.fetchFile(self.filename)
159                 else:
160                         self.sourcefile = self.filename
161                         self.setPicture(self.filename)
162
163         def exit(self):
164                 self.cleanUP()
165                 self.close()
166
167         def cleanUP(self):
168                 try:
169                         if os.path.exists("/tmp/loadedfile"):
170                                 os.remove("/tmp/loadedfile")
171                 except:## OSerror??
172                         pass
173
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)
180
181         def fetchFailed(self,string):
182                 print "fetch failed", string
183                 self.setTitle("fetch failed: "+string)
184
185         def fetchFinished(self,string):
186                 print "fetching finished"
187                 self.setPicture(self.sourcefile)
188
189         def setPicture(self, string):
190                 if not self.paused:
191                         self.setTitle(self.screentitle)
192                 else:
193                         self.setTitle(_("pause") + ":" + self.screentitle)
194                 self.picload.startDecode(string)
195
196         def setPictureCB(self, picInfo = None):
197                 ptr = self.picload.getData()
198                 if ptr is not None:
199                         self["pixmap"].instance.setPixmap(ptr)
200                 self.processing = False
201
202                 if self.autoreload is True:
203                                 self.cleanUP()
204                                 self.do()
205                 elif self.slideshowcallback is not None:
206                                 self.closetimer = eTimer()
207                                 self.closetimer_conn = self.closetimer.timeout.connect(self.slideshowcallback)
208                                 print "waiting", config.plugins.pictureviewer.slideshowtime.value, "seconds for next picture"
209                                 if not self.paused:
210                                         self.closetimer.start(int(config.plugins.pictureviewer.slideshowtime.value))
211
212         def pause(self):
213                 if not self.slideshowcallback:
214                         return
215                 if not self.paused:
216                         self.closetimer.stop()
217                         self.paused = True
218
219                         self.setTitle(_("pause") + ":" + self.filename.split("/")[-1])
220                 else:
221                         self.paused = False
222
223                         self.setTitle(self.filename.split("/")[-1])
224                         self.slideshowcallback()
225                         self.closetimer.start(int(config.plugins.pictureviewer.slideshowtime.value))
226
227         def prev(self):
228                 if not self.slideshowcallback:
229                         return
230                 if not self.paused:
231                         self.closetimer.stop()
232                         self.paused = True
233                 self.slideshowcallback(prev = True)
234
235         def next(self):
236                 if not self.slideshowcallback:
237                         return
238                 if not self.paused:
239                         self.closetimer.stop()
240                         self.paused = True
241                 self.slideshowcallback()
242