YouTube-Player plugin added
authorVolker Christian <voc@users.schwerkraft.elitedvb.net>
Thu, 25 Sep 2008 15:31:46 +0000 (15:31 +0000)
committerVolker Christian <voc@users.schwerkraft.elitedvb.net>
Thu, 25 Sep 2008 15:31:46 +0000 (15:31 +0000)
32 files changed:
Makefile.am
configure.ac
youtubeplayer/CONTROL/control [new file with mode: 0644]
youtubeplayer/Makefile.am [new file with mode: 0644]
youtubeplayer/src/ConfigTextWithSuggestions.py [new file with mode: 0644]
youtubeplayer/src/GoogleSuggestions.py [new file with mode: 0644]
youtubeplayer/src/Makefile.am [new file with mode: 0644]
youtubeplayer/src/Nemesis.GlassLine_Mod/Makefile.am [new file with mode: 0644]
youtubeplayer/src/Nemesis.GlassLine_Mod/skin.xml [new file with mode: 0644]
youtubeplayer/src/SkinLoader.py [new file with mode: 0644]
youtubeplayer/src/YouTubeAddPlayList.py [new file with mode: 0644]
youtubeplayer/src/YouTubeContextMenu.py [new file with mode: 0644]
youtubeplayer/src/YouTubeInterface.py [new file with mode: 0644]
youtubeplayer/src/YouTubeList.py [new file with mode: 0644]
youtubeplayer/src/YouTubePlayList.py [new file with mode: 0644]
youtubeplayer/src/YouTubePlayer.py [new file with mode: 0644]
youtubeplayer/src/YouTubeSearchDialog.py [new file with mode: 0644]
youtubeplayer/src/YouTubeStdFeedSelection.py [new file with mode: 0644]
youtubeplayer/src/YouTubeUserConfig.py [new file with mode: 0644]
youtubeplayer/src/YouTubeUserList.py [new file with mode: 0644]
youtubeplayer/src/__init__.py [new file with mode: 0644]
youtubeplayer/src/keymap.xml [new file with mode: 0644]
youtubeplayer/src/locale/de/LC_MESSAGES/YouTubePlayer.mo [new file with mode: 0644]
youtubeplayer/src/locale/de/YouTubePlayer.po [new file with mode: 0644]
youtubeplayer/src/locale/messages.pot [new file with mode: 0755]
youtubeplayer/src/plugin.png [new file with mode: 0644]
youtubeplayer/src/plugin.py [new file with mode: 0644]
youtubeplayer/src/skin.xml [new file with mode: 0644]
youtubeplayer/src/starsbar_empty.png [new file with mode: 0644]
youtubeplayer/src/starsbar_filled.png [new file with mode: 0644]
youtubeplayer/src/user.png [new file with mode: 0644]
youtubeplayer/src/user_default.png [new file with mode: 0644]

index 55ec5bc..691d221 100644 (file)
@@ -1,3 +1,3 @@
 AUTOMAKE_OPTIONS = gnu
-SUBDIRS = antiscrollbar movietagger webinterface wirelesslan netcaster lastfm logomanager vlcplayer simplerss trafficinfo fritzcall webcamviewer emailclient autotimer epgrefresh werbezapper httpproxy startuptostandby imdb ofdb networkwizard movieretitle moviecut tageditor cdinfo unwetterzentrale
+SUBDIRS = antiscrollbar movietagger webinterface wirelesslan netcaster lastfm logomanager vlcplayer simplerss trafficinfo fritzcall webcamviewer emailclient autotimer epgrefresh werbezapper httpproxy startuptostandby imdb ofdb networkwizard movieretitle moviecut tageditor cdinfo unwetterzentrale youtubeplayer
 
index c0f7fef..6fea58c 100644 (file)
@@ -135,4 +135,8 @@ cdinfo/src/Makefile
 unwetterzentrale/Makefile
 unwetterzentrale/src/Makefile
 
+youtubeplayer/Makefile
+youtubeplayer/src/Makefile
+youtubeplayer/src/Nemesis.GlassLine_Mod/Makefile
+
 ])
diff --git a/youtubeplayer/CONTROL/control b/youtubeplayer/CONTROL/control
new file mode 100644 (file)
index 0000000..5dcfddd
--- /dev/null
@@ -0,0 +1,10 @@
+Package: enigma2-plugin-extensions-youtubeplayer
+Version: 0.2
+Description: Enigma2 Plugin to search and play YouTube Movies
+Section: base
+Priority: optional
+Maintainer: Volker Christian <volker.christian@fh-hagenberg.at>
+Architecture: mipsel
+Homepage: http://www.i-have-a-dreambox.com/wbb2/board.php?boardid=240
+Depends: enigma2, enigma2-plugin-extensions-vlcplayer, twisted-web python-gdata
+Source: Just localy at my harddrive
diff --git a/youtubeplayer/Makefile.am b/youtubeplayer/Makefile.am
new file mode 100644 (file)
index 0000000..af437a6
--- /dev/null
@@ -0,0 +1 @@
+SUBDIRS = src
diff --git a/youtubeplayer/src/ConfigTextWithSuggestions.py b/youtubeplayer/src/ConfigTextWithSuggestions.py
new file mode 100644 (file)
index 0000000..abc5537
--- /dev/null
@@ -0,0 +1,242 @@
+############################################################################
+#    Copyright (C) 2008 by Volker Christian                                #
+#    Volker.Christian@fh-hagenberg.at                                      #
+#                                                                          #
+#    This program is free software; you can redistribute it and#or modify  #
+#    it under the terms of the GNU General Public License as published by  #
+#    the Free Software Foundation; either version 2 of the License, or     #
+#    (at your option) any later version.                                   #
+#                                                                          #
+#    This program is distributed in the hope that it will be useful,       #
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of        #
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         #
+#    GNU General Public License for more details.                          #
+#                                                                          #
+#    You should have received a copy of the GNU General Public License     #
+#    along with this program; if not, write to the                         #
+#    Free Software Foundation, Inc.,                                       #
+#    59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             #
+############################################################################
+
+from GoogleSuggestions import GoogleSuggestions
+
+from Screens.Screen import Screen
+from Components.config import ConfigText
+from Components.config import KEY_DELETE, KEY_BACKSPACE, KEY_LEFT, KEY_RIGHT
+from Components.config import KEY_HOME, KEY_END, KEY_TOGGLEOW, KEY_ASCII, KEY_TIMEOUT
+from Components.MenuList import MenuList
+from enigma import eListboxPythonMultiContent, RT_HALIGN_LEFT, gFont
+
+from threading import Thread
+from threading import Condition
+
+
+def SuggestionListEntry(suggestion):
+       res = [ suggestion ]
+       res.append((eListboxPythonMultiContent.TYPE_TEXT, 5, 1, 370, 20, 0, RT_HALIGN_LEFT, suggestion[0]))
+       return res
+
+
+class SuggestionsList(MenuList):
+       def __init__(self):
+               MenuList.__init__(self, list, False, eListboxPythonMultiContent)
+               self.l.setFont(0, gFont("Regular", 18))
+               self.l.setItemHeight(23)
+
+
+       def update(self, suggestions):
+               self.list = []
+               if suggestions:
+                       suggests = suggestions[1]
+                       for suggestion in suggests:
+                               self.list.append(SuggestionListEntry(suggestion))
+                       self.l.setList(self.list)
+                       self.moveToIndex(0)
+
+
+       def getSelection(self):
+               if self.getCurrent() is None:
+                       return None
+               return self.l.getCurrentSelection()[0][0]
+
+
+class SuggestionsListScreen(Screen):
+       skin = """
+       <screen name="SuggestionsListScreen" position="170,120" zPosition="2" size="394,185" backgroundColor="#202020" flags="wfNoBorder">
+               <eLabel position="0,0" size="394,185" backgroundColor="#c0c0c0" zPosition="-1" />
+               <widget name="suggestionslist" position="2,2" size="390,181"  scrollbarMode="showOnDemand"/>
+       </screen>"""
+
+
+       def __init__(self, session, configTextWithSuggestion):
+               Screen.__init__(self, session)
+               self.suggestionlist = SuggestionsList()
+               self["suggestionslist"] = self.suggestionlist
+               self.configTextWithSuggestion = configTextWithSuggestion
+
+
+       def update(self, suggestions):
+               if suggestions:
+                       if not self.shown:
+                               self.show()
+                       self.suggestionlist.update(suggestions)
+               else:
+                       self.hide()
+
+
+       def up(self):
+               self.suggestionlist.up()
+               return self.suggestionlist.getSelection()
+
+
+       def down(self):
+               self.suggestionlist.down()
+               return self.suggestionlist.getSelection()
+
+       
+       def pageUp(self):
+               self.suggestionlist.pageUp()
+               return self.suggestionlist.getSelection()
+
+
+       def pageDown(self):
+               self.suggestionlist.pageDown()
+               return self.suggestionlist.getSelection()
+
+
+       def activate(self):
+               self.suggestionlist.selectionEnabled(1)
+               return self.suggestionlist.getSelection()
+
+
+       def deactivate(self):
+               self.suggestionlist.selectionEnabled(0)
+               return self.suggestionlist.getSelection()
+
+
+class ConfigTextWithSuggestions(ConfigText):
+       class SuggestionsThread(Thread):
+               def __init__(self, suggestionsService):
+                       Thread.__init__(self)
+                       self.suggestionsService = suggestionsService
+                       self.value = None
+                       self.running = True
+                       self.condition = Condition()
+
+               def run(self):
+                       while self.running:
+                               self.condition.acquire()
+                               if self.value is None:
+                                       self.condition.wait()
+                               value = self.value
+                               self.value = None
+                               self.condition.release()
+                               if value is not None:
+                                       self.suggestionsService.getSuggestions(value)
+
+               def stop(self):
+                       self.running = False
+                       self.condition.acquire()
+                       self.condition.notify()
+                       self.condition.release()
+                       self.join()
+
+               def getSuggestions(self, value):
+                       self.condition.acquire()
+                       self.value = value
+                       self.condition.notify()
+                       self.condition.release()
+
+       def __init__(self, default = "", fixed_size = True, visible_width = False, threaded = False):
+               ConfigText.__init__(self, default, fixed_size, visible_width)
+               self.suggestions = GoogleSuggestions(self.propagateSuggestions, ds = "yt", hl = "en")
+               self.timeoutlistener = []
+               self.suggestionsThread = None
+               self.threaded = threaded
+               self.suggestionsListActivated = False
+
+
+       def propagateSuggestions(self, suggestionsList):
+               if self.suggestionsWindow:
+                       self.suggestionsWindow.update(suggestionsList)
+
+
+       def getSuggestions(self):
+               if self.suggestionsThread is not None:
+                       self.suggestionsThread.getSuggestions(self.value)
+               else:
+                       self.suggestions.getSuggestions(self.value)
+
+
+       def handleKey(self, key):
+               if not self.suggestionsListActivated:
+                       ConfigText.handleKey(self, key)
+                       if key in [KEY_DELETE, KEY_BACKSPACE, KEY_ASCII, KEY_TIMEOUT]:
+                               self.getSuggestions()
+
+
+       def onSelect(self, session):
+               if self.threaded:
+                       self.suggestionsThread = ConfigTextWithSuggestions.SuggestionsThread(self.suggestions)
+                       self.suggestionsThread.start()
+               else:
+                       self.suggestionsThread = None
+               ConfigText.onSelect(self, session)
+               if session is not None:
+                       self.suggestionsWindow = session.instantiateDialog(SuggestionsListScreen, self)
+                       self.suggestionsWindow.deactivate()
+                       self.suggestionsWindow.hide()
+               self.suggestions.getSuggestions(self.value)
+
+
+       def onDeselect(self, session):
+               if self.suggestionsThread is not None:
+                       self.suggestionsThread.stop()
+               ConfigText.onDeselect(self, session)
+               if self.suggestionsWindow:
+                       session.deleteDialog(self.suggestionsWindow)
+                       self.suggestionsWindow = None
+
+
+       def suggestionListUp(self):
+               self.value = self.suggestionsWindow.up()
+
+
+       def suggestionListDown(self):
+               self.value = self.suggestionsWindow.down()
+
+
+       def suggestionListPageDown(self):
+               self.value = self.suggestionsWindow.pageDown()
+
+
+       def suggestionListPageUp(self):
+               self.value = self.suggestionsWindow.pageUp()
+
+
+       def activateSuggestionList(self):
+               ret = False
+               if self.suggestionsWindow is not None and self.suggestionsWindow.shown:
+                       self.tmpValue = self.value
+                       self.value = self.suggestionsWindow.activate()
+                       self.allmarked = False
+                       self.marked_pos = -1
+                       self.suggestionsListActivated = True
+                       ret = True
+               return ret
+
+
+       def deactivateSuggestionList(self):
+               ret = False
+               if self.suggestionsWindow is not None:
+                       self.suggestionsWindow.deactivate()
+                       self.getSuggestions()
+                       self.allmarked = True
+                       self.suggestionsListActivated = False
+                       ret = True
+               return ret
+
+
+       def cancelSuggestionList(self):
+               self.value = self.tmpValue
+               return self.deactivateSuggestionList()
diff --git a/youtubeplayer/src/GoogleSuggestions.py b/youtubeplayer/src/GoogleSuggestions.py
new file mode 100644 (file)
index 0000000..075da35
--- /dev/null
@@ -0,0 +1,105 @@
+############################################################################
+#    Copyright (C) 2008 by Volker Christian                                #
+#    Volker.Christian@fh-hagenberg.at                                      #
+#                                                                          #
+#    This program is free software; you can redistribute it and#or modify  #
+#    it under the terms of the GNU General Public License as published by  #
+#    the Free Software Foundation; either version 2 of the License, or     #
+#    (at your option) any later version.                                   #
+#                                                                          #
+#    This program is distributed in the hope that it will be useful,       #
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of        #
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         #
+#    GNU General Public License for more details.                          #
+#                                                                          #
+#    You should have received a copy of the GNU General Public License     #
+#    along with this program; if not, write to the                         #
+#    Free Software Foundation, Inc.,                                       #
+#    59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             #
+############################################################################
+
+import urllib
+import httplib
+import socket
+
+
+class GoogleSuggestions():
+       def __init__(self, callback, ds = None, json = None, hl = None):
+               self.callback = callback
+               self.conn = httplib.HTTPConnection("google.com")
+               self.prepQuerry = "/complete/search?"
+               if ds is not None:
+                       self.prepQuerry = self.prepQuerry + "ds=" + ds + "&"
+               if json is not None:
+                       self.prepQuerry = self.prepQuerry + "json=" + json + "&"
+               if hl is not None:
+                       self.prepQuerry = self.prepQuerry + "hl=" + hl + "&"
+               self.prepQuerry = self.prepQuerry + "jsonp=self.gotSuggestions&q="
+
+
+       def gotSuggestions(self, suggestslist):
+               self.callback(suggestslist)
+
+
+       def getSuggestions(self, querryString):
+               if querryString is not "":
+                       querry = self.prepQuerry + urllib.quote(querryString)
+                       try:
+                               self.conn.request("GET", querry)
+                       except (httplib.CannotSendRequest, socket.gaierror, socket.error):
+                               print "[YTB] Can not send request for suggestions"
+                               self.callback(None)
+                       else:
+                               try:
+                                       response = self.conn.getresponse()
+                               except httplib.BadStatusLine:
+                                       print "[YTB] Can not get a response from google"
+                                       self.callback(None)
+                               else:
+                                       if response.status == 200:
+                                               data = response.read()
+                                               exec data
+                                       else:
+                                               self.callback(None)
+                       self.conn.close()
+               else:
+                       self.callback(None)
+
+
+
+#class GoogleSuggestions():
+#      def __init__(self, callback, ds = None, json = None, hl = None):
+#              self.callback = callback
+#              self.prepQuerry = "http://www.google.com/complete/search?"
+#              if ds is not None:
+#                      self.prepQuerry = self.prepQuerry + "ds=" + ds + "&"
+#              if json is not None:
+#                      self.prepQuerry = self.prepQuerry + "json=" + json + "&"
+#              if hl is not None:
+#                      self.prepQuerry = self.prepQuerry + "hl=" + hl + "&"
+#              self.prepQuerry = self.prepQuerry + "jsonp=self.gotSuggestions&q="
+#
+#
+#      def gotSuggestions(self, suggestslist):
+#              self.callback(suggestslist)
+#
+#              
+#      def getSuggestions(self, querryString):
+#              if querryString is not "":
+#                      querry = self.prepQuerry + urllib.quote(querryString)
+#                      try:
+#                              filehandler = urllib.urlopen(url = querry)
+#                      except IOError e:
+#                              print "[YTB] Error during urlopen: ", e
+#                              self.callback(None)
+#                      else:
+#                              try:
+#                                      content = filehandler.read()
+#                                      filehandler.close()
+#                              except IOError e:
+#                                      print "[YTB] Error during read: ", e
+#                                      self.callback(None)
+#                              else:
+#                                      exec content
+#              else:
+#                      self.callback(None)
diff --git a/youtubeplayer/src/Makefile.am b/youtubeplayer/src/Makefile.am
new file mode 100644 (file)
index 0000000..9e25047
--- /dev/null
@@ -0,0 +1,7 @@
+SUBDIRS = Nemesis.GlassLine_Mod
+
+installdir = /usr/lib/enigma2/python/Plugins/Extensions/YouTubePlayer
+
+install_PYTHON = *.py
+
+install_DATA = plugin.png starsbar_empty.png starsbar_filled.png user_default.png user.png keymap.xml skin.xml
diff --git a/youtubeplayer/src/Nemesis.GlassLine_Mod/Makefile.am b/youtubeplayer/src/Nemesis.GlassLine_Mod/Makefile.am
new file mode 100644 (file)
index 0000000..d057e19
--- /dev/null
@@ -0,0 +1,3 @@
+installdir = /usr/lib/enigma2/python/Plugins/Extensions/YouTubePlayer/Nemesis.GlassLine_Mod
+
+install_DATA = skin.xml
diff --git a/youtubeplayer/src/Nemesis.GlassLine_Mod/skin.xml b/youtubeplayer/src/Nemesis.GlassLine_Mod/skin.xml
new file mode 100644 (file)
index 0000000..9d7a8cd
--- /dev/null
@@ -0,0 +1,66 @@
+<skin>
+<!--
+               <ePixmap name="red" position="10,10" size="21,21" pixmap="Nemesis.GlassLine_Mod/red.png" alphatest="on" />
+               <ePixmap name="green" position="140,10" size="21,21" pixmap="Nemesis.GlassLine_Mod/green.png" alphatest="on" />
+               <ePixmap name="yellow" position="280,10" size="21,21" pixmap="Nemesis.GlassLine_Mod/yellow.png" alphatest="on" />
+               <ePixmap name="blue" position="420,10" size="21,21" pixmap="Nemesis.GlassLine_Mod/blue.png" alphatest="on" />
+               <widget name="key_red" position="40,10" size="115,21" halign="left" valign="center" font="Regular;20" />
+               <widget name="key_green" position="170,10" size="115,21" halign="left" valign="center" font="Regular;20" />
+               <widget name="key_yellow" position="310,10" size="115,21" halign="left" valign="center" font="Regular;20" />
+               <widget name="key_blue" position="450,10" size="115,21" halign="left" valign="center" font="Regular;20" />
+-->
+       <!-- YouTube-Player -->
+       <screen name = "YouTubeVideoDetailsScreen" position = "80,85" size = "560,410" title = "Video Details" transparent = "0">
+               <widget name = "video_thumbnail_1" position = "10,10" size = "130,97" alphatest = "on" />
+               <widget name = "video_thumbnail_2" position = "10,110" size = "130,97" alphatest = "on" />
+               <widget name = "video_thumbnail_3" position = "10,210" size = "130,97" alphatest = "on" />
+               <widget name = "label_video_duration" position = "150,10" size = "95,20" font = "Regular;20" halign = "right" />
+               <widget name = "video_duration" position = "250,10" size = "90,20" valign = "left" font = "Regular;20"/>
+               <widget name = "label_video_rating_average" position = "345,10" size = "95,20" font = "Regular;20" halign = "right" />
+               <widget name = "starsbg" pixmap = "/usr/lib/enigma2/python/Plugins/Extensions/YouTubePlayer/starsbar_empty.png" position = "445,10" zPosition = "0" size = "100,20" transparent = "1" alphatest = "on" />
+               <widget name = "stars" position = "445,10" size = "100,20" pixmap = "/usr/lib/enigma2/python/Plugins/Extensions/YouTubePlayer/starsbar_filled.png" transparent = "1" />
+               <widget name = "label_video_statistics_view_count" position = "150,30" size = "95,20" font = "Regular;20" halign = "right" />
+               <widget name = "video_statistics_view_count" position = "250,30" size = "90,20" valign = "left" font = "Regular;20"/>
+               <widget name = "label_video_numraters" position = "345,30" size = "95,20" font = "Regular;20" halign = "right" />
+               <widget name = "video_numraters" position = "445,30" size = "105,20" valign = "left" font = "Regular;20"/>
+               <widget name = "label_video_statistics_favorite_count" position = "150,50" size = "95,20" font = "Regular;20" halign = "right" />
+               <widget name = "video_statistics_favorite_count" position = "250,50" size = "90,20" valign = "left" font = "Regular;20"/>
+               <widget name = "label_video_published_on" position = "345,50" size = "95,20" font = "Regular;20" halign = "right" />
+               <widget name = "video_published_on" position = "445,50" size = "105,20" valign = "left" font = "Regular;20"/>
+               <widget name = "label_video_author" position = "150,70" size = "95,20" font = "Regular;20" halign = "right" />
+               <widget name = "video_author" position = "250,70" size = "300,20" valign = "left" font = "Regular;20"/>
+               <widget name = "label_video_category" position = "150,90" size = "95,20" font = "Regular;20" halign = "right" />
+               <widget name = "video_category" position = "250,90" size = "300,20" valign = "left" font = "Regular;20"/>
+               <widget name = "label_video_tags" position = "150,110" size = "95,20" font = "Regular;20" halign = "right" />
+               <widget name = "video_tags" position = "250,110" size = "300,60" valign = "left" font = "Regular;20"/>
+               <ePixmap pixmap="Nemesis.GlassLine_Mod/separator.png" position="150,178" zPosition="1" size="400,4" />
+               <widget name = "video_description" position = "150,190" size = "400,210" font = "Regular;20" />
+       </screen>
+
+       <screen name = "YouTubeListScreen" position = "80,85" size = "560,410" title = "YouTube Videos" transparent = "0">
+               <widget name = "label_total_results" position = "0,13" size = "160,20" font = "Regular;20" halign = "right" />
+               <widget name = "total_results" position = "170,13" size = "110,20" font = "Regular;20" />
+               <widget name = "label_currently_shown" position = "280,13" size = "110,20" font = "Regular;20" halign = "right" />
+               <widget name = "currently_shown" position = "400,13" size = "160,20" font = "Regular;20" />
+               <ePixmap pixmap="Nemesis.GlassLine_Mod/separator.png" position="0,43" zPosition="1" size="560,4" />
+               <widget name = "list" position = "5,55" size = "550,315" scrollbarMode = "showOnDemand" />
+               <ePixmap name = "key_red" position = "40,370" zPosition = "1" size = "200,40" pixmap = "skin_default/buttons/red-big.png" transparent = "1" alphatest = "on" />
+               <ePixmap name = "key_green" position = "320,370" zPosition = "1" size = "200,40" pixmap = "skin_default/buttons/green-big.png" transparent = "1" alphatest = "on" />
+               <widget name = "red" position = "40,370" size = "200,40" font = "Regular;19" valign = "center" halign = "center" transparent = "1" zPosition = "2" />
+               <widget name = "green" position = "320,370" size = "200,40" font = "Regular;19" valign = "center" halign = "center" transparent = "1" zPosition = "2" />
+       </screen>
+
+       <screen name = "YouTubeUserListScreen" position = "80,85" size = "560,410" title = "YouTube User-Profiles" >
+               <widget name = "label_info" position = "10,9" size = "540,42" halign = "center" valign = "center" font = "Regular;21" />
+               <ePixmap pixmap="Nemesis.GlassLine_Mod/separator.png" position="0,55" zPosition="1" size="560,4" />
+               <widget name = "userlist" position = "10,62" size = "540,283"  scrollbarMode = "showOnDemand"/>
+               <ePixmap name = "red"    position = "0,370"   zPosition = "4" size = "140,40" pixmap = "skin_default/buttons/red.png" transparent = "1" alphatest = "on" />
+               <ePixmap name = "green"  position = "140,370" zPosition = "4" size = "140,40" pixmap = "skin_default/buttons/green.png" transparent = "1" alphatest = "on" />
+               <ePixmap name = "yellow" position = "280,370" zPosition = "4" size = "140,40" pixmap = "skin_default/buttons/yellow.png" transparent = "1" alphatest = "on" />
+               <ePixmap name = "blue"   position = "420,370" zPosition = "4" size = "140,40" pixmap = "skin_default/buttons/blue.png" transparent = "1" alphatest = "on" />
+               <widget name = "key_red" position = "0,370" zPosition = "5" size = "140,40" valign = "center" halign = "center" font = "Regular;21" transparent = "1" foregroundColor = "white" shadowColor = "black" shadowOffset = "-1,-1" />
+               <widget name = "key_green" position = "140,370" zPosition = "5" size = "140,40" valign = "center" halign = "center" font = "Regular;21" transparent = "1" foregroundColor = "white" shadowColor = "black" shadowOffset = "-1,-1" />
+               <widget name = "key_yellow" position = "280,370" zPosition = "5" size = "140,40" valign = "center" halign = "center"  font = "Regular;21" transparent = "1" foregroundColor = "white" shadowColor = "black" shadowOffset = "-1,-1" />
+               <widget name = "key_blue" position = "420,370" zPosition = "5" size = "140,40" valign = "center" halign = "center" font = "Regular;21" transparent = "1" foregroundColor = "white" shadowColor = "black" shadowOffset = "-1,-1" />
+       </screen>
+</skin>
\ No newline at end of file
diff --git a/youtubeplayer/src/SkinLoader.py b/youtubeplayer/src/SkinLoader.py
new file mode 100644 (file)
index 0000000..3ab03e5
--- /dev/null
@@ -0,0 +1,34 @@
+############################################################################
+#    Copyright (C) 2008 by Volker Christian                                #
+#    Volker.Christian@fh-hagenberg.at                                      #
+#                                                                          #
+#    This program is free software; you can redistribute it and#or modify  #
+#    it under the terms of the GNU General Public License as published by  #
+#    the Free Software Foundation; either version 2 of the License, or     #
+#    (at your option) any later version.                                   #
+#                                                                          #
+#    This program is distributed in the hope that it will be useful,       #
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of        #
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         #
+#    GNU General Public License for more details.                          #
+#                                                                          #
+#    You should have received a copy of the GNU General Public License     #
+#    along with this program; if not, write to the                         #
+#    Free Software Foundation, Inc.,                                       #
+#    59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             #
+############################################################################
+
+from Components.config import config
+from skin import loadSkin
+import os
+
+
+def loadSkinReal(skinPath):
+       if os.path.exists(skinPath):
+               print "[SKLDR] Loading skin ", skinPath
+               loadSkin(skinPath)
+
+
+def loadPluginSkin(pluginPath):
+       loadSkinReal(pluginPath + "/" + config.skin.primary_skin.value)
+       loadSkinReal(pluginPath + "/skin.xml")
diff --git a/youtubeplayer/src/YouTubeAddPlayList.py b/youtubeplayer/src/YouTubeAddPlayList.py
new file mode 100644 (file)
index 0000000..99483c2
--- /dev/null
@@ -0,0 +1,71 @@
+############################################################################
+#    Copyright (C) 2008 by Volker Christian                                #
+#    Volker.Christian@fh-hagenberg.at                                      #
+#                                                                          #
+#    This program is free software; you can redistribute it and#or modify  #
+#    it under the terms of the GNU General Public License as published by  #
+#    the Free Software Foundation; either version 2 of the License, or     #
+#    (at your option) any later version.                                   #
+#                                                                          #
+#    This program is distributed in the hope that it will be useful,       #
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of        #
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         #
+#    GNU General Public License for more details.                          #
+#                                                                          #
+#    You should have received a copy of the GNU General Public License     #
+#    along with this program; if not, write to the                         #
+#    Free Software Foundation, Inc.,                                       #
+#    59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             #
+############################################################################
+
+from Screens.Screen import Screen
+
+from Components.config import Config
+from Components.config import ConfigText
+from Components.config import ConfigYesNo
+from Components.config import getConfigListEntry
+from Components.ConfigList import ConfigListScreen
+from Components.ActionMap import ActionMap
+from Components.Button import Button
+
+from ConfigTextWithSuggestions import ConfigTextWithSuggestions
+
+from . import _
+
+playlistContext = Config()
+playlistContext.name = ConfigText(_("Name"), False)
+playlistContext.description = ConfigText(_("Description"), False)
+playlistContext.private = ConfigYesNo()
+
+
+class YouTubeAddPlaylistDialog(Screen, ConfigListScreen):
+       def __init__(self, session):
+               Screen.__init__(self, session)
+
+               self.session = session
+
+               self["actions"] = ActionMap(["YouTubeAddPlaylistActions"],
+               {
+                       "save"          :       self.keySave,
+                       "cancel"        :       self.keyCancel
+               }, -2)
+
+               self["key_red"] = Button(_("Cancel"))
+               self["key_green"] = Button(_("Save"))
+               self["key_yellow"] = Button("")
+               self["key_blue"] = Button("")
+
+               cfglist = []
+               cfglist.append(getConfigListEntry(_("Playlist Name"), playlistContext.name))
+               cfglist.append(getConfigListEntry(_("Playlist Description"), playlistContext.description))
+               cfglist.append(getConfigListEntry(_("private"), playlistContext.private))
+
+               ConfigListScreen.__init__(self, cfglist, session)
+
+
+       def keySave(self):
+               self.close(True, playlistContext)
+
+
+       def keyCancel(self):
+               self.close(False, playlistContext)
diff --git a/youtubeplayer/src/YouTubeContextMenu.py b/youtubeplayer/src/YouTubeContextMenu.py
new file mode 100644 (file)
index 0000000..68f9865
--- /dev/null
@@ -0,0 +1,61 @@
+############################################################################
+#    Copyright (C) 2008 by Volker Christian                                #
+#    Volker.Christian@fh-hagenberg.at                                      #
+#                                                                          #
+#    This program is free software; you can redistribute it and#or modify  #
+#    it under the terms of the GNU General Public License as published by  #
+#    the Free Software Foundation; either version 2 of the License, or     #
+#    (at your option) any later version.                                   #
+#                                                                          #
+#    This program is distributed in the hope that it will be useful,       #
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of        #
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         #
+#    GNU General Public License for more details.                          #
+#                                                                          #
+#    You should have received a copy of the GNU General Public License     #
+#    along with this program; if not, write to the                         #
+#    Free Software Foundation, Inc.,                                       #
+#    59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             #
+############################################################################
+
+
+from Components.MenuList import MenuList
+from Screens.Screen import Screen
+from Components.ActionMap import ActionMap
+
+
+class YouTubeEntryContextMenuList(MenuList):
+       def __init__(self):
+               self.menuList = []
+               MenuList.__init__(self, self.menuList)
+
+               
+       def appendEntry(self, entry):
+               self.menuList.append(entry)
+
+
+class YouTubeEntryContextMenu(Screen):
+       def __init__(self, session, menuList, title):
+               Screen.__init__(self, session)
+               self.tmpTitle = title
+
+               self["actions"] = ActionMap(["OkCancelActions"],
+               {
+                       "ok": self.okbuttonClick,
+                       "cancel": self.cancelClick
+               })
+               self["menu"] = menuList
+               
+               self.onFirstExecBegin.append(self.setTitleDelaied)
+
+
+       def okbuttonClick(self):
+               self.close(self["menu"].getCurrent()[1])
+               
+
+       def cancelClick(self):
+               self.close(None)
+
+
+       def setTitleDelaied(self):
+               self.setTitle(self.tmpTitle)
diff --git a/youtubeplayer/src/YouTubeInterface.py b/youtubeplayer/src/YouTubeInterface.py
new file mode 100644 (file)
index 0000000..6357b5c
--- /dev/null
@@ -0,0 +1,550 @@
+############################################################################
+#    Copyright (C) 2008 by Volker Christian                                #
+#    Volker.Christian@fh-hagenberg.at                                      #
+#                                                                          #
+#    This program is free software; you can redistribute it and#or modify  #
+#    it under the terms of the GNU General Public License as published by  #
+#    the Free Software Foundation; either version 2 of the License, or     #
+#    (at your option) any later version.                                   #
+#                                                                          #
+#    This program is distributed in the hope that it will be useful,       #
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of        #
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         #
+#    GNU General Public License for more details.                          #
+#                                                                          #
+#    You should have received a copy of the GNU General Public License     #
+#    along with this program; if not, write to the                         #
+#    Free Software Foundation, Inc.,                                       #
+#    59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             #
+############################################################################
+
+import gdata.youtube
+import gdata.youtube.service
+
+from gdata.service import BadAuthentication
+
+from Tools.LoadPixmap import LoadPixmap
+
+from twisted.web.client import downloadPage
+
+from urllib import urlretrieve, quote
+
+from httplib import HTTPConnection
+
+from socket import gaierror
+
+import os
+import re
+
+# http://code.google.com/apis/youtube/reference.html#youtube_data_api_tag_media:group
+
+
+class YouTubeUser():
+       def __init__(self, cfg):
+               self.cfg = cfg
+
+
+       def getCfg(self):
+               return self.cfg
+
+
+       def getName(self):
+               return self.cfg.name.value
+
+
+       def name(self):
+               return self.cfg.name
+
+
+       def getEmail(self):
+               return self.cfg.email.value
+
+
+       def email(self):
+               return self.cfg.email
+
+
+       def getPassword(self):
+               return self.cfg.password.value
+
+
+       def password(self):
+               return self.cfg.password
+
+
+       def login(self):
+               return interface.login(self)
+
+
+class YouTubeFeed():
+       def __init__(self, feed, favoritesFeed = False):
+               print "[YTB] YouTubeFeed::__init__()"
+               self.feed = feed
+               self.favoritesFeed = favoritesFeed
+               self.entries = []
+               self.update()
+
+
+       def update(self):
+               print "[YTB] YouTubeFeed::update()"
+               sequenceNumber = int(self.feed.start_index.text)
+               print self.feed.entry
+               for entry in self.feed.entry:
+                       self.entries.append(YouTubeEntry(self, entry, sequenceNumber, self.favoritesFeed))
+                       sequenceNumber = sequenceNumber + 1
+
+
+       def getTitle(self):
+               return self.feed.title.text
+
+
+       def getEntries(self):
+               print "[YTB] YouTubeFeed::getEntries()"
+               return self.entries
+
+
+       def itemCount(self):
+               print "[YTB] YouTubeFeed::itemCount()"
+               return self.feed.items_per_page.text
+
+
+       def getTotalResults(self):
+               return self.feed.total_results.text
+       
+
+       def getNextFeed(self):
+               print "[YTB] YouTubeFeed::getNextFeed()"
+               for link in self.feed.link:
+                       if link.rel == "next":
+                               return link.href
+               return None
+
+
+       def getPreviousFeed(self):
+               print "[YTB] YouTubeFeed::getPreviousFeed()"
+               for link in self.feed.link:
+                       if link.rel == "previous":
+                               return link.href
+               return None
+
+
+       def getSelfFeed(self):
+               print "[YTB] YouTubeFeed::getSelfFeed()"
+               for link in self.feed.link:
+                       if link.rel == "self":
+                               return link.href
+               return None
+
+
+       def loadThumbnails(self, callback):
+               print "[YTB] YouTubeFeed::loadThumbnails()"
+               for entry in self.entries:
+                       entry.loadThumbnails(callback)
+
+
+class YouTubeEntry():
+       def __init__(self, feed, entry, sequenceNumber, favoritesFeed = False):
+               print "[YTB] YouTubeEntry::__init__()"
+               self.feed = feed
+               self.entry = entry
+               self.sequenceNumber = sequenceNumber
+               self.favoritesFeed = favoritesFeed
+               self.thumbnail = {}
+
+
+       def isPlaylistEntry(self):
+               return False
+
+
+       def getYouTubeId(self):
+               print "[YTB] YouTubeEntry::getYouTubeId()"
+               return self.entry.media.player.url.split("=").pop()
+
+
+       def getTitle(self):
+               print "[YTB] YouTubeEntry::getTitle()"
+               return self.entry.media.title.text
+
+
+       def getDescription(self):
+               print "[YTB] YouTubeEntry::getDescription()"
+               return self.entry.media.description.text
+
+
+       def getThumbnailUrl(self, index):
+               print "[YTB] YouTubeEntry::getThumbnailUrl"
+               if index < len(self.entry.media.thumbnail):
+                       return self.entry.media.thumbnail[index].url
+               return None
+
+
+       def getRelatedFeed(self):
+               print "[YTB] YouTubeEntry::getRelatedFeed()"
+               for link in self.entry.link:
+                       print "Related link: ", link.rel.endswith
+                       if link.rel.endswith("video.related"):
+                               print "Found Related: ", link.href
+                               return link.href
+
+
+       def getResponsesFeed(self):
+               print "[YTB] YouTubeEntry::getResponseFeed()"
+               for link in self.entry.link:
+                       print "Responses link: ", link.rel.endswith
+                       if link.rel.endswith("video.responses"):
+                               print "Found Responses: ", link.href
+                               return link.href
+
+
+       def loadThumbnail(self, index, callback):
+               print "[YTB] YouTubeEntry::loadThumbnail()"
+               thumbnailUrl = self.getThumbnailUrl(index)
+               if thumbnailUrl is not None and self.getYouTubeId() is not None:
+                       thumbnailFile = "/tmp/" + self.getYouTubeId() + "_" + str(index) + ".jpg"
+                       self.thumbnail[str(index)] = None
+                       cookie = {"entry" : self, "file" : thumbnailFile, "callback" : callback, "index" : index}
+                       downloadPage(thumbnailUrl, thumbnailFile).addCallback(fetchFinished, cookie).addErrback(fetchFailed, cookie)
+               
+
+       def loadThumbnails(self, callback):
+               print "[YTB] YouTubeEntry::loadThumbnails()"
+               self.loadThumbnail(0, callback)
+
+
+       def getVideoUrl(self, fmt):
+               conn = HTTPConnection("www.youtube.com")
+               conn.request("GET", "/v/" + quote(self.getYouTubeId()))
+               response = conn.getresponse()
+               conn.close()
+               mrl = None
+               print "[YTB] Response: ", response.status, response.reason
+               if response.status == 303:
+                       location = response.getheader("location")
+                       mrl = "http://www.youtube.com/get_video?video_id=" + quote(self.getYouTubeId()) + "&t=" + quote(re.match (".*[?&]t=([^&]+)", location).groups()[0]) + fmt
+                       print "[YTB] Playing ", mrl
+               else:
+                       print "[YTB] No valid flv-mrl found"
+               return mrl
+
+
+       def getDuration(self):
+               if self.entry.media is not None and self.entry.media.duration is not None:
+                       return self.entry.media.duration.seconds
+               return "not available"
+
+       
+       def getRatingAverage(self):
+               if self.entry.rating is not None:
+                       return self.entry.rating.average
+               return "not available"
+
+
+       def getNumRaters(self):
+               if self.entry.rating is not None:
+                       return self.entry.rating.num_raters
+               return ""
+       
+       
+       def getRatingMax(self):
+               if self.entry.rating is not None:
+                       return self.entry.rating.max
+               return "not available"
+       
+       def getRatingMin(self):
+               if self.entry.rating is not None:
+                       return self.entry.rating.min
+               return "not available"
+
+       
+       def getFavoriteCount(self):
+               if self.entry.statistics is not None:
+                       return self.entry.statistics.favorite_count
+               return "not available"
+       
+       
+       def getViewCount(self):
+               if self.entry.statistics is not None:
+                       return self.entry.statistics.view_count
+               return "not available"
+
+       
+       def getAuthor(self):
+               authorList = []
+               for author in self.entry.author:
+                       authorList.append(author.name.text)
+               authors = ", ".join(authorList)
+               return authors
+
+       
+       def getPublishedOn(self):
+               if self.entry.published is not None:
+                       return self.entry.published.text
+               return "unknown"
+
+       
+       def getCategory(self):
+               return self.entry.GetYouTubeCategoryAsString()
+
+       
+       def getTags(self):
+               if self.entry.media is not None and self.entry.media.keywords is not None:
+                       return self.entry.media.keywords.text
+               return "not available"
+
+
+       def belongsToFavorites(self):
+               return self.favoritesFeed
+
+
+       def belongsToPlaylistId(self):
+               return self.playlistId
+
+
+class YouTubePlaylistFeed():
+       def __init__(self, feed):
+               print "[YTB] YouTubePlayListFeed::__init__()"
+               self.feed = feed
+               self.entries = []
+               self.update()
+
+
+       def update(self):
+               print "[YTB] YouTubePlayListFeed::update()"
+               for entry in self.feed.entry:
+                       self.entries.append(YouTubePlaylistEntry(entry))
+
+
+       def getTitle(self):
+               print "[YTB] YouTubePlayListFeed::getTitle()"
+               return self.feed.title.text
+
+
+       def getEntries(self):
+               print "[YTB] YouTubePlayListFeed::getEntries()"
+               return self.entries
+
+
+class YouTubePlaylistEntry():
+       def __init__(self, entry):
+               print "[YTB] YouTubePlaylistEntry::__init__()"
+               self.entry = entry
+
+
+       def getTitle(self):
+               print "[YTB] YouTubePlaylistEntry::getTitle()"
+               return self.entry.title.text
+
+
+       def getDescription(self):
+               print "[YTB] YouTubePlaylistEntry::getDescription()"
+               return self.entry.description.text
+
+
+       def getFeed(self, index = 0):
+               print "[YTB] YouTubePlaylistEntry::getFeed()"
+               return self.entry.feed_link[index].href
+
+       
+       def getSelfFeed(self):
+               print "[YTB] YouTubeFeed::getSelfFeed()"
+               for link in self.entry.link:
+                       if link.rel == "self":
+                               return link.href
+               return None
+
+
+class YouTubePlaylistVideoFeed(YouTubeFeed):
+       def __init__(self, feed):
+               print "[YTB] YouTubePlaylistVideoFeed::__init__()"
+               YouTubeFeed.__init__(self, feed)
+
+
+       def update(self):
+               print "[YTB] YouTubePlaylistVideoFeed::update()"
+               sequenceNumber = 1
+               print self.feed.entry
+               for entry in self.feed.entry:
+                       self.entries.append(YouTubePlaylistVideoEntry(self, entry, sequenceNumber))
+                       sequenceNumber = sequenceNumber + 1
+
+       def getFeed(self):
+               print "[YTB] YouTubeFeed::getSelfFeed()"
+               for link in self.feed.link:
+                       if link.rel == "feed":
+                               return link.href
+               return None
+
+
+class YouTubePlaylistVideoEntry(YouTubeEntry):
+       def __init__(self, feed, entry, sequenceNumber):
+               print "[YTB] YouTubePlaylistVideoEntry::__init__()"
+               YouTubeEntry.__init__(self, feed, entry, sequenceNumber)
+
+
+       def isPlaylistEntry(self):
+               return True
+
+
+       def getSelf(self):
+               print "[YTB] YouTubePlaylistVideoEntry::getSelfFeed()"
+               for link in self.entry.link:
+                       if link.rel == "self":
+                               return link.href
+               return None
+
+
+       YOUTUBE_DEVELOPER_TAG_SCHEME = "http://gdata.youtube.com/schemas/2007/developertags.cat"
+       def getCategory(self):
+               for category in self.entry.media.category:
+                       if category.scheme != YouTubePlaylistVideoEntry.YOUTUBE_DEVELOPER_TAG_SCHEME:
+                               return category.text
+               return "not available"
+
+
+class YouTubeInterface():
+#      Do not change the client_id and developer_key in the login-section!
+#      ClientId: ytapi-VolkerChristian-YouTubePlayer-pq3mrg1o-0
+#      DeveloperKey: AI39si7t0WNyg_tvjBPdRIvBfaUA_XrTY1LNzfjLgCn8A_m92YKtWTcR_auEmI5gKGitJb4SskrjxJSmRc3yhQ4YlHTBAzPSig
+       def __init__(self):
+               print "[YTB] YouTubeInterface::__init__()"
+
+
+       def open(self):
+               self.ytService = gdata.youtube.service.YouTubeService()
+               print "[YTB] YouTubeInterface::open()"
+               self.loggedIn = False
+
+
+       def close(self):
+               print "[YTB] YouTubeInterface::close()"
+               del self.ytService
+               self.loggedIn = False
+
+
+       def login(self, user):
+               print "[YTB] YouTubeInterface::login()"
+               ret = False
+               if user is not None:
+                       try:
+                               # http://code.google.com/apis/youtube/developers_guide_python.html#ClientLogin
+                               self.ytService.email = user.getEmail()
+                               self.ytService.password = user.getPassword()
+                               self.ytService.source = 'my-example-application'
+                               self.ytService.developer_key = "AI39si7t0WNyg_tvjBPdRIvBfaUA_XrTY1LNzfjLgCn8A_m92YKtWTcR_auEmI5gKGitJb4SskrjxJSmRc3yhQ4YlHTBAzPSig"
+                               self.ytService.client_id = "ytapi-VolkerChristian-YouTubePlayer-pq3mrg1o-0"
+                               self.ytService.ProgrammaticLogin()
+                       except BadAuthentication:
+                               pass
+                       else:
+                               self.loggedIn = True
+                               ret = True
+               return ret
+
+
+       def isLoggedIn(self):
+               return self.loggedIn
+
+
+       def search(self, searchTerms, startIndex = 1, maxResults = 25,
+                                       orderby = "relevance", time = "all_time", racy = "include", 
+                                       author = ""):
+               print "[YTB] YouTubeInterface::search()"
+               query = gdata.youtube.service.YouTubeVideoQuery()
+               query.vq = searchTerms
+               query.orderby = orderby
+               query.racy = racy
+               query.start_index = startIndex
+               query.max_results = maxResults
+               try:
+                       feed = YouTubeFeed(self.ytService.YouTubeQuery(query))
+               except gaierror:
+                       feed = None
+               return feed
+
+
+       def getFeed(self, url):
+               return YouTubeFeed(self.ytService.GetYouTubeVideoFeed(url))
+
+
+       def getUserFavoritesFeed(self, userName = "default"):
+               return YouTubeFeed(self.ytService.GetUserFavoritesFeed(userName), favoritesFeed = True)
+
+
+       def getUserPlaylistFeed(self, playlistEntry):
+               print "[YTB] getUserPlaylistFeed: ", playlistEntry.getFeed()
+               return YouTubePlaylistVideoFeed(self.ytService.GetYouTubePlaylistVideoFeed(playlistEntry.getFeed()))
+
+
+       def addToFavorites(self, entry):
+               response = self.ytService.AddVideoEntryToFavorites(entry.entry)
+               # The response, if succesfully posted is a YouTubeVideoEntry
+               if isinstance(response, gdata.youtube.YouTubeVideoEntry):
+                       print "[YTB] Video successfully added to favorites"
+                       return response
+               else:
+                       return None
+
+
+       def removeFromFavorites(self, entry):
+               response = self.ytService.DeleteVideoEntryFromFavorites(entry.getYouTubeId())
+               if response is True:
+                       print "[YTB] Video deleted from favorites"
+               return response
+
+
+       def getPlaylistFeed(self):
+               return YouTubePlaylistFeed(self.ytService.GetYouTubePlaylistFeed())
+
+
+       def addPlaylist(self, name, description, private):
+               newPlaylist = None
+               newPlaylistEntry = self.ytService.AddPlaylist(name, description, private)
+               if isinstance(newPlaylistEntry, gdata.youtube.YouTubePlaylistEntry):
+                       newPlaylist = YouTubePlaylistEntry(newPlaylistEntry)
+               return newPlaylist
+
+
+       def deletePlaylist(self, playlistEntry):
+               playListUrl = playlistEntry.getSelfFeed()
+               return self.ytService.DeletePlaylist(playListUrl)
+
+       
+       def removeFromPlaylist(self, playlistVideoEntry):
+               print "[YTB] Removing from Playlist"
+               response = self.ytService.Delete(playlistVideoEntry.getSelf())
+               if response:
+                       print "[YTB] Successfull deleted"
+               else:
+                       print "[YTB] Delete unsuccessfull"
+               return response
+
+
+       def addToPlaylist(self, playlistEntry, videoEntry):
+               print "[YTB] Adding to Playlist"
+               playlistUri = playlistEntry.getFeed()
+               response = self.ytService.AddPlaylistVideoEntryToPlaylist(
+                                               playlistUri, videoEntry.getYouTubeId(), videoEntry.getTitle(), videoEntry.getDescription())
+               if isinstance(response, gdata.youtube.YouTubePlaylistVideoEntry):
+                       print "[YTB] Video added"
+                       return response
+               else:
+                       return None
+
+
+def fetchFailed(string, cookie):
+       print "[YTB] fetchFailed(): ", string
+       if os.path.exists(cookie["file"]):
+               os.remove(cookie["file"])
+       cookie["callback"](cookie["entry"])
+
+
+def fetchFinished(string, cookie):
+       print "[YTB] fetchFinished(): ", string
+       if os.path.exists(cookie["file"]):
+               print "Loading filename %s" % cookie["file"]
+               cookie["entry"].thumbnail[str(cookie["index"])] = LoadPixmap(cookie["file"])
+               os.remove(cookie["file"])
+       cookie["callback"](cookie["entry"])
+
+
+interface = YouTubeInterface()
diff --git a/youtubeplayer/src/YouTubeList.py b/youtubeplayer/src/YouTubeList.py
new file mode 100644 (file)
index 0000000..8cd638b
--- /dev/null
@@ -0,0 +1,633 @@
+############################################################################
+#    Copyright (C) 2008 by Volker Christian                                #
+#    Volker.Christian@fh-hagenberg.at                                      #
+#                                                                          #
+#    This program is free software; you can redistribute it and#or modify  #
+#    it under the terms of the GNU General Public License as published by  #
+#    the Free Software Foundation; either version 2 of the License, or     #
+#    (at your option) any later version.                                   #
+#                                                                          #
+#    This program is distributed in the hope that it will be useful,       #
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of        #
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         #
+#    GNU General Public License for more details.                          #
+#                                                                          #
+#    You should have received a copy of the GNU General Public License     #
+#    along with this program; if not, write to the                         #
+#    Free Software Foundation, Inc.,                                       #
+#    59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             #
+############################################################################
+
+from YouTubeInterface import interface
+
+from Components.ActionMap import ActionMap
+from Components.MenuList import MenuList
+from Components.Label import Label
+from Components.ScrollLabel import ScrollLabel
+from Components.Pixmap import Pixmap
+from Components.ProgressBar import ProgressBar
+
+from Components.MultiContent import MultiContentEntryText, MultiContentEntryPixmapAlphaTest
+from Tools.Directories import resolveFilename, SCOPE_PLUGINS, SCOPE_SKIN_IMAGE
+from enigma import eListboxPythonMultiContent, gFont, RT_HALIGN_LEFT, RT_VALIGN_TOP, RT_WRAP
+from enigma import eTimer
+
+from Tools.NumericalTextInput import NumericalTextInput
+
+from Screens.Screen import Screen
+from Screens.MessageBox import MessageBox
+
+from Components.config import config
+
+from Plugins.Extensions.VlcPlayer.VlcServerConfig import vlcServerConfig
+from Plugins.Extensions.VlcPlayer.VlcServer import VlcServer
+from Plugins.Extensions.VlcPlayer.VlcServerList import VlcServerListScreen
+
+from YouTubeContextMenu import YouTubeEntryContextMenu, YouTubeEntryContextMenuList
+
+from Tools.BoundFunction import boundFunction
+
+from YouTubePlayer import YouTubePlayer
+
+from YouTubeUserConfig import youTubeUserConfig
+from YouTubeUserList import YouTubeUserListScreen
+from YouTubePlayList import YouTubePlaylistScreen
+
+from . import _
+
+def YouTubeEntryComponent(entry):
+       res = [ entry ]
+# 385
+       res.append(MultiContentEntryText(pos = (150, 5), size = (370, 42), font = 0, flags = RT_HALIGN_LEFT | RT_VALIGN_TOP| RT_WRAP, text = entry.getTitle()))
+       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()))
+
+       if entry.thumbnail["0"] is None:
+               png = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/plugin.png"))
+       else:
+               png = entry.thumbnail["0"]
+       res.append(MultiContentEntryPixmapAlphaTest(pos = (10, 5), size = (130, 97), png = png))
+
+       return res
+
+
+class YouTubeVideoDetailsScreen(Screen):
+       def __init__(self, session, entry):
+               Screen.__init__(self, session)
+               self.entry = entry
+               self["video_description"] = ScrollLabel(entry.getDescription())
+               durationInSecs = int(entry.getDuration())
+               mins = int(durationInSecs / 60)
+               secs = durationInSecs - mins * 60
+               duration = "%d:%02d" % (mins, secs)
+               
+               self["label_video_duration"] = Label(_("Duration") + ":")
+               self["video_duration"] = Label(duration)
+               
+               self["label_video_rating_average"] = Label(_("Rate") + ":")
+               self["starsbg"] = Pixmap()
+               self["stars"] = ProgressBar()
+
+               self["label_video_numraters"] = Label(_("Ratings") + ":")
+               self["video_numraters"] = Label(entry.getNumRaters())
+               
+               self["label_video_statistics_favorite_count"] = Label(_("Favorited") + ":")
+               self["video_statistics_favorite_count"] = Label(entry.getFavoriteCount())
+               
+               self["label_video_statistics_view_count"] = Label(_("Views") + ":")
+               self["video_statistics_view_count"] = Label(entry.getViewCount())
+
+               self["label_video_author"] = Label(_("Author:") + ":")
+               self["video_author"] = Label(entry.getAuthor())
+
+               self["label_video_published_on"] = Label(_("Added") + ":")
+               self["video_published_on"] = Label(entry.getPublishedOn().split("T")[0])
+
+               self["label_video_category"] = Label(_("Category") + ":")
+               self["video_category"] = Label(entry.getCategory())
+               self["label_video_tags"] = Label(_("Tags") + ":")
+               self["video_tags"] = Label(entry.getTags())
+               
+               self["video_thumbnail_1"] = Pixmap()
+               self["video_thumbnail_2"] = Pixmap()
+               self["video_thumbnail_3"] = Pixmap()
+
+               self["actions"] = ActionMap(["YouTubeVideoDetailsScreenActions"],
+               {
+                       "ok"            :       self.close,
+                       "cancel"        :       self.close,
+                       "up"            :       self.pageUp,
+                       "down"          :       self.pageDown,
+                       "left"          :       self.pageUp,
+                       "right"         :       self.pageDown
+               })
+
+               self.onFirstExecBegin.append(self.setPixmap)
+               self.onFirstExecBegin.append(self.setInitialize)
+
+
+       def pageUp(self):
+               self["video_description"].pageUp()
+
+
+       def pageDown(self):
+               self["video_description"].pageDown()
+
+
+       def setInitialize(self):
+               Screen.setTitle(self, self.entry.getTitle())
+               if self.entry.getRatingAverage() != "not available":
+                       ratingStars = int(round(20 * float(self.entry.getRatingAverage()), 0))
+                       print "[YTB] Rating: ", ratingStars, "    ", self["stars"].getRange()
+                       self["stars"].setValue(ratingStars)
+               else:
+                       self["stars"].hide()
+                       self["starsbg"].hide()
+
+
+       def setPixmap(self):
+               self["video_thumbnail_1"].instance.setPixmap(self.entry.thumbnail["0"].__deref__())
+               self.entry.loadThumbnail(1, self.setThumbnail_2)
+               self.entry.loadThumbnail(2, self.setThumbnail_3)
+               self["video_thumbnail_2"].hide()
+               self["video_thumbnail_3"].hide()
+
+
+       def setThumbnail_2(self, entry):
+               self["video_thumbnail_2"].instance.setPixmap(self.entry.thumbnail["1"].__deref__())
+               self["video_thumbnail_2"].show()
+
+
+       def setThumbnail_3(self, entry):
+               self["video_thumbnail_3"].instance.setPixmap(self.entry.thumbnail["2"].__deref__())
+               self["video_thumbnail_3"].show()
+
+
+class PatientMessageBox(MessageBox):
+       def __init__(self, session, text, type = 1, timeout = -1, close_on_any_key = False, default = True):
+               MessageBox.__init__(self, session, text, type, timeout, close_on_any_key, default)
+               self.skinName = "MessageBox"
+
+
+       def processDelayed(self, function):
+               self.delay_timer = eTimer()
+               self.delay_timer.callback.append(self.processDelay)
+               self.delay_timer.start(0, 1)
+               self.function = function
+
+
+       def processDelay(self):
+               self.function()
+
+
+       def cancel(self):
+               pass
+
+
+       def ok(self):
+               pass
+
+
+       def alwaysOK(self):
+               pass
+
+
+class YouTubeList(MenuList):
+       def __init__(self, list, enableWrapAround = False):
+               MenuList.__init__(self, list, enableWrapAround, eListboxPythonMultiContent)
+               self.l.setFont(0, gFont("Regular", 18))
+               self.l.setFont(1, gFont("Regular", 14))
+               self.l.setItemHeight(105)
+
+
+class YouTubeListScreen(Screen, NumericalTextInput):
+       def __init__(self, session):
+               Screen.__init__(self, session)
+               NumericalTextInput.__init__(self)
+
+               self.session = session
+               self.serverName = config.plugins.youtubeplayer.serverprofile.value
+               self.currentServer = vlcServerConfig.getServerByName(self.serverName)
+
+               self["red"] = Label(_("Select a VLC-Server"))
+               self["green"] = Label(_("New YouTube search"))
+               
+               self.list = []
+               self["list"] = YouTubeList(self.list)
+
+               self["label_total_results"] = Label(_("Total results") + ":")
+               self["total_results"] = Label("")
+
+               self["label_currently_shown"] = Label(_("Shown") + ":")
+               self["currently_shown"] = Label("")
+
+               self.history = []
+               self.historyIndex = 0
+
+               self.isFavoritesFeed = False
+
+               self.patientDialog = None
+               
+               self["actions"] = ActionMap(["YouTubeVideoListActions"],
+               {
+                       "play"                  :       self.tryToPlay,
+                       "select"                :       self.justSelectServer,
+                       "search"                :       self.searchAgain,
+                       "menu"                  :       self.openContextMenu,
+                       "forward"               :       self.forwardInHistory,
+                       "backward"              :       self.backInHistory,
+                       "left"                  :       self.keyLeft,
+                       "right"                 :       self.keyRight,
+                       "up"                    :       self.keyUp,
+                       "down"                  :       self.keyDown,
+                       "info"                  :       self.showVideoInfo,
+                       "cancel"                :       self.close
+               }, -1)
+
+
+       def keyLeft(self):
+               self["list"].pageUp()
+
+
+       def keyRight(self):
+               if self["list"].getSelectionIndex() == len(self.list) - 1 and self.feed.getNextFeed() is not None:
+                       dlg = self.session.openWithCallback(self.loadNextFeed, MessageBox, _("Load further entries of current Feed?"))
+               else:
+                       self["list"].pageDown()
+
+
+       def keyUp(self):
+               self["list"].up()
+
+
+       def keyDown(self):
+               if self["list"].getSelectionIndex() == len(self.list) - 1 and self.feed.getNextFeed() is not None:
+                       dlg = self.session.openWithCallback(self.loadNextFeed, MessageBox, _("Load further entries of current Feed?"))
+               else:
+                       self["list"].down()
+
+
+       def insertEntry(self, entry):
+               print "[YTB] YouTubeTest::updateFinished()"
+               self.list.append(YouTubeEntryComponent(entry))
+               self.list.sort(cmp = lambda x, y : cmp(x[0].sequenceNumber, y[0].sequenceNumber))
+               currentlyShown = "%d" % len(self.list)
+               self["currently_shown"].setText(currentlyShown)
+               self["list"].setList(self.list)
+
+
+       def closePatientDialogDelayed(self):
+               if self.patientDialog:
+                       self.patientDialog.close()
+                       self.patientDialog = None
+               self["list"].setList(self.list)
+
+
+       def showFeed(self, feed, append):
+               self.feed = feed
+               self.setTitle(feed.getTitle())
+               self["total_results"].setText(feed.getTotalResults())
+               if not append:
+                       self.list = []
+                       self["list"].setList(self.list)
+               self.feed.loadThumbnails(self.insertEntry)
+               self.delay_timer = eTimer()
+               self.delay_timer.callback.append(self.closePatientDialogDelayed)
+               self.delay_timer.start(100, 1)
+
+
+       def addToHistory(self, feed):
+               del self.history[self.historyIndex : len(self.history)]
+               self.history.insert(self.historyIndex, feed.getSelfFeed())
+               self.historyIndex = self.historyIndex + 1
+
+
+       def searchFeedReal(self, searchContext):
+               print "[YTB] youTubeTest"
+               feed = interface.search(searchContext.searchTerm.value)
+               self.showFeed(feed, False)
+               self.addToHistory(feed)
+
+
+       def searchFeed(self, searchContext):
+               self.patientDialog = self.session.open(PatientMessageBox, _("Searching, be patient ..."))
+               self.patientDialog.processDelayed(boundFunction(self.searchFeedReal, searchContext = searchContext))
+               self.isFavoritesFeed = False
+
+
+       def loadPlaylistFeedReal(self, playlist):
+               feed = interface.getUserPlaylistFeed(playlist)
+               self.showFeed(feed, False)
+               self.addToHistory(feed)
+
+
+       def loadPlaylistFeed(self, playlist):
+               self.patientDialog = self.session.open(PatientMessageBox, _("Loading playlist, be patient ..."))
+               self.patientDialog.processDelayed(boundFunction(self.loadPlaylistFeedReal, playlist = playlist))
+
+
+       def loadFavoritesFeedReal(self, userName = "default"):
+               feed = interface.getUserFavoritesFeed(userName)
+               self.showFeed(feed, False)
+               self.addToHistory(feed)
+
+
+       def loadFavoritesFeed(self, userName = "default"):
+               self.patientDialog = self.session.open(PatientMessageBox, _("Loading favorits, be patient ..."))
+               self.patientDialog.processDelayed(boundFunction(self.loadFavoritesFeedReal, userName = userName))
+               self.isFavoritesFeed = True
+
+
+       def loadStandardFeed(self, url):
+               self.loadFeed(_("Loading standard feed, be patient ..."), url)
+
+
+       def loadFeedReal(self, feedUrl, append = False, addToHistory = True):
+               feed = interface.getFeed(feedUrl)
+               self.showFeed(feed, append)
+               if addToHistory:
+                       self.addToHistory(feed)
+
+
+       def loadFeed(self, text, feedUrl, append = False, addToHistory = True):
+               self.patientDialog = self.session.open(PatientMessageBox, text)
+               self.patientDialog.processDelayed(boundFunction(self.loadFeedReal, feedUrl = feedUrl,
+                                                                                       append = append, addToHistory = addToHistory))
+
+
+       def loadPreviousFeed(self, result):
+               if not result:
+                       return
+               prevUrl = self.feed.getPreviousFeed()
+               if prevUrl is not None:
+                       self.loadFeed(_("Loading additional videos, be patient ..."), prevUrl, True, True)
+
+
+       def loadNextFeed(self, result):
+               if not result:
+                       return
+               nextUrl = self.feed.getNextFeed()
+               if nextUrl is not None:
+                       self.loadFeed(_("Loading additional videos, be patient ..."), nextUrl, True, True)
+
+
+       def getRelated(self):
+               self.loadFeed(_("Loading related videos, be patient ..."), self["list"].getCurrent()[0].getRelatedFeed(), False, True)
+               self.isFavoritesFeed = False
+
+
+       def getResponses(self):
+               self.loadFeed(_("Loading response videos, be patient ..."), self["list"].getCurrent()[0].getResponsesFeed(), False, True)
+               self.isFavoritesFeed = False
+
+
+       def backInHistory(self):
+               if self.historyIndex > 1:
+                       self.historyIndex = self.historyIndex - 1
+                       self.loadFeed(_("Back in history, be patient ..."), self.history[self.historyIndex - 1], False, False)
+
+
+       def forwardInHistory(self):
+               if self.historyIndex < len(self.history):
+                       self.historyIndex = self.historyIndex + 1
+                       self.loadFeed(_("Forward in history, be patient ..."), self.history[self.historyIndex - 1], False, False)
+
+
+       def showVideoInfo(self):
+               self.session.open(YouTubeVideoDetailsScreen, self["list"].getCurrent()[0])
+
+
+       def justSelectServer(self):
+               defaultServer = vlcServerConfig.getServerByName(config.plugins.youtubeplayer.serverprofile.value)
+               self.selectServer(self.serverSelectedCB, defaultServer)
+
+
+       def selectServer(self, callback, currentServer):
+               self.session.openWithCallback(callback, VlcServerListScreen, currentServer)
+
+
+       def serverSelectedCB(self, selectedServer, defaultServer):
+               if selectedServer is not None:
+                       self.currentServer = selectedServer
+               elif defaultServer is not None:
+                               self.currentServer = defaultServer
+               if defaultServer is not None:
+                       config.plugins.youtubeplayer.serverprofile.value = defaultServer.getName()
+                       config.plugins.youtubeplayer.serverprofile.save()
+
+
+       def selectAndPlayCB(self, selectedServer, defaultServer):
+               self.serverSelectedCB(selectedServer, defaultServer)
+               self.tryToPlay()
+
+
+       def tryToPlay(self):
+               if self.currentServer is not None:
+                       self.play()
+               else:
+                       self.selectServer(self.selectAndPlayCB, None)
+
+
+       def login(self, callback):
+               self.session.openWithCallback(callback, YouTubeUserListScreen, youTubeUserConfig.getDefaultUser())
+
+
+       def addToFavoritesReal(self):
+               interface.addToFavorites(self["list"].getCurrent()[0])
+
+
+       def addToFavoritesLogin(self, loginState):
+               if loginState == YouTubeUserListScreen.LOGIN_SUCCESS:
+                       self.addToFavoritesReal()
+               elif loginState == YouTubeUserListScreen.LOGIN_FAILED:
+                       self.session.open(MessageBox, _("Login not successful"), MessageBox.TYPE_INFO)
+               else:
+                       pass
+
+
+       def addToFavorites(self):
+               if not interface.isLoggedIn():
+                       self.login(self.addToFavoritesLogin)
+               else:
+                       self.addToFavoritesReal()
+
+
+       def removeFromFavoritesReal(self):
+               if interface.removeFromFavorites(self["list"].getCurrent()[0]):
+                       self.list.remove(self["list"].getCurrent())
+                       self["list"].setList(self.list)
+
+
+       def removeFromFavoritesLogin(self, loginState):
+               if loginState == YouTubeUserListScreen.LOGIN_SUCCESS:
+                       self.removeFromFavoritesReal()
+               elif loginState == YouTubeUserListScreen.LOGIN_FAILED:
+                       self.session.open(MessageBox, _("Login not successful"), MessageBox.TYPE_INFO)
+               else:
+                       pass
+
+
+       def removeFromFavorites(self):
+               if not interface.isLoggedIn():
+                       self.login(self.removeFromFavoritesLogin)
+               else:
+                       self.removeFromFavoritesReal()
+
+
+       def removeFromPlaylistReal(self):
+               if interface.removeFromPlaylist(self["list"].getCurrent()[0]):
+                       self.list.remove(self["list"].getCurrent())
+                       self["list"].setList(self.list)
+
+
+       def removeFromPlaylistLogin(self, loginState):
+               if loginState == YouTubeUserListScreen.LOGIN_SUCCESS:
+                       self.removeFromPlaylistReal()
+               elif loginState == YouTubeUserListScreen.LOGIN_FAILED:
+                       self.session.open(MessageBox, _("Login not successful"), MessageBox.TYPE_INFO)
+               else:
+                       pass
+
+
+       def removeFromPlaylist(self):
+               if not interface.isLoggedIn():
+                       self.login(self.removeFromPlaylistLogin)
+               else:
+                       self.removeFromPlaylistReal()
+
+
+       def playlistChoosen(self, playlist):
+               if playlist is not None:
+                       interface.addToPlaylist(playlist, self["list"].getCurrent()[0])
+
+
+       def addToPlaylistReal(self):
+               dlg = self.session.openWithCallback(self.playlistChoosen, YouTubePlaylistScreen)
+               dlg.loadPlaylist()
+
+
+       def addToPlaylistLogin(self, loginState):
+               if loginState == YouTubeUserListScreen.LOGIN_SUCCESS:
+                       self.addToPlaylistReal()
+               elif loginState == YouTubeUserListScreen.LOGIN_FAILED:
+                       self.session.open(MessageBox, _("Login not successful"), MessageBox.TYPE_INFO)
+               else:
+                       pass
+
+
+       def addToPlaylist(self):
+               if not interface.isLoggedIn():
+                       self.login(self.addToPlaylistLogin)
+               else:
+                       self.addToPlaylistReal()
+
+
+# http://cacan.blog385.com/index.php/2008/05/09/youtube-high-quality-hacks/
+# add the &fmt=6 onto the end:
+#
+# http://youtube.com/watch?v=CQzUsTFqtW0&fmt=6
+#
+# If the YouTube video just sits there loading then that
+# is a sign that the video has not been converted to the
+# higher resolution yet. To really see the difference you
+# should view the video in full screen mode by clicking
+# the button in the bottom-right corner of the player.
+#
+# Note: Alternatively you can add &fmt=18 and it will play
+# the high-resolution version when available, otherwise it
+# will play the regular version. Here?s a Greasemonkey
+# script that will automatically add &fmt=18 onto the end
+# of each YouTube URL.
+       def play(self):
+               print "[YTB] Play()"
+               youTubeEntry = self["list"].getCurrent()[0]
+               mrl = youTubeEntry.getVideoUrl("&fmt=18")
+############## To be resolved
+#Traceback (most recent call last):
+#  File "/usr/lib/enigma2/python/Components/ActionMap.py", line 46, in action
+#    res = self.actions[action]()
+#  File "/usr/lib/enigma2/python/Plugins/Extensions/YouTubePlayer/YouTubeList.py", line 425, in tryToPlay
+#    self.play()
+#  File "/usr/lib/enigma2/python/Plugins/Extensions/YouTubePlayer/YouTubeList.py", line 543, in play
+#    mrl = youTubeEntry.getVideoUrl("&fmt=18")
+#  File "/usr/lib/enigma2/python/Plugins/Extensions/YouTubePlayer/YouTubeInterface.py", line 216, in getVideoUrl
+#    conn.request("GET", "/v/" + quote(self.getYouTubeId()))
+#  File "/usr/lib/python2.5/httplib.py", line 862, in request
+#    self._send_request(method, url, body, headers)
+#  File "/usr/lib/python2.5/httplib.py", line 885, in _send_request
+#    self.endheaders()
+#  File "/usr/lib/python2.5/httplib.py", line 856, in endheaders
+#    self._send_output()
+#  File "/usr/lib/python2.5/httplib.py", line 728, in _send_output
+#    self.send(msg)
+#  File "/usr/lib/python2.5/httplib.py", line 695, in send
+#    self.connect()
+#  File "/usr/lib/python2.5/httplib.py", line 663, in connect
+#    socket.SOCK_STREAM):
+#socket.gaierror: (2, 'temporary failure in name resolution.')
+
+               if mrl is not None:
+                       entries = []
+                       entries.append((_("Show video detail info"), [self.showVideoInfo, False]))
+                       if self["list"].getCurrent()[0].belongsToFavorites():
+                               entries.append((_("Remove from favorites"), [self.removeFromFavorites, False]))
+                       else:
+                               entries.append((_("Add to favorites"), [self.addToFavorites, False]))
+                               
+                       if self["list"].getCurrent()[0].isPlaylistEntry():
+                               entries.append((_("Remove from playlist"), [self.removeFromPlaylist, False]))
+                       else:
+                               entries.append((_("Add to playlist"), [self.addToPlaylist, False]))
+                       entries.append((_("Get related videos"), [self.getRelated, True]))
+                       entries.append((_("Get video responses"), [self.getResponses, True]))
+                       
+                       self.currentServer.play(self.session, mrl, youTubeEntry.getTitle(), self,
+                                                               player = boundFunction(YouTubePlayer, contextMenuEntries = entries, infoCallback = self.showVideoInfo, name = self["list"].getCurrent()[0].getTitle()))
+               else:
+                       print "[YTB] No valid flv-mrl found"
+
+
+       def getNextFile(self):
+               i = self["list"].getSelectedIndex() + 1
+               if i < len(self.list):
+                       self["list"].moveToIndex(i)
+                       youTubeEntry = self["list"].getCurrent()[0]
+                       return youTubeEntry.getVideoUrl("&fmt=18"), youTubeEntry.getTitle()
+               return None, None
+
+
+       def getPrevFile(self):
+               i = self["list"].getSelectedIndex() - 1
+               if i >= 0:
+                       self["list"].moveToIndex(i)
+                       youTubeEntry = self["list"].getCurrent()[0]
+                       return youTubeEntry.getVideoUrl("&fmt=18"), youTubeEntry.getTitle()
+               return None, None
+
+
+       def openContextMenu(self):
+               contextMenuList = YouTubeEntryContextMenuList()
+               contextMenuList.appendEntry((_("Show video detail info"), self.showVideoInfo))
+               if self["list"].getCurrent()[0].belongsToFavorites():
+                       contextMenuList.appendEntry((_("Remove from favorites"), self.removeFromFavorites))
+               else:
+                       contextMenuList.appendEntry((_("Add to favorites"), self.addToFavorites))
+               if self["list"].getCurrent()[0].isPlaylistEntry():
+                       contextMenuList.appendEntry((_("Remove from playlist"), self.removeFromPlaylist))
+               else:
+                       contextMenuList.appendEntry((_("Add to playlist"), self.addToPlaylist))
+               contextMenuList.appendEntry((_("Get related videos"), self.getRelated))
+               contextMenuList.appendEntry((_("Get video responses"), self.getResponses))
+               self.session.openWithCallback(self.menuActionCoosen, YouTubeEntryContextMenu, contextMenuList, self["list"].getCurrent()[0].getTitle())
+
+
+       def menuActionCoosen(self, function):
+               if function is not None:
+                       function()
+
+
+       def searchAgain(self):
+               Screen.close(self, True)
+
+
+       def close(self):
+               Screen.close(self, False)
\ No newline at end of file
diff --git a/youtubeplayer/src/YouTubePlayList.py b/youtubeplayer/src/YouTubePlayList.py
new file mode 100644 (file)
index 0000000..bd4bead
--- /dev/null
@@ -0,0 +1,109 @@
+############################################################################
+#    Copyright (C) 2008 by Volker Christian                                #
+#    Volker.Christian@fh-hagenberg.at                                      #
+#                                                                          #
+#    This program is free software; you can redistribute it and#or modify  #
+#    it under the terms of the GNU General Public License as published by  #
+#    the Free Software Foundation; either version 2 of the License, or     #
+#    (at your option) any later version.                                   #
+#                                                                          #
+#    This program is distributed in the hope that it will be useful,       #
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of        #
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         #
+#    GNU General Public License for more details.                          #
+#                                                                          #
+#    You should have received a copy of the GNU General Public License     #
+#    along with this program; if not, write to the                         #
+#    Free Software Foundation, Inc.,                                       #
+#    59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             #
+############################################################################
+
+from YouTubeInterface import interface
+from YouTubeAddPlayList import YouTubeAddPlaylistDialog
+from Components.ActionMap import ActionMap
+from Components.MenuList import MenuList
+from Components.Label import Label
+from Components.MultiContent import MultiContentEntryText
+from Screens.MessageBox import MessageBox
+from Screens.Screen import Screen
+from enigma import eListboxPythonMultiContent, gFont, RT_HALIGN_LEFT, RT_VALIGN_TOP, RT_WRAP
+
+from . import _
+
+
+def YouTubePlaylistEntryComponent(entry):
+       res = [ entry ]
+
+       res.append(MultiContentEntryText(pos = (5, 5), size = (550, 18), font = 0, flags = RT_HALIGN_LEFT | RT_VALIGN_TOP| RT_WRAP, text = entry.getTitle()))
+       res.append(MultiContentEntryText(pos = (5, 23), size = (550, 14), font = 1, color = 0xFFA323, color_sel = 0xFFA323, flags = RT_HALIGN_LEFT | RT_VALIGN_TOP| RT_WRAP, text = entry.getDescription()))
+
+       return res
+
+
+class YouTubePlaylistList(MenuList):
+       def __init__(self, list, enableWrapAround = False):
+               MenuList.__init__(self, list, enableWrapAround, eListboxPythonMultiContent)
+               self.l.setFont(0, gFont("Regular", 18))
+               self.l.setFont(1, gFont("Regular", 14))
+               self.l.setItemHeight(41)
+
+
+class YouTubePlaylistScreen(Screen):
+       def __init__(self, session):
+               Screen.__init__(self, session)
+
+               self.session = session
+
+               self["red"] = Label(_("Delete Playlist"))
+               self["green"] = Label(_("Add new Playlist"))
+               
+               self.list = []
+               self["list"] = YouTubePlaylistList(self.list)
+               
+               self["actions"] = ActionMap(["YouTubePlaylistScreenActions"],
+               {
+                       "ok"            :       self.choosePlaylist,
+                       "delete"        :       self.deletePlaylist,
+                       "add"           :       self.addPlaylist,
+                       "cancel"        :       self.close
+               }, -1)
+
+
+       def loadPlaylist(self):
+               self.list = []
+               feed = interface.getPlaylistFeed()
+               for entry in feed.getEntries():
+                       self.list.append(YouTubePlaylistEntryComponent(entry))
+               self["list"].setList(self.list)
+
+
+       def choosePlaylist(self):
+               Screen.close(self, self["list"].getCurrent()[0])
+
+
+       def deletePlaylist(self):
+               playList = self["list"].getCurrent()[0]
+               if playList is not None:
+                       self.session.openWithCallback(self.deleteCallback, MessageBox, _("Really delete %(playlist)s?") % {"playlist" : playList.getTitle()})
+
+
+       def deleteCallback(self, result):
+               if result:
+                       if interface.deletePlaylist(self["list"].getCurrent()[0]):
+                               self.list.remove(self["list"].getCurrent())
+                               self["list"].setList(self.list)
+
+
+       def addPlaylist(self):
+               self.session.openWithCallback(self.addCallback, YouTubeAddPlaylistDialog)
+
+
+       def addCallback(self, result, playlistContext):
+               if result:
+                       entry = interface.addPlaylist(playlistContext.name.value, playlistContext.description.value, playlistContext.private.value)
+                       self.list.append(YouTubePlaylistEntryComponent(entry))
+                       self["list"].setList(self.list)
+
+
+       def close(self):
+               Screen.close(self, None)
diff --git a/youtubeplayer/src/YouTubePlayer.py b/youtubeplayer/src/YouTubePlayer.py
new file mode 100644 (file)
index 0000000..1a367f8
--- /dev/null
@@ -0,0 +1,60 @@
+############################################################################
+#    Copyright (C) 2008 by Volker Christian                                #
+#    Volker.Christian@fh-hagenberg.at                                      #
+#                                                                          #
+#    This program is free software; you can redistribute it and#or modify  #
+#    it under the terms of the GNU General Public License as published by  #
+#    the Free Software Foundation; either version 2 of the License, or     #
+#    (at your option) any later version.                                   #
+#                                                                          #
+#    This program is distributed in the hope that it will be useful,       #
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of        #
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         #
+#    GNU General Public License for more details.                          #
+#                                                                          #
+#    You should have received a copy of the GNU General Public License     #
+#    along with this program; if not, write to the                         #
+#    Free Software Foundation, Inc.,                                       #
+#    59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             #
+############################################################################
+
+from Plugins.Extensions.VlcPlayer.VlcPlayer import VlcPlayer
+from Components.ActionMap import ActionMap
+
+from YouTubeContextMenu import YouTubeEntryContextMenu, YouTubeEntryContextMenuList
+
+
+class YouTubePlayer(VlcPlayer):
+       def __init__(self, session, server, currentList, contextMenuEntries, infoCallback, name):
+               VlcPlayer.__init__(self, session, server, currentList)
+               self.contextMenuEntries = contextMenuEntries
+               self.infoCallback = infoCallback
+               self.name = name
+
+               self["menuactions"] = ActionMap(["YouTubePlayerScreenActions"],
+               {
+                       "menu"  :       self.openContextMenu,
+                       "info"  :       self.showVideoInfo,
+               }, -1)
+
+
+       def showVideoInfo(self):
+               if self.shown:
+                       self.hideInfobar()
+               self.infoCallback()
+
+
+       def openContextMenu(self):
+               if self.shown:
+                       self.hideInfobar()
+               contextMenuList = YouTubeEntryContextMenuList()
+               for entry in self.contextMenuEntries:
+                       contextMenuList.appendEntry(entry)
+               self.session.openWithCallback(self.menuActionCoosen, YouTubeEntryContextMenu, contextMenuList, self.name)
+
+
+       def menuActionCoosen(self, cookie):
+               if cookie is not None:
+                       if cookie[1]:
+                               self.stop()
+                       cookie[0]()
diff --git a/youtubeplayer/src/YouTubeSearchDialog.py b/youtubeplayer/src/YouTubeSearchDialog.py
new file mode 100644 (file)
index 0000000..c12ded7
--- /dev/null
@@ -0,0 +1,158 @@
+############################################################################
+#    Copyright (C) 2008 by Volker Christian                                #
+#    Volker.Christian@fh-hagenberg.at                                      #
+#                                                                          #
+#    This program is free software; you can redistribute it and#or modify  #
+#    it under the terms of the GNU General Public License as published by  #
+#    the Free Software Foundation; either version 2 of the License, or     #
+#    (at your option) any later version.                                   #
+#                                                                          #
+#    This program is distributed in the hope that it will be useful,       #
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of        #
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         #
+#    GNU General Public License for more details.                          #
+#                                                                          #
+#    You should have received a copy of the GNU General Public License     #
+#    along with this program; if not, write to the                         #
+#    Free Software Foundation, Inc.,                                       #
+#    59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             #
+############################################################################
+
+from Screens.Screen import Screen
+
+from Components.config import Config
+from Components.config import ConfigText
+from Components.config import getConfigListEntry
+from Components.ConfigList import ConfigListScreen
+from Components.ActionMap import ActionMap
+from Components.Button import Button
+
+from ConfigTextWithSuggestions import ConfigTextWithSuggestions
+
+from . import _
+
+searchContext = Config()
+searchContext.searchTerm = ConfigTextWithSuggestions("", False, threaded = True)
+
+
+SEARCH         = 1
+STDFEEDS       = 2
+PLAYLISTS      = 3
+FAVORITES      = 4
+CANCEL         = 5
+
+
+class YouTubeSearchDialog(Screen, ConfigListScreen):
+       def __init__(self, session):
+               Screen.__init__(self, session)
+
+               self.session = session
+
+               self.propagateUpDownNormally = True
+               
+               self["actions"] = ActionMap(["YouTubeSearchDialogActions"],
+               {
+                       "standard"      :       self.keyStdFeeds,
+                       "search"        :       self.keySearch,
+                       "playlists"     :       self.keyPlaylists,
+                       "favorites"     :       self.keyFavorites,
+
+                       "cancel"        :       self.keyCancel,
+                       "left"          :       self.keyLeft,
+                       "right"         :       self.keyRight,
+                       "up"            :       self.keyUp,
+                       "down"          :       self.keyDown,
+               }, -2)
+
+               self["key_red"] = Button(_("Std.Feeds"))
+               self["key_green"] = Button(_("Search"))
+               self["key_yellow"] = Button(_("Playlists"))
+               self["key_blue"] = Button(_("Favorites"))
+
+               searchContextEntries = []
+               searchContextEntries.append(getConfigListEntry(_("Search Term(s)"), searchContext.searchTerm))
+
+               ConfigListScreen.__init__(self, searchContextEntries, session)
+
+
+       def keyOK(self):
+               if isinstance(self["config"].getCurrent()[1], ConfigTextWithSuggestions):
+                       if not self.propagateUpDownNormally:
+                               self.propagateUpDownNormally = True
+                               self["config"].getCurrent()[1].deactivateSuggestionList()
+                       else:
+                               if self["config"].getCurrent()[1].activateSuggestionList():
+                                       self.propagateUpDownNormally = False
+                       self["config"].invalidateCurrent()
+               else:
+                       ConfigListScreen.keyOK(self)
+
+
+       def keyUp(self):
+               if self.propagateUpDownNormally:
+                       self["config"].instance.moveSelection(self["config"].instance.moveUp)
+               else:
+                       self["config"].getCurrent()[1].suggestionListUp()
+                       self["config"].invalidateCurrent()
+
+
+       def keyDown(self):
+               if self.propagateUpDownNormally:
+                       self["config"].instance.moveSelection(self["config"].instance.moveDown)
+               else:
+                       self["config"].getCurrent()[1].suggestionListDown()
+                       self["config"].invalidateCurrent()
+
+
+       def keyRight(self):
+               if self.propagateUpDownNormally:
+                       ConfigListScreen.keyRight(self)
+               else:
+                       self["config"].getCurrent()[1].suggestionListPageDown()
+                       self["config"].invalidateCurrent()
+
+
+       def keyLeft(self):
+               if self.propagateUpDownNormally:
+                       ConfigListScreen.keyLeft(self)
+               else:
+                       self["config"].getCurrent()[1].suggestionListPageUp()
+                       self["config"].invalidateCurrent()
+
+
+       def keyCancel(self):
+               if self.propagateUpDownNormally:
+                       self.close(CANCEL)
+               else:
+                       self.propagateUpDownNormally = True
+                       self["config"].getCurrent()[1].cancelSuggestionList()
+                       self["config"].invalidateCurrent()
+
+
+       def keySearch(self):
+               if searchContext.searchTerm.value != "":
+                       if isinstance(self["config"].getCurrent()[1], ConfigTextWithSuggestions) and not self.propagateUpDownNormally:
+                               self.propagateUpDownNormally = True
+                               self["config"].getCurrent()[1].deactivateSuggestionList()
+                       self.close(SEARCH, searchContext)
+
+
+       def keyStdFeeds(self):
+               if isinstance(self["config"].getCurrent()[1], ConfigTextWithSuggestions) and not self.propagateUpDownNormally:
+                       self.propagateUpDownNormally = True
+                       self["config"].getCurrent()[1].deactivateSuggestionList()
+               self.close(STDFEEDS)
+
+
+       def keyPlaylists(self):
+               if isinstance(self["config"].getCurrent()[1], ConfigTextWithSuggestions) and not self.propagateUpDownNormally:
+                       self.propagateUpDownNormally = True
+                       self["config"].getCurrent()[1].deactivateSuggestionList()
+               self.close(PLAYLISTS)
+
+
+       def keyFavorites(self):
+               if isinstance(self["config"].getCurrent()[1], ConfigTextWithSuggestions) and not self.propagateUpDownNormally:
+                       self.propagateUpDownNormally = True
+                       self["config"].getCurrent()[1].deactivateSuggestionList()
+               self.close(FAVORITES)
diff --git a/youtubeplayer/src/YouTubeStdFeedSelection.py b/youtubeplayer/src/YouTubeStdFeedSelection.py
new file mode 100644 (file)
index 0000000..d35f34a
--- /dev/null
@@ -0,0 +1,58 @@
+############################################################################
+#    Copyright (C) 2008 by Volker Christian                                #
+#    Volker.Christian@fh-hagenberg.at                                      #
+#                                                                          #
+#    This program is free software; you can redistribute it and#or modify  #
+#    it under the terms of the GNU General Public License as published by  #
+#    the Free Software Foundation; either version 2 of the License, or     #
+#    (at your option) any later version.                                   #
+#                                                                          #
+#    This program is distributed in the hope that it will be useful,       #
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of        #
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         #
+#    GNU General Public License for more details.                          #
+#                                                                          #
+#    You should have received a copy of the GNU General Public License     #
+#    along with this program; if not, write to the                         #
+#    Free Software Foundation, Inc.,                                       #
+#    59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             #
+############################################################################
+
+from Screens.Screen import Screen
+from Components.Sources.List import List
+from Components.ActionMap import ActionMap
+from Components.Sources.StaticText import StaticText
+
+from . import _
+
+class YouTubeStdFeedSelectionScreen(Screen):
+       STD_FEED = "http://gdata.youtube.com/feeds/api/standardfeeds/"
+       
+       def __init__(self, session):
+               Screen.__init__(self, session)
+
+               self["actions"] = ActionMap(["OkCancelActions"], 
+                       {
+                               "ok"            :       self.ok,
+                               "cancel"        :       self.close
+                       })
+
+               menu = [(_("Most Viewed"), "most_viewed")]
+               menu.append((_("Top Rated"), "top_rated"))
+               menu.append((_("Recently Featured"), "recently_featured"))
+               menu.append((_("Watch On Mobile"), "watch_on_mobile"))
+               menu.append((_("Most Discussed"), "most_discussed"))
+               menu.append((_("Top Favorites"), "top_favorites"))
+               menu.append((_("Most Linked"), "most_linked"))
+               menu.append((_("Most Responded"), "most_responded"))
+               menu.append((_("Most Recent"), "most_recent"))
+
+               self["menu"] = List(menu)
+
+
+       def ok(self):
+               Screen.close(self, self.STD_FEED + self["menu"].getCurrent()[1])
+
+
+       def close(self):
+               Screen.close(self, None)
\ No newline at end of file
diff --git a/youtubeplayer/src/YouTubeUserConfig.py b/youtubeplayer/src/YouTubeUserConfig.py
new file mode 100644 (file)
index 0000000..9fbec23
--- /dev/null
@@ -0,0 +1,135 @@
+############################################################################
+#    Copyright (C) 2008 by Volker Christian                                #
+#    Volker.Christian@fh-hagenberg.at                                      #
+#                                                                          #
+#    This program is free software; you can redistribute it and#or modify  #
+#    it under the terms of the GNU General Public License as published by  #
+#    the Free Software Foundation; either version 2 of the License, or     #
+#    (at your option) any later version.                                   #
+#                                                                          #
+#    This program is distributed in the hope that it will be useful,       #
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of        #
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         #
+#    GNU General Public License for more details.                          #
+#                                                                          #
+#    You should have received a copy of the GNU General Public License     #
+#    along with this program; if not, write to the                         #
+#    Free Software Foundation, Inc.,                                       #
+#    59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             #
+############################################################################
+
+from Components.ActionMap import ActionMap
+from Components.Button import Button
+from Components.ConfigList import ConfigListScreen
+from Components.config import ConfigInteger
+from Components.config import ConfigSubsection
+from Components.config import ConfigSubList
+from Components.config import ConfigText
+from Components.config import config
+from Components.config import getConfigListEntry
+from Screens.Screen import Screen
+from YouTubeInterface import YouTubeUser
+
+from . import _
+
+# This should be executed only once during an enigma2-session
+config.plugins.youtubeplayer = ConfigSubsection()
+config.plugins.youtubeplayer.serverprofile = ConfigText("", False)
+
+class __YouTubeUserConfig():
+       def __init__(self):
+               self.userlist = []
+               config.plugins.youtubeplayer.usercount = ConfigInteger(0)
+               config.plugins.youtubeplayer.users = ConfigSubList()
+               config.plugins.youtubeplayer.defaultuser = ConfigText("", False)
+               for usernum in range(0, config.plugins.youtubeplayer.usercount.value):
+                       self.new()
+
+
+       # Add a new server or load a configsection if existing
+       def new(self):
+               newUserConfigSubsection = ConfigSubsection()
+               config.plugins.youtubeplayer.users.append(newUserConfigSubsection)
+               newUserConfigSubsection.name = ConfigText("User " + str(self.__getUserCount()), False)
+               if newUserConfigSubsection.name.value == newUserConfigSubsection.name.default:
+                       newUserConfigSubsection.name.default = ""
+               newUserConfigSubsection.email = ConfigText("", False)
+               newUserConfigSubsection.password = ConfigText("", False)
+               
+               newUser = YouTubeUser(newUserConfigSubsection)
+
+               self.userlist.append(newUser)
+
+               return newUser
+
+       # Add was canceled or existing server should be removed
+       def delete(self, user):
+               config.plugins.youtubeplayer.users.remove(user.getCfg())
+               self.userlist.remove(user)
+               self.__save()
+
+       # Edit or Add should complete
+       def save(self, user):
+               user.getCfg().save()
+               self.__save()
+
+       # Edit has been canceled
+       def cancel(self, user):
+               for element in user.getCfg().dict().values():
+                       element.cancel()
+
+       def getUserlist(self):
+               return self.userlist
+
+       def getUserByName(self, name):
+               for user in self.userlist:
+                       if user.getName() == name:
+                               return user
+               return None
+
+       def getDefaultUser(self):
+               return self.getUserByName(config.plugins.youtubeplayer.defaultuser.value)
+
+       def setAsDefault(self, defaultUser):
+               if defaultUser is not None:
+                       config.plugins.youtubeplayer.defaultuser.value = defaultUser.getName()
+                       config.plugins.youtubeplayer.defaultuser.save()
+
+       def __save(self):
+               config.plugins.youtubeplayer.usercount.value = self.__getUserCount()
+               config.plugins.youtubeplayer.usercount.save()
+
+       def __getUserCount(self):
+               return len(config.plugins.youtubeplayer.users)
+
+
+youTubeUserConfig = __YouTubeUserConfig()
+
+
+class YouTubeUserConfigScreen(Screen, ConfigListScreen):
+       def __init__(self, session, user):
+               Screen.__init__(self, session)
+               self.user = user
+               self["actions"] = ActionMap(["YouTubeUserConfigScreenActions"],
+               {
+                       "save"          :       self.keySave,
+                       "cancel"        :       self.keyCancel
+               }, -2)
+
+               self["key_red"] = Button(_("Cancel"))
+               self["key_green"] = Button(_("Save"))
+               self["key_yellow"] = Button("")
+               self["key_blue"] = Button("")
+
+               cfglist = []
+               cfglist.append(getConfigListEntry(_("User Profile Name"), user.name()))
+               cfglist.append(getConfigListEntry(_("E-Mail Address"), user.email()))
+               cfglist.append(getConfigListEntry(_("Password"), user.password()))
+
+               ConfigListScreen.__init__(self, cfglist, session)
+
+       def keySave(self):
+               self.close(True, self.user)
+
+       def keyCancel(self):
+               self.close(False, self.user)
diff --git a/youtubeplayer/src/YouTubeUserList.py b/youtubeplayer/src/YouTubeUserList.py
new file mode 100644 (file)
index 0000000..a29bfd2
--- /dev/null
@@ -0,0 +1,191 @@
+############################################################################
+#    Copyright (C) 2008 by Volker Christian                                #
+#    Volker.Christian@fh-hagenberg.at                                      #
+#                                                                          #
+#    This program is free software; you can redistribute it and#or modify  #
+#    it under the terms of the GNU General Public License as published by  #
+#    the Free Software Foundation; either version 2 of the License, or     #
+#    (at your option) any later version.                                   #
+#                                                                          #
+#    This program is distributed in the hope that it will be useful,       #
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of        #
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         #
+#    GNU General Public License for more details.                          #
+#                                                                          #
+#    You should have received a copy of the GNU General Public License     #
+#    along with this program; if not, write to the                         #
+#    Free Software Foundation, Inc.,                                       #
+#    59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             #
+############################################################################
+
+from Components.ActionMap import ActionMap
+from Components.Button import Button
+from Components.Label import Label
+from Components.MenuList import MenuList
+from Screens.MessageBox import MessageBox
+from Screens.Screen import Screen
+from Tools.Directories import resolveFilename, SCOPE_PLUGINS
+from Tools.LoadPixmap import LoadPixmap
+from YouTubeUserConfig import youTubeUserConfig
+from YouTubeUserConfig import YouTubeUserConfigScreen
+from enigma import eListboxPythonMultiContent, RT_HALIGN_LEFT, gFont
+
+from . import _
+
+def YouTubeUserListEntry(youTubeUser, defaultUser):
+       res = [ youTubeUser ]
+       res.append((eListboxPythonMultiContent.TYPE_TEXT, 35, 1, 470, 20, 0, RT_HALIGN_LEFT, youTubeUser.getName()))
+
+       if defaultUser is not None and defaultUser.getName() == youTubeUser.getName():
+               png = LoadPixmap(resolveFilename(SCOPE_PLUGINS, "Extensions/YouTubePlayer/user_default.png"))
+       else:
+               png = LoadPixmap(resolveFilename(SCOPE_PLUGINS, "Extensions/YouTubePlayer/user.png"))
+       if png is not None:
+               res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, 10, 2, 20, 20, png))
+
+       return res
+
+
+class YouTubeUserList(MenuList):
+       def __init__(self):
+               MenuList.__init__(self, list, False, eListboxPythonMultiContent)
+               self.l.setFont(0, gFont("Regular", 18))
+               self.l.setItemHeight(23)
+
+       def update(self, userList, defaultUser):
+               self.list = []
+               for user in userList:
+                       self.list.append(YouTubeUserListEntry(user, defaultUser))
+               self.l.setList(self.list)
+               self.moveToIndex(0)
+
+       def getSelection(self):
+               if self.l.getCurrentSelection() is None:
+                       return None
+               return self.l.getCurrentSelection()[0]
+
+
+class YouTubeUserListScreen(Screen):
+       LOGIN_SUCCESS = 1
+       LOGIN_CANCEL = 2
+       LOGIN_FAILED = 3
+
+       def __init__(self, session, defaultUser):
+               Screen.__init__(self, session)
+               self.session = session
+               self.userlist = YouTubeUserList()
+               self.defaultUser = defaultUser
+
+               self["label_info"] = Label(_("To use the selected feature you have to login to YouTube. Select a user-profile to login!"))
+               self["userlist"] = self.userlist
+               self["key_red"] = Button(_("delete user"))
+               self["key_green"] = Button(_("add user"))
+               self["key_yellow"] = Button(_("edit user"))
+               self["key_blue"] = Button(_("set default"))
+
+               self["actions"] = ActionMap(["YouTubeUserListScreenActions"],
+               {
+                       "delete":       self.keyDelete,
+                       "add":          self.keyAddUser,
+                       "edit":         self.keyEditUser,
+                       "default":      self.keySetAsDefault,
+                       
+                       "ok":           self.ok,
+                       "cancel":       self.close,
+                       "up":           self.up,
+                       "down":         self.down,
+                       "left":         self.left,
+                       "right":        self.right,
+               }, -2)
+               
+               self.onLayoutFinish.append(self.initialUserlistUpdate)
+
+
+       def showTestScreen(self):
+               self.suggestionsWindow.show()
+
+
+       def initialUserlistUpdate(self):
+               self.updateUserlist()
+               if self.defaultUser is not None:
+                       defaultIndex = youTubeUserConfig.getUserlist().index(self.defaultUser)
+                       self.userlist.moveToIndex(defaultIndex)
+
+
+       def updateUserlist(self):
+               self.userlist.update(youTubeUserConfig.getUserlist(), self.defaultUser)
+
+
+       def keyDelete(self):
+               user = self.userlist.getSelection()
+               if user is not None:
+                       self.session.openWithCallback(self.deleteCallback, MessageBox, _("Really delete %(user)s?") % {"user" : user.getName()})
+
+       def deleteCallback(self, result):
+               if result:
+                       youTubeUserConfig.delete(self.userlist.getSelection())
+                       self.updateUserlist()
+
+
+       def keyAddUser(self):
+               newUser = youTubeUserConfig.new()
+               self.session.openWithCallback(self.addCallback, YouTubeUserConfigScreen, newUser)
+
+
+       def addCallback(self, result, user):
+               if result:
+                       youTubeUserConfig.save(user)
+                       self.updateUserlist()
+               else:
+                       youTubeUserConfig.delete(user)
+
+
+       def keyEditUser(self):
+               user = self.userlist.getSelection()
+               if user is not None:
+                       self.session.openWithCallback(self.editCallback, YouTubeUserConfigScreen, user)
+
+
+       def editCallback(self, result, user):
+               if result:
+                       youTubeUserConfig.save(user)
+                       index = self.userlist.getSelectedIndex()
+                       self.updateUserlist()
+                       self.userlist.moveToIndex(index)
+               else:
+                       youTubeUserConfig.cancel(user)
+
+
+       def keySetAsDefault(self):
+               self.defaultUser = self.userlist.getSelection()
+               index = self.userlist.getSelectedIndex()
+               self.updateUserlist()
+               self.userlist.moveToIndex(index)
+
+
+       def up(self):
+               self.userlist.up()
+
+
+       def down(self):
+               self.userlist.down()
+
+
+       def left(self):
+               self.userlist.pageUp()
+
+
+       def right(self):
+               self.userlist.pageDown()
+
+
+       def close(self, loginState = LOGIN_CANCEL):
+               youTubeUserConfig.setAsDefault(self.defaultUser)
+               Screen.close(self, loginState)
+
+
+       def ok(self):
+               if self.userlist.getSelection().login():
+                       self.close(YouTubeUserListScreen.LOGIN_SUCCESS)
+               else:
+                       self.close(YouTubeUserListScreen.LOGIN_FAILED)
diff --git a/youtubeplayer/src/__init__.py b/youtubeplayer/src/__init__.py
new file mode 100644 (file)
index 0000000..54e0295
--- /dev/null
@@ -0,0 +1,29 @@
+# -*- coding: ISO-8859-1 -*-
+#===============================================================================
+# YouTube Plugin by Volker Christian 2008
+#
+# This is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2, or (at your option) any later
+# version.
+#===============================================================================
+
+from Components.Language import language
+from Tools.Directories import resolveFilename, SCOPE_PLUGINS, SCOPE_LANGUAGE
+import os,gettext
+
+def localeInit():
+    lang = language.getLanguage()[:2] # getLanguage returns e.g. "fi_FI" for "language_country"
+    os.environ["LANGUAGE"] = lang # Enigma doesn't set this (or LC_ALL, LC_MESSAGES, LANG). gettext needs it!
+    gettext.bindtextdomain("enigma2", resolveFilename(SCOPE_LANGUAGE))
+    gettext.textdomain("enigma2")
+    gettext.bindtextdomain("YouTubePlayer", resolveFilename(SCOPE_PLUGINS, "Extensions/YouTubePlayer/locale"))
+
+def _(txt):
+    t = gettext.dgettext("YouTubePlayer", txt)
+    if t == txt:
+        print "[YTB] fallback to default translation for", txt
+        t = gettext.gettext(txt)
+    return t
+
+localeInit()
diff --git a/youtubeplayer/src/keymap.xml b/youtubeplayer/src/keymap.xml
new file mode 100644 (file)
index 0000000..4ce8b0f
--- /dev/null
@@ -0,0 +1,109 @@
+<keymap>
+<!--
+"m" kommt einmal sobald die taste gedrueckt wurde.
+"r" kommt dann nach "m" wenn man die taste feshaelt.. und das solange bis man die taste loslaesst,
+"l" kommt nachdem 5 repeats kamen..aber nur exakt einmal (repeat kommt dann trotzdem weiter..)
+"b" kommt nachdem man die taste losgelassen hat.
+
+Wenn man nun also ein Fenster mit "m" oeffnet.. dann kann man im selben context r, l, b nicht mehr benutzen.
+Deshalb muss man dann halt das Fenster erst auf "b" oeffnen..
+-->
+       <map context = "YouTubeAddPlaylistActions">
+               <key id = "KEY_GREEN"   mapto = "save"          flags = "m" />
+               <key id = "KEY_RED"     mapto = "cancel"        flags = "m" />
+               <key id = "KEY_EXIT"    mapto = "cancel"        flags = "m" />
+               <key id = "KEY_ESC"             mapto = "cancel"        flags = "m" />
+       </map>
+
+       <map context = "YouTubeVideoDetailsScreenActions">
+               <key id = "KEY_LEFT"    mapto = "left"          flags = "mr" />
+               <key id = "KEY_RIGHT"   mapto = "right"         flags = "mr" />
+               <key id = "KEY_UP"              mapto = "up"            flags = "mr" />
+               <key id = "KEY_DOWN"    mapto = "down"          flags = "mr" />
+               
+               <key id = "KEY_OK"              mapto = "ok"            flags = "m" />
+               <key id = "KEY_EXIT"    mapto = "cancel"        flags = "m" />
+               
+               <key id = "KEY_ENTER"   mapto = "ok"            flags = "m" />
+               <key id = "KEY_ESC"             mapto = "cancel"        flags = "m" />
+       </map>
+
+       <map context = "YouTubeVideoListActions">
+               <key id = "KEY_OK"              mapto = "play"          flags = "m" />
+               <key id = "KEY_ENTER"   mapto = "play"          flags = "m" />
+               
+               <key id = "KEY_RED"             mapto = "select"        flags = "m" />
+               <key id = "KEY_GREEN"   mapto = "search"        flags = "m" />
+
+               <key id = "KEY_MENU"    mapto = "menu"          flags = "m" />
+               
+               <key id = "KEY_CHANNELUP"       mapto = "forward"       flags = "m" />
+               <key id = "KEY_CHANNELDOWN"     mapto = "backward"      flags = "m" />
+               
+               <key id = "KEY_LEFT"    mapto = "left"          flags = "mr" />
+               <key id = "KEY_RIGHT"   mapto = "right"         flags = "mr" />
+               <key id = "KEY_UP"              mapto = "up"            flags = "mr" />
+               <key id = "KEY_DOWN"    mapto = "down"          flags = "mr" />
+
+               <key id = "KEY_INFO"    mapto = "info"          flags = "m" />
+               
+               <key id = "KEY_EXIT"    mapto = "cancel"        flags = "m" />
+               <key id = "KEY_ESC"             mapto = "cancel"        flags = "m" />
+       </map>
+
+       <map context = "YouTubePlayerScreenActions">
+               <key id = "KEY_MENU"    mapto = "menu"          flags = "m" />
+               <key id = "KEY_INFO"    mapto = "info"          flags = "m" />
+       </map>
+       
+       <map context = "YouTubePlaylistScreenActions">
+               <key id = "KEY_OK"              mapto = "ok"            flags = "m" />
+               <key id = "KEY_EXIT"    mapto = "cancel"        flags = "m" />
+               
+               <key id = "KEY_ENTER"   mapto = "ok"            flags = "m" />
+               <key id = "KEY_ESC"             mapto = "cancel"        flags = "m" />
+               
+               <key id = "KEY_GREEN"   mapto = "add"           flags = "m" />
+               <key id = "KEY_RED"     mapto = "delete"        flags = "m" />
+       </map>
+
+       <map context = "YouTubeSearchDialogActions">
+               <key id = "KEY_RED"             mapto = "standard"      flags = "m" />
+               <key id = "KEY_GREEN"   mapto = "search"        flags = "m" />
+               <key id = "KEY_BLUE"    mapto = "favorites"     flags = "m" />
+               <key id = "KEY_YELLOW"  mapto = "playlists"     flags = "m" />
+               
+               <key id = "KEY_ESC"             mapto = "cancel"        flags = "m" />
+               <key id = "KEY_EXIT"    mapto = "cancel"        flags = "m" />
+               
+               <key id = "KEY_LEFT"    mapto = "left"          flags = "mr" />
+               <key id = "KEY_RIGHT"   mapto = "right"         flags = "mr" />
+               <key id = "KEY_UP"              mapto = "up"            flags = "mr" />
+               <key id = "KEY_DOWN"    mapto = "down"          flags = "mr" />
+       </map>
+
+       <map context = "YouTubeUserConfigScreenActions">
+               <key id = "KEY_GREEN"   mapto = "save"          flags = "m" />
+               <key id = "KEY_RED"             mapto = "cancel"        flags = "m" />
+               <key id = "KEY_EXIT"    mapto = "cancel"        flags = "m" />
+               <key id = "KEY_ESC"             mapto = "cancel"        flags = "m" />
+       </map>
+
+       <map context = "YouTubeUserListScreenActions">
+               <key id = "KEY_RED"             mapto = "delete"        flags = "m" />
+               <key id = "KEY_GREEN"   mapto = "add"           flags = "m" />
+               <key id = "KEY_BLUE"    mapto = "default"       flags = "m" />
+               <key id = "KEY_YELLOW"  mapto = "edit"          flags = "m" />
+               
+               <key id = "KEY_OK"              mapto = "ok"            flags = "m" />
+               <key id = "KEY_EXIT"    mapto = "cancel"        flags = "m" />
+               
+               <key id = "KEY_ENTER"   mapto = "ok"            flags = "m" />
+               <key id = "KEY_ESC"             mapto = "cancel"        flags = "m" />
+               
+               <key id = "KEY_LEFT"    mapto = "left"          flags = "mr" />
+               <key id = "KEY_RIGHT"   mapto = "right"         flags = "mr" />
+               <key id = "KEY_UP"              mapto = "up"            flags = "mr" />
+               <key id = "KEY_DOWN"    mapto = "down"          flags = "mr" />
+       </map>
+</keymap>
diff --git a/youtubeplayer/src/locale/de/LC_MESSAGES/YouTubePlayer.mo b/youtubeplayer/src/locale/de/LC_MESSAGES/YouTubePlayer.mo
new file mode 100644 (file)
index 0000000..9e05d6e
Binary files /dev/null and b/youtubeplayer/src/locale/de/LC_MESSAGES/YouTubePlayer.mo differ
diff --git a/youtubeplayer/src/locale/de/YouTubePlayer.po b/youtubeplayer/src/locale/de/YouTubePlayer.po
new file mode 100644 (file)
index 0000000..c9d9f23
--- /dev/null
@@ -0,0 +1,286 @@
+# translation of YouTubePlayer.po to German
+# translation of YouTubePlayer_old.po to
+# translation of YouTubePlayer.po to
+# translation of messages.po to
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Volker Christian <Volker.Christian@fh-hagenberg.at>, 2008.
+msgid ""
+msgstr ""
+"Project-Id-Version: YouTubePlayer\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2008-08-09 16:00+0200\n"
+"PO-Revision-Date: 2008-08-09 16:34+0200\n"
+"Last-Translator: Volker Christian <Volker.Christian@fh-hagenberg.at>\n"
+"Language-Team: German <en@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#: ../plugin.py:103 ../plugin.py:123 ../YouTubeList.py:442
+#: ../YouTubeList.py:464 ../YouTubeList.py:486 ../YouTubeList.py:512
+msgid "Login not successful"
+msgstr "Login nicht erfolgreich"
+
+#: ../plugin.py:146
+msgid "Search and play YouTube movies"
+msgstr "Videos auf YouTube suchen und abspielen"
+
+#: ../YouTubeAddPlayList.py:36
+msgid "Name"
+msgstr "Name"
+
+#: ../YouTubeAddPlayList.py:37
+msgid "Description"
+msgstr "Beschreibung "
+
+#: ../YouTubeAddPlayList.py:53 ../YouTubeUserConfig.py:119
+msgid "Cancel"
+msgstr "Abbrechen"
+
+#: ../YouTubeAddPlayList.py:54 ../YouTubeUserConfig.py:120
+msgid "Save"
+msgstr "Speichern"
+
+#: ../YouTubeAddPlayList.py:59
+msgid "Playlist Name"
+msgstr "Playlistenname"
+
+#: ../YouTubeAddPlayList.py:60
+msgid "Playlist Description"
+msgstr "Playlistenbeschreibung"
+
+#: ../YouTubeAddPlayList.py:61
+msgid "private"
+msgstr "privat"
+
+#: ../YouTubeList.py:83
+msgid "Duration"
+msgstr "Dauer"
+
+#: ../YouTubeList.py:86
+msgid "Rate"
+msgstr "Güte"
+
+#: ../YouTubeList.py:90
+msgid "Ratings"
+msgstr "Bewerter"
+
+#: ../YouTubeList.py:93
+msgid "Favorited"
+msgstr "Favoriten"
+
+#: ../YouTubeList.py:96
+msgid "Views"
+msgstr "Gesehen"
+
+#: ../YouTubeList.py:99
+msgid "Author:"
+msgstr "Autor"
+
+#: ../YouTubeList.py:102
+msgid "Added"
+msgstr "Datum"
+
+#: ../YouTubeList.py:105
+msgid "Category"
+msgstr "Rubrik"
+
+#: ../YouTubeList.py:107
+msgid "Tags"
+msgstr "Marken"
+
+#: ../YouTubeList.py:211
+msgid "Select a VLC-Server"
+msgstr "VLC-Server wählen"
+
+#: ../YouTubeList.py:212
+msgid "New YouTube search"
+msgstr "Neue YouTube-Suche"
+
+#: ../YouTubeList.py:217
+msgid "Total results"
+msgstr "Gesamtzahl"
+
+#: ../YouTubeList.py:220
+msgid "Shown"
+msgstr "Angezeigt"
+
+#: ../YouTubeList.py:253 ../YouTubeList.py:264
+msgid "Load further entries of current Feed?"
+msgstr "Weitere Einträge des aktuellen Feeds laden?"
+
+#: ../YouTubeList.py:312
+msgid "Searching, be patient ..."
+msgstr "Suche läuft, bitte haben Sie geduld ..."
+
+#: ../YouTubeList.py:324
+msgid "Loading playlist, be patient ..."
+msgstr "Playliste wird geladen, bitte haben Sie geduld ..."
+
+#: ../YouTubeList.py:335
+msgid "Loading favorits, be patient ..."
+msgstr "Favoriten werden geladen, bitte haben Sie geduld ..."
+
+#: ../YouTubeList.py:341
+msgid "Loading standard feed, be patient ..."
+msgstr "Standardfeed wird geladen, bitte haben Sie geduld ..."
+
+#: ../YouTubeList.py:362 ../YouTubeList.py:370
+msgid "Loading additional videos, be patient ..."
+msgstr "Weitere Videos werden geladen, bitte haben Sie geduld ..."
+
+#: ../YouTubeList.py:374
+msgid "Loading related videos, be patient ..."
+msgstr "Ähnliche Videos werden geladen, bitte haben Sie geduld ... "
+
+#: ../YouTubeList.py:379
+msgid "Loading response videos, be patient ..."
+msgstr "Antwortvideos werden geladen, bitte haben Sie geduld ..."
+
+#: ../YouTubeList.py:386
+msgid "Back in history, be patient ..."
+msgstr "Zurück in der Historie, bitte haben Sie geduld"
+
+#: ../YouTubeList.py:392
+msgid "Forward in history, be patient ..."
+msgstr "Vorwärts in der Historie, bitte haben Sie geduld"
+
+#: ../YouTubeList.py:546 ../YouTubeList.py:585
+msgid "Show video detail info"
+msgstr "Video-Detailinformation anzeigen"
+
+#: ../YouTubeList.py:548 ../YouTubeList.py:587
+msgid "Remove from favorites"
+msgstr "Von Favoriten löschen"
+
+#: ../YouTubeList.py:550 ../YouTubeList.py:589
+msgid "Add to favorites"
+msgstr "Zu Fovoriten hinzufügen"
+
+#: ../YouTubeList.py:553 ../YouTubeList.py:591
+msgid "Remove from playlist"
+msgstr "Von Wiedergabeliste löschen"
+
+#: ../YouTubeList.py:555 ../YouTubeList.py:593
+msgid "Add to playlist"
+msgstr "Zu Wiedergabeliste hinzufügen"
+
+#: ../YouTubeList.py:556 ../YouTubeList.py:594
+msgid "Get related videos"
+msgstr "Ähnliche Videos laden"
+
+#: ../YouTubeList.py:557 ../YouTubeList.py:595
+msgid "Get video responses"
+msgstr "Antwortvideos laden"
+
+#: ../YouTubePlayList.py:57
+msgid "Delete Playlist"
+msgstr "Playliste löschen"
+
+#: ../YouTubePlayList.py:58
+msgid "Add new Playlist"
+msgstr "Playliste hinzufügen"
+
+#: ../YouTubePlayList.py:86
+#, python-format
+msgid "Really delete %(playlist)s?"
+msgstr "%(playlist)s löschen?"
+
+#: ../YouTubeSearchDialog.py:67
+msgid "Std.Feeds"
+msgstr "Std.Feeds"
+
+#: ../YouTubeSearchDialog.py:68
+msgid "Search"
+msgstr "Suchen"
+
+#: ../YouTubeSearchDialog.py:69
+msgid "Playlists"
+msgstr "Playliste"
+
+#: ../YouTubeSearchDialog.py:70
+msgid "Favorites"
+msgstr "Favoriten"
+
+#: ../YouTubeSearchDialog.py:73
+msgid "Search Term(s)"
+msgstr "Suchbegriff(e)"
+
+#: ../YouTubeStdFeedSelection.py:40
+msgid "Most Viewed"
+msgstr "Am häufigsten gesehen"
+
+#: ../YouTubeStdFeedSelection.py:41
+msgid "Top Rated"
+msgstr "Am höchsten bewertet"
+
+#: ../YouTubeStdFeedSelection.py:42
+msgid "Recently Featured"
+msgstr "Kürzlich beworben"
+
+#: ../YouTubeStdFeedSelection.py:43
+msgid "Watch On Mobile"
+msgstr "Auf einem Mobilgerät betrachtbar"
+
+#: ../YouTubeStdFeedSelection.py:44
+msgid "Most Discussed"
+msgstr "Am häufigsten diskutiert"
+
+#: ../YouTubeStdFeedSelection.py:45
+msgid "Top Favorites"
+msgstr "Am häufigsten in Favoriten eingetragen"
+
+#: ../YouTubeStdFeedSelection.py:46
+msgid "Most Linked"
+msgstr "Am häufigsten verlinkt"
+
+#: ../YouTubeStdFeedSelection.py:47
+msgid "Most Responded"
+msgstr "Am häufigsten beantwortet"
+
+#: ../YouTubeStdFeedSelection.py:48
+msgid "Most Recent"
+msgstr "Kürzlich hinzugefügt"
+
+#: ../YouTubeUserConfig.py:125
+msgid "User Profile Name"
+msgstr "Benutzerprofilname"
+
+#: ../YouTubeUserConfig.py:126
+msgid "E-Mail Address"
+msgstr "E-Mail Adresse"
+
+#: ../YouTubeUserConfig.py:127
+msgid "Password"
+msgstr "Passwort"
+
+#: ../YouTubeUserList.py:79
+msgid ""
+"To use the selected feature you have to login to YouTube. Select a user-"
+"profile to login!"
+msgstr "Um diese Funktion nutzen zu können, wählen Sie einen Benutzer und melden Sie sich damit bei YouTube an."
+
+#: ../YouTubeUserList.py:81
+msgid "delete user"
+msgstr "löschen"
+
+#: ../YouTubeUserList.py:82
+msgid "add user"
+msgstr "hinzufügen"
+
+#: ../YouTubeUserList.py:83
+msgid "edit user"
+msgstr "ändern "
+
+#: ../YouTubeUserList.py:84
+msgid "set default"
+msgstr "standard"
+
+#: ../YouTubeUserList.py:122
+#, python-format
+msgid "Really delete %(user)s?"
+msgstr "%(user)s löschen?"
+
diff --git a/youtubeplayer/src/locale/messages.pot b/youtubeplayer/src/locale/messages.pot
new file mode 100755 (executable)
index 0000000..2fdb0db
--- /dev/null
@@ -0,0 +1,282 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2008-08-09 16:00+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../plugin.py:103 ../plugin.py:123 ../YouTubeList.py:442
+#: ../YouTubeList.py:464 ../YouTubeList.py:486 ../YouTubeList.py:512
+msgid "Login not successful"
+msgstr ""
+
+#: ../plugin.py:146
+msgid "Search and play YouTube movies"
+msgstr ""
+
+#: ../YouTubeAddPlayList.py:36
+msgid "Name"
+msgstr ""
+
+#: ../YouTubeAddPlayList.py:37
+msgid "Description"
+msgstr ""
+
+#: ../YouTubeAddPlayList.py:53 ../YouTubeUserConfig.py:119
+msgid "Cancel"
+msgstr ""
+
+#: ../YouTubeAddPlayList.py:54 ../YouTubeUserConfig.py:120
+msgid "Save"
+msgstr ""
+
+#: ../YouTubeAddPlayList.py:59
+msgid "Playlist Name"
+msgstr ""
+
+#: ../YouTubeAddPlayList.py:60
+msgid "Playlist Description"
+msgstr ""
+
+#: ../YouTubeAddPlayList.py:61
+msgid "private"
+msgstr ""
+
+#: ../YouTubeList.py:83
+msgid "Duration"
+msgstr ""
+
+#: ../YouTubeList.py:86
+msgid "Rate"
+msgstr ""
+
+#: ../YouTubeList.py:90
+msgid "Ratings"
+msgstr ""
+
+#: ../YouTubeList.py:93
+msgid "Favorited"
+msgstr ""
+
+#: ../YouTubeList.py:96
+msgid "Views"
+msgstr ""
+
+#: ../YouTubeList.py:99
+msgid "Author:"
+msgstr ""
+
+#: ../YouTubeList.py:102
+msgid "Added"
+msgstr ""
+
+#: ../YouTubeList.py:105
+msgid "Category"
+msgstr ""
+
+#: ../YouTubeList.py:107
+msgid "Tags"
+msgstr ""
+
+#: ../YouTubeList.py:211
+msgid "Select a VLC-Server"
+msgstr ""
+
+#: ../YouTubeList.py:212
+msgid "New YouTube search"
+msgstr ""
+
+#: ../YouTubeList.py:217
+msgid "Total results"
+msgstr ""
+
+#: ../YouTubeList.py:220
+msgid "Shown"
+msgstr ""
+
+#: ../YouTubeList.py:253 ../YouTubeList.py:264
+msgid "Load further entries of current Feed?"
+msgstr ""
+
+#: ../YouTubeList.py:312
+msgid "Searching, be patient ..."
+msgstr ""
+
+#: ../YouTubeList.py:324
+msgid "Loading playlist, be patient ..."
+msgstr ""
+
+#: ../YouTubeList.py:335
+msgid "Loading favorits, be patient ..."
+msgstr ""
+
+#: ../YouTubeList.py:341
+msgid "Loading standard feed, be patient ..."
+msgstr ""
+
+#: ../YouTubeList.py:362 ../YouTubeList.py:370
+msgid "Loading additional videos, be patient ..."
+msgstr ""
+
+#: ../YouTubeList.py:374
+msgid "Loading related videos, be patient ..."
+msgstr ""
+
+#: ../YouTubeList.py:379
+msgid "Loading response videos, be patient ..."
+msgstr ""
+
+#: ../YouTubeList.py:386
+msgid "Back in history, be patient ..."
+msgstr ""
+
+#: ../YouTubeList.py:392
+msgid "Forward in history, be patient ..."
+msgstr ""
+
+#: ../YouTubeList.py:546 ../YouTubeList.py:585
+msgid "Show video detail info"
+msgstr ""
+
+#: ../YouTubeList.py:548 ../YouTubeList.py:587
+msgid "Remove from favorites"
+msgstr ""
+
+#: ../YouTubeList.py:550 ../YouTubeList.py:589
+msgid "Add to favorites"
+msgstr ""
+
+#: ../YouTubeList.py:553 ../YouTubeList.py:591
+msgid "Remove from playlist"
+msgstr ""
+
+#: ../YouTubeList.py:555 ../YouTubeList.py:593
+msgid "Add to playlist"
+msgstr ""
+
+#: ../YouTubeList.py:556 ../YouTubeList.py:594
+msgid "Get related videos"
+msgstr ""
+
+#: ../YouTubeList.py:557 ../YouTubeList.py:595
+msgid "Get video responses"
+msgstr ""
+
+#: ../YouTubePlayList.py:57
+msgid "Delete Playlist"
+msgstr ""
+
+#: ../YouTubePlayList.py:58
+msgid "Add new Playlist"
+msgstr ""
+
+#: ../YouTubePlayList.py:86
+#, python-format
+msgid "Really delete %(playlist)s?"
+msgstr ""
+
+#: ../YouTubeSearchDialog.py:67
+msgid "Std.Feeds"
+msgstr ""
+
+#: ../YouTubeSearchDialog.py:68
+msgid "Search"
+msgstr ""
+
+#: ../YouTubeSearchDialog.py:69
+msgid "Playlists"
+msgstr ""
+
+#: ../YouTubeSearchDialog.py:70
+msgid "Favorites"
+msgstr ""
+
+#: ../YouTubeSearchDialog.py:73
+msgid "Search Term(s)"
+msgstr ""
+
+#: ../YouTubeStdFeedSelection.py:40
+msgid "Most Viewed"
+msgstr ""
+
+#: ../YouTubeStdFeedSelection.py:41
+msgid "Top Rated"
+msgstr ""
+
+#: ../YouTubeStdFeedSelection.py:42
+msgid "Recently Featured"
+msgstr ""
+
+#: ../YouTubeStdFeedSelection.py:43
+msgid "Watch On Mobile"
+msgstr ""
+
+#: ../YouTubeStdFeedSelection.py:44
+msgid "Most Discussed"
+msgstr ""
+
+#: ../YouTubeStdFeedSelection.py:45
+msgid "Top Favorites"
+msgstr ""
+
+#: ../YouTubeStdFeedSelection.py:46
+msgid "Most Linked"
+msgstr ""
+
+#: ../YouTubeStdFeedSelection.py:47
+msgid "Most Responded"
+msgstr ""
+
+#: ../YouTubeStdFeedSelection.py:48
+msgid "Most Recent"
+msgstr ""
+
+#: ../YouTubeUserConfig.py:125
+msgid "User Profile Name"
+msgstr ""
+
+#: ../YouTubeUserConfig.py:126
+msgid "E-Mail Address"
+msgstr ""
+
+#: ../YouTubeUserConfig.py:127
+msgid "Password"
+msgstr ""
+
+#: ../YouTubeUserList.py:79
+msgid ""
+"To use the selected feature you have to login to YouTube. Select a user-"
+"profile to login!"
+msgstr ""
+
+#: ../YouTubeUserList.py:81
+msgid "delete user"
+msgstr ""
+
+#: ../YouTubeUserList.py:82
+msgid "add user"
+msgstr ""
+
+#: ../YouTubeUserList.py:83
+msgid "edit user"
+msgstr ""
+
+#: ../YouTubeUserList.py:84
+msgid "set default"
+msgstr ""
+
+#: ../YouTubeUserList.py:122
+#, python-format
+msgid "Really delete %(user)s?"
+msgstr ""
diff --git a/youtubeplayer/src/plugin.png b/youtubeplayer/src/plugin.png
new file mode 100644 (file)
index 0000000..762c984
Binary files /dev/null and b/youtubeplayer/src/plugin.png differ
diff --git a/youtubeplayer/src/plugin.py b/youtubeplayer/src/plugin.py
new file mode 100644 (file)
index 0000000..431ca97
--- /dev/null
@@ -0,0 +1,140 @@
+############################################################################
+#    Copyright (C) 2008 by Volker Christian                                #
+#    Volker.Christian@fh-hagenberg.at                                      #
+#                                                                          #
+#    This program is free software; you can redistribute it and#or modify  #
+#    it under the terms of the GNU General Public License as published by  #
+#    the Free Software Foundation; either version 2 of the License, or     #
+#    (at your option) any later version.                                   #
+#                                                                          #
+#    This program is distributed in the hope that it will be useful,       #
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of        #
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         #
+#    GNU General Public License for more details.                          #
+#                                                                          #
+#    You should have received a copy of the GNU General Public License     #
+#    along with this program; if not, write to the                         #
+#    Free Software Foundation, Inc.,                                       #
+#    59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             #
+############################################################################
+
+from Plugins.Plugin import PluginDescriptor
+from Tools.BoundFunction import boundFunction
+
+from YouTubeList import YouTubeListScreen
+from YouTubePlayList import YouTubePlaylistScreen
+from YouTubeSearchDialog import YouTubeSearchDialog, SEARCH, STDFEEDS, PLAYLISTS, FAVORITES, CANCEL
+from YouTubeUserList import YouTubeUserListScreen
+from YouTubeUserConfig import youTubeUserConfig
+from YouTubeStdFeedSelection import YouTubeStdFeedSelectionScreen
+from YouTubeInterface import interface, YouTubeInterface
+from SkinLoader import loadPluginSkin
+from Screens.MessageBox import MessageBox
+
+import gettext
+
+
+def _(txt):
+       t = gettext.dgettext("YouTube", txt)
+       if t == txt:
+               print "[YTB] fallback to default translation for", txt
+               t = gettext.gettext(txt)
+       return t
+
+
+class YouTubeManager():
+       def __init__(self, session):
+               self.session = session
+               interface.open()
+
+
+       def openSearchDialog(self):
+               self.session.openWithCallback(self.searchDialogClosed, YouTubeSearchDialog)
+
+
+       def searchDialogClosed(self, what, searchContext = None):
+               print "[YTB] searchDialogClosed: ", what
+               if what == SEARCH:
+                       dlg = self.session.openWithCallback(self.youTubeListScreenClosed, YouTubeListScreen)
+                       dlg.searchFeed(searchContext)
+               elif what == CANCEL:
+                       interface.close()
+               elif what == STDFEEDS:
+                       self.openStandardFeeds()
+               else:
+                       if what == PLAYLISTS:
+                               callback = self.openPlaylists
+                       elif what == FAVORITES:
+                               callback = self.openFavorites
+                       if not interface.isLoggedIn():
+                               self.session.openWithCallback(callback, YouTubeUserListScreen, youTubeUserConfig.getDefaultUser())
+                       else:
+                               callback(YouTubeUserListScreen.LOGIN_SUCCESS)
+
+
+       def openStandardFeeds(self):
+               self.session.openWithCallback(self.standardFeedSelected, YouTubeStdFeedSelectionScreen)
+
+
+       def standardFeedSelected(self, stdFeedUrl):
+               if stdFeedUrl is not None:
+                       dlg = self.session.openWithCallback(self.youTubeListScreenClosed, YouTubeListScreen)
+                       dlg.loadStandardFeed(stdFeedUrl)
+               else:
+                       self.openSearchDialog()
+
+
+       def openPlaylists(self, loginState):
+               if loginState == YouTubeUserListScreen.LOGIN_SUCCESS:
+                       print "[YTB] logged in"
+                       dlg = self.session.openWithCallback(self.playlistChoosen, YouTubePlaylistScreen)
+                       dlg.loadPlaylist()
+               elif loginState == YouTubeUserListScreen.LOGIN_FAILED:
+                       print "[YTB] not logged in"
+                       self.session.openWithCallback(self.backToSearchDialog, MessageBox, _("Login not successful"), MessageBox.TYPE_INFO)
+               else:
+                       self.backToSearchDialog()
+
+
+       def playlistChoosen(self, playlist):
+               if playlist is not None:
+                       dlg = self.session.openWithCallback(self.youTubeListScreenClosed, YouTubeListScreen)
+                       dlg.loadPlaylistFeed(playlist)
+               else:
+                       self.openSearchDialog()
+
+
+       def openFavorites(self, loginState):
+               if loginState == YouTubeUserListScreen.LOGIN_SUCCESS:
+                       print "[YTB] logged in"
+                       dlg = self.session.openWithCallback(self.youTubeListScreenClosed, YouTubeListScreen)
+                       dlg.loadFavoritesFeed("default")
+               elif loginState == YouTubeUserListScreen.LOGIN_FAILED:
+                       print "[YTB] not logged in"
+                       self.session.openWithCallback(self.backToSearchDialog, MessageBox, _("Login not successful"), MessageBox.TYPE_INFO)
+               else:
+                       self.backToSearchDialog()
+
+
+       def backToSearchDialog(self, dummy = True):
+               self.openSearchDialog()
+
+
+       def youTubeListScreenClosed(self, proceed):
+               if proceed:
+                       self.openSearchDialog()
+               else:
+                       interface.close()
+
+
+def main(session, **kwargs):
+       YouTubeManager(session).openSearchDialog()
+
+
+def Plugins(**kwargs):
+       loadPluginSkin(kwargs["path"])
+       return PluginDescriptor(
+               name="YouTube Player",
+               description=_("Search and play YouTube movies"),
+               where = [ PluginDescriptor.WHERE_EXTENSIONSMENU, PluginDescriptor.WHERE_PLUGINMENU ],
+               icon = "plugin.png", fnc = boundFunction(main))
diff --git a/youtubeplayer/src/skin.xml b/youtubeplayer/src/skin.xml
new file mode 100644 (file)
index 0000000..34ce637
--- /dev/null
@@ -0,0 +1,114 @@
+<skin>
+       <screen name = "SuggestionsListScreen" position = "170,120" zPosition = "2" size = "394,185" backgroundColor = "#202020" flags = "wfNoBorder">
+               <eLabel position = "0,0" size = "394,185" backgroundColor = "#c0c0c0" zPosition = "-1" />
+               <widget name = "suggestionslist" position = "2,2" size = "390,181"  scrollbarMode = "showOnDemand"/>
+       </screen>
+
+       <screen name = "YouTubeAddPlaylistDialog" position = "80,85" size = "560,315" title = "Edit YouTube Playlists">
+               <widget name = "config" position = "10,10" size = "540,250" scrollbarMode = "showOnDemand" />
+               <ePixmap name = "red"    position = "0,275"   zPosition = "4" size = "140,40" pixmap = "skin_default/buttons/red.png" transparent = "1" alphatest = "on" />
+               <ePixmap name = "green"  position = "140,275" zPosition = "4" size = "140,40" pixmap = "skin_default/buttons/green.png" transparent = "1" alphatest = "on" />
+               <ePixmap name = "yellow" position = "280,275" zPosition = "4" size = "140,40" pixmap = "skin_default/buttons/yellow.png" transparent = "1" alphatest = "on" />
+               <ePixmap name = "blue"   position = "420,275" zPosition = "4" size = "140,40" pixmap = "skin_default/buttons/blue.png" transparent = "1" alphatest = "on" />
+               <widget name = "key_red" position = "0,275" zPosition = "5" size = "140,40" valign = "center" halign = "center" font = "Regular;21" transparent = "1" foregroundColor = "white" shadowColor = "black" shadowOffset = "-1,-1" />
+               <widget name = "key_green" position = "140,275" zPosition = "5" size = "140,40" valign = "center" halign = "center" font = "Regular;21" transparent = "1" foregroundColor = "white" shadowColor = "black" shadowOffset = "-1,-1" />
+               <widget name = "key_yellow" position = "280,275" zPosition = "5" size = "140,40" valign = "center" halign = "center"  font = "Regular;21" transparent = "1" foregroundColor = "white" shadowColor = "black" shadowOffset = "-1,-1" />
+               <widget name = "key_blue" position = "420,275" zPosition = "5" size = "140,40" valign = "center" halign = "center" font = "Regular;21" transparent = "1" foregroundColor = "white" shadowColor = "black" shadowOffset = "-1,-1" />
+       </screen>
+
+       <screen name = "YouTubeEntryContextMenu" position = "150,160" size = "400,260" title = "Video Context Menu">
+               <widget name = "menu" position = "10,10" size = "390,250" scrollbarMode = "showOnDemand" />
+       </screen>
+
+       <screen name = "YouTubeVideoDetailsScreen" position = "80,85" size = "560,410" title = "Video Details" transparent = "0">
+               <widget name = "video_thumbnail_1" position = "10,10" size = "130,97" alphatest = "on" />
+               <widget name = "video_thumbnail_2" position = "10,110" size = "130,97" alphatest = "on" />
+               <widget name = "video_thumbnail_3" position = "10,210" size = "130,97" alphatest = "on" />
+               <widget name = "label_video_duration" position = "150,10" size = "95,20" font = "Regular;20" halign = "right" />
+               <widget name = "video_duration" position = "250,10" size = "90,20" valign = "left" font = "Regular;20"/>
+               <widget name = "label_video_rating_average" position = "345,10" size = "95,20" font = "Regular;20" halign = "right" />
+               <widget name = "starsbg" pixmap = "/usr/lib/enigma2/python/Plugins/Extensions/YouTubePlayer/starsbar_empty.png" position = "445,10" zPosition = "0" size = "100,20" transparent = "1" alphatest = "on" />
+               <widget name = "stars" position = "445,10" size = "100,20" pixmap = "/usr/lib/enigma2/python/Plugins/Extensions/YouTubePlayer/starsbar_filled.png" transparent = "1" />
+               <widget name = "label_video_statistics_view_count" position = "150,30" size = "95,20" font = "Regular;20" halign = "right" />
+               <widget name = "video_statistics_view_count" position = "250,30" size = "90,20" valign = "left" font = "Regular;20"/>
+               <widget name = "label_video_numraters" position = "345,30" size = "95,20" font = "Regular;20" halign = "right" />
+               <widget name = "video_numraters" position = "445,30" size = "105,20" valign = "left" font = "Regular;20"/>
+               <widget name = "label_video_statistics_favorite_count" position = "150,50" size = "95,20" font = "Regular;20" halign = "right" />
+               <widget name = "video_statistics_favorite_count" position = "250,50" size = "90,20" valign = "left" font = "Regular;20"/>
+               <widget name = "label_video_published_on" position = "345,50" size = "95,20" font = "Regular;20" halign = "right" />
+               <widget name = "video_published_on" position = "445,50" size = "105,20" valign = "left" font = "Regular;20"/>
+               <widget name = "label_video_author" position = "150,70" size = "95,20" font = "Regular;20" halign = "right" />
+               <widget name = "video_author" position = "250,70" size = "300,20" valign = "left" font = "Regular;20"/>
+               <widget name = "label_video_category" position = "150,90" size = "95,20" font = "Regular;20" halign = "right" />
+               <widget name = "video_category" position = "250,90" size = "300,20" valign = "left" font = "Regular;20"/>
+               <widget name = "label_video_tags" position = "150,110" size = "95,20" font = "Regular;20" halign = "right" />
+               <widget name = "video_tags" position = "250,110" size = "300,60" valign = "left" font = "Regular;20"/>
+               <ePixmap pixmap = "skin_default/div-h.png" position = "150,179" zPosition = "1" size = "400,2" />
+               <widget name = "video_description" position = "150,190" size = "400,210" font = "Regular;20" />
+       </screen>
+
+       <screen name = "YouTubeListScreen" position = "80,85" size = "560,410" title = "YouTube Videos" transparent = "0">
+               <widget name = "label_total_results" position = "0,13" size = "160,20" font = "Regular;20" halign = "right" />
+               <widget name = "total_results" position = "170,13" size = "110,20" font = "Regular;20" />
+               <widget name = "label_currently_shown" position = "280,13" size = "110,20" font = "Regular;20" halign = "right" />
+               <widget name = "currently_shown" position = "400,13" size = "160,20" font = "Regular;20" />
+               <ePixmap pixmap = "skin_default/div-h.png" position = "0,44" zPosition = "1" size = "560,2" />
+               <widget name = "list" position = "5,55" size = "550,315" scrollbarMode = "showOnDemand" />
+               <ePixmap name = "key_red" position = "40,370" zPosition = "1" size = "200,40" pixmap = "skin_default/buttons/red-big.png" transparent = "1" alphatest = "on" />
+               <ePixmap name = "key_green" position = "320,370" zPosition = "1" size = "200,40" pixmap = "skin_default/buttons/green-big.png" transparent = "1" alphatest = "on" />
+               <widget name = "red" position = "40,370" size = "200,40" font = "Regular;19" valign = "center" halign = "center" transparent = "1" zPosition = "2" />
+               <widget name = "green" position = "320,370" size = "200,40" font = "Regular;19" valign = "center" halign = "center" transparent = "1" zPosition = "2" />
+       </screen>
+
+       <screen name = "YouTubePlaylistScreen" position = "80,85" size = "560,410" title = "YouTube Playlists" transparent = "0">
+               <widget name = "list" position = "5,10" size = "550,350" scrollbarMode = "showOnDemand" />
+               <ePixmap name = "key_red" position = "40,370" zPosition = "1" size = "200,40" pixmap = "skin_default/buttons/red-big.png" transparent = "1" alphatest = "on" />
+               <ePixmap name = "key_green" position = "320,370" zPosition = "1" size = "200,40" pixmap = "skin_default/buttons/green-big.png" transparent = "1" alphatest = "on" />
+               <widget name = "red" position = "40,370" size = "200,40" font = "Regular;19" valign = "center" halign = "center" transparent = "1" zPosition = "2" />
+               <widget name = "green" position = "320,370" size = "200,40" font = "Regular;19" valign = "center" halign = "center" transparent = "1" zPosition = "2" />
+       </screen>
+
+       <screen name = "YouTubeSearchDialog" position = "80,85" size = "560,315" title = "YouTube Player">
+               <widget name = "config" position = "10,10" size = "540,250" scrollbarMode = "showOnDemand" />
+               <ePixmap name = "red"    position = "0,275"   zPosition = "4" size = "140,40" pixmap = "skin_default/buttons/red.png" transparent = "1" alphatest = "on" />
+               <ePixmap name = "green"  position = "140,275" zPosition = "4" size = "140,40" pixmap = "skin_default/buttons/green.png" transparent = "1" alphatest = "on" />
+               <ePixmap name = "yellow" position = "280,275" zPosition = "4" size = "140,40" pixmap = "skin_default/buttons/yellow.png" transparent = "1" alphatest = "on" />
+               <ePixmap name = "blue"   position = "420,275" zPosition = "4" size = "140,40" pixmap = "skin_default/buttons/blue.png" transparent = "1" alphatest = "on" />
+               <widget name = "key_red" position = "0,275" zPosition = "5" size = "140,40" valign = "center" halign = "center" font = "Regular;21" transparent = "1" foregroundColor = "white" shadowColor = "black" shadowOffset = "-1,-1" />
+               <widget name = "key_green" position = "140,275" zPosition = "5" size = "140,40" valign = "center" halign = "center" font = "Regular;21" transparent = "1" foregroundColor = "white" shadowColor = "black" shadowOffset = "-1,-1" />
+               <widget name = "key_yellow" position = "280,275" zPosition = "5" size = "140,40" valign = "center" halign = "center"  font = "Regular;21" transparent = "1" foregroundColor = "white" shadowColor = "black" shadowOffset = "-1,-1" />
+               <widget name = "key_blue" position = "420,275" zPosition = "5" size = "140,40" valign = "center" halign = "center" font = "Regular;21" transparent = "1" foregroundColor = "white" shadowColor = "black" shadowOffset = "-1,-1" />
+       </screen>
+
+       <screen name = "YouTubeStdFeedSelectionScreen" position = "80,85" size = "560,410" title = "YouTube Standard-Feeds">
+               <widget source = "menu" render = "Listbox" position = "10,10" size = "540,390" scrollbarMode = "showOnDemand" >
+                       <convert type = "StringList" />
+               </widget>
+       </screen>
+
+       <screen name = "YouTubeUserConfigScreen" position = "80,85" size = "560,315" title = "Edit YouTube User-Profiles">
+               <widget name = "config" position = "10,10" size = "540,250" scrollbarMode = "showOnDemand" />
+               <ePixmap name = "red"    position = "0,275"   zPosition = "4" size = "140,40" pixmap = "skin_default/buttons/red.png" transparent = "1" alphatest = "on" />
+               <ePixmap name = "green"  position = "140,275" zPosition = "4" size = "140,40" pixmap = "skin_default/buttons/green.png" transparent = "1" alphatest = "on" />
+               <ePixmap name = "yellow" position = "280,275" zPosition = "4" size = "140,40" pixmap = "skin_default/buttons/yellow.png" transparent = "1" alphatest = "on" />
+               <ePixmap name = "blue"   position = "420,275" zPosition = "4" size = "140,40" pixmap = "skin_default/buttons/blue.png" transparent = "1" alphatest = "on" />
+               <widget name = "key_red" position = "0,275" zPosition = "5" size = "140,40" valign = "center" halign = "center" font = "Regular;21" transparent = "1" foregroundColor = "white" shadowColor = "black" shadowOffset = "-1,-1" />
+               <widget name = "key_green" position = "140,275" zPosition = "5" size = "140,40" valign = "center" halign = "center" font = "Regular;21" transparent = "1" foregroundColor = "white" shadowColor = "black" shadowOffset = "-1,-1" />
+               <widget name = "key_yellow" position = "280,275" zPosition = "5" size = "140,40" valign = "center" halign = "center"  font = "Regular;21" transparent = "1" foregroundColor = "white" shadowColor = "black" shadowOffset = "-1,-1" />
+               <widget name = "key_blue" position = "420,275" zPosition = "5" size = "140,40" valign = "center" halign = "center" font = "Regular;21" transparent = "1" foregroundColor = "white" shadowColor = "black" shadowOffset = "-1,-1" />
+       </screen>
+
+       <screen name = "YouTubeUserListScreen" position = "80,85" size = "560,410" title = "YouTube User-Profiles" >
+               <widget name = "label_info" position = "10,9" size = "540,42" halign = "center" valign = "center" font = "Regular;21" />
+               <ePixmap pixmap = "skin_default/div-h.png" position = "0,56" zPosition = "1" size = "560,2" />
+               <widget name = "userlist" position = "10,62" size = "540,283"  scrollbarMode = "showOnDemand"/>
+               <ePixmap name = "red"    position = "0,370"   zPosition = "4" size = "140,40" pixmap = "skin_default/buttons/red.png" transparent = "1" alphatest = "on" />
+               <ePixmap name = "green"  position = "140,370" zPosition = "4" size = "140,40" pixmap = "skin_default/buttons/green.png" transparent = "1" alphatest = "on" />
+               <ePixmap name = "yellow" position = "280,370" zPosition = "4" size = "140,40" pixmap = "skin_default/buttons/yellow.png" transparent = "1" alphatest = "on" />
+               <ePixmap name = "blue"   position = "420,370" zPosition = "4" size = "140,40" pixmap = "skin_default/buttons/blue.png" transparent = "1" alphatest = "on" />
+               <widget name = "key_red" position = "0,370" zPosition = "5" size = "140,40" valign = "center" halign = "center" font = "Regular;21" transparent = "1" foregroundColor = "white" shadowColor = "black" shadowOffset = "-1,-1" />
+               <widget name = "key_green" position = "140,370" zPosition = "5" size = "140,40" valign = "center" halign = "center" font = "Regular;21" transparent = "1" foregroundColor = "white" shadowColor = "black" shadowOffset = "-1,-1" />
+               <widget name = "key_yellow" position = "280,370" zPosition = "5" size = "140,40" valign = "center" halign = "center"  font = "Regular;21" transparent = "1" foregroundColor = "white" shadowColor = "black" shadowOffset = "-1,-1" />
+               <widget name = "key_blue" position = "420,370" zPosition = "5" size = "140,40" valign = "center" halign = "center" font = "Regular;21" transparent = "1" foregroundColor = "white" shadowColor = "black" shadowOffset = "-1,-1" />
+       </screen>
+</skin>
diff --git a/youtubeplayer/src/starsbar_empty.png b/youtubeplayer/src/starsbar_empty.png
new file mode 100644 (file)
index 0000000..b1c5774
Binary files /dev/null and b/youtubeplayer/src/starsbar_empty.png differ
diff --git a/youtubeplayer/src/starsbar_filled.png b/youtubeplayer/src/starsbar_filled.png
new file mode 100644 (file)
index 0000000..331e21e
Binary files /dev/null and b/youtubeplayer/src/starsbar_filled.png differ
diff --git a/youtubeplayer/src/user.png b/youtubeplayer/src/user.png
new file mode 100644 (file)
index 0000000..94649b6
Binary files /dev/null and b/youtubeplayer/src/user.png differ
diff --git a/youtubeplayer/src/user_default.png b/youtubeplayer/src/user_default.png
new file mode 100644 (file)
index 0000000..34eae3e
Binary files /dev/null and b/youtubeplayer/src/user_default.png differ