Commits

Damián Nohales committed 95014da

Rethinked the DownloadList updates to improve stability and performance.

  • Participants
  • Parent commits 2c8c008

Comments (0)

Files changed (4)

File lib/DownloadList.py

     def __init__(self, view):
         self.__gobject_init__()
         AbstractSongList.__init__(self, view)
-        self._downcount_semaphore = threading.Semaphore()
-        self._remove_semaphore = threading.Semaphore()
         self.downloads_count = 0
+        
+        gobject.timeout_add(300, self.on_timeout)
     
     def create_model(self):
         # Song, File Name, SongID, Progress, Size, Icon info stock
             "",
             "gtk-network"
         ])
-        
-        song.connect("download-initializing", self.on_download_initializing)
-        song.connect("download-started", self.on_download_started)
-        song.connect("download-updated", self.on_download_updated)
-        song.connect("download-completed", self.on_download_completed)
-        song.connect("download-paused", self.on_download_paused)
-        song.connect("download-canceled", self.on_download_canceled)
-        song.connect("download-error", self.on_download_error)
-    
+            
     def append_song(self, song):
         """
         Append song for download, if file exists, tries to continue the download
         column = gtk.TreeViewColumn(_("Size"), gtk.CellRendererText(), text = 4)
         column.set_resizable(True)
         self.get_view().append_column(column)
-    
-    def on_download_initializing(self, song):
-        print "[Download initializing]", song.get_id()
-        self.get_song_row(song)[5] = "gtk-network"
         
-        self.emit_download_changed()
-    
-    def on_download_started(self, song):
-        print "[Download started]", song.get_id()
-    
-    def on_download_updated(self, song):
-        self._remove_semaphore.acquire();
-        row = self.get_song_row(song)
-        if row == None:
-            return
+    def on_timeout(self):
+        downcount = 0
         
-        row[3] = song.get_download_progress()
-        row[4] = "%.02f MB" % (song.get_file_size() / (1024 ** 2))
-        row[5] = "gtk-go-down"
-        self._remove_semaphore.release();
-    
-    def on_download_completed(self, song):
-        print "[Download completed]", song.get_id()
-        row = self.get_song_row(song)
-        
-        row[3] = 100
-        row[5] = "gtk-ok"
-        
-        self.emit_download_changed()
-        
-    def on_download_paused(self, song):
-        print "[Download paused]", song.get_id()
-        row = self.get_song_row(song)
-        
-        row[3] = 0
-        row[5] = "gtk-media-stop"
-        
-        self.emit_download_changed()
-        
-    def on_download_canceled(self, song):
-        self._remove_semaphore.acquire()
-        print "[Download canceled]", song.get_id()
-        try:
-            self.get_model().remove(self.get_song_iter(song))
-        except:
-            pass
-        self._remove_semaphore.release()
-        
-        self.emit_download_changed()
-    
-    def on_download_error(self, song, msg):
-        print "[Download error]", song.get_id(), ":", msg
-        self.get_song_row(song)[5] = "gtk-dialog-error"
-        
-        self.emit_download_changed()
-        
-    def emit_download_changed(self):
-        self._downcount_semaphore.acquire()
-        
-        self.emit("downloads-changed")
-        
-        self._downcount_semaphore.release()
+        for i in reversed(self.range()):
+            row = self.get_model()[i]
+            song = self.get_song(i)
+            if song.get_state() == Song.STATE_NOT_STARTED or song.get_state() == Song.STATE_CONNECTING:
+                row[5] = "gtk-network"
+                downcount += 1
+            elif song.get_state() == Song.STATE_DOWNLOADING:
+                row[3] = song.get_download_progress()
+                row[4] = "%.02f MB" % (song.get_file_size() / (1024 ** 2))
+                row[5] = "gtk-go-down"
+                downcount += 1
+            elif song.get_state() == Song.STATE_COMPLETED:
+                row[3] = 100
+                row[5] = "gtk-ok"
+            elif song.get_state() == Song.STATE_PAUSED:
+                row[3] = 0
+                row[5] = "gtk-media-stop"
+            elif song.get_state() == Song.STATE_CANCELED:
+                self.get_model().remove(self.get_model().get_iter((i,)))
+            elif song.get_state() == Song.STATE_ERROR:
+                row[5] = "gtk-dialog-error"
+                
+        if downcount != self.downloads_count:
+            self.downloads_count = downcount
+            self.emit("downloads-changed", downcount)
+            
+        return True
         
     def stop_all_downloads(self):
         """
 
 gobject.type_register(DownloadList)
 # Emitted when the cover download was finished
-gobject.signal_new("downloads-changed", DownloadList, gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ())
+gobject.signal_new("downloads-changed", DownloadList, gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_INT,))

File lib/SharkDown.py

         self.downloads_count = builder.get_object('downloads_count')
         self.downloads_expander = builder.get_object('expander_download')
         self.downmenu = builder.get_object('downloadmenu')
-        self.on_downloads_changed(self.downloads)
+        self.on_downloads_changed(self.downloads, 0)
         
         # Song lists initialization
         if os.path.exists("%s/.gsharkdown/playlist.pkl" % os.environ.get("HOME")):
                 song.set_filename(filename)
                 self.downloads.append_song_restarting(song)
 
-    def on_downloads_changed(self, widget, data = None):
+    def on_downloads_changed(self, widget, count):
         """
         Update the label wich indicates the downloads count.
         """
-        count = 0
-        iter = self.downloads.first()
-        while iter != None:
-            if self.downloads.get_song(iter).state == Song.STATE_DOWNLOADING:
-                count += 1
-            iter = self.downloads.next(iter)
         text = ngettext("Downloading %d file", "Downloading %d files", count) % count
         self.downloads_count.set_label(text)
 
     }
     """
     STATE_NOT_STARTED = 0
-    STATE_CANCELED = 1
-    STATE_PAUSED = 2
-    STATE_DOWNLOADING = 3
-    STATE_COMPLETED = 4
-    STATE_ERROR = 5
+    STATE_CONNECTING = 1
+    STATE_DOWNLOADING = 2
+    STATE_COMPLETED = 3
+    STATE_PAUSED = 4
+    STATE_CANCELED = 5
+    STATE_ERROR = 6
     last_song_local_id = 0
     
     def __init__(self, data):
         self.filename = None
         self.state = Song.STATE_NOT_STARTED
         self.download_thread = None
+        self.last_error = None
         
         try:
             self.filename = self.data["filename"]
             self.set_cover_missed_pixbuf()
             
         self.connect("download-initializing", self.on_download_initializing)
+        self.connect("download-started", self.on_download_started)
         self.connect("download-paused", self.on_download_paused)
         self.connect("download-canceled", self.on_download_canceled)
         self.connect("download-completed", self.on_download_completed)
         self.connect("download-error", self.on_download_error)
     
     def on_download_initializing(self, song):
+        print "[Download connecting]", self.get_id()
+        self.state = Song.STATE_CONNECTING
+    
+    def on_download_started(self, song):
+        print "[Download started]", self.get_id()
         self.state = Song.STATE_DOWNLOADING
-        
+    
     def on_download_paused(self, song):
+        print "[Download paused]", self.get_id()
         self.state = Song.STATE_PAUSED
         
     def on_download_canceled(self, song):
+        print "[Download canceled]", self.get_id()
         self.state = Song.STATE_CANCELED
         
     def on_download_completed(self, song):
+        print "[Download completed]", self.get_id()
         self.state = Song.STATE_COMPLETED
         
-    def on_download_error(self, song):
+    def on_download_error(self, song, error):
+        print "[Download error]", self.get_id(), error
         self.state = Song.STATE_ERROR
+        self.last_error = error
     
     def __getitem__(self, key):
         """
     def get_data(self):
         return self.data
     
+    def get_state(self):
+        return self.state
+    
     def get_id(self):
         return self.data['SongID']
         
         
         return "%02d:%02d" % (mins, secs)
     
+    def get_last_error(self):
+        return self.last_error
+    
     def get_cover_filename(self):
         return self.data['CoverArtFilename']
     

File lib/tfuncs.py

                     self.app.result.append_song(Song(song_data))
         except Exception, e:
             print e.args
-        
-        self.__stop()
 
 
 class UpdateThread(threading.Thread):