Enigma2 plugin to to play various online streams (mostly Latvian).

subtitlesdvb.py 25KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  1. '''
  2. Created on Sep 16, 2014
  3. @author: marko
  4. '''
  5. import time
  6. from . import _
  7. from Components.ActionMap import HelpableActionMap
  8. from Components.Label import Label
  9. from Components.Sources.EventInfo import EventInfo
  10. from Components.config import ConfigSubsection, getConfigListEntry
  11. from Components.config import config, ConfigOnOff
  12. from Screens.HelpMenu import HelpableScreen
  13. from compat import MessageBox
  14. from Screens.MinuteInput import MinuteInput
  15. from Screens.Screen import Screen
  16. from e2_utils import getFps, fps_float, BaseMenuScreen
  17. from enigma import eTimer, getDesktop
  18. from parsers.baseparser import ParseError
  19. from process import LoadError, DecodeError, ParserNotFoundError
  20. from skin import parseColor
  21. from subtitles import SubsChooser, initSubsSettings, SubsScreen, \
  22. SubsLoader, PARSERS, ALL_LANGUAGES_ENCODINGS, ENCODINGS, \
  23. warningMessage
  24. config.plugins.subsSupport = ConfigSubsection()
  25. config.plugins.subsSupport.dvb = ConfigSubsection()
  26. config.plugins.subsSupport.dvb.autoSync = ConfigOnOff(default=True)
  27. class SubsSetupDVBPlayer(BaseMenuScreen):
  28. def __init__(self, session, dvbSettings):
  29. BaseMenuScreen.__init__(self, session, _("DVB player settings"))
  30. self.dvbSettings = dvbSettings
  31. def buildMenu(self):
  32. self['config'].setList([getConfigListEntry(_("Auto sync to current event"), self.dvbSettings.autoSync)])
  33. class SubsSupportDVB(object):
  34. def __init__(self, session):
  35. self.session = session
  36. self.subsSettings = initSubsSettings()
  37. session.openWithCallback(self.subsChooserCB, SubsChooser, self.subsSettings, searchSupport=True, historySupport=True, titleList=self.getTitleList())
  38. def getTitleList(self):
  39. eventList = []
  40. eventNow = self.session.screen["Event_Now"].getEvent()
  41. eventNext = self.session.screen["Event_Next"].getEvent()
  42. if eventNow:
  43. eventList.append(eventNow.getEventName())
  44. if eventNext:
  45. eventList.append(eventNext.getEventName())
  46. return eventList
  47. def subsChooserCB(self, subfile=None, embeddedSubtitle=None, forceReload=False):
  48. if subfile is not None:
  49. subsLoader = SubsLoader(PARSERS, ALL_LANGUAGES_ENCODINGS + ENCODINGS[self.subsSettings.encodingsGroup.getValue()])
  50. try:
  51. subsList, subsEnc = subsLoader.load(subfile, fps=getFps(self.session))
  52. except LoadError:
  53. warningMessage(self.session, _("Cannot load subtitles. Invalid path"))
  54. except DecodeError:
  55. warningMessage(self.session, _("Cannot decode subtitles. Try another encoding group"))
  56. except ParserNotFoundError:
  57. warningMessage(self.session, _("Cannot parse subtitles. Not supported subtitles format"))
  58. except ParseError:
  59. warningMessage(self.session, _("Cannot parse subtitles. Invalid subtitles format"))
  60. else:
  61. self.subsScreen = self.session.instantiateDialog(SubsScreen, self.subsSettings.external)
  62. subsEngine = SubsEngineDVB(self.session, self.subsSettings.engine, self.subsScreen)
  63. subsEngine.setSubsList(subsList)
  64. self.session.openWithCallback(self.subsControllerCB, SubsControllerDVB, subsEngine, config.plugins.subsSupport.dvb.autoSync.value)
  65. else:
  66. print '[SubsSupportDVB] no subtitles selected, exit'
  67. def subsControllerCB(self):
  68. self.session.deleteDialog(self.subsScreen)
  69. class SubsControllerDVB(Screen, HelpableScreen):
  70. fpsChoices = ["23.976", "23.980","24.000", "25.000", "29.970", "30.000"]
  71. def __init__(self, session, engine, autoSync=False, setSubtitlesFps=False, subtitlesFps=None):
  72. desktopWidth = getDesktop(0).size().width()
  73. offset = 20
  74. screenWidth = desktopWidth - (2 * offset)
  75. widgetWidth = screenWidth / 2 - 5
  76. self.skin = """
  77. <screen position="%d,0" size="%d,140" zPosition="2" backgroundColor="transparent" flags="wfNoBorder">
  78. <widget name="subtitle" position="0,0" size="%d,30" valign="center" halign="left" font="Regular;22" transparent="1" foregroundColor="#ffffff" shadowColor="#40101010" shadowOffset="2,2" />
  79. <widget name="subtitlesTime" position="0,35" size="%d,30" valign="center" halign="left" font="Regular;22" transparent="1" foregroundColor="#ffffff" shadowColor="#40101010" shadowOffset="2,2" />
  80. <widget name="subtitlesPosition" position="0,70" size="%d,30" valign="center" halign="left" font="Regular;22" transparent="1" foregroundColor="#ffffff" shadowColor="#40101010" shadowOffset="2,2" />
  81. <widget name="subtitlesFps" position="0,105" size="%d,30" valign="center" halign="left" font="Regular;22" transparent="1" foregroundColor="#6F9EF5" shadowColor="#40101010" shadowOffset="2,2" />
  82. <widget name="eventName" position="%d,0" size="%d,30" valign="center" halign="left" font="Regular;22" transparent="1" foregroundColor="#ffffff" shadowColor="#40101010" shadowOffset="2,2" />
  83. <widget name="eventTime" position="%d,35" size="%d,30" valign="center" halign="left" font="Regular;22" transparent="1" foregroundColor="#ffffff" shadowColor="#40101010" shadowOffset="2,2" />
  84. <widget name="eventDuration" position="%d,70" size="%d,30" valign="center" halign="left" font="Regular;22" transparent="1" foregroundColor="#ffffff" shadowColor="#40101010" shadowOffset="2,2" />
  85. </screen>""" % (offset, screenWidth,
  86. widgetWidth, widgetWidth, widgetWidth, widgetWidth,
  87. widgetWidth + 5, widgetWidth, widgetWidth + 5, widgetWidth, widgetWidth + 5, widgetWidth)
  88. Screen.__init__(self, session)
  89. HelpableScreen.__init__(self)
  90. self.engine = engine
  91. self.engine.onRenderSub.append(self.onRenderSub)
  92. self.engine.onHideSub.append(self.onHideSub)
  93. self.engine.onPositionUpdate.append(self.onUpdateSubPosition)
  94. subtitlesFps = subtitlesFps and fps_float(subtitlesFps)
  95. if subtitlesFps and str(subtitlesFps) in self.fpsChoices:
  96. self.providedSubtitlesFps = subtitlesFps
  97. else:
  98. self.providedSubtitlesFps = None
  99. self.hideTimer = eTimer()
  100. self.hideTimer.callback.append(self.hideStatus)
  101. self.hideTimerDelay = 5000
  102. self.eventTimer = eTimer()
  103. self.eventTimer.callback.append(self.updateEventStatus)
  104. self.subtitlesTimer = eTimer()
  105. self.subtitlesTimer.callback.append(self.updateSubtitlesTime)
  106. self.subtitlesTimerStep = 500
  107. self._baseTime = 0
  108. self._accTime = 0
  109. self.statusLocked = False
  110. self['subtitle'] = Label()
  111. self['subtitlesPosition'] = Label(_("Subtitles Position") + ":")
  112. self['subtitlesTime'] = Label(_("Subtitles Time") + ":")
  113. self['subtitlesFps'] = Label(_("Subtitles FPS") + ":")
  114. self["eventName"] = Label(_("Event Name") + ":")
  115. self["eventTime"] = Label(_("Event Time") + ":")
  116. self["eventDuration"] = Label(_("Event Duration") + ":")
  117. self['actions'] = HelpableActionMap(self, "SubtitlesDVBActions",
  118. {
  119. "closePlugin": (self.close, _("close plugin")),
  120. "showHideStatus": (self.showHideStatus, _("show/hide subtitles status")),
  121. "playPauseSub": (self.playPause, _("play/pause subtitles playback")),
  122. "pauseSub": (self.pause, _("pause subtitles playback")),
  123. "resumeSub": (self.resume, _("resumes subtitles playback")),
  124. "restartSub":(self.restart, _("restarts current subtitle")),
  125. "nextSub": (self.nextSkip, _("skip to next subtitle")),
  126. "nextSubMinute": (self.nextMinuteSkip, _("skip to next subtitle (minute jump)")),
  127. "nextSubManual":(self.nextManual, _("skip to next subtitle by setting time in minutes")),
  128. "prevSub":(self.previousSkip, _("skip to previous subtitle")),
  129. "prevSubMinute":(self.previousMinuteSkip, _("skip to previous subtitle (minute jump)")),
  130. "prevSubManual":(self.previousManual, _("skip previous subtitle by setting time in minutes")),
  131. "eventSync":(self.eventSync, _("skip subtitle to current event position")),
  132. "changeFps":(self.changeFps, _("change subtitles fps")),
  133. }, 0)
  134. try:
  135. from Screens.InfoBar import InfoBar
  136. InfoBar.instance.subtitle_window.hide()
  137. except:
  138. pass
  139. self.onLayoutFinish.append(self.hideStatus)
  140. self.onLayoutFinish.append(self.engine.start)
  141. self.onLayoutFinish.append(self.startEventTimer)
  142. self.onLayoutFinish.append(self.startSubtitlesTimer)
  143. self.onLayoutFinish.append(self.showStatusWithTimer)
  144. if setSubtitlesFps and self.providedSubtitlesFps:
  145. self.onFirstExecBegin.append(self.setProvidedSubtitlesFps)
  146. if autoSync:
  147. self.onFirstExecBegin.append(self.eventSync)
  148. self.onClose.append(self.engine.close)
  149. self.onClose.append(self.stopTimers)
  150. def startEventTimer(self):
  151. self.eventTimer.start(500)
  152. def startSubtitlesTimer(self):
  153. self.subtitlesTimer.start(self.subtitlesTimerStep)
  154. def setProvidedSubtitlesFps(self):
  155. self.engine.setSubsFps(self.providedSubtitlesFps)
  156. self.updateSubtitlesFps()
  157. def onUpdateSubPosition(self, position):
  158. self.updateSubtitlesPosition(position)
  159. def onRenderSub(self, sub):
  160. if self['subtitle'].visible:
  161. self.updateSubtitle(sub, True)
  162. if self['subtitlesTime'].visible:
  163. self.updateSubtitlesTime(sub)
  164. def onHideSub(self, sub):
  165. if sub == self.engine.subsList[-1]:
  166. self.subtitlesTimer.stop()
  167. if self['subtitle'].visible:
  168. nextSubIdx = self.engine.subsList.index(sub) + 1
  169. if nextSubIdx >= len(self.engine.subsList) - 1:
  170. nextSub = None
  171. else:
  172. nextSub = self.engine.subsList[nextSubIdx]
  173. self.updateSubtitle(nextSub, active=False)
  174. def showStatusWithTimer(self):
  175. self.showStatus(True)
  176. def showStatus(self, withTimer=False):
  177. sub = self.engine.getCurrentSub()
  178. active = self.engine.renderer.subShown
  179. self.updateSubtitle(sub, active)
  180. self.updateSubtitlesFps()
  181. self.updateSubtitlesPosition()
  182. self.updateEventStatus()
  183. self['subtitle'].visible = True
  184. self['subtitlesPosition'].visible = True
  185. self['subtitlesTime'].visible = True
  186. self['subtitlesFps'].visible = True
  187. self['eventName'].visible = True
  188. self['eventTime'].visible = True
  189. self['eventDuration'].visible = True
  190. if withTimer and not self.statusLocked:
  191. self.hideTimer.start(self.hideTimerDelay, True)
  192. def hideStatus(self):
  193. self['subtitle'].visible = False
  194. self['subtitlesPosition'].visible = False
  195. self['subtitlesTime'].visible = False
  196. self['subtitlesFps'].visible = False
  197. self['eventName'].visible = False
  198. self['eventTime'].visible = False
  199. self['eventDuration'].visible = False
  200. def updateSubtitle(self, sub, active):
  201. if sub is None:
  202. self['subtitle'].setText("")
  203. return
  204. st = sub['start'] * self.engine.fpsRatio / 90000
  205. et = sub['end'] * self.engine.fpsRatio / 90000
  206. stStr = "%d:%02d:%02d" % ((st / 3600, st % 3600 / 60, st % 60))
  207. etStr = "%d:%02d:%02d" % ((et / 3600, et % 3600 / 60, et % 60))
  208. if active:
  209. self['subtitle'].instance.setForegroundColor(parseColor("#F7A900"))
  210. self['subtitle'].setText("%s ----> %s" % (stStr, etStr))
  211. else:
  212. self['subtitle'].instance.setForegroundColor(parseColor("#aaaaaa"))
  213. self['subtitle'].setText("%s ----> %s" % (stStr, etStr))
  214. def updateSubtitlesPosition(self, position=None):
  215. if position is None:
  216. position = self.engine.subsList.index(self.engine.getCurrentSub())
  217. self['subtitlesPosition'].setText("%s: %d / %d" % (_("Subtitles Position"), position, len(self.engine.subsList) - 1))
  218. def updateSubtitlesTime(self, sub=None):
  219. if sub:
  220. self._baseTime = sub['start'] * self.engine.fpsRatio / 90
  221. self._accTime = 0
  222. if not self.engine.isPaused():
  223. self.startSubtitlesTimer()
  224. else:
  225. self._accTime += self.subtitlesTimerStep
  226. self._subtitlesTime = self._baseTime + self._accTime
  227. if self['subtitlesTime'].visible:
  228. st = self._subtitlesTime / 1000
  229. time = "%d:%02d:%02d" % (st / 3600, st % 3600 / 60, st % 60)
  230. self['subtitlesTime'].setText("%s: %s" % (_("Subtitles Time"), time))
  231. def updateSubtitlesFps(self):
  232. subsFps = self.engine.getSubsFps()
  233. videoFps = getFps(self.session, True)
  234. if subsFps is None or videoFps is None:
  235. self['subtitlesFps'].setText("%s: %s" % (_("Subtitles FPS"), _("unknown")))
  236. return
  237. if subsFps == videoFps:
  238. if self.providedSubtitlesFps is not None:
  239. if self.providedSubtitlesFps == videoFps:
  240. self['subtitlesFps'].setText("%s: %s (%s)" % (_("Subtitles FPS"), _("original"), _("original") ))
  241. else:
  242. self['subtitlesFps'].setText("%s: %s (%s)" % (_("Subtitles FPS"), _("original"), str(self.providedSubtitlesFps) ))
  243. else:
  244. self['subtitlesFps'].setText("%s: %s" % (_("Subtitles FPS"), _("original")))
  245. else:
  246. if self.providedSubtitlesFps is not None:
  247. if self.providedSubtitlesFps == videoFps:
  248. self['subtitlesFps'].setText("%s: %s (%s)" % (_("Subtitles FPS"), str(subsFps), _("original") ))
  249. else:
  250. self['subtitlesFps'].setText("%s: %s (%s)" % (_("Subtitles FPS"), str(subsFps), str(self.providedSubtitlesFps) ))
  251. else:
  252. self['subtitlesFps'].setText("%s: %s" % (_("Subtitles FPS"), str(subsFps)))
  253. def updateEventStatus(self):
  254. event = self.session.screen["Event_Now"].getEvent()
  255. if event is not None:
  256. eventName = event.getEventName()
  257. if eventName:
  258. if self["eventName"].getText() != eventName:
  259. self["eventName"].setText("%s" % eventName)
  260. else:
  261. self["eventName"].setText("%s" % (_("unknown")))
  262. eventStartTime = event.getBeginTime()
  263. if eventStartTime:
  264. ep = int(time.time()) - eventStartTime
  265. self["eventTime"].setText("%s: %d:%02d:%02d" % (_("Time"), ep / 3600, ep % 3600 / 60, ep % 60))
  266. else:
  267. self["eventTime"].setText("%s: %s" % (_("Event Time"), "0:00:00"))
  268. eventDuration = event.getDuration()
  269. if eventDuration:
  270. if eventStartTime:
  271. eventProgress = int(time.time()) - eventStartTime
  272. if eventProgress > eventDuration:
  273. ed = 0
  274. else:
  275. ed = eventDuration
  276. else:
  277. ed = eventDuration
  278. self["eventDuration"].setText("%s: %d:%02d:%02d" % (_("Duration"), ed / 3600, ed % 3600 / 60, ed % 60))
  279. else:
  280. self["eventTime"].setText("%s: %s" % (_("Event Duration"), "0:00:00"))
  281. else:
  282. self["eventName"].setText("")
  283. self["eventTime"].setText("")
  284. self["eventDuration"].setText("")
  285. def changeFps(self):
  286. subsFps = self.engine.getSubsFps()
  287. if subsFps is None:
  288. return
  289. currIdx = self.fpsChoices.index(str(subsFps))
  290. if currIdx == len(self.fpsChoices) - 1:
  291. nextIdx = 0
  292. else:
  293. nextIdx = currIdx + 1
  294. self.engine.setSubsFps(fps_float(self.fpsChoices[nextIdx]))
  295. self.updateSubtitlesFps()
  296. sub = self.engine.getCurrentSub()
  297. active = self.engine.renderer.subShown
  298. self.updateSubtitle(sub, active)
  299. self.updateSubtitlesPosition()
  300. self.showStatus(True)
  301. def showHideStatus(self):
  302. if self['subtitle'].visible:
  303. self.statusLocked = False
  304. self.hideStatus()
  305. else:
  306. self.statusLocked = True
  307. self.showStatus()
  308. def eventSync(self):
  309. event = EventInfo(self.session.nav, EventInfo.NOW).getEvent()
  310. if event is not None:
  311. progress = (int(time.time()) - event.getBeginTime()) * 1000
  312. self.engine.seekTo(progress)
  313. else:
  314. self.session.open(MessageBox, _("cannot sync to event, event is not available"), MessageBox.TYPE_INFO, simple=True, timeout=3)
  315. def playPause(self):
  316. if self.engine.isPaused():
  317. self.resume()
  318. else:
  319. self.pause()
  320. def pause(self):
  321. self.engine.pause()
  322. self.subtitlesTimer.stop()
  323. self.showStatus()
  324. def resume(self):
  325. self.engine.resume()
  326. self.startSubtitlesTimer()
  327. self.showStatus(True)
  328. def restart(self):
  329. self.engine.pause()
  330. self.engine.resume()
  331. self.showStatus(True)
  332. def nextSkip(self):
  333. self.engine.toNextSub()
  334. self.showStatus(True)
  335. def nextMinuteSkip(self):
  336. self.engine.seekRelative(60 * 1000)
  337. self.showStatus(True)
  338. def nextManual(self):
  339. def nextManualCB(minutes):
  340. if minutes > 0:
  341. self.engine.seekRelative(minutes* 60 * 1000)
  342. self.showStatus(True)
  343. self.session.openWithCallback(nextManualCB, MinuteInput)
  344. def previousSkip(self):
  345. self.engine.toPrevSub()
  346. self.showStatus(True)
  347. def previousMinuteSkip(self):
  348. self.engine.seekRelative(-60 * 1000)
  349. self.showStatus(True)
  350. def previousManual(self):
  351. def previousManualCB(minutes):
  352. if minutes > 0:
  353. self.engine.seekRelative(-minutes* 60 * 1000)
  354. self.showStatus(True)
  355. self.session.openWithCallback(previousManualCB, MinuteInput)
  356. def stopTimers(self):
  357. self.hideTimer.stop()
  358. self.eventTimer.stop()
  359. self.subtitlesTimer.stop()
  360. class SubsEngineDVB(object):
  361. def __init__(self, session, engineSettings, renderer):
  362. self.session = session
  363. self.renderer = renderer
  364. self.delay = 0
  365. self.__position = 0
  366. self.fpsRatio = 1
  367. self.subsList = None
  368. self.paused = True
  369. self.waitTimer = eTimer()
  370. self.waitTimer.callback.append(self.doWait)
  371. self.hideTimer = eTimer()
  372. self.hideTimer.callback.append(self.hideTimerCallback)
  373. self.onRenderSub = []
  374. self.onHideSub = []
  375. self.onPositionUpdate = []
  376. def setSubsList(self, subsList):
  377. self.subsList = subsList
  378. def setSubsFps(self, subsFps):
  379. print "[SubsEngineDVB] setSubsFps - setting fps to %s" % str(subsFps)
  380. videoFps = getFps(self.session, True)
  381. if videoFps is None:
  382. print "[SubsEngineDVB] setSubsFps - cannot get video fps!"
  383. else:
  384. self.waitTimer.stop()
  385. self.hideTimer.stop()
  386. self.fpsRatio = subsFps / float(videoFps)
  387. self.renderSub()
  388. if not self.paused:
  389. self.setRefTime()
  390. self.startHideTimer()
  391. def setPosition(self, position):
  392. if position > len(self.subsList) - 1:
  393. return
  394. self.__position = position
  395. for f in self.onPositionUpdate:
  396. f(self.__position)
  397. def getPosition(self):
  398. return self.__position
  399. position = property(getPosition, setPosition)
  400. def getSubsFps(self):
  401. videoFps = getFps(self.session, True)
  402. if videoFps is None:
  403. return None
  404. return fps_float(self.fpsRatio * videoFps)
  405. def getCurrentSub(self):
  406. return self.subsList[self.position]
  407. def setRefTime(self):
  408. self.reftime = time.time() * 1000
  409. self.refposition = self.position
  410. self.delay = 0
  411. def isPaused(self):
  412. return self.paused
  413. def start(self):
  414. self.renderer.show()
  415. self.resume()
  416. def pause(self):
  417. self.waitTimer.stop()
  418. self.hideTimer.stop()
  419. self.paused = True
  420. def resume(self):
  421. self.waitTimer.stop()
  422. self.hideTimer.stop()
  423. self.setRefTime()
  424. self.renderSub()
  425. self.paused = False
  426. self.startHideTimer()
  427. def renderSub(self):
  428. for f in self.onRenderSub:
  429. f(self.subsList[self.position])
  430. self.renderer.setSubtitle(self.subsList[self.position])
  431. def hideSub(self):
  432. for f in self.onHideSub:
  433. f(self.subsList[self.position])
  434. self.renderer.hideSubtitle()
  435. def startHideTimer(self):
  436. self.hideTimer.start(int(self.subsList[self.position]['duration'] * self.fpsRatio), True)
  437. def hideTimerCallback(self):
  438. self.hideTimer.stop()
  439. self.waitTimer.stop()
  440. if self.position == len(self.subsList) - 1:
  441. self.hideSub()
  442. elif self.subsList[self.position]['end']*self.fpsRatio + (200 * 90) < self.subsList[self.position + 1]['start'] * self.fpsRatio:
  443. self.hideSub()
  444. if self.position < len(self.subsList) - 1:
  445. self.position += 1
  446. self.toTime = self.reftime + ((self.subsList[self.position]['start'] - self.subsList[self.refposition]['start'])/90 * self.fpsRatio)
  447. timeout = ((self.subsList[self.position]['start'] - self.subsList[self.position - 1]['end']) / 90 * self.fpsRatio) + self.delay
  448. self.waitTimer.start(int(timeout), True)
  449. def doWait(self):
  450. timeNow = time.time() * 1000
  451. delay = int(self.toTime - timeNow)
  452. if delay > 50:
  453. self.waitTimer.start(delay, True)
  454. elif delay <= 50 and delay >= 0:
  455. print "[SubsEngineDVB] sub shown sooner by %s ms" % (delay)
  456. self.delay = 0
  457. self.waitTimer.stop()
  458. self.renderSub()
  459. self.startHideTimer()
  460. else:
  461. print "[SubsEngineDVB] sub shown later by %s ms" % (abs(delay))
  462. self.delay = delay
  463. self.waitTimer.stop()
  464. self.renderSub()
  465. self.startHideTimer()
  466. def seekTo(self, time):
  467. self.waitTimer.stop()
  468. self.hideTimer.stop()
  469. print "[SubsEngineDVB] seekTo, position before seek: %d" % self.position
  470. firstSub = self.subsList[0]
  471. lastSub = self.subsList[-1]
  472. position = self.position
  473. if time > lastSub['start'] / 90 * self.fpsRatio:
  474. position = self.subsList.index(lastSub)
  475. elif time < firstSub['start'] / 90 * self.fpsRatio:
  476. position = 0
  477. elif abs(time - (firstSub['start'] / 90 * self.fpsRatio)) < abs(time - (lastSub['start'] / 90 * self.fpsRatio)):
  478. position = 0
  479. subStartTime = firstSub['start'] / 90 * self.fpsRatio
  480. while time > subStartTime:
  481. position += 1
  482. subStartTime = self.subsList[position]['start'] / 90 * self.fpsRatio
  483. else:
  484. position = self.subsList.index(lastSub)
  485. subStartTime = lastSub['start'] / 90 * self.fpsRatio
  486. while time < subStartTime:
  487. position -= 1
  488. subStartTime = self.subsList[position]['start'] / 90 * self.fpsRatio
  489. self.position = position
  490. print "[SubsEngineDVB] seekTo, position after seek: %d" % (self.position)
  491. self.renderSub()
  492. if not self.paused:
  493. self.setRefTime()
  494. self.startHideTimer()
  495. def seekRelative(self, time):
  496. self.waitTimer.stop()
  497. self.hideTimer.stop()
  498. print "[SubsEngine] seekRelative, position before seek: %d" % self.position
  499. startSubTime = self.subsList[self.position]['start'] / 90 * self.fpsRatio
  500. position = self.position
  501. if time > 0:
  502. nextStartSubTime = 0
  503. while position != len(self.subsList) - 1 and time > nextStartSubTime:
  504. position += 1
  505. nextStartSubTime = ((self.subsList[position]['start']) / 90 * self.fpsRatio) - startSubTime
  506. else:
  507. prevEndSubTime = 0
  508. while position != 0 and time < prevEndSubTime:
  509. position -= 1
  510. prevEndSubTime = (self.subsList[position]['end'] / 90 * self.fpsRatio) - startSubTime
  511. self.position = position
  512. print "[SubsEngine] seekRelative, position after seek: %d" % self.position
  513. self.renderSub()
  514. if not self.paused:
  515. self.setRefTime()
  516. self.startHideTimer()
  517. def toNextSub(self):
  518. self.waitTimer.stop()
  519. self.hideTimer.stop()
  520. if self.renderer.subShown and self.position < len(self.subsList) - 1:
  521. self.position += 1
  522. self.renderSub()
  523. if not self.paused:
  524. self.setRefTime()
  525. self.startHideTimer()
  526. def toPrevSub(self):
  527. self.waitTimer.stop()
  528. self.hideTimer.stop()
  529. if self.position > 0:
  530. self.position -= 1
  531. self.renderSub()
  532. if not self.paused:
  533. self.setRefTime()
  534. self.startHideTimer()
  535. def close(self):
  536. self.waitTimer.stop()
  537. self.hideTimer.stop()