Commits

Damián Nohales  committed b1cfd0c

Support for download pausing and Song.get_streaming_url method added

  • Participants
  • Parent commits b95c4de

Comments (0)

Files changed (4)

File data/main_window.ui

     <property name="visible">True</property>
     <property name="can_focus">False</property>
     <child>
-      <object class="GtkImageMenuItem" id="menuitem2">
-        <property name="label">gtk-cancel</property>
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="use_action_appearance">False</property>
-        <property name="use_underline">True</property>
-        <property name="use_stock">True</property>
-        <signal name="activate" handler="on_cancel_download" swapped="no"/>
-      </object>
-    </child>
-    <child>
       <object class="GtkImageMenuItem" id="menuitem3">
-        <property name="label">gtk-media-stop</property>
+        <property name="label">gtk-media-pause</property>
         <property name="visible">True</property>
         <property name="can_focus">False</property>
         <property name="use_action_appearance">False</property>
         <signal name="activate" handler="on_resume_download" swapped="no"/>
       </object>
     </child>
+    <child>
+      <object class="GtkImageMenuItem" id="menuitem2">
+        <property name="label">gtk-cancel</property>
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="use_action_appearance">False</property>
+        <property name="use_underline">True</property>
+        <property name="use_stock">True</property>
+        <signal name="activate" handler="on_cancel_download" swapped="no"/>
+      </object>
+    </child>
   </object>
   <object class="GtkImage" id="image1">
     <property name="visible">True</property>
     <property name="can_focus">False</property>
     <property name="stock">gtk-open</property>
   </object>
+  <object class="GtkImage" id="image_pause_download">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="stock">gtk-media-pause</property>
+  </object>
   <object class="GtkImage" id="image_playlist_back">
     <property name="visible">True</property>
     <property name="can_focus">False</property>
     <property name="can_focus">False</property>
     <property name="stock">gtk-save-as</property>
   </object>
-  <object class="GtkImage" id="image_stop_download">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="stock">gtk-media-stop</property>
-  </object>
   <object class="GtkImage" id="image_toolbar_playlist">
     <property name="visible">True</property>
     <property name="can_focus">False</property>
                         </child>
                         <child>
                           <object class="GtkButton" id="button3">
-                            <property name="label" translatable="yes">Stop all</property>
+                            <property name="label" translatable="yes">Pause all</property>
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
                             <property name="receives_default">True</property>
                             <property name="tooltip_text" translatable="yes">Stops all downloads</property>
                             <property name="use_action_appearance">False</property>
-                            <property name="image">image_stop_download</property>
+                            <property name="image">image_pause_download</property>
                             <signal name="clicked" handler="on_stop_all_downloads" swapped="no"/>
                           </object>
                           <packing>

File lib/DownloadList.py

         gobject.timeout_add(300, self.on_timeout)
     
     def create_model(self):
-        # Song, File Name, SongID, Progress, Size, Icon info stock
+        # Song, File Name, Speed, Progress, Size, Icon info stock
         return gtk.ListStore(object, str, str, int, str, str)
     
     def __append_song_to_model(self, song):
         self.get_model().append([
             song,
             unicode(os.path.basename(song.get_filename()), errors = 'replace'),
-            song.get_id(),
+            "",
             0,
             "",
             "gtk-network"
         column.set_resizable(True)
         self.get_view().append_column(column)
 
-        column = gtk.TreeViewColumn(_("SongID"), gtk.CellRendererText(), text = 2)
+        column = gtk.TreeViewColumn(_("Speed"), gtk.CellRendererText(), text = 2)
         column.set_resizable(True)
         self.get_view().append_column(column)
-
-        column = gtk.TreeViewColumn(_("Download progress"), gtk.CellRendererProgress(), value = 3)
+        
+        column = gtk.TreeViewColumn(_("Size"), gtk.CellRendererText(), text = 4)
         column.set_resizable(True)
         self.get_view().append_column(column)
-
-        column = gtk.TreeViewColumn(_("Size"), gtk.CellRendererText(), text = 4)
+        
+        column = gtk.TreeViewColumn(_("Download progress"), gtk.CellRendererProgress(), value = 3)
         column.set_resizable(True)
         self.get_view().append_column(column)
         
             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[2] = ""
                 row[5] = "gtk-network"
                 downcount += 1
             elif song.get_state() == Song.STATE_DOWNLOADING:
+                if song.get_download_speed() == None:
+                    row[2] = "N/A"
+                else:
+                    row[2] = "%d kB/s" % (song.get_download_speed() / 1024)
                 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[2] = ""
                 row[3] = 100
                 row[5] = "gtk-ok"
             elif song.get_state() == Song.STATE_PAUSED:
-                row[3] = 0
-                row[5] = "gtk-media-stop"
+                row[2] = ""
+                row[5] = "gtk-media-pause"
             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[2] = ""
                 row[5] = "gtk-dialog-error"
                 
         if downcount != self.downloads_count:
         self.local_id = Song.last_song_local_id
         self.data = data
         self.cover_pixbuf = None
-        self.download_progress = None
-        self.file_size = None
         self.filename = None
         self.state = Song.STATE_NOT_STARTED
         self.download_thread = None
         gured in the app.
         """
         if speed == None:
-            speed = int(config()["speed_limit"])
+            speed = int(config()["speed_limit"]) * 1024
         
         self.download_thread = DownloadThread(self)
         self.download_thread.restart = restart
         Returns the current download progress in bytes or None if
         the download is not initialized.
         """
-        return self.download_progress
-
-    def set_download_progress(self, value):
-        self.download_progress = value
+        if self.download_thread != None:
+            return self.download_thread.download_progress
+        else:
+            return None
 
     def get_file_size(self):
         """
         Returns the current file size in bytes or None if
         the download is not initialized.
         """
-        return self.file_size
-
-    def set_file_size(self, value):
-        self.file_size = value
+        if self.download_thread != None:
+            return self.download_thread.file_size
+        else:
+            return None
+    
+    def get_download_speed(self):
+        """
+        Returns the current download speed in bytes per second
+        the download is not initialized.
+        """
+        if self.download_thread != None:
+            return self.download_thread.download_speed
+        else:
+            return None
     
     def get_filename(self):
         return self.filename
         filename = os.path.join(config()['down_path'], filename)
         
         return filename
+    
+    def get_streaming_url(self):
+        try:
+            key = groove.getStreamKeyFromSongIDEx(self.get_id())
+        except Exception, e:
+            print "[Streaming URL error]", e.__str__()
+            raise e
+        
+        playurls = "http://%s/stream.php?streamKey=%s"
+        play_url = playurls % (key["result"]["%s" % self.get_id()]["ip"],
+                               key["result"]["%s" % self.get_id()]["streamKey"])
+        
+        return str(play_url)
 
 gobject.type_register(Song)
 """
         self.song = song
         self.restart = False
         self.speed = 0
+        self.download_progress = None
+        
+        self.download_speed = None
+        self.download_time_start = None
+        self.download_size_on_start = None
+        
+        self.file_size = None
+        self.resume_downloaded = 0
+        
         self.first_hook = True
         self._stop = threading.Event()
         self.is_canceled = True
             return
         
         try:
-            key = groove.getStreamKeyFromSongIDEx(self.song.get_id())
-        except Exception as e:
-            self.song.emit("download-error", e.__str__())
-            return
-
-        try:
-            url = "http://" + key["result"]["%s" % self.song.get_id()]["ip"] + "/stream.php"
-            url = str(url)
+            url = self.song.get_streaming_url()
             c = pycurl.Curl()
             c.setopt(pycurl.URL, url)
             c.setopt(pycurl.NOPROGRESS, 0)
             c.setopt(pycurl.FAILONERROR, True)
             c.setopt(pycurl.WRITEDATA, self.file)
             if restart == False:
-                c.setopt(pycurl.RESUME_FROM, os.path.getsize(self.song.get_filename()))
-            c.setopt(pycurl.POST, True)
+                self.resume_downloaded = os.path.getsize(self.song.get_filename())
+                c.setopt(pycurl.RESUME_FROM, self.resume_downloaded)
+            else:
+                self.resume_downloaded = 0
             c.setopt(pycurl.NOSIGNAL, True)
             if self.speed != 0:
                 c.setopt(pycurl.MAX_RECV_SPEED_LARGE, self.speed)
-            c.setopt(pycurl.POSTFIELDS, str("streamKey=" + key["result"]["%s" % self.song.get_id()]["streamKey"]))
             
             c.perform()
             
             self.file.close()
-            self.song.set_download_progress(100)
+            self.download_progress = 100
             self.song.emit("download-completed")
         except pycurl.error, e:
             self.file.close()
                 self.first_hook = False
                 self.song.emit("download-started")
             
+            downloadTotal += self.resume_downloaded
+            downloadCurrent += self.resume_downloaded
+            
             progress = (downloadCurrent / downloadTotal) * 100
-            self.song.set_download_progress(progress)
-            self.song.set_file_size(downloadTotal)
+            self.download_progress = progress
+            self.file_size = downloadTotal
+            
+            current_time = time.time()
+            if current_time - self.download_time_start > 1:
+                self.download_speed = downloadCurrent - self.resume_downloaded - self.download_size_on_start
+                self.download_size_on_start = downloadCurrent - self.resume_downloaded
+                self.download_time_start = current_time
 
             if progress <= 99:
                 self.song.emit("download-updated")
+        else:
+            self.download_time_start = time.time()
+            self.download_size_on_start = 0
         
-        return False
+        return False
+    

File lib/tfuncs.py

         self._stop.wait(1)
         if self.stopped():
             return
-
+        
         try:
-            key = groove.getStreamKeyFromSongIDEx(self.song.get_id())
+            play_url = self.song.get_streaming_url()
         except Exception, e:
-            print e
-
+            return
+        
         if self.stopped():
             return
-
-        playurls = "http://%s/stream.php?streamKey=%s"
-        play_url = playurls % (key["result"]["%s" % self.song.get_id()]["ip"],
-                               key["result"]["%s" % self.song.get_id()]["streamKey"])
+        
         print "[Playing]", self.song.get_id(), play_url
         self.app.player.set_property('uri', play_url)
         self.app.player.set_state(gst.STATE_PLAYING)