fix downloading image to flash or harddrive (#480)
[vuplus_dvbapp] / lib / python / Plugins / SystemPlugins / NFIFlash / downloader.py
index 79fa069..2c8b45d 100644 (file)
@@ -16,7 +16,7 @@ from Components.MultiContent import MultiContentEntryText
 from Components.ScrollLabel import ScrollLabel
 from Components.Harddisk import harddiskmanager
 from Components.Task import Task, Job, job_manager, Condition
-from Tools.Directories import fileExists
+from Tools.Directories import fileExists, isMount
 from Tools.HardwareInfo import HardwareInfo
 from Tools.Downloader import downloadWithProgress
 from enigma import eConsoleAppContainer, gFont, RT_HALIGN_LEFT, RT_HALIGN_CENTER, RT_VALIGN_CENTER, RT_WRAP, eTimer
@@ -30,6 +30,8 @@ class ImageDownloadJob(Job):
        def __init__(self, url, filename, device=None, mountpoint="/"):
                Job.__init__(self, _("Download .NFI-Files for USB-Flasher"))
                if device:
+                       if isMount(mountpoint):
+                               UmountTask(self, mountpoint)
                        MountTask(self, device, mountpoint)
                ImageDownloadTask(self, url, mountpoint+filename)
                ImageDownloadTask(self, url[:-4]+".nfo", mountpoint+filename[:-4]+".nfo")
@@ -44,7 +46,9 @@ class MountTask(Task):
        def __init__(self, job, device, mountpoint):
                Task.__init__(self, job, ("mount"))
                self.setTool("mount")
-               self.args += [device, mountpoint, "-orw,sync"]
+               options = "rw,sync"
+               self.mountpoint = mountpoint
+               self.args += [ device, mountpoint, "-o"+options ]
                self.weighting = 1
 
        def processOutput(self, data):
@@ -74,7 +78,9 @@ class ImageDownloadTask(Task):
                self.error_message = ""
                self.last_recvbytes = 0
                self.error_message = None
-               
+               self.download = None
+               self.aborted = False
+
        def run(self, callback):
                self.callback = callback
                self.download = downloadWithProgress(self.url,self.path)
@@ -82,23 +88,30 @@ class ImageDownloadTask(Task):
                self.download.start().addCallback(self.download_finished).addErrback(self.download_failed)
                print "[ImageDownloadTask] downloading", self.url, "to", self.path
 
+       def abort(self):
+               print "[ImageDownloadTask] aborting", self.url
+               if self.download:
+                       self.download.stop()
+               self.aborted = True
+
        def download_progress(self, recvbytes, totalbytes):
                #print "[update_progress] recvbytes=%d, totalbytes=%d" % (recvbytes, totalbytes)
                if ( recvbytes - self.last_recvbytes  ) > 10000: # anti-flicker
                        self.progress = int(100*(float(recvbytes)/float(totalbytes)))
                        self.name = _("Downloading") + ' ' + "%d of %d kBytes" % (recvbytes/1024, totalbytes/1024)
                        self.last_recvbytes = recvbytes
-               
+
        def download_failed(self, failure_instance=None, error_message=""):
                self.error_message = error_message
                if error_message == "" and failure_instance is not None:
                        self.error_message = failure_instance.getErrorMessage()
-               print "[download_failed]", self.error_message
                Task.processFinished(self, 1)
-               
+
        def download_finished(self, string=""):
-               print "[download_finished]", string
-               Task.processFinished(self, 0)
+               if self.aborted:
+                       self.finish(aborted = True)
+               else:
+                       Task.processFinished(self, 0)
 
 class StickWizardJob(Job):
        def __init__(self, path):
@@ -164,7 +177,7 @@ class UnpackTask(Task):
        
        def run(self, callback):
                Task.run(self, callback)
-               self.delayTimer.start(1000, False)
+               self.delayTimer.start(950, False)
                
        def progress_increment(self):
                self.progress += 1
@@ -419,7 +432,10 @@ class NFIDownload(Screen):
 
        def go(self):
                self.onShown.remove(self.go)
-               self["menu"].index = 0
+               self.umountCallback = self.getMD5
+               self.umount()
+       
+       def getMD5(self):
                url = "http://www.dreamboxupdate.com/download/opendreambox/dreambox-nfiflasher-%s-md5sums" % self.box
                client.getPage(url).addCallback(self.md5sums_finished).addErrback(self.feed_failed)
 
@@ -495,8 +511,16 @@ class NFIDownload(Screen):
        def listImages(self):
                print "[listImages]"
                imagelist = []
+               mask = re.compile("%s/(?P<OE_vers>1\.\d)/%s/images/(?P<branch>.*?)-%s_(?P<version>.*?).nfi" % (self.feed_base, self.box, self.box), re.DOTALL)
                for name, url in self.feedlists[ALLIMAGES]:
-                       imagelist.append((url, name, _("Download %s from Server" ) % url, None))
+                       result = mask.match(url)
+                       if result:
+                               if result.group("version").startswith("20"):
+                                       version = ( result.group("version")[:4]+'-'+result.group("version")[4:6]+'-'+result.group("version")[6:8] )
+                               else:
+                                       version = result.group("version")
+                               description = "\nOpendreambox %s\n%s image\n%s\n" % (result.group("OE_vers"), result.group("branch"), version)
+                               imagelist.append((url, name, _("Download %s from Server" ) % description, None))
                self["menu"].setList(imagelist)
        
        def getUSBPartitions(self):
@@ -515,7 +539,10 @@ class NFIDownload(Screen):
                        self.target_dir = usbpartition[0][1]
                        self.ackDestinationDevice(device_description=usbpartition[0][0])
                else:
-                       self.session.openWithCallback(self.DeviceBrowserClosed, DeviceBrowser, None, showDirectories=True, showMountpoints=True, inhibitMounts=["/autofs/sr0/"])
+                       self.openDeviceBrowser()
+       
+       def openDeviceBrowser(self):
+               self.session.openWithCallback(self.DeviceBrowserClosed, DeviceBrowser, None, showDirectories=True, showMountpoints=True, inhibitMounts=["/autofs/sr0/"])
 
        def DeviceBrowserClosed(self, path):
                print "[DeviceBrowserClosed]", str(path)
@@ -531,7 +558,7 @@ class NFIDownload(Screen):
                else:
                        dev = device_description
                message = _("Do you want to download the image to %s ?") % (dev)
-               choices = [(_("Yes"), self.ackedDestination), (_("List of Storage Devices"),self.askDestination), (_("Cancel"),self.keyRed)]
+               choices = [(_("Yes"), self.ackedDestination), (_("List of Storage Devices"),self.openDeviceBrowser), (_("Cancel"),self.keyRed)]
                self.session.openWithCallback(self.ackDestination_query, ChoiceBox, title=message, list=choices)
 
        def ackDestination_query(self, choice):
@@ -542,35 +569,52 @@ class NFIDownload(Screen):
                        self.keyRed()
 
        def ackedDestination(self):
-               print "[ackedDestination]", self.branch, self.target_dir, self.target_dir[8:]
+               print "[ackedDestination]", self.branch, self.target_dir
                self.container.setCWD("/mnt")
                if self.target_dir[:8] == "/autofs/":
                        self.target_dir = "/dev/" + self.target_dir[8:-1]
 
-                       if self.branch == STICK_WIZARD:
-                               job = StickWizardJob(self.target_dir)
-                               job_manager.AddJob(job)
-                               self.session.openWithCallback(self.StickWizardCB, JobView, job)
-
-                       elif self.branch != STICK_WIZARD:
-                               url = self.feedlists[self.branch][self.image_idx][1]
-                               filename = self.feedlists[self.branch][self.image_idx][0]
-                               print "[getImage] start downloading %s to %s" % (url, path)
+               if self.branch == STICK_WIZARD:
+                       job = StickWizardJob(self.target_dir)
+                       job.afterEvent = "close"
+                       job_manager.AddJob(job)
+                       job_manager.failed_jobs = []
+                       self.session.openWithCallback(self.StickWizardCB, JobView, job, afterEventChangeable = False)
+
+               elif self.branch != STICK_WIZARD:
+                       url = self.feedlists[self.branch][self.image_idx][1]
+                       filename = self.feedlists[self.branch][self.image_idx][0]
+                       print "[getImage] start downloading %s to %s" % (url, filename)
+                       if self.target_dir.startswith("/dev/"):
                                job = ImageDownloadJob(url, filename, self.target_dir, self.usbmountpoint)
-                               job_manager.AddJob(job)
-                               self.session.openWithCallback(self.ImageDownloadCB, JobView, job)
+                       else:
+                               job = ImageDownloadJob(url, filename, None, self.target_dir)
+                       job.afterEvent = "close"
+                       job_manager.AddJob(job)
+                       job_manager.failed_jobs = []
+                       self.session.openWithCallback(self.ImageDownloadCB, JobView, job, afterEventChangeable = False)
 
        def StickWizardCB(self, ret=None):
-               self.session.open(MessageBox, _("The USB stick was prepared to be bootable.\nNow you can download an NFI image file!"), type = MessageBox.TYPE_INFO)
                print "[StickWizardCB]", ret
-               if len(self.feedlists[ALLIMAGES]) == 0:
-                       self.getFeed()
+#              print job_manager.active_jobs, job_manager.failed_jobs, job_manager.job_classes, job_manager.in_background, job_manager.active_job
+               if len(job_manager.failed_jobs) == 0:
+                       self.session.open(MessageBox, _("The USB stick was prepared to be bootable.\nNow you can download an NFI image file!"), type = MessageBox.TYPE_INFO)
+                       if len(self.feedlists[ALLIMAGES]) == 0:
+                               self.getFeed()
+                       else:
+                               self.setMenu()
                else:
-                       self.setMenu()
+                       self.umountCallback = self.checkUSBStick
+                       self.umount()
 
        def ImageDownloadCB(self, ret):
                print "[ImageDownloadCB]", ret
-               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)
+#              print job_manager.active_jobs, job_manager.failed_jobs, job_manager.job_classes, job_manager.in_background, job_manager.active_job
+               if len(job_manager.failed_jobs) == 0:
+                       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)
+               else:
+                       self.umountCallback = self.keyRed
+                       self.umount()
 
        def getFeed(self):
                self.feedDownloader15 = feedDownloader(self.feed_base, self.box, OE_vers="1.5")
@@ -631,7 +675,7 @@ class NFIDownload(Screen):
 First, you need to prepare a USB stick so that it is bootable.
 In the next step, an NFI image file can be downloaded from the update server and saved on the USB stick.
 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!""")
-               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/"])
+               self.session.openWithCallback(self.wizardDeviceBrowserClosed, DeviceBrowser, None, message, showDirectories=True, showMountpoints=True, inhibitMounts=["/","/autofs/sr0/","/autofs/sda1/","/media/hdd/","/media/net/",self.usbmountpoint,"/media/dvd/"])
 
        def wizardDeviceBrowserClosed(self, path):
                print "[wizardDeviceBrowserClosed]", path
@@ -716,6 +760,18 @@ If you already have a prepared bootable USB stick, please insert it now. Otherwi
                        print "check failed! calling", repr(self.md5_failback)
                        self.md5_failback()
 
+       def umount(self):
+               cmd = "umount " + self.usbmountpoint
+               print "[umount]", cmd
+               self.container.setCWD('/')
+               self.container.appClosed.append(self.umountFinished)
+               self.container.execute(cmd)
+
+       def umountFinished(self, retval):
+               print "[umountFinished]", str(retval)
+               self.container.appClosed.remove(self.umountFinished)
+               self.umountCallback()
+
 def main(session, **kwargs):
        session.open(NFIDownload,"/home/root")