1 from Plugins.Plugin import PluginDescriptor
3 import time, os, socket, thread, socket, copy
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, ConfigSlider
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
40 print "prepared cmd:", cmd
44 def change_galpha(set_const, set_value):
45 op = "/proc/stb/fb/alpha_op"
46 val = "/proc/stb/fb/alpha_value"
48 if os.path.exists(op) and set_const and alpha_value < 255:
49 excute_cmd("echo \"const\" > %s" % (op))
51 excute_cmd("echo \"copypsrc\" > %s" % (op))
53 if os.path.exists(val) and set_value:
54 excute_cmd("echo \"%s\" > %s" % (str(hex(alpha_value)), val))
56 def enable_rc_mouse(mode): #mode=[0|1]|[False|True]
57 mouse_cond = "/proc/stb/fp/mouse"
58 if os.path.exists(mouse_cond):
59 excute_cmd("echo %d > %s" % (mode, mouse_cond))
61 def is_process_running(pname):
62 if pname is None or len(pname) == 0:
65 cmd = "/bin/ps -ef | grep %s | grep -v grep | awk \'{print $5}\'"%(pname)
66 for line in os.popen(cmd).readlines():
71 def wb_lock(alpha_on=True):
75 change_galpha(set_const=False, set_value=False)
76 fbClass.getInstance().unlock()
78 def wb_unlock(alpha_on=True):
81 change_galpha(set_const=True, set_value=False)
82 fbClass.getInstance().lock()
89 class VuPlayer(Screen, InfoBarNotifications):
91 <screen name="VuPlayer" flags="wfNoBorder" position="center,620" size="455,53" title="VuPlayer" backgroundColor="transparent">
92 <ePixmap pixmap="Vu_HD/mp_wb_background.png" position="0,0" zPosition="-1" size="455,53" />
93 <ePixmap pixmap="Vu_HD/icons/mp_wb_buttons.png" position="40,23" size="30,13" alphatest="on" />
95 <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">
96 <convert type="ServicePosition">Gauge</convert>
99 <widget source="session.CurrentService" render="Label" position="310,20" size="50,20" font="Regular;18" halign="center" valign="center" backgroundColor="#4e5a74" transparent="1" >
100 <convert type="ServicePosition">Position</convert>
102 <widget name="sidebar" position="362,20" size="10,20" font="Regular;18" halign="center" valign="center" backgroundColor="#4e5a74" transparent="1" />
103 <widget source="session.CurrentService" render="Label" position="374,20" size="50,20" font="Regular;18" halign="center" valign="center" backgroundColor="#4e5a74" transparent="1" >
104 <convert type="ServicePosition">Length</convert>
112 def __init__(self, session, service, lastservice):
113 Screen.__init__(self, session)
114 InfoBarNotifications.__init__(self)
116 self.session = session
117 self.service = service
118 self.lastservice = lastservice
119 self["actions"] = ActionMap(["OkCancelActions", "InfobarSeekActions", "MediaPlayerActions", "MovieSelectionActions"],
121 "ok": self.doInfoAction,
122 "cancel": self.doExit,
124 "playpauseService": self.playpauseService,
126 self["sidebar"] = Label(_("/"))
128 self.__event_tracker = ServiceEventTracker(screen = self, eventmap =
130 iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged,
131 iPlayableService.evStart: self.__serviceStarted,
132 iPlayableService.evEOF: self.__evEOF,
135 self.hidetimer = eTimer()
136 self.hidetimer.timeout.get().append(self.doInfoAction)
138 self.state = self.PLAYER_PLAYING
139 self.lastseekstate = self.PLAYER_PLAYING
140 self.__seekableStatusChanged()
142 self.onClose.append(self.__onClose)
146 self.session.nav.stopService()
148 def __seekableStatusChanged(self):
149 service = self.session.nav.getCurrentService()
150 if service is not None:
151 seek = service.seek()
152 if seek is None or not seek.isCurrentlySeekable():
153 self.setSeekState(self.PLAYER_PLAYING)
155 def __serviceStarted(self):
156 self.state = self.PLAYER_PLAYING
157 self.__seekableStatusChanged()
162 def __setHideTimer(self):
163 self.hidetimer.start(5000)
166 list = ((_("Yes"), "y"), (_("No, but play video again"), "n"),)
167 self.session.openWithCallback(self.cbDoExit, ChoiceBox, title=_("Stop playing this movie?"), list = list)
169 def cbDoExit(self, answer):
170 answer = answer and answer[1]
175 if self.state != self.PLAYER_IDLE:
176 self.session.nav.stopService()
177 self.state = self.PLAYER_IDLE
180 def setSeekState(self, wantstate):
181 service = self.session.nav.getCurrentService()
183 print "No Service found"
186 pauseable = service.pause()
187 if pauseable is not None:
188 if wantstate == self.PLAYER_PAUSED:
190 self.state = self.PLAYER_PAUSED
192 self.hidetimer.stop()
194 elif wantstate == self.PLAYER_PLAYING:
196 self.state = self.PLAYER_PLAYING
198 self.__setHideTimer()
200 self.state = self.PLAYER_PLAYING
202 def doInfoAction(self):
205 self.hidetimer.stop()
208 if self.state == self.PLAYER_PLAYING:
209 self.__setHideTimer()
212 if self.state == self.PLAYER_PAUSED:
214 self.__setHideTimer()
215 self.state = self.PLAYER_PLAYING
216 self.session.nav.playService(self.service)
218 self.__setHideTimer()
220 def playpauseService(self):
221 if self.state == self.PLAYER_PLAYING:
222 self.setSeekState(self.PLAYER_PAUSED)
223 elif self.state == self.PLAYER_PAUSED:
224 self.setSeekState(self.PLAYER_PLAYING)
226 VIDEO_FMT_PRIORITY_MAP = {
227 '38' : 1, #MP4 Original (HD)
228 '37' : 2, #MP4 1080p (HD)
229 '22' : 3, #MP4 720p (HD)
235 'User-Agent': 'Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.6) Gecko/20100627 Firefox/3.6.6',
236 'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
237 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
238 'Accept-Language': 'en-us,en;q=0.5',
241 class VuPlayerLauncher:
242 def getVideoUrl(self, video_id):
245 if video_id is None or video_id == "":
248 # Getting video webpage
249 watch_url = 'http://www.youtube.com/watch?v=%s&gl=US&hl=en' % video_id
250 watchrequest = Request(watch_url, None, std_headers)
252 #print "trying to find out if a HD Stream is available",watch_url
253 watchvideopage = urlopen2(watchrequest).read()
254 except (URLError, HTTPException, socket.error), err:
255 print "Error: Unable to retrieve watchpage - Error code: ", str(err)
259 for el in ['&el=embedded', '&el=detailpage', '&el=vevo', '']:
260 info_url = ('http://www.youtube.com/get_video_info?&video_id=%s%s&ps=default&eurl=&gl=US&hl=en' % (video_id, el))
261 request = Request(info_url, None, std_headers)
263 infopage = urlopen2(request).read()
264 videoinfo = parse_qs(infopage)
265 if ('url_encoded_fmt_stream_map' or 'fmt_url_map') in videoinfo:
267 except (URLError, HTTPException, socket.error), err:
268 print "Error: unable to download video infopage",str(err)
271 if ('url_encoded_fmt_stream_map' or 'fmt_url_map') not in videoinfo:
272 if 'reason' not in videoinfo:
273 print 'Error: unable to extract "fmt_url_map" or "url_encoded_fmt_stream_map" parameter for unknown reason'
275 reason = unquote_plus(videoinfo['reason'][0])
276 print 'Error: YouTube said: %s' % reason.decode('utf-8')
281 if videoinfo.has_key('url_encoded_fmt_stream_map'):
282 tmp_fmtUrlDATA = videoinfo['url_encoded_fmt_stream_map'][0].split(',url=')
284 tmp_fmtUrlDATA = videoinfo['fmt_url_map'][0].split(',')
285 for fmtstring in tmp_fmtUrlDATA:
286 if videoinfo.has_key('url_encoded_fmt_stream_map'):
287 (fmturl, fmtid) = fmtstring.split('&itag=')
288 if fmturl.find("url=") !=-1:
289 fmturl = fmturl.replace("url=","")
291 (fmtid,fmturl) = fmtstring.split('|')
292 if VIDEO_FMT_PRIORITY_MAP.has_key(fmtid):
293 video_fmt_map[VIDEO_FMT_PRIORITY_MAP[fmtid]] = { 'fmtid': fmtid, 'fmturl': unquote_plus(fmturl) }
294 fmt_infomap[int(fmtid)] = unquote_plus(fmturl)
295 print "got",sorted(fmt_infomap.iterkeys())
296 if video_fmt_map and len(video_fmt_map):
297 video_url = video_fmt_map[sorted(video_fmt_map.iterkeys())[0]]['fmturl'].split(';')[0]
298 #print "found best available video format:",video_fmt_map[sorted(video_fmt_map.iterkeys())[0]]['fmtid']
299 #print "found best available video url:",video_url
302 def run(self, tubeid, session, service):
304 myurl = self.getVideoUrl(tubeid)
305 print "Playing URL", myurl
307 session.open(MessageBox, _("Sorry, video is not available!"), MessageBox.TYPE_INFO)
309 myreference = eServiceReference(4097, 0, myurl)
310 session.open(VuPlayer, myreference, service)
311 except Exception, msg:
313 print "Error >>", msg
315 class VuPlayerService:
316 def __init__(self, session):
318 self.socket_timeout = 0
319 self.max_buffer_size = 1024
320 self.uds_file = "/tmp/vuplus.tmp"
321 self.session = session
323 os.remove(self.uds_file)
327 def start(self, timeout = 1):
328 self.socket_timeout = timeout
329 thread.start_new_thread(self.run, (True,))
337 def run(self, e = True):
340 print "VuPlayerService start!!"
342 self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
343 self.sock.settimeout(self.socket_timeout)
344 self.sock.bind(self.uds_file)
348 conn, addr = self.sock.accept()
349 self.parseHandle(conn, addr)
350 except socket.timeout:
351 #print "[socket timeout]"
353 print "VuPlayerService stop!!"
355 def parseHandle(self, conn, addr):
356 # [http://www.youtube.com/watch?v=BpThu778qB4&feature=related]
357 data = conn.recv(self.max_buffer_size)
358 print "[%s]" % (data)
359 enable_rc_mouse(False)
360 if data.startswith("http://www.youtube.com"):
361 print "youtube start!!"
362 tmp = data.split("?")
363 print tmp # ['http://www.youtube.com/watch', 'v=BpThu778qB4&feature=related']
364 service = self.session.nav.getCurrentlyPlayingServiceReference()
365 if len(tmp) == 2 and tmp[0] == "http://www.youtube.com/watch":
366 tmp = tmp[1].split("&")
367 print tmp # ['v=BpThu778qB4', 'feature=related']
369 tmp = tmp[0].split("=")
370 print tmp # ['v', 'BpThu778qB4']
371 if len(tmp) == 2 and tmp[0] == "v":
373 player = VuPlayerLauncher()
374 player.run(tmp[1], self.session, service)
377 self.session.nav.playService(service)
380 data = "nok$parsing fail"
382 data = "nok$parsing fail"
384 data = "nok$parsing fail"
385 self.sendResponse(conn, data)
386 elif data.startswith("vk://open"):
387 print "virtual keyboard start!!"
388 from Screens.VirtualKeyBoard import VirtualKeyBoard
391 self.session.openWithCallback(self.cbOpenKeyboard, VirtualKeyBoard, title = (_("Enter your input data")), text = "")
393 def cbOpenKeyboard(self, data = None):
394 print "virtual keyboard callback!!"
396 self.sendResponse(self.vk_conn, data)
398 def sendResponse(self, conn, data):
399 if data is None or len(data) == 0:
401 enable_rc_mouse(True)
405 class BrowserLauncher(ConfigListScreen, Screen):
407 <screen name="BrowserLauncher" position="center,center" size="309,478" title="Web Browser">
408 <ePixmap pixmap="Vu_HD/buttons/red.png" position="4,0" size="40,40" alphatest="on" />
409 <ePixmap pixmap="Vu_HD/buttons/green.png" position="100,0" size="40,40" alphatest="on" />
410 <ePixmap pixmap="Vu_HD/buttons/button_off.png" position="200,0" size="40,40" alphatest="on" />
411 <widget source="key_red" render="Label" position="15,0" zPosition="1" size="50,30" font="Regular;20" halign="right" valign="center" transparent="1" />
412 <widget source="key_green" render="Label" position="120,0" zPosition="1" size="50,30" font="Regular;20" halign="right" valign="center" transparent="1" />
413 <widget name="config" position="0,50" size="309,80" scrollbarMode="showOnDemand" />
414 <ePixmap pixmap="Vu_HD/rc_wb_desc.png" position="0,130" size="309,296" alphatest="on" />
415 <widget name="info" position="0,435" size="309,50" font="Regular;18" halign="center" foregroundColor="blue" transparent="1" />
419 def __init__(self, session):
420 Screen.__init__(self, session)
421 self.session = session
423 ConfigListScreen.__init__(self, self.list)
425 self.browser_root = "/usr/bin"
426 self.browser_name = "arora"
427 self.conf_file = "/usr/lib/enigma2/python/Plugins/Extensions/WebBrowser/settings.conf"
428 self["actions"] = ActionMap(["OkCancelActions", "ShortcutActions", "WizardActions", "ColorActions", "SetupActions", ],
429 { "red": self.keyCancel,
431 "cancel": self.keyExit,
433 self.info = Label(_("If you want to quit the Browser,\nPress RED -> EXIT."))
434 self["info"] = self.info
435 self["key_red"] = StaticText(_("Exit"))
436 self["key_green"] = StaticText(_("Start"))
440 self.conf_keyboard = ""
442 self.usb_mouse = None
443 self.usb_keyboard = None
445 self.rc_keyboard = None
451 self.vu_service = VuPlayerService(self.session)
452 self.vu_service.start(timeout=5)
454 self.exit_wait_cond = False
455 self.timer_exit_cond = eTimer()
456 self.timer_exit_cond.callback.append(self.resetExitCond)
458 self.test_cond = True
464 change_galpha(set_const=False, set_value=False)
466 self.vu_service.stop()
467 excute_cmd("killall -15 %s"%(self.browser_name))
468 excute_cmd("echo 60 > /proc/sys/vm/swappiness")
469 enable_rc_mouse(False) #rc-mouse off
470 fbClass.getInstance().unlock()
471 #eRCInput.getInstance().unlock()
475 if self.exit_wait_cond:
477 if is_process_running(self.browser_name) == False:
481 if is_process_running(self.browser_name) == False:
482 ConfigListScreen.keyLeft(self)
484 alpha_value = self.alpha.value
488 if is_process_running(self.browser_name) == False:
489 ConfigListScreen.keyRight(self)
490 alpha_value = self.alpha.value
494 if is_process_running(self.browser_name) == False:
496 self.exit_wait_cond = True
497 self.timer_exit_cond.start(5000)
499 # mouse:keyboard:alpha_value
500 def saveConfig(self):
501 if is_process_running(self.browser_name) == False:
502 command = "echo \"%s:%s:%d\" > %s"%(self.mouse.value, self.keyboard.value, int(self.alpha.value), self.conf_file)
505 # mouse:keyboard:alpha_value
506 def loadConfig(self):
507 if os.path.exists(self.conf_file) == False:
509 config_list = open(self.conf_file).readline().strip().split(':')
510 if len(config_list) == 3:
511 self.conf_mouse = config_list[0]
512 self.conf_keyboard = config_list[1]
513 self.conf_alpha = config_list[2]
514 print "load config : ", config_list
516 def resetExitCond(self):
517 self.timer_exit_cond.stop()
518 self.exit_wait_cond = False
520 def makeConfig(self):
522 self.devices_string = ""
523 self.devices = eConsoleAppContainer()
524 self.devices.dataAvail.append(self.callbackDevicesDataAvail)
525 self.devices.appClosed.append(self.callbakcDevicesAppClose)
526 self.devices.execute(_("cat /proc/bus/input/devices"))
528 def callbackDevicesDataAvail(self, ret_data):
529 self.devices_string = self.devices_string + ret_data
531 def callbakcDevicesAppClose(self, retval):
533 self.mouse_list = None
534 self.keyboard_list = None
536 self.makeHandlerList(self.devices_string)
538 if self.conf_mouse == "" or self.getHandlerName(self.conf_mouse) is None:
539 self.conf_mouse = self.mouse_list[0][0]
540 if self.conf_keyboard == "" or self.getHandlerName(self.conf_keyboard) is None:
541 self.conf_keyboard = self.keyboard_list[0][0]
542 if self.conf_alpha == "":
543 self.conf_alpha = "255"
545 self.mouse = ConfigSelection(default = self.conf_mouse, choices = self.mouse_list)
546 self.keyboard = ConfigSelection(default = self.conf_keyboard, choices = self.keyboard_list)
547 self.alpha = ConfigSlider(default = int(self.conf_alpha), increment = 10, limits = (0, 255))
549 self.list.append(getConfigListEntry(_('Mouse'), self.mouse))
550 self.list.append(getConfigListEntry(_('Keyboard'), self.keyboard))
551 self.list.append(getConfigListEntry(_("Alpha Value"), self.alpha))
553 self["config"].list = self.list
554 self["config"].l.setList(self.list)
556 def makeHandlerList(self, data):
562 lines = data.split('\n')
565 if line is not None and len(line) > 0:
575 h_list = line[12:].strip().split()
576 tn = line[12:].strip().find("mouse")
578 event_list.append((h, _(h)))
579 self.name_list.append((h, n))
580 if n[1:].startswith("dream") and self.rc_mouse is None:
581 self.rc_mouse = copy.deepcopy(h)
582 self.rc_keyboard = copy.deepcopy(h)
583 print "detected!! rc"
585 if h.startswith("mouse") and self.usb_mouse is None:
586 self.usb_mouse = copy.deepcopy(h)
587 print "detected!! usb mouse"
589 if tn == -1 and self.usb_keyboard is None:
590 self.usb_keyboard = copy.deepcopy(h)
591 print "detected!! usb keyboard"
592 elif line[0] == 'B' and line[3:].startswith("ABS") and p.startswith("usb-"):
594 if self.usb_mouse is not None:
596 if self.usb_keyboard is not None and h == self.usb_keyboard[0]:
597 self.usb_keyboard = None
598 print "clean!! usb keyboard"
599 self.usb_mouse = copy.deepcopy(h)
600 print "detected!! usb mouse"
602 tmp = copy.deepcopy(event_list)
603 if self.usb_mouse is not None:
604 tmp.insert(0, ("musb", "USB Mouse"))
605 if self.rc_mouse is not None:
606 tmp.insert(0, ("mrc", "Remote Control"))
607 self.mouse_list = tmp
609 tmp = copy.deepcopy(event_list)
610 if self.usb_keyboard is not None:
611 tmp.insert(0, ("kusb", "USB Keyboard"))
612 if self.rc_keyboard is not None:
613 tmp.insert(0, ("krc", "Remote Control"))
614 self.keyboard_list = tmp
615 print "E:", event_list
616 print "M:", self.mouse_list
617 print "K:", self.keyboard_list
619 def startBrowser(self):
620 self.timer_start.stop()
623 excute_cmd("killall -15 %s"%(self.browser_name))
624 excute_cmd("echo 0 > /proc/sys/vm/swappiness")
629 browser_cmd = "%s/%s -qws" % (self.browser_root, self.browser_name)
631 mouse_param = self.mouse.value
632 if self.mouse.value == "mrc":
633 mouse_param = self.rc_mouse
634 elif self.mouse.value == "musb":
635 mouse_param = self.usb_mouse
636 keyboard_param = self.keyboard.value
637 if self.keyboard.value == "krc":
638 keyboard_param = self.rc_keyboard
639 elif self.keyboard.value == "kusb":
640 keyboard_param = self.usb_keyboard
642 if self.getHandlerName(mouse_param)[1:].startswith("dreambox"):
643 enable_rc_mouse(True) #rc-mouse on
644 if str(mouse_param).startswith("event"):
645 mouse_cmd = "export QWS_MOUSE_PROTO=LinuxInput:/dev/input/%s; " % (str(mouse_param))
646 kbd_cmd = "export QWS_KEYBOARD=LinuxInput:/dev/input/%s; " % (str(keyboard_param))
648 cmd = "%s%s%s%s" % (extra_cmd, kbd_cmd, mouse_cmd, browser_cmd)
649 print "prepared command : [%s]" % cmd
651 self.launcher = eConsoleAppContainer()
652 self.launcher.appClosed.append(self.callbackLauncherAppClosed)
653 self.launcher.dataAvail.append(self.callbackLauncherDataAvail)
655 fbClass.getInstance().lock()
656 #eRCInput.getInstance().lock()
659 alpha_value = self.alpha.value
660 change_galpha(set_const=True, set_value=True)
662 self.launcher.execute(cmd)
663 print "started browser..."
667 self.info.setText("Starting Webbrowser. Please wait...")
668 if self.lock == False:
669 self.timer_start = eTimer()
670 self.timer_start.callback.append(self.startBrowser)
671 self.timer_start.start(10)
673 def getHandlerName(self, v):
681 v = self.usb_keyboard
682 for l in self.name_list:
687 def callbackLauncherDataAvail(self, ret_data):
689 if ret_data.startswith("--done--"):
693 def callbackLauncherAppClosed(self, retval = 1):
696 def sessionstart(session, **kwargs):
697 enable_rc_mouse(False)
698 change_galpha(set_const=False, set_value=True)
699 excute_cmd("killall -15 arora")
701 def main(session, **kwargs):
702 session.open(BrowserLauncher)
704 def Plugins(**kwargs):
705 return [PluginDescriptor(where = PluginDescriptor.WHERE_SESSIONSTART, needsRestart = False, fnc=sessionstart),
706 PluginDescriptor(name=_("Web Browser"), description="start web browser", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main)]