allow ftp sources, remove stray whitespaces and use tabs for indentation
[enigma2-plugins.git] / webcamviewer / src / PictureScreen.py
1 from enigma import loadPic
2 from enigma import eTimer
3 from enigma import getDesktop
4
5 from Screens.Screen import Screen
6 from Components.AVSwitch import AVSwitch
7 from Components.config import config
8 from Components.Pixmap import Pixmap
9 from Components.ActionMap import ActionMap
10
11 from FTPDownloader import FTPDownloader
12 from twisted.web.client import HTTPDownloader
13 from twisted.internet import reactor
14 from urlparse import urlparse, urlunparse
15
16 def _parse(url, defaultPort = None):
17         url = url.strip()
18         parsed = urlparse(url)
19         scheme = parsed[0]
20         path = urlunparse(('','')+parsed[2:])
21
22         if defaultPort is None:
23                 if scheme == 'https':
24                         defaultPort = 443
25                 elif scheme == 'ftp':
26                         defaultPort = 21
27                 else:
28                         defaultPort = 80
29
30         host, port = parsed[1], defaultPort
31
32         if '@' in host:
33                 username, host = host.split('@')
34                 if ':' in username:
35                         username, password = username.split(':')
36                 else:
37                         password = ""
38         else:
39                 username = ""
40                 password = ""
41
42         if ':' in host:
43                 host, port = host.split(':')
44                 port = int(port)
45
46         if path == "":
47                 path = "/"
48
49         return scheme, host, port, path, username, password
50
51 def download(url, file, contextFactory = None, *args, **kwargs):
52
53         """Download a remote file from http(s) or ftp.
54
55         @param file: path to file on filesystem, or file-like object.
56
57         See HTTPDownloader to see what extra args can be passed if remote file
58         is accessible via http or https. Both Backends should offer supportPartial.
59         """
60         scheme, host, port, path, username, password = _parse(url)
61
62         if scheme == 'ftp':
63                 if not (username and password):
64                         username = 'anonymous'
65                         password = 'my@email.com'
66
67                 client = FTPDownloader(
68                         host,
69                         port,
70                         path,
71                         file,
72                         username,
73                         password,
74                         *args,
75                         **kwargs
76                 )
77                 return client.deferred
78
79         # We force username and password here as we lack a satisfying input method
80         if username and password:
81                 from base64 import encodestring
82
83                 # twisted will crash if we don't rewrite this ;-)
84                 url = scheme + '://' + host + ':' + str(port) + path
85
86                 basicAuth = encodestring("%s:%s" % (username, password))
87                 authHeader = "Basic " + basicAuth.strip()
88                 AuthHeaders = {"Authorization": authHeader}
89
90                 if kwargs.has_key("headers"):
91                         kwargs["headers"].update(AuthHeaders)
92                 else:
93                         kwargs["headers"] = AuthHeaders
94
95         factory = HTTPDownloader(url, file, *args, **kwargs)
96         if scheme == 'https':
97                 from twisted.internet import ssl
98                 if contextFactory is None:
99                         contextFactory = ssl.ClientContextFactory()
100                 reactor.connectSSL(host, port, factory, contextFactory)
101         else:
102                 reactor.connectTCP(host, port, factory)
103
104         return factory.deferred
105
106 class PictureScreen(Screen):
107         skin = ""
108         prozessing =False # if fetching or converting is active
109         autoreload =False
110         def __init__(self, session,title,filename, slideshowcallback = None,args=0):
111                 self.slideshowcallback=slideshowcallback
112                 self.screentitle = title
113                 ##
114                 size_w = getDesktop(0).size().width()
115                 size_h = getDesktop(0).size().height()
116                 self.skin = """
117                 <screen position="0,0" size="%i,%i" title="%s" flags=\"wfNoBorder\">
118                          <widget name="pixmap" position="0,0" size="%i,%i" backgroundColor=\"black\"/>
119                 </screen>""" % (size_w,size_h,filename,size_w,size_h)
120                 Screen.__init__(self, session)
121                 self.filename = filename
122                 self["pixmap"] = Pixmap()
123
124                 self["actions"] = ActionMap(["WizardActions", "DirectionActions","ChannelSelectBaseActions","ShortcutActions"],
125                         {
126                          "ok": self.do,
127                          "back": self.exit,
128                          "green":self.AutoReloaderSwitch,
129                          }, -1)
130
131                 self.onLayoutFinish.append(self.do)
132
133         def AutoReloaderSwitch(self):
134                 if self.filename.startswith("http") or self.filename.startswith("ftp"):
135                         if self.autoreload is False:
136                                 self.autoreload = True
137                                 self.do()
138                         else:
139                                 self.autoreload = False
140
141         def do(self):
142                 if self.prozessing:
143                         pass
144                 elif self.filename.startswith("http") or self.filename.startswith("ftp"):
145                         self.fetchFile(self.filename)
146                 else:
147                         self.sourcefile = self.filename
148                         self.setPicture(self.filename)
149
150         def exit(self):
151                 self.cleanUP()
152                 self.close()
153
154         def cleanUP(self):
155                 try:
156                         if os.path.exists("/tmp/loadedfile"):
157                                 os.remove("/tmp/loadedfile")
158                 except:## OSerror??
159                         pass
160
161         def fetchFile(self,url):
162                 self.prozessing =True
163                 self.setTitle("loading File")
164                 print "fetching URL ",url
165                 self.sourcefile = "/tmp/loadedfile"
166                 download(url,self.sourcefile).addCallback(self.fetchFinished).addErrback(self.fetchFailed)
167
168         def fetchFailed(self,string):
169                 print "fetch failed",string
170                 self.setTitle( "fetch failed: "+string)
171
172         def fetchFinished(self,string):
173                 print "fetching finished "
174                 self.setPicture(self.sourcefile)
175
176         def setPicture(self,string):
177                 self.setTitle(self.filename.split("/")[-1])
178                 pixmap = loadPic(string,getDesktop(0).size().width(),getDesktop(0).size().height(), AVSwitch().getAspectRatioSetting()/2,1, 0,1)
179                 if pixmap is not None:
180                         self["pixmap"].instance.setPixmap(pixmap)
181                 self.prozessing =False
182
183                 if self.autoreload is True:
184                                 self.cleanUP()
185                                 self.do()
186                 elif self.slideshowcallback is not None:
187                                 self.closetimer = eTimer()
188                                 self.closetimer.timeout.get().append(self.slideshowcallback)
189                                 print "waiting ",config.plugins.pictureviewer.slideshowtime.value," seconds for next picture"
190                                 self.closetimer.start(int(config.plugins.pictureviewer.slideshowtime.value))
191