Much improved error-handling
[enigma2-plugins.git] / youtubeplayer / src / YouTubeList.py
1 ############################################################################
2 #    Copyright (C) 2008 by Volker Christian                                #
3 #    Volker.Christian@fh-hagenberg.at                                      #
4 #                                                                          #
5 #    This program is free software; you can redistribute it and#or modify  #
6 #    it under the terms of the GNU General Public License as published by  #
7 #    the Free Software Foundation; either version 2 of the License, or     #
8 #    (at your option) any later version.                                   #
9 #                                                                          #
10 #    This program is distributed in the hope that it will be useful,       #
11 #    but WITHOUT ANY WARRANTY; without even the implied warranty of        #
12 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         #
13 #    GNU General Public License for more details.                          #
14 #                                                                          #
15 #    You should have received a copy of the GNU General Public License     #
16 #    along with this program; if not, write to the                         #
17 #    Free Software Foundation, Inc.,                                       #
18 #    59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             #
19 ############################################################################
20
21 from YouTubeInterface import interface
22
23 from Components.ActionMap import ActionMap
24 from Components.MenuList import MenuList
25 from Components.Label import Label
26 from Components.ScrollLabel import ScrollLabel
27 from Components.Pixmap import Pixmap
28 from Components.ProgressBar import ProgressBar
29
30 from Components.MultiContent import MultiContentEntryText, MultiContentEntryPixmapAlphaTest
31 from Tools.Directories import resolveFilename, SCOPE_PLUGINS, SCOPE_SKIN_IMAGE
32 from enigma import eListboxPythonMultiContent, gFont, RT_HALIGN_LEFT, RT_VALIGN_TOP, RT_WRAP
33 from enigma import eTimer
34
35 from Tools.NumericalTextInput import NumericalTextInput
36
37 from Screens.Screen import Screen
38 from Screens.MessageBox import MessageBox
39
40 from Components.config import config
41
42 from Plugins.Extensions.VlcPlayer.VlcServerConfig import vlcServerConfig
43 from Plugins.Extensions.VlcPlayer.VlcServer import VlcServer
44 from Plugins.Extensions.VlcPlayer.VlcServerList import VlcServerListScreen
45
46 from YouTubeContextMenu import YouTubeEntryContextMenu, YouTubeEntryContextMenuList
47
48 from Tools.BoundFunction import boundFunction
49
50 from YouTubePlayer import YouTubePlayer
51
52 from YouTubeUserConfig import youTubeUserConfig
53 from YouTubeUserList import YouTubeUserListScreen
54 from YouTubePlayList import YouTubePlaylistScreen
55
56 from . import _
57
58 def YouTubeEntryComponent(entry):
59         res = [ entry ]
60 # 385
61         res.append(MultiContentEntryText(pos = (150, 5), size = (370, 42), font = 0, flags = RT_HALIGN_LEFT | RT_VALIGN_TOP| RT_WRAP, text = entry.getTitle()))
62         res.append(MultiContentEntryText(pos = (150, 46), size = (370, 56), font = 1, color = 0xFFA323, color_sel = 0xFFA323, flags = RT_HALIGN_LEFT | RT_VALIGN_TOP| RT_WRAP, text = entry.getDescription()))
63
64         if entry.thumbnail["0"] is None:
65                 png = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/plugin.png"))
66         else:
67                 png = entry.thumbnail["0"]
68         res.append(MultiContentEntryPixmapAlphaTest(pos = (10, 5), size = (130, 97), png = png))
69
70         return res
71
72
73 class YouTubeVideoDetailsScreen(Screen):
74         def __init__(self, session, entry):
75                 Screen.__init__(self, session)
76                 self.entry = entry
77                 self["video_description"] = ScrollLabel(entry.getDescription())
78                 durationInSecs = int(entry.getDuration())
79                 mins = int(durationInSecs / 60)
80                 secs = durationInSecs - mins * 60
81                 duration = "%d:%02d" % (mins, secs)
82                 
83                 self["label_video_duration"] = Label(_("Duration") + ":")
84                 self["video_duration"] = Label(duration)
85                 
86                 self["label_video_rating_average"] = Label(_("Rate") + ":")
87                 self["starsbg"] = Pixmap()
88                 self["stars"] = ProgressBar()
89
90                 self["label_video_numraters"] = Label(_("Ratings") + ":")
91                 self["video_numraters"] = Label(entry.getNumRaters())
92                 
93                 self["label_video_statistics_favorite_count"] = Label(_("Favorited") + ":")
94                 self["video_statistics_favorite_count"] = Label(entry.getFavoriteCount())
95                 
96                 self["label_video_statistics_view_count"] = Label(_("Views") + ":")
97                 self["video_statistics_view_count"] = Label(entry.getViewCount())
98
99                 self["label_video_author"] = Label(_("Author:") + ":")
100                 self["video_author"] = Label(entry.getAuthor())
101
102                 self["label_video_published_on"] = Label(_("Added") + ":")
103                 self["video_published_on"] = Label(entry.getPublishedOn().split("T")[0])
104
105                 self["label_video_category"] = Label(_("Category") + ":")
106                 self["video_category"] = Label(entry.getCategory())
107                 self["label_video_tags"] = Label(_("Tags") + ":")
108                 self["video_tags"] = Label(entry.getTags())
109                 
110                 self["video_thumbnail_1"] = Pixmap()
111                 self["video_thumbnail_2"] = Pixmap()
112                 self["video_thumbnail_3"] = Pixmap()
113
114                 self["actions"] = ActionMap(["YouTubeVideoDetailsScreenActions"],
115                 {
116                         "ok"            :       self.close,
117                         "cancel"        :       self.close,
118                         "up"            :       self.pageUp,
119                         "down"          :       self.pageDown,
120                         "left"          :       self.pageUp,
121                         "right"         :       self.pageDown
122                 })
123
124                 self.onFirstExecBegin.append(self.setPixmap)
125                 self.onFirstExecBegin.append(self.setInitialize)
126
127
128         def pageUp(self):
129                 self["video_description"].pageUp()
130
131
132         def pageDown(self):
133                 self["video_description"].pageDown()
134
135
136         def setInitialize(self):
137                 Screen.setTitle(self, self.entry.getTitle())
138                 if self.entry.getRatingAverage() != "not available":
139                         ratingStars = int(round(20 * float(self.entry.getRatingAverage()), 0))
140                         print "[YTB] Rating: ", ratingStars, "    ", self["stars"].getRange()
141                         self["stars"].setValue(ratingStars)
142                 else:
143                         self["stars"].hide()
144                         self["starsbg"].hide()
145
146
147         def setPixmap(self):
148                 self["video_thumbnail_1"].instance.setPixmap(self.entry.thumbnail["0"].__deref__())
149                 self.entry.loadThumbnail(1, self.setThumbnail_2)
150                 self.entry.loadThumbnail(2, self.setThumbnail_3)
151                 self["video_thumbnail_2"].hide()
152                 self["video_thumbnail_3"].hide()
153
154
155         def setThumbnail_2(self, entry):
156                 self["video_thumbnail_2"].instance.setPixmap(self.entry.thumbnail["1"].__deref__())
157                 self["video_thumbnail_2"].show()
158
159
160         def setThumbnail_3(self, entry):
161                 self["video_thumbnail_3"].instance.setPixmap(self.entry.thumbnail["2"].__deref__())
162                 self["video_thumbnail_3"].show()
163
164
165 class PatientMessageBox(MessageBox):
166         def __init__(self, session, text, type = 1, timeout = -1, close_on_any_key = False, default = True):
167                 MessageBox.__init__(self, session, text, type, timeout, close_on_any_key, default)
168                 self.skinName = "MessageBox"
169
170
171         def processDelayed(self, function):
172                 self.delay_timer = eTimer()
173                 self.delay_timer.callback.append(self.processDelay)
174                 self.delay_timer.start(0, 1)
175                 self.function = function
176
177
178         def processDelay(self):
179                 self.function()
180
181
182         def cancel(self):
183                 pass
184
185
186         def ok(self):
187                 pass
188
189
190         def alwaysOK(self):
191                 pass
192
193
194 class YouTubeList(MenuList):
195         def __init__(self, list, enableWrapAround = False):
196                 MenuList.__init__(self, list, enableWrapAround, eListboxPythonMultiContent)
197                 self.l.setFont(0, gFont("Regular", 18))
198                 self.l.setFont(1, gFont("Regular", 14))
199                 self.l.setItemHeight(105)
200
201
202 class YouTubeListScreen(Screen, NumericalTextInput):
203         def __init__(self, session):
204                 Screen.__init__(self, session)
205                 NumericalTextInput.__init__(self)
206
207                 self.session = session
208                 self.serverName = config.plugins.youtubeplayer.serverprofile.value
209                 self.currentServer = vlcServerConfig.getServerByName(self.serverName)
210
211                 self["red"] = Label(_("Select a VLC-Server"))
212                 self["green"] = Label(_("New YouTube search"))
213                 
214                 self.list = []
215                 self["list"] = YouTubeList(self.list)
216
217                 self["label_total_results"] = Label(_("Total results") + ":")
218                 self["total_results"] = Label("")
219
220                 self["label_currently_shown"] = Label(_("Shown") + ":")
221                 self["currently_shown"] = Label("")
222
223                 self.history = []
224                 self.historyIndex = 0
225
226                 self.isFavoritesFeed = False
227
228                 self.patientDialog = None
229                 
230                 self["actions"] = ActionMap(["YouTubeVideoListActions"],
231                 {
232                         "play"                  :       self.tryToPlay,
233                         "select"                :       self.justSelectServer,
234                         "search"                :       self.searchAgain,
235                         "menu"                  :       self.openContextMenu,
236                         "forward"               :       self.forwardInHistory,
237                         "backward"              :       self.backInHistory,
238                         "left"                  :       self.keyLeft,
239                         "right"                 :       self.keyRight,
240                         "up"                    :       self.keyUp,
241                         "down"                  :       self.keyDown,
242                         "info"                  :       self.showVideoInfo,
243                         "cancel"                :       self.close
244                 }, -1)
245
246
247         def keyLeft(self):
248                 self["list"].pageUp()
249
250
251         def keyRight(self):
252                 if self["list"].getSelectionIndex() == len(self.list) - 1 and self.feed.getNextFeed() is not None:
253                         dlg = self.session.openWithCallback(self.loadNextFeed, MessageBox, _("Load further entries of current Feed?"))
254                 else:
255                         self["list"].pageDown()
256
257
258         def keyUp(self):
259                 self["list"].up()
260
261
262         def keyDown(self):
263                 if self["list"].getSelectionIndex() == len(self.list) - 1 and self.feed.getNextFeed() is not None:
264                         dlg = self.session.openWithCallback(self.loadNextFeed, MessageBox, _("Load further entries of current Feed?"))
265                 else:
266                         self["list"].down()
267
268
269         def insertEntry(self, entry):
270                 print "[YTB] YouTubeTest::updateFinished()"
271                 self.list.append(YouTubeEntryComponent(entry))
272                 self.list.sort(cmp = lambda x, y : cmp(x[0].sequenceNumber, y[0].sequenceNumber))
273                 currentlyShown = "%d" % len(self.list)
274                 self["currently_shown"].setText(currentlyShown)
275                 self["list"].setList(self.list)
276
277
278         def closePatientDialogDelayed(self):
279                 if self.patientDialog:
280                         self.patientDialog.close()
281                         self.patientDialog = None
282                 self["list"].setList(self.list)
283
284
285         def showFeed(self, feed, append):
286                 if feed is not None:
287                         self.feed = feed
288                         self.setTitle(feed.getTitle())
289                         self["total_results"].setText(feed.getTotalResults())
290                         if not append:
291                                 self.list = []
292                                 self["list"].setList(self.list)
293                         self.feed.loadThumbnails(self.insertEntry)
294                 self.delay_timer = eTimer()
295                 self.delay_timer.callback.append(self.closePatientDialogDelayed)
296                 self.delay_timer.start(100, 1)
297
298
299         def addToHistory(self, feed):
300                 if feed is not None:
301                         del self.history[self.historyIndex : len(self.history)]
302                         self.history.insert(self.historyIndex, feed.getSelfFeed())
303                         self.historyIndex = self.historyIndex + 1
304
305                 
306         def searchFeedReal(self, searchContext):
307                 print "[YTB] searchFeedReal"
308                 try:
309                         feed = interface.search(searchContext.searchTerm.value)
310                 except Exception, e:
311                         feed = None
312                         self.session.open(MessageBox, _("Error querying feed for search term %s:\n%s" %
313                                         (searchContext.searchTerm.value, e)), MessageBox.TYPE_ERROR)
314                 self.showFeed(feed, False)
315                 self.addToHistory(feed)
316
317
318         def searchFeed(self, searchContext):
319                 self.patientDialog = self.session.open(PatientMessageBox, _("Searching, be patient ..."))
320                 self.patientDialog.processDelayed(boundFunction(self.searchFeedReal, searchContext = searchContext))
321                 self.isFavoritesFeed = False
322
323
324         def loadPlaylistFeedReal(self, playlist):
325                 try:
326                         feed = interface.getUserPlaylistFeed(playlist)
327                 except Exception, e:
328                         feed = None
329                         self.session.open(MessageBox, _("Error querying playlist-feed for playlist %s:\n%s" %
330                                         (playlist.getTitle(), e)), MessageBox.TYPE_ERROR)
331                 self.showFeed(feed, False)
332                 self.addToHistory(feed)
333
334
335         def loadPlaylistFeed(self, playlist):
336                 self.patientDialog = self.session.open(PatientMessageBox, _("Loading playlist, be patient ..."))
337                 self.patientDialog.processDelayed(boundFunction(self.loadPlaylistFeedReal, playlist = playlist))
338
339
340         def loadFavoritesFeedReal(self, userName = "default"):
341                 try:
342                         feed = interface.getUserFavoritesFeed(userName)
343                 except Exception, e:
344                         feed = None
345                         self.session.open(MessageBox, _("Error querying favorites feed:\n%s" %
346                                         e), MessageBox.TYPE_ERROR)
347                 self.showFeed(feed, False)
348                 self.addToHistory(feed)
349
350
351         def loadFavoritesFeed(self, userName = "default"):
352                 self.patientDialog = self.session.open(PatientMessageBox, _("Loading favorits, be patient ..."))
353                 self.patientDialog.processDelayed(boundFunction(self.loadFavoritesFeedReal, userName = userName))
354                 self.isFavoritesFeed = True
355
356
357         def loadStandardFeed(self, url):
358                 self.loadFeed(_("Loading standard feed, be patient ..."), url, "standard feed")
359
360
361         def loadFeedReal(self, feedUrl, feedName, append = False, addToHistory = True):
362                 try:
363                         feed = interface.getFeed(feedUrl)
364                 except Exception, e:
365                         feed = None
366                         self.session.open(MessageBox, _("Error querying feed %s:\n%s" %
367                                         (feedName, e)), MessageBox.TYPE_ERROR)
368                 self.showFeed(feed, append)
369                 if addToHistory:
370                         self.addToHistory(feed)
371
372
373         def loadFeed(self, text, feedUrl, feedName, append = False, addToHistory = True):
374                 self.patientDialog = self.session.open(PatientMessageBox, text)
375                 self.patientDialog.processDelayed(boundFunction(self.loadFeedReal, feedName = feedName,
376                                                                                         feedUrl = feedUrl, append = append, addToHistory = addToHistory))
377
378
379         def loadPreviousFeed(self, result):
380                 if not result:
381                         return
382                 prevUrl = self.feed.getPreviousFeed()
383                 if prevUrl is not None:
384                         self.loadFeed(_("Loading additional videos, be patient ..."), prevUrl, _("additional videos"),
385                         True, True)
386
387
388         def loadNextFeed(self, result):
389                 if not result:
390                         return
391                 nextUrl = self.feed.getNextFeed()
392                 if nextUrl is not None:
393                         self.loadFeed(_("Loading additional videos, be patient ..."), nextUrl, _("additional videos"),
394                         True, True)
395
396
397         def getRelated(self):
398                 self.loadFeed(_("Loading related videos, be patient ..."), self["list"].getCurrent()[0].getRelatedFeed(), _("related videos"), False, True)
399                 self.isFavoritesFeed = False
400
401
402         def getResponses(self):
403                 self.loadFeed(_("Loading response videos, be patient ..."), self["list"].getCurrent()[0].getResponsesFeed(), _("response videos"), False, True)
404                 self.isFavoritesFeed = False
405
406
407         def backInHistory(self):
408                 if self.historyIndex > 1:
409                         self.historyIndex = self.historyIndex - 1
410                         self.loadFeed(_("Back in history, be patient ..."), self.history[self.historyIndex - 1], _("back in history"), False, False)
411
412
413         def forwardInHistory(self):
414                 if self.historyIndex < len(self.history):
415                         self.historyIndex = self.historyIndex + 1
416                         self.loadFeed(_("Forward in history, be patient ..."), self.history[self.historyIndex - 1], _("forward in history"), False, False)
417
418
419         def showVideoInfo(self):
420                 self.session.open(YouTubeVideoDetailsScreen, self["list"].getCurrent()[0])
421
422
423         def justSelectServer(self):
424                 defaultServer = vlcServerConfig.getServerByName(config.plugins.youtubeplayer.serverprofile.value)
425                 self.selectServer(self.serverSelectedCB, defaultServer)
426
427
428         def selectServer(self, callback, currentServer):
429                 self.session.openWithCallback(callback, VlcServerListScreen, currentServer)
430
431
432         def serverSelectedCB(self, selectedServer, defaultServer):
433                 if selectedServer is not None:
434                         self.currentServer = selectedServer
435                 elif defaultServer is not None:
436                                 self.currentServer = defaultServer
437                 if defaultServer is not None:
438                         config.plugins.youtubeplayer.serverprofile.value = defaultServer.getName()
439                         config.plugins.youtubeplayer.serverprofile.save()
440
441
442         def selectAndPlayCB(self, selectedServer, defaultServer):
443                 self.serverSelectedCB(selectedServer, defaultServer)
444                 self.tryToPlay()
445
446
447         def tryToPlay(self):
448                 if self.currentServer is not None:
449                         self.play()
450                 else:
451                         self.selectServer(self.selectAndPlayCB, None)
452
453
454         def login(self, callback):
455                 self.session.openWithCallback(callback, YouTubeUserListScreen, youTubeUserConfig.getDefaultUser())
456
457
458         def addToFavoritesReal(self):
459                 try:
460                         interface.addToFavorites(self["list"].getCurrent()[0])
461                 except Exception, e:
462                         self.session.open(MessageBox, _("Error adding video to favorites:\n%s" %
463                                         e), MessageBox.TYPE_ERROR)
464
465
466         def addToFavoritesLogin(self, loginState):
467                 if loginState == YouTubeUserListScreen.LOGIN_SUCCESS:
468                         self.addToFavoritesReal()
469                 elif loginState == YouTubeUserListScreen.LOGIN_FAILED:
470                         self.session.open(MessageBox, _("Login not successful"), MessageBox.TYPE_INFO)
471                 else:
472                         pass
473
474
475         def addToFavorites(self):
476                 if not interface.isLoggedIn():
477                         self.login(self.addToFavoritesLogin)
478                 else:
479                         self.addToFavoritesReal()
480
481
482         def removeFromFavoritesReal(self):
483                 try:
484                         if interface.removeFromFavorites(self["list"].getCurrent()[0]):
485                                 self.list.remove(self["list"].getCurrent())
486                                 self["list"].setList(self.list)
487                 except Exception, e:
488                         self.session.open(MessageBox, _("Error removing video from favorites:\n%s" %
489                                         e), MessageBox.TYPE_ERROR)
490
491
492         def removeFromFavoritesLogin(self, loginState):
493                 if loginState == YouTubeUserListScreen.LOGIN_SUCCESS:
494                         self.removeFromFavoritesReal()
495                 elif loginState == YouTubeUserListScreen.LOGIN_FAILED:
496                         self.session.open(MessageBox, _("Login not successful"), MessageBox.TYPE_INFO)
497                 else:
498                         pass
499
500
501         def removeFromFavorites(self):
502                 if not interface.isLoggedIn():
503                         self.login(self.removeFromFavoritesLogin)
504                 else:
505                         self.removeFromFavoritesReal()
506
507
508         def removeFromPlaylistReal(self):
509                 try:
510                         if interface.removeFromPlaylist(self["list"].getCurrent()[0]):
511                                 self.list.remove(self["list"].getCurrent())
512                                 self["list"].setList(self.list)
513                 except Exception, e:
514                         self.session.open(MessageBox, _("Error removing video from playlist:\n%s" %
515                                         e), MessageBox.TYPE_ERROR)
516
517
518         def removeFromPlaylistLogin(self, loginState):
519                 if loginState == YouTubeUserListScreen.LOGIN_SUCCESS:
520                         self.removeFromPlaylistReal()
521                 elif loginState == YouTubeUserListScreen.LOGIN_FAILED:
522                         self.session.open(MessageBox, _("Login not successful"), MessageBox.TYPE_INFO)
523                 else:
524                         pass
525
526
527         def removeFromPlaylist(self):
528                 if not interface.isLoggedIn():
529                         self.login(self.removeFromPlaylistLogin)
530                 else:
531                         self.removeFromPlaylistReal()
532
533
534         def playlistChoosen(self, playlist):
535                 if playlist is not None:
536                         try:
537                                 interface.addToPlaylist(playlist, self["list"].getCurrent()[0])
538                         except Exception, e:
539                                 self.session.open(MessageBox, _("Error adding video to playlist:\n%s" %
540                                         e), MessageBox.TYPE_ERROR)
541
542
543         def addToPlaylistReal(self):
544                 dlg = self.session.openWithCallback(self.playlistChoosen, YouTubePlaylistScreen)
545                 dlg.loadPlaylist()
546
547
548         def addToPlaylistLogin(self, loginState):
549                 if loginState == YouTubeUserListScreen.LOGIN_SUCCESS:
550                         self.addToPlaylistReal()
551                 elif loginState == YouTubeUserListScreen.LOGIN_FAILED:
552                         self.session.open(MessageBox, _("Login not successful"), MessageBox.TYPE_INFO)
553                 else:
554                         pass
555
556
557         def addToPlaylist(self):
558                 if not interface.isLoggedIn():
559                         self.login(self.addToPlaylistLogin)
560                 else:
561                         self.addToPlaylistReal()
562
563
564 # http://cacan.blog385.com/index.php/2008/05/09/youtube-high-quality-hacks/
565 # add the &fmt=6 onto the end:
566 #
567 # http://youtube.com/watch?v=CQzUsTFqtW0&fmt=6
568 #
569 # If the YouTube video just sits there loading then that
570 # is a sign that the video has not been converted to the
571 # higher resolution yet. To really see the difference you
572 # should view the video in full screen mode by clicking
573 # the button in the bottom-right corner of the player.
574 #
575 # Note: Alternatively you can add &fmt=18 and it will play
576 # the high-resolution version when available, otherwise it
577 # will play the regular version. Here?s a Greasemonkey
578 # script that will automatically add &fmt=18 onto the end
579 # of each YouTube URL.
580         def play(self):
581                 print "[YTB] Play()"
582                 youTubeEntry = self["list"].getCurrent()[0]
583                 mrl = youTubeEntry.getVideoUrl("&fmt=18")
584 ############## To be resolved
585 #Traceback (most recent call last):
586 #  File "/usr/lib/enigma2/python/Components/ActionMap.py", line 46, in action
587 #    res = self.actions[action]()
588 #  File "/usr/lib/enigma2/python/Plugins/Extensions/YouTubePlayer/YouTubeList.py", line 425, in tryToPlay
589 #    self.play()
590 #  File "/usr/lib/enigma2/python/Plugins/Extensions/YouTubePlayer/YouTubeList.py", line 543, in play
591 #    mrl = youTubeEntry.getVideoUrl("&fmt=18")
592 #  File "/usr/lib/enigma2/python/Plugins/Extensions/YouTubePlayer/YouTubeInterface.py", line 216, in getVideoUrl
593 #    conn.request("GET", "/v/" + quote(self.getYouTubeId()))
594 #  File "/usr/lib/python2.5/httplib.py", line 862, in request
595 #    self._send_request(method, url, body, headers)
596 #  File "/usr/lib/python2.5/httplib.py", line 885, in _send_request
597 #    self.endheaders()
598 #  File "/usr/lib/python2.5/httplib.py", line 856, in endheaders
599 #    self._send_output()
600 #  File "/usr/lib/python2.5/httplib.py", line 728, in _send_output
601 #    self.send(msg)
602 #  File "/usr/lib/python2.5/httplib.py", line 695, in send
603 #    self.connect()
604 #  File "/usr/lib/python2.5/httplib.py", line 663, in connect
605 #    socket.SOCK_STREAM):
606 #socket.gaierror: (2, 'temporary failure in name resolution.')
607
608                 if mrl is not None:
609                         entries = []
610                         entries.append((_("Show video detail info"), [self.showVideoInfo, False]))
611                         if self["list"].getCurrent()[0].belongsToFavorites():
612                                 entries.append((_("Remove from favorites"), [self.removeFromFavorites, False]))
613                         else:
614                                 entries.append((_("Add to favorites"), [self.addToFavorites, False]))
615                                 
616                         if self["list"].getCurrent()[0].isPlaylistEntry():
617                                 entries.append((_("Remove from playlist"), [self.removeFromPlaylist, False]))
618                         else:
619                                 entries.append((_("Add to playlist"), [self.addToPlaylist, False]))
620                         entries.append((_("Get related videos"), [self.getRelated, True]))
621                         entries.append((_("Get video responses"), [self.getResponses, True]))
622                         
623                         self.currentServer.play(self.session, mrl, youTubeEntry.getTitle(), self,
624                                                                 player = boundFunction(YouTubePlayer, contextMenuEntries = entries, infoCallback = self.showVideoInfo, name = self["list"].getCurrent()[0].getTitle()))
625                 else:
626                         print "[YTB] No valid flv-mrl found"
627
628
629         def getNextFile(self):
630                 i = self["list"].getSelectedIndex() + 1
631                 if i < len(self.list):
632                         self["list"].moveToIndex(i)
633                         youTubeEntry = self["list"].getCurrent()[0]
634                         return youTubeEntry.getVideoUrl("&fmt=18"), youTubeEntry.getTitle()
635                 return None, None
636
637
638         def getPrevFile(self):
639                 i = self["list"].getSelectedIndex() - 1
640                 if i >= 0:
641                         self["list"].moveToIndex(i)
642                         youTubeEntry = self["list"].getCurrent()[0]
643                         return youTubeEntry.getVideoUrl("&fmt=18"), youTubeEntry.getTitle()
644                 return None, None
645
646
647         def openContextMenu(self):
648                 contextMenuList = YouTubeEntryContextMenuList()
649                 contextMenuList.appendEntry((_("Show video detail info"), self.showVideoInfo))
650                 if self["list"].getCurrent()[0].belongsToFavorites():
651                         contextMenuList.appendEntry((_("Remove from favorites"), self.removeFromFavorites))
652                 else:
653                         contextMenuList.appendEntry((_("Add to favorites"), self.addToFavorites))
654                 if self["list"].getCurrent()[0].isPlaylistEntry():
655                         contextMenuList.appendEntry((_("Remove from playlist"), self.removeFromPlaylist))
656                 else:
657                         contextMenuList.appendEntry((_("Add to playlist"), self.addToPlaylist))
658                 contextMenuList.appendEntry((_("Get related videos"), self.getRelated))
659                 contextMenuList.appendEntry((_("Get video responses"), self.getResponses))
660                 self.session.openWithCallback(self.menuActionCoosen, YouTubeEntryContextMenu, contextMenuList, self["list"].getCurrent()[0].getTitle())
661
662
663         def menuActionCoosen(self, function):
664                 if function is not None:
665                         function()
666
667
668         def searchAgain(self):
669                 Screen.close(self, True)
670
671
672         def close(self):
673                 Screen.close(self, False)