allow DVD burning in background. to view progress of jobs, press extensions key ...
[enigma2.git] / lib / python / Plugins / SystemPlugins / NFIFlash / flasher.py
1 # -*- coding: utf8 -*-
2 from Screens.Screen import Screen
3 from Screens.MessageBox import MessageBox
4 from Screens.ChoiceBox import ChoiceBox
5 from Screens.Standby import TryQuitMainloop
6 from Components.ActionMap import ActionMap
7 from Components.Sources.StaticText import StaticText
8 from Components.Sources.Progress import Progress
9 from Components.Sources.Boolean import Boolean
10 from Components.Label import Label
11 from Components.FileList import FileList
12 from Components.Task import Task, Job, JobManager
13 from Tools.Directories import fileExists
14 from Tools.HardwareInfo import HardwareInfo
15 from os import system
16 from enigma import eConsoleAppContainer
17 import re
18
19 class writeNAND(Task):
20         def __init__(self,job,param,box):
21                 Task.__init__(self,job, _("Writing image file to NAND Flash"))
22                 self.setTool("/usr/lib/enigma2/python/Plugins/SystemPlugins/NFIFlash/mywritenand")
23                 if box == "dm7025":
24                         self.end = 256
25                 elif box[:5] == "dm800":
26                         self.end = 512
27                 if box == "dm8000":
28                         self.setTool("/usr/lib/enigma2/python/Plugins/SystemPlugins/NFIFlash/dm8000_writenand")
29                 self.args += param
30                 self.weighting = 1      
31
32         def processOutput(self, data):
33                 print "[writeNand] " + data
34                 if data == "." or data.endswith(" ."):
35                         self.progress += 1
36                 elif data.find("*** done!") > 0:
37                         print "data.found done"
38                         self.setProgress(self.end)
39                 else:
40                         self.output_line = data
41
42 class NFISummary(Screen):
43         skin = """
44         <screen position="0,0" size="132,64">
45                 <widget source="title" render="Label" position="2,0" size="120,14" valign="center" font="Regular;12" />
46                 <widget source="content" render="Label" position="2,14" size="120,34" font="Regular;12" transparent="1" zPosition="1"  />
47                 <widget source="job_progresslabel" render="Label" position="66,50" size="60,14" font="Regular;12" transparent="1" halign="right" zPosition="0" />
48                 <widget source="job_progressbar" render="Progress" position="2,50" size="66,14" borderWidth="1" />
49         </screen>"""
50
51         def __init__(self, session, parent):
52                 Screen.__init__(self, session, parent)
53                 self["title"] = StaticText(_("Image flash utility"))
54                 self["content"] = StaticText(_("Please select .NFI flash image file from medium"))
55                 self["job_progressbar"] = Progress()
56                 self["job_progresslabel"] = StaticText("")
57
58         def setText(self, text):
59                 self["content"].setText(text)
60
61 class NFIFlash(Screen):
62         skin = """
63                 <screen name="NFIFlash" position="90,95" size="560,420" title="Image flash utility">
64                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
65                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
66                         <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
67                         <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
68                         <widget source="key_yellow" render="Label" position="280,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#a08500" transparent="1" />
69                         <widget source="key_blue" render="Label" position="420,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#18188b" transparent="1" />
70                         <widget source="listlabel" render="Label" position="16,44" size="200,21" valign="center" font="Regular;18" />
71                         <widget name="filelist" position="0,68" size="260,260" scrollbarMode="showOnDemand" />
72                         <widget source="infolabel" render="Label" position="270,44" size="280,284" font="Regular;16" />
73                         <widget source="job_progressbar" render="Progress" position="10,374" size="540,26" borderWidth="1" backgroundColor="#254f7497" />
74                         <widget source="job_progresslabel" render="Label" position="180,378" zPosition="2" font="Regular;18" halign="center" transparent="1" size="200,22" foregroundColor="#000000" />
75                         <widget source="statusbar" render="Label" position="10,404" size="540,16" font="Regular;16" foregroundColor="#cccccc" />
76                 </screen>"""
77
78         def __init__(self, session, cancelable = True, close_on_finish = False):
79                 self.skin = NFIFlash.skin
80                 Screen.__init__(self, session)
81                 
82                 self["job_progressbar"] = Progress()
83                 self["job_progresslabel"] = StaticText("")
84                 
85                 self["finished"] = Boolean()
86
87                 self["infolabel"] = StaticText("")
88                 self["statusbar"] = StaticText(_("Please select .NFI flash image file from medium"))
89                 self["listlabel"] = StaticText(_("select .NFI flash file")+":")
90                 
91                 self["key_green"] = StaticText()
92                 self["key_yellow"] = StaticText()
93                 self["key_blue"] = StaticText()
94
95                 self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "DirectionActions"],
96                 {
97                         "green": self.ok,
98                         "yellow": self.reboot,
99                         "ok": self.ok,
100                         "left": self.left,
101                         "right": self.right,
102                         "up": self.up,
103                         "down": self.down
104                 }, -1)
105
106                 currDir = "/media/usb/"
107                 self.filelist = FileList(currDir, matchingPattern = "^.*\.(nfi|NFI)")
108                 self["filelist"] = self.filelist
109                 self.nfifile = ""
110                 self.md5sum = ""
111                 self.job = None
112                 self.box = HardwareInfo().get_device_name()
113
114         def closeCB(self):
115                 if ( self.job is None or self.job.status is not self.job.IN_PROGRESS ) and not self.no_autostart:
116                         self.close()
117                 #else:
118                         #if self.cancelable:
119                                 #self.cancel()
120
121         def up(self):
122                 self["filelist"].up()
123                 self.check_for_NFO()
124
125         def down(self):
126                 self["filelist"].down()
127                 self.check_for_NFO()
128         
129         def right(self):
130                 self["filelist"].pageDown()
131                 self.check_for_NFO()
132
133         def left(self):
134                 self["filelist"].pageUp()
135                 self.check_for_NFO()
136
137         def check_for_NFO(self):
138                 self.session.summary.setText(self["filelist"].getFilename())
139                 if self["filelist"].getFilename() is None:
140                         return
141                 if self["filelist"].getCurrentDirectory() is not None:
142                         self.nfifile = self["filelist"].getCurrentDirectory()+self["filelist"].getFilename()
143
144                 if self.nfifile.upper().endswith(".NFI"):
145                         self["key_green"].text = _("Flash")
146                         nfofilename = self.nfifile[0:-3]+"nfo"
147                         if fileExists(nfofilename):
148                                 nfocontent = open(nfofilename, "r").read()
149                                 self["infolabel"].text = nfocontent
150                                 pos = nfocontent.find("md5sum")
151                                 if pos > 0:
152                                         self.md5sum = nfofilename
153                                 else:
154                                         self.md5sum = ""
155                         else:
156                                 self["infolabel"].text = _("No details for this image file") + ":\n" + self["filelist"].getFilename()
157                                 self.md5sum = ""
158                 else:
159                         self["infolabel"].text = ""
160                         self["key_green"].text = ""
161
162         def ok(self):
163                 if self.job is None or self.job.status is not self.job.IN_PROGRESS:
164                         if self["filelist"].canDescent(): # isDir
165                                 self["filelist"].descent()
166                                 self.session.summary.setText(self["filelist"].getFilename())
167                                 self.check_for_NFO()
168                         else:
169                                 self.queryFlash()
170         
171         def queryFlash(self):
172                 fd = open(self.nfifile, 'r')
173                 print fd
174                 sign = fd.read(11)
175                 print sign
176                 if sign.find("NFI1" + self.box + "\0") == 0:
177                         if self.md5sum != "":
178                                 self["statusbar"].text = _("Please wait for md5 signature verification...")
179                                 self.session.summary.setText(_("Please wait for md5 signature verification..."))
180                                 self.container = eConsoleAppContainer()
181                                 self.container.setCWD(self["filelist"].getCurrentDirectory())
182                                 self.container.appClosed.get().append(self.md5finished)
183                                 self.container.execute("md5sum -cs " + self.md5sum)
184                         else:
185                                 self.session.openWithCallback(self.queryCB, MessageBox, _("This .NFI file does not have a md5sum signature and is not guaranteed to work. Do you really want to burn this image to flash memory?"), MessageBox.TYPE_YESNO)
186                 else:
187                         self.session.open(MessageBox, (_("This .NFI file does not contain a valid %s image!") % (self.box.upper())), MessageBox.TYPE_ERROR)
188                         
189         def md5finished(self, retval):
190                 if retval==0:
191                         self.session.openWithCallback(self.queryCB, MessageBox, _("This .NFI file has a valid md5 signature. Continue programming this image to flash memory?"), MessageBox.TYPE_YESNO)
192                 else:
193                         self.session.openWithCallback(self.queryCB, MessageBox, _("The md5sum validation failed, the file may be corrupted! Are you sure that you want to burn this image to flash memory? You are doing this at your own risk!"), MessageBox.TYPE_YESNO)
194
195         def queryCB(self, answer):
196                 if answer == True:
197                         self.createJob()
198                 else:
199                         self["statusbar"].text = _("Please select .NFI flash image file from medium")
200
201         def createJob(self):
202                 self.job = Job("Image flashing job")
203                 param = [self.nfifile]
204                 writeNAND(self.job,param,self.box)
205                 #writeNAND2(self.job,param)
206                 #writeNAND3(self.job,param)
207                 self.job.state_changed.append(self.update_job)
208                 self.job.end = 540
209                 self.cwd = self["filelist"].getCurrentDirectory()
210                 self["job_progressbar"].range = self.job.end
211                 self.startJob()
212
213         def startJob(self):
214                 self["key_blue"].text = ""
215                 self["key_yellow"].text = ""
216                 self["key_green"].text = ""
217                 #self["progress0"].show()
218                 #self["progress1"].show()
219
220                 self.job.start(self.jobcb)
221
222         def update_job(self):
223                 j = self.job
224                 #print "[job state_changed]"
225                 if j.status == j.IN_PROGRESS:
226                         self.session.summary["job_progressbar"].value = j.progress
227                         self.session.summary["job_progressbar"].range = j.end
228                         self.session.summary["job_progresslabel"].text = "%.2f%%" % (100*j.progress/float(j.end))
229                         self["job_progressbar"].range = j.end
230                         self["job_progressbar"].value = j.progress
231                         #print "[update_job] j.progress=%f, j.getProgress()=%f, j.end=%d, text=%f" % (j.progress, j.getProgress(), j.end,  (100*j.progress/float(j.end)))
232                         self["job_progresslabel"].text = "%.2f%%" % (100*j.progress/float(j.end))
233                         self.session.summary.setText(j.tasks[j.current_task].name)
234                         self["statusbar"].text = (j.tasks[j.current_task].name)
235
236                 elif j.status == j.FINISHED:
237                         self["statusbar"].text = _("Writing NFI image file to flash completed")
238                         self.session.summary.setText(_("NFI image flashing completed. Press Yellow to Reboot!"))
239                         self["key_yellow"].text = _("Reboot")
240
241                 elif j.status == j.FAILED:
242                         self["statusbar"].text = j.tasks[j.current_task].name + " " + _("failed")
243                         self.session.open(MessageBox, (_("Flashing failed") + ":\n" + j.tasks[j.current_task].name + ":\n" + j.tasks[j.current_task].output_line), MessageBox.TYPE_ERROR)
244
245         def jobcb(self, jobref, fasel, blubber):
246                 print "[jobcb] %s %s %s" % (jobref, fasel, blubber)
247                 self["key_green"].text = _("Flash")
248
249         def reboot(self):
250                 if self.job.status == self.job.FINISHED:
251                         self["statusbar"].text = _("rebooting...")
252                         TryQuitMainloop(self.session,2)
253                         
254         def createSummary(self):
255                 return NFISummary