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