1 # -*- coding: utf-8 -*-
2 from Plugins.SystemPlugins.Hotplug.plugin import hotplugNotifier
3 from Screens.Screen import Screen
4 from Screens.MessageBox import MessageBox
5 from Screens.ChoiceBox import ChoiceBox
6 from Screens.HelpMenu import HelpableScreen
7 from Screens.TaskView import JobView
8 from Components.About import about
9 from Components.ActionMap import ActionMap
10 from Components.Sources.StaticText import StaticText
11 from Components.Sources.List import List
12 from Components.Label import Label
13 from Components.FileList import FileList
14 from Components.MenuList import MenuList
15 from Components.MultiContent import MultiContentEntryText
16 from Components.ScrollLabel import ScrollLabel
17 from Components.Harddisk import harddiskmanager
18 from Components.Task import Task, Job, job_manager, Condition
19 from Tools.Directories import fileExists, isMount
20 from Tools.HardwareInfo import HardwareInfo
21 from Tools.Downloader import downloadWithProgress
22 from enigma import eConsoleAppContainer, gFont, RT_HALIGN_LEFT, RT_HALIGN_CENTER, RT_VALIGN_CENTER, RT_WRAP, eTimer
23 from os import system, path, access, stat, remove, W_OK, R_OK
24 from twisted.web import client
25 from twisted.internet import reactor, defer
26 from twisted.python import failure
29 class ImageDownloadJob(Job):
30 def __init__(self, url, filename, device=None, mountpoint="/"):
31 Job.__init__(self, _("Download .NFI-Files for USB-Flasher"))
33 if isMount(mountpoint):
34 UmountTask(self, mountpoint)
35 MountTask(self, device, mountpoint)
36 ImageDownloadTask(self, url, mountpoint+filename)
37 ImageDownloadTask(self, url[:-4]+".nfo", mountpoint+filename[:-4]+".nfo")
39 UmountTask(self, mountpoint)
42 self.tasks[0].args += self.tasks[0].retryargs
45 class MountTask(Task):
46 def __init__(self, job, device, mountpoint):
47 Task.__init__(self, job, ("mount"))
50 self.mountpoint = mountpoint
51 self.args += [ device, mountpoint, "-o"+options ]
54 def processOutput(self, data):
55 print "[MountTask] output:", data
57 class UmountTask(Task):
58 def __init__(self, job, mountpoint):
59 Task.__init__(self, job, ("mount"))
60 self.setTool("umount")
61 self.args += [mountpoint]
64 class DownloaderPostcondition(Condition):
65 def check(self, task):
66 return task.returncode == 0
68 def getErrorMessage(self, task):
69 return self.error_message
71 class ImageDownloadTask(Task):
72 def __init__(self, job, url, path):
73 Task.__init__(self, job, _("Downloading"))
74 self.postconditions.append(DownloaderPostcondition())
78 self.error_message = ""
79 self.last_recvbytes = 0
80 self.error_message = None
82 def run(self, callback):
83 self.callback = callback
84 self.download = downloadWithProgress(self.url,self.path)
85 self.download.addProgress(self.download_progress)
86 self.download.start().addCallback(self.download_finished).addErrback(self.download_failed)
87 print "[ImageDownloadTask] downloading", self.url, "to", self.path
89 def download_progress(self, recvbytes, totalbytes):
90 #print "[update_progress] recvbytes=%d, totalbytes=%d" % (recvbytes, totalbytes)
91 if ( recvbytes - self.last_recvbytes ) > 10000: # anti-flicker
92 self.progress = int(100*(float(recvbytes)/float(totalbytes)))
93 self.name = _("Downloading") + ' ' + "%d of %d kBytes" % (recvbytes/1024, totalbytes/1024)
94 self.last_recvbytes = recvbytes
96 def download_failed(self, failure_instance=None, error_message=""):
97 self.error_message = error_message
98 if error_message == "" and failure_instance is not None:
99 self.error_message = failure_instance.getErrorMessage()
100 print "[download_failed]", self.error_message
101 Task.processFinished(self, 1)
103 def download_finished(self, string=""):
104 print "[download_finished]", string
105 Task.processFinished(self, 0)
107 class StickWizardJob(Job):
108 def __init__(self, path):
109 Job.__init__(self, _("USB stick wizard"))
112 while self.device[-1:] == "/" or self.device[-1:].isdigit():
113 self.device = self.device[:-1]
115 box = HardwareInfo().get_device_name()
116 url = "http://www.dreamboxupdate.com/download/opendreambox/dreambox-nfiflasher-%s.tar.bz2" % box
117 self.downloadfilename = "/tmp/dreambox-nfiflasher-%s.tar.bz2" % box
118 self.imagefilename = "/tmp/nfiflash_%s.img" % box
119 #UmountTask(self, device)
121 ImageDownloadTask(self, url, self.downloadfilename)
125 class PartitionTaskPostcondition(Condition):
126 def check(self, task):
127 return task.returncode == 0
129 def getErrorMessage(self, task):
131 task.ERROR_BLKRRPART: ("Device or resource busy"),
132 task.ERROR_UNKNOWN: (task.errormsg)
135 class PartitionTask(Task):
136 ERROR_UNKNOWN, ERROR_BLKRRPART = range(2)
137 def __init__(self, job):
138 Task.__init__(self, job, ("partitioning"))
139 self.postconditions.append(PartitionTaskPostcondition())
141 self.setTool("sfdisk")
142 self.args += [self.job.device]
144 self.initial_input = "0 - 0x6 *\n;\n;\n;\ny"
147 def run(self, callback):
148 Task.run(self, callback)
150 def processOutput(self, data):
151 print "[PartitionTask] output:", data
152 if data.startswith("BLKRRPART:"):
153 self.error = self.ERROR_BLKRRPART
155 self.error = self.ERROR_UNKNOWN
158 class UnpackTask(Task):
159 def __init__(self, job):
160 Task.__init__(self, job, ("Unpacking USB flasher image..."))
163 self.args += ["-xjvf", self.job.downloadfilename]
166 self.delayTimer = eTimer()
167 self.delayTimer.callback.append(self.progress_increment)
169 def run(self, callback):
170 Task.run(self, callback)
171 self.delayTimer.start(950, False)
173 def progress_increment(self):
176 def processOutput(self, data):
177 print "[UnpackTask] output: \'%s\'" % data
178 self.job.imagefilename = data
181 self.delayTimer.callback.remove(self.progress_increment)
183 class CopyTask(Task):
184 def __init__(self, job):
185 Task.__init__(self, job, ("Copying USB flasher boot image to stick..."))
188 self.args += ["if=%s" % self.job.imagefilename, "of=%s1" % self.job.device]
191 self.delayTimer = eTimer()
192 self.delayTimer.callback.append(self.progress_increment)
194 def run(self, callback):
195 Task.run(self, callback)
196 self.delayTimer.start(100, False)
198 def progress_increment(self):
201 def processOutput(self, data):
202 print "[CopyTask] output:", data
205 self.delayTimer.callback.remove(self.progress_increment)
207 class NFOViewer(Screen):
209 <screen name="NFOViewer" position="center,center" size="610,410" title="Changelog viewer" >
210 <widget name="changelog" position="10,10" size="590,380" font="Regular;16" />
213 def __init__(self, session, nfo):
214 Screen.__init__(self, session)
215 self["changelog"] = ScrollLabel(nfo)
217 self["ViewerActions"] = ActionMap(["SetupActions", "ColorActions", "DirectionActions"],
223 "down": self.pageDown,
227 self["changelog"].pageUp()
230 self["changelog"].pageDown()
235 class feedDownloader:
236 def __init__(self, feed_base, box, OE_vers):
237 print "[feedDownloader::init] feed_base=%s, box=%s" % (feed_base, box)
238 self.feed_base = feed_base
239 self.OE_vers = OE_vers
242 def getList(self, callback, errback):
243 self.urlbase = "%s/%s/%s/images/" % (self.feed_base, self.OE_vers, self.box)
244 print "[getList]", self.urlbase
245 self.callback = callback
246 self.errback = errback
247 client.getPage(self.urlbase).addCallback(self.feed_finished).addErrback(self.feed_failed)
249 def feed_failed(self, failure_instance):
250 print "[feed_failed]", str(failure_instance)
251 self.errback(failure_instance.getErrorMessage())
253 def feed_finished(self, feedhtml):
254 print "[feed_finished]"
255 fileresultmask = re.compile("<a class=[\'\"]nfi[\'\"] href=[\'\"](?P<url>.*?)[\'\"]>(?P<name>.*?.nfi)</a>", re.DOTALL)
256 searchresults = fileresultmask.finditer(feedhtml)
259 for x in searchresults:
261 if url[0:7] != "http://":
262 url = self.urlbase + x.group("url")
263 name = x.group("name")
265 fileresultlist.append(entry)
266 self.callback(fileresultlist, self.OE_vers)
268 class DeviceBrowser(Screen, HelpableScreen):
270 <screen name="DeviceBrowser" position="center,center" size="520,430" title="Please select target medium" >
271 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
272 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
273 <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" />
274 <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" />
275 <widget source="message" render="Label" position="5,50" size="510,150" font="Regular;16" />
276 <widget name="filelist" position="5,210" size="510,220" scrollbarMode="showOnDemand" />
279 def __init__(self, session, startdir, message="", showDirectories = True, showFiles = True, showMountpoints = True, matchingPattern = "", useServiceRef = False, inhibitDirs = False, inhibitMounts = False, isTop = False, enableWrapAround = False, additionalExtensions = None):
280 Screen.__init__(self, session)
282 HelpableScreen.__init__(self)
284 self["key_red"] = StaticText(_("Cancel"))
285 self["key_green"] = StaticText()
286 self["message"] = StaticText(message)
288 self.filelist = FileList(startdir, showDirectories = showDirectories, showFiles = showFiles, showMountpoints = showMountpoints, matchingPattern = matchingPattern, useServiceRef = useServiceRef, inhibitDirs = inhibitDirs, inhibitMounts = inhibitMounts, isTop = isTop, enableWrapAround = enableWrapAround, additionalExtensions = additionalExtensions)
289 self["filelist"] = self.filelist
291 self["FilelistActions"] = ActionMap(["SetupActions", "ColorActions"],
299 hotplugNotifier.append(self.hotplugCB)
300 self.onShown.append(self.updateButton)
301 self.onClose.append(self.removeHotplug)
303 def hotplugCB(self, dev, action):
304 print "[hotplugCB]", dev, action
307 def updateButton(self):
309 if self["filelist"].getFilename() or self["filelist"].getCurrentDirectory():
310 self["key_green"].text = _("Use")
312 self["key_green"].text = ""
314 def removeHotplug(self):
315 print "[removeHotplug]"
316 hotplugNotifier.remove(self.hotplugCB)
319 if self.filelist.canDescent():
320 if self["filelist"].showMountpoints == True and self["filelist"].showDirectories == False:
323 self.filelist.descent()
326 print "[use]", self["filelist"].getCurrentDirectory(), self["filelist"].getFilename()
327 if self["filelist"].getCurrentDirectory() is not None:
328 if self.filelist.canDescent() and self["filelist"].getFilename() and len(self["filelist"].getFilename()) > len(self["filelist"].getCurrentDirectory()):
329 self.filelist.descent()
330 self.close(self["filelist"].getCurrentDirectory())
331 elif self["filelist"].getFilename():
332 self.close(self["filelist"].getFilename())
337 (ALLIMAGES, RELEASE, EXPERIMENTAL, STICK_WIZARD, START) = range(5)
339 class NFIDownload(Screen):
341 <screen name="NFIDownload" position="center,center" size="610,410" title="NFIDownload" >
342 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
343 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
344 <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
345 <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" alphatest="on" />
346 <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" />
347 <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" />
348 <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" />
349 <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" />
350 <ePixmap pixmap="skin_default/border_menu_350.png" position="5,50" zPosition="1" size="350,300" transparent="1" alphatest="on" />
351 <widget source="menu" render="Listbox" position="15,60" size="330,290" scrollbarMode="showOnDemand">
352 <convert type="TemplatedMultiContent">
355 MultiContentEntryText(pos = (2, 2), size = (330, 24), flags = RT_HALIGN_LEFT, text = 1), # index 0 is the MenuText,
356 ], True, "showOnDemand")
358 "fonts": [gFont("Regular", 22)],
363 <widget source="menu" render="Listbox" position="360,50" size="240,300" scrollbarMode="showNever" selectionDisabled="1">
364 <convert type="TemplatedMultiContent">
367 MultiContentEntryText(pos = (2, 2), size = (240, 300), flags = RT_HALIGN_CENTER|RT_VALIGN_CENTER|RT_WRAP, text = 2), # index 2 is the Description,
368 ], False, "showNever")
370 "fonts": [gFont("Regular", 22)],
375 <widget source="status" render="Label" position="5,360" zPosition="10" size="600,50" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
378 def __init__(self, session, destdir=None):
379 Screen.__init__(self, session)
380 #self.skin_path = plugin_path
383 self.box = HardwareInfo().get_device_name()
384 self.feed_base = "http://www.dreamboxupdate.com/opendreambox" #/1.5/%s/images/" % self.box
385 self.usbmountpoint = "/mnt/usb/"
389 self["menu"] = List(self.menulist)
390 self["key_red"] = StaticText(_("Close"))
391 self["key_green"] = StaticText()
392 self["key_yellow"] = StaticText()
393 self["key_blue"] = StaticText()
395 self["status"] = StaticText(_("Please wait... Loading list..."))
397 self["shortcuts"] = ActionMap(["OkCancelActions", "ColorActions", "ShortcutActions", "DirectionActions"],
402 "blue": self.keyBlue,
404 "upRepeated": self.keyUp,
405 "downRepeated": self.keyDown,
406 "down": self.keyDown,
407 "cancel": self.close,
409 self.onShown.append(self.go)
410 self.feedlists = [[],[],[]]
412 self.container = eConsoleAppContainer()
413 self.container.dataAvail.append(self.tool_avail)
416 self.nfofilename = ""
418 self.target_dir = None
420 def tool_avail(self, string):
421 print "[tool_avail]" + string
422 self.taskstring += string
425 self.onShown.remove(self.go)
426 self["menu"].index = 0
427 url = "http://www.dreamboxupdate.com/download/opendreambox/dreambox-nfiflasher-%s-md5sums" % self.box
428 client.getPage(url).addCallback(self.md5sums_finished).addErrback(self.feed_failed)
430 def md5sums_finished(self, data):
431 print "[md5sums_finished]", data
432 self.stickimage_md5 = data
436 if self.branch == START:
440 self["menu"].setList(self.menulist)
441 #elif self.branch == ALLIMAGES or self.branch == STICK_WIZARD:
445 self.session.open(NFOViewer, self.nfo)
448 print "[keyOk]", self["menu"].getCurrent()
449 current = self["menu"].getCurrent()
451 if self.branch == START:
452 currentEntry = current[0]
453 if currentEntry == RELEASE:
455 self.branch = RELEASE
456 self.askDestination()
457 elif currentEntry == EXPERIMENTAL:
459 self.branch = EXPERIMENTAL
460 self.askDestination()
461 elif currentEntry == ALLIMAGES:
462 self.branch = ALLIMAGES
464 elif currentEntry == STICK_WIZARD:
465 self.askStartWizard()
466 elif self.branch == ALLIMAGES:
467 self.image_idx = self["menu"].getIndex()
468 self.askDestination()
472 self["menu"].selectPrevious()
476 self["menu"].selectNext()
479 def updateButtons(self):
480 current = self["menu"].getCurrent()
482 if self.branch == START:
483 self["key_red"].text = _("Close")
484 currentEntry = current[0]
485 if currentEntry in (RELEASE, EXPERIMENTAL):
486 self.nfo_download(currentEntry, 0)
487 self["key_green"].text = _("Download")
489 self.nfofilename = ""
491 self["key_blue"].text = ""
492 self["key_green"].text = _("continue")
494 elif self.branch == ALLIMAGES:
495 self["key_red"].text = _("Back")
496 self["key_green"].text = _("Download")
497 self.nfo_download(ALLIMAGES, self["menu"].getIndex())
499 def listImages(self):
502 for name, url in self.feedlists[ALLIMAGES]:
503 imagelist.append((url, name, _("Download %s from Server" ) % url, None))
504 self["menu"].setList(imagelist)
506 def getUSBPartitions(self):
507 allpartitions = [ (r.description, r.mountpoint) for r in harddiskmanager.getMountedPartitions(onlyhotplug = True)]
508 print "[getUSBPartitions]", allpartitions
510 for x in allpartitions:
511 print x, x[1] == '/', x[0].find("USB"), access(x[1], R_OK)
512 if x[1] != '/' and x[0].find("USB") > -1: # and access(x[1], R_OK) is True:
513 usbpartition.append(x)
516 def askDestination(self):
517 usbpartition = self.getUSBPartitions()
518 if len(usbpartition) == 1:
519 self.target_dir = usbpartition[0][1]
520 self.ackDestinationDevice(device_description=usbpartition[0][0])
522 self.session.openWithCallback(self.DeviceBrowserClosed, DeviceBrowser, None, showDirectories=True, showMountpoints=True, inhibitMounts=["/autofs/sr0/"])
524 def DeviceBrowserClosed(self, path):
525 print "[DeviceBrowserClosed]", str(path)
526 self.target_dir = path
528 self.ackDestinationDevice()
532 def ackDestinationDevice(self, device_description=None):
533 if device_description == None:
534 dev = self.target_dir
536 dev = device_description
537 message = _("Do you want to download the image to %s ?") % (dev)
538 choices = [(_("Yes"), self.ackedDestination), (_("List of Storage Devices"),self.askDestination), (_("Cancel"),self.keyRed)]
539 self.session.openWithCallback(self.ackDestination_query, ChoiceBox, title=message, list=choices)
541 def ackDestination_query(self, choice):
542 print "[ackDestination_query]", choice
543 if isinstance(choice, tuple):
548 def ackedDestination(self):
549 print "[ackedDestination]", self.branch, self.target_dir, self.target_dir[8:]
550 self.container.setCWD("/mnt")
551 if self.target_dir[:8] == "/autofs/":
552 self.target_dir = "/dev/" + self.target_dir[8:-1]
554 if self.branch == STICK_WIZARD:
555 job = StickWizardJob(self.target_dir)
556 job.afterEvent = "close"
557 job_manager.AddJob(job)
558 job_manager.failed_jobs = []
559 self.session.openWithCallback(self.StickWizardCB, JobView, job, afterEventChangeable = False)
561 elif self.branch != STICK_WIZARD:
562 url = self.feedlists[self.branch][self.image_idx][1]
563 filename = self.feedlists[self.branch][self.image_idx][0]
564 print "[getImage] start downloading %s to %s" % (url, filename)
565 job = ImageDownloadJob(url, filename, self.target_dir, self.usbmountpoint)
566 job.afterEvent = "close"
567 job_manager.AddJob(job)
568 job_manager.failed_jobs = []
569 self.session.openWithCallback(self.ImageDownloadCB, JobView, job, afterEventChangeable = False)
571 def StickWizardCB(self, ret=None):
572 print "[StickWizardCB]", ret
573 print job_manager.active_jobs, job_manager.failed_jobs, job_manager.job_classes, job_manager.in_background, job_manager.active_job
574 if len(job_manager.failed_jobs) == 0:
575 self.session.open(MessageBox, _("The USB stick was prepared to be bootable.\nNow you can download an NFI image file!"), type = MessageBox.TYPE_INFO)
576 if len(self.feedlists[ALLIMAGES]) == 0:
583 def ImageDownloadCB(self, ret):
584 print "[ImageDownloadCB]", ret
585 print job_manager.active_jobs, job_manager.failed_jobs, job_manager.job_classes, job_manager.in_background, job_manager.active_job
586 if len(job_manager.failed_jobs) == 0:
587 self.session.open(MessageBox, _("To update your Dreambox firmware, please follow these steps:\n1) Turn off your box with the rear power switch and plug in the bootable USB stick.\n2) Turn mains back on and hold the DOWN button on the front panel pressed for 10 seconds.\n3) Wait for bootup and follow instructions of the wizard."), type = MessageBox.TYPE_INFO)
592 self.feedDownloader15 = feedDownloader(self.feed_base, self.box, OE_vers="1.5")
593 self.feedDownloader16 = feedDownloader(self.feed_base, self.box, OE_vers="1.6")
594 self.feedlists = [[],[],[]]
595 self.feedDownloader15.getList(self.gotFeed, self.feed_failed)
596 self.feedDownloader16.getList(self.gotFeed, self.feed_failed)
598 def feed_failed(self, message=""):
599 self["status"].text = _("Could not connect to Dreambox .NFI Image Feed Server:") + "\n" + str(message) + "\n" + _("Please check your network settings!")
601 def gotFeed(self, feedlist, OE_vers):
602 print "[gotFeed]", OE_vers
604 experimentallist = []
606 for name, url in feedlist:
607 if name.find("release") > -1:
608 releaselist.append((name, url))
609 if name.find("experimental") > -1:
610 experimentallist.append((name, url))
611 self.feedlists[ALLIMAGES].append((name, url))
614 self.feedlists[RELEASE] = releaselist + self.feedlists[RELEASE]
615 self.feedlists[EXPERIMENTAL] = experimentallist + self.feedlists[RELEASE]
616 elif OE_vers == "1.5":
617 self.feedlists[RELEASE] = self.feedlists[RELEASE] + releaselist
618 self.feedlists[EXPERIMENTAL] = self.feedlists[EXPERIMENTAL] + experimentallist
622 def checkUSBStick(self):
623 self.target_dir = None
624 allpartitions = [ (r.description, r.mountpoint) for r in harddiskmanager.getMountedPartitions(onlyhotplug = True)]
625 print "[checkUSBStick] found partitions:", allpartitions
627 for x in allpartitions:
628 print x, x[1] == '/', x[0].find("USB"), access(x[1], R_OK)
629 if x[1] != '/' and x[0].find("USB") > -1: # and access(x[1], R_OK) is True:
630 usbpartition.append(x)
633 if len(usbpartition) == 1:
634 self.target_dir = usbpartition[0][1]
635 self.md5_passback = self.getFeed
636 self.md5_failback = self.askStartWizard
637 self.md5verify(self.stickimage_md5, self.target_dir)
638 elif usbpartition == []:
639 print "[NFIFlash] needs to create usb flasher stick first!"
640 self.askStartWizard()
642 self.askStartWizard()
644 def askStartWizard(self):
645 self.branch = STICK_WIZARD
646 message = _("""This plugin creates a USB stick which can be used to update the firmware of your Dreambox in case it has no network connection or only WLAN access.
647 First, you need to prepare a USB stick so that it is bootable.
648 In the next step, an NFI image file can be downloaded from the update server and saved on the USB stick.
649 If you already have a prepared bootable USB stick, please insert it now. Otherwise plug in a USB stick with a minimum size of 64 MB!""")
650 self.session.openWithCallback(self.wizardDeviceBrowserClosed, DeviceBrowser, None, message, showDirectories=True, showMountpoints=True, inhibitMounts=["/","/autofs/sr0/","/autofs/sda1/","/media/hdd/","/media/net/","/media/usb/","/media/dvd/"])
652 def wizardDeviceBrowserClosed(self, path):
653 print "[wizardDeviceBrowserClosed]", path
654 self.target_dir = path
656 self.md5_passback = self.getFeed
657 self.md5_failback = self.wizardQuery
658 self.md5verify(self.stickimage_md5, self.target_dir)
662 def wizardQuery(self):
663 print "[wizardQuery]"
664 description = self.target_dir
665 for name, dev in self.getUSBPartitions():
666 if dev == self.target_dir:
668 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.") + "\n"
669 message += _("The following device was found:\n\n%s\n\nDo you want to write the USB flasher to this stick?") % description
670 choices = [(_("Yes"), self.ackedDestination), (_("List of Storage Devices"),self.askStartWizard), (_("Cancel"),self.close)]
671 self.session.openWithCallback(self.ackDestination_query, ChoiceBox, title=message, list=choices)
676 latest_release = "Release %s (Opendreambox 1.5)" % self.feedlists[RELEASE][0][0][-9:-4]
677 self.menulist.append((RELEASE, _("Get latest release image"), _("Download %s from Server" ) % latest_release, None))
682 dat = self.feedlists[EXPERIMENTAL][0][0][-12:-4]
683 latest_experimental = "Experimental %s-%s-%s (Opendreambox 1.6)" % (dat[:4], dat[4:6], dat[6:])
684 self.menulist.append((EXPERIMENTAL, _("Get latest experimental image"), _("Download %s from Server") % latest_experimental, None))
688 self.menulist.append((ALLIMAGES, _("Choose image to download"), _("Select desired image from feed list" ), None))
689 self.menulist.append((STICK_WIZARD, _("USB stick wizard"), _("Prepare another USB stick for image flashing" ), None))
690 self["menu"].setList(self.menulist)
691 self["status"].text = _("Currently installed image") + ": %s" % (about.getImageVersionString())
695 def nfo_download(self, branch, idx):
696 nfourl = (self.feedlists[branch][idx][1])[:-4]+".nfo"
697 self.nfofilename = (self.feedlists[branch][idx][0])[:-4]+".nfo"
698 print "[check_for_NFO]", nfourl
699 client.getPage(nfourl).addCallback(self.nfo_finished).addErrback(self.nfo_failed)
701 def nfo_failed(self, failure_instance):
702 print "[nfo_failed] " + str(failure_instance)
703 self["key_blue"].text = ""
704 self.nfofilename = ""
707 def nfo_finished(self,nfodata=""):
708 print "[nfo_finished] " + str(nfodata)
709 self["key_blue"].text = _("Changelog viewer")
712 def md5verify(self, md5, path):
714 print "[verify_md5]", md5, path, cmd
715 self.container.setCWD(path)
716 self.container.appClosed.append(self.md5finished)
717 self.container.execute(cmd)
718 self.container.write(md5)
719 self.container.dataSent.append(self.md5ready)
721 def md5ready(self, retval):
722 self.container.sendEOF()
724 def md5finished(self, retval):
725 print "[md5finished]", str(retval)
726 self.container.appClosed.remove(self.md5finished)
727 self.container.dataSent.remove(self.md5ready)
729 print "check passed! calling", repr(self.md5_passback)
732 print "check failed! calling", repr(self.md5_failback)
735 def main(session, **kwargs):
736 session.open(NFIDownload,"/home/root")
738 def filescan_open(list, session, **kwargs):
739 dev = "/dev/" + (list[0].path).rsplit('/',1)[0][7:]
740 print "mounting device " + dev + " to /mnt/usb..."
741 system("mount "+dev+" /mnt/usb/ -o rw,sync")
742 session.open(NFIDownload,"/mnt/usb/")
744 def filescan(**kwargs):
745 from Components.Scanner import Scanner, ScanPath
747 Scanner(mimetypes = ["application/x-dream-image"],
750 ScanPath(path = "", with_subdirs = False),
753 description = (_("Download .NFI-Files for USB-Flasher")+"..."),
754 openfnc = filescan_open, )