fix wrap around with enabled movemode
[enigma2.git] / lib / python / Screens / InfoBarGenerics.py
1 from Screen import Screen
2 from Components.ActionMap import ActionMap, HelpableActionMap
3 from Components.ActionMap import NumberActionMap
4 from Components.Label import *
5 from Components.ProgressBar import *
6 from Components.config import configfile, configsequencearg
7 from Components.config import config, configElement, ConfigSubsection, configSequence
8 from ChannelSelection import ChannelSelection, BouquetSelector
9
10 from Components.Pixmap import Pixmap, PixmapConditional
11 from Components.BlinkingPixmap import BlinkingPixmapConditional
12 from Components.ServiceName import ServiceName
13 from Components.EventInfo import EventInfo, EventInfoProgress
14
15 from ServiceReference import ServiceReference
16 from EpgSelection import EPGSelection
17
18 from Screens.MessageBox import MessageBox
19 from Screens.Dish import Dish
20 from Screens.Standby import Standby
21 from Screens.EventView import EventViewEPGSelect
22 from Screens.MinuteInput import MinuteInput
23 from Components.Harddisk import harddiskmanager
24
25 from Components.ServiceEventTracker import ServiceEventTracker
26
27 from Tools import Notifications
28 from Tools.Directories import *
29
30 #from enigma import eTimer, eDVBVolumecontrol, quitMainloop
31 from enigma import *
32
33 import time
34 import os
35 import bisect
36
37 from Components.config import config, currentConfigSelectionElement
38
39 # hack alert!
40 from Menu import MainMenu, mdom
41
42 class InfoBarDish:
43         def __init__(self):
44                 self.dishDialog = self.session.instantiateDialog(Dish)
45                 self.onLayoutFinish.append(self.dishDialog.show)
46
47 class InfoBarShowHide:
48         """ InfoBar show/hide control, accepts toggleShow and hide actions, might start
49         fancy animations. """
50         STATE_HIDDEN = 0
51         STATE_HIDING = 1
52         STATE_SHOWING = 2
53         STATE_SHOWN = 3
54         
55         def __init__(self):
56                 self["ShowHideActions"] = ActionMap( ["InfobarShowHideActions"] ,
57                         {
58                                 "toggleShow": self.toggleShow,
59                                 "hide": self.hide,
60                         })
61
62                 self.__state = self.STATE_SHOWN
63                 self.__locked = 0
64                 
65                 self.onExecBegin.append(self.show)
66                 
67                 self.hideTimer = eTimer()
68                 self.hideTimer.timeout.get().append(self.doTimerHide)
69                 self.hideTimer.start(5000, True)
70                 
71                 self.onShow.append(self.__onShow)
72                 self.onHide.append(self.__onHide)
73
74         def __onShow(self):
75                 self.__state = self.STATE_SHOWN
76                 self.startHideTimer()
77         
78         def startHideTimer(self):
79                 if self.__state == self.STATE_SHOWN and not self.__locked:
80                         self.hideTimer.start(5000, True)
81
82         def __onHide(self):
83                 self.__state = self.STATE_HIDDEN
84
85         def doShow(self):
86                 self.show()
87                 self.startHideTimer()
88
89         def doTimerHide(self):
90                 self.hideTimer.stop()
91                 if self.__state == self.STATE_SHOWN:
92                         self.hide()
93
94         def toggleShow(self):
95                 if self.__state == self.STATE_SHOWN:
96                         self.hide()
97                         self.hideTimer.stop()
98                 elif self.__state == self.STATE_HIDDEN:
99                         self.show()
100
101         def lockShow(self):
102                 self.__locked = self.__locked + 1
103                 if self.execing:
104                         self.show()
105                         self.hideTimer.stop()
106         
107         def unlockShow(self):
108                 self.__locked = self.__locked - 1
109                 if self.execing:
110                         self.startHideTimer()
111
112 #       def startShow(self):
113 #               self.instance.m_animation.startMoveAnimation(ePoint(0, 600), ePoint(0, 380), 100)
114 #               self.__state = self.STATE_SHOWN
115 #       
116 #       def startHide(self):
117 #               self.instance.m_animation.startMoveAnimation(ePoint(0, 380), ePoint(0, 600), 100)
118 #               self.__state = self.STATE_HIDDEN
119
120 class NumberZap(Screen):
121         def quit(self):
122                 self.Timer.stop()
123                 self.close(0)
124
125         def keyOK(self):
126                 self.Timer.stop()
127                 self.close(int(self["number"].getText()))
128
129         def keyNumberGlobal(self, number):
130                 self.Timer.start(3000, True)            #reset timer
131                 self.field = self.field + str(number)
132                 self["number"].setText(self.field)
133                 if len(self.field) >= 4:
134                         self.keyOK()
135
136         def __init__(self, session, number):
137                 Screen.__init__(self, session)
138                 self.field = str(number)
139
140                 self["channel"] = Label(_("Channel:"))
141
142                 self["number"] = Label(self.field)
143
144                 self["actions"] = NumberActionMap( [ "SetupActions" ], 
145                         {
146                                 "cancel": self.quit,
147                                 "ok": self.keyOK,
148                                 "1": self.keyNumberGlobal,
149                                 "2": self.keyNumberGlobal,
150                                 "3": self.keyNumberGlobal,
151                                 "4": self.keyNumberGlobal,
152                                 "5": self.keyNumberGlobal,
153                                 "6": self.keyNumberGlobal,
154                                 "7": self.keyNumberGlobal,
155                                 "8": self.keyNumberGlobal,
156                                 "9": self.keyNumberGlobal,
157                                 "0": self.keyNumberGlobal
158                         })
159
160                 self.Timer = eTimer()
161                 self.Timer.timeout.get().append(self.keyOK)
162                 self.Timer.start(3000, True)
163
164 class InfoBarPowerKey:
165         """ PowerKey stuff - handles the powerkey press and powerkey release actions"""
166         
167         def __init__(self):
168                 self.powerKeyTimer = eTimer()
169                 self.powerKeyTimer.timeout.get().append(self.powertimer)
170                 self["PowerKeyActions"] = HelpableActionMap(self, "PowerKeyActions",
171                         {
172                                 "powerdown": self.powerdown,
173                                 "powerup": self.powerup,
174                                 "discreteStandby": (self.standby, "Go standby"),
175                                 "discretePowerOff": (self.quit, "Go to deep standby"),
176                         })
177
178         def powertimer(self):   
179                 print "PowerOff - Now!"
180                 self.quit()
181         
182         def powerdown(self):
183                 self.standbyblocked = 0
184                 self.powerKeyTimer.start(3000, True)
185
186         def powerup(self):
187                 self.powerKeyTimer.stop()
188                 if self.standbyblocked == 0:
189                         self.standbyblocked = 1
190                         self.standby()
191
192         def standby(self):
193                 self.session.open(Standby, self)
194
195         def quit(self):
196                 # halt
197                 quitMainloop(1)
198
199 class InfoBarNumberZap:
200         """ Handles an initial number for NumberZapping """
201         def __init__(self):
202                 self["NumberActions"] = NumberActionMap( [ "NumberActions"],
203                         {
204                                 "1": self.keyNumberGlobal,
205                                 "2": self.keyNumberGlobal,
206                                 "3": self.keyNumberGlobal,
207                                 "4": self.keyNumberGlobal,
208                                 "5": self.keyNumberGlobal,
209                                 "6": self.keyNumberGlobal,
210                                 "7": self.keyNumberGlobal,
211                                 "8": self.keyNumberGlobal,
212                                 "9": self.keyNumberGlobal,
213                                 "0": self.keyNumberGlobal,
214                         })
215
216         def keyNumberGlobal(self, number):
217 #               print "You pressed number " + str(number)
218                 if number == 0:
219                         self.servicelist.recallPrevService()
220                         self.doShow()
221                 else:
222                         self.session.openWithCallback(self.numberEntered, NumberZap, number)
223
224         def numberEntered(self, retval):
225 #               print self.servicelist
226                 if retval > 0:
227                         self.zapToNumber(retval)
228
229         def searchNumberHelper(self, serviceHandler, num, bouquet):
230                 servicelist = serviceHandler.list(bouquet)
231                 if not servicelist is None:
232                         while num:
233                                 serviceIterator = servicelist.getNext()
234                                 if not serviceIterator.valid(): #check end of list
235                                         break
236                                 if serviceIterator.flags: #assume normal dvb service have no flags set
237                                         continue
238                                 num -= 1;
239                         if not num: #found service with searched number ?
240                                 return serviceIterator, 0
241                 return None, num
242
243         def zapToNumber(self, number):
244                 bouquet = self.servicelist.bouquet_root
245                 service = None
246                 serviceHandler = eServiceCenter.getInstance()
247                 if bouquet.toString().find('FROM BOUQUET "bouquets.') == -1: #FIXME HACK
248                         service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
249                 else:
250                         bouquetlist = serviceHandler.list(bouquet)
251                         if not bouquetlist is None:
252                                 while number:
253                                         bouquet = self.servicelist.appendDVBTypes(bouquetlist.getNext())
254                                         if not bouquet.valid(): #check end of list
255                                                 break
256                                         if (bouquet.flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory:
257                                                 continue
258                                         service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
259                 if not service is None:
260                         if self.servicelist.getRoot() != bouquet: #already in correct bouquet?
261                                 self.servicelist.clearPath()
262                                 if self.servicelist.bouquet_root != bouquet:
263                                         self.servicelist.enterPath(self.servicelist.bouquet_root)
264                                 self.servicelist.enterPath(bouquet)
265                         self.servicelist.setCurrentSelection(service) #select the service in servicelist
266                         self.servicelist.zap()
267
268 class InfoBarChannelSelection:
269         """ ChannelSelection - handles the channelSelection dialog and the initial 
270         channelChange actions which open the channelSelection dialog """
271         def __init__(self):
272                 #instantiate forever
273                 self.servicelist = self.session.instantiateDialog(ChannelSelection)
274
275                 self["ChannelSelectActions"] = HelpableActionMap(self, "InfobarChannelSelection",
276                         {
277                                 "switchChannelUp": self.switchChannelUp,
278                                 "switchChannelDown": self.switchChannelDown,
279                                 "zapUp": (self.zapUp, _("next channel")),
280                                 "zapDown": (self.zapDown, _("previous channel")),
281                         })
282
283         def switchChannelUp(self):
284                 self.servicelist.moveUp()
285                 self.session.execDialog(self.servicelist)
286
287         def switchChannelDown(self):
288                 self.servicelist.moveDown()
289                 self.session.execDialog(self.servicelist)
290
291         def zapUp(self):
292                 if currentConfigSelectionElement(config.usage.quickzap_bouquet_change) == "yes":
293                         if self.servicelist.inBouquet() and self.servicelist.atBegin():
294                                 self.servicelist.prevBouquet()
295                 self.servicelist.moveUp()
296                 self.servicelist.zap()
297                 self.doShow()
298
299         def zapDown(self):
300                 if currentConfigSelectionElement(config.usage.quickzap_bouquet_change) == "yes" and self.servicelist.inBouquet() and self.servicelist.atEnd():
301                         self.servicelist.nextBouquet()
302                 else:
303                         self.servicelist.moveDown()
304                 self.servicelist.zap()
305                 self.doShow()
306
307 class InfoBarMenu:
308         """ Handles a menu action, to open the (main) menu """
309         def __init__(self):
310                 self["MenuActions"] = HelpableActionMap(self, "InfobarMenuActions", 
311                         {
312                                 "mainMenu": (self.mainMenu, "Enter main menu..."),
313                         })
314
315         def mainMenu(self):
316                 print "loading mainmenu XML..."
317                 menu = mdom.childNodes[0]
318                 assert menu.tagName == "menu", "root element in menu must be 'menu'!"
319                 self.session.open(MainMenu, menu, menu.childNodes)
320
321 class InfoBarEPG:
322         """ EPG - Opens an EPG list when the showEPGList action fires """
323         def __init__(self):
324                 self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions", 
325                         {
326                                 "showEventInfo": (self.openEventView, _("show EPG...")),
327                         })
328
329         def zapToService(self, service):
330                 if not service is None:
331                         if self.servicelist.getRoot() != self.epg_bouquet: #already in correct bouquet?
332                                 self.servicelist.clearPath()
333                                 if self.servicelist.bouquet_root != self.epg_bouquet:
334                                         self.servicelist.enterPath(self.servicelist.bouquet_root)
335                                 self.servicelist.enterPath(self.epg_bouquet)
336                         self.servicelist.setCurrentSelection(service) #select the service in servicelist
337                         self.servicelist.zap()
338
339         def openBouquetEPG(self, bouquet):
340                 ptr=eEPGCache.getInstance()
341                 services = [ ]
342                 servicelist = eServiceCenter.getInstance().list(bouquet)
343                 if not servicelist is None:
344                         while True:
345                                 service = servicelist.getNext()
346                                 if not service.valid(): #check if end of list
347                                         break
348                                 if service.flags: #ignore non playable services
349                                         continue
350                                 services.append(ServiceReference(service))
351                 if len(services):
352                         self.epg_bouquet = bouquet
353                         self.session.openWithCallback(self.closed, EPGSelection, services, self.zapToService)
354
355         def closed(self, ret):
356                 if ret:
357                         self.close(ret)
358
359         def openMultiServiceEPG(self):
360                 bouquets = self.servicelist.getBouquetList()
361                 if bouquets is None:
362                         cnt = 0
363                 else:
364                         cnt = len(bouquets)
365                 if cnt > 1: # show bouquet list
366                         self.session.openWithCallback(self.closed, BouquetSelector, bouquets, self.openBouquetEPG)
367                 elif cnt == 1: 
368                         self.openBouquetEPG(bouquets[0][1])
369
370         def openSingleServiceEPG(self):
371                 ref=self.session.nav.getCurrentlyPlayingServiceReference()
372                 ptr=eEPGCache.getInstance()
373                 self.session.openWithCallback(self.closed, EPGSelection, ref)
374
375         def openEventView(self):
376                 self.epglist = [ ]
377                 service = self.session.nav.getCurrentService()
378                 ref = self.session.nav.getCurrentlyPlayingServiceReference()
379                 info = service.info()
380                 ptr=info.getEvent(0)
381                 if ptr:
382                         self.epglist.append(ptr)
383                 ptr=info.getEvent(1)
384                 if ptr:
385                         self.epglist.append(ptr)
386                 if len(self.epglist) == 0:
387                         epg = eEPGCache.getInstance()
388                         ptr = epg.lookupEventTime(ref, -1)
389                         if ptr:
390                                 self.epglist.append(ptr)
391                                 ptr = epg.lookupEventTime(ref, ptr.getBeginTime(), +1)
392                                 if ptr:
393                                         self.epglist.append(ptr)
394                 if len(self.epglist) > 0:
395                         self.session.open(EventViewEPGSelect, self.epglist[0], ServiceReference(ref), self.eventViewCallback, self.openSingleServiceEPG, self.openMultiServiceEPG)
396                 else:
397                         print "no epg for the service avail.. so we show multiepg instead of eventinfo"
398                         self.openMultiServiceEPG()
399
400         def eventViewCallback(self, setEvent, setService, val): #used for now/next displaying
401                 if len(self.epglist) > 1:
402                         tmp = self.epglist[0]
403                         self.epglist[0]=self.epglist[1]
404                         self.epglist[1]=tmp
405                         setEvent(self.epglist[0])
406
407 from math import log
408
409 class InfoBarTuner:
410         """provides a snr/agc/ber display"""
411         def __init__(self):
412                 self["snr"] = Label()
413                 self["agc"] = Label()
414                 self["ber"] = Label()
415                 self["snr_percent"] = Label()
416                 self["agc_percent"] = Label()
417                 self["ber_count"] = Label()
418                 self["snr_progress"] = ProgressBar()
419                 self["agc_progress"] = ProgressBar()
420                 self["ber_progress"] = ProgressBar()
421                 self.timer = eTimer()
422                 self.timer.timeout.get().append(self.updateTunerInfo)
423                 self.timer.start(1000)
424
425         def calc(self,val):
426                 if not val:
427                         return 0
428                 if val < 2500:
429                         return (long)(log(val)/log(2))
430                 return val*100/65535
431
432         def updateTunerInfo(self):
433                 if self.instance.isVisible():
434                         service = self.session.nav.getCurrentService()
435                         snr=0
436                         agc=0
437                         ber=0
438                         if service is not None:
439                                 feinfo = service.frontendStatusInfo()
440                                 if feinfo is not None:
441                                         ber=feinfo.getFrontendInfo(iFrontendStatusInformation.bitErrorRate)
442                                         snr=feinfo.getFrontendInfo(iFrontendStatusInformation.signalPower)*100/65536
443                                         agc=feinfo.getFrontendInfo(iFrontendStatusInformation.signalQuality)*100/65536
444                         self["snr_percent"].setText("%d%%"%(snr))
445                         self["agc_percent"].setText("%d%%"%(agc))
446                         self["ber_count"].setText("%d"%(ber))
447                         self["snr_progress"].setValue(snr)
448                         self["agc_progress"].setValue(agc)
449                         self["ber_progress"].setValue(self.calc(ber))
450
451 class InfoBarEvent:
452         """provides a current/next event info display"""
453         def __init__(self):
454                 self["Event_Now_StartTime"] = EventInfo(self.session.nav, EventInfo.Now_StartTime)
455                 self["Event_Next_StartTime"] = EventInfo(self.session.nav, EventInfo.Next_StartTime)
456                                 
457                 self["Event_Now"] = EventInfo(self.session.nav, EventInfo.Now)
458                 self["Event_Next"] = EventInfo(self.session.nav, EventInfo.Next)
459
460                 self["Event_Now_Duration"] = EventInfo(self.session.nav, EventInfo.Now_Remaining)
461                 self["Event_Next_Duration"] = EventInfo(self.session.nav, EventInfo.Next_Duration)
462
463                 self["Now_ProgressBar"] = EventInfoProgress(self.session.nav, EventInfo.Now)
464
465 class InfoBarServiceName:
466         def __init__(self):
467                 self["ServiceName"] = ServiceName(self.session.nav)
468
469 class InfoBarSeek:
470         """handles actions like seeking, pause"""
471         
472         # ispause, isff, issm
473         SEEK_STATE_PLAY = (0, 0, 0, ">")
474         SEEK_STATE_PAUSE = (1, 0, 0, "||")
475         SEEK_STATE_FF_2X = (0, 2, 0, ">> 2x")
476         SEEK_STATE_FF_4X = (0, 4, 0, ">> 4x")
477         SEEK_STATE_FF_8X = (0, 8, 0, ">> 8x")
478         SEEK_STATE_FF_32X = (0, 32, 0, ">> 32x")
479         SEEK_STATE_FF_64X = (0, 64, 0, ">> 64x")
480         SEEK_STATE_FF_128X = (0, 128, 0, ">> 128x")
481         
482         SEEK_STATE_BACK_4X = (0, -4, 0, "<< 4x")
483         SEEK_STATE_BACK_32X = (0, -32, 0, "<< 32x")
484         SEEK_STATE_BACK_64X = (0, -64, 0, "<< 64x")
485         SEEK_STATE_BACK_128X = (0, -128, 0, "<< 128x")
486         
487         SEEK_STATE_SM_HALF = (0, 0, 2, "/2")
488         SEEK_STATE_SM_QUARTER = (0, 0, 4, "/4")
489         SEEK_STATE_SM_EIGHTH = (0, 0, 8, "/8")
490         
491         def __init__(self):
492                 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
493                         {
494                                 iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged,
495                                 iPlayableService.evStart: self.__serviceStarted,
496                                 
497                                 iPlayableService.evEOF: self.__evEOF,
498                                 iPlayableService.evSOF: self.__evSOF,
499                         })
500                 self["SeekActions"] = HelpableActionMap(self, "InfobarSeekActions", 
501                         {
502                                 "pauseService": (self.pauseService, "pause"),
503                                 "unPauseService": (self.unPauseService, "continue"),
504                                 
505                                 "seekFwd": (self.seekFwd, "skip forward"),
506                                 "seekFwdUp": (self.seekFwdUp, "skip forward"),
507                                 "seekBack": (self.seekBack, "skip backward"),
508                                 "seekBackUp": (self.seekBackUp, "skip backward"),
509                         }, prio=-1)
510                         # give them a little more priority to win over color buttons
511
512                 self.seekstate = self.SEEK_STATE_PLAY
513                 self.onClose.append(self.delTimer)
514                 
515                 self.fwdtimer = False
516                 self.fwdKeyTimer = eTimer()
517                 self.fwdKeyTimer.timeout.get().append(self.fwdTimerFire)
518
519                 self.rwdtimer = False
520                 self.rwdKeyTimer = eTimer()
521                 self.rwdKeyTimer.timeout.get().append(self.rwdTimerFire)
522                 
523                 self.onPlayStateChanged = [ ]
524                 
525                 self.lockedBecauseOfSkipping = False
526         
527         def up(self):
528                 pass
529         
530         def down(self):
531                 pass
532         
533         def delTimer(self):
534                 del self.fwdKeyTimer
535                 del self.rwdKeyTimer
536         
537         def getSeek(self):
538                 service = self.session.nav.getCurrentService()
539                 if service is None:
540                         return False
541
542                 seek = service.seek()
543
544                 if seek is None or not seek.isCurrentlySeekable():
545                         return None
546                 
547                 return seek
548         
549         def isSeekable(self):
550                 if self.getSeek() is None:
551                         return False
552                 return True
553
554         def __seekableStatusChanged(self):
555                 print "seekable status changed!"
556                 if not self.isSeekable():
557                         self["SeekActions"].setEnabled(False)
558                         print "not seekable, return to play"
559                         self.setSeekState(self.SEEK_STATE_PLAY)
560                 else:
561                         self["SeekActions"].setEnabled(True)
562                         print "seekable"
563
564         def __serviceStarted(self):
565                 self.seekstate = self.SEEK_STATE_PLAY
566
567         def setSeekState(self, state):
568                 service = self.session.nav.getCurrentService()
569                 
570                 if service is None:
571                         return False
572                 
573                 if not self.isSeekable():
574                         if state not in [self.SEEK_STATE_PLAY, self.SEEK_STATE_PAUSE]:
575                                 state = self.SEEK_STATE_PLAY
576                 
577                 pauseable = service.pause()
578
579                 if pauseable is None:
580                         print "not pauseable."
581                         state = self.SEEK_STATE_PLAY
582                 
583                 oldstate = self.seekstate
584                 self.seekstate = state
585                 
586                 for i in range(3):
587                         if oldstate[i] != self.seekstate[i]:
588                                 (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion)[i](self.seekstate[i])
589
590                 for c in self.onPlayStateChanged:
591                         c(self.seekstate)
592                 
593                 self.checkSkipShowHideLock()
594
595                 return True
596                 
597         def pauseService(self):
598                 if self.seekstate == self.SEEK_STATE_PAUSE:
599                         print "pause, but in fact unpause"
600                         self.unPauseService()
601                 else:
602                         if self.seekstate == self.SEEK_STATE_PLAY:
603                                 print "yes, playing."
604                         else:
605                                 print "no", self.seekstate
606                         print "pause"
607                         self.setSeekState(self.SEEK_STATE_PAUSE);
608                 
609         def unPauseService(self):
610                 print "unpause"
611                 self.setSeekState(self.SEEK_STATE_PLAY);
612         
613         def doSeek(self, seektime):
614                 print "doseek", seektime
615                 service = self.session.nav.getCurrentService()
616                 if service is None:
617                         return
618                 
619                 seekable = self.getSeek()
620                 if seekable is None:
621                         return
622                 
623                 seekable.seekTo(90 * seektime)
624
625         def seekFwd(self):
626                 print "start fwd timer"
627                 self.fwdtimer = True
628                 self.fwdKeyTimer.start(500)
629
630         def seekBack(self):
631                 print "start rewind timer"
632                 self.rwdtimer = True
633                 self.rwdKeyTimer.start(500)
634
635         def seekFwdUp(self):
636                 print "seekFwdUp"
637                 if self.fwdtimer:
638                         self.fwdKeyTimer.stop()
639                         self.fwdtimer = False
640                         lookup = {
641                                         self.SEEK_STATE_PLAY: self.SEEK_STATE_FF_2X,
642                                         self.SEEK_STATE_PAUSE: self.SEEK_STATE_SM_EIGHTH,
643                                         self.SEEK_STATE_FF_2X: self.SEEK_STATE_FF_4X,
644                                         self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_8X,
645                                         self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_32X,
646                                         self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_64X,
647                                         self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_128X,
648                                         self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_128X,
649                                         self.SEEK_STATE_BACK_4X: self.SEEK_STATE_PLAY,
650                                         self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_4X,
651                                         self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_32X,
652                                         self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_64X,
653                                         self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_HALF,
654                                         self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_HALF,
655                                         self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_SM_QUARTER
656                                 }
657                         self.setSeekState(lookup[self.seekstate]);
658         
659         def seekBackUp(self):
660                 print "seekBackUp"
661                 if self.rwdtimer:
662                         self.rwdKeyTimer.stop()
663                         self.rwdtimer = False
664                 
665                         lookup = {
666                                         self.SEEK_STATE_PLAY: self.SEEK_STATE_BACK_4X,
667                                         self.SEEK_STATE_PAUSE: self.SEEK_STATE_PAUSE,
668                                         self.SEEK_STATE_FF_2X: self.SEEK_STATE_PLAY,
669                                         self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_2X,
670                                         self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_4X,
671                                         self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_8X,
672                                         self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_32X,
673                                         self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_64X,
674                                         self.SEEK_STATE_BACK_4X: self.SEEK_STATE_BACK_32X,
675                                         self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_64X,
676                                         self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_128X,
677                                         self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_128X,
678                                         self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_QUARTER,
679                                         self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_EIGHTH,
680                                         self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_PAUSE
681                                 }
682                         self.setSeekState(lookup[self.seekstate]);
683                 
684         def fwdTimerFire(self):
685                 print "Display seek fwd"
686                 self.fwdKeyTimer.stop()
687                 self.fwdtimer = False
688                 self.session.openWithCallback(self.fwdSeekTo, MinuteInput)
689                 
690         def fwdSeekTo(self, minutes):
691                 print "Seek", minutes, "minutes forward"
692                 if minutes != 0:
693                         seekable = self.getSeek()
694                         if seekable is not None:
695                                 seekable.seekRelative(1, minutes * 60 * 90000)
696         
697         def rwdTimerFire(self):
698                 print "rwdTimerFire"
699                 self.rwdKeyTimer.stop()
700                 self.rwdtimer = False
701                 self.session.openWithCallback(self.rwdSeekTo, MinuteInput)
702         
703         def rwdSeekTo(self, minutes):
704                 print "rwdSeekTo"
705                 self.fwdSeekTo(0 - minutes)
706         
707         def checkSkipShowHideLock(self):
708                 wantlock = self.seekstate != self.SEEK_STATE_PLAY
709                 
710                 if self.lockedBecauseOfSkipping and not wantlock:
711                         self.unlockShow()
712                         self.lockedBecauseOfSkipping = False
713                 
714                 if wantlock and not self.lockedBecauseOfSkipping:
715                         self.lockShow()
716                         self.lockedBecauseOfSkipping = True
717
718         def __evEOF(self):
719                 self.setSeekState(self.SEEK_STATE_PAUSE)
720         
721         def __evSOF(self):
722                 self.setSeekState(self.SEEK_STATE_PLAY)
723                 self.doSeek(0)
724
725         def seekRelative(self, diff):
726                 seekable = self.getSeek()
727                 if seekable is not None:
728                         seekable.seekRelative(0, diff)
729
730 from Screens.PVRState import PVRState
731
732 class InfoBarPVRState:
733         def __init__(self):
734                 self.onPlayStateChanged.append(self.__playStateChanged)
735                 self.pvrStateDialog = self.session.instantiateDialog(PVRState)
736                 self.onShow.append(self.__mayShow)
737                 self.onHide.append(self.pvrStateDialog.hide)
738         
739         def __mayShow(self):
740                 if self.seekstate != self.SEEK_STATE_PLAY:
741                         self.pvrStateDialog.show()
742
743         def __playStateChanged(self, state):
744                 playstateString = state[3]
745                 self.pvrStateDialog["state"].setText(playstateString)
746                 self.__mayShow()
747
748 class InfoBarShowMovies:
749
750         # i don't really like this class. 
751         # it calls a not further specified "movie list" on up/down/movieList,
752         # so this is not more than an action map
753         def __init__(self):
754                 self["MovieListActions"] = HelpableActionMap(self, "InfobarMovieListActions", 
755                         {
756                                 "movieList": (self.showMovies, "movie list"),
757                                 "up": (self.showMovies, "movie list"),
758                                 "down": (self.showMovies, "movie list")
759                         })
760
761 # InfoBarTimeshift requires InfoBarSeek, instantiated BEFORE!
762
763 # Hrmf.
764 #
765 # Timeshift works the following way:
766 #                                         demux0   demux1                    "TimeshiftActions" "TimeshiftActivateActions" "SeekActions"
767 # - normal playback                       TUNER    unused      PLAY               enable                disable              disable
768 # - user presses "yellow" button.         TUNER    record      PAUSE              enable                disable              enable
769 # - user presess pause again              FILE     record      PLAY               enable                disable              enable
770 # - user fast forwards                    FILE     record      FF                 enable                disable              enable
771 # - end of timeshift buffer reached       TUNER    record      PLAY               enable                enable               disable
772 # - user backwards                        FILE     record      BACK  # !!         enable                disable              enable
773 #
774
775 # in other words:
776 # - when a service is playing, pressing the "timeshiftStart" button ("yellow") enables recording ("enables timeshift"),
777 # freezes the picture (to indicate timeshift), sets timeshiftMode ("activates timeshift")
778 # now, the service becomes seekable, so "SeekActions" are enabled, "TimeshiftEnableActions" are disabled.
779 # - the user can now PVR around
780 # - if it hits the end, the service goes into live mode ("deactivates timeshift", it's of course still "enabled")
781 # the service looses it's "seekable" state. It can still be paused, but just to activate timeshift right
782 # after!
783 # the seek actions will be disabled, but the timeshiftActivateActions will be enabled
784 # - if the user rewinds, or press pause, timeshift will be activated again
785
786 # note that a timeshift can be enabled ("recording") and
787 # activated (currently time-shifting).
788
789 class InfoBarTimeshift:
790         def __init__(self):
791                 self["TimeshiftActions"] = HelpableActionMap(self, "InfobarTimeshiftActions", 
792                         {
793                                 "timeshiftStart": (self.startTimeshift, "start timeshift"),  # the "yellow key"
794                                 "timeshiftStop": (self.stopTimeshift, "stop timeshift")      # currently undefined :), probably 'TV'
795                         }, prio=1)
796                 self["TimeshiftActivateActions"] = ActionMap(["InfobarTimeshiftActivateActions"],
797                         {
798                                 "timeshiftActivateEnd": self.activateTimeshiftEnd, # something like "pause key"
799                                 "timeshiftActivateEndAndPause": self.activateTimeshiftEndAndPause  # something like "backward key"
800                         }, prio=-1) # priority over record
801
802                 self.timeshift_enabled = 0
803                 self.timeshift_state = 0
804                 self.ts_pause_timer = eTimer()
805                 self.ts_pause_timer.timeout.get().append(self.pauseService)
806
807                 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
808                         {
809                                 iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged
810                         })
811         
812         def getTimeshift(self):
813                 service = self.session.nav.getCurrentService()
814                 return service.timeshift()
815
816         def startTimeshift(self):
817                 print "enable timeshift"
818                 ts = self.getTimeshift()
819                 if ts is None:
820                         self.session.open(MessageBox, _("Timeshift not possible!"), MessageBox.TYPE_ERROR)
821                         print "no ts interface"
822                         return
823                 
824                 if self.timeshift_enabled:
825                         print "hu, timeshift already enabled?"
826                 else:
827                         if not ts.startTimeshift():
828                                 self.timeshift_enabled = 1
829                                 
830                                 # PAUSE.
831                                 self.setSeekState(self.SEEK_STATE_PAUSE)
832                                 
833                                 # enable the "TimeshiftEnableActions", which will override
834                                 # the startTimeshift actions
835                                 self.__seekableStatusChanged()
836                         else:
837                                 print "timeshift failed"
838
839         def stopTimeshift(self):
840                 if not self.timeshift_enabled:
841                         return
842                 print "disable timeshift"
843                 ts = self.getTimeshift()
844                 if ts is None:
845                         return
846                 self.session.openWithCallback(self.stopTimeshiftConfirmed, MessageBox, _("Stop Timeshift?"), MessageBox.TYPE_YESNO)
847
848         def stopTimeshiftConfirmed(self, confirmed):
849                 if not confirmed:
850                         return
851
852                 ts = self.getTimeshift()
853                 if ts is None:
854                         return
855
856                 ts.stopTimeshift()
857                 self.timeshift_enabled = 0
858
859                 # disable actions
860                 self.__seekableStatusChanged()
861         
862         # activates timeshift, and seeks to (almost) the end
863         def activateTimeshiftEnd(self):
864                 ts = self.getTimeshift()
865                 
866                 if ts is None:
867                         return
868                 
869                 if ts.isTimeshiftActive():
870                         print "!! activate timeshift called - but shouldn't this be a normal pause?"
871                         self.pauseService()
872                 else:
873                         self.setSeekState(self.SEEK_STATE_PLAY)
874                         ts.activateTimeshift()
875                         self.seekRelative(0)
876         
877         # same as activateTimeshiftEnd, but pauses afterwards.
878         def activateTimeshiftEndAndPause(self):
879                 state = self.seekstate
880                 self.activateTimeshiftEnd()
881                 
882                 # well, this is "andPause", but it could be pressed from pause,
883                 # when pausing on the (fake-)"live" picture, so an un-pause
884                 # is perfectly ok.
885                 
886                 print "now, pauseService"
887                 if state == self.SEEK_STATE_PLAY:
888                         print "is PLAYING, start pause timer"
889                         self.ts_pause_timer.start(200, 1)
890                 else:
891                         print "unpause"
892                         self.unPauseService()
893         
894         def __seekableStatusChanged(self):
895                 enabled = False
896                 
897                 print "self.isSeekable", self.isSeekable()
898                 print "self.timeshift_enabled", self.timeshift_enabled
899                 
900                 # when this service is not seekable, but timeshift
901                 # is enabled, this means we can activate
902                 # the timeshift
903                 if not self.isSeekable() and self.timeshift_enabled:
904                         enabled = True
905
906                 print "timeshift activate:", enabled
907                 self["TimeshiftActivateActions"].setEnabled(enabled)
908
909 from RecordTimer import parseEvent
910
911 class InfoBarInstantRecord:
912         """Instant Record - handles the instantRecord action in order to 
913         start/stop instant records"""
914         def __init__(self):
915                 self["InstantRecordActions"] = HelpableActionMap(self, "InfobarInstantRecord",
916                         {
917                                 "instantRecord": (self.instantRecord, "Instant Record..."),
918                         })
919                 self.recording = None
920                 self["BlinkingPoint"] = BlinkingPixmapConditional()
921                 self.onLayoutFinish.append(self["BlinkingPoint"].hideWidget)
922                 self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording)
923
924         def stopCurrentRecording(self): 
925                 self.session.nav.RecordTimer.removeEntry(self.recording)
926                 self.recording = None
927
928         def startInstantRecording(self):
929                 serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
930                 
931                 # try to get event info
932                 event = None
933                 try:
934                         service = self.session.nav.getCurrentService()
935                         info = service.info()
936                         ev = info.getEvent(0)
937                         event = ev
938                 except:
939                         pass
940                 
941                 if event is not None:
942                         data = parseEvent(event)
943                         begin = time.time()
944                         end = begin + 3600 * 10
945                         
946                         data = (begin, end, data[2], data[3], data[4])
947                 else:
948                         data = (time.time(), time.time() + 3600 * 10, "instant record", "", None)
949                 
950                 # fix me, description. 
951                 self.recording = self.session.nav.recordWithTimer(serviceref, *data)
952                 self.recording.dontSave = True
953                 
954                 #self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
955                 
956         def isInstantRecordRunning(self):
957                 if self.recording != None:
958                         if self.recording.isRunning():
959                                 return True
960                 return False
961
962         def recordQuestionCallback(self, answer):
963                 if answer == False:
964                         return
965                 
966                 if self.isInstantRecordRunning():
967                         self.stopCurrentRecording()
968                 else:
969                         self.startInstantRecording()
970
971         def instantRecord(self):
972                 try:
973                         stat = os.stat(resolveFilename(SCOPE_HDD))
974                 except:
975                         self.session.open(MessageBox, _("No HDD found or HDD not initialized!"), MessageBox.TYPE_ERROR)
976                         return
977         
978                 if self.isInstantRecordRunning():
979                         self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Do you want to stop the current\n(instant) recording?"))
980                 else:
981                         self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Start recording?"))
982
983 from Screens.AudioSelection import AudioSelection
984
985 class InfoBarAudioSelection:
986         def __init__(self):
987                 self["AudioSelectionAction"] = HelpableActionMap(self, "InfobarAudioSelectionActions", 
988                         {
989                                 "audioSelection": (self.audioSelection, "Audio Options..."),
990                         })
991
992         def audioSelection(self):
993                 service = self.session.nav.getCurrentService()
994                 audio = service.audioTracks()
995                 n = audio.getNumberOfTracks()
996                 if n > 0:
997                         self.session.open(AudioSelection, audio)
998
999 from Screens.SubserviceSelection import SubserviceSelection
1000
1001 class InfoBarSubserviceSelection:
1002         def __init__(self):
1003                 self["SubserviceSelectionAction"] = HelpableActionMap(self, "InfobarSubserviceSelectionActions",
1004                         {
1005                                 "subserviceSelection": (self.subserviceSelection, "Subservice list..."),
1006                         })
1007
1008         def subserviceSelection(self):
1009                 service = self.session.nav.getCurrentService()
1010                 subservices = service.subServices()
1011                 n = subservices.getNumberOfSubservices()
1012                 if n > 0:
1013                         self.session.openWithCallback(self.subserviceSelected, SubserviceSelection, subservices)
1014
1015         def subserviceSelected(self, service):
1016                 if not service is None:
1017                         self.session.nav.playService(service)
1018
1019 class InfoBarAdditionalInfo:
1020         def __init__(self):
1021                 self["DolbyActive"] = Pixmap()
1022                 self["CryptActive"] = Pixmap()
1023                 self["FormatActive"] = Pixmap()
1024                 
1025                 self["ButtonRed"] = PixmapConditional(withTimer = False)
1026                 self["ButtonRed"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
1027                 self.onShown.append(self["ButtonRed"].update)
1028                 self["ButtonRedText"] = LabelConditional(text = _("Record"), withTimer = False)
1029                 self["ButtonRedText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
1030                 self.onShown.append(self["ButtonRedText"].update)
1031
1032                 self["ButtonGreen"] = Pixmap()
1033                 self["ButtonGreenText"] = Label(_("Subservices"))
1034
1035                 self["ButtonYellow"] = PixmapConditional(withTimer = False)
1036                 self["ButtonYellow"].setConnect(lambda: False)
1037
1038                 self["ButtonBlue"] = PixmapConditional(withTimer = False)
1039                 self["ButtonBlue"].setConnect(lambda: False)
1040
1041                 self.session.nav.event.append(self.gotServiceEvent) # we like to get service events
1042
1043         def hideSubServiceIndication(self):
1044                 self["ButtonGreen"].hideWidget()
1045                 self["ButtonGreenText"].hide()
1046
1047         def showSubServiceIndication(self):
1048                 self["ButtonGreen"].showWidget()
1049                 self["ButtonGreenText"].show()
1050
1051         def checkFormat(self, service):
1052                 info = service.info()
1053                 if info is not None:
1054                         aspect = info.getInfo(iServiceInformation.sAspect)
1055                         if aspect in [ 3, 4, 7, 8, 0xB, 0xC, 0xF, 0x10 ]:
1056                                 self["FormatActive"].showWidget()
1057                         else:
1058                                 self["FormatActive"].hideWidget()
1059
1060         def checkSubservices(self, service):
1061                 if service.subServices().getNumberOfSubservices() > 0:
1062                         self.showSubServiceIndication()
1063                 else:
1064                         self.hideSubServiceIndication()
1065
1066         def checkDolby(self, service):
1067                 # FIXME
1068                 dolby = False
1069                 audio = service.audioTracks()
1070                 if audio is not None:
1071                         n = audio.getNumberOfTracks()
1072                         for x in range(n):
1073                                 i = audio.getTrackInfo(x)
1074                                 description = i.getDescription();
1075                                 if description.find("AC3") != -1 or description.find("DTS") != -1:
1076                                         dolby = True
1077                                         break
1078                 if dolby:
1079                         self["DolbyActive"].showWidget()
1080                 else:
1081                         self["DolbyActive"].hideWidget()
1082
1083         def checkCrypted(self, service):
1084                 info = service.info()
1085                 if info is not None:
1086                         if info.getInfo(iServiceInformation.sIsCrypted) > 0:
1087                                 self["CryptActive"].showWidget()
1088                         else:
1089                                 self["CryptActive"].hideWidget()
1090
1091         def gotServiceEvent(self, ev):
1092                 service = self.session.nav.getCurrentService()
1093                 if ev == iPlayableService.evUpdatedEventInfo:
1094                         self.checkSubservices(service)
1095                         self.checkFormat(service)
1096                 elif ev == iPlayableService.evUpdatedInfo:
1097                         self.checkCrypted(service)
1098                         self.checkDolby(service)
1099                 elif ev == iPlayableService.evEnd:
1100                         self.hideSubServiceIndication()
1101                         self["CryptActive"].hideWidget()
1102                         self["DolbyActive"].hideWidget()
1103                         self["FormatActive"].hideWidget()
1104
1105 class InfoBarNotifications:
1106         def __init__(self):
1107                 self.onExecBegin.append(self.checkNotifications)
1108                 Notifications.notificationAdded.append(self.checkNotificationsIfExecing)
1109         
1110         def checkNotificationsIfExecing(self):
1111                 if self.execing:
1112                         self.checkNotifications()
1113
1114         def checkNotifications(self):
1115                 if len(Notifications.notifications):
1116                         n = Notifications.notifications[0]
1117                         Notifications.notifications = Notifications.notifications[1:]
1118                         print "open",n
1119                         cb = n[0]
1120                         if cb is not None:
1121                                 self.session.openWithCallback(cb, *n[1:])
1122                         else:
1123                                 self.session.open(*n[1:])
1124
1125 class InfoBarServiceNotifications:
1126         def __init__(self):
1127                 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1128                         {
1129                                 iPlayableService.evEnd: self.serviceHasEnded
1130                         })
1131
1132         def serviceHasEnded(self):
1133                 print "service end!"
1134
1135                 try:
1136                         self.setSeekState(self.SEEK_STATE_PLAY)
1137                 except:
1138                         pass
1139
1140 class InfoBarCueSheetSupport:
1141         CUT_TYPE_IN = 0
1142         CUT_TYPE_OUT = 1
1143         CUT_TYPE_MARK = 2
1144         
1145         def __init__(self):
1146                 self["CueSheetActions"] = HelpableActionMap(self, "InfobarCueSheetActions", 
1147                         {
1148                                 "jumpPreviousMark": (self.jumpPreviousMark, "jump to next marked position"),
1149                                 "jumpNextMark": (self.jumpNextMark, "jump to previous marked position"),
1150                                 "toggleMark": (self.toggleMark, "toggle a cut mark at the current position")
1151                         }, prio=1) 
1152                 
1153                 self.cut_list = [ ]
1154                 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1155                         {
1156                                 iPlayableService.evStart: self.__serviceStarted,
1157                         })
1158
1159         def __serviceStarted(self):
1160                 print "new service started! trying to download cuts!"
1161                 self.downloadCuesheet()
1162
1163         def __getSeekable(self):
1164                 service = self.session.nav.getCurrentService()
1165                 if service is None:
1166                         return None
1167                 return service.seek()
1168
1169         def __getCurrentPosition(self):
1170                 seek = self.__getSeekable()
1171                 if seek is None:
1172                         return None
1173                 r = seek.getPlayPosition()
1174                 if r[0]:
1175                         return None
1176                 return long(r[1])
1177
1178         def jumpPreviousNextMark(self, cmp, alternative=None):
1179                 current_pos = self.__getCurrentPosition()
1180                 if current_pos is None:
1181                         return
1182                 mark = self.getNearestCutPoint(current_pos, cmp=cmp)
1183                 if mark is not None:
1184                         pts = mark[0]
1185                 elif alternative is not None:
1186                         pts = alternative
1187                 else:
1188                         return
1189
1190                 seekable = self.__getSeekable()
1191                 if seekable is not None:
1192                         seekable.seekTo(pts)
1193
1194         def jumpPreviousMark(self):
1195                 print "jumpPreviousMark"
1196                 # we add 2 seconds, so if the play position is <2s after
1197                 # the mark, the mark before will be used
1198                 self.jumpPreviousNextMark(lambda x: -x-5*90000, alternative=0)
1199
1200         def jumpNextMark(self):
1201                 print "jumpNextMark"
1202                 self.jumpPreviousNextMark(lambda x: x)
1203
1204         def getNearestCutPoint(self, pts, cmp=abs):
1205                 # can be optimized
1206                 nearest = None
1207                 for cp in self.cut_list:
1208                         diff = cmp(cp[0] - pts)
1209                         if diff >= 0 and (nearest is None or cmp(nearest[0] - pts) > diff):
1210                                 nearest = cp
1211                 return nearest
1212
1213         def toggleMark(self):
1214                 print "toggleMark"
1215                 current_pos = self.__getCurrentPosition()
1216                 if current_pos is None:
1217                         print "not seekable"
1218                         return
1219                 
1220                 print "current position: ", current_pos
1221
1222                 nearest_cutpoint = self.getNearestCutPoint(current_pos)
1223                 print "nearest_cutpoint: ", nearest_cutpoint
1224                 
1225                 if nearest_cutpoint is not None and abs(nearest_cutpoint[0] - current_pos) < 5*90000:
1226                         self.cut_list.remove(nearest_cutpoint)
1227                 else:
1228                         bisect.insort(self.cut_list, (current_pos, self.CUT_TYPE_MARK))
1229                 
1230                 self.uploadCuesheet()
1231
1232         def __getCuesheet(self):
1233                 service = self.session.nav.getCurrentService()
1234                 if service is None:
1235                         return None
1236                 return service.cueSheet()
1237
1238         def uploadCuesheet(self):
1239                 cue = self.__getCuesheet()
1240
1241                 if cue is None:
1242                         print "upload failed, no cuesheet interface"
1243                         return
1244                 cue.setCutList(self.cut_list)
1245
1246         def downloadCuesheet(self):
1247                 cue = self.__getCuesheet()
1248
1249                 if cue is None:
1250                         print "upload failed, no cuesheet interface"
1251                         return
1252                 self.cut_list = cue.getCutList()
1253
1254                 print "cuts:", self.cut_list