From 9cfc89d1e46ef91b74c05dad8cadd5c606bc6531 Mon Sep 17 00:00:00 2001 From: Thomas Perl Date: Sun, 18 Mar 2007 18:28:17 +0000 Subject: [PATCH] support for single file transfer to device, based on a patch by Preben Randhol git-svn-id: svn://svn.berlios.de/gpodder/trunk@280 b0d088ad-0a06-0410-aad2-9ed5178a7e87 --- ChangeLog | 14 +++ bin/gpodder | 4 +- data/gpodder.glade | 120 +++++++++++++++++++++++-- src/gpodder/gpodder.py | 169 ++++++++++++++++++------------------ src/gpodder/gpodder.py.orig | 5 ++ src/gpodder/libipodsync.py | 38 +++++--- 6 files changed, 242 insertions(+), 108 deletions(-) diff --git a/ChangeLog b/ChangeLog index bbc7c62f..87f78376 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +Sun, 18 Mar 2007 19:23:46 +0100 + * src/gpodder/libipodsync.py: Add support for selected episodes to be + transferred to the device; get configuration data directly + from gPodderLib() + * src/gpodder/gpodder.py.orig: Updated by tepache + * src/gpodder/gpodder.py: Add support for "transfer" to device of + selected episodes instead of all episodes based on a patch by + Preben Randhol ; simplified and cleaned-up + code for device sync and device cleanup to allow for easier addition + of aforementioned patch + * data/gpodder.glade: Support for "transfer" to device button and menu + item based on a patch by Preben Randhol + * bin/gpodder: pushed version + release date + Sun, 18 Mar 2007 17:18:17 +0100 * Makefile: Bugfix - remove manpage "gpodder.1" in "make uninstall" diff --git a/bin/gpodder b/bin/gpodder index 0c47fddd..e9821e9c 100755 --- a/bin/gpodder +++ b/bin/gpodder @@ -32,8 +32,8 @@ or played back on the user's desktop. # PLEASE DO NOT CHANGE FORMAT OF __version__ LINE (setup.py reads this) __author__ = "Thomas Perl " -__version__ = "0.9.0+svn20070317" -__date__ = "2007-03-17" +__version__ = "0.9.0+svn20070318" +__date__ = "2007-03-18" __copyright__ = "Copyright (c) 2005-2007 %s. All rights reserved." % __author__ __licence__ = "GPL" diff --git a/data/gpodder.glade b/data/gpodder.glade index 79ee79b6..3b801ed0 100644 --- a/data/gpodder.glade +++ b/data/gpodder.glade @@ -505,19 +505,19 @@ - - - True - - + + + True + + True Play selected episode True - - + + @@ -532,6 +532,33 @@ + + + + True + + + + + + True + Transfer selected episodes + True + + + + + True + gtk-network + 1 + 0.5 + 0.5 + 0 + 0 + + + + @@ -846,6 +873,85 @@ + + + Transfer selected file(s) to player + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + gtk-network + 4 + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + _Transfer + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + True diff --git a/src/gpodder/gpodder.py b/src/gpodder/gpodder.py index e032abd9..a7ab479f 100644 --- a/src/gpodder/gpodder.py +++ b/src/gpodder/gpodder.py @@ -206,9 +206,12 @@ class Gpodder(SimpleGladeApp): if is_download_button: self.btnPlay.hide_all() self.btnDownload.show_all() + self.btnTransfer.hide_all() else: self.btnPlay.show_all() self.btnDownload.hide_all() + if gl.device_type != 'none': + self.btnTransfer.show_all() def updateComboBox( self): try: @@ -231,6 +234,7 @@ class Gpodder(SimpleGladeApp): while gtk.events_pending(): gtk.main_iteration( False) self.treeAvailable.scroll_to_point( rect.x, rect.y) + self.play_or_download() else: if self.treeAvailable.get_model(): self.treeAvailable.get_model().clear() @@ -332,50 +336,27 @@ class Gpodder(SimpleGladeApp): message = _('gPodder currently only supports URLs starting with http://, feed:// or ftp://.') self.show_message( message, title) - def sync_to_ipod_proc( self, sync_win): - gpl = gPodderLib() - gpl.loadConfig() - sync = gPodder_iPodSync( ipod_mount = gpl.ipod_mount, callback_status = sync_win.set_status, callback_progress = sync_win.set_progress, callback_done = sync_win.close) + def sync_to_ipod_proc( self, sync, episodes = None): if not sync.open(): - title = _('Cannot access iPod') - message = _('Make sure your iPod is connected to your computer and mounted. Please also make sure you have set the correct path to your iPod in the preferences dialog.') + title = _('Cannot access device') + message = _('Make sure your device is connected to your computer and mounted. Please also make sure you have set the correct path to your device in the preferences dialog.') gobject.idle_add( self.show_message, message, title) sync.close() return False - for channel in self.ldb.channel_list: - channel.set_metadata_from_localdb() - sync.sync_channel( channel) + if episodes == None: + for channel in self.ldb.channel_list: + channel.set_metadata_from_localdb() + sync.sync_channel( channel) + else: + sync.sync_channel( self.active_channel, episodes) sync.close() - def sync_to_fs_proc( self, sync_win): - gpl = gPodderLib() - gpl.loadConfig() - - if not gpl.can_write_directory( gpl.mp3_player_folder): - title = _('Cannot write to MP3 player') - message = _('Make sure your MP3 player is connected to your computer and mounted and that you have the correct permissions.') - gobject.idle_add( self.show_message, message, title) - if sync_win.close: - sync_win.close() - return False - - sync = gPodder_FSSync( destination = gpl.mp3_player_folder, callback_status = sync_win.set_status, callback_progress = sync_win.set_progress, callback_done = sync_win.close) - - for channel in self.ldb.channel_list: - channel.set_metadata_from_localdb() - sync.sync_channel( channel) - - sync.close() - - def ipod_cleanup_proc( self, sync_win): - gpl = gPodderLib() - gpl.loadConfig() - sync = gPodder_iPodSync( ipod_mount = gpl.ipod_mount, callback_status = sync_win.set_status, callback_progress = sync_win.set_progress, callback_done = sync_win.close) + def ipod_cleanup_proc( self, sync): if not sync.open(): - title = _('Cannot access iPod') - message = _('Make sure your iPod is connected to your computer and mounted. Please also make sure you have set the correct path to your iPod in the preferences dialog.') + title = _('Cannot access device') + message = _('Make sure your device is connected to your computer and mounted. Please also make sure you have set the correct path to your device in the preferences dialog.') gobject.idle_add( self.show_message, message, title) sync.close() return False @@ -383,23 +364,6 @@ class Gpodder(SimpleGladeApp): sync.clean_playlist() sync.close() - def fs_cleanup_proc( self, sync_win): - gpl = gPodderLib() - gpl.loadConfig() - - if not gpl.can_write_directory( gpl.mp3_player_folder): - title = _('Cannot write to MP3 player') - message = _('Make sure your MP3 player is connected to your computer and mounted and that you have the correct permissions.') - gobject.idle_add( self.show_message, message, title) - if sync_win.close: - sync_win.close() - return False - - sync = gPodder_FSSync( destination = gpl.mp3_player_folder, callback_status = sync_win.set_status, callback_progress = sync_win.set_progress, callback_done = sync_win.close) - - sync.clean_playlist() - sync.close() - def update_feed_cache_callback( self, label, progressbar, position, count): title = _('Please wait...') @@ -603,53 +567,69 @@ class Gpodder(SimpleGladeApp): title = _('No device configured') message = _('To use the synchronization feature, please configure your device in the preferences dialog first.') self.show_message( message, title) - elif gl.device_type == 'ipod': - if not ipod_supported(): - title = _('Libraries needed: gpod, pymad') - message = _('To use the iPod synchronization feature, you need to install the python-gpod and python-pymad libraries from your distribution vendor. More information about the needed libraries can be found on the gPodder website.') - self.show_message( message, title) + return + + if gl.device_type == 'ipod' and not ipod_supported(): + title = _('Libraries needed: gpod, pymad') + message = _('To use the iPod synchronization feature, you need to install the python-gpod and python-pymad libraries from your distribution vendor. More information about the needed libraries can be found on the gPodder website.') + self.show_message( message, title) + return + + if gl.device_type in [ 'ipod', 'filesystem' ]: + sync_class = None + + if gl.device_type == 'filesystem': + sync_class = gPodder_FSSync + elif gl.device_type == 'ipod': + sync_class = gPodder_iPodSync + + if not sync_class: return + sync_win = Gpoddersync( gpodderwindow = self.gPodder) - while gtk.events_pending(): - gtk.main_iteration( False) - args = ( sync_win, ) - thread = Thread( target = self.sync_to_ipod_proc, args = args) - thread.start() - elif gl.device_type == 'filesystem': - sync_win = Gpoddersync( gpodderwindow = self.gPodder) - while gtk.events_pending(): - gtk.main_iteration( False) - args = ( sync_win, ) - thread = Thread( target = self.sync_to_fs_proc, args = args) + sync = sync_class( callback_status = sync_win.set_status, callback_progress = sync_win.set_progress, callback_done = sync_win.close) + thread_args = [ sync ] + if widget == None: + thread_args.append( args[0]) + thread = Thread( target = self.sync_to_ipod_proc, args = thread_args) thread.start() #-- Gpodder.on_sync_to_ipod_activate } #-- Gpodder.on_cleanup_ipod_activate { def on_cleanup_ipod_activate(self, widget, *args): gl = gPodderLib() - target_function = None - if gl.device_type == 'none': title = _('No device configured') message = _('To use the synchronization feature, please configure your device in the preferences dialog first.') self.show_message( message, title) - elif gl.device_type == 'ipod': - title = _('Delete podcasts on iPod?') - message = _('Do you really want to completely remove all episodes in the Podcasts playlist on your iPod?') - if self.show_confirmation( message, title): - target_function = self.ipod_cleanup_proc - elif gl.device_type == 'filesystem': - title = _('Delete podcasts from MP3 player?') - message = _('Do you really want to completely remove all episodes from your MP3 player?') - if self.show_confirmation( message, title): - target_function = self.fs_cleanup_proc + return + + if gl.device_type == 'ipod' and not ipod_supported(): + title = _('Libraries needed: gpod, pymad') + message = _('To use the iPod synchronization feature, you need to install the python-gpod and python-pymad libraries from your distribution vendor. More information about the needed libraries can be found on the gPodder website.') + self.show_message( message, title) + return + + if gl.device_type in [ 'ipod', 'filesystem' ]: + sync_class = None + + if gl.device_type == 'filesystem': + title = _('Delete podcasts from MP3 player?') + message = _('Do you really want to completely remove all episodes from your MP3 player?') + if self.show_confirmation( message, title): + sync_class = gPodder_FSSync + elif gl.device_type == 'ipod': + title = _('Delete podcasts on iPod?') + message = _('Do you really want to completely remove all episodes in the Podcasts playlist on your iPod?') + if self.show_confirmation( message, title): + sync_class = gPodder_iPodSync + + if not sync_class: + return - if target_function: sync_win = Gpoddersync( gpodderwindow = self.gPodder) - while gtk.events_pending(): - gtk.main_iteration( False) - args = ( sync_win, ) - thread = Thread( target = target_function, args = args) + sync = sync_class( callback_status = sync_win.set_status, callback_progress = sync_win.set_progress, callback_done = sync_win.close) + thread = Thread( target = self.ipod_cleanup_proc, args = ( sync, )) thread.start() #-- Gpodder.on_cleanup_ipod_activate } @@ -730,6 +710,11 @@ class Gpodder(SimpleGladeApp): Gpodderopmllister( gpodderwindow = self.gPodder).get_channels_from_url( gPodderLib().opml_url, self.add_new_channel) #-- Gpodder.on_itemImportChannels_activate } + #-- Gpodder.on_btnTransfer_clicked { + def on_btnTransfer_clicked(self, widget, *args): + self.on_treeAvailable_row_activated( widget, args) + #-- Gpodder.on_btnTransfer_clicked } + #-- Gpodder.on_homepage_activate { def on_homepage_activate(self, widget, *args): os.system( 'gnome-open ' + app_website) @@ -801,6 +786,8 @@ class Gpodder(SimpleGladeApp): try: selection = self.treeAvailable.get_selection() selection_tuple = selection.get_selected_rows() + transfer_files = False + episodes = [] if selection.count_selected_rows() > 1: widget_to_send = None @@ -809,10 +796,20 @@ class Gpodder(SimpleGladeApp): widget_to_send = widget show_message_dialog = True + if widget.get_name() == 'itemTransferSelected' or widget.get_name() == 'btnTransfer': + transfer_files = True + for apath in selection_tuple[1]: selection_iter = self.treeAvailable.get_model().get_iter( apath) url = self.treeAvailable.get_model().get_value( selection_iter, 0) - self.download_podcast_by_url( url, show_message_dialog, widget_to_send) + + if transfer_files: + episodes.append( self.active_channel.find_episode( url)) + else: + self.download_podcast_by_url( url, show_message_dialog, widget_to_send) + + if transfer_files and len(episodes): + self.on_sync_to_ipod_activate( None, episodes) except: title = _('Nothing selected') message = _('Please select an episode that you want to download and then click on the download button to start downloading the selected episode.') diff --git a/src/gpodder/gpodder.py.orig b/src/gpodder/gpodder.py.orig index e032b1e5..c4be5572 100644 --- a/src/gpodder/gpodder.py.orig +++ b/src/gpodder/gpodder.py.orig @@ -125,6 +125,11 @@ class Gpodder(SimpleGladeApp): print "on_btnDownloadedExecute_clicked called with self.%s" % widget.get_name() #-- Gpodder.on_btnDownloadedExecute_clicked } + #-- Gpodder.on_btnTransfer_clicked { + def on_btnTransfer_clicked(self, widget, *args): + print "on_btnTransfer_clicked called with self.%s" % widget.get_name() + #-- Gpodder.on_btnTransfer_clicked } + #-- Gpodder.on_homepage_activate { def on_homepage_activate(self, widget, *args): print "on_homepage_activate called with self.%s" % widget.get_name() diff --git a/src/gpodder/libipodsync.py b/src/gpodder/libipodsync.py index c1dee2e3..4fea2d97 100644 --- a/src/gpodder/libipodsync.py +++ b/src/gpodder/libipodsync.py @@ -91,6 +91,7 @@ import email.Utils import liblocaldb import libpodcasts +import libgpodder import gobject @@ -115,6 +116,9 @@ class gPodderSyncMethod: self.callback_progress = callback_progress self.callback_status = callback_status self.callback_done = callback_done + + def open( self): + return False def set_progress( self, pos, max): if self.callback_progress: @@ -128,14 +132,17 @@ class gPodderSyncMethod: if self.callback_done: gobject.idle_add( self.callback_done) - def sync_channel( self, channel): - if not channel.sync_to_devices: + def sync_channel( self, channel, episodes = None): + if not channel.sync_to_devices and episodes == None: return False - max = len( channel) + if episodes == None: + episodes = channel + + max = len( episodes) pos = 1 - for episode in channel: + for episode in episodes: self.set_progress( pos, max) if channel.is_downloaded( episode): self.add_episode_from_channel( channel, episode) @@ -165,10 +172,11 @@ class gPodder_iPodSync( gPodderSyncMethod): pl_master = None pl_podcasts = None - def __init__( self, ipod_mount = '/media/ipod/', callback_progress = None, callback_status = None, callback_done = None): + def __init__( self, callback_progress = None, callback_status = None, callback_done = None): if not ipod_supported(): log( '(ipodsync) iPod functions not supported. (libgpod + eyed3 needed)') - self.ipod_mount = ipod_mount + gl = libgpodder.gPodderLib() + self.ipod_mount = gl.ipod_mount gPodderSyncMethod.__init__( self, callback_progress, callback_status, callback_done) def open( self): @@ -187,14 +195,13 @@ class gPodder_iPodSync( gPodderSyncMethod): return False return True - def close( self, write_update = True): + def close( self): if not ipod_supported(): return False - if write_update: + if self.itdb: self.set_progress( 100, 100) self.set_status( '...', '...', _('Saving iPod database...')) - if self.itdb: - gpod.itdb_write( self.itdb, None) + gpod.itdb_write( self.itdb, None) self.itdb = None time.sleep( 1) gPodderSyncMethod.close( self) @@ -401,9 +408,14 @@ class gPodder_iPodSync( gPodderSyncMethod): class gPodder_FSSync( gPodderSyncMethod): - def __init__( self, destination = '/tmp/', callback_progress = None, callback_status = None, callback_done = None): - self.destination = destination + def __init__( self, callback_progress = None, callback_status = None, callback_done = None): + gl = libgpodder.gPodderLib() + self.destination = gl.mp3_player_folder gPodderSyncMethod.__init__( self, callback_progress, callback_status, callback_done) + + def open( self): + gpl = libgpodder.gPodderLib() + return gpl.can_write_directory( self.destination) def add_episode_from_channel( self, channel, episode): replace_chars = ( '/', '?', ':', '!', '<', '>', '&', '*', '|') @@ -440,7 +452,7 @@ class gPodder_FSSync( gPodderSyncMethod): folders = glob.glob( os.path.join( self.destination, '*')) for folder in range( len( folders)): self.set_progress( folder+1, len( folders)) - self.set_status( channel = os.path.basename( folders[folder]), progressbar_text = _('%d of %d') % ( folder+1, len(folders), )) + self.set_status( episode = _('All files'), channel = os.path.basename( folders[folder]), progressbar_text = _('%d of %d') % ( folder+1, len(folders), )) log( 'deleting: %s', folders[folder]) shutil.rmtree( folders[folder]) try: