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.Pixmap import Pixmap
7 from Components.ProgressBar import ProgressBar
8 from Components.ScrollLabel import ScrollLabel
9 from Components.Sources.List import List
10 from Components.Task import Task, Job, job_manager
11 from Components.config import config, ConfigSelection, ConfigSubsection, ConfigText, ConfigYesNo, getConfigListEntry
12 #, ConfigIP, ConfigNumber, ConfigLocations
13 from Screens.ChoiceBox import ChoiceBox
14 from Screens.MessageBox import MessageBox
15 from Screens.Screen import Screen
16 from Screens.VirtualKeyBoard import VirtualKeyBoard
17 from Tools.BoundFunction import boundFunction
18 from Tools.Directories import resolveFilename, SCOPE_HDD, SCOPE_CURRENT_PLUGIN
19 from Tools.Downloader import downloadWithProgress
20 from Tools.Log import Log
22 from Plugins.Plugin import PluginDescriptor
24 from MyTubePlayer import MyTubePlayer
25 from MyTubeSearch import ConfigTextWithGoogleSuggestions, MyTubeTasksScreen, MyTubeHistoryScreen
26 from MyTubeService import validate_cert, get_rnd, myTubeService
27 from MyTubeSettings import MyTubeSettingsScreen
29 from Plugins.SystemPlugins.TubeLib.youtube.Search import Search
31 from __init__ import decrypt_block
33 from enigma import eTPM, eTimer, ePoint, ePicLoad, eServiceReference
34 from os import path as os_path, remove as os_remove
35 from twisted.web import client
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', ':', '?']
40 config.plugins.mytube = ConfigSubsection()
41 config.plugins.mytube.search = ConfigSubsection()
44 config.plugins.mytube.search.searchTerm = ConfigTextWithGoogleSuggestions("", False)
45 config.plugins.mytube.search.orderBy = ConfigSelection(
47 ("relevance", _("Relevance")),
48 ("viewCount", _("View Count")),
49 ("date", _("Published")),
50 ("rating", _("Rating"))
52 config.plugins.mytube.search.time = ConfigSelection(
54 ("all_time", _("All Time")),
55 ("this_month", _("This Month")),
56 ("this_week", _("This Week")),
59 config.plugins.mytube.search.safeSearch = ConfigSelection(
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(
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"))
85 config.plugins.mytube.search.lr = ConfigSelection(
87 ("au", _("Australia")),
90 ("cz", _("Czech Republic")),
93 ("gb", _("Great Britain")),
94 ("au", _("Australia")),
96 ("hk", _("Hong Kong")),
103 ("nz", _("New Zealand")),
106 ("kr", _("South Korea")),
110 ("us", _("United States"))
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(
118 ("top_rated", _("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")) ])
123 config.plugins.mytube.general.on_exit = ConfigSelection(default = "ask", choices = [
124 ("ask", _("Ask user")), ("quit", _("Return to movie list"))])
126 default = resolveFilename(SCOPE_HDD)
127 tmp = config.movielist.videodirs.value
128 if default not in tmp:
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.authenticate = ConfigYesNo(default=False)
137 class downloadJob(Job):
138 def __init__(self, url, file, title):
139 Job.__init__(self, title)
140 downloadTask(self, url, file)
142 class downloadTask(Task):
143 def __init__(self, job, url, file):
144 Task.__init__(self, job, ("download task"))
152 def run(self, callback):
153 self.callback = callback
154 self.download = downloadWithProgress(self.url,self.local)
155 self.download.addProgress(self.http_progress)
156 self.download.start().addCallback(self.http_finished).addErrback(self.http_failed)
158 def http_progress(self, recvbytes, totalbytes):
159 #print "[http_progress] recvbytes=%d, totalbytes=%d" % (recvbytes, totalbytes)
160 self.progress = int(self.end*recvbytes/float(totalbytes))
162 def http_finished(self, string=""):
163 print "[http_finished]" + str(string)
164 Task.processFinished(self, 0)
166 def http_failed(self, failure_instance=None, error_message=""):
167 if error_message == "" and failure_instance is not None:
168 error_message = failure_instance.getErrorMessage()
169 print "[http_failed] " + error_message
170 Task.processFinished(self, 1)
176 class MyTubePlayerMainScreen(Screen, ConfigListScreen):
178 #(entry, Title, Description, TubeID, thumbnail, PublishedDate,Views,duration,ratings )
180 <screen name="MyTubePlayerMainScreen" flags="wfNoBorder" position="0,0" size="720,576" title="MyTube - Browser" >
181 <ePixmap position="0,0" zPosition="-1" size="720,576" pixmap="~/mytubemain_bg.png" alphatest="on" transparent="1" backgroundColor="transparent"/>
182 <widget name="config" zPosition="2" position="60,60" size="600,50" scrollbarMode="showNever" transparent="1" />
183 <widget name="result" position="300,60" zPosition="3" size="350,50" font="Regular;21" transparent="1" backgroundColor="transparent" halign="right"/>
184 <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" >
185 <convert type="TemplatedMultiContent">
188 MultiContentEntryPixmapAlphaTest(pos = (0, 0), size = (100, 75), png = 4), # index 4 is the thumbnail
189 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
190 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
191 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
192 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
193 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
196 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
197 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
200 "fonts": [gFont("Regular", 22),gFont("Regular", 18),gFont("Regular", 26),gFont("Regular", 20)],
206 <ePixmap pixmap="skin_default/buttons/key_info.png" position="50,500" zPosition="4" size="35,25" alphatest="on" transparent="1" />
207 <ePixmap pixmap="skin_default/buttons/key_menu.png" position="50,520" zPosition="4" size="35,25" alphatest="on" transparent="1" />
208 <ePixmap position="90,500" size="100,40" zPosition="4" pixmap="~/plugin.png" alphatest="on" transparent="1" />
209 <ePixmap position="190,500" zPosition="4" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
210 <ePixmap position="330,500" zPosition="4" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
211 <ePixmap position="470,500" zPosition="4" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
212 <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" />
213 <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" />
214 <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" />
215 <widget name="ButtonBlue" pixmap="skin_default/buttons/button_blue.png" position="610,510" zPosition="10" size="15,16" transparent="1" alphatest="on" />
216 <widget name="VKeyIcon" pixmap="skin_default/vkey_icon.png" position="620,495" zPosition="10" size="60,48" transparent="1" alphatest="on" />
217 <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.
218 <widget name="HelpWindow" position="160,255" zPosition="1" size="1,1" transparent="1" alphatest="on" />
221 def __init__(self, session, l2key=None):
222 Screen.__init__(self, session)
223 self.session = session
224 self._userCodeMbx = None
227 self.skin_path = plugin_path
230 self.currentFeedName = None
232 self.queryThread = None
233 self.queryRunning = False
235 self.video_playlist = []
237 self.mytubeentries = None
243 self.screenshotList = []
244 self.pixmaps_to_load = []
247 self.oldfeedentrycount = 0
248 self.appendEntries = False
249 self.lastservice = session.nav.getCurrentlyPlayingServiceReference()
250 self.propagateUpDownNormally = True
252 self.HistoryWindow = None
254 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.")
255 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.")
256 self.currList = "configlist"
259 self["feedlist"] = List(self.videolist)
260 self["thumbnail"] = Pixmap()
261 self["thumbnail"].hide()
262 self["HelpWindow"] = Pixmap()
263 self["HelpWindow"].hide()
264 self["key_red"] = Button(_("Close"))
265 self["key_green"] = Button(_("Std. Feeds"))
266 self["key_yellow"] = Button(_("History"))
267 self["ButtonBlue"] = Pixmap()
268 self["VKeyIcon"] = Pixmap()
269 self["ButtonBlue"].hide()
270 self["VKeyIcon"].hide()
271 self["result"] = Label("")
274 self["searchactions"] = ActionMap(["ShortcutActions", "WizardActions", "HelpActions", "MediaPlayerActions"],
277 "back": self.leavePlayer,
278 "red": self.leavePlayer,
279 "blue": self.openKeyboard,
280 "yellow": self.handleHistory,
282 "down": self.handleSuggestions,
283 "left": self.keyLeft,
284 "right": self.keyRight,
285 "prevBouquet": self.switchToFeedList,
286 "nextBouquet": self.switchToConfigList,
287 "displayHelp": self.handleHelpWindow,
288 "menu" : self.handleMenu,
291 self["suggestionactions"] = ActionMap(["ShortcutActions", "WizardActions", "MediaPlayerActions", "HelpActions", "NumberActions"],
294 "back": self.switchToConfigList,
295 "red": self.switchToConfigList,
296 "nextBouquet": self.switchToConfigList,
297 "prevBouquet": self.switchToFeedList,
299 "down": self.keyDown,
300 "left": self.keyLeft,
301 "right": self.keyRight,
302 "0": self.toggleScreenVisibility
306 self["videoactions"] = ActionMap(["ShortcutActions", "WizardActions", "MediaPlayerActions", "MovieSelectionActions", "HelpActions"],
309 "back": self.leavePlayer,
310 "red": self.leavePlayer,
311 "yellow": self.handleHistory,
313 "down": self.keyDown,
314 "nextBouquet": self.switchToConfigList,
315 "green": self.keyStdFeed,
316 "showEventInfo": self.showVideoInfo,
317 "displayHelp": self.handleHelpWindow,
318 "menu" : self.handleMenu,
321 self["statusactions"] = ActionMap(["ShortcutActions", "WizardActions", "HelpActions", "MediaPlayerActions"],
323 "back": self.leavePlayer,
324 "red": self.leavePlayer,
325 "nextBouquet": self.switchToConfigList,
326 "green": self.keyStdFeed,
327 "yellow": self.handleHistory,
328 "menu": self.handleMenu
331 self["historyactions"] = ActionMap(["ShortcutActions", "WizardActions", "MediaPlayerActions", "MovieSelectionActions", "HelpActions"],
334 "back": self.closeHistory,
335 "red": self.closeHistory,
336 "yellow": self.handleHistory,
338 "down": self.keyDown,
339 "left": self.keyLeft,
340 "right": self.keyRight,
343 self["videoactions"].setEnabled(False)
344 self["statusactions"].setEnabled(False)
345 self["historyactions"].setEnabled(False)
347 self.timer_startDownload = eTimer()
348 self.timer_startDownload_conn = self.timer_startDownload.timeout.connect(self.downloadThumbnails)
349 self.timer_thumbnails = eTimer()
350 self.timer_thumbnails_conn = self.timer_thumbnails.timeout.connect(self.updateFeedThumbnails)
352 self.SearchConfigEntry = None
353 self.searchContextEntries = []
354 config.plugins.mytube.search.searchTerm.value = ""
355 ConfigListScreen.__init__(self, self.searchContextEntries, session)
357 self.onLayoutFinish.append(self.layoutFinished)
358 self.onShown.append(self.setWindowTitle)
359 self.onClose.append(self.__onClose)
362 del self.timer_startDownload
363 del self.timer_thumbnails
365 self.session.nav.playService(self.lastservice)
367 def layoutFinished(self):
368 self.currList = "status"
369 current = self["config"].getCurrent()
370 if current[1].help_window.instance is not None:
371 current[1].help_window.instance.hide()
373 l3cert = etpm.getData(eTPM.DT_LEVEL3_CERT)
374 if l3cert is None or l3cert is "":
375 self["videoactions"].setEnabled(False)
376 self["searchactions"].setEnabled(False)
377 self["config_actions"].setEnabled(False)
378 self["historyactions"].setEnabled(False)
379 self["statusactions"].setEnabled(True)
380 self.hideSuggestions()
382 self.statuslist.append(( _("Genuine Dreambox validation failed!"), _("Verify your Dreambox authenticity by running the genuine dreambox plugin!" ) ))
383 self["feedlist"].style = "state"
384 self['feedlist'].setList(self.statuslist)
387 self.l3key = validate_cert(l3cert, self.l2key)
388 if self.l3key is None:
389 print "l3cert invalid"
396 val = etpm.computeSignature(rnd)
397 result = decrypt_block(val, self.l3key)
400 if result[80:88] != rnd:
401 self.statuslist.append(( _("Genuine Dreambox validation failed!"), _("Verify your Dreambox authenticity by running the genuine dreambox plugin!" ) ))
402 self["feedlist"].style = "state"
403 self['feedlist'].setList(self.statuslist)
406 # we need to login here; startService() is fired too often for external curl
407 # self.tryUserLogin()
409 self.statuslist.append(( _("Fetching feed entries"), _("Trying to download the Youtube feed entries. Please wait..." ) ))
410 self["feedlist"].style = "state"
411 self['feedlist'].setList(self.statuslist)
412 myTubeService.addReadyCallback(self._onServiceReady)
413 if config.plugins.mytube.general.authenticate.value:
414 myTubeService.startAuthenticatedService(self._onUserCodeReady)
416 myTubeService.startService()
418 def _onServiceReady(self, ready):
419 Log.w("%s" %(ready,))
420 if self._userCodeMbx:
421 self._userCodeMbx.close()
422 self._userCodeMbx = None
425 if config.plugins.mytube.general.loadFeedOnOpen.value:
427 self.setState('getFeed')
429 self.setState('byPass')
431 def setWindowTitle(self):
432 self.setTitle(_("MyTubePlayer"))
434 def createSetup(self):
435 self.searchContextEntries = []
436 self.SearchConfigEntry = getConfigListEntry(_("Search Term(s)"), config.plugins.mytube.search.searchTerm)
437 self.searchContextEntries.append(self.SearchConfigEntry)
438 self["config"].list = self.searchContextEntries
439 self["config"].l.setList(self.searchContextEntries)
441 def setState(self,status = None):
443 self.currList = "status"
444 self["videoactions"].setEnabled(False)
445 self["searchactions"].setEnabled(False)
446 self["config_actions"].setEnabled(False)
447 self["historyactions"].setEnabled(False)
448 self["statusactions"].setEnabled(True)
449 self["ButtonBlue"].hide()
450 self["VKeyIcon"].hide()
452 self.hideSuggestions()
454 if self.l3key is not None:
458 val = etpm.computeSignature(rnd)
459 result = decrypt_block(val, self.l3key)
460 if not result or result[80:88] != rnd:
461 self["key_green"].show()
462 self.statuslist.append(( _("Genuine Dreambox validation failed!"), _("Verify your Dreambox authenticity by running the genuine dreambox plugin!" ) ))
463 self["feedlist"].style = "state"
464 self['feedlist'].setList(self.statuslist)
467 print "Genuine Dreambox validation passed"
469 if self.HistoryWindow is not None:
470 self.HistoryWindow.deactivate()
471 self.HistoryWindow.instance.hide()
472 if status == 'getFeed':
473 self.statuslist.append(( _("Fetching feed entries"), _("Trying to download the Youtube feed entries. Please wait..." ) ))
474 elif status == 'getSearchFeed':
475 self.statuslist.append(( _("Fetching search entries"), _("Trying to download the Youtube search results. Please wait..." ) ))
476 elif status == 'Error':
477 self.statuslist.append(( _("An error occured."), _("There was an error getting the feed entries. Please try again." ) ))
478 elif status == 'noVideos':
479 self["key_green"].show()
480 self.statuslist.append(( _("No videos to display"), _("Please select a standard feed or try searching for videos." ) ))
481 elif status == 'byPass':
482 self.statuslist.append(( _("Not fetching feed entries"), _("Please enter your search term." ) ))
483 self["feedlist"].style = "state"
484 self['feedlist'].setList(self.statuslist)
485 self.switchToConfigList()
486 self["feedlist"].style = "state"
487 self['feedlist'].setList(self.statuslist)
490 def _onUserCodeReady(self, userCode):
491 self._userCodeMbx = self.session.open(MessageBox, str(_("Please visit: %s\nAnd enter: %s") % (userCode.verification_url, userCode.user_code)), type=MessageBox.TYPE_INFO, title=_("Authentication awaiting"))
494 def handleHelpWindow(self):
495 print "[handleHelpWindow]"
496 if self.currList == "configlist":
497 self.hideSuggestions()
498 self.session.openWithCallback(self.ScreenClosed, MyTubeVideoHelpScreen, self.skin_path, wantedinfo = self.searchtext, wantedtitle = _("MyTubePlayer Help") )
499 elif self.currList == "feedlist":
500 self.session.openWithCallback(self.ScreenClosed, MyTubeVideoHelpScreen, self.skin_path, wantedinfo = self.feedtext, wantedtitle = _("MyTubePlayer Help") )
502 def handleFirstHelpWindow(self):
503 print "[handleFirstHelpWindow]"
504 if config.plugins.mytube.general.showHelpOnOpen.value is True:
505 if self.currList == "configlist":
506 self.hideSuggestions()
507 self.session.openWithCallback(self.firstRunHelpClosed, MyTubeVideoHelpScreen, self.skin_path,wantedinfo = self.feedtext, wantedtitle = _("MyTubePlayer Help") )
509 self.FirstRun = False
511 def firstRunHelpClosed(self):
512 if self.FirstRun == True:
513 self.FirstRun = False
514 self.switchToConfigList()
516 def handleMenu(self):
517 if self.currList == "configlist" or self.currList == "status":
519 (_("MyTube Settings"), "settings"),
521 self.hideSuggestions()
522 self.session.openWithCallback(self.openMenu, ChoiceBox, title=_("Select your choice."), list = menulist)
524 elif self.currList == "feedlist":
525 menulist = [(_("MyTube Settings"), "settings")]
527 (_("Related videos"), "related"),
528 (_("Channel videos"), "channel_videos"),
531 if myTubeService.is_auth() is True:
533 (_("Subscribe to channel"), "subscribe"),
534 (_("Add to favorites"), "favorite"),
537 if config.usage.setup_level.index >= 2: # expert+
539 (_("Download Video"), "download"),
540 (_("View active downloads"), "downview")
543 self.hideSuggestions()
544 self.session.openWithCallback(self.openMenu, ChoiceBox, title=_("Select your choice."), list = menulist)
546 def openMenu(self, answer):
547 answer = answer and answer[1]
548 if answer == "settings":
549 print "settings selected"
550 self.session.openWithCallback(self.ScreenClosed,MyTubeSettingsScreen, self.skin_path )
551 elif answer == "related":
552 current = self["feedlist"].getCurrent()[0]
553 self.setState('getFeed')
554 self.getRelatedVideos(current)
555 elif answer == "channel_videos":
556 current = self["feedlist"].getCurrent()[0]
557 self.setState('getFeed')
558 self.getChannelVideos(current)
559 elif answer == "subscribe":
560 current = self["feedlist"].getCurrent()[0]
561 self.session.open(MessageBox, current.subscribeToUser(), MessageBox.TYPE_INFO)
562 elif answer == "favorite":
563 current = self["feedlist"].getCurrent()[0]
564 self.session.open(MessageBox, current.addToFavorites(), MessageBox.TYPE_INFO)
566 elif answer == "response":
567 current = self["feedlist"].getCurrent()[0]
568 self.setState('getFeed')
569 self.getResponseVideos(current)
570 elif answer == "download":
571 if self.currList == "feedlist":
572 current = self[self.currList].getCurrent()
577 filename = str(config.plugins.mytube.general.videodir.value)+ str(video.title) + '.mp4'
578 job_manager.AddJob(downloadJob(myurl,filename, str(video.title)[:30]))
579 elif answer == "downview":
581 for job in job_manager.getPendingJobs():
582 self.tasklist.append((job,job.name,job.getStatustext(),int(100*job.progress/float(job.end)) ,str(100*job.progress/float(job.end)) + "%" ))
583 self.session.open(MyTubeTasksScreen, self.skin_path , self.tasklist)
587 def openKeyboard(self):
588 self.hideSuggestions()
589 self.session.openWithCallback(self.SearchEntryCallback, VirtualKeyBoard, title = (_("Enter your search term(s)")), text = config.plugins.mytube.search.searchTerm.value)
591 def ScreenClosed(self):
592 print "ScreenCLosed, restoring old window state"
593 if self.currList == "historylist":
594 if self.HistoryWindow.status() is False:
595 self.HistoryWindow.activate()
596 self.HistoryWindow.instance.show()
597 elif self.currList == "configlist":
598 self.switchToConfigList()
599 ConfigListScreen.keyOK(self)
600 elif self.currList == "feedlist":
601 self.switchToFeedList()
603 def SearchEntryCallback(self, callback = None):
604 if callback is not None and len(callback):
605 config.plugins.mytube.search.searchTerm.value = callback
606 ConfigListScreen.keyOK(self)
607 self["config"].getCurrent()[1].getSuggestions()
608 current = self["config"].getCurrent()
609 if current[1].help_window.instance is not None:
610 current[1].help_window.instance.show()
611 if current[1].suggestionsWindow.instance is not None:
612 current[1].suggestionsWindow.instance.show()
613 self.propagateUpDownNormally = True
615 def openStandardFeedClosed(self, answer):
616 answer = answer and answer[1]
617 if answer is not None:
618 self.setState('getFeed')
619 self.appendEntries = False
620 self.getFeed(videoCategoryId=answer)
622 def handleLeave(self, how):
623 self.is_closing = True
625 if self.currList == "configlist":
628 (_("No"), "continue"),
629 (_("No, but switch to video entries."), "switch2feed")
634 (_("No"), "continue"),
635 (_("No, but switch to video search."), "switch2search")
637 self.session.openWithCallback(self.leavePlayerConfirmed, ChoiceBox, title=_("Really quit MyTube Player?"), list = list)
639 self.leavePlayerConfirmed([True, how])
641 def leavePlayer(self):
643 if self.HistoryWindow is not None:
644 self.HistoryWindow.deactivate()
645 self.HistoryWindow.instance.hide()
646 if self.currList == "configlist":
647 current = self["config"].getCurrent()
648 if current[1].suggestionsWindow.activeState is True:
649 self.propagateUpDownNormally = True
650 current[1].deactivateSuggestionList()
651 self["config"].invalidateCurrent()
653 self.hideSuggestions()
654 self.handleLeave(config.plugins.mytube.general.on_exit.value)
656 self.hideSuggestions()
657 self.handleLeave(config.plugins.mytube.general.on_exit.value)
659 def leavePlayerConfirmed(self, answer):
660 answer = answer and answer[1]
663 elif answer == "continue":
664 if self.currList == "historylist":
665 if self.HistoryWindow.status() is False:
666 self.HistoryWindow.activate()
667 self.HistoryWindow.instance.show()
668 elif self.currList == "configlist":
669 self.switchToConfigList()
670 elif self.currList == "feedlist":
671 self.switchToFeedList()
672 elif answer == "switch2feed":
673 self.switchToFeedList()
674 elif answer == "switch2search":
675 self.switchToConfigList()
677 if self.currList == "historylist":
678 if self.HistoryWindow.status() is False:
679 self.HistoryWindow.activate()
680 self.HistoryWindow.instance.show()
681 elif self.currList == "configlist":
682 self.switchToConfigList()
683 elif self.currList == "feedlist":
684 self.switchToFeedList()
687 myTubeService.onReady.remove(self._onServiceReady)
689 if self["config"].getCurrent()[1].suggestionsWindow is not None:
690 self.session.deleteDialog(self["config"].getCurrent()[1].suggestionsWindow)
691 if self.HistoryWindow is not None:
692 self.session.deleteDialog(self.HistoryWindow)
693 if config.plugins.mytube.general.showHelpOnOpen.value is True:
694 config.plugins.mytube.general.showHelpOnOpen.value = False
695 config.plugins.mytube.general.showHelpOnOpen.save()
696 if not config.plugins.mytube.general.clearHistoryOnClose.value:
697 if self.History and len(self.History):
698 config.plugins.mytube.general.history.value = ",".join(self.History)
700 config.plugins.mytube.general.history.value = ""
701 config.plugins.mytube.general.history.save()
702 config.plugins.mytube.general.save()
703 config.plugins.mytube.save()
708 print "self.currList im KeyOK",self.currList
709 if self.currList == "configlist" or self.currList == "suggestionslist":
710 self["config"].invalidateCurrent()
711 if config.plugins.mytube.search.searchTerm.value != "":
713 searchTerm = config.plugins.mytube.search.searchTerm.value
714 print "Search searchcontext",searchTerm
715 if isinstance(self["config"].getCurrent()[1], ConfigTextWithGoogleSuggestions) and not self.propagateUpDownNormally:
716 self.propagateUpDownNormally = True
717 self["config"].getCurrent()[1].deactivateSuggestionList()
718 self.setState('getSearchFeed')
719 self.runSearch(searchTerm)
720 elif self.currList == "feedlist":
721 current = self[self.currList].getCurrent()
725 if video is not None:
727 print "Playing URL",myurl
728 if myurl is not None:
729 myreference = eServiceReference(4097,0,myurl)
730 myreference.setName(video.title)
731 self.session.openWithCallback(self.onPlayerClosed, MyTubePlayer, myreference, self.lastservice, infoCallback = self.showVideoInfo, nextCallback = self.getNextEntry, prevCallback = self.getPrevEntry )
733 self.session.open(MessageBox, _("Sorry, video is not available!"), MessageBox.TYPE_INFO)
734 elif self.currList == "historylist":
735 if self.HistoryWindow is not None:
736 config.plugins.mytube.search.searchTerm.value = self.HistoryWindow.getSelection()
737 self["config"].invalidateCurrent()
738 if config.plugins.mytube.search.searchTerm.value != "":
739 searchTerm = config.plugins.mytube.search.searchTerm.value
740 print "Search searchcontext",searchTerm
741 self.setState('getSearchFeed')
742 self.runSearch(searchTerm)
744 def onPlayerClosed(self):
745 if config.plugins.mytube.general.resetPlayService.value is True:
746 self.session.nav.playService(self.lastservice)
748 def toggleScreenVisibility(self):
749 if self.shown is True:
755 print "self.currList im KeyUp",self.currList
756 if self.currList == "suggestionslist":
757 if config.plugins.mytube.search.searchTerm.value != "":
758 if not self.propagateUpDownNormally:
759 self["config"].getCurrent()[1].suggestionListUp()
760 self["config"].invalidateCurrent()
761 elif self.currList == "feedlist":
762 self[self.currList].selectPrevious()
763 elif self.currList == "historylist":
764 if self.HistoryWindow is not None and self.HistoryWindow.shown:
765 self.HistoryWindow.up()
768 print "self.currList im KeyDown",self.currList
769 if self.currList == "suggestionslist":
770 if config.plugins.mytube.search.searchTerm.value != "":
771 if not self.propagateUpDownNormally:
772 self["config"].getCurrent()[1].suggestionListDown()
773 self["config"].invalidateCurrent()
774 elif self.currList == "feedlist":
775 print self[self.currList].count()
776 print self[self.currList].index
777 if self[self.currList].index == self[self.currList].count()-1 and myTubeService.hasNextPage():
778 # load new feeds on last selected item
779 if config.plugins.mytube.general.AutoLoadFeeds.value is False:
780 self.session.openWithCallback(self.getNextEntries, MessageBox, _("Do you want to see more entries?"))
782 self.getNextEntries(True)
784 self[self.currList].selectNext()
785 elif self.currList == "historylist":
786 if self.HistoryWindow is not None and self.HistoryWindow.shown:
787 self.HistoryWindow.down()
789 print "self.currList im KeyRight",self.currList
790 if self.propagateUpDownNormally:
791 ConfigListScreen.keyRight(self)
793 if self.currList == "suggestionslist":
794 if config.plugins.mytube.search.searchTerm.value != "":
795 self["config"].getCurrent()[1].suggestionListPageDown()
796 self["config"].invalidateCurrent()
797 elif self.currList == "historylist":
798 if self.HistoryWindow is not None and self.HistoryWindow.shown:
799 self.HistoryWindow.pageDown()
802 print "self.currList im kEyLeft",self.currList
803 if self.propagateUpDownNormally:
804 ConfigListScreen.keyLeft(self)
806 if self.currList == "suggestionslist":
807 if config.plugins.mytube.search.searchTerm.value != "":
808 self["config"].getCurrent()[1].suggestionListPageUp()
809 self["config"].invalidateCurrent()
810 elif self.currList == "historylist":
811 if self.HistoryWindow is not None and self.HistoryWindow.shown:
812 self.HistoryWindow.pageDown()
813 def keyStdFeed(self):
814 self.hideSuggestions()
816 for category in myTubeService.getCategories():
817 menulist.append((category.title, category.id))
818 # if myTubeService.is_auth():
820 # (_("My Subscriptions"), "my_subscriptions"),
821 # (_("My Favorites"), "my_favorites"),
822 # (_("My History"), "my_history"),
823 # (_("My Watch Later"), "my_watch_later"),
824 # (_("My Recommendations"), "my_recommendations"),
825 # (_("My Uploads"), "my_uploads"),
828 self.session.openWithCallback(self.openStandardFeedClosed, ChoiceBox, title=_("Select new feed to view."), list = menulist)
830 def handleSuggestions(self):
831 print "handleSuggestions"
832 print "self.currList",self.currList
833 if self.currList == "configlist":
834 self.switchToSuggestionsList()
835 elif self.currList == "historylist":
836 if self.HistoryWindow is not None and self.HistoryWindow.shown:
837 self.HistoryWindow.down()
839 def switchToSuggestionsList(self):
840 print "switchToSuggestionsList"
841 self.currList = "suggestionslist"
842 self["ButtonBlue"].hide()
843 self["VKeyIcon"].hide()
844 self["statusactions"].setEnabled(False)
845 self["config_actions"].setEnabled(False)
846 self["videoactions"].setEnabled(False)
847 self["searchactions"].setEnabled(False)
848 self["suggestionactions"].setEnabled(True)
849 self["historyactions"].setEnabled(False)
850 self["key_green"].hide()
851 self.propagateUpDownNormally = False
852 self["config"].invalidateCurrent()
853 if self.HistoryWindow is not None and self.HistoryWindow.shown:
854 self.HistoryWindow.deactivate()
855 self.HistoryWindow.instance.hide()
857 def switchToConfigList(self):
858 print "switchToConfigList"
859 self.currList = "configlist"
860 self["config_actions"].setEnabled(True)
861 self["historyactions"].setEnabled(False)
862 self["statusactions"].setEnabled(False)
863 self["videoactions"].setEnabled(False)
864 self["suggestionactions"].setEnabled(False)
865 self["searchactions"].setEnabled(True)
866 self["key_green"].hide()
867 self["ButtonBlue"].show()
868 self["VKeyIcon"].show()
869 self["config"].invalidateCurrent()
870 helpwindowpos = self["HelpWindow"].getPosition()
871 current = self["config"].getCurrent()
872 if current[1].help_window.instance is not None:
873 current[1].help_window.instance.move(ePoint(helpwindowpos[0],helpwindowpos[1]))
874 current[1].help_window.instance.show()
875 if current[1].suggestionsWindow.instance is not None:
876 current[1].suggestionsWindow.instance.show()
877 self["config"].getCurrent()[1].getSuggestions()
878 self.propagateUpDownNormally = True
879 if self.HistoryWindow is not None and self.HistoryWindow.shown:
880 self.HistoryWindow.deactivate()
881 self.HistoryWindow.instance.hide()
882 if self.FirstRun == True:
883 self.handleFirstHelpWindow()
885 def switchToFeedList(self, append = False):
886 print "switchToFeedList"
887 print "switching to feedlist from:",self.currList
888 print "len(self.videolist):",len(self.videolist)
889 if self.HistoryWindow is not None and self.HistoryWindow.shown:
890 self.HistoryWindow.deactivate()
891 self.HistoryWindow.instance.hide()
892 self.hideSuggestions()
893 if len(self.videolist):
894 self.currList = "feedlist"
895 self["ButtonBlue"].hide()
896 self["VKeyIcon"].hide()
897 self["videoactions"].setEnabled(True)
898 self["suggestionactions"].setEnabled(False)
899 self["searchactions"].setEnabled(False)
900 self["statusactions"].setEnabled(False)
901 self["historyactions"].setEnabled(False)
902 self["key_green"].show()
903 self["config_actions"].setEnabled(False)
905 self[self.currList].setIndex(0)
906 self["feedlist"].updateList(self.videolist)
908 self.setState('noVideos')
911 def switchToHistory(self):
912 print "switchToHistory"
913 self.oldlist = self.currList
914 self.currList = "historylist"
915 print "switchToHistory currentlist",self.currList
916 print "switchToHistory oldlist",self.oldlist
917 self.hideSuggestions()
918 self["ButtonBlue"].hide()
919 self["VKeyIcon"].hide()
920 self["key_green"].hide()
921 self["videoactions"].setEnabled(False)
922 self["suggestionactions"].setEnabled(False)
923 self["searchactions"].setEnabled(False)
924 self["statusactions"].setEnabled(False)
925 self["config_actions"].setEnabled(False)
926 self["historyactions"].setEnabled(True)
927 self.HistoryWindow.activate()
928 self.HistoryWindow.instance.show()
930 def handleHistory(self):
931 if self.HistoryWindow is None:
932 self.HistoryWindow = self.session.instantiateDialog(MyTubeHistoryScreen, zPosition=1000)
933 if self.currList in ("configlist","feedlist"):
934 if self.HistoryWindow.status() is False:
935 print "status is FALSE,switchToHistory"
936 self.switchToHistory()
937 elif self.currList == "historylist":
940 def closeHistory(self):
941 print "closeHistory currentlist",self.currList
942 print "closeHistory oldlist",self.oldlist
943 if self.currList == "historylist":
944 if self.HistoryWindow.status() is True:
945 print "status is TRUE, closing historyscreen"
946 self.HistoryWindow.deactivate()
947 self.HistoryWindow.instance.hide()
948 if self.oldlist == "configlist":
949 self.switchToConfigList()
950 elif self.oldlist == "feedlist":
951 self.switchToFeedList()
953 def add2History(self):
954 if self.History is None:
955 self.History = config.plugins.mytube.general.history.value.split(',')
956 if self.History[0] == '':
958 print "self.History im add",self.History
959 if config.plugins.mytube.search.searchTerm.value in self.History:
960 self.History.remove((config.plugins.mytube.search.searchTerm.value))
961 self.History.insert(0,(config.plugins.mytube.search.searchTerm.value))
962 if len(self.History) == 30:
964 config.plugins.mytube.general.history.value = ",".join(self.History)
965 config.plugins.mytube.general.history.save()
966 print "configvalue",config.plugins.mytube.general.history.value
968 def hideSuggestions(self):
969 current = self["config"].getCurrent()
970 if current[1].help_window.instance is not None:
971 current[1].help_window.instance.hide()
972 if current[1].suggestionsWindow.instance is not None:
973 current[1].suggestionsWindow.instance.hide()
974 self.propagateUpDownNormally = True
976 def getFeed(self, chart=None, videoCategoryId=None, ids=[]):
978 self.queryThread = myTubeService.getFeed(callback=self.gotFeed, chart=chart, videoCategoryId=videoCategoryId, ids=ids)
980 def getNextEntries(self, result):
983 if myTubeService.hasNextPage():
984 self.appendEntries = True
985 myTubeService.getNextPage()
987 def getRelatedVideos(self, video):
989 self.search(relatedToVideoId=video.id)
991 def getChannelVideos(self, video):
993 self.search(channelId=video.channelId)
995 def runSearch(self, searchTerm = None):
998 self.search(searchTerm=searchTerm)
1000 def search(self, searchTerm=None, relatedToVideoId=None, channelId=None):
1001 Log.d("searchTerm=%s, relatedToVideoId=%s, channelId=%s" % (searchTerm, relatedToVideoId, channelId))
1003 self.appendEntries = False
1005 # categories = [ config.plugins.mytube.search.categories.value ],
1007 self.queryThread = myTubeService.search(
1008 searchTerm=searchTerm,
1009 orderby=config.plugins.mytube.search.orderBy.value,
1010 time=config.plugins.mytube.search.time.value,
1011 lr=config.plugins.mytube.search.lr.value,
1012 relatedToVideoId=relatedToVideoId,
1013 channelId=channelId,
1014 safeSearch=config.plugins.mytube.search.safeSearch.value,
1015 callback=self.gotSearchFeed)
1017 def queryStarted(self):
1018 if self.queryRunning:
1020 self.queryRunning = True
1022 def queryFinished(self):
1023 self.queryRunning = False
1025 def cancelThread(self):
1026 print "[MyTubePlayer] cancelThread"
1027 if self.queryThread is not None:
1028 self.queryThread.cancel()
1029 self.queryFinished()
1031 def gotFeed(self, success, items, data):
1032 print "[MyTubePlayer] gotFeed"
1034 self.FirstRun = False
1035 self.queryFinished()
1037 self.gotFeedError(items)
1038 if success and items is not None:
1040 myTubeService.feed = data
1041 self.buildEntryList()
1042 text = _("Results: %s - Page: %s " % (str(myTubeService.getTotalResults()), str(myTubeService.getCurrentPage())))
1043 text = "TODO" #TODO text
1044 #auth_username = myTubeService.getAuthedUsername()
1046 # text = auth_username + ' - ' + text
1047 self["result"].setText(text)
1049 def gotFeedError(self, error):
1050 print "[MyTubePlayer] gotFeedError"
1051 self.queryFinished()
1052 self.setState('Error')
1054 def gotSearchFeed(self, success, feed, data):
1056 self.FirstRun = False
1057 self.gotFeed(success, feed, data)
1059 def buildEntryList(self):
1060 self.mytubeentries = None
1061 self.screenshotList = []
1063 self.mytubeentries = self.ytfeed
1064 self.maxentries = len(self.mytubeentries)-1
1065 if self.mytubeentries and len(self.mytubeentries):
1066 if self.appendEntries == False:
1068 for video in self.mytubeentries:
1071 thumbnailUrl = video.thumbnailUrl
1072 if thumbnailUrl is not None:
1073 self.screenshotList.append((video_id,thumbnailUrl))
1074 if not self.Details.has_key(video_id):
1075 self.Details[video_id] = { 'thumbnail': None}
1076 self.videolist.append(self.buildEntryComponent(video, video_id))
1077 if len(self.videolist):
1078 self["feedlist"].style = "default"
1079 self["feedlist"].disable_callbacks = True
1080 self["feedlist"].list = self.videolist
1081 self["feedlist"].disable_callbacks = False
1082 self["feedlist"].setIndex(0)
1083 self["feedlist"].setList(self.videolist)
1084 self["feedlist"].updateList(self.videolist)
1085 if self.FirstRun and not config.plugins.mytube.general.loadFeedOnOpen.value:
1086 self.switchToConfigList()
1088 self.switchToFeedList()
1090 self.oldfeedentrycount = 0 #TODO self["feedlist"].count()
1091 for video in self.mytubeentries:
1094 thumbnailUrl = video.thumbnailUrl
1095 if thumbnailUrl is not None:
1096 self.screenshotList.append((video_id,thumbnailUrl))
1097 if not self.Details.has_key(video_id):
1098 self.Details[video_id] = { 'thumbnail': None}
1099 self.videolist.append(self.buildEntryComponent(video, video_id))
1100 if len(self.videolist):
1101 self["feedlist"].style = "default"
1102 old_index = self["feedlist"].index
1103 self["feedlist"].disable_callbacks = True
1104 self["feedlist"].list = self.videolist
1105 self["feedlist"].disable_callbacks = False
1106 self["feedlist"].setList(self.videolist)
1107 self["feedlist"].setIndex(old_index)
1108 self["feedlist"].updateList(self.videolist)
1109 self["feedlist"].selectNext()
1110 self.switchToFeedList(True)
1111 if not self.timer_startDownload.isActive():
1112 print "STARRTDOWNLOADTIMER IM BUILDENTRYLIST"
1113 self.timer_startDownload.start(5)
1115 self.setState('Error')
1118 def buildEntryComponent(self, entry,TubeID):
1120 description = entry.description
1122 publishedDate = entry.publishedDate
1123 if publishedDate is not "unknown":
1124 published = publishedDate.split("T")[0]
1126 published = "unknown"
1128 if Views is not "not available":
1131 views = "not available"
1132 duration = entry.duration
1133 if duration is not 0:
1134 durationInSecs = int(duration)
1135 mins = int(durationInSecs / 60)
1136 secs = durationInSecs - mins * 60
1137 duration = "%d:%02d" % (mins, secs)
1139 duration = "not available"
1146 if self.Details[myTubeID]["thumbnail"]:
1147 thumbnail = self.Details[myTubeID]["thumbnail"]
1148 return((entry, title, description, myTubeID, thumbnail, _("Added: ") + str(published), _("Views: ") + str(views), _("Duration: ") + str(duration), _("Likes: ") + str(likes) ))
1150 def getNextEntry(self):
1151 i = self["feedlist"].getIndex() + 1
1152 if i < len(self.videolist):
1153 self["feedlist"].selectNext()
1154 current = self["feedlist"].getCurrent()
1159 if myurl is not None:
1160 print "Got a URL to stream"
1161 myreference = eServiceReference(4097,0,myurl)
1162 myreference.setName(video.title)
1163 return myreference,False
1165 print "NoURL im getNextEntry"
1168 print "no more entries to play"
1171 def getPrevEntry(self):
1172 i = self["feedlist"].getIndex() - 1
1174 self["feedlist"].selectPrevious()
1175 current = self["feedlist"].getCurrent()
1180 if myurl is not None:
1181 print "Got a URL to stream"
1182 myreference = eServiceReference(4097,0,myurl)
1183 myreference.setName(video.title)
1184 return myreference,False
1189 def showVideoInfo(self):
1190 if self.currList == "feedlist":
1191 self.openInfoScreen()
1193 def openInfoScreen(self):
1194 if self.currList == "feedlist":
1195 current = self[self.currList].getCurrent()
1199 print "Title im showVideoInfo",video.title
1200 self.session.open(MyTubeVideoInfoScreen, self.skin_path, video = video )
1202 def downloadThumbnails(self):
1203 self.timer_startDownload.stop()
1204 for entry in self.screenshotList:
1205 thumbnailUrl = entry[1]
1207 thumbnailFile = "/tmp/"+str(tubeid)+".jpg"
1208 if self.Details.has_key(tubeid):
1209 if self.Details[tubeid]["thumbnail"] is None:
1210 if thumbnailUrl is not None:
1211 if tubeid not in self.pixmaps_to_load:
1212 self.pixmaps_to_load.append(tubeid)
1213 if (os_path.exists(thumbnailFile) == True):
1214 self.fetchFinished(False,tubeid)
1216 client.downloadPage(thumbnailUrl,thumbnailFile).addCallback(self.fetchFinished,str(tubeid)).addErrback(self.fetchFailed,str(tubeid))
1218 if tubeid not in self.pixmaps_to_load:
1219 self.pixmaps_to_load.append(tubeid)
1220 self.fetchFinished(False,tubeid, failed = True)
1222 def fetchFailed(self,string,tubeid):
1223 print "thumbnail-fetchFailed for: ",tubeid,string.getErrorMessage()
1224 self.fetchFinished(False,tubeid, failed = True)
1226 def fetchFinished(self,x,tubeid, failed = False):
1227 print "thumbnail-fetchFinished for:",tubeid
1228 self.pixmaps_to_load.remove(tubeid)
1230 thumbnailFile = resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MyTube/plugin.png")
1232 thumbnailFile = "/tmp/"+str(tubeid)+".jpg"
1233 sc = AVSwitch().getFramebufferScale()
1234 if (os_path.exists(thumbnailFile) == True):
1235 self.picloads[tubeid] = ePicLoad()
1236 self.picloads[tubeid].conn = self.picloads[tubeid].PictureData.connect(boundFunction(self.finish_decode, tubeid))
1237 self.picloads[tubeid].setPara((self["thumbnail"].instance.size().width(), self["thumbnail"].instance.size().height(), sc[0], sc[1], False, 1, "#00000000"))
1238 self.picloads[tubeid].startDecode(thumbnailFile)
1240 self.pixmaps_to_load.append(tubeid)
1241 self.fetchFinished(False,tubeid, failed = True)
1243 def finish_decode(self,tubeid,info):
1244 print "thumbnail finish_decode:", tubeid,info
1245 ptr = self.picloads[tubeid].getData()
1246 thumbnailFile = "/tmp/"+str(tubeid)+".jpg"
1248 if self.Details.has_key(tubeid):
1249 self.Details[tubeid]["thumbnail"] = ptr
1250 if (os_path.exists(thumbnailFile) == True):
1251 os_remove(thumbnailFile)
1252 del self.picloads[tubeid]
1254 del self.picloads[tubeid]
1255 if self.Details.has_key(tubeid):
1256 self.Details[tubeid]["thumbnail"] = None
1257 self.timer_thumbnails.start(1)
1259 def updateFeedThumbnails(self):
1260 self.timer_thumbnails.stop()
1261 if len(self.picloads) != 0:
1262 self.timer_thumbnails.start(1)
1265 for entry in self.videolist:
1267 if self.Details.has_key(tubeid):
1268 if self.Details[tubeid]["thumbnail"] is not None:
1269 thumbnail = entry[4]
1270 if thumbnail == None:
1272 self.videolist[idx] = self.buildEntryComponent(video, tubeid )
1274 if self.currList == "feedlist":
1275 self["feedlist"].updateList(self.videolist)
1278 class MyTubeVideoInfoScreen(Screen):
1280 <screen name="MyTubeVideoInfoScreen" flags="wfNoBorder" position="0,0" size="720,576" title="MyTube - Video Info" >
1281 <ePixmap position="0,0" zPosition="-1" size="720,576" pixmap="~/mytubemain_bg.png" alphatest="on" transparent="1" backgroundColor="transparent"/>
1282 <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" />
1283 <widget name="starsbg" pixmap="~/starsbar_empty.png" position="560,220" zPosition="5" size="100,20" transparent="1" alphatest="on" />
1284 <widget name="stars" pixmap="~/starsbar_filled.png" position="560,220" zPosition="6" size="100,20" transparent="1" />
1285 <widget source="infolist" render="Listbox" position="50,110" size="620,110" zPosition="6" scrollbarMode="showNever" selectionDisabled="1" transparent="1">
1286 <convert type="TemplatedMultiContent">
1289 MultiContentEntryPixmapAlphaTest(pos = (0, 4), size = (130, 98), png = 0), # index 0 is the thumbnail
1290 MultiContentEntryPixmapAlphaTest(pos = (130, 4), size = (130, 98), png = 1), # index 0 is the thumbnail
1291 MultiContentEntryPixmapAlphaTest(pos = (260, 4), size = (130, 98), png = 2), # index 0 is the thumbnail
1292 MultiContentEntryPixmapAlphaTest(pos = (390, 4), size = (130, 98), png = 3), # index 0 is the thumbnail
1295 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
1298 "fonts": [gFont("Regular", 20),gFont("Regular", 14),gFont("Regular", 28)],
1303 <widget name="channelTitle" position="60,220" size="300,20" zPosition="10" font="Regular;21" transparent="1" halign="left" valign="top" />
1304 <widget name="duration" position="370,220" size="200,20" zPosition="10" font="Regular;21" transparent="1" halign="left" valign="top" />
1305 <widget name="published" position="60,245" size="300,20" zPosition="10" font="Regular;21" transparent="1" halign="left" valign="top" />
1306 <widget name="views" position="370,245" size="200,20" zPosition="10" font="Regular;21" transparent="1" halign="left" valign="top" />
1307 <widget name="tags" position="60,270" size="600,20" zPosition="10" font="Regular;21" transparent="1" halign="left" valign="top" />
1308 <widget name="detailtext" position="60,300" size="610,200" zPosition="10" font="Regular;21" transparent="1" halign="left" valign="top"/>
1309 <ePixmap position="100,500" size="100,40" zPosition="0" pixmap="~/plugin.png" alphatest="on" transparent="1" />
1310 <ePixmap position="220,500" zPosition="4" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
1311 <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" />
1312 <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.
1315 def __init__(self, session, plugin_path, video = None):
1316 Screen.__init__(self, session)
1317 self.session = session
1318 self.skin_path = plugin_path
1321 self.thumbnails = []
1323 self["title"] = Label()
1324 self["key_red"] = Button(_("Close"))
1325 self["thumbnail"] = Pixmap()
1326 self["thumbnail"].hide()
1327 self["detailtext"] = ScrollLabel()
1328 self["starsbg"] = Pixmap()
1329 self["stars"] = ProgressBar()
1330 self["duration"] = Label()
1331 self["channelTitle"] = Label()
1332 self["author"] = self["channelTitle"] #skincompat
1333 self["published"] = Label()
1334 self["views"] = Label()
1335 self["tags"] = Label()
1336 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions", "MovieSelectionActions"],
1341 "down": self.pageDown,
1342 "left": self.pageUp,
1343 "right": self.pageDown,
1346 self["infolist"] = List(self.infolist)
1347 self.timer = eTimer()
1348 self.timer_conn = self.timer.timeout.connect(self.picloadTimeout)
1349 self.onLayoutFinish.append(self.layoutFinished)
1350 self.onShown.append(self.setWindowTitle)
1352 def layoutFinished(self):
1353 self.statuslist = []
1354 self.statuslist.append(( _("Downloading screenshots. Please wait..." ),_("Downloading screenshots. Please wait..." ) ))
1355 self["infolist"].style = "state"
1356 self['infolist'].setList(self.statuslist)
1357 self.loadPreviewpics()
1358 if self.video.title is not None:
1359 self["title"].setText(self.video.title)
1361 if self.video.description is not None:
1362 self["detailtext"].setText(self.video.description.strip())
1364 #TODO implement Likes
1365 self["stars"].hide()
1366 self["starsbg"].hide()
1368 if self.video.duration is not 0:
1369 durationInSecs = int(self.video.duration)
1370 mins = int(durationInSecs / 60)
1371 secs = durationInSecs - mins * 60
1372 duration = "%d:%02d" % (mins, secs)
1373 self["duration"].setText(_("Duration: ") + str(duration))
1375 if self.video.channelTitle:
1376 self["channelTitle"].setText(_("Channel: ") + self.video.channelTitle)
1378 if self.video.publishedDate is not "unknown":
1379 self["published"].setText(_("Added: ") + self.video.publishedDate.split("T")[0])
1381 if self.video.views is not "not available":
1382 self["views"].setText(_("Views: ") + str(self.video.views))
1384 def setWindowTitle(self):
1385 self.setTitle(_("MyTubeVideoInfoScreen"))
1388 self["detailtext"].pageUp()
1391 self["detailtext"].pageDown()
1393 def loadPreviewpics(self):
1394 self.thumbnails = []
1395 self.mythumbubeentries = None
1399 self.mythumbubeentries = [self.video.thumbnailUrl]
1400 self.maxentries = len(self.mythumbubeentries)-1
1401 if self.mythumbubeentries:
1403 for entry in self.mythumbubeentries:
1404 thumbID = self.video.id + str(currindex)
1405 thumbnailFile = "/tmp/" + thumbID + ".jpg"
1406 currPic = [currindex,thumbID,thumbnailFile,None]
1407 self.thumbnails.append(currPic)
1409 thumbnailUrl = entry
1410 if thumbnailUrl is not None:
1411 client.downloadPage(thumbnailUrl,thumbnailFile).addCallback(self.fetchFinished,currindex,thumbID).addErrback(self.fetchFailed,currindex,thumbID)
1416 def fetchFailed(self, string, index, id):
1417 print "[fetchFailed] for index:" + str(index) + "for ThumbID:" + id + string.getErrorMessage()
1419 def fetchFinished(self, string, index, id):
1420 print "[fetchFinished] for index:" + str(index) + " for ThumbID:" + id
1421 self.decodePic(index)
1423 def decodePic(self, index):
1424 sc = AVSwitch().getFramebufferScale()
1425 self.picloads[index] = ePicLoad()
1426 self.picloads[index].conn = self.picloads[index].PictureData.connect(boundFunction(self.finish_decode, index))
1427 for entry in self.thumbnails:
1428 if entry[0] == index:
1430 thumbnailFile = entry[2]
1431 if (os_path.exists(thumbnailFile) == True):
1432 print "[decodePic] DECODING THUMBNAIL for INDEX:"+ str(self.index) + "and file: " + thumbnailFile
1433 self.picloads[index].setPara((self["thumbnail"].instance.size().width(), self["thumbnail"].instance.size().height(), sc[0], sc[1], False, 1, "#00000000"))
1434 self.picloads[index].startDecode(thumbnailFile)
1436 print "[decodePic] Thumbnail file NOT FOUND !!!-->:",thumbnailFile
1438 def finish_decode(self, picindex = None, picInfo=None):
1439 print "finish_decode - of INDEX", picindex
1440 ptr = self.picloads[picindex].getData()
1442 self.thumbnails[picindex][3] = ptr
1443 if (os_path.exists(self.thumbnails[picindex][2]) == True):
1444 print "removing", self.thumbnails[picindex][2]
1445 os_remove(self.thumbnails[picindex][2])
1446 del self.picloads[picindex]
1447 if len(self.picloads) == 0:
1448 self.timer.startLongTimer(3)
1450 def picloadTimeout(self):
1452 if len(self.picloads) == 0:
1453 self.buildInfoList()
1455 self.timer.startLongTimer(2)
1457 def buildInfoList(self):
1463 count = len(self.thumbnails)
1465 thumb0 = self.thumbnails[0][3]
1467 thumb1 = self.thumbnails[1][3]
1469 thumb2 = self.thumbnails[2][3]
1471 thumb3 = self.thumbnails[3][3]
1472 self.infolist.append(( thumb0, thumb1, thumb2, thumb3))
1473 if len(self.infolist):
1474 self["infolist"].style = "default"
1475 self["infolist"].disable_callbacks = True
1476 self["infolist"].list = self.infolist
1477 self["infolist"].disable_callbacks = False
1478 self["infolist"].setIndex(0)
1479 self["infolist"].setList(self.infolist)
1480 self["infolist"].updateList(self.infolist)
1483 class MyTubeVideoHelpScreen(Screen):
1485 <screen name="MyTubeVideoHelpScreen" flags="wfNoBorder" position="0,0" size="720,576" title="MyTube - Help" >
1486 <ePixmap position="0,0" zPosition="-1" size="720,576" pixmap="~/mytubemain_bg.png" alphatest="on" transparent="1" backgroundColor="transparent"/>
1487 <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" />
1488 <widget name="detailtext" position="60,120" size="610,370" zPosition="10" font="Regular;21" transparent="1" halign="left" valign="top"/>
1489 <ePixmap position="100,500" size="100,40" zPosition="0" pixmap="~/plugin.png" alphatest="on" transparent="1" />
1490 <ePixmap position="220,500" zPosition="4" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
1491 <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" />
1494 def __init__(self, session, plugin_path, wantedinfo = None, wantedtitle = None):
1495 Screen.__init__(self, session)
1496 self.session = session
1497 self.skin_path = plugin_path
1498 self.wantedinfo = wantedinfo
1499 self.wantedtitle = wantedtitle
1500 self["title"] = Label()
1501 self["key_red"] = Button(_("Close"))
1502 self["detailtext"] = ScrollLabel()
1504 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
1509 "down": self.pageDown,
1510 "left": self.pageUp,
1511 "right": self.pageDown,
1514 self.onLayoutFinish.append(self.layoutFinished)
1515 self.onShown.append(self.setWindowTitle)
1517 def layoutFinished(self):
1518 if self.wantedtitle is None:
1519 self["title"].setText(_("Help"))
1521 self["title"].setText(self.wantedtitle)
1522 if self.wantedinfo is None:
1523 self["detailtext"].setText(_("This is the help screen. Feed me with something to display."))
1525 self["detailtext"].setText(self.wantedinfo)
1527 def setWindowTitle(self):
1528 self.setTitle(_("MyTubeVideohelpScreen"))
1531 self["detailtext"].pageUp()
1534 self["detailtext"].pageDown()
1537 def MyTubeMain(session, **kwargs):
1539 l2cert = etpm.getData(eTPM.DT_LEVEL2_CERT)
1541 print "l2cert not found"
1544 l2key = validate_cert(l2cert, rootkey)
1546 print "l2cert invalid"
1550 session.open(MyTubePlayerMainScreen, l2key)
1552 def Plugins(path, **kwargs):
1555 return PluginDescriptor(
1556 name=_("My TubePlayer"),
1557 description=_("Play YouTube movies"),
1558 where = [ PluginDescriptor.WHERE_EXTENSIONSMENU, PluginDescriptor.WHERE_PLUGINMENU ],
1559 icon = "plugin.png", fnc = MyTubeMain)