1 from Components.MenuList import MenuList
2 from Screens.Screen import Screen
3 from Screens.MessageBox import MessageBox
4 from Screens.ChoiceBox import ChoiceBox
5 from Components.ActionMap import ActionMap
6 from Components.Sources.StaticText import StaticText
7 from Components.Sources.Progress import Progress
8 from Components.Label import Label
9 from Components.FileList import FileList
10 from Components.MultiContent import MultiContentEntryText
11 from Tools.Directories import fileExists
12 from Tools.HardwareInfo import HardwareInfo
13 from enigma import eConsoleAppContainer, eListbox, gFont, eListboxPythonMultiContent, \
14 RT_HALIGN_LEFT, RT_HALIGN_CENTER, RT_VALIGN_CENTER, RT_WRAP, eRect, eTimer
15 from os import system, remove
18 from twisted.web import client
19 from twisted.internet import reactor, defer
20 from twisted.python import failure
21 from Plugins.SystemPlugins.Hotplug.plugin import hotplugNotifier
23 class UserRequestedCancel(Exception):
26 class HTTPProgressDownloader(client.HTTPDownloader):
27 def __init__(self, url, outfile, headers=None):
28 client.HTTPDownloader.__init__(self, url, outfile, headers=headers, agent="Dreambox .NFI Download Plugin")
30 self.progress_callback = None
31 self.deferred = defer.Deferred()
33 def noPage(self, reason):
34 if self.status == "304":
35 print reason.getErrorMessage()
36 client.HTTPDownloader.page(self, "")
38 client.HTTPDownloader.noPage(self, reason)
40 def gotHeaders(self, headers):
41 if self.status == "200":
42 if headers.has_key("content-length"):
43 self.totalbytes = int(headers["content-length"][0])
46 self.currentbytes = 0.0
47 return client.HTTPDownloader.gotHeaders(self, headers)
49 def pagePart(self, packet):
50 if self.status == "200":
51 self.currentbytes += len(packet)
52 if self.totalbytes and self.progress_callback:
53 self.progress_callback(self.currentbytes, self.totalbytes)
54 return client.HTTPDownloader.pagePart(self, packet)
57 return client.HTTPDownloader.pageEnd(self)
59 class downloadWithProgress:
60 def __init__(self, url, outputfile, contextFactory=None, *args, **kwargs):
61 scheme, host, port, path = client._parse(url)
62 self.factory = HTTPProgressDownloader(url, outputfile, *args, **kwargs)
63 self.connection = reactor.connectTCP(host, port, self.factory)
66 return self.factory.deferred
70 self.connection.disconnect()
71 #self.factory.deferred.errback(failure.Failure(UserRequestedCancel))
73 def addProgress(self, progress_callback):
75 self.factory.progress_callback = progress_callback
77 class Feedlist(MenuList):
78 def __init__(self, list=[], enableWrapAround = False):
79 MenuList.__init__(self, list, enableWrapAround, eListboxPythonMultiContent)
80 self.l.setFont(0, gFont("Regular", 16))
81 self.l.setItemHeight(22)
85 self.l.setList(self.list)
88 l = self.l.getCurrentSelection()
92 l = self.l.getCurrentSelection()
96 l = self.l.getCurrentSelection()
97 return l and l[0][0][:-3]+"nfo"
100 l = self.l.getCurrentSelection()
101 return l and l[0][1][:-3]+"nfo"
104 l = self.l.getCurrentSelection()
110 def moveSelection(self,idx=0):
111 if self.instance is not None:
112 self.instance.moveSelectionTo(idx)
114 class NFIDownload(Screen):
118 <screen name="NFIDownload" position="90,95" size="560,420" title="Image download utility">
119 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
120 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
121 <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
122 <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
123 <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#9f1313" transparent="1" />
124 <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" />
125 <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" />
126 <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" />
128 <widget source="label_top" render="Label" position="10,44" size="240,20" font="Regular;16" />
129 <widget name="feedlist" position="10,66" size="250,222" scrollbarMode="showOnDemand" />
130 <widget name="destlist" position="0,66" size="260,222" scrollbarMode="showOnDemand" />
132 <widget source="label_bottom" render="Label" position="10,312" size="240,18" font="Regular;16"/>
133 <widget source="path_bottom" render="Label" position="10,330" size="250,42" font="Regular;18" />
135 <widget source="infolabel" render="Label" position="270,44" size="280,284" font="Regular;16" />
136 <widget source="job_progressbar" render="Progress" position="10,374" size="540,26" borderWidth="1" backgroundColor="#254f7497" />
137 <widget source="job_progresslabel" render="Label" position="130,378" zPosition="2" font="Regular;18" halign="center" transparent="1" size="300,22" foregroundColor="#000000" />
138 <widget source="statusbar" render="Label" position="10,404" size="540,16" font="Regular;16" foregroundColor="#cccccc" />
141 def __init__(self, session, destdir="/tmp/"):
142 self.skin = NFIDownload.skin
143 Screen.__init__(self, session)
145 self["job_progressbar"] = Progress()
146 self["job_progresslabel"] = StaticText()
148 self["infolabel"] = StaticText()
149 self["statusbar"] = StaticText()
150 self["label_top"] = StaticText()
151 self["label_bottom"] = StaticText()
152 self["path_bottom"] = StaticText()
154 self["key_green"] = StaticText()
155 self["key_yellow"] = StaticText()
156 self["key_blue"] = StaticText()
158 self["key_red"] = StaticText()
160 self["feedlist"] = Feedlist([0,(eListboxPythonMultiContent.TYPE_TEXT, 0, 0,250, 30, 0, RT_HALIGN_LEFT|RT_VALIGN_CENTER, "feed not available")])
161 self["destlist"] = FileList(destdir, showDirectories = True, showFiles = False)
162 self["destlist"].hide()
164 self.download_container = eConsoleAppContainer()
170 self.box = HardwareInfo().get_device_name()
171 self.feed_base = "http://www.dreamboxupdate.com/opendreambox/1.5/%s/images/" % self.box
172 self.nfi_filter = "" # "release" # only show NFIs containing this string, or all if ""
174 self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "DirectionActions", "EPGSelectActions"],
176 "cancel": self.closeCB,
178 "green": self.nfi_download,
179 "yellow": self.switchList,
180 "blue": self.askCreateUSBstick,
181 "prevBouquet": self.switchList,
182 "nextBouquet": self.switchList,
187 "upRepeated": self.up,
188 "downRepeated": self.down,
194 def downloading(self, state=True):
196 self["key_red"].text = _("Cancel")
197 self["key_green"].text = ""
198 self["key_yellow"].text = ""
199 self["key_blue"].text = ""
202 self["key_red"].text = _("Exit")
203 if self["feedlist"].isValid():
204 self["key_green"].text = (_("Download"))
205 if self.focus is self.LIST_SOURCE:
206 self["key_yellow"].text = (_("Change dir."))
208 self["key_yellow"].text = (_("Select image"))
209 self["key_blue"].text = (_("Fix USB stick"))
211 def switchList(self,to_where=None):
212 if self.download or not self["feedlist"].isValid():
215 self["job_progressbar"].value = 0
216 self["job_progresslabel"].text = ""
219 if self.focus is self.LIST_SOURCE:
220 to_where = self.LIST_DEST
221 if self.focus is self.LIST_DEST:
222 to_where = self.LIST_SOURCE
224 if to_where is self.LIST_DEST:
225 self.focus = self.LIST_DEST
226 self["statusbar"].text = _("Please select target directory or medium")
227 self["label_top"].text = _("choose destination directory")+":"
228 self["feedlist"].hide()
229 self["destlist"].show()
230 self["label_bottom"].text = _("Selected source image")+":"
231 self["path_bottom"].text = str(self["feedlist"].getNFIname())
232 self["key_yellow"].text = (_("Select image"))
234 elif to_where is self.LIST_SOURCE:
235 self.focus = self.LIST_SOURCE
236 self["statusbar"].text = _("Please choose .NFI image file from feed server to download")
237 self["label_top"].text = _("select image from server")+":"
238 self["feedlist"].show()
239 self["destlist"].hide()
240 self["label_bottom"].text = _("Destination directory")+":"
241 self["path_bottom"].text = str(self["destlist"].getCurrentDirectory())
242 self["key_yellow"].text = (_("Change dir."))
247 if self.focus is self.LIST_SOURCE:
248 self["feedlist"].up()
250 if self.focus is self.LIST_DEST:
251 self["destlist"].up()
256 if self.focus is self.LIST_SOURCE:
257 self["feedlist"].down()
259 if self.focus is self.LIST_DEST:
260 self["destlist"].down()
265 if self.focus is self.LIST_SOURCE:
266 self["feedlist"].pageUp()
268 if self.focus is self.LIST_DEST:
269 self["destlist"].pageUp()
274 if self.focus is self.LIST_SOURCE:
275 self["feedlist"].pageDown()
277 if self.focus is self.LIST_DEST:
278 self["destlist"].pageDown()
283 if self.focus is self.LIST_DEST:
284 if self["destlist"].canDescent():
285 self["destlist"].descent()
287 def feed_download(self):
288 self.downloading(True)
289 self.download = self.feed_download
290 client.getPage(self.feed_base).addCallback(self.feed_finished).addErrback(self.feed_failed)
292 def feed_failed(self, failure_instance):
293 print "[feed_failed] " + str(failure_instance)
294 self["infolabel"].text = _("Could not connect to Dreambox .NFI Image Feed Server:") + "\n" + failure_instance.getErrorMessage() + "\n\n" + _("Please check your network settings!")
295 self.downloading(False)
297 def feed_finished(self, feedhtml):
298 print "[feed_finished] " + str(feedhtml)
299 self.downloading(False)
300 fileresultmask = re.compile("<a href=[\'\"](?P<url>.*?)[\'\"]>(?P<name>.*?.nfi)</a>", re.DOTALL)
301 searchresults = fileresultmask.finditer(feedhtml)
304 for x in searchresults:
306 if url[0:7] != "http://":
307 url = self.feed_base + x.group("url")
308 name = x.group("name")
309 if name.find(self.nfi_filter) > -1:
310 entry = [[name, url],(eListboxPythonMultiContent.TYPE_TEXT, 0, 0,250, 30, 0, RT_HALIGN_LEFT|RT_VALIGN_CENTER, name)]
311 print "adding to feedlist: " + str(entry)
312 fileresultlist.append(entry)
314 print "NOT adding to feedlist: " + name
315 self["feedlist"].l.setList(fileresultlist)
316 self["feedlist"].moveSelection(0)
318 if len(fileresultlist) > 0:
319 self.switchList(self.LIST_SOURCE)
322 self["infolabel"].text = _("Cannot parse feed directory")
324 def nfo_download(self):
325 print "[check_for_NFO]"
326 if self["feedlist"].isValid():
327 print "nfiname: " + self["feedlist"].getNFIname()
328 self["job_progressbar"].value = 0
329 self["job_progresslabel"].text = ""
330 if self["feedlist"].getNFIurl() is None:
331 self["key_green"].text = ""
333 self["key_green"].text = _("Download")
334 nfourl = self["feedlist"].getNFOurl()
335 print "downloading " + nfourl
336 self.download = self.nfo_download
337 self.downloading(True)
338 client.getPage(nfourl).addCallback(self.nfo_finished).addErrback(self.nfo_failed)
339 self["statusbar"].text = ("Downloading image description...")
341 def nfo_failed(self, failure_instance):
342 print "[nfo_failed] " + str(failure_instance)
343 self["infolabel"].text = _("No details for this image file") + "\n" + self["feedlist"].getNFIname()
344 self["statusbar"].text = ""
345 self.nfofilename = ""
347 self.downloading(False)
349 def nfo_finished(self,nfodata=""):
350 print "[nfo_finished] " + str(nfodata)
351 self.downloading(False)
354 self.nfofilename = self["destlist"].getCurrentDirectory() + '/' + self["feedlist"].getNFOname()
355 self["infolabel"].text = self.nfo
357 self.nfofilename = ""
358 self["infolabel"].text = _("No details for this image file")
359 self["statusbar"].text = ""
361 def nfi_download(self):
362 if self["destlist"].getCurrentDirectory() is None:
363 self.switchList(self.LIST_TARGET)
364 if self["feedlist"].isValid():
365 url = self["feedlist"].getNFIurl()
366 self.nfilocal = self["destlist"].getCurrentDirectory()+'/'+self["feedlist"].getNFIname()
367 print "[nfi_download] downloading %s to %s" % (url, self.nfilocal)
368 self.download = downloadWithProgress(url,self.nfilocal)
369 self.download.addProgress(self.nfi_progress)
370 self["job_progressbar"].range = 1000
371 self.download.start().addCallback(self.nfi_finished).addErrback(self.nfi_failed)
372 self.downloading(True)
374 def nfi_progress(self, recvbytes, totalbytes):
375 #print "[update_progress] recvbytes=%d, totalbytes=%d" % (recvbytes, totalbytes)
376 self["job_progressbar"].value = int(1000*recvbytes/float(totalbytes))
377 self["job_progresslabel"].text = "%d of %d kBytes (%.2f%%)" % (recvbytes/1024, totalbytes/1024, 100*recvbytes/float(totalbytes))
379 def nfi_failed(self, failure_instance=None, error_message=""):
380 if error_message == "" and failure_instance is not None:
381 error_message = failure_instance.getErrorMessage()
382 print "[nfi_failed] " + error_message
383 if fileExists(self["destlist"].getCurrentDirectory()+'/'+self["feedlist"].getNFIname()):
384 message = "%s %s\n%s" % (_(".NFI Download failed:"), error_message, _("Remove the incomplete .NFI file?"))
385 self.session.openWithCallback(self.nfi_remove, MessageBox, message, MessageBox.TYPE_YESNO)
387 message = "%s %s" % (_(".NFI Download failed:"),error_message)
388 self.session.open(MessageBox, message, MessageBox.TYPE_ERROR)
389 self.downloading(False)
391 def nfi_finished(self, string=""):
392 print "[nfi_finished] " + str(string)
394 self.nfofilename = self["destlist"].getCurrentDirectory() + '/' + self["feedlist"].getNFOname()
395 nfofd = open(self.nfofilename, "w")
397 nfofd.write(self.nfo)
400 print "couldn't save nfo file " + self.nfofilename
402 pos = self.nfo.find("MD5:")
403 if pos > 0 and len(self.nfo) >= pos+5+32:
404 self["statusbar"].text = ("Please wait for md5 signature verification...")
406 md5 = self.nfo[pos+5:pos+5+32] + " " + self.nfilocal
408 self.download_container.setCWD(self["destlist"].getCurrentDirectory())
409 self.download_container.appClosed.append(self.md5finished)
410 self.download_container.execute(cmd)
411 self.download_container.write(md5)
412 self.download_container.dataSent.append(self.md5ready)
414 self["statusbar"].text = "Download completed."
415 self.downloading(False)
417 self["statusbar"].text = "Download completed."
418 self.downloading(False)
420 def md5ready(self, retval):
421 self.download_container.sendEOF()
423 def md5finished(self, retval):
424 print "[md5finished]: " + str(retval)
425 self.download_container.appClosed.remove(self.md5finished)
427 self["statusbar"].text = _(".NFI file passed md5sum signature check. You can safely flash this image!")
428 self.switchList(self.LIST_SOURCE)
429 self.downloading(False)
431 self.session.openWithCallback(self.nfi_remove, MessageBox, (_("The md5sum validation failed, the file may be downloaded incompletely or be corrupted!") + "\n" + _("Remove the broken .NFI file?")), MessageBox.TYPE_YESNO)
433 def nfi_remove(self, answer):
434 self.downloading(False)
436 nfifilename = self["destlist"].getCurrentDirectory()+'/'+self["feedlist"].getNFIname()
437 if fileExists(self.nfofilename):
438 remove(self.nfofilename)
439 if fileExists(nfifilename):
441 self.switchList(self.LIST_SOURCE)
443 def askCreateUSBstick(self):
445 self.imagefilename = "/tmp/nfiflash_" + self.box + ".img"
446 message = _("You have chosen to create a new .NFI flasher bootable USB stick. This will repartition the USB stick and therefore all data on it will be erased.")
447 self.session.openWithCallback(self.flasherdownload_query, MessageBox, (message + '\n' + _("First we need to download the latest boot environment for the USB flasher.")), MessageBox.TYPE_YESNO)
449 def flasherdownload_query(self, answer):
451 self.downloading(False)
452 self.switchList(self.LIST_SOURCE)
454 #url = self.feed_base + "/nfiflasher_" + self.box + ".tar.bz2"
455 url = "http://www.dreamboxupdate.com/download/opendreambox/dreambox-nfiflasher-%s.tar.bz2" % self.box
456 localfile = "/tmp/nfiflasher_image.tar.bz2"
457 print "[flasherdownload_query] downloading %s to %s" % (url, localfile)
458 self["statusbar"].text = ("Downloading %s..." % url)
459 self.download = downloadWithProgress(url,localfile)
460 self.download.addProgress(self.nfi_progress)
461 self["job_progressbar"].range = 1000
462 self.download.start().addCallback(self.flasherdownload_finished).addErrback(self.flasherdownload_failed)
464 def flasherdownload_failed(self, failure_instance=None, error_message=""):
465 if error_message == "" and failure_instance is not None:
466 error_message = failure_instance.getErrorMessage()
467 print "[flasherdownload_failed] " + error_message
468 message = "%s %s" % (_("Download of USB flasher boot image failed: "),error_message)
469 self.session.open(MessageBox, message, MessageBox.TYPE_ERROR)
470 self.remove_img(True)
472 def flasherdownload_finished(self, string=""):
473 print "[flasherdownload_finished] " + str(string)
474 self.container = eConsoleAppContainer()
475 self.container.appClosed.append(self.umount_finished)
476 self.container.dataAvail.append(self.tool_avail)
479 from os import listdir
480 for device in listdir("/dev"):
481 if device[:2] == "sd" and device[-1:].isdigit():
482 umountdevs += "/dev/"+device
483 self.cmd = "umount " + umountdevs
484 print "executing " + self.cmd
485 self.container.execute(self.cmd)
487 def tool_avail(self, string):
488 print "[tool_avail]" + string
489 self.taskstring += string
491 def umount_finished(self, retval):
492 self.container.appClosed.remove(self.umount_finished)
493 self.container.appClosed.append(self.dmesg_cleared)
495 self.cmd = "dmesg -c"
496 print "executing " + self.cmd
497 self.container.execute(self.cmd)
499 def dmesg_cleared(self, answer):
500 self.container.appClosed.remove(self.dmesg_cleared)
501 self.msgbox = self.session.open(MessageBox, _("Please disconnect all USB devices from your Dreambox and (re-)attach the target USB stick (minimum size is 64 MB) now!"), MessageBox.TYPE_INFO)
502 hotplugNotifier.append(self.hotplugCB)
504 def hotplugCB(self, dev, action):
505 print "[hotplugCB]", dev, action
506 if dev.startswith("sd") and action == "add":
508 hotplugNotifier.remove(self.hotplugCB)
509 self.container.appClosed.append(self.dmesg_scanned)
512 print "executing " + self.cmd
513 self.container.execute(self.cmd)
515 def dmesg_scanned(self, retval):
516 self.container.appClosed.remove(self.dmesg_scanned)
517 dmesg_lines = self.taskstring.splitlines()
518 self.devicetext = None
519 self.stickdevice = None
520 for i, line in enumerate(dmesg_lines):
521 if line.find("usb-storage: waiting for device") != -1 and len(dmesg_lines) > i+3:
522 self.devicetext = dmesg_lines[i+1].lstrip()+"\n"+dmesg_lines[i+3]
523 elif line.find("/dev/scsi/host") != -1:
524 self.stickdevice = line.split(":",1)[0].lstrip()
526 if retval != 0 or self.devicetext is None or self.stickdevice is None:
527 self.session.openWithCallback(self.remove_img, MessageBox, _("No useable USB stick found"), MessageBox.TYPE_ERROR)
529 self.session.openWithCallback(self.fdisk_query, MessageBox, (_("The following device was found:\n\n%s\n\nDo you want to write the USB flasher to this stick?") % self.devicetext), MessageBox.TYPE_YESNO)
531 def fdisk_query(self, answer):
532 if answer == True and self.stickdevice:
533 self["statusbar"].text = ("Partitioning USB stick...")
534 self["job_progressbar"].range = 1000
535 self["job_progressbar"].value = 100
536 self["job_progresslabel"].text = "5.00%"
538 self.container.appClosed.append(self.fdisk_finished)
539 self.container.execute("fdisk " + self.stickdevice + "/disc")
540 self.container.write("d\nn\np\n1\n\n\nt\n6\nw\n")
541 self.delayTimer = eTimer()
542 self.delayTimer.callback.append(self.progress_increment)
543 self.delayTimer.start(105, False)
545 self.remove_img(True)
547 def fdisk_finished(self, retval):
548 self.container.appClosed.remove(self.fdisk_finished)
549 self.delayTimer.stop()
551 if fileExists(self.imagefilename):
553 self["job_progressbar"].value = 700
555 self["statusbar"].text = ("Decompressing USB stick flasher boot image...")
557 self.container.appClosed.append(self.tar_finished)
558 self.container.setCWD("/tmp")
559 self.cmd = "tar -xjvf nfiflasher_image.tar.bz2"
560 self.container.execute(self.cmd)
561 print "executing " + self.cmd
562 self.delayTimer = eTimer()
563 self.delayTimer.callback.append(self.progress_increment)
564 self.delayTimer.start(105, False)
566 print "fdisk failed: " + str(retval)
567 self.session.openWithCallback(self.remove_img, MessageBox, ("fdisk " + _("failed") + ":\n" + str(self.taskstring)), MessageBox.TYPE_ERROR)
569 def progress_increment(self):
570 newval = int(self["job_progressbar"].value) + 1
572 self["job_progressbar"].value = newval
573 self["job_progresslabel"].text = "%.2f%%" % (newval/10.0)
575 def tar_finished(self, retval):
576 self.delayTimer.stop()
577 if len(self.container.appClosed) > 0:
578 self.container.appClosed.remove(self.tar_finished)
580 self.imagefilename = "/tmp/nfiflash_" + self.box + ".img"
581 self["statusbar"].text = ("Copying USB flasher boot image to stick...")
583 self.container.appClosed.append(self.dd_finished)
584 self.cmd = "dd if=%s of=%s" % (self.imagefilename,self.stickdevice+"/part1")
585 self.container.execute(self.cmd)
586 print "executing " + self.cmd
587 self.delayTimer = eTimer()
588 self.delayTimer.callback.append(self.progress_increment)
589 self.delayTimer.start(105, False)
591 self.session.openWithCallback(self.remove_img, MessageBox, (self.cmd + " " + _("failed") + ":\n" + str(self.taskstring)), MessageBox.TYPE_ERROR)
593 def dd_finished(self, retval):
594 self.delayTimer.stop()
595 self.container.appClosed.remove(self.dd_finished)
596 self.downloading(False)
598 self["job_progressbar"].value = 950
599 self["job_progresslabel"].text = "95.00%"
600 self["statusbar"].text = ("Remounting stick partition...")
602 self.container.appClosed.append(self.mount_finished)
603 self.cmd = "mount %s /mnt/usb -o rw,sync" % (self.stickdevice+"/part1")
604 self.container.execute(self.cmd)
605 print "executing " + self.cmd
607 self.session.openWithCallback(self.remove_img, MessageBox, (self.cmd + " " + _("failed") + ":\n" + str(self.taskstring)), MessageBox.TYPE_ERROR)
609 def mount_finished(self, retval):
610 self.container.dataAvail.remove(self.tool_avail)
611 self.container.appClosed.remove(self.mount_finished)
613 self["job_progressbar"].value = 1000
614 self["job_progresslabel"].text = "100.00%"
615 self["statusbar"].text = (".NFI Flasher bootable USB stick successfully created.")
616 self.session.openWithCallback(self.remove_img, MessageBox, _("The .NFI Image flasher USB stick is now ready to use. Please download an .NFI image file from the feed server and save it on the stick. Then reboot and hold the 'Down' key on the front panel to boot the .NFI flasher from the stick!"), MessageBox.TYPE_INFO)
617 self["destlist"].changeDir("/mnt/usb")
619 self.session.openWithCallback(self.remove_img, MessageBox, (self.cmd + " " + _("failed") + ":\n" + str(self.taskstring)), MessageBox.TYPE_ERROR)
621 def remove_img(self, answer):
622 if fileExists("/tmp/nfiflasher_image.tar.bz2"):
623 remove("/tmp/nfiflasher_image.tar.bz2")
624 if fileExists(self.imagefilename):
625 remove(self.imagefilename)
626 self.downloading(False)
627 self.switchList(self.LIST_SOURCE)
632 #self.nfi_failed(None, "Cancelled by user request")
633 self.downloading(False)
637 def main(session, **kwargs):
638 session.open(NFIDownload,"/home/root")
640 def filescan_open(list, session, **kwargs):
641 dev = "/dev/" + (list[0].path).rsplit('/',1)[0][7:]
642 print "mounting device " + dev + " to /mnt/usb..."
643 system("mount "+dev+" /mnt/usb/ -o rw,sync")
644 session.open(NFIDownload,"/mnt/usb/")
646 def filescan(**kwargs):
647 from Components.Scanner import Scanner, ScanPath
649 Scanner(mimetypes = ["application/x-dream-image"],
652 ScanPath(path = "", with_subdirs = False),
655 description = (_("Download .NFI-Files for USB-Flasher")+"..."),
656 openfnc = filescan_open, )