update some missing plugin icons (and some minor cleanups)
[enigma2-plugins.git] / mytube / src / MyTubeSearch.py
1 from enigma import eTimer, ePythonMessagePump
2 from MyTubeService import GoogleSuggestions
3 from Screens.Screen import Screen
4 from Components.config import config, ConfigText
5 from Components.config import KEY_DELETE, KEY_BACKSPACE, KEY_ASCII, KEY_TIMEOUT
6 from Components.ActionMap import ActionMap
7 from Components.Button import Button
8 from Components.Label import Label
9 from Components.Sources.List import List
10 from Components.Task import job_manager
11 from Tools.Directories import resolveFilename, SCOPE_HDD
12
13 from threading import Thread
14 from ThreadQueue import ThreadQueue
15
16 #import urllib
17 from urllib import FancyURLopener
18 import json
19
20 class MyOpener(FancyURLopener):
21         version = 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.12) Gecko/20070731 Ubuntu/dapper-security Firefox/1.5.0.12'
22
23 class SuggestionsQueryThread(Thread):
24         def __init__(self, query, param, callback, errorback):
25                 Thread.__init__(self)
26                 self.messagePump = ePythonMessagePump()
27                 self.messages = ThreadQueue()
28                 self.query = query
29                 self.param = param
30                 self.callback = callback
31                 self.errorback = errorback
32                 self.canceled = False
33                 self.messagePump_conn = self.messagePump.recv_msg.connect(self.finished)
34
35         def cancel(self):
36                 self.canceled = True
37
38         def run(self):
39                 if self.param not in (None, ""):
40                         try:
41                                 suggestions = self.query.getSuggestions(self.param)
42                                 self.messages.push((suggestions, self.callback))
43                                 self.messagePump.send(0)
44                         except Exception, ex:
45                                 self.messages.push((ex, self.errorback))
46                                 self.messagePump.send(0)
47
48         def finished(self, val):
49                 if not self.canceled:
50                         message = self.messages.pop()
51                         message[1](message[0])
52
53 class ConfigTextWithGoogleSuggestions(ConfigText):
54         def __init__(self, default = "", fixed_size = True, visible_width = False):
55                 ConfigText.__init__(self, default, fixed_size, visible_width)
56                 self.suggestions = GoogleSuggestions()
57                 self.suggestionsThread = None
58                 self.suggestionsThreadRunning = False
59                 self.suggestionsListActivated = False
60
61         def prepareSuggestionsThread(self):
62                 self.suggestions.hl = "en"
63                 if config.plugins.mytube.search.lr.value is not None:
64                         self.suggestions.hl=config.plugins.mytube.search.lr.value
65
66         def suggestionsThreadStarted(self):
67                 if self.suggestionsThreadRunning:
68                         self.cancelSuggestionsThread()
69                 self.suggestionsThreadRunning = True
70
71         def suggestionsThreadFinished(self):
72                 self.suggestionsThreadRunning = False
73
74         def cancelSuggestionsThread(self):
75                 if self.suggestionsThread is not None:
76                         self.suggestionsThread.cancel()
77                 self.suggestionsThreadFinished()
78
79         def propagateSuggestions(self, suggestionsList):
80                 self.cancelSuggestionsThread()
81                 print "[MyTube - ConfigTextWithGoogleSuggestions] propagateSuggestions:",suggestionsList
82                 if self.suggestionsWindow:
83                         self.suggestionsWindow.update(suggestionsList)
84
85         def gotSuggestionsError(self, val):
86                 print "[MyTube - ConfigTextWithGoogleSuggestions] gotSuggestionsError:",val
87
88         def getSuggestions(self):
89                 self.prepareSuggestionsThread()
90                 self.suggestionsThreadStarted()
91                 self.suggestionsThread = SuggestionsQueryThread(self.suggestions, self.value, self.propagateSuggestions, self.gotSuggestionsError)
92                 self.suggestionsThread.start()
93
94         def handleKey(self, key):
95                 if not self.suggestionsListActivated:
96                         ConfigText.handleKey(self, key)
97                         if key in [KEY_DELETE, KEY_BACKSPACE, KEY_ASCII, KEY_TIMEOUT]:
98                                 self.getSuggestions()
99
100         def onSelect(self, session):
101                 ConfigText.onSelect(self, session)
102                 if session is not None:
103                         self.suggestionsWindow = session.instantiateDialog(MyTubeSuggestionsListScreen, self, zPosition=1000)
104                         self.suggestionsWindow.deactivate()
105                         self.suggestionsWindow.hide()
106                 self.getSuggestions()
107
108         def onDeselect(self, session):
109                 self.cancelSuggestionsThread()
110                 ConfigText.onDeselect(self, session)
111                 if self.suggestionsWindow:
112                         session.deleteDialog(self.suggestionsWindow)
113                         self.suggestionsWindow = None
114
115         def suggestionListUp(self):
116                 if self.suggestionsWindow.getlistlenght() > 0:
117                         self.value = self.suggestionsWindow.up()
118
119         def suggestionListDown(self):
120                 if self.suggestionsWindow.getlistlenght() > 0:
121                         self.value = self.suggestionsWindow.down()
122
123         def suggestionListPageDown(self):
124                 if self.suggestionsWindow.getlistlenght() > 0:
125                         self.value = self.suggestionsWindow.pageDown()
126
127         def suggestionListPageUp(self):
128                 if self.suggestionsWindow.getlistlenght() > 0:
129                         self.value = self.suggestionsWindow.pageUp()
130
131         def activateSuggestionList(self):
132                 ret = False
133                 if self.suggestionsWindow is not None and self.suggestionsWindow.shown:
134                         self.tmpValue = self.value
135                         self.value = self.suggestionsWindow.activate()
136                         self.allmarked = False
137                         self.suggestionsListActivated = True
138                         ret = True
139                 return ret
140
141         def deactivateSuggestionList(self):
142                 ret = False
143                 if self.suggestionsWindow is not None:
144                         self.suggestionsWindow.deactivate()
145                         self.getSuggestions()
146                         self.allmarked = True
147                         self.suggestionsListActivated = False
148                         ret = True
149                 return ret
150
151         def cancelSuggestionList(self):
152                 self.value = self.tmpValue
153                 return self.deactivateSuggestionList()
154
155         def enableSuggestionSelection(self,value):
156                 if self.suggestionsWindow is not None:
157                         self.suggestionsWindow.enableSelection(value)
158
159 default = resolveFilename(SCOPE_HDD)
160 tmp = config.movielist.videodirs.value
161 if default not in tmp:
162         tmp.append(default)
163
164 class MyTubeSuggestionsListScreen(Screen):
165         skin = """
166                 <screen name="MyTubeSuggestionsListScreen" position="center,205" size="920,450" zPosition="6" title="MyTube - Search" flags="wfNoBorder">
167                 <widget source="suggestionslist" render="Listbox" position="10,10" size="900,270" zPosition="2" enableWrapAround="1" scrollbarMode="showOnDemand">
168                         <convert type="TemplatedMultiContent">
169                                 {"template": [
170                                 MultiContentEntryText(pos=(5,2),size=(590,26),font=0,flags=RT_HALIGN_LEFT,text=0),# index 0 is the name
171                                 MultiContentEntryText(pos=(610,2),size=(300,26),font=1,flags=RT_HALIGN_RIGHT,text=1),# index 1 are the rtesults
172                                 ],
173                                 "fonts": [gFont("Regular",22),gFont("Regular",18)],
174                                 "itemHeight": 30
175                                 }
176                         </convert>
177                 </widget>
178         </screen>"""
179
180         def __init__(self, session, configTextWithGoogleSuggestion):
181                 Screen.__init__(self, session)
182                 self.activeState = False
183                 self.list = []
184                 self.suggestlist = []
185                 self["suggestionslist"] = List(self.list)
186                 self.configTextWithSuggestion = configTextWithGoogleSuggestion
187
188         def update(self, suggestions):
189                 if suggestions and len(suggestions) > 0:
190                         if not self.shown:
191                                 self.show()
192                         suggestions_tree = json.loads(str(suggestions[20:-1]))
193                         if suggestions_tree:
194                                 self.list = []
195                                 self.suggestlist = []
196                                 suggested = suggestions_tree[1]
197                                 count = 0
198                                 if suggested:
199                                         suggestrelevance = suggestions_tree[4]["google:suggestrelevance"]
200                                         suggesttype = suggestions_tree[4]["google:suggesttype"]
201                                         for suggest in suggested:
202                                                 name = None
203                                                 numresults = None
204                                                 if suggesttype[count] == u'NAVIGATION':
205                                                         count +=1
206                                                         continue
207                                                 name = str(suggest)
208                                                 numresults = suggestrelevance[count]
209                                                 if name and numresults:
210                                                         self.suggestlist.append((name, numresults ))
211                                                 count +=1
212                                 """for suggestion in suggestions_tree.findall("CompleteSuggestion"):
213                                         name = None
214                                         numresults = None
215                                         for subelement in suggestion:
216                                                 if subelement.attrib.has_key('data'):
217                                                         name = subelement.attrib['data'].encode("UTF-8")
218                                                 if subelement.attrib.has_key('int'):
219                                                         numresults = subelement.attrib['int']
220                                                 if name and numresults:
221                                                         self.suggestlist.append((name, numresults ))"""
222                                 if len(self.suggestlist):
223                                         self.suggestlist.sort(key=lambda x: int(x[1]))
224                                         self.suggestlist.reverse()
225                                         for entry in self.suggestlist:
226                                                 self.list.append((entry[0], str(entry[1]) + _(" Results") ))
227                                         self["suggestionslist"].setList(self.list)
228                                         self["suggestionslist"].setIndex(0)
229                 else:
230                         self.hide()
231
232         def getlistlenght(self):
233                 return len(self.list)
234
235         def up(self):
236                 print "up"
237                 if self.list and len(self.list) > 0:
238                         self["suggestionslist"].selectPrevious()
239                         return self.getSelection()
240
241         def down(self):
242                 print "down"
243                 if self.list and len(self.list) > 0:
244                         self["suggestionslist"].selectNext()
245                         return self.getSelection()
246
247         def pageUp(self):
248                 print "up"
249                 if self.list and len(self.list) > 0:
250                         self["suggestionslist"].selectPrevious()
251                         return self.getSelection()
252
253         def pageDown(self):
254                 print "down"
255                 if self.list and len(self.list) > 0:
256                         self["suggestionslist"].selectNext()
257                         return self.getSelection()
258
259         def activate(self):
260                 print "activate"
261                 self.activeState = True
262                 return self.getSelection()
263
264         def deactivate(self):
265                 print "deactivate"
266                 self.activeState = False
267                 return self.getSelection()
268
269         def getSelection(self):
270                 if self["suggestionslist"].getCurrent() is None:
271                         return None
272                 print self["suggestionslist"].getCurrent()[0]
273                 return self["suggestionslist"].getCurrent()[0]
274
275         def enableSelection(self,value):
276                 self["suggestionslist"].selectionEnabled(value)
277
278 class MyTubeTasksScreen(Screen):
279         skin = """
280                 <screen name="MyTubeTasksScreen" position="center,120" size="920,520" title="MyTube - Tasks">
281                 <ePixmap pixmap="skin_default/buttons/red.png" position="10,5" size="200,40" alphatest="on"/>
282                 <widget name="key_red" position="10,5" size="200,40" zPosition="1" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" shadowColor="black" shadowOffset="-2,-2"/>
283                 <eLabel position="10,50" size="900,1" backgroundColor="grey"/>
284                 <widget source="tasklist" render="Listbox" position="10,60" size="900,450" enableWrapAround="1" scrollbarMode="showOnDemand">
285                         <convert type="TemplatedMultiContent">
286                                 {"template": [
287                                 MultiContentEntryText(pos=(10,2),size=(420,25),flags=RT_HALIGN_LEFT,text=1),# index 1 is the name
288                                 MultiContentEntryText(pos=(440,2),size=(160,25),flags=RT_HALIGN_RIGHT,text=2),# index 2 is the state
289                                 MultiContentEntryProgress(pos=(630,5),size=(150,20),percent=-3),# index 3 should be progress
290                                 MultiContentEntryText(pos=(790,2),size=(80,25),flags=RT_HALIGN_RIGHT,text=4),# index 4 is the percentage
291                                 ],
292                                 "fonts": [gFont("Regular",21)],
293                                 "itemHeight": 30
294                                 }
295                         </convert>
296                 </widget>
297                 <widget name="title" position="0,0" size="0,0"/>
298         </screen>"""
299
300         def __init__(self, session, plugin_path, tasklist):
301                 Screen.__init__(self, session)
302                 self.skin_path = plugin_path
303                 self.session = session
304                 self.tasklist = tasklist
305                 self["tasklist"] = List(self.tasklist)
306
307                 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions", "MediaPlayerActions"],
308                 {
309                         "ok": self.keyOK,
310                         "back": self.keyCancel,
311                         "red": self.keyCancel,
312                 }, -1)
313
314                 self["key_red"] = Button(_("Close"))
315                 self["title"] = Label()
316
317                 self.onLayoutFinish.append(self.layoutFinished)
318                 self.onShown.append(self.setWindowTitle)
319                 self.onClose.append(self.__onClose)
320                 self._searchTimer = eTimer()
321                 self.__searchTimer_conn = self._searchTimer.timeout.connect(self.TimerFire)
322
323         def __onClose(self):
324                 del self._searchTimer
325
326         def layoutFinished(self):
327                 self["title"].setText(_("MyTubePlayer active video downloads"))
328                 self._searchTimer.startLongTimer(2)
329
330         def TimerFire(self):
331                 self._searchTimer.stop()
332                 self.rebuildTaskList()
333
334         def rebuildTaskList(self):
335                 self.tasklist = []
336                 for job in job_manager.getPendingJobs():
337                         self.tasklist.append((job,job.name,job.getStatustext(),int(100*job.progress/float(job.end)) ,str(100*job.progress/float(job.end)) + "%" ))
338                 self['tasklist'].setList(self.tasklist)
339                 self['tasklist'].updateList(self.tasklist)
340                 self._searchTimer.startLongTimer(2)
341
342         def setWindowTitle(self):
343                 self.setTitle(_("MyTubePlayer active video downloads"))
344
345         def keyOK(self):
346                 current = self["tasklist"].getCurrent()
347                 print current
348                 if current:
349                         job = current[0]
350                         from Screens.TaskView import JobView
351                         self.session.openWithCallback(self.JobViewCB, JobView, job)
352
353         def JobViewCB(self, why):
354                 print "WHY---",why
355
356         def keyCancel(self):
357                 self.close()
358
359         def keySave(self):
360                 self.close()
361
362
363 class MyTubeHistoryScreen(Screen):
364         skin = """
365                 <screen name="MyTubeHistoryScreen" position="center,205" size="920,450" zPosition="6" title="MyTube - History" flags="wfNoBorder">
366                 <widget source="historylist" render="Listbox" position="10,10" size="900,420" zPosition="2" enableWrapAround="1" scrollbarMode="showOnDemand">
367                         <convert type="TemplatedMultiContent">
368                                 {"template": [
369                                 MultiContentEntryText(pos=(5,2),size=(900,26),flags=RT_HALIGN_LEFT,text=0),# index 0 is the name
370                                 ],
371                                 "fonts": [gFont("Regular",22)],
372                                 "itemHeight": 30
373                                 }
374                         </convert>
375                 </widget>
376         </screen>"""
377
378         def __init__(self, session):
379                 Screen.__init__(self, session)
380                 self.session = session
381                 self.historylist = []
382                 print "self.historylist",self.historylist
383                 self["historylist"] = List(self.historylist)
384                 self.activeState = False
385
386         def activate(self):
387                 print "activate"
388                 self.activeState = True
389                 self.history = config.plugins.mytube.general.history.value.split(',')
390                 if self.history[0] == '':
391                         del self.history[0]
392                 print "self.history",self.history
393                 self.historylist = []
394                 for entry in self.history:
395                         self.historylist.append(( str(entry),))
396                 self["historylist"].setList(self.historylist)
397                 self["historylist"].updateList(self.historylist)
398
399         def deactivate(self):
400                 print "deactivate"
401                 self.activeState = False
402
403         def status(self):
404                 print self.activeState
405                 return self.activeState
406
407         def getSelection(self):
408                 if self["historylist"].getCurrent() is None:
409                         return None
410                 print self["historylist"].getCurrent()[0]
411                 return self["historylist"].getCurrent()[0]
412
413         def up(self):
414                 print "up"
415                 self["historylist"].selectPrevious()
416                 return self.getSelection()
417
418         def down(self):
419                 print "down"
420                 self["historylist"].selectNext()
421                 return self.getSelection()
422
423         def pageUp(self):
424                 print "up"
425                 self["historylist"].selectPrevious()
426                 return self.getSelection()
427
428         def pageDown(self):
429                 print "down"
430                 self["historylist"].selectNext()
431                 return self.getSelection()
432