Fri, 13 Jun 2008 16:08:16 +0200 <thp@perli.net>

Merge patch to add experimental support for "normal" file naming

	* src/gpodder/config.py: New option "experimental_file_naming" that
	defaults to False and enables the new (but experimental!) normal file
	naming mode in which the downloaded podcast episodes get their name
	not from the md5sum of the download URL, but from the basename of the
	download URL, which makes filenames more human-readable
	* src/gpodder/libpodcasts.py: Change local_filename() in podcastItem
	to decide if we use md5sums or the "new" file naming mode for creating
	the local file name of an episode
	* src/gpodder/sync.py: Change usage of the "encoding" detection in
	gpodder.util (from detect_os_encoding() to simply encoding)
	* src/gpodder/util.py: Only detect the filename encoding once (at
	program start) and then make it accessible via a global "encoding"
	variable in the gpodder.util module; add improvements to
	file_extension_from_url() to be able to return the complete filename
	and to support more creative URL schemes as implemented by podcast
	feed authors (this hopefully makes more feeds work in a proper way)
	(Closes: http://bugs.gpodder.org/show_bug.cgi?id=57)

Add line to the previous ChangeLog entry (which I forgot initially):
	(Closes: http://bugs.gpodder.org/show_bug.cgi?id=124)


git-svn-id: svn://svn.berlios.de/gpodder/trunk@736 b0d088ad-0a06-0410-aad2-9ed5178a7e87
This commit is contained in:
Thomas Perl 2008-06-13 14:13:27 +00:00
parent ed11f1eef9
commit 0aec290ec2
5 changed files with 82 additions and 26 deletions

View file

@ -1,3 +1,24 @@
Fri, 13 Jun 2008 16:08:16 +0200 <thp@perli.net>
Merge patch to add experimental support for "normal" file naming
* src/gpodder/config.py: New option "experimental_file_naming" that
defaults to False and enables the new (but experimental!) normal file
naming mode in which the downloaded podcast episodes get their name
not from the md5sum of the download URL, but from the basename of the
download URL, which makes filenames more human-readable
* src/gpodder/libpodcasts.py: Change local_filename() in podcastItem
to decide if we use md5sums or the "new" file naming mode for creating
the local file name of an episode
* src/gpodder/sync.py: Change usage of the "encoding" detection in
gpodder.util (from detect_os_encoding() to simply encoding)
* src/gpodder/util.py: Only detect the filename encoding once (at
program start) and then make it accessible via a global "encoding"
variable in the gpodder.util module; add improvements to
file_extension_from_url() to be able to return the complete filename
and to support more creative URL schemes as implemented by podcast
feed authors (this hopefully makes more feeds work in a proper way)
(Closes: http://bugs.gpodder.org/show_bug.cgi?id=57)
Fri, 13 Jun 2008 14:27:30 +0200 <thp@perli.net>
Merge patch from Justin Forest to speed up pubDate detection
@ -7,6 +28,7 @@ Merge patch from Justin Forest to speed up pubDate detection
* src/gpodder/libpodcasts.py: Merge patch from Justin Forest to speed
up the newest_pubdate_downloaded() function by caching its value
instead of re-calculating it on every call
(Closes: http://bugs.gpodder.org/show_bug.cgi?id=124)
Fri, 13 Jun 2008 09:37:45 +0200 <thp@perli.net>
Merge patch from Nick to add support for deleting played files on sync

View file

@ -112,6 +112,7 @@ gPodderSettings = {
'maemo_allow_custom_player': (bool, False),
'rockbox_copy_coverart' : (bool, False),
'rockbox_coverart_size' : (int, 100),
'experimental_file_naming': (bool, False),
# Hide the cover/pill from the podcast sidebar when it gets too small
'podcast_sidebar_save_space': (bool, True),

View file

@ -721,8 +721,25 @@ class podcastItem(object):
log('Cannot delete episode from disk: %s', self.title, traceback=True, sender=self)
def local_filename( self):
extension = util.file_extension_from_url( self.url)
return os.path.join( self.channel.save_dir, md5.new( self.url).hexdigest() + extension)
ext = util.file_extension_from_url(self.url)
# For compatibility with already-downloaded episodes,
# we accept md5 filenames if they are downloaded now.
md5_filename = os.path.join(self.channel.save_dir, md5.new(self.url).hexdigest()+ext)
if os.path.exists(md5_filename) or not gl.config.experimental_file_naming:
return md5_filename
# If the md5 filename does not exist,
episode = util.file_extension_from_url(self.url, complete_filename=True)
episode = util.sanitize_filename(episode)
# If the episode filename looks suspicious,
# we still return the md5 filename to be on
# the safe side of the fence ;)
if len(episode) == 0 or episode.startswith('redirect.'):
return md5_filename
filename = os.path.join(self.channel.save_dir, episode)
return filename
def sync_filename( self):
if gl.config.custom_sync_name_enabled:

View file

@ -431,7 +431,6 @@ class MP3PlayerDevice(Device):
def __init__(self):
Device.__init__(self)
self.enc = util.detect_os_encoding()
self.destination = gl.config.mp3_player_folder
self.buffer_size = 1024*1024 # 1 MiB
self.scrobbler_log = []
@ -495,7 +494,7 @@ class MP3PlayerDevice(Device):
self.copy_rockbox_cover_art(folder, from_file)
if not os.path.exists(to_file):
log('Copying %s => %s', os.path.basename(from_file), to_file.decode(self.enc), sender=self)
log('Copying %s => %s', os.path.basename(from_file), to_file.decode(util.encoding), sender=self)
return self.copy_file_progress(from_file, to_file)
return True

View file

@ -61,6 +61,20 @@ import StringIO
import xml.dom.minidom
# Try to detect OS encoding (by Leonid Ponomarev)
encoding = 'iso-8859-15'
if 'LANG' in os.environ and '.' in os.environ['LANG']:
lang = os.environ['LANG']
(language, encoding) = lang.rsplit('.', 1)
log('Detected encoding: %s', encoding)
enc = encoding
else:
# Using iso-8859-15 here as (hopefully) sane default
# see http://en.wikipedia.org/wiki/ISO/IEC_8859-1
log('Using ISO-8859-15 as encoding. If this')
log('is incorrect, please set your $LANG variable.')
if gpodder.interface == gpodder.GUI:
ICON_UNPLAYED = gtk.STOCK_YES
ICON_LOCKED = 'emblem-nowrite'
@ -388,7 +402,7 @@ def torrent_filename( filename):
return None
def file_extension_from_url( url):
def file_extension_from_url(url, complete_filename=False):
"""
Extracts the (lowercase) file name extension (with dot)
from a URL, e.g. http://server.com/file.MP3?download=yes
@ -400,16 +414,26 @@ def file_extension_from_url( url):
into the query string to find better matches, if the
original extension does not resolve to a known type.
If the optional parameter "complete_filename" is set to
True, this will not return the extension, but the
complete filename (basename) of the found media file.
http://my.net/redirect.php?my.net/file.ogg => ".ogg"
http://server/get.jsp?file=/episode0815.MOV => ".mov"
http://s/redirect.mp4?http://serv2/test.mp4 => ".mp4"
"""
(scheme, netloc, path, para, query, fragid) = urlparse.urlparse(url)
filename = os.path.basename( urllib.unquote(path))
(filename, extension) = os.path.splitext(filename)
(tmp, extension) = os.path.splitext(filename)
if file_type_by_extension(extension) is not None:
if file_type_by_extension(extension) is not None and not \
query.startswith(scheme+'://'):
# We have found a valid extension (audio, video, torrent)
return extension.lower()
# and the query string doesn't look like a URL
if complete_filename:
return filename
else:
return extension.lower()
# If the query string looks like a possible URL, try that first
if len(query.strip()) > 0 and query.find('/') != -1:
@ -417,10 +441,16 @@ def file_extension_from_url( url):
query_extension = file_extension_from_url(query_url)
if file_type_by_extension(query_extension) is not None:
return query_extension
if complete_filename:
return os.path.basename(query_url)
else:
return query_extension
# No exact match found, simply return the original extension
return extension.lower()
if complete_filename:
return filename
else:
return extension.lower()
def file_type_by_extension( extension):
@ -891,7 +921,7 @@ def gui_open(filename):
# FIXME: Win32-specific "open" code needed here
# as fallback when xdg-open not available
except:
log('Cannot open file/folder: "%s"', folder, sender=self, traceback=True)
log('Cannot open file/folder: "%s"', filename, sender=self, traceback=True)
def open_website(url):
@ -902,20 +932,6 @@ def open_website(url):
"""
threading.Thread(target=webbrowser.open, args=(url,)).start()
def detect_os_encoding():
# Try to detect OS encoding (by Leonid Ponomarev)
if 'LANG' in os.environ and '.' in os.environ['LANG']:
lang = os.environ['LANG']
(language, encoding) = lang.rsplit('.', 1)
log('Detected encoding: %s', encoding)
enc = encoding
else:
# Using iso-8859-15 here as (hopefully) sane default
# see http://en.wikipedia.org/wiki/ISO/IEC_8859-1
log('Using ISO-8859-15 as encoding. If this')
log('is incorrect, please set your $LANG variable.')
enc = 'iso-8859-15'
return enc
def sanitize_filename(filename, max_length=0):
"""
@ -928,7 +944,8 @@ def sanitize_filename(filename, max_length=0):
log('Limiting file/folder name "%s" to %d characters.', filename, max_length, sender=self)
filename = filename[:max_length]
return re.sub('[/|?*<>:+\[\]\"\\\]', '_', filename.strip().encode(detect_os_encoding(), 'ignore'))
global encoding
return re.sub('[/|?*<>:+\[\]\"\\\]', '_', filename.strip().encode(encoding, 'ignore'))
def find_mount_point(directory):