Remove BitTorrent-specific code

Let the Desktop Environment / the default BitTorrent
client handle torrent downloads. We just use the default
handler for .torrent files to "open" a torrent file after
download has completed.

Discussed on the mailing list in the following thread:

https://lists.berlios.de/pipermail/gpodder-devel/2008-November/002256.html
This commit is contained in:
Thomas Perl 2008-11-17 21:35:25 +01:00
parent c0629e17d8
commit 9c4bc90e8b
8 changed files with 5 additions and 327 deletions

4
README
View File

@ -58,10 +58,6 @@
* oggdec (for decoding OGG files)
* lame (for encoding MP3 files)
Additional dependencies if you want direct BitTorrent download support:
* gnome-btdownload
Additional dependencies if you want Bluetooth file send support:
* python-bluez OR hcitool (for detecting nearby devices)

View File

@ -4617,252 +4617,6 @@ MTP-based player</property>
</packing>
</child>
<child>
<widget class="GtkTable" id="table6">
<property name="border_width">10</property>
<property name="visible">True</property>
<property name="n_rows">7</property>
<property name="n_columns">2</property>
<property name="homogeneous">False</property>
<property name="row_spacing">6</property>
<property name="column_spacing">6</property>
<child>
<widget class="GtkLabel" id="label83">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Download Method&lt;/b&gt;</property>
<property name="use_underline">False</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">2</property>
<property name="top_attach">0</property>
<property name="bottom_attach">1</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkRadioButton" id="radio_gnome_bittorrent">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Download using gnome-bittorrent</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkRadioButton" id="radio_copy_torrents">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Just save .torrent files in download folder</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
<property name="group">radio_gnome_bittorrent</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkImage" id="image2419">
<property name="visible">True</property>
<property name="icon_size">6</property>
<property name="icon_name">text-x-generic</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">1</property>
<property name="bottom_attach">3</property>
<property name="x_padding">6</property>
<property name="x_options">fill</property>
<property name="y_options">fill</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label82">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Torrent Download Folder&lt;/b&gt;</property>
<property name="use_underline">False</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">2</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkFileChooserButton" id="chooserBitTorrentTo">
<property name="visible">True</property>
<property name="title" translatable="yes">Select BitTorrent folder</property>
<property name="action">GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER</property>
<property name="local_only">True</property>
<property name="show_hidden">False</property>
<property name="do_overwrite_confirmation">False</property>
<property name="width_chars">-1</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkImage" id="image2418">
<property name="visible">True</property>
<property name="icon_size">6</property>
<property name="icon_name">gtk-save-as</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="x_padding">6</property>
<property name="x_options">fill</property>
<property name="y_options">fill</property>
</packing>
</child>
<child>
<widget class="GtkHSeparator" id="hseparator11">
<property name="visible">True</property>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="y_padding">3</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
</widget>
<packing>
<property name="tab_expand">False</property>
<property name="tab_fill">True</property>
</packing>
</child>
<child>
<widget class="GtkVBox" id="vbox8">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkImage" id="image2416">
<property name="visible">True</property>
<property name="icon_size">3</property>
<property name="icon_name">gtk-network</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label79">
<property name="visible">True</property>
<property name="label" translatable="yes">BitTorrent</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
<packing>
<property name="type">tab</property>
</packing>
</child>
<child>
<widget class="GtkTable" id="table12">
<property name="border_width">10</property>

View File

@ -38,10 +38,8 @@ import threading
import ConfigParser
if gpodder.interface == gpodder.MAEMO:
default_bittorrent_dir = '/media/mmc2/gpodder/torrents'
default_download_dir = '/media/mmc2/gpodder/downloads'
else:
default_bittorrent_dir = os.path.expanduser('~/gpodder-downloads/torrents')
default_download_dir = os.path.expanduser('~/gpodder-downloads')
gPodderSettings = {
@ -57,13 +55,11 @@ gPodderSettings = {
'max_downloads_enabled': ( bool, False ),
'limit_rate': ( bool, False ),
'limit_rate_value': ( float, 500.0 ),
'bittorrent_dir': (str, default_bittorrent_dir),
'episode_old_age': ( int, 7 ),
# Boolean config flags
'update_on_startup': ( bool, False ),
'auto_download_when_minimized': (bool, False),
'use_gnome_bittorrent': ( bool, True ),
'only_sync_not_played': ( bool, False ),
'proxy_use_environment': ( bool, True ),
'update_tags': ( bool, False ),

View File

@ -1141,9 +1141,6 @@ class gPodder(GladeWidget):
else:
can_download = True
if episode.file_type() == 'torrent':
can_download = can_download or gl.config.use_gnome_bittorrent
can_download = can_download and not can_cancel
can_play = can_play and not can_cancel and not can_download
can_transfer = can_play and gl.config.device_type != 'none'
@ -2688,7 +2685,6 @@ class gPodderProperties(GladeWidget):
if gpodder.interface == gpodder.MAEMO:
self.table13.hide_all() # bluetooth
self.table5.hide_all() # player
self.table6.hide_all() # bittorrent
self.gPodderProperties.fullscreen()
gl.config.connect_gtk_editable( 'http_proxy', self.httpProxy)
@ -2698,14 +2694,12 @@ class gPodderProperties(GladeWidget):
gl.config.connect_gtk_editable( 'custom_sync_name', self.entryCustomSyncName)
gl.config.connect_gtk_togglebutton( 'custom_sync_name_enabled', self.cbCustomSyncName)
gl.config.connect_gtk_togglebutton( 'auto_download_when_minimized', self.downloadnew)
gl.config.connect_gtk_togglebutton( 'use_gnome_bittorrent', self.radio_gnome_bittorrent)
gl.config.connect_gtk_togglebutton( 'update_on_startup', self.updateonstartup)
gl.config.connect_gtk_togglebutton( 'only_sync_not_played', self.only_sync_not_played)
gl.config.connect_gtk_togglebutton( 'fssync_channel_subfolders', self.cbChannelSubfolder)
gl.config.connect_gtk_togglebutton( 'on_sync_mark_played', self.on_sync_mark_played)
gl.config.connect_gtk_togglebutton( 'on_sync_delete', self.on_sync_delete)
gl.config.connect_gtk_togglebutton( 'proxy_use_environment', self.cbEnvironmentVariables)
gl.config.connect_gtk_filechooser( 'bittorrent_dir', self.chooserBitTorrentTo)
gl.config.connect_gtk_spinbutton('episode_old_age', self.episode_old_age)
gl.config.connect_gtk_togglebutton('auto_remove_old_episodes', self.auto_remove_old_episodes)
gl.config.connect_gtk_togglebutton('auto_update_feeds', self.auto_update_feeds)
@ -2727,9 +2721,6 @@ class gPodderProperties(GladeWidget):
self.entryCustomSyncName.set_sensitive( self.cbCustomSyncName.get_active())
self.radio_gnome_bittorrent.set_active(gl.config.use_gnome_bittorrent)
self.radio_copy_torrents.set_active(not gl.config.use_gnome_bittorrent)
self.iPodMountpoint.set_label( gl.config.ipod_mount)
self.filesystemMountpoint.set_label( gl.config.mp3_player_folder)
self.bluetooth_device_name.set_markup('<b>%s</b>'%gl.config.bluetooth_device_name)

View File

@ -73,7 +73,6 @@ class gPodderLib(object):
self.migrate_channels_xml()
self.config = config.Config( os.path.join( gpodder_dir, 'gpodder.conf'))
util.make_directory(self.config.bittorrent_dir)
# We need to make a seamless upgrade, so by default the video player is not specified
# so the first time this application is run it will detect this and set it to the same
@ -262,7 +261,7 @@ class gPodderLib(object):
for ddir in download_dirs:
if os.path.isdir( ddir):
globr = glob.glob( '%s/*' % ( ddir, ))
if not globr and ddir != self.config.bittorrent_dir:
if not globr:
log( 'Stale download directory found: %s', os.path.basename( ddir))
try:
os.rmdir( ddir)
@ -341,29 +340,6 @@ class gPodderLib(object):
return ( False, command_line[0] )
return ( True, command_line[0] )
def invoke_torrent( self, url, torrent_filename, target_filename):
db.mark_episode(url, is_played=True)
if self.config.use_gnome_bittorrent:
if util.find_command('gnome-btdownload') is None:
log( 'Cannot find "gnome-btdownload". Please install gnome-bittorrent.', sender = self)
return False
command = 'gnome-btdownload "%s" --saveas "%s"' % ( torrent_filename, os.path.join( self.config.bittorrent_dir, target_filename))
log( command, sender = self)
os.system( '%s &' % command)
return True
else:
# Simply copy the .torrent with a suitable name
try:
target_filename = os.path.join( self.config.bittorrent_dir, os.path.splitext( target_filename)[0] + '.torrent')
shutil.copyfile( torrent_filename, target_filename)
return True
except:
log( 'Torrent copy failed: %s => %s.', torrent_filename, target_filename)
return False
def ext_command_thread(self, notification, command_line):
"""
This is the function that will be called in a separate

View File

@ -64,14 +64,12 @@ from xml.sax import saxutils
if gpodder.interface == gpodder.MAEMO:
ICON_AUDIO_FILE = 'gnome-mime-audio-mp3'
ICON_VIDEO_FILE = 'gnome-mime-video-mp4'
ICON_BITTORRENT = 'qgn_toolb_browser_web'
ICON_DOWNLOADING = 'qgn_toolb_messagin_moveto'
ICON_DELETED = 'qgn_toolb_gene_deletebutton'
ICON_NEW = 'qgn_list_gene_favor'
else:
ICON_AUDIO_FILE = 'audio-x-generic'
ICON_VIDEO_FILE = 'video-x-generic'
ICON_BITTORRENT = 'applications-internet'
ICON_DOWNLOADING = gtk.STOCK_GO_DOWN
ICON_DELETED = gtk.STOCK_DELETE
ICON_NEW = gtk.STOCK_ABOUT
@ -331,11 +329,6 @@ class podcastChannel(object):
log('Error while calling update_metadata_on_file(): %s', e)
self.update_m3u_playlist()
if item.file_type() == 'torrent':
torrent_filename = item.local_filename()
destination_filename = util.torrent_filename( torrent_filename)
gl.invoke_torrent(item.url, torrent_filename, destination_filename)
def get_all_episodes(self):
return db.load_episodes(self, factory = lambda d: podcastItem.create_from_dict(d, self))
@ -356,7 +349,7 @@ class podcastChannel(object):
return self.items_liststore()
def iter_set_downloading_columns( self, model, iter, episode=None):
global ICON_AUDIO_FILE, ICON_VIDEO_FILE, ICON_BITTORRENT
global ICON_AUDIO_FILE, ICON_VIDEO_FILE
global ICON_DOWNLOADING, ICON_DELETED, ICON_NEW
if episode is None:
@ -389,8 +382,6 @@ class podcastChannel(object):
status_icon = util.get_tree_icon(ICON_AUDIO_FILE, not episode.is_played, episode.is_locked, not episode.file_exists(), self.icon_cache, icon_size)
elif file_type == 'video':
status_icon = util.get_tree_icon(ICON_VIDEO_FILE, not episode.is_played, episode.is_locked, not episode.file_exists(), self.icon_cache, icon_size)
elif file_type == 'torrent':
status_icon = util.get_tree_icon(ICON_BITTORRENT, not episode.is_played, episode.is_locked, not episode.file_exists(), self.icon_cache, icon_size)
else:
status_icon = util.get_tree_icon('unknown', not episode.is_played, episode.is_locked, not episode.file_exists(), self.icon_cache, icon_size)
elif episode.state == db.STATE_DELETED or episode.state == db.STATE_DOWNLOADED:

View File

@ -149,7 +149,6 @@ dependency_manager = DependencyManager()
dependency_manager.depend_on(_('Bluetooth file transfer'), _('Send podcast episodes to Bluetooth devices. Needs Python Bluez bindings.'), ['bluetooth'], ['bluetooth-sendto'])
dependency_manager.depend_on(_('Update tags on MP3 files'), _('Support the "Update tags after download" option for MP3 files.'), ['eyeD3'], [])
dependency_manager.depend_on(_('Update tags on OGG files'), _('Support the "Update tags after download" option for OGG files.'), [], ['vorbiscomment'])
dependency_manager.depend_on(_('Gnome BitTorrent integration'), _('Download .torrent files using Gnome BitTorrent.'), [], ['gnome-btdownload'])
class CoverDownloader(ObservableService):

View File

@ -406,30 +406,6 @@ def remove_html_tags(html):
return result.strip()
def torrent_filename( filename):
"""
Checks if a file is a ".torrent" file by examining its
contents and searching for the file name of the file
to be downloaded.
Returns the name of the file the ".torrent" will download
or None if no filename is found (the file is no ".torrent")
"""
if not os.path.exists( filename):
return None
header = open( filename).readline()
try:
header.index( '6:pieces')
name_length_pos = header.index('4:name') + 6
colon_pos = header.find( ':', name_length_pos)
name_length = int(header[name_length_pos:colon_pos]) + 1
name = header[(colon_pos + 1):(colon_pos + name_length)]
return name
except:
return None
def extension_from_mimetype(mimetype):
"""
Simply guesses what the file extension should be from the mimetype
@ -443,7 +419,7 @@ def filename_from_url(url):
will result in the string ("file", ".mp3") being returned.
This function will also try to best-guess the "real"
extension for a media file (audio, video, torrent) by
extension for a media file (audio, video) by
trying to match an extension to these types and recurse
into the query string to find better matches, if the
original extension does not resolve to a known type.
@ -457,7 +433,7 @@ def filename_from_url(url):
if file_type_by_extension(extension) is not None and not \
query.startswith(scheme+'://'):
# We have found a valid extension (audio, video, torrent)
# We have found a valid extension (audio, video)
# and the query string doesn't look like a URL
return ( filename, extension.lower() )
@ -477,13 +453,12 @@ def file_type_by_extension( extension):
"""
Tries to guess the file type by looking up the filename
extension from a table of known file types. Will return
the type as string ("audio", "video" or "torrent") or
the type as string ("audio" or "video") or
None if the file type cannot be determined.
"""
types = {
'audio': [ 'mp3', 'ogg', 'wav', 'wma', 'aac', 'm4a' ],
'video': [ 'mp4', 'avi', 'mpg', 'mpeg', 'm4v', 'mov', 'divx', 'flv', 'wmv', '3gp' ],
'torrent': [ 'torrent' ],
}
if extension == '':