1 from Plugins.Plugin import PluginDescriptor
3 import time, os, socket, thread
4 from socket import gaierror, error
5 from os import path as os_path, remove as os_remove
8 import gdata.youtube.service
9 from gdata.service import BadAuthentication
11 from twisted.web import client
12 from twisted.internet import reactor
14 from urlparse import parse_qs
15 from urllib import quote, unquote_plus, unquote
16 from urllib2 import Request, URLError, urlopen as urlopen2
17 from httplib import HTTPConnection, CannotSendRequest, BadStatusLine, HTTPException
19 from Components.Button import Button
20 from Components.Label import Label
21 from Components.Pixmap import Pixmap
22 from Components.Sources.List import List
23 from Components.ConfigList import ConfigListScreen
24 from Components.Sources.StaticText import StaticText
25 from Components.ActionMap import NumberActionMap, ActionMap
26 from Components.ServiceEventTracker import ServiceEventTracker
27 from Components.config import config, ConfigSelection, getConfigListEntry
29 from Screens.Screen import Screen
30 from Screens.ChoiceBox import ChoiceBox
31 from Screens.MessageBox import MessageBox
32 from Screens.DefaultWizard import DefaultWizard
33 from Screens.InfoBarGenerics import InfoBarNotifications
35 from enigma import eTimer, eServiceReference, iPlayableService, fbClass, eRCInput, eConsoleAppContainer
37 HTTPConnection.debuglevel = 1
43 fbClass.getInstance().unlock()
47 fbClass.getInstance().lock()
54 class VuPlayer(Screen, InfoBarNotifications):
56 <screen name="VuPlayer" flags="wfNoBorder" position="center,620" size="455,53" title="VuPlayer" backgroundColor="transparent">
57 <ePixmap pixmap="Vu_HD/mp_wb_background.png" position="0,0" zPosition="-1" size="455,53" />
58 <ePixmap pixmap="Vu_HD/icons/mp_wb_buttons.png" position="40,23" size="30,13" alphatest="on" />
60 <widget source="session.CurrentService" render="PositionGauge" position="80,25" size="220,10" zPosition="2" pointer="skin_default/position_pointer.png:540,0" transparent="1" foregroundColor="#20224f">
61 <convert type="ServicePosition">Gauge</convert>
64 <widget source="session.CurrentService" render="Label" position="310,20" size="50,20" font="Regular;18" halign="center" valign="center" backgroundColor="#4e5a74" transparent="1" >
65 <convert type="ServicePosition">Position</convert>
67 <widget name="sidebar" position="362,20" size="10,20" font="Regular;18" halign="center" valign="center" backgroundColor="#4e5a74" transparent="1" />
68 <widget source="session.CurrentService" render="Label" position="374,20" size="50,20" font="Regular;18" halign="center" valign="center" backgroundColor="#4e5a74" transparent="1" >
69 <convert type="ServicePosition">Length</convert>
77 def __init__(self, session, service, lastservice):
78 Screen.__init__(self, session)
79 InfoBarNotifications.__init__(self)
81 self.session = session
82 self.service = service
83 self.lastservice = lastservice
84 self["actions"] = ActionMap(["OkCancelActions", "InfobarSeekActions", "MediaPlayerActions", "MovieSelectionActions"],
86 "ok": self.doInfoAction,
87 "cancel": self.doExit,
89 "playpauseService": self.playpauseService,
91 self["sidebar"] = Label(_("/"))
93 self.__event_tracker = ServiceEventTracker(screen = self, eventmap =
95 iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged,
96 iPlayableService.evStart: self.__serviceStarted,
97 iPlayableService.evEOF: self.__evEOF,
100 self.hidetimer = eTimer()
101 self.hidetimer.timeout.get().append(self.doInfoAction)
103 self.state = self.PLAYER_PLAYING
104 self.lastseekstate = self.PLAYER_PLAYING
105 self.__seekableStatusChanged()
107 self.onClose.append(self.__onClose)
111 self.session.nav.stopService()
113 def __seekableStatusChanged(self):
114 service = self.session.nav.getCurrentService()
115 if service is not None:
116 seek = service.seek()
117 if seek is None or not seek.isCurrentlySeekable():
118 self.setSeekState(self.PLAYER_PLAYING)
120 def __serviceStarted(self):
121 self.state = self.PLAYER_PLAYING
122 self.__seekableStatusChanged()
127 def __setHideTimer(self):
128 self.hidetimer.start(5000)
131 list = ((_("Yes"), "y"), (_("No, but play video again"), "n"),)
132 self.session.openWithCallback(self.cbDoExit, ChoiceBox, title=_("Stop playing this movie?"), list = list)
134 def cbDoExit(self, answer):
135 answer = answer and answer[1]
140 if self.state != self.PLAYER_IDLE:
141 self.session.nav.stopService()
142 self.state = self.PLAYER_IDLE
145 def setSeekState(self, wantstate):
146 service = self.session.nav.getCurrentService()
148 print "No Service found"
151 pauseable = service.pause()
152 if pauseable is not None:
153 if wantstate == self.PLAYER_PAUSED:
155 self.state = self.PLAYER_PAUSED
157 self.hidetimer.stop()
159 elif wantstate == self.PLAYER_PLAYING:
161 self.state = self.PLAYER_PLAYING
163 self.__setHideTimer()
165 self.state = self.PLAYER_PLAYING
167 def doInfoAction(self):
170 self.hidetimer.stop()
173 if self.state == self.PLAYER_PLAYING:
174 self.__setHideTimer()
177 if self.state == self.PLAYER_PAUSED:
179 self.__setHideTimer()
180 self.state = self.PLAYER_PLAYING
181 self.session.nav.playService(self.service)
183 self.__setHideTimer()
185 def playpauseService(self):
186 if self.state == self.PLAYER_PLAYING:
187 self.setSeekState(self.PLAYER_PAUSED)
188 elif self.state == self.PLAYER_PAUSED:
189 self.setSeekState(self.PLAYER_PLAYING)
191 VIDEO_FMT_PRIORITY_MAP = {
192 '38' : 1, #MP4 Original (HD)
193 '37' : 2, #MP4 1080p (HD)
194 '22' : 3, #MP4 720p (HD)
200 'User-Agent': 'Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.6) Gecko/20100627 Firefox/3.6.6',
201 'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
202 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
203 'Accept-Language': 'en-us,en;q=0.5',
206 class VuPlayerLauncher:
207 def getVideoUrl(self, video_id):
210 if video_id is None or video_id == "":
213 # Getting video webpage
214 watch_url = 'http://www.youtube.com/watch?v=%s&gl=US&hl=en' % video_id
215 watchrequest = Request(watch_url, None, std_headers)
217 #print "trying to find out if a HD Stream is available",watch_url
218 watchvideopage = urlopen2(watchrequest).read()
219 except (URLError, HTTPException, socket.error), err:
220 print "Error: Unable to retrieve watchpage - Error code: ", str(err)
224 for el in ['&el=embedded', '&el=detailpage', '&el=vevo', '']:
225 info_url = ('http://www.youtube.com/get_video_info?&video_id=%s%s&ps=default&eurl=&gl=US&hl=en' % (video_id, el))
226 request = Request(info_url, None, std_headers)
228 infopage = urlopen2(request).read()
229 videoinfo = parse_qs(infopage)
230 if ('url_encoded_fmt_stream_map' or 'fmt_url_map') in videoinfo:
232 except (URLError, HTTPException, socket.error), err:
233 print "Error: unable to download video infopage",str(err)
236 if ('url_encoded_fmt_stream_map' or 'fmt_url_map') not in videoinfo:
237 if 'reason' not in videoinfo:
238 print 'Error: unable to extract "fmt_url_map" or "url_encoded_fmt_stream_map" parameter for unknown reason'
240 reason = unquote_plus(videoinfo['reason'][0])
241 print 'Error: YouTube said: %s' % reason.decode('utf-8')
246 if videoinfo.has_key('url_encoded_fmt_stream_map'):
247 tmp_fmtUrlDATA = videoinfo['url_encoded_fmt_stream_map'][0].split(',url=')
249 tmp_fmtUrlDATA = videoinfo['fmt_url_map'][0].split(',')
250 for fmtstring in tmp_fmtUrlDATA:
251 if videoinfo.has_key('url_encoded_fmt_stream_map'):
252 (fmturl, fmtid) = fmtstring.split('&itag=')
253 if fmturl.find("url=") !=-1:
254 fmturl = fmturl.replace("url=","")
256 (fmtid,fmturl) = fmtstring.split('|')
257 if VIDEO_FMT_PRIORITY_MAP.has_key(fmtid):
258 video_fmt_map[VIDEO_FMT_PRIORITY_MAP[fmtid]] = { 'fmtid': fmtid, 'fmturl': unquote_plus(fmturl) }
259 fmt_infomap[int(fmtid)] = unquote_plus(fmturl)
260 print "got",sorted(fmt_infomap.iterkeys())
261 if video_fmt_map and len(video_fmt_map):
262 video_url = video_fmt_map[sorted(video_fmt_map.iterkeys())[0]]['fmturl'].split(';')[0]
263 #print "found best available video format:",video_fmt_map[sorted(video_fmt_map.iterkeys())[0]]['fmtid']
264 #print "found best available video url:",video_url
267 def run(self, tubeid, session, service):
269 myurl = self.getVideoUrl(tubeid)
270 print "Playing URL", myurl
272 session.open(MessageBox, _("Sorry, video is not available!"), MessageBox.TYPE_INFO)
276 myreference = eServiceReference(4097, 0, myurl)
277 session.open(VuPlayer, myreference, service)
278 except Exception, msg:
280 print "Error >>", msg
282 class VuPlayerService:
283 def __init__(self, session):
285 self.socket_timeout = 0
286 self.max_buffer_size = 1024
287 self.uds_file = "/tmp/vuplus.tmp"
288 self.session = session
290 os.remove(self.uds_file)
294 def start(self, timeout = 1):
295 self.socket_timeout = timeout
296 thread.start_new_thread(self.run, (True,))
304 def run(self, e = True):
308 self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
309 self.sock.settimeout(self.socket_timeout)
310 self.sock.bind(self.uds_file)
314 conn, addr = self.sock.accept()
315 self.parseHandle(conn, addr)
317 except socket.timeout:
318 #print "[socket timeout]"
321 def parseHandle(self, conn, addr):
322 # [http://www.youtube.com/watch?v=BpThu778qB4&feature=related]
323 data = conn.recv(self.max_buffer_size)
324 print "[%s]" % (data)
325 tmp = data.split("?")
326 print tmp # ['http://www.youtube.com/watch', 'v=BpThu778qB4&feature=related']
327 service = self.session.nav.getCurrentlyPlayingServiceReference()
328 if len(tmp) == 2 and tmp[0] == "http://www.youtube.com/watch":
329 tmp = tmp[1].split("&")
330 print tmp # ['v=BpThu778qB4', 'feature=related']
332 tmp = tmp[0].split("=")
333 print tmp # ['v', 'BpThu778qB4']
334 if len(tmp) == 2 and tmp[0] == "v":
335 player = VuPlayerLauncher()
336 player.run(tmp[1], self.session, service)
337 while player_islock():
339 self.session.nav.playService(service)
342 data = "nok$parsing fail"
344 data = "nok$parsing fail"
346 data = "nok$parsing fail"
349 class BrowserLauncher(ConfigListScreen, Screen):
351 <screen name="BrowserLauncher" position="center,center" size="300,160" title="Web Browser">
352 <ePixmap pixmap="Vu_HD/buttons/red.png" position="50,0" size="140,40" alphatest="on" />
353 <ePixmap pixmap="Vu_HD/buttons/green.png" position="170,0" size="140,40" alphatest="on" />
354 <widget source="key_red" render="Label" position="50,0" zPosition="1" size="115,30" font="Regular;20" halign="center" valign="center" transparent="1" />
355 <widget source="key_green" render="Label" position="170,0" zPosition="1" size="115,30" font="Regular;20" halign="center" valign="center" transparent="1" />
356 <widget name="config" position="0,50" size="300,70" scrollbarMode="showOnDemand" />
357 <widget name="introduction" position="0,120" size="300,40" font="Regular;20" halign="center" backgroundColor="#a08500" transparent="1" />
360 def __init__(self, session):
361 Screen.__init__(self, session)
362 self.session = session
364 self.browser_root = "/usr/bin"
365 self.browser_name = "arora"
366 self.mouse_cond = "/proc/stb/fp/mouse"
367 self["actions"] = ActionMap(["OkCancelActions", "ShortcutActions", "WizardActions", "ColorActions", "SetupActions", ],
368 { "red": self.keyCancel,
369 "cancel": self.keyCancel,
374 ConfigListScreen.__init__(self, self.list)
376 self["key_red"] = StaticText(_("Exit"))
377 self["key_green"] = StaticText(_("Start"))
378 self.introduntion = Label(_(" "))
379 self["introduction"] = self.introduntion
381 self.devices_string = ""
382 self.mouse_choice_list = []
383 self.mouse_device_list = []
384 self.keyboard_choice_list = []
385 self.keyboard_device_list = []
390 self.vu_service = VuPlayerService(self.session)
391 self.vu_service.start(timeout=5)
393 def enableRCMouse(self, mode): #mode=[0|1]|[False|True]
394 if os.path.exists(self.mouse_cond):
395 self.cmd("echo %d > %s" % (mode, self.mouse_cond))
398 print "prepared cmd:", cmd
405 #if self.lock == False:
406 self.vu_service.stop()
407 self.cmd("killall -9 %s"%(self.browser_name))
408 self.cmd("echo 60 > /proc/sys/vm/swappiness")
409 self.introduntion.setText(" ")
410 if self.mouse.value == 0:
411 self.enableRCMouse(False) #rc-mouse off
412 fbClass.getInstance().unlock()
413 #eRCInput.getInstance().unlock()
416 def makeConfig(self):
417 self.devices = eConsoleAppContainer()
418 self.devices.dataAvail.append(self.callbackDevicesDataAvail)
419 self.devices.appClosed.append(self.callbakcDevicesAppClose)
420 self.devices.execute(_("cat /proc/bus/input/devices"))
422 def callbackDevicesDataAvail(self, ret_data):
423 self.devices_string = self.devices_string + ret_data
425 def callbakcDevicesAppClose(self, retval):
426 self.parseDeviceData(self.devices_string)
427 self.makeHandlerList()
429 # none : -1, rc : 0, usb : 1
430 self.mouse_choice_list.append((2, _("None")))
431 self.keyboard_choice_list.append((2, _("None")))
433 print self.mouse_choice_list
434 print self.keyboard_choice_list
435 print self.mouse_device_list
436 print self.keyboard_device_list
438 self.mouse = ConfigSelection(default = self.mouse_choice_list[0][0], choices = self.mouse_choice_list)
439 self.keyboard = ConfigSelection(default = self.mouse_choice_list[0][0], choices = self.keyboard_choice_list)
441 self.list.append(getConfigListEntry(_('Mouse'), self.mouse))
442 self.list.append(getConfigListEntry(_('Keyboard'), self.keyboard))
443 self["config"].list = self.list
444 self["config"].l.setList(self.list)
446 def parseDeviceData(self, data):
451 lines=data.split('\n')
453 if line == None or line == "":
454 if h != None and len(h) != 0:
455 print "find driver >> name[%s], phys[%s], handler[%s]" % (n, p, h)
456 self.devices.append([n, p, h])
466 h = line[12:].strip()
468 def makeHandlerList(self):
469 if self.devices == None or self.devices == []:
476 for dev in self.devices:
480 if p.startswith("usb-ohci-brcm"):
481 if h.rfind("mouse") >= 0:
482 mouse_pc_h = [(1, _("USB Mouse")), self.getHandlerName(h, "mouse")]
484 if len(keyboard_pc_h) == 0:
485 keyboard_pc_h = [(1, _("USB Keyboard")), self.getHandlerName(h, "event")]
487 if n[1:].startswith("dreambox") and os.path.exists(self.mouse_cond) :
488 mouse_rc_h = [(0, _("RemoteControl")), self.getHandlerName(h, "event")]
489 keyboard_rc_h = [(0, _("RemoteControl")), self.getHandlerName(h, "event")]
490 if len(mouse_rc_h) > 0:
491 self.mouse_choice_list.append(mouse_rc_h[0])
492 self.mouse_device_list.append(mouse_rc_h[1])
493 if len(mouse_pc_h) > 0:
494 self.mouse_choice_list.append(mouse_pc_h[0])
495 self.mouse_device_list.append(mouse_pc_h[1])
497 if len(keyboard_rc_h) > 0:
498 self.keyboard_choice_list.append(keyboard_rc_h[0])
499 self.keyboard_device_list.append(keyboard_rc_h[1])
500 if len(keyboard_pc_h) > 0:
501 self.keyboard_choice_list.append(keyboard_pc_h[0])
502 self.keyboard_device_list.append(keyboard_pc_h[1])
505 def getHandlerName(self, h, s):
506 if h is None or len(h) == 0:
510 #print "handles >> ", handles
511 for tmp_h in handles:
512 #print "handle_item >> ", tmp_h
513 if tmp_h.startswith(s):
514 #print "detected : [%s]" % tmp_h
519 if self.lock == False:
522 self.introduntion.setText("Run web-browser.\nPlease, wait...")
523 self.cmd("echo 0 > /proc/sys/vm/swappiness")
528 browser_cmd = "%s/%s -qws" % (self.browser_root, self.browser_name)
530 fbClass.getInstance().lock()
531 #eRCInput.getInstance().lock()
533 if self.mouse.value == 0:
534 self.enableRCMouse(True) #rc-mouse on
535 idx = self.getListIndex(self.mouse_choice_list, 0)
536 mouse_cmd = "export QWS_MOUSE_PROTO=LinuxInput:/dev/input/%s; " % (self.mouse_device_list[idx])
537 elif self.mouse.value == 1:
539 #mouse_cmd = "export QWS_MOUSE_PROTO=Auto:/dev/input/%s; " % (m)
540 elif self.mouse.value == 2:
541 mouse_cmd = "export QWS_MOUSE_PROTO=None; "
543 if self.keyboard.value == 0:
544 idx = self.getListIndex(self.keyboard_choice_list, 0)
545 kbd_cmd = "export QWS_KEYBOARD=LinuxInput:/dev/input/%s; " % (self.keyboard_device_list[idx])
546 elif self.keyboard.value == 1:
547 idx = self.getListIndex(self.keyboard_choice_list, 1)
548 kbd_cmd = "export QWS_KEYBOARD=LinuxInput:/dev/input/%s; " % (self.keyboard_device_list[idx])
549 elif self.keyboard.value == 2:
551 print "mouse cmd >>", mouse_cmd, " >> ", self.mouse.value
552 print "keyboard cmd >>", kbd_cmd, " >> ", self.keyboard.value
554 cmd = "%s%s%s%s" % (extra_cmd, kbd_cmd, mouse_cmd, browser_cmd)
555 print "prepared command : [%s]" % cmd
557 self.launcher = eConsoleAppContainer()
558 self.launcher.appClosed.append(self.callbackLauncherAppClosed)
559 self.launcher.dataAvail.append(self.callbackLauncherDataAvail)
560 self.launcher.execute(cmd)
561 print "running arora..."
563 def getListIndex(self, l, v):
571 def callbackLauncherDataAvail(self, ret_data):
573 if ret_data.startswith("--done--"):
577 def callbackLauncherAppClosed(self, retval = 1):
580 def main(session, **kwargs):
581 session.open(BrowserLauncher)
583 def Plugins(**kwargs):
584 return PluginDescriptor(name=_("Web Browser"), description="start web browser", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main)