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