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.Language import language
23 from Components.Sources.List import List
24 from Components.ConfigList import ConfigListScreen
25 from Components.Sources.StaticText import StaticText
26 from Components.ActionMap import NumberActionMap, ActionMap
27 from Components.ServiceEventTracker import ServiceEventTracker
28 from Components.config import config, ConfigSelection, getConfigListEntry, ConfigSlider
30 from Screens.Screen import Screen
31 from Screens.ChoiceBox import ChoiceBox
32 from Screens.MessageBox import MessageBox
33 from Screens.DefaultWizard import DefaultWizard
34 from Screens.InfoBarGenerics import InfoBarNotifications
36 from enigma import eTimer, eServiceReference, iPlayableService, fbClass, eRCInput, eConsoleAppContainer
38 HTTPConnection.debuglevel = 1
41 print "prepared cmd:", cmd
45 def change_galpha(set_const, set_value):
46 op = "/proc/stb/fb/alpha_op"
47 val = "/proc/stb/fb/alpha_value"
49 if os.path.exists(op) and set_const and alpha_value < 255:
50 excute_cmd("echo \"const\" > %s" % (op))
52 excute_cmd("echo \"copypsrc\" > %s" % (op))
54 if os.path.exists(val) and set_value:
55 excute_cmd("echo \"%s\" > %s" % (str(hex(alpha_value)), val))
57 def enable_rc_mouse(mode): #mode=[0|1]|[False|True]
58 mouse_cond = "/proc/stb/fp/mouse"
59 if os.path.exists(mouse_cond):
60 excute_cmd("echo %d > %s" % (mode, mouse_cond))
62 def is_process_running(pname):
63 if pname is None or len(pname) == 0:
66 cmd = "/bin/ps -ef | grep %s | grep -v grep | awk \'{print $5}\'"%(pname)
67 for line in os.popen(cmd).readlines():
72 def wb_lock(alpha_on=True):
76 change_galpha(set_const=False, set_value=False)
77 fbClass.getInstance().unlock()
79 def wb_unlock(alpha_on=True):
82 change_galpha(set_const=True, set_value=False)
83 fbClass.getInstance().lock()
90 class VuPlayer(Screen, InfoBarNotifications):
92 <screen name="VuPlayer" flags="wfNoBorder" position="center,620" size="455,53" title="VuPlayer" backgroundColor="transparent">
93 <ePixmap pixmap="Vu_HD/mp_wb_background.png" position="0,0" zPosition="-1" size="455,53" />
94 <ePixmap pixmap="Vu_HD/icons/mp_wb_buttons.png" position="40,23" size="30,13" alphatest="on" />
96 <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">
97 <convert type="ServicePosition">Gauge</convert>
100 <widget source="session.CurrentService" render="Label" position="310,20" size="50,20" font="Regular;18" halign="center" valign="center" backgroundColor="#4e5a74" transparent="1" >
101 <convert type="ServicePosition">Position</convert>
103 <widget name="sidebar" position="362,20" size="10,20" font="Regular;18" halign="center" valign="center" backgroundColor="#4e5a74" transparent="1" />
104 <widget source="session.CurrentService" render="Label" position="374,20" size="50,20" font="Regular;18" halign="center" valign="center" backgroundColor="#4e5a74" transparent="1" >
105 <convert type="ServicePosition">Length</convert>
113 def __init__(self, session, service, lastservice):
114 Screen.__init__(self, session)
115 InfoBarNotifications.__init__(self)
117 self.session = session
118 self.service = service
119 self.lastservice = lastservice
120 self["actions"] = ActionMap(["OkCancelActions", "InfobarSeekActions", "MediaPlayerActions", "MovieSelectionActions"],
122 "ok": self.doInfoAction,
123 "cancel": self.doExit,
125 "playpauseService": self.playpauseService,
127 self["sidebar"] = Label(_("/"))
129 self.__event_tracker = ServiceEventTracker(screen = self, eventmap =
131 iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged,
132 iPlayableService.evStart: self.__serviceStarted,
133 iPlayableService.evEOF: self.__evEOF,
136 self.hidetimer = eTimer()
137 self.hidetimer.timeout.get().append(self.doInfoAction)
139 self.state = self.PLAYER_PLAYING
140 self.lastseekstate = self.PLAYER_PLAYING
141 self.__seekableStatusChanged()
143 self.onClose.append(self.__onClose)
147 self.session.nav.stopService()
149 def __seekableStatusChanged(self):
150 service = self.session.nav.getCurrentService()
151 if service is not None:
152 seek = service.seek()
153 if seek is None or not seek.isCurrentlySeekable():
154 self.setSeekState(self.PLAYER_PLAYING)
156 def __serviceStarted(self):
157 self.state = self.PLAYER_PLAYING
158 self.__seekableStatusChanged()
163 def __setHideTimer(self):
164 self.hidetimer.start(5000)
167 list = ((_("Yes"), "y"), (_("No, but play video again"), "n"),)
168 self.session.openWithCallback(self.cbDoExit, ChoiceBox, title=_("Stop playing this movie?"), list = list)
170 def cbDoExit(self, answer):
171 answer = answer and answer[1]
176 if self.state != self.PLAYER_IDLE:
177 self.session.nav.stopService()
178 self.state = self.PLAYER_IDLE
181 def setSeekState(self, wantstate):
182 service = self.session.nav.getCurrentService()
184 print "No Service found"
187 pauseable = service.pause()
188 if pauseable is not None:
189 if wantstate == self.PLAYER_PAUSED:
191 self.state = self.PLAYER_PAUSED
193 self.hidetimer.stop()
195 elif wantstate == self.PLAYER_PLAYING:
197 self.state = self.PLAYER_PLAYING
199 self.__setHideTimer()
201 self.state = self.PLAYER_PLAYING
203 def doInfoAction(self):
206 self.hidetimer.stop()
209 if self.state == self.PLAYER_PLAYING:
210 self.__setHideTimer()
213 if self.state == self.PLAYER_PAUSED:
215 self.__setHideTimer()
216 self.state = self.PLAYER_PLAYING
217 self.session.nav.playService(self.service)
219 self.__setHideTimer()
221 def playpauseService(self):
222 if self.state == self.PLAYER_PLAYING:
223 self.setSeekState(self.PLAYER_PAUSED)
224 elif self.state == self.PLAYER_PAUSED:
225 self.setSeekState(self.PLAYER_PLAYING)
227 VIDEO_FMT_PRIORITY_MAP = {
228 '38' : 1, #MP4 Original (HD)
229 '37' : 2, #MP4 1080p (HD)
230 '22' : 3, #MP4 720p (HD)
236 'User-Agent': 'Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.6) Gecko/20100627 Firefox/3.6.6',
237 'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
238 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
239 'Accept-Language': 'en-us,en;q=0.5',
242 class VuPlayerLauncher:
243 def getVideoUrl(self, video_id):
246 if video_id is None or video_id == "":
249 # Getting video webpage
250 watch_url = 'http://www.youtube.com/watch?v=%s&gl=US&hl=en' % video_id
251 watchrequest = Request(watch_url, None, std_headers)
253 #print "trying to find out if a HD Stream is available",watch_url
254 watchvideopage = urlopen2(watchrequest).read()
255 except (URLError, HTTPException, socket.error), err:
256 print "Error: Unable to retrieve watchpage - Error code: ", str(err)
260 for el in ['&el=embedded', '&el=detailpage', '&el=vevo', '']:
261 info_url = ('http://www.youtube.com/get_video_info?&video_id=%s%s&ps=default&eurl=&gl=US&hl=en' % (video_id, el))
262 request = Request(info_url, None, std_headers)
264 infopage = urlopen2(request).read()
265 videoinfo = parse_qs(infopage)
266 if ('url_encoded_fmt_stream_map' or 'fmt_url_map') in videoinfo:
268 except (URLError, HTTPException, socket.error), err:
269 print "Error: unable to download video infopage",str(err)
272 if ('url_encoded_fmt_stream_map' or 'fmt_url_map') not in videoinfo:
273 if 'reason' not in videoinfo:
274 print 'Error: unable to extract "fmt_url_map" or "url_encoded_fmt_stream_map" parameter for unknown reason'
276 reason = unquote_plus(videoinfo['reason'][0])
277 print 'Error: YouTube said: %s' % reason.decode('utf-8')
282 if videoinfo.has_key('url_encoded_fmt_stream_map'):
283 tmp_fmtUrlDATA = videoinfo['url_encoded_fmt_stream_map'][0].split(',url=')
285 tmp_fmtUrlDATA = videoinfo['fmt_url_map'][0].split(',')
286 for fmtstring in tmp_fmtUrlDATA:
287 if videoinfo.has_key('url_encoded_fmt_stream_map'):
288 (fmturl, fmtid) = fmtstring.split('&itag=')
289 if fmturl.find("url=") !=-1:
290 fmturl = fmturl.replace("url=","")
292 (fmtid,fmturl) = fmtstring.split('|')
293 if VIDEO_FMT_PRIORITY_MAP.has_key(fmtid):
294 video_fmt_map[VIDEO_FMT_PRIORITY_MAP[fmtid]] = { 'fmtid': fmtid, 'fmturl': unquote_plus(fmturl) }
295 fmt_infomap[int(fmtid)] = unquote_plus(fmturl)
296 print "got",sorted(fmt_infomap.iterkeys())
297 if video_fmt_map and len(video_fmt_map):
298 video_url = video_fmt_map[sorted(video_fmt_map.iterkeys())[0]]['fmturl'].split(';')[0]
299 #print "found best available video format:",video_fmt_map[sorted(video_fmt_map.iterkeys())[0]]['fmtid']
300 #print "found best available video url:",video_url
303 def run(self, tubeid, session, service):
305 myurl = self.getVideoUrl(tubeid)
306 print "Playing URL", myurl
308 session.open(MessageBox, _("Sorry, video is not available!"), MessageBox.TYPE_INFO)
310 myreference = eServiceReference(4097, 0, myurl)
311 session.open(VuPlayer, myreference, service)
312 except Exception, msg:
314 print "Error >>", msg
316 class VuPlayerService:
317 def __init__(self, session):
319 self.socket_timeout = 0
320 self.max_buffer_size = 1024
321 self.uds_file = "/tmp/vuplus.tmp"
322 self.session = session
324 os.remove(self.uds_file)
328 def start(self, timeout = 1):
329 self.socket_timeout = timeout
330 thread.start_new_thread(self.run, (True,))
338 def run(self, e = True):
341 print "VuPlayerService start!!"
343 self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
344 self.sock.settimeout(self.socket_timeout)
345 self.sock.bind(self.uds_file)
349 conn, addr = self.sock.accept()
350 self.parseHandle(conn, addr)
351 except socket.timeout:
352 #print "[socket timeout]"
354 print "VuPlayerService stop!!"
356 def parseHandle(self, conn, addr):
357 # [http://www.youtube.com/watch?v=BpThu778qB4&feature=related]
358 data = conn.recv(self.max_buffer_size)
359 print "[%s]" % (data)
360 enable_rc_mouse(False)
361 if data.startswith("http://www.youtube.com"):
362 print "youtube start!!"
363 tmp = data.split("?")
364 print tmp # ['http://www.youtube.com/watch', 'v=BpThu778qB4&feature=related']
365 service = self.session.nav.getCurrentlyPlayingServiceReference()
366 if len(tmp) == 2 and tmp[0] == "http://www.youtube.com/watch":
367 tmp = tmp[1].split("&")
368 print tmp # ['v=BpThu778qB4', 'feature=related']
370 tmp = tmp[0].split("=")
371 print tmp # ['v', 'BpThu778qB4']
372 if len(tmp) == 2 and tmp[0] == "v":
374 player = VuPlayerLauncher()
375 player.run(tmp[1], self.session, service)
378 self.session.nav.playService(service)
381 data = "nok$parsing fail"
383 data = "nok$parsing fail"
385 data = "nok$parsing fail"
386 self.sendResponse(conn, data)
387 elif data.startswith("vk://open"):
388 print "virtual keyboard start!!"
389 from Screens.VirtualKeyBoard import VirtualKeyBoard
392 self.session.openWithCallback(self.cbOpenKeyboard, VirtualKeyBoard, title = (_("Enter your input data")), text = "")
394 def cbOpenKeyboard(self, data = None):
395 print "virtual keyboard callback!!"
397 self.sendResponse(self.vk_conn, data)
399 def sendResponse(self, conn, data):
400 if data is None or len(data) == 0:
402 enable_rc_mouse(True)
406 class BrowserLauncher(ConfigListScreen, Screen):
408 <screen name="BrowserLauncher" position="center,center" size="309,498" title="Web Browser">
409 <ePixmap pixmap="Vu_HD/buttons/red.png" position="4,0" size="40,40" alphatest="on" />
410 <ePixmap pixmap="Vu_HD/buttons/green.png" position="154,0" size="40,40" alphatest="on" />
412 <widget source="key_red" render="Label" position="30,0" zPosition="1" size="125,30" font="Regular;20" halign="center" valign="center" transparent="1" />
413 <widget source="key_green" render="Label" position="180,0" zPosition="1" size="125,30" font="Regular;20" halign="center" valign="center" transparent="1" />
415 <widget name="config" position="0,50" size="309,100" scrollbarMode="showOnDemand" />
416 <ePixmap pixmap="Vu_HD/rc_wb_desc.png" position="0,150" size="309,296" alphatest="on" />
417 <widget name="info" position="0,455" size="309,50" font="Regular;18" halign="center" foregroundColor="blue" transparent="1" />
421 def __init__(self, session):
422 Screen.__init__(self, session)
423 self.session = session
425 ConfigListScreen.__init__(self, self.list)
427 self.browser_root = "/usr/bin"
428 self.browser_name = "arora"
429 self.conf_file = "/usr/lib/enigma2/python/Plugins/Extensions/WebBrowser/settings.conf"
430 self["actions"] = ActionMap(["OkCancelActions", "ShortcutActions", "WizardActions", "ColorActions", "SetupActions", ],
431 { "red": self.keyCancel,
433 "cancel": self.keyExit,
435 self.info = Label(_("If you want to quit the Browser,\nPress RED -> EXIT."))
436 self["info"] = self.info
437 self["key_red"] = StaticText(_("Exit"))
438 self["key_green"] = StaticText(_("Start"))
442 self.conf_keyboard = ""
443 self.conf_keymap = ""
445 self.usb_mouse = None
446 self.usb_keyboard = None
448 self.rc_keyboard = None
454 self.vu_service = VuPlayerService(self.session)
455 self.vu_service.start(timeout=5)
457 self.exit_wait_cond = False
458 self.timer_exit_cond = eTimer()
459 self.timer_exit_cond.callback.append(self.resetExitCond)
461 self.test_cond = True
462 self.current_lang_idx = language.getActiveLanguageIndex()
468 change_galpha(set_const=False, set_value=False)
470 self.vu_service.stop()
471 excute_cmd("killall -15 %s"%(self.browser_name))
472 excute_cmd("echo 60 > /proc/sys/vm/swappiness")
473 enable_rc_mouse(False) #rc-mouse off
474 language.activateLanguageIndex(self.current_lang_idx)
475 fbClass.getInstance().unlock()
476 #eRCInput.getInstance().unlock()
480 if self.exit_wait_cond:
482 if is_process_running(self.browser_name) == False:
486 if is_process_running(self.browser_name) == False:
487 ConfigListScreen.keyLeft(self)
489 alpha_value = self.alpha.value
493 if is_process_running(self.browser_name) == False:
494 ConfigListScreen.keyRight(self)
495 alpha_value = self.alpha.value
499 if is_process_running(self.browser_name) == False:
501 self.exit_wait_cond = True
502 self.timer_exit_cond.start(5000)
504 # mouse:keyboard:alpha_value
505 def saveConfig(self):
506 if is_process_running(self.browser_name) == False:
507 command = "echo \"%s:%s:%d:%s\" > %s"%(self.mouse.value, self.keyboard.value, int(self.alpha.value), self.langs.value, self.conf_file)
510 # mouse:keyboard:alpha_value
511 def loadConfig(self):
512 if os.path.exists(self.conf_file) == False:
514 config_list = open(self.conf_file).readline().strip().split(':')
515 if len(config_list) == 3:
516 self.conf_mouse = config_list[0]
517 self.conf_keyboard = config_list[1]
518 self.conf_alpha = config_list[2]
519 elif len(config_list) == 4:
520 self.conf_mouse = config_list[0]
521 self.conf_keyboard = config_list[1]
522 self.conf_alpha = config_list[2]
523 self.conf_keymap = config_list[3]
524 print "load config : ", config_list
526 def resetExitCond(self):
527 self.timer_exit_cond.stop()
528 self.exit_wait_cond = False
530 def makeConfig(self):
532 self.devices_string = ""
533 self.devices = eConsoleAppContainer()
534 self.devices.dataAvail.append(self.callbackDevicesDataAvail)
535 self.devices.appClosed.append(self.callbakcDevicesAppClose)
536 self.devices.execute(_("cat /proc/bus/input/devices"))
538 def callbackDevicesDataAvail(self, ret_data):
539 self.devices_string = self.devices_string + ret_data
541 def callbakcDevicesAppClose(self, retval):
543 self.mouse_list = None
544 self.keyboard_list = None
546 self.makeHandlerList(self.devices_string)
548 if self.conf_mouse == "" or self.getHandlerName(self.conf_mouse) is None:
549 self.conf_mouse = self.mouse_list[0][0]
550 self.mouse = ConfigSelection(default = self.conf_mouse, choices = self.mouse_list)
551 self.list.append(getConfigListEntry(_('Mouse'), self.mouse))
553 if self.conf_keyboard == "" or self.getHandlerName(self.conf_keyboard) is None:
554 self.conf_keyboard = self.keyboard_list[0][0]
555 self.keyboard = ConfigSelection(default = self.conf_keyboard, choices = self.keyboard_list)
556 self.list.append(getConfigListEntry(_('Keyboard'), self.keyboard))
558 if self.conf_alpha == "":
559 self.conf_alpha = "255"
560 self.alpha = ConfigSlider(default = int(self.conf_alpha), increment = 10, limits = (0, 255))
561 self.list.append(getConfigListEntry(_("Alpha Value"), self.alpha))
563 if self.conf_keymap == "":
564 self.conf_keymap = self.getLanguage()
565 self.lang_list = [("en", "English"), ("de", "German")]
566 self.langs = ConfigSelection(default = self.conf_keymap, choices = self.lang_list)
567 self.list.append(getConfigListEntry(_("Language"), self.langs))
569 self["config"].list = self.list
570 self["config"].l.setList(self.list)
572 def getLanguage(self, lang=language.getLanguage()):
573 if self.current_lang_idx == 1:
577 def makeHandlerList(self, data):
583 lines = data.split('\n')
586 if line is not None and len(line) > 0:
596 h_list = line[12:].strip().split()
597 tn = line[12:].strip().find("mouse")
599 event_list.append((h, _(h)))
600 self.name_list.append((h, n))
601 if n[1:].startswith("dream") and self.rc_mouse is None:
602 self.rc_mouse = copy.deepcopy(h)
603 self.rc_keyboard = copy.deepcopy(h)
604 print "detected!! rc"
606 if h.startswith("mouse") and self.usb_mouse is None:
607 self.usb_mouse = copy.deepcopy(h)
608 print "detected!! usb mouse"
610 if tn == -1 and self.usb_keyboard is None:
611 self.usb_keyboard = copy.deepcopy(h)
612 print "detected!! usb keyboard"
613 elif line[0] == 'B' and line[3:].startswith("ABS") and p.startswith("usb-"):
615 if self.usb_mouse is not None:
617 if self.usb_keyboard is not None and h == self.usb_keyboard[0]:
618 self.usb_keyboard = None
619 print "clean!! usb keyboard"
620 self.usb_mouse = copy.deepcopy(h)
621 print "detected!! usb mouse"
623 tmp = copy.deepcopy(event_list)
624 if self.usb_mouse is not None:
625 tmp.insert(0, ("musb", "USB Mouse"))
626 if self.rc_mouse is not None:
627 tmp.insert(0, ("mrc", "Remote Control"))
628 self.mouse_list = tmp
630 tmp = copy.deepcopy(event_list)
631 if self.usb_keyboard is not None:
632 tmp.insert(0, ("kusb", "USB Keyboard"))
633 if self.rc_keyboard is not None:
634 tmp.insert(0, ("krc", "Remote Control"))
635 self.keyboard_list = tmp
636 print "E:", event_list
637 print "M:", self.mouse_list
638 print "K:", self.keyboard_list
640 def startBrowser(self):
641 self.timer_start.stop()
644 excute_cmd("killall -15 %s"%(self.browser_name))
645 excute_cmd("echo 0 > /proc/sys/vm/swappiness")
649 extra_cmd = "export VU_DOWNLOAD_DIR=/tmp; "
650 browser_cmd = "%s/%s -qws" % (self.browser_root, self.browser_name)
652 mouse_param = self.mouse.value
653 if self.mouse.value == "mrc":
654 mouse_param = self.rc_mouse
655 elif self.mouse.value == "musb":
656 mouse_param = self.usb_mouse
657 keyboard_param = self.keyboard.value
658 if self.keyboard.value == "krc":
659 keyboard_param = self.rc_keyboard
660 elif self.keyboard.value == "kusb":
661 keyboard_param = self.usb_keyboard
663 if self.getHandlerName(mouse_param)[1:].startswith("dreambox"):
664 enable_rc_mouse(True) #rc-mouse on
665 if str(mouse_param).startswith("event"):
666 mouse_cmd = "export QWS_MOUSE_PROTO=LinuxInput:/dev/input/%s; " % (str(mouse_param))
669 if self.langs.value == "de":
670 keymap_param = ":keymap=/usr/share/keymaps/vuplus/de.qmap"
671 kbd_cmd = "export QWS_KEYBOARD=LinuxInput:/dev/input/%s%s; " % (str(keyboard_param), keymap_param)
673 cmd = "%s%s%s%s" % (extra_cmd, kbd_cmd, mouse_cmd, browser_cmd)
674 print "prepared command : [%s]" % cmd
676 self.launcher = eConsoleAppContainer()
677 self.launcher.appClosed.append(self.callbackLauncherAppClosed)
678 self.launcher.dataAvail.append(self.callbackLauncherDataAvail)
680 fbClass.getInstance().lock()
681 #eRCInput.getInstance().lock()
684 alpha_value = self.alpha.value
685 change_galpha(set_const=True, set_value=True)
687 self.launcher.execute(cmd)
688 print "started browser..."
692 self.info.setText("Starting Webbrowser. Please wait...")
693 if self.lock == False:
694 if self.langs.value == "de":
695 language.activateLanguageIndex(1)
697 language.activateLanguageIndex(0)
698 self.timer_start = eTimer()
699 self.timer_start.callback.append(self.startBrowser)
700 self.timer_start.start(10)
702 def getHandlerName(self, v):
710 v = self.usb_keyboard
711 for l in self.name_list:
716 def callbackLauncherDataAvail(self, ret_data):
718 if ret_data.startswith("--done--"):
722 def callbackLauncherAppClosed(self, retval = 1):
725 def sessionstart(session, **kwargs):
726 enable_rc_mouse(False)
727 change_galpha(set_const=False, set_value=True)
728 excute_cmd("killall -15 arora")
730 def main(session, **kwargs):
731 session.open(BrowserLauncher)
733 def Plugins(**kwargs):
734 return [PluginDescriptor(where = PluginDescriptor.WHERE_SESSIONSTART, needsRestart = False, fnc=sessionstart),
735 PluginDescriptor(name=_("Web Browser"), description="start web browser", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main)]