allow burning DVDs with multiple titles where playback automatically jumps to the...
[enigma2.git] / lib / python / Plugins / Extensions / DVDBurn / TitleList.py
1 import DVDProject, TitleList, TitleCutter
2
3 from Screens.Screen import Screen
4 from Components.ActionMap import HelpableActionMap, ActionMap
5 from Components.Sources.List import List
6 from Components.Sources.StaticText import StaticText
7 from enigma import eListboxPythonMultiContent, gFont, RT_HALIGN_LEFT
8
9 class TitleList(Screen):
10
11         skin = """
12                 <screen position="90,83" size="560,445" title="DVD Tool" >
13                     <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
14                     <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
15                     <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
16                     <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" alphatest="on" />
17                     <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
18                     <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
19                     <widget source="key_yellow" render="Label" position="280,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" transparent="1" />
20                     <widget source="key_blue" render="Label" position="420,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" transparent="1" />
21                     <widget source="title_label" render="Label" position="6,48" size="436,24" font="Regular;18" />
22                     <widget source="titles" render="Listbox" scrollbarMode="showOnDemand" position="6,72" size="540,350">
23                         <convert type="StaticMultiList" />
24                     </widget>
25                     <widget source="statusbar" render="Label" position="6,422" size="548,24" font="Regular;18" halign="left" />
26                 </screen>"""
27
28         def __init__(self, session, project = None):
29                 Screen.__init__(self, session)
30
31                 if project is not None:
32                         self.project = project
33                 else:
34                         self.newProject()
35
36                 self["titleactions"] = HelpableActionMap(self, "DVDTitleList",
37                         {
38                                 "addTitle": (self.addTitle, _("Add a new title"), _("Add title...")),
39                                 "editTitle": (self.editTitle, _("Edit current title"), _("Edit title...")),
40                                 "removeCurrentTitle": (self.removeCurrentTitle, _("Remove currently selected title"), _("Remove title")),
41                                 "saveProject": (self.saveProject, _("Save current project to disk"), _("Save...")),
42                                 "burnProject": (self.burnProject, _("Burn DVD"), _("Burn")),
43                         })
44
45                 self["key_red"] = StaticText(_("Add title"))
46                 self["key_green"] = StaticText(_("Edit title"))
47                 self["key_yellow"] = StaticText(_("Remove title"))
48                 self["key_blue"] = StaticText(_("Save"))
49
50                 self["title_label"] = StaticText(_("Table of content to be burned to DVD:"))
51                 self["statusbar"] = StaticText(_("When complete, press record key to burn the collection!"))
52
53                 self["actions"] = ActionMap(["OkCancelActions"],
54                         {
55                                 "cancel": self.leave
56                         })
57
58                 #Action("addTitle", self.addTitle)
59
60                 self["titles"] = List(list = [ ], enableWrapAround = True, item_height=30, fonts = [gFont("Regular", 20)])
61                 self.updateTitleList()
62
63                 #self["addTitle"] = ActionButton("titleactions", "addTitle")
64                 #self["editTitle"] = ActionButton("titleactions", "editTitle")
65                 #self["removeCurrentTitle"] = ActionButton("titleactions", "removeCurrentTitle")
66                 #self["saveProject"] = ActionButton("titleactions", "saveProject")
67                 #self["burnProject"] = ActionButton("titleactions", "burnProject")
68
69         def newProject(self):
70                 self.project = DVDProject.DVDProject()
71                 self.project.titles = [ ]
72
73         def addTitle(self):
74                 from Screens.MovieSelection import MovieSelection
75                 self.session.openWithCallback(self.selectedSource, MovieSelection)
76
77         def selectedSource(self, source):
78                 if source is None:
79                         return None
80                 t = self.project.addService(source)
81                 self.updateTitleList()
82                 #self.editTitle(t)
83
84         def removeCurrentTitle(self):
85                 title = self.getCurrentTitle()
86                 if title is not None:
87                         self.project.titles.remove(title)
88                         self.updateTitleList()
89
90         def saveProject(self):
91                 pass
92
93         def burnProject(self):
94                 print "producing final cue sheet:"
95                 cue = self.produceFinalCuesheet()
96                 print str(cue)
97                 import Process
98                 job = Process.Burn(self.session, cue)
99                 print cue
100                 from Screens.TaskView import JobView
101                 self.session.open(JobView, job)
102
103         def updateTitleList(self):
104                 res = [ ]
105                 for title in self.project.titles:
106                         a = [ title, (eListboxPythonMultiContent.TYPE_TEXT, 0, 10, 400, 50, 0, RT_HALIGN_LEFT, title.name)  ]
107                         res.append(a)
108
109                 self["titles"].list = res
110
111         def getCurrentTitle(self):
112                 t = self["titles"].getCurrent()
113                 return t and t[0]
114
115         def editTitle(self, title = None):
116                 t = title or self.getCurrentTitle()
117                 if t is not None:
118                         self.current_edit_title = t
119                         self.session.openWithCallback(self.titleEditDone, TitleCutter.TitleCutter, t)
120
121         def titleEditDone(self, cutlist):
122                 t = self.current_edit_title
123                 t.cutlist = cutlist
124                 print "title edit of %s done, resulting cutlist:" % (t.source.toString()), t.cutlist
125
126         def leave(self):
127                 self.close()
128
129         def produceFinalCuesheet(self):
130                 res = [ ]
131                 for title in self.project.titles:
132                         path = title.source.getPath()
133                         print ">>> path:", path
134                         cutlist = title.cutlist
135
136                         # our demuxer expects *stricly* IN,OUT lists.
137                         first = True
138                         currently_in = False
139                         CUT_TYPE_IN = 0
140                         CUT_TYPE_OUT = 1
141                         CUT_TYPE_MARK = 2
142                         CUT_TYPE_LAST = 3
143
144                         accumulated_in = 0
145                         accumulated_at = 0
146                         last_in = 0
147
148                         res_cutlist = [ ]
149
150                         res_chaptermarks = [0]
151
152                         for (pts, type) in cutlist:
153                                 if first and type == CUT_TYPE_OUT: # first mark is "out"
154                                         res_cutlist.append(0) # emulate "in" at first
155                                         currently_in = True
156
157                                 first = False
158
159                                 if type == CUT_TYPE_IN and not currently_in:
160                                         res_cutlist.append(pts)
161                                         last_in = pts
162                                         currently_in = True
163
164                                 if type == CUT_TYPE_OUT and currently_in:
165                                         res_cutlist.append(pts)
166
167                                         # accumulate the segment
168                                         accumulated_in += pts - last_in 
169                                         accumulated_at = pts
170                                         currently_in = False
171
172                                 if type == CUT_TYPE_MARK and currently_in:
173                                         # relocate chaptermark against "in" time. This is not 100% accurate,
174                                         # as the in/out points are not.
175                                         res_chaptermarks.append(pts - accumulated_at + accumulated_in)
176
177                         res.append( (path, res_cutlist, res_chaptermarks) )
178
179                 return res