MyTube: Fix sorting of search results
[enigma2-plugins.git] / mytube / src / plugin.py
1 from Components.AVSwitch import AVSwitch
2 from Components.ActionMap import ActionMap
3 from Components.Button import Button
4 from Components.ConfigList import ConfigListScreen
5 from Components.Label import Label
6 from Components.MultiContent import MultiContentEntryText, MultiContentEntryPixmapAlphaTest
7 from Components.Pixmap import Pixmap
8 from Components.ProgressBar import ProgressBar
9 from Components.ScrollLabel import ScrollLabel
10 from Components.ServiceEventTracker import ServiceEventTracker
11 from Components.Sources.List import List
12 from Components.Task import Task, Job, job_manager
13 from Components.config import config, ConfigSelection, ConfigSubsection, ConfigText, ConfigYesNo, getConfigListEntry, ConfigPassword
14 #, ConfigIP, ConfigNumber, ConfigLocations
15 from Screens.ChoiceBox import ChoiceBox
16 from Screens.InfoBarGenerics import InfoBarNotifications, InfoBarSeek
17 from Screens.MessageBox import MessageBox
18 from Screens.Screen import Screen
19 from Screens.VirtualKeyBoard import VirtualKeyBoard
20 from Tools.BoundFunction import boundFunction
21 from Tools.Directories import resolveFilename, SCOPE_HDD, SCOPE_CURRENT_PLUGIN
22 from Tools.Downloader import downloadWithProgress
23 from Tools.Log import Log
24
25 from Plugins.Plugin import PluginDescriptor
26
27 from MyTubeSearch import ConfigTextWithGoogleSuggestions, MyTubeSettingsScreen, MyTubeTasksScreen, MyTubeHistoryScreen
28 from MyTubeService import validate_cert, get_rnd, myTubeService
29 from Plugins.SystemPlugins.TubeLib.youtube.Search import Search
30
31 from __init__ import decrypt_block
32
33 from enigma import eTPM, eTimer, ePoint, RT_HALIGN_LEFT, RT_VALIGN_CENTER, gFont, ePicLoad, eServiceReference, iPlayableService
34 from os import path as os_path, remove as os_remove
35 from twisted.web import client
36
37 etpm = eTPM()
38 rootkey = ['\x9f', '|', '\xe4', 'G', '\xc9', '\xb4', '\xf4', '#', '&', '\xce', '\xb3', '\xfe', '\xda', '\xc9', 'U', '`', '\xd8', '\x8c', 's', 'o', '\x90', '\x9b', '\\', 'b', '\xc0', '\x89', '\xd1', '\x8c', '\x9e', 'J', 'T', '\xc5', 'X', '\xa1', '\xb8', '\x13', '5', 'E', '\x02', '\xc9', '\xb2', '\xe6', 't', '\x89', '\xde', '\xcd', '\x9d', '\x11', '\xdd', '\xc7', '\xf4', '\xe4', '\xe4', '\xbc', '\xdb', '\x9c', '\xea', '}', '\xad', '\xda', 't', 'r', '\x9b', '\xdc', '\xbc', '\x18', '3', '\xe7', '\xaf', '|', '\xae', '\x0c', '\xe3', '\xb5', '\x84', '\x8d', '\r', '\x8d', '\x9d', '2', '\xd0', '\xce', '\xd5', 'q', '\t', '\x84', 'c', '\xa8', ')', '\x99', '\xdc', '<', '"', 'x', '\xe8', '\x87', '\x8f', '\x02', ';', 'S', 'm', '\xd5', '\xf0', '\xa3', '_', '\xb7', 'T', '\t', '\xde', '\xa7', '\xf1', '\xc9', '\xae', '\x8a', '\xd7', '\xd2', '\xcf', '\xb2', '.', '\x13', '\xfb', '\xac', 'j', '\xdf', '\xb1', '\x1d', ':', '?']
39
40 config.plugins.mytube = ConfigSubsection()
41 config.plugins.mytube.search = ConfigSubsection()
42
43
44 config.plugins.mytube.search.searchTerm = ConfigTextWithGoogleSuggestions("", False)
45 config.plugins.mytube.search.orderBy = ConfigSelection(
46                                 [
47                                  ("relevance", _("Relevance")),
48                                  ("viewCount", _("View Count")),
49                                  ("date", _("Published")),
50                                  ("rating", _("Rating"))
51                                 ], "relevance")
52 config.plugins.mytube.search.time = ConfigSelection(
53                                 [
54                                  ("all_time", _("All Time")),
55                                  ("this_month", _("This Month")),
56                                  ("this_week", _("This Week")),
57                                  ("today", _("Today"))
58                                 ], "all_time")
59 config.plugins.mytube.search.safeSearch = ConfigSelection(
60                                 [
61                                  (Search.SAFE_SEARCH_NONE, _("No")),
62                                  (Search.SAFE_SEARCH_MODERATE, _("Moderately")),
63                                  (Search.SAFE_SEARCH_STRICT, _("Strictly")),
64                                 ], Search.SAFE_SEARCH_NONE)
65 config.plugins.mytube.search.categories = ConfigSelection(
66                                 [
67                                  (None, _("All")),
68                                  ("Film", _("Film & Animation")),
69                                  ("Autos", _("Autos & Vehicles")),
70                                  ("Music", _("Music")),
71                                  ("Animals", _("Pets & Animals")),
72                                  ("Sports", _("Sports")),
73                                  ("Travel", _("Travel & Events")),
74                                  ("Shortmov", _("Short Movies")),
75                                  ("Games", _("Gaming")),
76                                  ("Comedy", _("Comedy")),
77                                  ("People", _("People & Blogs")),
78                                  ("News", _("News & Politics")),
79                                  ("Entertainment", _("Entertainment")),
80                                  ("Education", _("Education")),
81                                  ("Howto", _("Howto & Style")),
82                                  ("Nonprofit", _("Nonprofits & Activism")),
83                                  ("Tech", _("Science & Technology"))
84                                 ], None)
85 config.plugins.mytube.search.lr = ConfigSelection(
86                                 [
87                                  ("au", _("Australia")),
88                                  ("br", _("Brazil")),
89                                  ("ca", _("Canada")),
90                                  ("cz", _("Czech Republic")),
91                                  ("fr", _("France")),
92                                  ("de", _("Germany")),
93                                  ("gb", _("Great Britain")),
94                                  ("au", _("Australia")),
95                                  ("nl", _("Holland")),
96                                  ("hk", _("Hong Kong")),
97                                  ("in", _("India")),
98                                  ("ie", _("Ireland")),
99                                  ("il", _("Israel")),
100                                  ("it", _("Italy")),
101                                  ("jp", _("Japan")),
102                                  ("mx", _("Mexico")),
103                                  ("nz", _("New Zealand")),
104                                  ("pl", _("Poland")),
105                                  ("ru", _("Russia")),
106                                  ("kr", _("South Korea")),
107                                  ("es", _("Spain")),
108                                  ("se", _("Sweden")),
109                                  ("tw", _("Taiwan")),
110                                  ("us", _("United States"))
111                                 ], "de")
112
113 config.plugins.mytube.general = ConfigSubsection()
114 config.plugins.mytube.general.showHelpOnOpen = ConfigYesNo(default = True)
115 config.plugins.mytube.general.loadFeedOnOpen = ConfigYesNo(default = True)
116 config.plugins.mytube.general.startFeed = ConfigSelection(
117                                 [
118                                  ("top_rated", _("Top rated")),
119                                 ], "top_rated")
120 config.plugins.mytube.general.on_movie_stop = ConfigSelection(default = "ask", choices = [
121         ("ask", _("Ask user")), ("quit", _("Return to movie list")), ("playnext", _("Play next video")), ("playagain", _("Play video again")) ])
122
123 config.plugins.mytube.general.on_exit = ConfigSelection(default = "ask", choices = [
124         ("ask", _("Ask user")), ("quit", _("Return to movie list"))])
125
126 default = resolveFilename(SCOPE_HDD)
127 tmp = config.movielist.videodirs.value
128 if default not in tmp:
129         tmp.append(default)
130 config.plugins.mytube.general.videodir = ConfigSelection(default = default, choices = tmp)
131 config.plugins.mytube.general.history = ConfigText(default="")
132 config.plugins.mytube.general.clearHistoryOnClose = ConfigYesNo(default = False)
133 config.plugins.mytube.general.AutoLoadFeeds = ConfigYesNo(default = True)
134 config.plugins.mytube.general.resetPlayService = ConfigYesNo(default = False)
135 config.plugins.mytube.general.username = ConfigText(default="", fixed_size = False)
136 config.plugins.mytube.general.password = ConfigPassword(default="")
137 #config.plugins.mytube.general.useHTTPProxy = ConfigYesNo(default = False)
138 #config.plugins.mytube.general.ProxyIP = ConfigIP(default=[0,0,0,0])
139 #config.plugins.mytube.general.ProxyPort = ConfigNumber(default=8080)
140
141
142 class downloadJob(Job):
143         def __init__(self, url, file, title):
144                 Job.__init__(self, title)
145                 downloadTask(self, url, file)
146
147 class downloadTask(Task):
148         def __init__(self, job, url, file):
149                 Task.__init__(self, job, ("download task"))
150                 self.end = 100
151                 self.url = url
152                 self.local = file
153
154         def prepare(self):
155                 self.error = None
156
157         def run(self, callback):
158                 self.callback = callback
159                 self.download = downloadWithProgress(self.url,self.local)
160                 self.download.addProgress(self.http_progress)
161                 self.download.start().addCallback(self.http_finished).addErrback(self.http_failed)
162
163         def http_progress(self, recvbytes, totalbytes):
164                 #print "[http_progress] recvbytes=%d, totalbytes=%d" % (recvbytes, totalbytes)
165                 self.progress = int(self.end*recvbytes/float(totalbytes))
166
167         def http_finished(self, string=""):
168                 print "[http_finished]" + str(string)
169                 Task.processFinished(self, 0)
170
171         def http_failed(self, failure_instance=None, error_message=""):
172                 if error_message == "" and failure_instance is not None:
173                         error_message = failure_instance.getErrorMessage()
174                         print "[http_failed] " + error_message
175                         Task.processFinished(self, 1)
176
177
178
179
180
181 class MyTubePlayerMainScreen(Screen, ConfigListScreen):
182         Details = {}
183         #(entry, Title, Description, TubeID, thumbnail, PublishedDate,Views,duration,ratings )
184         skin = """
185                 <screen name="MyTubePlayerMainScreen" flags="wfNoBorder" position="0,0" size="720,576" title="MyTube - Browser" >
186                         <ePixmap position="0,0" zPosition="-1" size="720,576" pixmap="~/mytubemain_bg.png" alphatest="on" transparent="1" backgroundColor="transparent"/>
187                         <widget name="config" zPosition="2" position="60,60" size="600,50" scrollbarMode="showNever" transparent="1" />
188                         <widget name="result" position="300,60" zPosition="3" size="350,50" font="Regular;21" transparent="1" backgroundColor="transparent" halign="right"/>
189                         <widget source="feedlist" render="Listbox" position="49,110" size="628,385" zPosition="1" scrollbarMode="showOnDemand" transparent="1" backgroundPixmap="~/list_bg.png" selectionPixmap="~/list_sel.png" >
190                                 <convert type="TemplatedMultiContent">
191                                 {"templates":
192                                         {"default": (77,[
193                                                         MultiContentEntryPixmapAlphaTest(pos = (0, 0), size = (100, 75), png = 4), # index 4 is the thumbnail
194                                                         MultiContentEntryText(pos = (100, 1), size = (500, 22), font=0, flags = RT_HALIGN_LEFT | RT_VALIGN_TOP| RT_WRAP, text = 1), # index 1 is the Title
195                                                         MultiContentEntryText(pos = (100, 24), size = (300, 18), font=1, flags = RT_HALIGN_LEFT | RT_VALIGN_TOP| RT_WRAP, text = 5), # index 5 is the Published Date
196                                                         MultiContentEntryText(pos = (100, 43), size = (300, 18), font=1, flags = RT_HALIGN_LEFT | RT_VALIGN_TOP| RT_WRAP, text = 6), # index 6 is the Views Count
197                                                         MultiContentEntryText(pos = (400, 24), size = (200, 18), font=1, flags = RT_HALIGN_LEFT | RT_VALIGN_TOP| RT_WRAP, text = 7), # index 7 is the duration
198                                                         MultiContentEntryText(pos = (400, 43), size = (200, 18), font=1, flags = RT_HALIGN_LEFT | RT_VALIGN_TOP| RT_WRAP, text = 8), # index 8 is the ratingcount
199                                                 ]),
200                                         "state": (77,[
201                                                         MultiContentEntryText(pos = (10, 1), size = (560, 28), font=2, flags = RT_HALIGN_LEFT | RT_VALIGN_TOP| RT_WRAP, text = 0), # index 0 is the name
202                                                         MultiContentEntryText(pos = (10, 22), size = (560, 46), font=3, flags = RT_HALIGN_LEFT | RT_VALIGN_TOP| RT_WRAP, text = 1), # index 2 is the description
203                                                 ])
204                                         },
205                                         "fonts": [gFont("Regular", 22),gFont("Regular", 18),gFont("Regular", 26),gFont("Regular", 20)],
206                                         "itemHeight": 77
207                                 }
208                                 </convert>
209                         </widget>
210
211                         <ePixmap pixmap="skin_default/buttons/key_info.png" position="50,500" zPosition="4" size="35,25" alphatest="on" transparent="1" />
212                         <ePixmap pixmap="skin_default/buttons/key_menu.png" position="50,520" zPosition="4" size="35,25" alphatest="on" transparent="1" />
213                         <ePixmap position="90,500" size="100,40" zPosition="4" pixmap="~/plugin.png" alphatest="on" transparent="1" />
214                         <ePixmap position="190,500" zPosition="4" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
215                         <ePixmap position="330,500" zPosition="4" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
216                         <ePixmap position="470,500" zPosition="4" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
217                         <widget name="key_red" position="190,500" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
218                         <widget name="key_green" position="330,500" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
219                         <widget name="key_yellow" position="470,500" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
220                         <widget name="ButtonBlue" pixmap="skin_default/buttons/button_blue.png" position="610,510" zPosition="10" size="15,16" transparent="1" alphatest="on" />
221                         <widget name="VKeyIcon" pixmap="skin_default/vkey_icon.png" position="620,495" zPosition="10" size="60,48" transparent="1" alphatest="on" />
222                         <widget name="thumbnail" position="0,0" size="100,75" alphatest="on"/> # fake entry for dynamic thumbnail resizing, currently there is no other way doing this.
223                         <widget name="HelpWindow" position="160,255" zPosition="1" size="1,1" transparent="1" alphatest="on" />
224                 </screen>"""
225
226         def __init__(self, session, l2key=None):
227                 Screen.__init__(self, session)
228                 self.session = session
229                 self.l2key = l2key
230                 self.l3key = None
231                 self.skin_path = plugin_path
232                 self.FeedURL = None
233                 self.ytfeed = None
234                 self.currentFeedName = None
235                 self.videolist = []
236                 self.queryThread = None
237                 self.queryRunning = False
238
239                 self.video_playlist = []
240                 self.statuslist = []
241                 self.mytubeentries = None
242
243                 self.thumbnails = []
244                 self.index = 0
245                 self.maxentries = 0
246
247                 self.screenshotList = []
248                 self.pixmaps_to_load = []
249                 self.picloads = {}
250
251                 self.oldfeedentrycount = 0
252                 self.appendEntries = False
253                 self.lastservice = session.nav.getCurrentlyPlayingServiceReference()
254                 self.propagateUpDownNormally = True
255                 self.FirstRun = True
256                 self.HistoryWindow = None
257                 self.History = None
258                 self.searchtext = _("Welcome to the MyTube Youtube Player.\n\nWhile entering your search term(s) you will get suggestions displayed matching your search term.\n\nTo select a suggestion press DOWN on your remote, select the desired result and press OK on your remote to start the search.\n\nPress exit to get back to the input field.")
259                 self.feedtext = _("Welcome to the MyTube Youtube Player.\n\nUse the Bouqet+ button to navigate to the search field and the Bouqet- to navigate to the video entries.\n\nTo play a movie just press OK on your remote control.\n\nPress info to see the movie description.\n\nPress the Menu button for additional options.\n\nThe Help button shows this help again.")
260                 self.currList = "configlist"
261                 self.oldlist = None
262
263                 self["feedlist"] = List(self.videolist)
264                 self["thumbnail"] = Pixmap()
265                 self["thumbnail"].hide()
266                 self["HelpWindow"] = Pixmap()
267                 self["HelpWindow"].hide()
268                 self["key_red"] = Button(_("Close"))
269                 self["key_green"] = Button(_("Std. Feeds"))
270                 self["key_yellow"] = Button(_("History"))
271                 self["ButtonBlue"] = Pixmap()
272                 self["VKeyIcon"] = Pixmap()
273                 self["ButtonBlue"].hide()
274                 self["VKeyIcon"].hide()
275                 self["result"] = Label("")
276
277
278                 self["searchactions"] = ActionMap(["ShortcutActions", "WizardActions", "HelpActions", "MediaPlayerActions"],
279                 {
280                         "ok": self.keyOK,
281                         "back": self.leavePlayer,
282                         "red": self.leavePlayer,
283                         "blue": self.openKeyboard,
284                         "yellow": self.handleHistory,
285                         "up": self.keyUp,
286                         "down": self.handleSuggestions,
287                         "left": self.keyLeft,
288                         "right": self.keyRight,
289                         "prevBouquet": self.switchToFeedList,
290                         "nextBouquet": self.switchToConfigList,
291                         "displayHelp": self.handleHelpWindow,
292                         "menu" : self.handleMenu,
293                 }, -2)
294
295                 self["suggestionactions"] = ActionMap(["ShortcutActions", "WizardActions", "MediaPlayerActions", "HelpActions", "NumberActions"],
296                 {
297                         "ok": self.keyOK,
298                         "back": self.switchToConfigList,
299                         "red": self.switchToConfigList,
300                         "nextBouquet": self.switchToConfigList,
301                         "prevBouquet": self.switchToFeedList,
302                         "up": self.keyUp,
303                         "down": self.keyDown,
304                         "left": self.keyLeft,
305                         "right": self.keyRight,
306                         "0": self.toggleScreenVisibility
307                 }, -2)
308
309
310                 self["videoactions"] = ActionMap(["ShortcutActions", "WizardActions", "MediaPlayerActions", "MovieSelectionActions", "HelpActions"],
311                 {
312                         "ok": self.keyOK,
313                         "back": self.leavePlayer,
314                         "red": self.leavePlayer,
315                         "yellow": self.handleHistory,
316                         "up": self.keyUp,
317                         "down": self.keyDown,
318                         "nextBouquet": self.switchToConfigList,
319                         "green": self.keyStdFeed,
320                         "showEventInfo": self.showVideoInfo,
321                         "displayHelp": self.handleHelpWindow,
322                         "menu" : self.handleMenu,
323                 }, -2)
324
325                 self["statusactions"] = ActionMap(["ShortcutActions", "WizardActions", "HelpActions", "MediaPlayerActions"],
326                 {
327                         "back": self.leavePlayer,
328                         "red": self.leavePlayer,
329                         "nextBouquet": self.switchToConfigList,
330                         "green": self.keyStdFeed,
331                         "yellow": self.handleHistory,
332                         "menu": self.handleMenu
333                 }, -2)
334
335                 self["historyactions"] = ActionMap(["ShortcutActions", "WizardActions", "MediaPlayerActions", "MovieSelectionActions", "HelpActions"],
336                 {
337                         "ok": self.keyOK,
338                         "back": self.closeHistory,
339                         "red": self.closeHistory,
340                         "yellow": self.handleHistory,
341                         "up": self.keyUp,
342                         "down": self.keyDown,
343                         "left": self.keyLeft,
344                         "right": self.keyRight,
345                 }, -2)
346
347                 self["videoactions"].setEnabled(False)
348                 self["statusactions"].setEnabled(False)
349                 self["historyactions"].setEnabled(False)
350
351                 self.timer_startDownload = eTimer()
352                 self.timer_startDownload_conn = self.timer_startDownload.timeout.connect(self.downloadThumbnails)
353                 self.timer_thumbnails = eTimer()
354                 self.timer_thumbnails_conn = self.timer_thumbnails.timeout.connect(self.updateFeedThumbnails)
355
356                 self.SearchConfigEntry = None
357                 self.searchContextEntries = []
358                 config.plugins.mytube.search.searchTerm.value = ""
359                 ConfigListScreen.__init__(self, self.searchContextEntries, session)
360                 self.createSetup()
361                 self.onLayoutFinish.append(self.layoutFinished)
362                 self.onShown.append(self.setWindowTitle)
363                 self.onClose.append(self.__onClose)
364                 self._initTimer = eTimer()
365                 self.__initTimer_conn = self._initTimer.timeout.connect(self._initTimerFire)
366
367         def __onClose(self):
368                 myTubeService.resetAuthState()
369                 del self._initTimer
370                 del self.timer_startDownload
371                 del self.timer_thumbnails
372                 self.Details = {}
373                 self.session.nav.playService(self.lastservice)
374
375         def layoutFinished(self):
376                 self.currList = "status"
377                 current = self["config"].getCurrent()
378                 if current[1].help_window.instance is not None:
379                         current[1].help_window.instance.hide()
380
381                 l3cert = etpm.getData(eTPM.DT_LEVEL3_CERT)
382                 if l3cert is None or l3cert is "":
383                         self["videoactions"].setEnabled(False)
384                         self["searchactions"].setEnabled(False)
385                         self["config_actions"].setEnabled(False)
386                         self["historyactions"].setEnabled(False)
387                         self["statusactions"].setEnabled(True)
388                         self.hideSuggestions()
389                         self.statuslist = []
390                         self.statuslist.append(( _("Genuine Dreambox validation failed!"), _("Verify your Dreambox authenticity by running the genuine dreambox plugin!" ) ))
391                         self["feedlist"].style = "state"
392                         self['feedlist'].setList(self.statuslist)
393                         return
394
395                 self.l3key = validate_cert(l3cert, self.l2key)
396                 if self.l3key is None:
397                         print "l3cert invalid"
398                         return
399                 rnd = get_rnd()
400                 if rnd is None:
401                         print "random error"
402                         return
403
404                 val = etpm.computeSignature(rnd)
405                 result = decrypt_block(val, self.l3key)
406
407                 self.statuslist = []
408                 if result[80:88] != rnd:
409                         self.statuslist.append(( _("Genuine Dreambox validation failed!"), _("Verify your Dreambox authenticity by running the genuine dreambox plugin!" ) ))
410                         self["feedlist"].style = "state"
411                         self['feedlist'].setList(self.statuslist)
412                         return
413
414                 # we need to login here; startService() is fired too often for external curl
415 #               self.tryUserLogin()
416
417                 self.statuslist.append(( _("Fetching feed entries"), _("Trying to download the Youtube feed entries. Please wait..." ) ))
418                 self["feedlist"].style = "state"
419                 self['feedlist'].setList(self.statuslist)
420                 self._initTimer.start(500)
421
422         def _initTimerFire(self):
423                 self._initTimer.stop()
424                 if config.plugins.mytube.general.loadFeedOnOpen.value:
425                         self.setState('getFeed')
426                 else:
427                         self.setState('byPass')
428
429         def setWindowTitle(self):
430                 self.setTitle(_("MyTubePlayer"))
431
432         def createSetup(self):
433                 self.searchContextEntries = []
434                 self.SearchConfigEntry = getConfigListEntry(_("Search Term(s)"), config.plugins.mytube.search.searchTerm)
435                 self.searchContextEntries.append(self.SearchConfigEntry)
436                 self["config"].list = self.searchContextEntries
437                 self["config"].l.setList(self.searchContextEntries)
438
439
440         def tryUserLogin(self):
441                 if config.plugins.mytube.general.username.value is "" or config.plugins.mytube.general.password.value is "":
442                         return
443
444                 try:
445                         myTubeService.auth_user(config.plugins.mytube.general.username.value, config.plugins.mytube.general.password.value)
446                         self.statuslist.append(( _("Login OK"), _('Hello') + ' ' + str(config.plugins.mytube.general.username.value)))
447                 except Exception as e:
448                         print 'Login-Error: ' + str(e)
449                         self.statuslist.append(( _("Login failed"), str(e)))
450
451         def setState(self,status = None):
452                 if status:
453                         self.currList = "status"
454                         self["videoactions"].setEnabled(False)
455                         self["searchactions"].setEnabled(False)
456                         self["config_actions"].setEnabled(False)
457                         self["historyactions"].setEnabled(False)
458                         self["statusactions"].setEnabled(True)
459                         self["ButtonBlue"].hide()
460                         self["VKeyIcon"].hide()
461                         self.statuslist = []
462                         self.hideSuggestions()
463                         result = None
464                         if self.l3key is not None:
465                                 rnd = get_rnd()
466                                 if rnd is None:
467                                         return
468                                 val = etpm.computeSignature(rnd)
469                                 result = decrypt_block(val, self.l3key)
470                         if not result or result[80:88] != rnd:
471                                 self["key_green"].show()
472                                 self.statuslist.append(( _("Genuine Dreambox validation failed!"), _("Verify your Dreambox authenticity by running the genuine dreambox plugin!" ) ))
473                                 self["feedlist"].style = "state"
474                                 self['feedlist'].setList(self.statuslist)
475                                 return
476
477                         print "Genuine Dreambox validation passed"
478                         if self.FirstRun == True:
479                                 self.appendEntries = False
480                                 myTubeService.startService()
481                         if self.HistoryWindow is not None:
482                                 self.HistoryWindow.deactivate()
483                                 self.HistoryWindow.instance.hide()
484                         if status == 'getFeed':
485                                 self.statuslist.append(( _("Fetching feed entries"), _("Trying to download the Youtube feed entries. Please wait..." ) ))
486                         elif status == 'getSearchFeed':
487                                 self.statuslist.append(( _("Fetching search entries"), _("Trying to download the Youtube search results. Please wait..." ) ))
488                         elif status == 'Error':
489                                 self.statuslist.append(( _("An error occured."), _("There was an error getting the feed entries. Please try again." ) ))
490                         elif status == 'noVideos':
491                                 self["key_green"].show()
492                                 self.statuslist.append(( _("No videos to display"), _("Please select a standard feed or try searching for videos." ) ))
493                         elif status == 'byPass':
494                                 self.statuslist.append(( _("Not fetching feed entries"), _("Please enter your search term." ) ))
495                                 self["feedlist"].style = "state"
496                                 self['feedlist'].setList(self.statuslist)
497                                 self.switchToConfigList()
498                         self["feedlist"].style = "state"
499                         self['feedlist'].setList(self.statuslist)
500                         if self.FirstRun == True:
501                                 if config.plugins.mytube.general.loadFeedOnOpen.value:
502                                         self.getFeed()
503
504         def handleHelpWindow(self):
505                 print "[handleHelpWindow]"
506                 if self.currList == "configlist":
507                         self.hideSuggestions()
508                         self.session.openWithCallback(self.ScreenClosed, MyTubeVideoHelpScreen, self.skin_path, wantedinfo = self.searchtext, wantedtitle = _("MyTubePlayer Help") )
509                 elif self.currList == "feedlist":
510                         self.session.openWithCallback(self.ScreenClosed, MyTubeVideoHelpScreen, self.skin_path, wantedinfo = self.feedtext, wantedtitle = _("MyTubePlayer Help") )
511
512         def handleFirstHelpWindow(self):
513                 print "[handleFirstHelpWindow]"
514                 if config.plugins.mytube.general.showHelpOnOpen.value is True:
515                         if self.currList == "configlist":
516                                 self.hideSuggestions()
517                                 self.session.openWithCallback(self.firstRunHelpClosed, MyTubeVideoHelpScreen, self.skin_path,wantedinfo = self.feedtext, wantedtitle = _("MyTubePlayer Help") )
518                 else:
519                         self.FirstRun = False
520
521         def firstRunHelpClosed(self):
522                 if self.FirstRun == True:
523                         self.FirstRun = False
524                         self.switchToConfigList()
525
526         def handleMenu(self):
527                 if self.currList == "configlist" or self.currList == "status":
528                         menulist = (
529                                         (_("MyTube Settings"), "settings"),
530                                 )
531                         self.hideSuggestions()
532                         self.session.openWithCallback(self.openMenu, ChoiceBox, title=_("Select your choice."), list = menulist)
533
534                 elif self.currList == "feedlist":
535                         menulist = [(_("MyTube Settings"), "settings")]
536                         menulist.extend((
537                                         (_("Related videos"), "related"),
538                                         (_("Channel videos"), "channel_videos"),
539                                 ))
540                         
541                         if myTubeService.is_auth() is True:
542                                 menulist.extend((
543                                                 (_("Subscribe to channel"), "subscribe"),
544                                                 (_("Add to favorites"), "favorite"),
545                                         ))                              
546                         
547                         if config.usage.setup_level.index >= 2: # expert+
548                                 menulist.extend((
549                                         (_("Download Video"), "download"),
550                                         (_("View active downloads"), "downview")
551                                 ))
552
553                         self.hideSuggestions()
554                         self.session.openWithCallback(self.openMenu, ChoiceBox, title=_("Select your choice."), list = menulist)
555
556         def openMenu(self, answer):
557                 answer = answer and answer[1]
558                 if answer == "settings":
559                         print "settings selected"
560                         self.session.openWithCallback(self.ScreenClosed,MyTubeSettingsScreen, self.skin_path )
561                 elif answer == "related":
562                         current = self["feedlist"].getCurrent()[0]
563                         self.setState('getFeed')
564                         self.getRelatedVideos(current)
565                 elif answer == "channel_videos":
566                         current = self["feedlist"].getCurrent()[0]
567                         self.setState('getFeed')
568                         self.getChannelVideos(current)
569                 elif answer == "subscribe":
570                         current = self["feedlist"].getCurrent()[0]
571                         self.session.open(MessageBox, current.subscribeToUser(), MessageBox.TYPE_INFO)
572                 elif answer == "favorite":
573                         current = self["feedlist"].getCurrent()[0]
574                         self.session.open(MessageBox, current.addToFavorites(), MessageBox.TYPE_INFO)
575                                         
576                 elif answer == "response":
577                         current = self["feedlist"].getCurrent()[0]
578                         self.setState('getFeed')
579                         self.getResponseVideos(current)
580                 elif answer == "download":
581                         if self.currList == "feedlist":
582                                 current = self[self.currList].getCurrent()
583                                 if current:
584                                         video = current[0]
585                                         if video:
586                                                 myurl = video.url
587                                                 filename = str(config.plugins.mytube.general.videodir.value)+ str(video.title) + '.mp4'
588                                                 job_manager.AddJob(downloadJob(myurl,filename, str(video.title)[:30]))
589                 elif answer == "downview":
590                         self.tasklist = []
591                         for job in job_manager.getPendingJobs():
592                                 self.tasklist.append((job,job.name,job.getStatustext(),int(100*job.progress/float(job.end)) ,str(100*job.progress/float(job.end)) + "%" ))
593                         self.session.open(MyTubeTasksScreen, self.skin_path , self.tasklist)
594                 elif answer == None:
595                         self.ScreenClosed()
596
597         def openKeyboard(self):
598                 self.hideSuggestions()
599                 self.session.openWithCallback(self.SearchEntryCallback, VirtualKeyBoard, title = (_("Enter your search term(s)")), text = config.plugins.mytube.search.searchTerm.value)
600
601         def ScreenClosed(self):
602                 print "ScreenCLosed, restoring old window state"
603                 if self.currList == "historylist":
604                         if self.HistoryWindow.status() is False:
605                                 self.HistoryWindow.activate()
606                                 self.HistoryWindow.instance.show()
607                 elif self.currList == "configlist":
608                         self.switchToConfigList()
609                         ConfigListScreen.keyOK(self)
610                 elif self.currList == "feedlist":
611                         self.switchToFeedList()
612
613         def SearchEntryCallback(self, callback = None):
614                 if callback is not None and len(callback):
615                         config.plugins.mytube.search.searchTerm.value = callback
616                         ConfigListScreen.keyOK(self)
617                         self["config"].getCurrent()[1].getSuggestions()
618                 current = self["config"].getCurrent()
619                 if current[1].help_window.instance is not None:
620                         current[1].help_window.instance.show()
621                 if current[1].suggestionsWindow.instance is not None:
622                         current[1].suggestionsWindow.instance.show()
623                 self.propagateUpDownNormally = True
624
625         def openStandardFeedClosed(self, answer):
626                 answer = answer and answer[1]
627                 if answer is not None:
628                         self.setState('getFeed')
629                         self.appendEntries = False
630                         self.getFeed(videoCategoryId=answer)
631
632         def handleLeave(self, how):
633                 self.is_closing = True
634                 if how == "ask":
635                         if self.currList == "configlist":
636                                 list = (
637                                         (_("Yes"), "quit"),
638                                         (_("No"), "continue"),
639                                         (_("No, but switch to video entries."), "switch2feed")
640                                 )
641                         else:
642                                 list = (
643                                         (_("Yes"), "quit"),
644                                         (_("No"), "continue"),
645                                         (_("No, but switch to video search."), "switch2search")
646                                 )
647                         self.session.openWithCallback(self.leavePlayerConfirmed, ChoiceBox, title=_("Really quit MyTube Player?"), list = list)
648                 else:
649                         self.leavePlayerConfirmed([True, how])
650
651         def leavePlayer(self):
652                 print "leavePlayer"
653                 if self.HistoryWindow is not None:
654                         self.HistoryWindow.deactivate()
655                         self.HistoryWindow.instance.hide()
656                 if self.currList == "configlist":
657                         current = self["config"].getCurrent()
658                         if current[1].suggestionsWindow.activeState is True:
659                                 self.propagateUpDownNormally = True
660                                 current[1].deactivateSuggestionList()
661                                 self["config"].invalidateCurrent()
662                         else:
663                                 self.hideSuggestions()
664                                 self.handleLeave(config.plugins.mytube.general.on_exit.value)
665                 else:
666                         self.hideSuggestions()
667                         self.handleLeave(config.plugins.mytube.general.on_exit.value)
668
669         def leavePlayerConfirmed(self, answer):
670                 answer = answer and answer[1]
671                 if answer == "quit":
672                         self.doQuit()
673                 elif answer == "continue":
674                         if self.currList == "historylist":
675                                 if self.HistoryWindow.status() is False:
676                                         self.HistoryWindow.activate()
677                                         self.HistoryWindow.instance.show()
678                         elif self.currList == "configlist":
679                                 self.switchToConfigList()
680                         elif self.currList == "feedlist":
681                                 self.switchToFeedList()
682                 elif answer == "switch2feed":
683                         self.switchToFeedList()
684                 elif answer == "switch2search":
685                         self.switchToConfigList()
686                 elif answer == None:
687                         if self.currList == "historylist":
688                                 if self.HistoryWindow.status() is False:
689                                         self.HistoryWindow.activate()
690                                         self.HistoryWindow.instance.show()
691                         elif self.currList == "configlist":
692                                 self.switchToConfigList()
693                         elif self.currList == "feedlist":
694                                 self.switchToFeedList()
695
696         def doQuit(self):
697                 if self["config"].getCurrent()[1].suggestionsWindow is not None:
698                         self.session.deleteDialog(self["config"].getCurrent()[1].suggestionsWindow)
699                 if self.HistoryWindow is not None:
700                         self.session.deleteDialog(self.HistoryWindow)
701                 if config.plugins.mytube.general.showHelpOnOpen.value is True:
702                         config.plugins.mytube.general.showHelpOnOpen.value = False
703                         config.plugins.mytube.general.showHelpOnOpen.save()
704                 if not config.plugins.mytube.general.clearHistoryOnClose.value:
705                         if self.History and len(self.History):
706                                 config.plugins.mytube.general.history.value = ",".join(self.History)
707                 else:
708                         config.plugins.mytube.general.history.value = ""
709                 config.plugins.mytube.general.history.save()
710                 config.plugins.mytube.general.save()
711                 config.plugins.mytube.save()
712                 self.cancelThread()
713                 self.close()
714
715         def keyOK(self):
716                 print "self.currList im KeyOK",self.currList
717                 if self.currList == "configlist" or self.currList == "suggestionslist":
718                         self["config"].invalidateCurrent()
719                         if config.plugins.mytube.search.searchTerm.value != "":
720                                 self.add2History()
721                                 searchTerm = config.plugins.mytube.search.searchTerm.value
722                                 print "Search searchcontext",searchTerm
723                                 if isinstance(self["config"].getCurrent()[1], ConfigTextWithGoogleSuggestions) and not self.propagateUpDownNormally:
724                                         self.propagateUpDownNormally = True
725                                         self["config"].getCurrent()[1].deactivateSuggestionList()
726                                 self.setState('getSearchFeed')
727                                 self.runSearch(searchTerm)
728                 elif self.currList == "feedlist":
729                         current = self[self.currList].getCurrent()
730                         if current:
731                                 Log.d(current)
732                                 video = current[0]
733                                 if video is not None:
734                                         myurl = video.url
735                                         print "Playing URL",myurl
736                                         if myurl is not None:
737                                                 myreference = eServiceReference(4097,0,myurl)
738                                                 myreference.setName(video.title)
739                                                 self.session.openWithCallback(self.onPlayerClosed, MyTubePlayer, myreference, self.lastservice, infoCallback = self.showVideoInfo, nextCallback = self.getNextEntry, prevCallback = self.getPrevEntry )
740                                         else:
741                                                 self.session.open(MessageBox, _("Sorry, video is not available!"), MessageBox.TYPE_INFO)
742                 elif self.currList == "historylist":
743                         if self.HistoryWindow is not None:
744                                 config.plugins.mytube.search.searchTerm.value = self.HistoryWindow.getSelection()
745                         self["config"].invalidateCurrent()
746                         if config.plugins.mytube.search.searchTerm.value != "":
747                                 searchTerm = config.plugins.mytube.search.searchTerm.value
748                                 print "Search searchcontext",searchTerm
749                                 self.setState('getSearchFeed')
750                                 self.runSearch(searchTerm)
751
752         def onPlayerClosed(self):
753                 if config.plugins.mytube.general.resetPlayService.value is True:
754                         self.session.nav.playService(self.lastservice)
755
756         def toggleScreenVisibility(self):
757                 if self.shown is True:
758                         self.hide()
759                 else:
760                         self.show()
761
762         def keyUp(self):
763                 print "self.currList im KeyUp",self.currList
764                 if self.currList == "suggestionslist":
765                         if config.plugins.mytube.search.searchTerm.value != "":
766                                 if not self.propagateUpDownNormally:
767                                         self["config"].getCurrent()[1].suggestionListUp()
768                                         self["config"].invalidateCurrent()
769                 elif self.currList == "feedlist":
770                         self[self.currList].selectPrevious()
771                 elif self.currList == "historylist":
772                         if self.HistoryWindow is not None and self.HistoryWindow.shown:
773                                 self.HistoryWindow.up()
774
775         def keyDown(self):
776                 print "self.currList im KeyDown",self.currList
777                 if self.currList == "suggestionslist":
778                         if config.plugins.mytube.search.searchTerm.value != "":
779                                 if not self.propagateUpDownNormally:
780                                         self["config"].getCurrent()[1].suggestionListDown()
781                                         self["config"].invalidateCurrent()
782                 elif self.currList == "feedlist":
783                         print self[self.currList].count()
784                         print self[self.currList].index
785                         if self[self.currList].index == self[self.currList].count()-1 and myTubeService.hasNextPage():
786                                 # load new feeds on last selected item
787                                 if config.plugins.mytube.general.AutoLoadFeeds.value is False:
788                                         self.session.openWithCallback(self.getNextEntries, MessageBox, _("Do you want to see more entries?"))
789                                 else:
790                                         self.getNextEntries(True)
791                         else:
792                                 self[self.currList].selectNext()
793                 elif self.currList == "historylist":
794                         if self.HistoryWindow is not None and self.HistoryWindow.shown:
795                                 self.HistoryWindow.down()
796         def keyRight(self):
797                 print "self.currList im KeyRight",self.currList
798                 if self.propagateUpDownNormally:
799                         ConfigListScreen.keyRight(self)
800                 else:
801                         if self.currList == "suggestionslist":
802                                 if config.plugins.mytube.search.searchTerm.value != "":
803                                         self["config"].getCurrent()[1].suggestionListPageDown()
804                                         self["config"].invalidateCurrent()
805                         elif self.currList == "historylist":
806                                 if self.HistoryWindow is not None and self.HistoryWindow.shown:
807                                         self.HistoryWindow.pageDown()
808
809         def keyLeft(self):
810                 print "self.currList im kEyLeft",self.currList
811                 if self.propagateUpDownNormally:
812                         ConfigListScreen.keyLeft(self)
813                 else:
814                         if self.currList == "suggestionslist":
815                                 if config.plugins.mytube.search.searchTerm.value != "":
816                                         self["config"].getCurrent()[1].suggestionListPageUp()
817                                         self["config"].invalidateCurrent()
818                         elif self.currList == "historylist":
819                                 if self.HistoryWindow is not None and self.HistoryWindow.shown:
820                                         self.HistoryWindow.pageDown()
821         def keyStdFeed(self):
822                 self.hideSuggestions()
823                 menulist = []
824                 for category in myTubeService.getCategories():
825                         menulist.append((category.title, category.id))
826 #               if myTubeService.is_auth():
827 #                       menulist.extend((
828 #                               (_("My Subscriptions"), "my_subscriptions"),
829 #                               (_("My Favorites"), "my_favorites"),
830 #                               (_("My History"), "my_history"),
831 #                               (_("My Watch Later"), "my_watch_later"),
832 #                               (_("My Recommendations"), "my_recommendations"),
833 #                               (_("My Uploads"), "my_uploads"),
834 #                       ))
835
836                 self.session.openWithCallback(self.openStandardFeedClosed, ChoiceBox, title=_("Select new feed to view."), list = menulist)
837
838         def handleSuggestions(self):
839                 print "handleSuggestions"
840                 print "self.currList",self.currList
841                 if self.currList == "configlist":
842                         self.switchToSuggestionsList()
843                 elif self.currList == "historylist":
844                         if self.HistoryWindow is not None and self.HistoryWindow.shown:
845                                 self.HistoryWindow.down()
846
847         def switchToSuggestionsList(self):
848                 print "switchToSuggestionsList"
849                 self.currList = "suggestionslist"
850                 self["ButtonBlue"].hide()
851                 self["VKeyIcon"].hide()
852                 self["statusactions"].setEnabled(False)
853                 self["config_actions"].setEnabled(False)
854                 self["videoactions"].setEnabled(False)
855                 self["searchactions"].setEnabled(False)
856                 self["suggestionactions"].setEnabled(True)
857                 self["historyactions"].setEnabled(False)
858                 self["key_green"].hide()
859                 self.propagateUpDownNormally = False
860                 self["config"].invalidateCurrent()
861                 if self.HistoryWindow is not None and self.HistoryWindow.shown:
862                         self.HistoryWindow.deactivate()
863                         self.HistoryWindow.instance.hide()
864
865         def switchToConfigList(self):
866                 print "switchToConfigList"
867                 self.currList = "configlist"
868                 self["config_actions"].setEnabled(True)
869                 self["historyactions"].setEnabled(False)
870                 self["statusactions"].setEnabled(False)
871                 self["videoactions"].setEnabled(False)
872                 self["suggestionactions"].setEnabled(False)
873                 self["searchactions"].setEnabled(True)
874                 self["key_green"].hide()
875                 self["ButtonBlue"].show()
876                 self["VKeyIcon"].show()
877                 self["config"].invalidateCurrent()
878                 helpwindowpos = self["HelpWindow"].getPosition()
879                 current = self["config"].getCurrent()
880                 if current[1].help_window.instance is not None:
881                         current[1].help_window.instance.move(ePoint(helpwindowpos[0],helpwindowpos[1]))
882                         current[1].help_window.instance.show()
883                 if current[1].suggestionsWindow.instance is not None:
884                         current[1].suggestionsWindow.instance.show()
885                         self["config"].getCurrent()[1].getSuggestions()
886                 self.propagateUpDownNormally = True
887                 if self.HistoryWindow is not None and self.HistoryWindow.shown:
888                         self.HistoryWindow.deactivate()
889                         self.HistoryWindow.instance.hide()
890                 if self.FirstRun == True:
891                         self.handleFirstHelpWindow()
892
893         def switchToFeedList(self, append = False):
894                 print "switchToFeedList"
895                 print "switching to feedlist from:",self.currList
896                 print "len(self.videolist):",len(self.videolist)
897                 if self.HistoryWindow is not None and self.HistoryWindow.shown:
898                         self.HistoryWindow.deactivate()
899                         self.HistoryWindow.instance.hide()
900                 self.hideSuggestions()
901                 if len(self.videolist):
902                         self.currList = "feedlist"
903                         self["ButtonBlue"].hide()
904                         self["VKeyIcon"].hide()
905                         self["videoactions"].setEnabled(True)
906                         self["suggestionactions"].setEnabled(False)
907                         self["searchactions"].setEnabled(False)
908                         self["statusactions"].setEnabled(False)
909                         self["historyactions"].setEnabled(False)
910                         self["key_green"].show()
911                         self["config_actions"].setEnabled(False)
912                         if not append:
913                                 self[self.currList].setIndex(0)
914                         self["feedlist"].updateList(self.videolist)
915                 else:
916                         self.setState('noVideos')
917
918
919         def switchToHistory(self):
920                 print "switchToHistory"
921                 self.oldlist = self.currList
922                 self.currList = "historylist"
923                 print "switchToHistory currentlist",self.currList
924                 print "switchToHistory oldlist",self.oldlist
925                 self.hideSuggestions()
926                 self["ButtonBlue"].hide()
927                 self["VKeyIcon"].hide()
928                 self["key_green"].hide()
929                 self["videoactions"].setEnabled(False)
930                 self["suggestionactions"].setEnabled(False)
931                 self["searchactions"].setEnabled(False)
932                 self["statusactions"].setEnabled(False)
933                 self["config_actions"].setEnabled(False)
934                 self["historyactions"].setEnabled(True)
935                 self.HistoryWindow.activate()
936                 self.HistoryWindow.instance.show()
937
938         def handleHistory(self):
939                 if self.HistoryWindow is None:
940                         self.HistoryWindow = self.session.instantiateDialog(MyTubeHistoryScreen, zPosition=1000)
941                 if self.currList in ("configlist","feedlist"):
942                         if self.HistoryWindow.status() is False:
943                                 print "status is FALSE,switchToHistory"
944                                 self.switchToHistory()
945                 elif self.currList == "historylist":
946                         self.closeHistory()
947
948         def closeHistory(self):
949                 print "closeHistory currentlist",self.currList
950                 print "closeHistory oldlist",self.oldlist
951                 if self.currList == "historylist":
952                         if self.HistoryWindow.status() is True:
953                                 print "status is TRUE, closing historyscreen"
954                                 self.HistoryWindow.deactivate()
955                                 self.HistoryWindow.instance.hide()
956                                 if self.oldlist == "configlist":
957                                         self.switchToConfigList()
958                                 elif self.oldlist == "feedlist":
959                                         self.switchToFeedList()
960
961         def add2History(self):
962                 if self.History is None:
963                         self.History = config.plugins.mytube.general.history.value.split(',')
964                 if self.History[0] == '':
965                         del self.History[0]
966                 print "self.History im add",self.History
967                 if config.plugins.mytube.search.searchTerm.value in self.History:
968                         self.History.remove((config.plugins.mytube.search.searchTerm.value))
969                 self.History.insert(0,(config.plugins.mytube.search.searchTerm.value))
970                 if len(self.History) == 30:
971                         self.History.pop()
972                 config.plugins.mytube.general.history.value = ",".join(self.History)
973                 config.plugins.mytube.general.history.save()
974                 print "configvalue",config.plugins.mytube.general.history.value
975
976         def hideSuggestions(self):
977                 current = self["config"].getCurrent()
978                 if current[1].help_window.instance is not None:
979                         current[1].help_window.instance.hide()
980                 if current[1].suggestionsWindow.instance is not None:
981                         current[1].suggestionsWindow.instance.hide()
982                 self.propagateUpDownNormally = True
983
984         def getFeed(self, chart=None, videoCategoryId=None, ids=[]):
985                 self.queryStarted()
986                 self.queryThread = myTubeService.getFeed(callback=self.gotFeed, chart=chart, videoCategoryId=videoCategoryId, ids=ids)
987
988         def getNextEntries(self, result):
989                 if not result:
990                         return
991                 if myTubeService.hasNextPage():
992                         self.appendEntries = True
993                         myTubeService.getNextPage()
994
995         def getRelatedVideos(self, video):
996                 if video:
997                         self.search(relatedToVideoId=video.id)
998
999         def getChannelVideos(self, video):
1000                 if video:
1001                         self.search(channelId=video.channelId)
1002
1003         def runSearch(self, searchTerm = None):
1004                 Log.d(searchTerm)
1005                 if searchTerm:
1006                         self.search(searchTerm=searchTerm)
1007
1008         def search(self, searchTerm=None, relatedToVideoId=None, channelId=None):
1009                 Log.d("searchTerm=%s, relatedToVideoId=%s, channelId=%s" % (searchTerm, relatedToVideoId, channelId))
1010                 self.queryStarted()
1011                 self.appendEntries = False
1012
1013 #               categories = [ config.plugins.mytube.search.categories.value ],
1014
1015                 self.queryThread = myTubeService.search(
1016                                         searchTerm=searchTerm,
1017                                         orderby=config.plugins.mytube.search.orderBy.value,
1018                                         time=config.plugins.mytube.search.time.value,
1019                                         lr=config.plugins.mytube.search.lr.value,
1020                                         relatedToVideoId=relatedToVideoId,
1021                                         channelId=channelId,
1022                                         safeSearch=config.plugins.mytube.search.safeSearch.value,
1023                                         callback=self.gotSearchFeed)
1024
1025         def queryStarted(self):
1026                 if self.queryRunning:
1027                         self.cancelThread()
1028                 self.queryRunning = True
1029
1030         def queryFinished(self):
1031                 self.queryRunning = False
1032
1033         def cancelThread(self):
1034                 print "[MyTubePlayer] cancelThread"
1035                 if self.queryThread is not None:
1036                         self.queryThread.cancel()
1037                 self.queryFinished()
1038
1039         def gotFeed(self, success, items, data):
1040                 print "[MyTubePlayer] gotFeed"
1041                 if self.FirstRun:
1042                         self.FirstRun = False
1043                 self.queryFinished()
1044                 if not success:
1045                         self.gotFeedError(items)
1046                 if success and items is not None:
1047                         self.ytfeed = items
1048                 myTubeService.feed = data
1049                 self.buildEntryList()
1050                 text = _("Results: %s - Page: %s " % (str(myTubeService.getTotalResults()), str(myTubeService.getCurrentPage())))
1051                 text = "TODO" #TODO text
1052                 #auth_username = myTubeService.getAuthedUsername()
1053                 #if auth_username:
1054                 #                       text = auth_username + ' - ' + text
1055                 self["result"].setText(text)
1056
1057         def gotFeedError(self, error):
1058                 print "[MyTubePlayer] gotFeedError"
1059                 self.queryFinished()
1060                 self.setState('Error')
1061
1062         def gotSearchFeed(self, success, feed, data):
1063                 if self.FirstRun:
1064                         self.FirstRun = False
1065                 self.gotFeed(success, feed, data)
1066
1067         def buildEntryList(self):
1068                 self.mytubeentries = None
1069                 self.screenshotList = []
1070                 self.maxentries = 0
1071                 self.mytubeentries = self.ytfeed
1072                 self.maxentries = len(self.mytubeentries)-1
1073                 if self.mytubeentries and len(self.mytubeentries):
1074                         if self.appendEntries == False:
1075                                 self.videolist = []
1076                                 for video in self.mytubeentries:
1077                                         video_id = video.id
1078                                         thumbnailUrl = None
1079                                         thumbnailUrl = video.thumbnailUrl
1080                                         if thumbnailUrl is not None:
1081                                                 self.screenshotList.append((video_id,thumbnailUrl))
1082                                         if not self.Details.has_key(video_id):
1083                                                 self.Details[video_id] = { 'thumbnail': None}
1084                                         self.videolist.append(self.buildEntryComponent(video, video_id))
1085                                 if len(self.videolist):
1086                                         self["feedlist"].style = "default"
1087                                         self["feedlist"].disable_callbacks = True
1088                                         self["feedlist"].list = self.videolist
1089                                         self["feedlist"].disable_callbacks = False
1090                                         self["feedlist"].setIndex(0)
1091                                         self["feedlist"].setList(self.videolist)
1092                                         self["feedlist"].updateList(self.videolist)
1093                                         if self.FirstRun and not config.plugins.mytube.general.loadFeedOnOpen.value:
1094                                                 self.switchToConfigList()
1095                                         else:
1096                                                 self.switchToFeedList()
1097                         else:
1098                                 self.oldfeedentrycount = 0 #TODO self["feedlist"].count()
1099                                 for video in self.mytubeentries:
1100                                         video_id = video.id
1101                                         thumbnailUrl = None
1102                                         thumbnailUrl = video.thumbnailUrl
1103                                         if thumbnailUrl is not None:
1104                                                 self.screenshotList.append((video_id,thumbnailUrl))
1105                                         if not self.Details.has_key(video_id):
1106                                                 self.Details[video_id] = { 'thumbnail': None}
1107                                         self.videolist.append(self.buildEntryComponent(video, video_id))
1108                                 if len(self.videolist):
1109                                         self["feedlist"].style = "default"
1110                                         old_index = self["feedlist"].index
1111                                         self["feedlist"].disable_callbacks = True
1112                                         self["feedlist"].list = self.videolist
1113                                         self["feedlist"].disable_callbacks = False
1114                                         self["feedlist"].setList(self.videolist)
1115                                         self["feedlist"].setIndex(old_index)
1116                                         self["feedlist"].updateList(self.videolist)
1117                                         self["feedlist"].selectNext()
1118                                         self.switchToFeedList(True)
1119                         if not self.timer_startDownload.isActive():
1120                                 print "STARRTDOWNLOADTIMER IM BUILDENTRYLIST"
1121                                 self.timer_startDownload.start(5)
1122                 else:
1123                         self.setState('Error')
1124                         pass
1125
1126         def buildEntryComponent(self, entry,TubeID):
1127                 title = entry.title
1128                 description = entry.description
1129                 myTubeID = TubeID
1130                 publishedDate = entry.publishedDate
1131                 if publishedDate is not "unknown":
1132                         published = publishedDate.split("T")[0]
1133                 else:
1134                         published = "unknown"
1135                 Views = entry.views
1136                 if Views is not "not available":
1137                         views = Views
1138                 else:
1139                         views = "not available"
1140                 duration = entry.duration
1141                 if duration is not 0:
1142                         durationInSecs = int(duration)
1143                         mins = int(durationInSecs / 60)
1144                         secs = durationInSecs - mins * 60
1145                         duration = "%d:%02d" % (mins, secs)
1146                 else:
1147                         duration = "not available"
1148                 likes = entry.likes
1149                 if likes is not "":
1150                         likes = likes
1151                 else:
1152                         likes = ""
1153                 thumbnail = None
1154                 if self.Details[myTubeID]["thumbnail"]:
1155                         thumbnail = self.Details[myTubeID]["thumbnail"]
1156                 return((entry, title, description, myTubeID, thumbnail, _("Added: ") + str(published), _("Views: ") + str(views), _("Duration: ") + str(duration), _("Likes: ") + str(likes) ))
1157
1158         def getNextEntry(self):
1159                 i = self["feedlist"].getIndex() + 1
1160                 if i < len(self.videolist):
1161                         self["feedlist"].selectNext()
1162                         current = self["feedlist"].getCurrent()
1163                         if current:
1164                                 video = current[0]
1165                                 if video:
1166                                         myurl = video.url
1167                                         if myurl is not None:
1168                                                 print "Got a URL to stream"
1169                                                 myreference = eServiceReference(4097,0,myurl)
1170                                                 myreference.setName(video.title)
1171                                                 return myreference,False
1172                                         else:
1173                                                 print "NoURL im getNextEntry"
1174                                                 return None,True
1175
1176                 print "no more entries to play"
1177                 return None,False
1178
1179         def getPrevEntry(self):
1180                 i = self["feedlist"].getIndex() - 1
1181                 if i >= 0:
1182                         self["feedlist"].selectPrevious()
1183                         current = self["feedlist"].getCurrent()
1184                         if current:
1185                                 video = current[0]
1186                                 if video:
1187                                         myurl = video.url
1188                                         if myurl is not None:
1189                                                 print "Got a URL to stream"
1190                                                 myreference = eServiceReference(4097,0,myurl)
1191                                                 myreference.setName(video.title)
1192                                                 return myreference,False
1193                                         else:
1194                                                 return None,True
1195                 return None,False
1196
1197         def showVideoInfo(self):
1198                 if self.currList == "feedlist":
1199                         self.openInfoScreen()
1200
1201         def openInfoScreen(self):
1202                 if self.currList == "feedlist":
1203                         current = self[self.currList].getCurrent()
1204                         if current:
1205                                 video = current[0]
1206                                 if video:
1207                                         print "Title im showVideoInfo",video.title
1208                                         self.session.open(MyTubeVideoInfoScreen, self.skin_path, video = video )
1209
1210         def downloadThumbnails(self):
1211                 self.timer_startDownload.stop()
1212                 for entry in self.screenshotList:
1213                         thumbnailUrl = entry[1]
1214                         tubeid = entry[0]
1215                         thumbnailFile = "/tmp/"+str(tubeid)+".jpg"
1216                         if self.Details.has_key(tubeid):
1217                                 if self.Details[tubeid]["thumbnail"] is None:
1218                                         if thumbnailUrl is not None:
1219                                                 if tubeid not in self.pixmaps_to_load:
1220                                                         self.pixmaps_to_load.append(tubeid)
1221                                                         if (os_path.exists(thumbnailFile) == True):
1222                                                                 self.fetchFinished(False,tubeid)
1223                                                         else:
1224                                                                 client.downloadPage(thumbnailUrl,thumbnailFile).addCallback(self.fetchFinished,str(tubeid)).addErrback(self.fetchFailed,str(tubeid))
1225                                         else:
1226                                                 if tubeid not in self.pixmaps_to_load:
1227                                                         self.pixmaps_to_load.append(tubeid)
1228                                                         self.fetchFinished(False,tubeid, failed = True)
1229
1230         def fetchFailed(self,string,tubeid):
1231                 print "thumbnail-fetchFailed for: ",tubeid,string.getErrorMessage()
1232                 self.fetchFinished(False,tubeid, failed = True)
1233
1234         def fetchFinished(self,x,tubeid, failed = False):
1235                 print "thumbnail-fetchFinished for:",tubeid
1236                 self.pixmaps_to_load.remove(tubeid)
1237                 if failed:
1238                         thumbnailFile = resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MyTube/plugin.png")
1239                 else:
1240                         thumbnailFile = "/tmp/"+str(tubeid)+".jpg"
1241                 sc = AVSwitch().getFramebufferScale()
1242                 if (os_path.exists(thumbnailFile) == True):
1243                         self.picloads[tubeid] = ePicLoad()
1244                         self.picloads[tubeid].conn = self.picloads[tubeid].PictureData.connect(boundFunction(self.finish_decode, tubeid))
1245                         self.picloads[tubeid].setPara((self["thumbnail"].instance.size().width(), self["thumbnail"].instance.size().height(), sc[0], sc[1], False, 1, "#00000000"))
1246                         self.picloads[tubeid].startDecode(thumbnailFile)
1247                 else:
1248                         self.pixmaps_to_load.append(tubeid)
1249                         self.fetchFinished(False,tubeid, failed = True)
1250
1251         def finish_decode(self,tubeid,info):
1252                 print "thumbnail finish_decode:", tubeid,info
1253                 ptr = self.picloads[tubeid].getData()
1254                 thumbnailFile = "/tmp/"+str(tubeid)+".jpg"
1255                 if ptr != None:
1256                         if self.Details.has_key(tubeid):
1257                                 self.Details[tubeid]["thumbnail"] = ptr
1258                         if (os_path.exists(thumbnailFile) == True):
1259                                 os_remove(thumbnailFile)
1260                         del self.picloads[tubeid]
1261                 else:
1262                         del self.picloads[tubeid]
1263                         if self.Details.has_key(tubeid):
1264                                 self.Details[tubeid]["thumbnail"] = None
1265                 self.timer_thumbnails.start(1)
1266
1267         def updateFeedThumbnails(self):
1268                 self.timer_thumbnails.stop()
1269                 if len(self.picloads) != 0:
1270                         self.timer_thumbnails.start(1)
1271                 else:
1272                         idx = 0
1273                         for entry in self.videolist:
1274                                 tubeid = entry[3]
1275                                 if self.Details.has_key(tubeid):
1276                                         if self.Details[tubeid]["thumbnail"] is not None:
1277                                                 thumbnail = entry[4]
1278                                                 if thumbnail == None:
1279                                                         video = entry[0]
1280                                                         self.videolist[idx] = self.buildEntryComponent(video, tubeid )
1281                                 idx += 1
1282                         if self.currList == "feedlist":
1283                                 self["feedlist"].updateList(self.videolist)
1284
1285
1286 class MyTubeVideoInfoScreen(Screen):
1287         skin = """
1288                 <screen name="MyTubeVideoInfoScreen" flags="wfNoBorder" position="0,0" size="720,576" title="MyTube - Video Info" >
1289                         <ePixmap position="0,0" zPosition="-1" size="720,576" pixmap="~/mytubemain_bg.png" alphatest="on" transparent="1" backgroundColor="transparent"/>
1290                         <widget name="title" position="60,50" size="600,50" zPosition="5" valign="center" halign="left" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
1291                         <widget name="starsbg" pixmap="~/starsbar_empty.png" position="560,220" zPosition="5" size="100,20" transparent="1" alphatest="on" />
1292                         <widget name="stars" pixmap="~/starsbar_filled.png" position="560,220" zPosition="6" size="100,20"  transparent="1" />
1293                         <widget source="infolist" render="Listbox" position="50,110" size="620,110" zPosition="6" scrollbarMode="showNever" selectionDisabled="1" transparent="1">
1294                                 <convert type="TemplatedMultiContent">
1295                                 {"templates":
1296                                         {"default": (110,[
1297                                                         MultiContentEntryPixmapAlphaTest(pos = (0, 4), size = (130, 98), png = 0), # index 0 is the thumbnail
1298                                                         MultiContentEntryPixmapAlphaTest(pos = (130, 4), size = (130, 98), png = 1), # index 0 is the thumbnail
1299                                                         MultiContentEntryPixmapAlphaTest(pos = (260, 4), size = (130, 98), png = 2), # index 0 is the thumbnail
1300                                                         MultiContentEntryPixmapAlphaTest(pos = (390, 4), size = (130, 98), png = 3), # index 0 is the thumbnail
1301                                                 ]),
1302                                         "state": (110,[
1303                                                         MultiContentEntryText(pos = (10, 40), size = (550, 38), font=2, flags = RT_HALIGN_LEFT | RT_VALIGN_TOP| RT_WRAP, text = 0), # index 0 is the name
1304                                                 ])
1305                                         },
1306                                         "fonts": [gFont("Regular", 20),gFont("Regular", 14),gFont("Regular", 28)],
1307                                         "itemHeight": 110
1308                                 }
1309                                 </convert>
1310                         </widget>
1311                         <widget name="channelTitle" position="60,220" size="300,20" zPosition="10" font="Regular;21" transparent="1" halign="left" valign="top" />
1312                         <widget name="duration" position="370,220" size="200,20" zPosition="10" font="Regular;21" transparent="1" halign="left" valign="top" />
1313                         <widget name="published" position="60,245" size="300,20" zPosition="10" font="Regular;21" transparent="1" halign="left" valign="top" />
1314                         <widget name="views" position="370,245" size="200,20" zPosition="10" font="Regular;21" transparent="1" halign="left" valign="top" />
1315                         <widget name="tags" position="60,270" size="600,20" zPosition="10" font="Regular;21" transparent="1" halign="left" valign="top" />
1316                         <widget name="detailtext" position="60,300" size="610,200" zPosition="10" font="Regular;21" transparent="1" halign="left" valign="top"/>
1317                         <ePixmap position="100,500" size="100,40" zPosition="0" pixmap="~/plugin.png" alphatest="on" transparent="1" />
1318                         <ePixmap position="220,500" zPosition="4" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
1319                         <widget name="key_red" position="220,500" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
1320                         <widget name="thumbnail" position="0,0" size="130,98" alphatest="on"/> # fake entry for dynamic thumbnail resizing, currently there is no other way doing this.
1321                 </screen>"""
1322
1323         def __init__(self, session, plugin_path, video = None):
1324                 Screen.__init__(self, session)
1325                 self.session = session
1326                 self.skin_path = plugin_path
1327                 self.video = video
1328                 self.infolist = []
1329                 self.thumbnails = []
1330                 self.picloads = {}
1331                 self["title"] = Label()
1332                 self["key_red"] = Button(_("Close"))
1333                 self["thumbnail"] = Pixmap()
1334                 self["thumbnail"].hide()
1335                 self["detailtext"] = ScrollLabel()
1336                 self["starsbg"] = Pixmap()
1337                 self["stars"] = ProgressBar()
1338                 self["duration"] = Label()
1339                 self["channelTitle"] = Label()
1340                 self["author"] = self["channelTitle"] #skincompat
1341                 self["published"] = Label()
1342                 self["views"] = Label()
1343                 self["tags"] = Label()
1344                 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions", "MovieSelectionActions"],
1345                 {
1346                         "back": self.close,
1347                         "red": self.close,
1348                         "up": self.pageUp,
1349                         "down": self.pageDown,
1350                         "left": self.pageUp,
1351                         "right": self.pageDown,
1352                 }, -2)
1353
1354                 self["infolist"] = List(self.infolist)
1355                 self.timer = eTimer()
1356                 self.timer_conn = self.timer.timeout.connect(self.picloadTimeout)
1357                 self.onLayoutFinish.append(self.layoutFinished)
1358                 self.onShown.append(self.setWindowTitle)
1359
1360         def layoutFinished(self):
1361                 self.statuslist = []
1362                 self.statuslist.append(( _("Downloading screenshots. Please wait..." ),_("Downloading screenshots. Please wait..." ) ))
1363                 self["infolist"].style = "state"
1364                 self['infolist'].setList(self.statuslist)
1365                 self.loadPreviewpics()
1366                 if self.video.title is not None:
1367                         self["title"].setText(self.video.title)
1368                 description = None
1369                 if self.video.description is not None:
1370                         self["detailtext"].setText(self.video.description.strip())
1371
1372                 #TODO implement Likes
1373                 self["stars"].hide()
1374                 self["starsbg"].hide()
1375
1376                 if self.video.duration is not 0:
1377                         durationInSecs = int(self.video.duration)
1378                         mins = int(durationInSecs / 60)
1379                         secs = durationInSecs - mins * 60
1380                         duration = "%d:%02d" % (mins, secs)
1381                         self["duration"].setText(_("Duration: ") + str(duration))
1382
1383                 if self.video.channelTitle:
1384                         self["channelTitle"].setText(_("Channel: ") + self.video.channelTitle)
1385
1386                 if self.video.publishedDate is not "unknown":
1387                         self["published"].setText(_("Added: ") + self.video.publishedDate.split("T")[0])
1388
1389                 if self.video.views is not "not available":
1390                         self["views"].setText(_("Views: ") + str(self.video.views))
1391
1392         def setWindowTitle(self):
1393                 self.setTitle(_("MyTubeVideoInfoScreen"))
1394
1395         def pageUp(self):
1396                 self["detailtext"].pageUp()
1397
1398         def pageDown(self):
1399                 self["detailtext"].pageDown()
1400
1401         def loadPreviewpics(self):
1402                 self.thumbnails = []
1403                 self.mythumbubeentries = None
1404                 self.index = 0
1405                 self.maxentries = 0
1406                 self.picloads = {}
1407                 self.mythumbubeentries = [self.video.thumbnailUrl]
1408                 self.maxentries = len(self.mythumbubeentries)-1
1409                 if self.mythumbubeentries:
1410                         currindex = 0
1411                         for entry in self.mythumbubeentries:
1412                                 thumbID = self.video.id + str(currindex)
1413                                 thumbnailFile = "/tmp/" + thumbID + ".jpg"
1414                                 currPic = [currindex,thumbID,thumbnailFile,None]
1415                                 self.thumbnails.append(currPic)
1416                                 thumbnailUrl = None
1417                                 thumbnailUrl = entry
1418                                 if thumbnailUrl is not None:
1419                                         client.downloadPage(thumbnailUrl,thumbnailFile).addCallback(self.fetchFinished,currindex,thumbID).addErrback(self.fetchFailed,currindex,thumbID)
1420                                 currindex +=1
1421                 else:
1422                         pass
1423
1424         def fetchFailed(self, string, index, id):
1425                 print "[fetchFailed] for index:" + str(index) + "for ThumbID:" + id + string.getErrorMessage()
1426
1427         def fetchFinished(self, string, index, id):
1428                 print "[fetchFinished] for index:" + str(index) + " for ThumbID:" + id
1429                 self.decodePic(index)
1430
1431         def decodePic(self, index):
1432                 sc = AVSwitch().getFramebufferScale()
1433                 self.picloads[index] = ePicLoad()
1434                 self.picloads[index].conn = self.picloads[index].PictureData.connect(boundFunction(self.finish_decode, index))
1435                 for entry in self.thumbnails:
1436                         if entry[0] == index:
1437                                 self.index = index
1438                                 thumbnailFile = entry[2]
1439                                 if (os_path.exists(thumbnailFile) == True):
1440                                         print "[decodePic] DECODING THUMBNAIL for INDEX:"+  str(self.index) + "and file: " + thumbnailFile
1441                                         self.picloads[index].setPara((self["thumbnail"].instance.size().width(), self["thumbnail"].instance.size().height(), sc[0], sc[1], False, 1, "#00000000"))
1442                                         self.picloads[index].startDecode(thumbnailFile)
1443                                 else:
1444                                         print "[decodePic] Thumbnail file NOT FOUND !!!-->:",thumbnailFile
1445
1446         def finish_decode(self, picindex = None, picInfo=None):
1447                 print "finish_decode - of INDEX", picindex
1448                 ptr = self.picloads[picindex].getData()
1449                 if ptr != None:
1450                         self.thumbnails[picindex][3] = ptr
1451                         if (os_path.exists(self.thumbnails[picindex][2]) == True):
1452                                 print "removing", self.thumbnails[picindex][2]
1453                                 os_remove(self.thumbnails[picindex][2])
1454                                 del self.picloads[picindex]
1455                                 if len(self.picloads) == 0:
1456                                         self.timer.startLongTimer(3)
1457
1458         def picloadTimeout(self):
1459                 self.timer.stop()
1460                 if len(self.picloads) == 0:
1461                                 self.buildInfoList()
1462                 else:
1463                         self.timer.startLongTimer(2)
1464
1465         def buildInfoList(self):
1466                 self.infolist = []
1467                 thumb0 = None
1468                 thumb1 = None
1469                 thumb2 = None
1470                 thumb3 = None
1471                 count = len(self.thumbnails)
1472                 if count > 0:
1473                         thumb0 = self.thumbnails[0][3]
1474                 if count > 1:
1475                         thumb1 = self.thumbnails[1][3]
1476                 if count > 2:
1477                         thumb2 = self.thumbnails[2][3]
1478                 if count > 3:
1479                         thumb3 = self.thumbnails[3][3]
1480                 self.infolist.append(( thumb0, thumb1, thumb2, thumb3))
1481                 if len(self.infolist):
1482                         self["infolist"].style = "default"
1483                         self["infolist"].disable_callbacks = True
1484                         self["infolist"].list = self.infolist
1485                         self["infolist"].disable_callbacks = False
1486                         self["infolist"].setIndex(0)
1487                         self["infolist"].setList(self.infolist)
1488                         self["infolist"].updateList(self.infolist)
1489
1490
1491 class MyTubeVideoHelpScreen(Screen):
1492         skin = """
1493                 <screen name="MyTubeVideoHelpScreen" flags="wfNoBorder" position="0,0" size="720,576" title="MyTube - Help" >
1494                         <ePixmap position="0,0" zPosition="-1" size="720,576" pixmap="~/mytubemain_bg.png" alphatest="on" transparent="1" backgroundColor="transparent"/>
1495                         <widget name="title" position="60,50" size="600,50" zPosition="5" valign="center" halign="left" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
1496                         <widget name="detailtext" position="60,120" size="610,370" zPosition="10" font="Regular;21" transparent="1" halign="left" valign="top"/>
1497                         <ePixmap position="100,500" size="100,40" zPosition="0" pixmap="~/plugin.png" alphatest="on" transparent="1" />
1498                         <ePixmap position="220,500" zPosition="4" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
1499                         <widget name="key_red" position="220,500" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
1500                 </screen>"""
1501
1502         def __init__(self, session, plugin_path, wantedinfo = None, wantedtitle = None):
1503                 Screen.__init__(self, session)
1504                 self.session = session
1505                 self.skin_path = plugin_path
1506                 self.wantedinfo = wantedinfo
1507                 self.wantedtitle = wantedtitle
1508                 self["title"] = Label()
1509                 self["key_red"] = Button(_("Close"))
1510                 self["detailtext"] = ScrollLabel()
1511
1512                 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
1513                 {
1514                         "back": self.close,
1515                         "red": self.close,
1516                         "up": self.pageUp,
1517                         "down": self.pageDown,
1518                         "left": self.pageUp,
1519                         "right": self.pageDown,
1520                 }, -2)
1521
1522                 self.onLayoutFinish.append(self.layoutFinished)
1523                 self.onShown.append(self.setWindowTitle)
1524
1525         def layoutFinished(self):
1526                 if self.wantedtitle is None:
1527                         self["title"].setText(_("Help"))
1528                 else:
1529                         self["title"].setText(self.wantedtitle)
1530                 if self.wantedinfo is None:
1531                         self["detailtext"].setText(_("This is the help screen. Feed me with something to display."))
1532                 else:
1533                         self["detailtext"].setText(self.wantedinfo)
1534
1535         def setWindowTitle(self):
1536                 self.setTitle(_("MyTubeVideohelpScreen"))
1537
1538         def pageUp(self):
1539                 self["detailtext"].pageUp()
1540
1541         def pageDown(self):
1542                 self["detailtext"].pageDown()
1543
1544
1545 class MyTubePlayer(Screen, InfoBarNotifications, InfoBarSeek):
1546         STATE_IDLE = 0
1547         STATE_PLAYING = 1
1548         STATE_PAUSED = 2
1549         ENABLE_RESUME_SUPPORT = True
1550         ALLOW_SUSPEND = True
1551
1552         skin = """<screen name="MyTubePlayer" flags="wfNoBorder" position="0,380" size="720,160" title="InfoBar" backgroundColor="transparent">
1553                 <ePixmap position="0,0" pixmap="skin_default/info-bg_mp.png" zPosition="-1" size="720,160" />
1554                 <ePixmap position="29,40" pixmap="skin_default/screws_mp.png" size="665,104" alphatest="on" />
1555                 <ePixmap position="48,70" pixmap="skin_default/icons/mp_buttons.png" size="108,13" alphatest="on" />
1556                 <ePixmap pixmap="skin_default/icons/icon_event.png" position="207,78" size="15,10" alphatest="on" />
1557                 <widget source="session.CurrentService" render="Label" position="230,73" size="360,40" font="Regular;20" backgroundColor="#263c59" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1">
1558                         <convert type="ServiceName">Name</convert>
1559                 </widget>
1560                 <widget source="session.CurrentService" render="Label" position="580,73" size="90,24" font="Regular;20" halign="right" backgroundColor="#4e5a74" transparent="1">
1561                         <convert type="ServicePosition">Length</convert>
1562                 </widget>
1563                 <widget source="session.CurrentService" render="Label" position="205,129" size="100,20" font="Regular;18" halign="center" valign="center" backgroundColor="#06224f" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1">
1564                         <convert type="ServicePosition">Position</convert>
1565                 </widget>
1566                 <widget source="session.CurrentService" render="PositionGauge" position="300,133" size="270,10" zPosition="2" pointer="skin_default/position_pointer.png:540,0" transparent="1" foregroundColor="#20224f">
1567                         <convert type="ServicePosition">Gauge</convert>
1568                 </widget>
1569                 <widget source="session.CurrentService" render="Label" position="576,129" size="100,20" font="Regular;18" halign="center" valign="center" backgroundColor="#06224f" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1">
1570                         <convert type="ServicePosition">Remaining</convert>
1571                 </widget>
1572                 </screen>"""
1573
1574         def __init__(self, session, service, lastservice, infoCallback = None, nextCallback = None, prevCallback = None):
1575                 Screen.__init__(self, session)
1576                 InfoBarNotifications.__init__(self)
1577                 InfoBarSeek.__init__(self)
1578                 self.session = session
1579                 self.service = service
1580                 self.infoCallback = infoCallback
1581                 self.nextCallback = nextCallback
1582                 self.prevCallback = prevCallback
1583                 self.screen_timeout = 5000
1584                 self.nextservice = None
1585
1586                 print "evEOF=%d" % iPlayableService.evEOF
1587                 self.__event_tracker = ServiceEventTracker(screen = self, eventmap =
1588                         {
1589                                 iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged,
1590                                 iPlayableService.evStart: self.__serviceStarted,
1591                                 iPlayableService.evEOF: self.__evEOF,
1592                         })
1593
1594                 self["actions"] = ActionMap(["OkCancelActions", "InfobarSeekActions", "MediaPlayerActions", "MovieSelectionActions"],
1595                 {
1596                                 "ok": self.ok,
1597                                 "cancel": self.leavePlayer,
1598                                 "stop": self.leavePlayer,
1599                                 "playpauseService": self.playpauseService,
1600                                 "seekFwd": self.playNextFile,
1601                                 "seekBack": self.playPrevFile,
1602                                 "showEventInfo": self.showVideoInfo,
1603                         }, -2)
1604
1605
1606                 self.lastservice = lastservice
1607
1608                 self.hidetimer = eTimer()
1609                 self.hidetimer_conn = self.hidetimer.timeout.connect(self.ok)
1610                 self.returning = False
1611
1612                 self.state = self.STATE_PLAYING
1613                 self.lastseekstate = self.STATE_PLAYING
1614
1615                 self.onPlayStateChanged = [ ]
1616                 self.__seekableStatusChanged()
1617
1618                 self.play()
1619                 self.onClose.append(self.__onClose)
1620
1621         def __onClose(self):
1622                 self.session.nav.stopService()
1623
1624         def __evEOF(self):
1625                 print "evEOF=%d" % iPlayableService.evEOF
1626                 print "Event EOF"
1627                 self.handleLeave(config.plugins.mytube.general.on_movie_stop.value)
1628
1629         def __setHideTimer(self):
1630                 self.hidetimer.start(self.screen_timeout)
1631
1632         def showInfobar(self):
1633                 self.show()
1634                 if self.state == self.STATE_PLAYING:
1635                         self.__setHideTimer()
1636                 else:
1637                         pass
1638
1639         def hideInfobar(self):
1640                 self.hide()
1641                 self.hidetimer.stop()
1642
1643         def ok(self):
1644                 if self.shown:
1645                         self.hideInfobar()
1646                 else:
1647                         self.showInfobar()
1648
1649         def showVideoInfo(self):
1650                 if self.shown:
1651                         self.hideInfobar()
1652                 if self.infoCallback is not None:
1653                         self.infoCallback()
1654
1655         def playNextFile(self):
1656                 print "playNextFile"
1657                 nextservice,error = self.nextCallback()
1658                 print "nextservice--->",nextservice
1659                 if nextservice is None:
1660                         self.handleLeave(config.plugins.mytube.general.on_movie_stop.value, error)
1661                 else:
1662                         self.playService(nextservice)
1663                         self.showInfobar()
1664
1665         def playPrevFile(self):
1666                 print "playPrevFile"
1667                 prevservice,error = self.prevCallback()
1668                 if prevservice is None:
1669                         self.handleLeave(config.plugins.mytube.general.on_movie_stop.value, error)
1670                 else:
1671                         self.playService(prevservice)
1672                         self.showInfobar()
1673
1674         def playagain(self):
1675                 print "playagain"
1676                 if self.state != self.STATE_IDLE:
1677                         self.stopCurrent()
1678                 self.play()
1679
1680         def playService(self, newservice):
1681                 if self.state != self.STATE_IDLE:
1682                         self.stopCurrent()
1683                 self.service = newservice
1684                 self.play()
1685
1686         def play(self):
1687                 if self.state == self.STATE_PAUSED:
1688                         if self.shown:
1689                                 self.__setHideTimer()
1690                 self.state = self.STATE_PLAYING
1691                 self.session.nav.playService(self.service)
1692                 if self.shown:
1693                         self.__setHideTimer()
1694
1695         def stopCurrent(self):
1696                 print "stopCurrent"
1697                 self.session.nav.stopService()
1698                 self.state = self.STATE_IDLE
1699
1700         def playpauseService(self):
1701                 print "playpauseService"
1702                 if self.state == self.STATE_PLAYING:
1703                         self.pauseService()
1704                 elif self.state == self.STATE_PAUSED:
1705                         self.unPauseService()
1706
1707         def pauseService(self):
1708                 print "pauseService"
1709                 if self.state == self.STATE_PLAYING:
1710                         self.setSeekState(self.STATE_PAUSED)
1711
1712         def unPauseService(self):
1713                 print "unPauseService"
1714                 if self.state == self.STATE_PAUSED:
1715                         self.setSeekState(self.STATE_PLAYING)
1716
1717
1718         def getSeek(self):
1719                 service = self.session.nav.getCurrentService()
1720                 if service is None:
1721                         return None
1722
1723                 seek = service.seek()
1724
1725                 if seek is None or not seek.isCurrentlySeekable():
1726                         return None
1727
1728                 return seek
1729
1730         def isSeekable(self):
1731                 if self.getSeek() is None:
1732                         return False
1733                 return True
1734
1735         def __seekableStatusChanged(self):
1736                 print "seekable status changed!"
1737                 if not self.isSeekable():
1738                         self["SeekActions"].setEnabled(False)
1739                         self.setSeekState(self.STATE_PLAYING)
1740                 else:
1741                         self["SeekActions"].setEnabled(True)
1742                         print "seekable"
1743
1744         def __serviceStarted(self):
1745                 self.state = self.STATE_PLAYING
1746                 self.__seekableStatusChanged()
1747
1748         def setSeekState(self, wantstate, onlyGUI = False):
1749                 print "setSeekState"
1750                 if wantstate == self.STATE_PAUSED:
1751                         print "trying to switch to Pause- state:",self.STATE_PAUSED
1752                 elif wantstate == self.STATE_PLAYING:
1753                         print "trying to switch to playing- state:",self.STATE_PLAYING
1754                 service = self.session.nav.getCurrentService()
1755                 if service is None:
1756                         print "No Service found"
1757                         return False
1758                 pauseable = service.pause()
1759                 if pauseable is None:
1760                         print "not pauseable."
1761                         self.state = self.STATE_PLAYING
1762
1763                 if pauseable is not None:
1764                         print "service is pausable"
1765                         if wantstate == self.STATE_PAUSED:
1766                                 print "WANT TO PAUSE"
1767                                 pauseable.pause()
1768                                 self.state = self.STATE_PAUSED
1769                                 if not self.shown:
1770                                         self.hidetimer.stop()
1771                                         self.show()
1772                         elif wantstate == self.STATE_PLAYING:
1773                                 print "WANT TO PLAY"
1774                                 pauseable.unpause()
1775                                 self.state = self.STATE_PLAYING
1776                                 if self.shown:
1777                                         self.__setHideTimer()
1778
1779                 for c in self.onPlayStateChanged:
1780                         c(self.state)
1781
1782                 return True
1783
1784         def handleLeave(self, how, error = False):
1785                 self.is_closing = True
1786                 if how == "ask":
1787                         list = (
1788                                 (_("Yes"), "quit"),
1789                                 (_("No, but play video again"), "playagain"),
1790                                 (_("Yes, but play next video"), "playnext"),
1791                                 (_("Yes, but play previous video"), "playprev"),
1792                         )
1793                         if error is False:
1794                                 self.session.openWithCallback(self.leavePlayerConfirmed, ChoiceBox, title=_("Stop playing this movie?"), list = list)
1795                         else:
1796                                 self.session.openWithCallback(self.leavePlayerConfirmed, ChoiceBox, title=_("No playable video found! Stop playing this movie?"), list = list)
1797                 else:
1798                         self.leavePlayerConfirmed([True, how])
1799
1800         def leavePlayer(self):
1801                 self.handleLeave(config.plugins.mytube.general.on_movie_stop.value)
1802
1803         def leavePlayerConfirmed(self, answer):
1804                 answer = answer and answer[1]
1805                 if answer == "quit":
1806                         print 'quited'
1807                         self.close()
1808                 elif answer == "playnext":
1809                         self.playNextFile()
1810                 elif answer == "playprev":
1811                         self.playPrevFile()
1812                 elif answer == "playagain":
1813                         self.playagain()
1814
1815         def doEofInternal(self, playing):
1816                 if not self.execing:
1817                         return
1818                 if not playing :
1819                         return
1820                 self.handleLeave(config.usage.on_movie_eof.value)
1821
1822 def MyTubeMain(session, **kwargs):
1823         l2 = False
1824         l2cert = etpm.getData(eTPM.DT_LEVEL2_CERT)
1825         if l2cert is None:
1826                 print "l2cert not found"
1827                 return
1828
1829         l2key = validate_cert(l2cert, rootkey)
1830         if l2key is None:
1831                 print "l2cert invalid"
1832                 return
1833         l2 = True
1834         if l2:
1835                 session.open(MyTubePlayerMainScreen, l2key)
1836
1837
1838 def Plugins(path, **kwargs):
1839         global plugin_path
1840         plugin_path = path
1841         return PluginDescriptor(
1842                 name=_("My TubePlayer"),
1843                 description=_("Play YouTube movies"),
1844                 where = [ PluginDescriptor.WHERE_EXTENSIONSMENU, PluginDescriptor.WHERE_PLUGINMENU ],
1845                 icon = "plugin.png", fnc = MyTubeMain)