Commits

Damián Nohales committed 2716acd

Implementation of downloads using pycurl and download cancellation.

  • Participants
  • Parent commits e1ff20b

Comments (0)

Files changed (2)

File gsharkdown.py

         self.entry.set_completion(completition)
         
         # Results List definition
+        # Model: Title, Artist, Album, SongID, Song Array
         self.result = gtk.ListStore(str, str, str, str, object)
         self.result_view = builder.get_object('list_results')
         self.result_view.set_model(self.result)
         self._create_search_columns()
 
         # Play List definition
+        # Model: Title, Artist, SongID, Song Array, Font Weight (bold on playing)
         self.playlist = gtk.ListStore(str, str, str, object, int)
         self.play_view = builder.get_object('list_playlist')
         self.play_view.set_model(self.playlist)
         self.selector = self.play_view.get_selection()
         
         # Download list definition
-        self.downloads = gtk.ListStore(str, str, int, str)
+        # Model: File Name, SongID, Progress, Size, Thread Object
+        self.downloads = gtk.ListStore(str, str, int, str, object)
         self.downloads_view = builder.get_object('list_downloads')
         self.downloads_view.set_model(self.downloads)
         self.downloads_view.hide_all()
         builder.connect_signals(self)
         self.tlisten = t_key_listener(self)
         self.tlisten.start()
-        self.check_for_update(None)
+        #self.check_for_update(None)
         self.window.show_all()
         self.hide_download_list()
         
                                     song["SongName"].strip("<>:\"/\|?*"))
             if CONFIG['down_path'] == "":
                 CONFIG['down_path'] = os.environ.get("HOME") + "/Music"
-            self.downqueue[filename] = t_download(self, song, filename, CONFIG['down_path'])
-            self.downqueue[filename].start()
+            tDownload = t_download(self, song, filename, CONFIG['down_path'])
+            tDownload.start()
             
     def update_downloads_count(self):
         """
             else:
                 self.downmenu.popup(None, None, None, event.button, event.time)
                 print "Selected one row!"
-
+    
+    def cancel_download(self, path):
+        """
+        Cancel a download by a list path
+        """
+        thread = self.downloads[path[0]][4]
+        thread.stop()
+        # TODO: Should improve the busy waiting
+        while(thread.is_alive()):
+            pass
+    
     def on_cancel_download(self, menu, data=None):
         """
-        Cancle the download. Have to check how to cancle the thread.
+        Cancel the download. Have to check how to cancel the thread.
         """
-        selection = self.downloads_view.get_selection()
-        rows, paths = selection.get_selected_rows()
-        for i in range(selection.count_selected_rows()):
-            self.downqueue[rows[i][0]].stop()
-            self.downloads.remove(self.downloads.get_iter(paths[i]))
+        select = self.downloads_view.get_selection().get_selected_rows()
+        for path in select[1]:
+            self.cancel_download(path)
 
     def toggle_download_list(self, param):
         if self.downloads_view.get_visible():

File lib/tfuncs.py

 from urllib import urlretrieve
 import threading
 import groove
+
 try:
     import pygst
     pygst.require('0.10')
     print "You don't have python-gstreamer installed!"
     sys.exit(0)
 
+try:
+    import pycurl
+except:
+    print "You don't have python-pycurl installed!"
+    sys.exit(0)
+
 basepath = os.path.abspath(os.path.dirname(sys.argv[0]).strip("/lib"))
 
 
         threading.Thread.__init__(self)
         self.win = _window
         self.filename = _filename
+        self.song = _song
         self.songid = _song["SongID"]
         self.path = _path
         self.duration = float(_song["EstimateDuration"])
-        self.iter = self.win.downloads.append([self.filename, self.songid, 0, ""])
+        self.iter = self.win.downloads.append([self.filename, self.songid, 0, "", self])
         self.win.update_downloads_count()
         self._stop = threading.Event()
 
             key = groove.getStreamKeyFromSongIDEx(self.songid)
         except Exception, e:
             print e
+            return
+        
         try:
-            self.t = time.time()
-            self.beg = self.t
-            self.lastCount = 0
-            urlretrieve("http://" + key["result"]["%s" % self.songid]["ip"] + "/stream.php",
-                       os.path.join(self.path, self.filename),
-                       self.hook,
-                        "streamKey=" + key["result"]["%s" % self.songid]["streamKey"])
+            full_path_name = os.path.join(self.path, self.filename);
+            file = open(full_path_name, "w")
+        except IOError:
+            self.win.show_error(_("Failed to create '%s' for writing.") % full_path_name)
+            return
+        
+        try:
+            url = "http://" + key["result"]["%s" % self.songid]["ip"] + "/stream.php"
+            url = str(url)
+            c = pycurl.Curl()
+            c.setopt(pycurl.URL, url)
+            c.setopt(pycurl.NOPROGRESS, 0)
+            c.setopt(pycurl.PROGRESSFUNCTION, self.hook)
+            c.setopt(pycurl.FAILONERROR, True)
+            c.setopt(pycurl.FILE, file)
+            c.setopt(pycurl.POST, True)
+            c.setopt(pycurl.POSTFIELDS, str("streamKey=" + key["result"]["%s" % self.songid]["streamKey"]))
+            c.perform()
+        except pycurl.error, e:
+            os.remove(full_path_name)
+            print e.args
         except Exception, e:
+            os.remove(full_path_name)
             print e.args
+            
+        self._remove_download()
+        file.close()
 
     def stop(self):
         # TODO: This one should be checked how to resolve, at the moment
         # stopping the thread terminates the program
         self._stop.set()
-        os.remove(os.path.join(self.path, self.filename))
         print "Stopping Thread"
 
     def stopped(self):
         return self._stop.isSet()
 
-    def hook(self, countBlocks, Block, TotalSize):
-        if self.iter != None:
-            progress = (float(countBlocks * Block) / float(TotalSize)) * 100
+    def hook(self, downloadTotal, downloadCurrent, uploadTotal, uploadCurrent):
+        if self.iter != None and downloadTotal > 0:
+            progress = (downloadCurrent / downloadTotal) * 100
 
             if progress < 99:
                 mb = 1024 ** 2
                 self.set_value(2, progress)
-                self.set_value(3, "%.02f MB" % (float(TotalSize) / mb))
+                self.set_value(3, "%.02f MB" % (downloadTotal / mb))
             else:
-                self.win.downloads.remove(self.iter)
-                self.iter = None
-                self.win.update_downloads_count()
-            
+                self._remove_download()
+                
+        if self._stop.isSet():
+            return True
+        else:
+            return False
+       
+    def _remove_download(self):
+        self.win.downloads.remove(self.iter)
+        self.iter = None
+        self.win.update_downloads_count()
+        
     def set_value(self, column, value):
         try:
             self.win.downloads.set_value(self.iter, column, value)