2 from Plugins.Plugin import PluginDescriptor
3 from MyTubeService import GoogleSuggestions
4 from MyTubeSearch import ConfigTextWithGoogleSuggestions
5 from Tools.BoundFunction import boundFunction
6 from Screens.MessageBox import MessageBox
7 from Screens.Screen import Screen
8 from Screens.ChoiceBox import ChoiceBox
9 from Screens.InfoBar import MoviePlayer
10 from Screens.VirtualKeyBoard import VirtualKeyBoard
11 from Components.ActionMap import ActionMap, NumberActionMap
12 from Components.Label import Label
13 from Components.ScrollLabel import ScrollLabel
14 from Components.ProgressBar import ProgressBar
15 from Components.Pixmap import Pixmap
16 from Components.Button import Button
17 from Components.Sources.List import List
18 from Components.MultiContent import MultiContentEntryText, MultiContentEntryPixmapAlphaTest
19 from Components.AVSwitch import AVSwitch
20 from Components.ActionMap import HelpableActionMap
21 from Components.config import config, Config, ConfigSelection, ConfigSubsection, ConfigText, getConfigListEntry, ConfigYesNo, ConfigIP, ConfigNumber,ConfigLocations
22 from Components.config import KEY_DELETE, KEY_BACKSPACE, KEY_LEFT, KEY_RIGHT, KEY_HOME, KEY_END, KEY_TOGGLEOW, KEY_ASCII, KEY_TIMEOUT
23 from Components.ConfigList import ConfigListScreen
24 from Components.ServiceEventTracker import ServiceEventTracker, InfoBarBase
25 from Components.Console import Console
26 from Components.Sources.Source import Source
27 from Components.Task import Task, Job, job_manager
29 from threading import Thread
30 from threading import Condition
32 from Tools.Directories import pathExists, fileExists, resolveFilename, SCOPE_PLUGINS, SCOPE_SKIN_IMAGE, SCOPE_HDD
33 from Tools.LoadPixmap import LoadPixmap
34 from Tools.Downloader import HTTPProgressDownloader, downloadWithProgress
35 from enigma import eTimer, quitMainloop,eListbox,ePoint, RT_HALIGN_LEFT, RT_HALIGN_RIGHT, RT_VALIGN_CENTER, eListboxPythonMultiContent, eListbox, gFont, getDesktop, ePicLoad, eServiceCenter, iServiceInformation, eServiceReference,iSeekableService,iServiceInformation, iPlayableService, iPlayableServicePtr
36 from os import path as os_path, system as os_system, unlink, stat, mkdir, popen, makedirs, listdir, access, rename, remove, W_OK, R_OK, F_OK
37 from twisted.web import client
38 from twisted.internet import reactor
41 from Screens.InfoBarGenerics import InfoBarShowHide, InfoBarSeek, InfoBarNotifications, InfoBarServiceNotifications
43 config.plugins.mytube = ConfigSubsection()
44 config.plugins.mytube.search = ConfigSubsection()
46 config.plugins.mytube.search.searchTerm = ConfigTextWithGoogleSuggestions("", False, threaded = True)
47 config.plugins.mytube.search.orderBy = ConfigSelection(
49 ("relevance", _("Relevance")),
50 ("viewCount", _("View Count")),
51 ("published", _("Published")),
52 ("rating", _("Rating"))
54 config.plugins.mytube.search.time = ConfigSelection(
56 ("all_time", _("All Time")),
57 ("this_month", _("This Month")),
58 ("this_week", _("This Week")),
61 config.plugins.mytube.search.racy = ConfigSelection(
63 ("include", _("Yes")),
66 config.plugins.mytube.search.categories = ConfigSelection(
69 ("Film", _("Film & Animation")),
70 ("Autos", _("Autos & Vehicles")),
71 ("Music", _("Music")),
72 ("Animals", _("Pets & Animals")),
73 ("Sports", _("Sports")),
74 ("Travel", _("Travel & Events")),
75 ("Shortmov", _("Short Movies")),
76 ("Games", _("Gaming")),
77 ("Comedy", _("Comedy")),
78 ("People", _("People & Blogs")),
79 ("News", _("News & Politics")),
80 ("Entertainment", _("Entertainment")),
81 ("Education", _("Education")),
82 ("Howto", _("Howto & Style")),
83 ("Nonprofit", _("Nonprofits & Activism")),
84 ("Tech", _("Science & Technology"))
86 config.plugins.mytube.search.lr = ConfigSelection(
89 ("au", _("Australia")),
92 ("cz", _("Czech Republic")),
95 ("gb", _("Great Britain")),
96 ("au", _("Australia")),
98 ("hk", _("Hong Kong")),
100 ("ie", _("Ireland")),
105 ("nz", _("New Zealand")),
108 ("kr", _("South Korea")),
112 ("us", _("United States"))
114 config.plugins.mytube.search.sortOrder = ConfigSelection(
116 ("ascending", _("Ascending")),
117 ("descending", _("Descending"))
120 config.plugins.mytube.general = ConfigSubsection()
121 config.plugins.mytube.general.showHelpOnOpen = ConfigYesNo(default = True)
122 config.plugins.mytube.general.startFeed = ConfigSelection(
124 ("hd", _("High definition")),
125 ("top_rated", _("Top rated")),
126 ("top_favorites", _("Top favorites")),
127 ("most_viewed", _("Most viewed")),
128 ("most_popular", _("Most popular")),
129 ("most_recent", _("Most recent")),
130 ("most_discussed", _("Most discussed")),
131 ("top_favorites", _("Most linked")),
132 ("most_linked", _("Most responded"))
134 config.plugins.mytube.general.on_movie_stop = ConfigSelection(default = "ask", choices = [
135 ("ask", _("Ask user")), ("quit", _("Return to movie list")), ("playnext", _("Play next video")), ("playagain", _("Play video again")) ])
137 config.plugins.mytube.general.on_exit = ConfigSelection(default = "ask", choices = [
138 ("ask", _("Ask user")), ("quit", _("Return to movie list"))])
140 default = resolveFilename(SCOPE_HDD)
141 tmp = config.movielist.videodirs.value
142 if default not in tmp:
144 config.plugins.mytube.general.videodir = ConfigSelection(default = default, choices = tmp)
145 config.plugins.mytube.general.history = ConfigText(default="")
146 #config.plugins.mytube.general.useHTTPProxy = ConfigYesNo(default = False)
147 #config.plugins.mytube.general.ProxyIP = ConfigIP(default=[0,0,0,0])
148 #config.plugins.mytube.general.ProxyPort = ConfigNumber(default=8080)
150 class downloadJob(Job):
151 def __init__(self, url, file, title):
152 Job.__init__(self, title)
153 downloadTask(self, url, file)
155 class downloadTask(Task):
156 def __init__(self, job, url, file):
157 Task.__init__(self, job, ("download task"))
165 def run(self, callback):
166 self.callback = callback
167 self.download = downloadWithProgress(self.url,self.local)
168 self.download.addProgress(self.http_progress)
169 self.download.start().addCallback(self.http_finished).addErrback(self.http_failed)
171 def http_progress(self, recvbytes, totalbytes):
172 #print "[http_progress] recvbytes=%d, totalbytes=%d" % (recvbytes, totalbytes)
173 self.progress = int(self.end*recvbytes/float(totalbytes))
175 def http_finished(self, string=""):
176 print "[http_finished]" + str(string)
177 Task.processFinished(self, 0)
179 def http_failed(self, failure_instance=None, error_message=""):
180 if error_message == "" and failure_instance is not None:
181 error_message = failure_instance.getErrorMessage()
182 print "[http_failed] " + error_message
183 Task.processFinished(self, 1)
187 from MyTubeService import myTubeService
188 from MyTubeSearch import MyTubeSettingsScreen,MyTubeTasksScreen,MyTubeHistoryScreen
191 class MyTubePlayerMainScreen(Screen, ConfigListScreen):
192 BASE_STD_FEEDURL = "http://gdata.youtube.com/feeds/api/standardfeeds/"
193 #(entry, Title, Description, TubeID, thumbnail, PublishedDate,Views,duration,ratings )
195 <screen name="MyTubePlayerMainScreen" flags="wfNoBorder" position="0,0" size="720,576" title="MyTubePlayerMainScreen..." >
196 <ePixmap position="0,0" zPosition="-1" size="720,576" pixmap="~/mytubemain_bg.png" alphatest="on" transparent="1" backgroundColor="transparent"/>
197 <widget name="config" zPosition="2" position="60,60" size="600,50" scrollbarMode="showNever" transparent="1" />
198 <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" >
199 <convert type="TemplatedMultiContent">
202 MultiContentEntryPixmapAlphaTest(pos = (0, 0), size = (100, 75), png = 4), # index 4 is the thumbnail
203 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
204 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
205 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
206 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
207 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
210 MultiContentEntryText(pos = (10, 1), size = (500, 28), font=2, flags = RT_HALIGN_LEFT | RT_VALIGN_TOP| RT_WRAP, text = 0), # index 0 is the name
211 MultiContentEntryText(pos = (10, 22), size = (500, 46), font=3, flags = RT_HALIGN_LEFT | RT_VALIGN_TOP| RT_WRAP, text = 1), # index 2 is the description
214 "fonts": [gFont("Regular", 22),gFont("Regular", 18),gFont("Regular", 26),gFont("Regular", 20)],
220 <ePixmap pixmap="skin_default/buttons/key_info.png" position="50,500" zPosition="4" size="35,25" alphatest="on" transparent="1" />
221 <ePixmap pixmap="skin_default/buttons/key_menu.png" position="50,520" zPosition="4" size="35,25" alphatest="on" transparent="1" />
222 <ePixmap position="90,500" size="100,40" zPosition="4" pixmap="~/plugin.png" alphatest="on" transparent="1" />
223 <ePixmap position="190,500" zPosition="4" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
224 <ePixmap position="330,500" zPosition="4" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
225 <ePixmap position="470,500" zPosition="4" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
226 <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" />
227 <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" />
228 <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" />
229 <widget name="ButtonBlue" pixmap="skin_default/buttons/button_blue.png" position="610,510" zPosition="10" size="15,16" transparent="1" alphatest="on" />
230 <widget name="VKeyIcon" pixmap="skin_default/vkey_icon.png" position="620,495" zPosition="10" size="60,48" transparent="1" alphatest="on" />
231 <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.
232 <widget name="HelpWindow" position="160,255" zPosition="1" size="1,1" transparent="1" alphatest="on" />
235 def __init__(self, session):
236 Screen.__init__(self, session)
237 self.session = session
238 self.skin_path = plugin_path
241 self.currentFeedName = None
244 self.video_playlist = []
246 self.mytubeentries = None
250 self.oldfeedentrycount = 0
251 self.appendEntries = False
252 self.lastservice = session.nav.getCurrentlyPlayingServiceReference()
253 self.propagateUpDownNormally = True
255 self.HistoryWindow = None
257 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.")
258 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.")
259 self.currList = "configlist"
261 self.CleanupConsole = None
262 self["feedlist"] = List(self.videolist)
263 self["thumbnail"] = Pixmap()
264 self["thumbnail"].hide()
265 self["HelpWindow"] = Pixmap()
266 self["HelpWindow"].hide()
267 self["key_red"] = Button(_("Close"))
268 self["key_green"] = Button(_("Std. Feeds"))
269 self["key_yellow"] = Button(_("History"))
270 self["ButtonBlue"] = Pixmap()
271 self["VKeyIcon"] = Pixmap()
272 self["ButtonBlue"].hide()
273 self["VKeyIcon"].hide()
275 self["searchactions"] = ActionMap(["ShortcutActions", "WizardActions", "HelpActions", "MediaPlayerActions"],
278 "back": self.leavePlayer,
279 "red": self.leavePlayer,
280 "blue": self.openKeyboard,
281 "yellow": self.handleHistory,
283 "down": self.handleSuggestions,
284 "left": self.keyLeft,
285 "right": self.keyRight,
286 "prevBouquet": self.switchToFeedList,
287 "nextBouquet": self.switchToConfigList,
288 "displayHelp": self.handleHelpWindow,
289 "menu" : self.handleMenu,
292 self["suggestionactions"] = ActionMap(["ShortcutActions", "WizardActions", "MediaPlayerActions", "HelpActions"],
295 "back": self.switchToConfigList,
296 "red": self.switchToConfigList,
297 #"prevBouquet": self.switchToFeedList,
299 "down": self.keyDown,
300 "left": self.keyLeft,
301 "right": self.keyRight,
305 self["videoactions"] = ActionMap(["ShortcutActions", "WizardActions", "MediaPlayerActions", "MovieSelectionActions", "HelpActions"],
308 "back": self.leavePlayer,
309 "red": self.leavePlayer,
310 "yellow": self.handleHistory,
312 "down": self.keyDown,
313 "nextBouquet": self.switchToConfigList,
314 "green": self.keyStdFeed,
315 "showEventInfo": self.showVideoInfo,
316 "displayHelp": self.handleHelpWindow,
317 "menu" : self.handleMenu,
320 self["statusactions"] = ActionMap(["WizardActions"],
322 "back": self.leavePlayer,
323 "red": self.leavePlayer,
324 "nextBouquet": self.switchToConfigList,
327 self["videoactions"].setEnabled(False)
328 self["statusactions"].setEnabled(False)
329 self.timer = eTimer()
330 self.timer.callback.append(self.picloadTimeout)
331 self.SearchConfigEntry = None
332 self.searchContextEntries = []
333 ConfigListScreen.__init__(self, self.searchContextEntries, session)
335 self.onLayoutFinish.append(self.layoutFinished)
336 self.onShown.append(self.setWindowTitle)
337 self.onClose.append(self.__onClose)
338 self.Timer = eTimer()
339 self.Timer.callback.append(self.TimerFire)
344 self.session.nav.playService(self.lastservice)
346 def layoutFinished(self):
347 self.currList = "status"
348 self["key_green"].hide()
350 self.statuslist.append(( _("Fetching feed entries"), _("Trying to download the Youtube feed entries. Please wait..." ) ))
351 self["feedlist"].style = "state"
352 self['feedlist'].setList(self.statuslist)
353 current = self["config"].getCurrent()
354 if current[1].help_window.instance is not None:
355 current[1].help_window.instance.hide()
356 self.Timer.start(500)
360 self.setState('getFeed')
362 def setWindowTitle(self):
363 self.setTitle(_("MyTubePlayer"))
365 def handleHelpWindow(self):
366 print "[handleHelpWindow]"
367 if self.currList == "configlist":
368 self.hideSuggestions()
369 self.session.openWithCallback(self.searchHelpClosed, MyTubeVideoHelpScreen, self.skin_path, wantedinfo = self.searchtext, wantedtitle = _("MyTubePlayer Help") )
370 elif self.currList == "feedlist":
371 self.session.open(MyTubeVideoHelpScreen, self.skin_path, wantedinfo = self.feedtext, wantedtitle = _("MyTubePlayer Help") )
373 def searchHelpClosed(self):
374 self.switchToConfigList()
376 def handleFirstHelpWindow(self):
377 print "[handleFirstHelpWindow]"
378 if config.plugins.mytube.general.showHelpOnOpen.value is True:
379 if self.currList == "configlist":
380 self.hideSuggestions()
381 self.session.openWithCallback(self.firstRunHelpClosed, MyTubeVideoHelpScreen, self.skin_path,wantedinfo = self.feedtext, wantedtitle = _("MyTubePlayer Help") )
383 self.FirstRun = False
385 def firstRunHelpClosed(self):
386 if self.FirstRun == True:
387 self.FirstRun = False
388 self.switchToConfigList()
390 def setState(self,status = None):
392 self["videoactions"].setEnabled(False)
393 self["searchactions"].setEnabled(False)
394 self["key_green"].hide()
395 self.hideSuggestions()
396 self["config_actions"].setEnabled(False)
397 self["statusactions"].setEnabled(True)
398 if self.HistoryWindow is not None:
399 self.HistoryWindow.deactivate()
400 self.HistoryWindow.instance.hide()
401 self.currList = "status"
403 if status == 'getFeed':
404 self.statuslist.append(( _("Fetching feed entries"), _("Trying to download the Youtube feed entries. Please wait..." ) ))
405 print "self.statuslist",self.statuslist
406 self["feedlist"].style = "state"
407 self['feedlist'].setList(self.statuslist)
408 if status == 'getSearchFeed':
409 self.statuslist.append(( _("Fetching search entries"), _("Trying to download the Youtube search results. Please wait..." ) ))
410 self["feedlist"].style = "state"
411 self['feedlist'].setList(self.statuslist)
412 if status == 'Error':
413 self.statuslist.append(( _("An error occured."), _("There was an error getting the feed entries. Try again..." ) ))
414 self["feedlist"].style = "state"
415 self['feedlist'].setList(self.statuslist)
416 if self.FirstRun == True:
417 self.appendEntries = False
418 myTubeService.startService()
419 self.FeedURL = self.BASE_STD_FEEDURL + str(config.plugins.mytube.general.startFeed.value)
420 self.getFeed(self.FeedURL, str(config.plugins.mytube.general.startFeed.value))
422 def createSetup(self):
423 self.searchContextEntries = []
424 self.SearchConfigEntry = getConfigListEntry(_("Search Term(s)"), config.plugins.mytube.search.searchTerm)
425 self.searchContextEntries.append(self.SearchConfigEntry)
426 self["config"].list = self.searchContextEntries
427 self["config"].l.setList(self.searchContextEntries)
428 self["config"].onSelectionChanged.append(self.selectionChanged)
430 def selectionChanged(self):
431 current = self["config"].getCurrent()
433 if current == self.SearchConfigEntry:
434 helpwindowpos = self["HelpWindow"].getPosition()
435 if current[1].help_window.instance is not None:
436 current[1].help_window.instance.move(ePoint(helpwindowpos[0],helpwindowpos[1]))
438 def handleMenu(self):
439 print "currlist im HandleMenu:",self.currList
440 if self.currList == "configlist":
442 (_("MyTube Settings"), "settings"),
443 (_("View standard feed"), "stdfeed"),
445 self.hideSuggestions()
446 self.session.openWithCallback(self.openMenu, ChoiceBox, title=_("Select your choice."), list = menulist)
448 elif self.currList == "feedlist":
449 menulist = [(_("MyTube Settings"), "settings")]
451 (_("View related videos"), "related"),
452 (_("View response videos"), "response"),
453 (_("View standard feed"), "stdfeed")
455 if config.usage.setup_level.index >= 2: # expert+
457 (_("Download Video"), "download"),
458 (_("View Downloads"), "downview")
461 self.hideSuggestions()
462 self.session.openWithCallback(self.openMenu, ChoiceBox, title=_("Select your choice."), list = menulist)
464 def openMenu(self, answer):
465 answer = answer and answer[1]
466 print "openMenu - ANSWER",answer
467 if answer == "settings":
468 print "settings selected"
469 self.session.open(MyTubeSettingsScreen, self.skin_path )
470 elif answer == "stdfeed":
472 elif answer == "related":
473 current = self["feedlist"].getCurrent()[0]
474 self.setState('getFeed')
475 self.getRelatedVideos(current)
476 elif answer == "response":
477 current = self["feedlist"].getCurrent()[0]
478 self.setState('getFeed')
479 self.getResponseVideos(current)
480 elif answer == "download":
481 if self.currList == "feedlist":
482 current = self[self.currList].getCurrent()
486 myurl = myentry.getVideoUrl()
487 filename = str(config.plugins.mytube.general.videodir.value)+ str(myentry.getTitle()) + '.mp4'
488 job_manager.AddJob(downloadJob(myurl,filename, str(myentry.getTitle())[:30]))
489 elif answer == "downview":
491 for job in job_manager.getPendingJobs():
492 self.tasklist.append((job,job.name,job.getStatustext(),int(100*job.progress/float(job.end)) ,str(100*job.progress/float(job.end)) + "%" ))
493 self.session.open(MyTubeTasksScreen, self.skin_path , self.tasklist)
495 def openKeyboard(self):
496 self.hideSuggestions()
497 self.session.openWithCallback(self.SearchEntryCallback, VirtualKeyBoard, title = (_("Enter your search term(s)")), text = config.plugins.mytube.search.searchTerm.value)
499 def SearchEntryCallback(self, callback = None):
500 if callback is not None and len(callback):
501 config.plugins.mytube.search.searchTerm.value = callback
502 ConfigListScreen.keyOK(self)
503 self["config"].getCurrent()[1].getSuggestions()
504 current = self["config"].getCurrent()
505 if current[1].help_window.instance is not None:
506 current[1].help_window.instance.show()
507 if current[1].suggestionsWindow.instance is not None:
508 current[1].suggestionsWindow.instance.show()
509 self.propagateUpDownNormally = True
511 def openStandardFeedClosed(self, answer):
512 answer = answer and answer[1]
513 print "openStandardFeedClosed - ANSWER",answer
514 if answer is not None:
516 self.setState('getFeed')
517 self.appendEntries = False
518 self.FeedURL = "http://gdata.youtube.com/feeds/api/videos/-/HD"
519 self.getFeed(self.FeedURL, str(answer))
521 self.setState('getFeed')
522 self.appendEntries = False
523 self.FeedURL = self.BASE_STD_FEEDURL + str(answer)
524 self.getFeed(self.FeedURL, str(answer))
526 def handleLeave(self, how):
527 self.is_closing = True
529 if self.currList == "configlist":
532 (_("No"), "continue"),
533 (_("No, but switch to video entries."), "switch2feed")
538 (_("No"), "continue"),
539 (_("No, but switch to video search."), "switch2search")
541 self.session.openWithCallback(self.leavePlayerConfirmed, ChoiceBox, title=_("Really quit MyTube Player?"), list = list)
543 self.leavePlayerConfirmed([True, how])
545 def leavePlayer(self):
546 print "self.currList im leavePlayer",self.currList
547 if self.HistoryWindow is not None:
548 self.HistoryWindow.deactivate()
549 self.HistoryWindow.instance.hide()
550 if self.currList == "configlist":
551 current = self["config"].getCurrent()
552 if current[1].suggestionsWindow.activeState is True:
553 self.propagateUpDownNormally = True
554 current[1].deactivateSuggestionList()
555 self["config"].invalidateCurrent()
557 self.hideSuggestions()
558 self.handleLeave(config.plugins.mytube.general.on_exit.value)
560 self.hideSuggestions()
561 self.handleLeave(config.plugins.mytube.general.on_exit.value)
563 def leavePlayerConfirmed(self, answer):
564 answer = answer and answer[1]
565 print "ANSWER",answer
567 cmd = "rm -rf /tmp/*.jpg"
568 self.CleanupConsole = Console()
569 self.CleanupConsole.ePopen(cmd, self.doQuit)
570 elif answer == "continue":
571 if self.currList == "historylist":
572 if self.HistoryWindow.status() is False:
573 print "status is FALSE"
574 self.HistoryWindow.activate()
575 self.HistoryWindow.instance.show()
576 elif self.currList == "configlist":
577 self.switchToConfigList()
578 elif self.currList == "feedlist":
579 self.switchToFeedList()
580 elif answer == "switch2feed":
581 self.switchToFeedList()
582 elif answer == "switch2search":
583 self.switchToConfigList()
585 print "No menuentry selected, we should just switch back to old state."
586 if self.currList == "historylist":
587 if self.HistoryWindow.status() is False:
588 print "status is FALSE"
589 self.HistoryWindow.activate()
590 self.HistoryWindow.instance.show()
591 elif self.currList == "configlist":
592 self.switchToConfigList()
593 elif self.currList == "feedlist":
594 self.switchToFeedList()
596 def doQuit(self, result, retval,extra_args):
597 if self["config"].getCurrent()[1].suggestionsWindow is not None:
598 self.session.deleteDialog(self["config"].getCurrent()[1].suggestionsWindow)
599 if self.HistoryWindow is not None:
600 self.session.deleteDialog(self.HistoryWindow)
601 if config.plugins.mytube.general.showHelpOnOpen.value is True:
602 config.plugins.mytube.general.showHelpOnOpen.value = False
603 config.plugins.mytube.general.showHelpOnOpen.save()
604 print "self.History im doQuit:",self.History
605 if self.History and len(self.History):
606 config.plugins.mytube.general.history.value = ",".join(self.History)
607 config.plugins.mytube.general.history.save()
608 config.plugins.mytube.general.save()
609 config.plugins.mytube.save()
610 if self.CleanupConsole is not None:
611 if len(self.CleanupConsole.appContainers):
612 for name in self.CleanupConsole.appContainers.keys():
613 self.CleanupConsole.kill(name)
617 print "self.currList----->",self.currList
618 if self.currList == "configlist" or self.currList == "suggestionslist":
619 self["config"].invalidateCurrent()
620 if config.plugins.mytube.search.searchTerm.value != "":
622 searchContext = config.plugins.mytube.search.searchTerm.value
623 print "Search searchcontext",searchContext
624 if isinstance(self["config"].getCurrent()[1], ConfigTextWithGoogleSuggestions) and not self.propagateUpDownNormally:
625 self.propagateUpDownNormally = True
626 self["config"].getCurrent()[1].deactivateSuggestionList()
627 self.setState('getSearchFeed')
628 self.runSearch(searchContext)
629 elif self.currList == "historylist":
630 config.plugins.mytube.search.searchTerm.value = self.HistoryWindow.getSelection()
631 self["config"].invalidateCurrent()
632 if config.plugins.mytube.search.searchTerm.value != "":
633 searchContext = config.plugins.mytube.search.searchTerm.value
634 print "Search searchcontext",searchContext
635 self.setState('getSearchFeed')
636 self.runSearch(searchContext)
637 elif self.currList == "feedlist":
638 current = self[self.currList].getCurrent()
642 if myentry is not None:
643 myurl = myentry.getVideoUrl()
644 print "Playing URL",myurl
645 if myurl is not None:
646 myreference = eServiceReference(4097,0,myurl)
647 myreference.setName(myentry.getTitle())
648 self.session.open(MyTubePlayer, myreference, self.lastservice, infoCallback = self.showVideoInfo, nextCallback = self.getNextEntry, prevCallback = self.getPrevEntry )
650 self.session.open(MessageBox, _("Sorry, video is not available!"), MessageBox.TYPE_INFO)
653 print "self.currList im KeyUp",self.currList
654 if self.currList == "suggestionslist":
655 if config.plugins.mytube.search.searchTerm.value != "":
656 if not self.propagateUpDownNormally:
657 self["config"].getCurrent()[1].suggestionListUp()
658 self["config"].invalidateCurrent()
659 elif self.currList == "historylist":
660 if self.HistoryWindow is not None and self.HistoryWindow.shown:
661 self.HistoryWindow.up()
662 elif self.currList == "feedlist":
663 self[self.currList].selectPrevious()
666 print "self.currList im KeyDown",self.currList
667 if self.currList == "suggestionslist":
668 if config.plugins.mytube.search.searchTerm.value != "":
669 if not self.propagateUpDownNormally:
670 self["config"].getCurrent()[1].suggestionListDown()
671 self["config"].invalidateCurrent()
672 elif self.currList == "historylist":
673 if self.HistoryWindow is not None and self.HistoryWindow.shown:
674 self.HistoryWindow.down()
675 elif self.currList == "feedlist":
676 print self[self.currList].count()
677 print self[self.currList].index
678 if self[self.currList].index == self[self.currList].count()-1 and myTubeService.getNextFeedEntriesURL() is not None:
679 self.session.openWithCallback(self.getNextEntries, MessageBox, _("Do you want to see more entries?"))
681 self[self.currList].selectNext()
684 print "self.currList im KeyRight",self.currList
685 if self.propagateUpDownNormally:
686 ConfigListScreen.keyRight(self)
688 if self.currList == "suggestionslist":
689 if config.plugins.mytube.search.searchTerm.value != "":
690 self["config"].getCurrent()[1].suggestionListPageDown()
691 self["config"].invalidateCurrent()
692 elif self.currList == "historylist":
693 if self.HistoryWindow is not None and self.HistoryWindow.shown:
694 self.HistoryWindow.pageDown()
697 print "self.currList im kEyLeft",self.currList
698 if self.propagateUpDownNormally:
699 ConfigListScreen.keyLeft(self)
701 if self.currList == "suggestionslist":
702 if config.plugins.mytube.search.searchTerm.value != "":
703 self["config"].getCurrent()[1].suggestionListPageUp()
704 self["config"].invalidateCurrent()
705 elif self.currList == "historylist":
706 if self.HistoryWindow is not None and self.HistoryWindow.shown:
707 self.HistoryWindow.pageDown()
708 def keyStdFeed(self):
709 self.hideSuggestions()
710 menulist = [(_("High definition"), "hd")]
712 (_("Top rated"), "top_rated"),
713 (_("Top favorites"), "top_favorites"),
714 (_("Most viewed"), "most_viewed"),
715 (_("Most popular"), "most_popular"),
716 (_("Most recent"), "most_recent"),
717 (_("Most discussed"), "most_discussed"),
718 (_("Most linked"), "most_linked"),
719 (_("Most responded"), "most_responded")
721 self.session.openWithCallback(self.openStandardFeedClosed, ChoiceBox, title=_("Select new feed to view."), list = menulist)
723 def handleSuggestions(self):
724 print "handleSuggestions"
725 print "self.currList",self.currList
726 if self.currList == "configlist":
727 self.switchToSuggestionsList()
728 elif self.currList == "historylist":
729 if self.HistoryWindow is not None and self.HistoryWindow.shown:
730 self.HistoryWindow.down()
732 def switchToSuggestionsList(self):
733 print "switchToSuggestionsList"
734 self.currList = "suggestionslist"
735 self["ButtonBlue"].hide()
736 self["VKeyIcon"].hide()
737 self["statusactions"].setEnabled(False)
738 self["config_actions"].setEnabled(False)
739 self["videoactions"].setEnabled(False)
740 self["searchactions"].setEnabled(False)
741 self["suggestionactions"].setEnabled(True)
742 self["key_green"].hide()
743 self.propagateUpDownNormally = False
744 self["config"].invalidateCurrent()
745 if self.HistoryWindow is not None and self.HistoryWindow.shown:
746 self.HistoryWindow.deactivate()
747 self.HistoryWindow.instance.hide()
749 def switchToConfigList(self):
750 print "switchToConfigList"
751 self.currList = "configlist"
752 self["statusactions"].setEnabled(False)
753 self["config_actions"].setEnabled(True)
754 self["videoactions"].setEnabled(False)
755 self["suggestionactions"].setEnabled(False)
756 self["searchactions"].setEnabled(True)
757 self["key_green"].hide()
758 self["ButtonBlue"].show()
759 self["VKeyIcon"].show()
760 current = self["config"].getCurrent()
761 helpwindowpos = self["HelpWindow"].getPosition()
762 if current[1].help_window.instance is not None:
763 current[1].help_window.instance.move(ePoint(helpwindowpos[0],helpwindowpos[1]))
764 current[1].help_window.instance.show()
765 if current[1].suggestionsWindow.instance is not None:
766 current[1].suggestionsWindow.instance.show()
767 self["config"].getCurrent()[1].getSuggestions()
768 self.propagateUpDownNormally = True
769 if self.HistoryWindow is not None and self.HistoryWindow.shown:
770 self.HistoryWindow.deactivate()
771 self.HistoryWindow.instance.hide()
772 if self.FirstRun == True:
773 self.handleFirstHelpWindow()
775 def switchToFeedList(self, append = False):
776 print "switchToFeedList"
777 self.currList = "feedlist"
778 self["ButtonBlue"].hide()
779 self["VKeyIcon"].hide()
780 self["videoactions"].setEnabled(True)
781 self["suggestionactions"].setEnabled(False)
782 self["searchactions"].setEnabled(False)
783 self["statusactions"].setEnabled(False)
784 self["key_green"].show()
785 self["config_actions"].setEnabled(False)
787 self[self.currList].setIndex(0)
788 if self.HistoryWindow is not None and self.HistoryWindow.shown:
789 self.HistoryWindow.deactivate()
790 self.HistoryWindow.instance.hide()
791 self.hideSuggestions()
793 def handleHistory(self):
794 if self.HistoryWindow is None:
795 self.HistoryWindow = self.session.instantiateDialog(MyTubeHistoryScreen)
796 if self.currList == "configlist":
797 print "handle history currentlist",self.currList
798 print "handle history oldlist",self.oldlist
799 if self.HistoryWindow.status() is False:
800 print "status is FALSE"
801 self.oldlist = self.currList
802 self.currList = "historylist"
803 self.hideSuggestions()
804 self.HistoryWindow.activate()
805 self.HistoryWindow.instance.show()
806 elif self.currList == "feedlist":
807 print "handle history currentlist",self.currList
808 print "handle history oldlist",self.oldlist
809 if self.HistoryWindow.status() is False:
810 print "status is FALSE"
811 self.oldlist = self.currList
812 self.currList = "historylist"
813 self.HistoryWindow.activate()
814 self.HistoryWindow.instance.show()
815 elif self.currList == "historylist":
816 print "handle history currentlist",self.currList
817 print "handle history oldlist",self.oldlist
818 if self.HistoryWindow.status() is True:
819 print "status is TRUE"
820 self.currList = self.oldlist
821 self.HistoryWindow.deactivate()
822 self.HistoryWindow.instance.hide()
823 if self.oldlist == 'configlist':
824 current = self["config"].getCurrent()
825 helpwindowpos = self["HelpWindow"].getPosition()
826 if current[1].help_window.instance is not None:
827 current[1].help_window.instance.move(ePoint(helpwindowpos[0],helpwindowpos[1]))
828 current[1].help_window.instance.show()
829 if current[1].suggestionsWindow.instance is not None:
830 current[1].suggestionsWindow.instance.show()
831 self.propagateUpDownNormally = True
833 def add2History(self):
834 if self.History is None:
835 self.History = config.plugins.mytube.general.history.value.split(',')
836 if self.History[0] == '':
838 print "self.History im add",self.History
839 if config.plugins.mytube.search.searchTerm.value not in self.History:
840 self.History.append((config.plugins.mytube.search.searchTerm.value))
841 self.History.reverse()
842 if len(self.History) == 15:
844 config.plugins.mytube.general.history.value = ",".join(self.History)
845 config.plugins.mytube.general.history.save()
846 print "configvalue",config.plugins.mytube.general.history.value
848 def hideSuggestions(self):
849 current = self["config"].getCurrent()
850 if current[1].help_window.instance is not None:
851 current[1].help_window.instance.hide()
852 if current[1].suggestionsWindow.instance is not None:
853 current[1].suggestionsWindow.instance.hide()
854 self.propagateUpDownNormally = True
856 def getFeed(self, feedUrl, feedName):
858 feed = myTubeService.getFeed(feedUrl)
861 print "Error querying feed :",feedName
863 self.setState('Error')
866 self.loadPreviewpics()
868 def getNextEntries(self, result):
871 nextUrl = myTubeService.getNextFeedEntriesURL()
872 if nextUrl is not None:
873 self.appendEntries = True
874 self.getFeed(nextUrl, _("More video entries."))
876 def getRelatedVideos(self, myentry):
878 myurl = myentry.getRelatedVideos()
879 print "RELATEDURL--->",myurl
880 if myurl is not None:
881 self.getFeed(myurl, _("Related video entries."))
883 def getResponseVideos(self, myentry):
885 myurl = myentry.getResponseVideos()
886 print "RESPONSEURL--->",myurl
887 if myurl is not None:
888 self.getFeed(myurl, _("Response video entries."))
890 def runSearch(self, searchContext = None):
891 print "[MyTubePlayer] runSearch"
892 if searchContext is not None:
893 print "[MyTubePlayer] searchDialogClosed: ", searchContext
894 self.searchFeed(searchContext)
896 def searchFeed(self, searchContext):
897 print "[MyTubePlayer] searchFeed"
898 self.appendEntries = False
900 feed = myTubeService.search(searchContext,
901 orderby = config.plugins.mytube.search.orderBy.value,
902 racy = config.plugins.mytube.search.racy.value,
903 lr = config.plugins.mytube.search.lr.value,
904 categories = [ config.plugins.mytube.search.categories.value ],
905 sortOrder = config.plugins.mytube.search.sortOrder.value)
908 print "Error querying search for :",config.plugins.mytube.search.searchTerm.value
910 self.setState('Error')
913 if self.FirstRun == True:
914 self.FirstRun = False
915 self.loadPreviewpics()
917 def loadPreviewpics(self):
919 self.mytubeentries = None
923 self.mytubeentries = myTubeService.getEntries()
924 self.maxentries = len(self.mytubeentries)-1
925 if self.mytubeentries and len(self.mytubeentries):
927 for entry in self.mytubeentries:
928 TubeID = entry.getTubeId()
929 thumbnailFile = "/tmp/" + str(TubeID) + ".jpg"
930 currPic = [currindex,TubeID,thumbnailFile,None]
931 self.thumbnails.append(currPic)
933 thumbnailUrl = entry.getThumbnailUrl(0)
934 if thumbnailUrl is not None:
935 client.downloadPage(thumbnailUrl,thumbnailFile).addCallback(self.fetchFinished,currindex,str(TubeID)).addErrback(self.fetchFailed,currindex,str(TubeID))
940 def fetchFailed(self, string, index, id):
941 print "[fetchFailed] for index:" + str(index) + "for YoutubeID:" + id + string.getErrorMessage()
943 def fetchFinished(self, string, index, id):
944 print "[fetchFinished] for index:" + str(index) + " for YoutubeID:" + id
945 self.decodePic(index)
947 def decodePic(self, index):
948 sc = AVSwitch().getFramebufferScale()
949 self.picloads[index] = ePicLoad()
950 self.picloads[index].PictureData.get().append(boundFunction(self.finish_decode, index))
951 for entry in self.thumbnails:
952 if entry[0] == index:
954 thumbnailFile = entry[2]
955 if (os_path.exists(thumbnailFile) == True):
956 #print "[decodePic] DECODING THUMBNAIL for INDEX:"+ str(self.index) + "and file: " + thumbnailFile
957 self.picloads[index].setPara((self["thumbnail"].instance.size().width(), self["thumbnail"].instance.size().height(), sc[0], sc[1], False, 1, "#00000000"))
958 self.picloads[index].startDecode(thumbnailFile)
960 print "[decodePic] Thumbnail file NOT FOUND !!!-->:",thumbnailFile
962 def finish_decode(self, picindex = None, picInfo=None):
963 #print "finish_decode - of INDEX", picindex
964 ptr = self.picloads[picindex].getData()
967 self.thumbnails[picindex][3] = ptr
968 if (os_path.exists(self.thumbnails[picindex][2]) == True):
969 #print "removing", self.thumbnails[picindex][2]
970 remove(self.thumbnails[picindex][2])
971 del self.picloads[picindex]
972 if len(self.picloads) == 0:
973 self.timer.startLongTimer(3)
975 def picloadTimeout(self):
977 if len(self.picloads) == 0:
978 print "all decodes should be now really finished"
979 self.buildEntryList()
981 self.timer.startLongTimer(2)
983 def buildEntryList(self):
985 if self.appendEntries == False:
987 for entry in self.mytubeentries:
988 self.videolist.append(self.buildEntryComponent(entry, myindex))
990 if len(self.videolist):
991 self["feedlist"].style = "default"
992 self["feedlist"].disable_callbacks = True
993 self["feedlist"].list = self.videolist
994 self["feedlist"].disable_callbacks = False
995 self["feedlist"].setIndex(0)
996 self["feedlist"].setList(self.videolist)
997 self["feedlist"].updateList(self.videolist)
998 if self.FirstRun == True:
999 self.switchToConfigList()
1001 self.switchToFeedList()
1003 self.oldfeedentrycount = self["feedlist"].count()
1004 for entry in self.mytubeentries:
1005 self.videolist.append(self.buildEntryComponent(entry, myindex))
1007 if len(self.videolist):
1008 self["feedlist"].style = "default"
1009 old_index = self["feedlist"].index
1010 self["feedlist"].disable_callbacks = True
1011 self["feedlist"].list = self.videolist
1012 self["feedlist"].disable_callbacks = False
1013 self["feedlist"].setList(self.videolist)
1014 self["feedlist"].setIndex(old_index)
1015 self["feedlist"].updateList(self.videolist)
1016 self["feedlist"].selectNext()
1017 self.switchToFeedList(True)
1020 def buildEntryComponent(self, entry, index):
1021 Title = entry.getTitle()
1022 print "Titel-->",Title
1023 Description = entry.getDescription()
1024 TubeID = entry.getTubeId()
1025 PublishedDate = entry.getPublishedDate()
1026 if PublishedDate is not "unknown":
1027 published = PublishedDate.split("T")[0]
1029 published = "unknown"
1030 Views = entry.getViews()
1031 if Views is not "not available":
1034 views = "not available"
1035 Duration = entry.getDuration()
1036 if Duration is not 0:
1037 durationInSecs = int(Duration)
1038 mins = int(durationInSecs / 60)
1039 secs = durationInSecs - mins * 60
1040 duration = "%d:%02d" % (mins, secs)
1042 duration = "not available"
1043 Ratings = entry.getNumRaters()
1044 if Ratings is not "":
1048 thumbnail = self.thumbnails[index][3]
1049 return((entry, Title, Description, TubeID, thumbnail, _("Added: ") + str(published), _("Views: ") + str(views), _("Duration: ") + str(duration), _("Ratings: ") + str(ratings) ))
1051 def getNextEntry(self):
1052 i = self["feedlist"].getIndex() + 1
1053 if i < len(self.videolist):
1054 self["feedlist"].selectNext()
1055 current = self["feedlist"].getCurrent()
1057 myentry = current[0]
1059 myurl = myentry.getVideoUrl()
1060 if myurl is not None:
1061 print "Got a URL to stream"
1062 myreference = eServiceReference(4097,0,myurl)
1063 myreference.setName(myentry.getTitle())
1064 return myreference,False
1066 print "NoURL im getNextEntry"
1069 print "no more entries to play"
1072 def getPrevEntry(self):
1073 i = self["feedlist"].getIndex() - 1
1075 self["feedlist"].selectPrevious()
1076 current = self["feedlist"].getCurrent()
1078 myentry = current[0]
1080 myurl = myentry.getVideoUrl()
1081 if myurl is not None:
1082 print "Got a URL to stream"
1083 myreference = eServiceReference(4097,0,myurl)
1084 myreference.setName(myentry.getTitle())
1085 return myreference,False
1090 def showVideoInfo(self):
1091 if self.currList == "feedlist":
1092 cmd = "rm -rf /tmp/*.jpg"
1093 if self.CleanupConsole is None:
1094 self.CleanupConsole = Console()
1095 self.CleanupConsole.ePopen(cmd, self.openInfoScreen)
1097 def openInfoScreen(self, result, retval,extra_args):
1098 if self.currList == "feedlist":
1099 current = self[self.currList].getCurrent()
1101 myentry = current[0]
1103 print "Title im showVideoInfo",myentry.getTitle()
1104 videoinfos = myentry.PrintEntryDetails()
1105 self.session.open(MyTubeVideoInfoScreen, self.skin_path, videoinfo = videoinfos )
1108 class MyTubeVideoInfoScreen(Screen):
1110 <screen name="MyTubeVideoInfoScreen" flags="wfNoBorder" position="0,0" size="720,576" title="MyTubePlayerMainScreen..." >
1111 <ePixmap position="0,0" zPosition="-1" size="720,576" pixmap="~/mytubemain_bg.png" alphatest="on" transparent="1" backgroundColor="transparent"/>
1112 <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" />
1113 <widget name="starsbg" pixmap="~/starsbar_empty.png" position="560,220" zPosition="5" size="100,20" transparent="1" alphatest="on" />
1114 <widget name="stars" pixmap="~/starsbar_filled.png" position="560,220" zPosition="6" size="100,20" transparent="1" />
1115 <widget source="infolist" render="Listbox" position="50,110" size="620,110" zPosition="6" scrollbarMode="showNever" selectionDisabled="1" transparent="1">
1116 <convert type="TemplatedMultiContent">
1119 MultiContentEntryPixmapAlphaTest(pos = (0, 4), size = (130, 98), png = 0), # index 0 is the thumbnail
1120 MultiContentEntryPixmapAlphaTest(pos = (130, 4), size = (130, 98), png = 1), # index 0 is the thumbnail
1121 MultiContentEntryPixmapAlphaTest(pos = (260, 4), size = (130, 98), png = 2), # index 0 is the thumbnail
1122 MultiContentEntryPixmapAlphaTest(pos = (390, 4), size = (130, 98), png = 3), # index 0 is the thumbnail
1125 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
1128 "fonts": [gFont("Regular", 20),gFont("Regular", 14),gFont("Regular", 28)],
1133 <widget name="author" position="60,220" size="300,20" zPosition="10" font="Regular;21" transparent="1" halign="left" valign="top" />
1134 <widget name="duration" position="370,220" size="200,20" zPosition="10" font="Regular;21" transparent="1" halign="left" valign="top" />
1135 <widget name="published" position="60,245" size="300,20" zPosition="10" font="Regular;21" transparent="1" halign="left" valign="top" />
1136 <widget name="views" position="370,245" size="200,20" zPosition="10" font="Regular;21" transparent="1" halign="left" valign="top" />
1137 <widget name="tags" position="60,270" size="600,20" zPosition="10" font="Regular;21" transparent="1" halign="left" valign="top" />
1138 <widget name="detailtext" position="60,300" size="610,200" zPosition="10" font="Regular;21" transparent="1" halign="left" valign="top"/>
1139 <ePixmap position="100,500" size="100,40" zPosition="0" pixmap="~/plugin.png" alphatest="on" transparent="1" />
1140 <ePixmap position="220,500" zPosition="4" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
1141 <ePixmap position="360,500" zPosition="4" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
1142 <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" />
1143 <widget name="key_green" position="360,500" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
1144 <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.
1147 def __init__(self, session, plugin_path, videoinfo = None):
1148 Screen.__init__(self, session)
1149 self.session = session
1150 self.skin_path = plugin_path
1151 self.videoinfo = videoinfo
1153 self.thumbnails = []
1155 self["title"] = Label()
1156 self["key_red"] = Button(_("Close"))
1157 self["key_green"] = Button(_("Search"))
1158 self["thumbnail"] = Pixmap()
1159 self["thumbnail"].hide()
1160 self["detailtext"] = ScrollLabel()
1161 self["starsbg"] = Pixmap()
1162 self["stars"] = ProgressBar()
1163 self["duration"] = Label()
1164 self["author"] = Label()
1165 self["published"] = Label()
1166 self["views"] = Label()
1167 self["tags"] = Label()
1168 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions", "MovieSelectionActions"],
1173 "down": self.pageDown,
1174 "left": self.pageUp,
1175 "right": self.pageDown,
1178 self["infolist"] = List(self.infolist)
1179 self.timer = eTimer()
1180 self.timer.callback.append(self.picloadTimeout)
1181 self.onLayoutFinish.append(self.layoutFinished)
1182 self.onShown.append(self.setWindowTitle)
1184 def layoutFinished(self):
1185 self.statuslist = []
1186 self.statuslist.append(( _("Downloading screenshots. Please wait..." ),_("Downloading screenshots. Please wait..." ) ))
1187 self["infolist"].style = "state"
1188 self['infolist'].setList(self.statuslist)
1189 self.loadPreviewpics()
1190 if self.videoinfo["Title"] is not None:
1191 self["title"].setText(self.videoinfo["Title"])
1193 if self.videoinfo["Description"] is not None:
1194 Description = self.videoinfo["Description"]
1197 if Description is not None:
1198 self["detailtext"].setText(Description.strip())
1200 if self.videoinfo["RatingAverage"] is not 0:
1201 ratingStars = int(round(20 * float(self.videoinfo["RatingAverage"]), 0))
1202 self["stars"].setValue(ratingStars)
1204 self["stars"].hide()
1205 self["starsbg"].hide()
1207 if self.videoinfo["Duration"] is not 0:
1208 durationInSecs = int(self.videoinfo["Duration"])
1209 mins = int(durationInSecs / 60)
1210 secs = durationInSecs - mins * 60
1211 duration = "%d:%02d" % (mins, secs)
1212 self["duration"].setText(_("Duration: ") + str(duration))
1214 if self.videoinfo["Author"] is not None or '':
1215 self["author"].setText(_("Author: ") + self.videoinfo["Author"])
1217 if self.videoinfo["Published"] is not "unknown":
1218 self["published"].setText(_("Added: ") + self.videoinfo["Published"].split("T")[0])
1220 if self.videoinfo["Views"] is not "not available":
1221 self["views"].setText(_("Views: ") + str(self.videoinfo["Views"]))
1223 if self.videoinfo["Tags"] is not "not available":
1224 self["tags"].setText(_("Tags: ") + str(self.videoinfo["Tags"]))
1226 def setWindowTitle(self):
1227 self.setTitle(_("MyTubeVideoInfoScreen"))
1230 self["detailtext"].pageUp()
1233 self["detailtext"].pageDown()
1235 def loadPreviewpics(self):
1236 self.thumbnails = []
1237 self.mythumbubeentries = None
1241 self.mythumbubeentries = self.videoinfo["Thumbnails"]
1242 self.maxentries = len(self.mythumbubeentries)-1
1243 if self.mythumbubeentries and len(self.mythumbubeentries):
1245 for entry in self.mythumbubeentries:
1246 TubeID = self.videoinfo["TubeID"]
1247 ThumbID = TubeID + str(currindex)
1248 thumbnailFile = "/tmp/" + ThumbID + ".jpg"
1249 currPic = [currindex,ThumbID,thumbnailFile,None]
1250 self.thumbnails.append(currPic)
1252 thumbnailUrl = entry
1253 if thumbnailUrl is not None:
1254 client.downloadPage(thumbnailUrl,thumbnailFile).addCallback(self.fetchFinished,currindex,ThumbID).addErrback(self.fetchFailed,currindex,ThumbID)
1259 def fetchFailed(self, string, index, id):
1260 print "[fetchFailed] for index:" + str(index) + "for ThumbID:" + id + string.getErrorMessage()
1262 def fetchFinished(self, string, index, id):
1263 print "[fetchFinished] for index:" + str(index) + " for ThumbID:" + id
1264 self.decodePic(index)
1266 def decodePic(self, index):
1267 sc = AVSwitch().getFramebufferScale()
1268 self.picloads[index] = ePicLoad()
1269 self.picloads[index].PictureData.get().append(boundFunction(self.finish_decode, index))
1270 for entry in self.thumbnails:
1271 if entry[0] == index:
1273 thumbnailFile = entry[2]
1274 if (os_path.exists(thumbnailFile) == True):
1275 print "[decodePic] DECODING THUMBNAIL for INDEX:"+ str(self.index) + "and file: " + thumbnailFile
1276 self.picloads[index].setPara((self["thumbnail"].instance.size().width(), self["thumbnail"].instance.size().height(), sc[0], sc[1], False, 1, "#00000000"))
1277 self.picloads[index].startDecode(thumbnailFile)
1279 print "[decodePic] Thumbnail file NOT FOUND !!!-->:",thumbnailFile
1281 def finish_decode(self, picindex = None, picInfo=None):
1282 print "finish_decode - of INDEX", picindex
1283 ptr = self.picloads[picindex].getData()
1286 self.thumbnails[picindex][3] = ptr
1287 if (os_path.exists(self.thumbnails[picindex][2]) == True):
1288 print "removing", self.thumbnails[picindex][2]
1289 remove(self.thumbnails[picindex][2])
1290 del self.picloads[picindex]
1291 if len(self.picloads) == 0:
1292 self.timer.startLongTimer(3)
1294 def picloadTimeout(self):
1296 if len(self.picloads) == 0:
1297 print "all decodes should be now really finished"
1298 self.buildInfoList()
1300 self.timer.startLongTimer(2)
1302 def buildInfoList(self):
1309 if self.thumbnails[0][3] is not None:
1310 Thumbail0 = self.thumbnails[0][3]
1311 if self.thumbnails[1][3] is not None:
1312 Thumbail1 = self.thumbnails[1][3]
1313 if self.thumbnails[2][3] is not None:
1314 Thumbail2 = self.thumbnails[2][3]
1315 if self.thumbnails[3][3] is not None:
1316 Thumbail3 = self.thumbnails[3][3]
1317 self.infolist.append(( Thumbail0, Thumbail1, Thumbail2, Thumbail3))
1318 if len(self.infolist):
1319 self["infolist"].style = "default"
1320 self["infolist"].disable_callbacks = True
1321 self["infolist"].list = self.infolist
1322 self["infolist"].disable_callbacks = False
1323 self["infolist"].setIndex(0)
1324 self["infolist"].setList(self.infolist)
1325 self["infolist"].updateList(self.infolist)
1328 class MyTubeVideoHelpScreen(Screen):
1330 <screen name="MyTubeVideoHelpScreen" flags="wfNoBorder" position="0,0" size="720,576" title="MyTubePlayerMainScreen..." >
1331 <ePixmap position="0,0" zPosition="-1" size="720,576" pixmap="~/mytubemain_bg.png" alphatest="on" transparent="1" backgroundColor="transparent"/>
1332 <widget name="title" position="60,50" size="600,50" zPosition="5" valign="center" halign="left" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
1333 <widget name="detailtext" position="60,120" size="610,370" zPosition="10" font="Regular;21" transparent="1" halign="left" valign="top"/>
1334 <ePixmap position="100,500" size="100,40" zPosition="0" pixmap="~/plugin.png" alphatest="on" transparent="1" />
1335 <ePixmap position="220,500" zPosition="4" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
1336 <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" />
1339 def __init__(self, session, plugin_path, wantedinfo = None, wantedtitle = None):
1340 Screen.__init__(self, session)
1341 self.session = session
1342 self.skin_path = plugin_path
1343 self.wantedinfo = wantedinfo
1344 self.wantedtitle = wantedtitle
1345 self["title"] = Label()
1346 self["key_red"] = Button(_("Close"))
1347 self["detailtext"] = ScrollLabel()
1349 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
1354 "down": self.pageDown,
1355 "left": self.pageUp,
1356 "right": self.pageDown,
1359 self.onLayoutFinish.append(self.layoutFinished)
1360 self.onShown.append(self.setWindowTitle)
1362 def layoutFinished(self):
1363 if self.wantedtitle is None:
1364 self["title"].setText(_("Help"))
1366 self["title"].setText(self.wantedtitle)
1367 if self.wantedinfo is None:
1368 self["detailtext"].setText(_("This is the help screen. Feed me with something to display."))
1370 self["detailtext"].setText(self.wantedinfo)
1372 def setWindowTitle(self):
1373 self.setTitle(_("MyTubeVideohelpScreen"))
1376 self["detailtext"].pageUp()
1379 self["detailtext"].pageDown()
1382 class MyTubePlayer(Screen, InfoBarNotifications):
1386 ENABLE_RESUME_SUPPORT = True
1387 ALLOW_SUSPEND = True
1389 skin = """<screen name="MyTubePlayer" flags="wfNoBorder" position="0,380" size="720,160" title="InfoBar" backgroundColor="transparent">
1390 <ePixmap position="0,0" pixmap="skin_default/info-bg_mp.png" zPosition="-1" size="720,160" />
1391 <ePixmap position="29,40" pixmap="skin_default/screws_mp.png" size="665,104" alphatest="on" />
1392 <ePixmap position="48,70" pixmap="skin_default/icons/mp_buttons.png" size="108,13" alphatest="on" />
1393 <ePixmap pixmap="skin_default/icons/icon_event.png" position="207,78" size="15,10" alphatest="on" />
1394 <widget source="session.CurrentService" render="Label" position="230,73" size="360,40" font="Regular;20" backgroundColor="#263c59" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1">
1395 <convert type="ServiceName">Name</convert>
1397 <widget source="session.CurrentService" render="Label" position="580,73" size="90,24" font="Regular;20" halign="right" backgroundColor="#4e5a74" transparent="1">
1398 <convert type="ServicePosition">Length</convert>
1400 <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">
1401 <convert type="ServicePosition">Position</convert>
1403 <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">
1404 <convert type="ServicePosition">Gauge</convert>
1406 <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">
1407 <convert type="ServicePosition">Remaining</convert>
1411 def __init__(self, session, service, lastservice, infoCallback = None, nextCallback = None, prevCallback = None):
1412 Screen.__init__(self, session)
1413 InfoBarNotifications.__init__(self)
1414 self.session = session
1415 self.service = service
1416 self.infoCallback = infoCallback
1417 self.nextCallback = nextCallback
1418 self.prevCallback = prevCallback
1419 self.screen_timeout = 5000
1420 self.nextservice = None
1422 print "evEOF=%d" % iPlayableService.evEOF
1423 self.__event_tracker = ServiceEventTracker(screen = self, eventmap =
1425 iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged,
1426 iPlayableService.evStart: self.__serviceStarted,
1427 iPlayableService.evEOF: self.__evEOF,
1430 self["actions"] = ActionMap(["OkCancelActions", "InfobarSeekActions", "MediaPlayerActions", "MovieSelectionActions"],
1433 "cancel": self.leavePlayer,
1434 "stop": self.leavePlayer,
1435 "playpauseService": self.playpauseService,
1436 "seekFwd": self.playNextFile,
1437 "seekBack": self.playPrevFile,
1438 "showEventInfo": self.showVideoInfo,
1442 self.lastservice = lastservice
1444 self.hidetimer = eTimer()
1445 self.hidetimer.timeout.get().append(self.ok)
1446 self.returning = False
1448 self.state = self.STATE_PLAYING
1449 self.lastseekstate = self.STATE_PLAYING
1451 self.onPlayStateChanged = [ ]
1452 self.__seekableStatusChanged()
1455 self.onClose.append(self.__onClose)
1457 def __onClose(self):
1458 self.session.nav.stopService()
1461 print "evEOF=%d" % iPlayableService.evEOF
1463 self.handleLeave(config.plugins.mytube.general.on_movie_stop.value)
1465 def __setHideTimer(self):
1466 self.hidetimer.start(self.screen_timeout)
1468 def showInfobar(self):
1470 if self.state == self.STATE_PLAYING:
1471 self.__setHideTimer()
1475 def hideInfobar(self):
1477 self.hidetimer.stop()
1485 def showVideoInfo(self):
1488 if self.infoCallback is not None:
1492 def playNextFile(self):
1493 print "playNextFile"
1494 nextservice,error = self.nextCallback()
1495 print "nextservice--->",nextservice
1496 if nextservice is None:
1497 self.handleLeave(config.plugins.mytube.general.on_movie_stop.value, error)
1499 self.playService(nextservice)
1502 def playPrevFile(self):
1503 print "playPrevFile"
1504 prevservice,error = self.prevCallback()
1505 if prevservice is None:
1506 self.handleLeave(config.plugins.mytube.general.on_movie_stop.value, error)
1508 self.playService(prevservice)
1511 def playagain(self):
1513 if self.state != self.STATE_IDLE:
1517 def playService(self, newservice):
1518 if self.state != self.STATE_IDLE:
1520 self.service = newservice
1524 if self.state == self.STATE_PAUSED:
1526 self.__setHideTimer()
1527 self.state = self.STATE_PLAYING
1528 print "self.state--->",self.state
1529 self.session.nav.playService(self.service)
1531 self.__setHideTimer()
1533 def stopCurrent(self):
1535 self.session.nav.stopService()
1536 #if self.state == self.STATE_IDLE:
1538 self.state = self.STATE_IDLE
1539 print "self.state--->",self.state
1542 def playpauseService(self):
1543 print "playpauseService"
1544 #print "self.state--->",self.state
1545 if self.state == self.STATE_PLAYING:
1547 elif self.state == self.STATE_PAUSED:
1548 self.unPauseService()
1550 def pauseService(self):
1551 print "pauseService"
1552 if self.state == self.STATE_PLAYING:
1553 #print "self.state--->",self.state
1554 print "calling setseekstate pause"
1555 self.setSeekState(self.STATE_PAUSED)
1557 def unPauseService(self):
1558 print "unPauseService"
1559 if self.state == self.STATE_PAUSED:
1560 #print "self.state--->",self.state
1561 print "calling setseekstate playing"
1562 self.setSeekState(self.STATE_PLAYING)
1566 service = self.session.nav.getCurrentService()
1570 seek = service.seek()
1572 if seek is None or not seek.isCurrentlySeekable():
1577 def isSeekable(self):
1578 if self.getSeek() is None:
1582 def __seekableStatusChanged(self):
1583 print "seekable status changed!"
1584 if not self.isSeekable():
1585 #self["SeekActions"].setEnabled(False)
1586 print "not seekable, return to play"
1587 self.setSeekState(self.STATE_PLAYING)
1589 # self["SeekActions"].setEnabled(True)
1592 def __serviceStarted(self):
1593 self.state = self.STATE_PLAYING
1594 self.__seekableStatusChanged()
1596 def setSeekState(self, wantstate):
1597 print "setSeekState"
1598 #print "current state--->",self.state
1599 #print " wanted state--->",wantstate
1600 if wantstate == self.STATE_PAUSED:
1601 print "trying to switch to Pause- state:",self.STATE_PAUSED
1602 elif wantstate == self.STATE_PLAYING:
1603 print "trying to switch to playing- state:",self.STATE_PLAYING
1604 service = self.session.nav.getCurrentService()
1606 print "No Service found"
1608 pauseable = service.pause()
1609 if pauseable is None:
1610 print "not pauseable."
1611 self.state = self.STATE_PLAYING
1613 if pauseable is not None:
1614 print "service is pausable"
1615 if wantstate == self.STATE_PAUSED:
1616 print "WANT TO PAUSE"
1617 print "current state --->",self.state
1618 print "wanted state --->",wantstate
1620 self.state = self.STATE_PAUSED
1622 self.hidetimer.stop()
1624 elif wantstate == self.STATE_PLAYING:
1625 print "WANT TO PLAY"
1626 print "current state --->",self.state
1627 print "wanted state --->",wantstate
1629 self.state = self.STATE_PLAYING
1631 self.__setHideTimer()
1633 for c in self.onPlayStateChanged:
1638 def handleLeave(self, how, error = False):
1639 self.is_closing = True
1643 (_("No, but play video again"), "playagain"),
1644 (_("Yes, but play next video"), "playnext"),
1645 (_("Yes, but play previous video"), "playprev"),
1648 self.session.openWithCallback(self.leavePlayerConfirmed, ChoiceBox, title=_("Stop playing this movie?"), list = list)
1650 self.session.openWithCallback(self.leavePlayerConfirmed, ChoiceBox, title=_("No playable video found! Stop playing this movie?"), list = list)
1652 self.leavePlayerConfirmed([True, how])
1654 def leavePlayer(self):
1655 self.handleLeave(config.plugins.mytube.general.on_movie_stop.value)
1657 def leavePlayerConfirmed(self, answer):
1658 answer = answer and answer[1]
1659 print "ANSWER im player leave",answer
1660 if answer == "quit":
1662 elif answer == "playnext":
1664 elif answer == "playprev":
1666 elif answer == "playagain":
1669 def doEofInternal(self, playing):
1670 if not self.execing:
1674 self.handleLeave(config.usage.on_movie_eof.value)
1677 def MyTubeMain(session, **kwargs):
1678 Console().ePopen(("rm -rf /tmp/*.jpg"))
1679 session.open(MyTubePlayerMainScreen)
1682 def Plugins(path, **kwargs):
1685 return PluginDescriptor(
1686 name=_("My TubePlayer"),
1687 description=_("Play YouTube movies"),
1688 where = [ PluginDescriptor.WHERE_EXTENSIONSMENU, PluginDescriptor.WHERE_PLUGINMENU ],
1689 icon = "plugin.png", fnc = boundFunction(MyTubeMain))