Extensions: Various fixes and clean-ups from review
This commit is contained in:
parent
e787bef4e3
commit
9c147cf980
|
@ -8,10 +8,10 @@
|
|||
# Released under the same license terms as gPodder itself.
|
||||
|
||||
import os
|
||||
import shlex
|
||||
import subprocess
|
||||
|
||||
import gpodder
|
||||
|
||||
from gpodder import util
|
||||
from gpodder import youtube
|
||||
|
||||
|
@ -20,96 +20,75 @@ logger = logging.getLogger(__name__)
|
|||
|
||||
_ = gpodder.gettext
|
||||
|
||||
__title__ = _('Convert FLV to MP4')
|
||||
__description__ = _('Put FLV files from YouTube into a MP4 container after download')
|
||||
__title__ = _('Convert .flv files from YouTube to .mp4')
|
||||
__description__ = _('Useful for playing downloaded videos on hardware players')
|
||||
__author__ = 'Thomas Perl <thp@gpodder.org>, Bernd Schlapsi <brot@gmx.info>'
|
||||
|
||||
DefaultConfig = {
|
||||
'extensions': {
|
||||
'flv2mp4': {
|
||||
'context_menu': True,
|
||||
}
|
||||
}
|
||||
'context_menu': True, # Show the conversion option in the context menu
|
||||
}
|
||||
|
||||
FFMPEG_CMD = 'ffmpeg -i "%(infile)s" -vcodec copy -acodec copy "%(outfile)s"'
|
||||
|
||||
|
||||
class gPodderExtension:
|
||||
MIME_TYPE = 'video/x-flv'
|
||||
|
||||
def __init__(self, container):
|
||||
self.container = container
|
||||
self.config = self.container.config
|
||||
|
||||
self.cmd = FFMPEG_CMD
|
||||
program = shlex.split(self.cmd)[0]
|
||||
if not util.find_command(program):
|
||||
raise ImportError("Couldn't find program '%s'" % program)
|
||||
|
||||
def on_load(self):
|
||||
logger.info('Extension "%s" is being loaded.' % __title__)
|
||||
|
||||
def on_unload(self):
|
||||
logger.info('Extension "%s" is being unloaded.' % __title__)
|
||||
# Dependency checks
|
||||
self.container.require_command('ffmpeg')
|
||||
|
||||
def on_episode_downloaded(self, episode):
|
||||
self._convert_episode(episode)
|
||||
if youtube.is_video_link(episode.url):
|
||||
self._convert_episode(episode)
|
||||
|
||||
def on_episodes_context_menu(self, episodes):
|
||||
if not self.container.config.context_menu:
|
||||
if not self.config.context_menu:
|
||||
return None
|
||||
|
||||
if 'video/x-flv' not in [e.mime_type for e in episodes if e.file_exists()]:
|
||||
if not all(e.was_downloaded(and_exists=True) for e in episodes):
|
||||
return None
|
||||
|
||||
return [(self.container.metadata.title, self._convert_episodes)]
|
||||
if not any(e.mime_type == self.MIME_TYPE for e in episodes):
|
||||
return None
|
||||
|
||||
return [(_('Convert FLV to MP4'), self._convert_episodes)]
|
||||
|
||||
|
||||
def _convert_episode(self, episode):
|
||||
retvalue = self._run_conversion(episode)
|
||||
old_filename = episode.local_filename(create=False)
|
||||
filename, ext = os.path.splitext(filename)
|
||||
new_filename = filename + '.mp4'
|
||||
|
||||
if retvalue == 0:
|
||||
logger.info('FLV conversion successful.')
|
||||
self.rename_episode_file(episode, basename+'.mp4')
|
||||
os.remove(filename)
|
||||
else:
|
||||
logger.info('Error converting file. FFMPEG installed?')
|
||||
try:
|
||||
os.remove(target)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
def _run_conversion(self, episode):
|
||||
if not youtube.is_video_link(episode.url):
|
||||
logger.debug('Not a YouTube video. Ignoring.')
|
||||
return
|
||||
|
||||
filename = episode.local_filename(create=False)
|
||||
dirname = os.path.dirname(filename)
|
||||
basename, ext = os.path.splitext(os.path.basename(filename))
|
||||
|
||||
if open(filename, 'rb').read(3) != 'FLV':
|
||||
if open(old_filename, 'rb').read(3) != 'FLV':
|
||||
logger.debug('Not a FLV file. Ignoring.')
|
||||
return
|
||||
|
||||
if ext == '.mp4':
|
||||
if ext.lower() == '.mp4':
|
||||
# Move file out of place for conversion
|
||||
newname = os.path.join(dirname, basename+'.flv')
|
||||
os.rename(filename, newname)
|
||||
filename = newname
|
||||
tmp_filename = filename + '.flv'
|
||||
os.rename(old_filename, tmp_filename)
|
||||
old_filename = tmp_filename
|
||||
|
||||
target = os.path.join(dirname, basename+'.mp4')
|
||||
cmd = FFMPEG_CMD % {
|
||||
'infile': filename,
|
||||
'outfile': target
|
||||
}
|
||||
cmd = ['ffmpeg',
|
||||
'-i', old_filename,
|
||||
'-vcodec', 'copy',
|
||||
'-acodec', 'copy',
|
||||
new_filename]
|
||||
|
||||
# Prior to Python 2.7.3, this module (shlex) did not support Unicode input.
|
||||
cmd = util.sanitize_encoding(cmd)
|
||||
|
||||
ffmpeg = subprocess.Popen(shlex.split(cmd),
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
||||
)
|
||||
ffmpeg = subprocess.Popen(cmd, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
stdout, stderr = ffmpeg.communicate()
|
||||
return ffmpeg.returncode
|
||||
|
||||
if ffmpeg.returncode == 0:
|
||||
logger.info('FLV conversion successful.')
|
||||
util.rename_episode_file(episode, new_filename)
|
||||
os.remove(old_filename)
|
||||
else:
|
||||
logger.warn('Error converting file: %s / %s', stdout, stderr)
|
||||
|
||||
def _convert_episodes(self, episodes):
|
||||
for episode in episodes:
|
||||
self._convert_episode(episode)
|
||||
|
||||
|
|
|
@ -7,108 +7,81 @@
|
|||
# Released under the same license terms as gPodder itself.
|
||||
|
||||
import os
|
||||
import shlex
|
||||
import subprocess
|
||||
|
||||
import gpodder
|
||||
from gpodder import util
|
||||
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
_ = gpodder.gettext
|
||||
|
||||
__title__ = _('Converts M4A audio')
|
||||
__description__ = _('Converts m4a audio files to mp3')
|
||||
__author__ = 'Bernd Schlapsi <brot@gmx.info>'
|
||||
__title__ = _('Convert M4A audio to MP3 or OGG')
|
||||
__description__ = _('Transcode .m4a files to .mp3 or .ogg using ffmpeg')
|
||||
__author__ = 'Bernd Schlapsi <brot@gmx.info>, Thomas Perl <thp@gpodder.org>'
|
||||
|
||||
|
||||
DefaultConfig = {
|
||||
'extensions': {
|
||||
'm4a_converter': {
|
||||
'file_format': [ True, False ],
|
||||
'context_menu': True,
|
||||
}
|
||||
}
|
||||
'use_ogg': False, # Set to True to convert to .ogg (otherwise .mp3)
|
||||
'context_menu': True, # Show the conversion option in the context menu
|
||||
}
|
||||
|
||||
FILE_FORMATS = ( 'mp3', 'ogg' )
|
||||
FFMPEG_CMD = 'ffmpeg -i "%(infile)s" -sameq "%(outfile)s"'
|
||||
MIME_TYPES = ['audio/x-m4a', 'audio/mp4']
|
||||
|
||||
|
||||
class gPodderExtension:
|
||||
MIME_TYPES = ['audio/x-m4a', 'audio/mp4']
|
||||
|
||||
def __init__(self, container):
|
||||
self.container = container
|
||||
self.config = self.container.config
|
||||
|
||||
program = shlex.split(FFMPEG_CMD)[0]
|
||||
if not util.find_command(program):
|
||||
raise ImportError("Couldn't find program '%s'" % program)
|
||||
|
||||
def on_load(self):
|
||||
logger.info('Extension "%s" is being loaded.' % __title__)
|
||||
|
||||
def on_unload(self):
|
||||
logger.info('Extension "%s" is being unloaded.' % __title__)
|
||||
# Dependency checks
|
||||
self.container.require_command('ffmpeg')
|
||||
|
||||
def on_episode_downloaded(self, episode):
|
||||
self._convert_episode(episode)
|
||||
|
||||
def on_episodes_context_menu(self, episodes):
|
||||
if not self.container.config.context_menu:
|
||||
if not self.config.context_menu:
|
||||
return None
|
||||
|
||||
if not [e for e in episodes if e.mime_type in MIME_TYPES and e.file_exists()]:
|
||||
if not all(e.was_downloaded(and_exists=True) for e in episodes):
|
||||
return None
|
||||
|
||||
return [(self.container.metadata.title, self._convert_episodes)]
|
||||
if not any(e.mime_type in self.MIME_TYPES for e in episodes):
|
||||
return None
|
||||
|
||||
target_format = ('OGG' if self.config.use_ogg else 'MP3')
|
||||
menu_item = _('Convert to %(format)s') % {'format': target_format}
|
||||
|
||||
return [(menu_item, self._convert_episodes)]
|
||||
|
||||
def _convert_episode(self, episode):
|
||||
retvalue = self._run_conversion(episode)
|
||||
|
||||
if retvalue == 0:
|
||||
logger.info('m4a -> %s conversion successful.', extension)
|
||||
gpodder.user_extensions.on_notification_show("Converting finished", episode)
|
||||
if not self.container.manager.testrun:
|
||||
self.rename_episode_file(episode, target)
|
||||
os.remove(filename)
|
||||
else:
|
||||
logger.info('Error converting file. FFMPEG installed?')
|
||||
gpodder.user_extensions.on_notification_show("Converting finished with errors", episode)
|
||||
try:
|
||||
os.remove(target)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
def _run_conversion(self, episode):
|
||||
choices = zip(FILE_FORMATS, self.container.config.file_format)
|
||||
extension = '.' + [ext for ext, state in choices if state][0]
|
||||
|
||||
filename = episode.local_filename(create=False)
|
||||
dirname = os.path.dirname(filename)
|
||||
basename, ext = os.path.splitext(os.path.basename(filename))
|
||||
new_filename = basename + extension
|
||||
|
||||
if episode.mime_type not in MIME_TYPES:
|
||||
if episode.mime_type not in self.MIME_TYPES:
|
||||
return
|
||||
|
||||
gpodder.user_extensions.on_notification_show("Converting", episode)
|
||||
if self.config.use_ogg:
|
||||
extension = '.ogg'
|
||||
else:
|
||||
extension = '.mp3'
|
||||
|
||||
target = os.path.join(dirname, new_filename)
|
||||
cmd = FFMPEG_CMD % {
|
||||
'infile': filename,
|
||||
'outfile': target
|
||||
}
|
||||
old_filename = episode.local_filename(create=False)
|
||||
filename, _ = os.path.splitext(old_filename)
|
||||
new_filename = filename + extension
|
||||
|
||||
# Prior to Python 2.7.3, this module (shlex) did not support Unicode input.
|
||||
cmd = util.sanitize_encoding(cmd)
|
||||
|
||||
ffmpeg = subprocess.Popen(shlex.split(cmd),
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
||||
)
|
||||
cmd = ['ffmpeg', '-i', old_filename, '-sameq', new_filename]
|
||||
ffmpeg = subprocess.Popen(cmd, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
stdout, stderr = ffmpeg.communicate()
|
||||
return ffmpeg.returncode
|
||||
|
||||
if ffmpeg.returncode == 0:
|
||||
logger.info('Converted M4A file.')
|
||||
gpodder.user_extensions.on_notification_show(_('File converted'),
|
||||
episode)
|
||||
else:
|
||||
logger.warn('Error converting file: %s / %s', stdout, stderr)
|
||||
gpodder.user_extensions.on_notification_show(_('Conversion failed'),
|
||||
episode)
|
||||
|
||||
def _convert_episodes(self, episodes):
|
||||
for episode in episodes:
|
||||
self._convert_episode(episode)
|
||||
|
||||
|
|
|
@ -5,9 +5,8 @@
|
|||
#
|
||||
# (c) 2011-11-06 Bernd Schlapsi <brot@gmx.info>
|
||||
# Released under the same license terms as gPodder itself.
|
||||
|
||||
import os
|
||||
import platform
|
||||
import shlex
|
||||
import subprocess
|
||||
|
||||
import gpodder
|
||||
|
@ -18,77 +17,60 @@ logger = logging.getLogger(__name__)
|
|||
|
||||
_ = gpodder.gettext
|
||||
|
||||
__title__ = _('mp3gain')
|
||||
__description__ = _('This hook adjusts mp3s so that they all have the same volume. It don\'t decode and re-encode the audio file')
|
||||
__title__ = _('mp3gain Volume Normalizer')
|
||||
__description__ = _('Normalize the volume of MP3 files without re-encoding')
|
||||
__author__ = 'Bernd Schlapsi <brot@gmx.info>'
|
||||
|
||||
|
||||
DefaultConfig = {
|
||||
'extensions': {
|
||||
'mp3gain': {
|
||||
'context_menu': True,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CMD = {
|
||||
'Linux': 'mp3gain -c "%s"',
|
||||
'Windows': 'mp3gain.exe -c "%s"'
|
||||
'context_menu': True,
|
||||
}
|
||||
|
||||
|
||||
class gPodderExtension:
|
||||
MIME_TYPE = 'audio/mpeg'
|
||||
|
||||
def __init__(self, container):
|
||||
self.container = container
|
||||
self.config = self.container.config
|
||||
|
||||
self.cmd = CMD[platform.system()]
|
||||
program = shlex.split(self.cmd)[0]
|
||||
if not util.find_command(program):
|
||||
raise ImportError("Couldn't find program '%s'" % program)
|
||||
|
||||
def on_load(self):
|
||||
logger.info('Extension "%s" is being loaded.' % __title__)
|
||||
|
||||
def on_unload(self):
|
||||
logger.info('Extension "%s" is being unloaded.' % __title__)
|
||||
self.mp3gain = self.container.require_command('mp3gain')
|
||||
|
||||
def on_episode_downloaded(self, episode):
|
||||
self._convert_episode(episode)
|
||||
|
||||
def on_episodes_context_menu(self, episodes):
|
||||
if not self.container.config.context_menu:
|
||||
if not self.config.context_menu:
|
||||
return None
|
||||
|
||||
if 'audio/mpeg' not in [e.mime_type for e in episodes
|
||||
if e.mime_type is not None and e.file_exists()]:
|
||||
if not all(e.was_downloaded(and_exists=True) for e in episodes):
|
||||
return None
|
||||
|
||||
return [(self.container.metadata.title, self._convert_episodes)]
|
||||
if not any(e.mime_type == self.MIME_TYPE for e in episodes):
|
||||
return None
|
||||
|
||||
return [(_('Normalize volume (mp3gain)'), self._convert_episodes)]
|
||||
|
||||
def _convert_episode(self, episode):
|
||||
filename = episode.local_filename(create=False, check_only=True)
|
||||
if episode.mime_type != self.MIME_TYPE:
|
||||
return
|
||||
|
||||
filename = episode.local_filename(create=False)
|
||||
if filename is None:
|
||||
return
|
||||
|
||||
(basename, extension) = os.path.splitext(filename)
|
||||
if episode.file_type() == 'audio' and extension.lower().endswith('mp3'):
|
||||
cmd = [self.mp3gain, '-c', filename]
|
||||
|
||||
cmd = self.cmd % filename
|
||||
p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
stdout, stderr = p.communicate()
|
||||
|
||||
# Prior to Python 2.7.3, this module (shlex) did not support Unicode input.
|
||||
cmd = util.sanitize_encoding(cmd)
|
||||
|
||||
p = subprocess.Popen(shlex.split(cmd),
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stdout, stderr = p.communicate()
|
||||
|
||||
if p.returncode == 0:
|
||||
logger.info('mp3gain processing successfull.')
|
||||
|
||||
else:
|
||||
logger.info('mp3gain processing not successfull.')
|
||||
logger.debug(stdout + stderr)
|
||||
if p.returncode == 0:
|
||||
logger.info('mp3gain processing successful.')
|
||||
else:
|
||||
logger.warn('mp3gain failed: %s / %s', stdout, stderr)
|
||||
|
||||
def _convert_episodes(self, episodes):
|
||||
for episode in episodes:
|
||||
self._convert_episode(episode)
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
#
|
||||
# (c) 2011-11-06 Bernd Schlapsi <brot@gmx.info>
|
||||
# Released under the same license terms as gPodder itself.
|
||||
|
||||
import os
|
||||
import shlex
|
||||
import subprocess
|
||||
|
||||
import gpodder
|
||||
|
@ -18,38 +18,29 @@ logger = logging.getLogger(__name__)
|
|||
|
||||
_ = gpodder.gettext
|
||||
|
||||
__title__ = _('Normalize audio')
|
||||
__description__ = _('This hook adjusts mp3s/oggs so that they all have the same volume. It decode and re-encode the audio file')
|
||||
__title__ = _('Normalize audio with re-encoding')
|
||||
__description__ = _('Normalize the volume of audio files with normalize-audio')
|
||||
__author__ = 'Bernd Schlapsi <brot@gmx.info>'
|
||||
|
||||
|
||||
DefaultConfig = {
|
||||
'extensions': {
|
||||
'normalize_audio': {
|
||||
'context_menu': True,
|
||||
}
|
||||
}
|
||||
'context_menu': True, # Show action in the episode list context menu
|
||||
}
|
||||
|
||||
# a tuple of (extension, command)
|
||||
SUPPORTED = (('ogg', 'normalize-ogg "%s"'), ('mp3', 'normalize-mp3 "%s"'))
|
||||
|
||||
#TODO: add setting to use normalize-audio instead of normalizie-mp3 for mp3 files if wanted
|
||||
# http://normalize.nongnu.org/README.html FAQ #5
|
||||
#MP3_CMD = 'normalize-audio "%s"'
|
||||
|
||||
CMDS_TO_TEST = ('normalize-ogg', 'normalize-mp3', 'normalize-audio',
|
||||
'lame', 'mpg123', 'oggenc', 'oggdec')
|
||||
|
||||
CONVERT_COMMANDS = {
|
||||
'ogg': 'normalize-ogg',
|
||||
'mp3': 'normalize-mp3',
|
||||
}
|
||||
|
||||
class gPodderExtension:
|
||||
def __init__(self, container):
|
||||
self.container = container
|
||||
|
||||
for cmd in CMDS_TO_TEST:
|
||||
program = shlex.split(cmd)[0]
|
||||
if not util.find_command(program):
|
||||
raise ImportError("Couldn't find program '%s'" % program)
|
||||
# Dependency check
|
||||
self.container.require_command('normalize-ogg')
|
||||
self.container.require_command('normalize-mp3')
|
||||
self.container.require_command('normalize-audio')
|
||||
|
||||
def on_load(self):
|
||||
logger.info('Extension "%s" is being loaded.' % __title__)
|
||||
|
@ -72,34 +63,29 @@ class gPodderExtension:
|
|||
return [(self.container.metadata.title, self._convert_episodes)]
|
||||
|
||||
def _convert_episode(self, episode):
|
||||
filename = episode.local_filename(create=False, check_only=True)
|
||||
if episode.file_type() != 'audio':
|
||||
return
|
||||
|
||||
filename = episode.local_filename(create=False)
|
||||
if filename is None:
|
||||
return
|
||||
|
||||
formats, commands = zip(*SUPPORTED)
|
||||
(basename, extension) = os.path.splitext(filename)
|
||||
extension = extension.lstrip('.').lower()
|
||||
if episode.file_type() == 'audio' and extension in formats:
|
||||
gpodder.user_extensions.on_notification_show("Normalizing", episode)
|
||||
basename, extension = os.path.splitext(filename)
|
||||
|
||||
cmd = commands[formats.index(extension)] % filename
|
||||
cmd = [CONVERT_COMMANDS.get(extension, 'normalize-audio'), filename]
|
||||
|
||||
# Prior to Python 2.7.3, this module (shlex) did not support Unicode input.
|
||||
cmd = util.sanitize_encoding(cmd)
|
||||
p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
stdout, stderr = p.communicate()
|
||||
|
||||
p = subprocess.Popen(shlex.split(cmd),
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stdout, stderr = p.communicate()
|
||||
|
||||
if p.returncode == 0:
|
||||
logger.info('normalize-audio processing successfull.')
|
||||
gpodder.user_extensions.on_notification_show("Normalizing finished successfully", episode)
|
||||
|
||||
else:
|
||||
logger.info('normalize-audio processing not successfull.')
|
||||
gpodder.user_extensions.on_notification_show("Normalizing finished not successfully", episode)
|
||||
logger.debug(stderr)
|
||||
if p.returncode == 0:
|
||||
logger.info('normalize-audio processing successful.')
|
||||
gpodder.user_extensions.on_notification_show(_('File normalized'),
|
||||
episode)
|
||||
else:
|
||||
logger.warn('normalize-audio failed: %s / %s', stdout, stderr)
|
||||
|
||||
def _convert_episodes(self, episodes):
|
||||
for episode in episodes:
|
||||
self._convert_episode(episode)
|
||||
|
||||
|
|
|
@ -45,10 +45,8 @@ else:
|
|||
|
||||
def on_load(self):
|
||||
pynotify.init('gPodder')
|
||||
logger.info('PyNotify initialized.')
|
||||
|
||||
def on_unload(self):
|
||||
logger.info('Uninitializing PyNotify.')
|
||||
pynotify.uninit()
|
||||
|
||||
def on_notification_show(self, title, message):
|
||||
|
|
|
@ -13,34 +13,38 @@ logger = logging.getLogger(__name__)
|
|||
|
||||
_ = gpodder.gettext
|
||||
|
||||
__title__ = _('Rename after download')
|
||||
__description__ = _('rename files after download based on the episode title')
|
||||
__author__ = 'Bernd Schlapsi <brot@gmx.info>'
|
||||
__title__ = _('Rename episodes after download')
|
||||
__description__ = _('Rename episodes to "<Episode Title>.<ext>" on download')
|
||||
__author__ = 'Bernd Schlapsi <brot@gmx.info>, Thomas Perl <thp@gpodder.org>'
|
||||
|
||||
|
||||
class gPodderExtension:
|
||||
def __init__(self, container):
|
||||
self.container = container
|
||||
|
||||
def on_load(self):
|
||||
logger.info('Extension "%s" is being loaded.' % __title__)
|
||||
|
||||
def on_unload(self):
|
||||
logger.info('Extension "%s" is being unloaded.' % __title__)
|
||||
|
||||
def on_episode_downloaded(self, episode):
|
||||
current_filename = episode.local_filename(create=False)
|
||||
|
||||
new_filename = self.rename_file(current_filename, episode.title)
|
||||
logger.info('Renaming %s -> %s:', current_filename, new_filename)
|
||||
new_filename = self.make_filename(current_filename, episode.title)
|
||||
|
||||
os.rename(current_filename, new_filename)
|
||||
util.rename_episode_file(episode, new_filename)
|
||||
if new_filename != current_filename:
|
||||
logger.info('Renaming: %s -> %s', current_filename, new_filename)
|
||||
os.rename(current_filename, new_filename)
|
||||
util.rename_episode_file(episode, new_filename)
|
||||
|
||||
def rename_file(self, current_filename, title):
|
||||
def make_filename(self, current_filename, title):
|
||||
dirname = os.path.dirname(current_filename)
|
||||
filename = os.path.basename(current_filename)
|
||||
basename, ext = os.path.splitext(filename)
|
||||
|
||||
new_filename = util.sanitize_encoding(title) + ext
|
||||
return os.path.join(dirname, new_filename)
|
||||
new_basename = util.sanitize_encoding(title) + ext
|
||||
new_filename = os.path.join(dirname, new_basename)
|
||||
|
||||
if new_filename == current_filename:
|
||||
return current_filename
|
||||
|
||||
for filename in util.generate_names(new_filename):
|
||||
# Avoid filename collisions
|
||||
if not os.path.exists(filename):
|
||||
return filename
|
||||
|
||||
|
|
|
@ -30,75 +30,67 @@ import gpodder
|
|||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
try:
|
||||
from mutagen.oggvorbis import OggVorbis
|
||||
except:
|
||||
logger.error( '(remove ogg cover extension) Could not find mutagen')
|
||||
from mutagen.oggvorbis import OggVorbis
|
||||
|
||||
_ = gpodder.gettext
|
||||
|
||||
__title__ = _('Remove Coverart from OGG')
|
||||
__title__ = _('Remove cover art from OGG files')
|
||||
__description__ = _('removes coverart from all downloaded ogg files')
|
||||
__author__ = 'Bernd Schlapsi <brot@gmx.info>'
|
||||
|
||||
|
||||
DefaultConfig = {
|
||||
'extensions': {
|
||||
'rm_ogg_cover': {
|
||||
'context_menu': True,
|
||||
}
|
||||
}
|
||||
'context_menu': True, # Show item in context menu
|
||||
}
|
||||
|
||||
|
||||
class gPodderExtension:
|
||||
def __init__(self, container):
|
||||
self.container = container
|
||||
|
||||
def on_load(self):
|
||||
logger.info('Extension "%s" is being loaded.' % __title__)
|
||||
|
||||
def on_unload(self):
|
||||
logger.info('Extension "%s" is being unloaded.' % __title__)
|
||||
self.config = self.container.config
|
||||
|
||||
def on_episode_downloaded(self, episode):
|
||||
self.rm_ogg_cover(episode)
|
||||
|
||||
def on_episodes_context_menu(self, episodes):
|
||||
if not self.container.config.context_menu:
|
||||
if not self.config.context_menu:
|
||||
return None
|
||||
|
||||
if 'audio/ogg' not in [e.mime_type for e in episodes
|
||||
if e.mime_type is not None and e.file_exists()]:
|
||||
return None
|
||||
|
||||
return [(self.container.metadata.title, self._rm_ogg_covers)]
|
||||
return [(_('Remove cover art'), self._rm_ogg_covers)]
|
||||
|
||||
def _rm_ogg_covers(self, episodes):
|
||||
for episode in episodes:
|
||||
self.rm_ogg_cover(episode)
|
||||
|
||||
def rm_ogg_cover(self, episode):
|
||||
filename = episode.local_filename(create=False, check_only=True)
|
||||
filename = episode.local_filename(create=False)
|
||||
if filename is None:
|
||||
return
|
||||
|
||||
(basename, extension) = os.path.splitext(filename)
|
||||
if episode.file_type() == 'audio' and extension.lower().endswith('ogg'):
|
||||
logger.info(u'trying to remove cover from %s' % filename)
|
||||
basename, extension = os.path.splitext(filename)
|
||||
|
||||
if episode.file_type() != 'audio':
|
||||
return
|
||||
|
||||
if extension.lower() != '.ogg'):
|
||||
return
|
||||
|
||||
try:
|
||||
ogg = OggVorbis(filename)
|
||||
|
||||
found = False
|
||||
for key in ogg.keys():
|
||||
if key.startswith('cover'):
|
||||
found = True
|
||||
ogg.pop(key)
|
||||
|
||||
try:
|
||||
ogg = OggVorbis(filename)
|
||||
for key in ogg.keys():
|
||||
if key.startswith('cover'):
|
||||
found = True
|
||||
ogg.pop(key)
|
||||
if found:
|
||||
logger.info('Removed cover art from OGG file: %s', filename)
|
||||
ogg.save()
|
||||
except Exception, e:
|
||||
logger.warn('Failed to remove OGG cover: %s', e, exc_info=True)
|
||||
|
||||
if found:
|
||||
logger.info(u'removed cover from the ogg file successfully')
|
||||
ogg.save()
|
||||
else:
|
||||
logger.info(u'there was no cover to remove in the ogg file')
|
||||
except:
|
||||
None
|
||||
|
|
|
@ -23,23 +23,19 @@ logger = logging.getLogger(__name__)
|
|||
|
||||
_ = gpodder.gettext
|
||||
|
||||
__title__ = _('Convert to MP4')
|
||||
__description__ = _('Converts Files to MP4 to use on Rockbox devices')
|
||||
__author__ = 'Guy Sheffer <guysoft at gmail.com>, Thomas Perl <thp@gpodder.org>, Bernd Schlapsi <brot@gmx.info>'
|
||||
__title__ = _('Convert video files to MP4 for Rockbox')
|
||||
__description__ = _('Converts all videos to a Rockbox-compatible format')
|
||||
__author__ = 'Guy Sheffer <guysoft@gmail.com>, Thomas Perl <thp@gpodder.org>, Bernd Schlapsi <brot@gmx.info>'
|
||||
|
||||
|
||||
DefaultConfig = {
|
||||
'extensions': {
|
||||
'rockbox_convert2mp4': {
|
||||
"device_height": 176.0,
|
||||
"device_width": 224.0,
|
||||
"ffmpeg_options": u'-vcodec mpeg2video -b 500k -ab 192k -ac 2 -ar 44100 -acodec libmp3lame',
|
||||
}
|
||||
}
|
||||
'device_height': 176.0,
|
||||
'device_width': 224.0,
|
||||
'ffmpeg_options': '-vcodec mpeg2video -b 500k -ab 192k -ac 2 -ar 44100 -acodec libmp3lame',
|
||||
}
|
||||
|
||||
ROCKBOX_EXTENTION = "mpg"
|
||||
EXTENTIONS_TO_CONVERT = ['.mp4',"." + ROCKBOX_EXTENTION]
|
||||
ROCKBOX_EXTENSION = "mpg"
|
||||
EXTENTIONS_TO_CONVERT = ['.mp4',"." + ROCKBOX_EXTENSION]
|
||||
FFMPEG_CMD = 'ffmpeg -y -i "%(from)s" -s %(width)sx%(height)s %(options)s "%(to)s"'
|
||||
|
||||
|
||||
|
@ -79,10 +75,10 @@ class gPodderExtension:
|
|||
logger.info("Ignore file with file-extension %s." % ext)
|
||||
return None
|
||||
|
||||
if filename.endswith(ROCKBOX_EXTENTION):
|
||||
new_filename = "%s-convert.%s" % (basename, ROCKBOX_EXTENTION)
|
||||
if filename.endswith(ROCKBOX_EXTENSION):
|
||||
new_filename = "%s-convert.%s" % (basename, ROCKBOX_EXTENSION)
|
||||
else:
|
||||
new_filename = "%s.%s" % (basename, ROCKBOX_EXTENTION)
|
||||
new_filename = "%s.%s" % (basename, ROCKBOX_EXTENSION)
|
||||
return os.path.join(dirname, new_filename)
|
||||
|
||||
|
||||
|
|
|
@ -40,18 +40,14 @@ except:
|
|||
|
||||
_ = gpodder.gettext
|
||||
|
||||
__title__ = _('Tagging')
|
||||
__description__ = _('adds episode title and podcast title to the audio file')
|
||||
__title__ = _('Tag downloaded files using Mutagen')
|
||||
__description__ = _('Add episode and podcast titles to MP3/OGG tags')
|
||||
__author__ = 'Bernd Schlapsi <brot@gmx.info>'
|
||||
|
||||
|
||||
DefaultConfig = {
|
||||
'extensions': {
|
||||
'tagging': {
|
||||
"strip_album_from_title": True,
|
||||
"genre_tag": u'Podcast',
|
||||
}
|
||||
}
|
||||
'strip_album_from_title': True,
|
||||
'genre_tag': 'Podcast',
|
||||
}
|
||||
|
||||
|
||||
|
@ -59,12 +55,6 @@ class gPodderExtension:
|
|||
def __init__(self, container):
|
||||
self.container = container
|
||||
|
||||
def on_load(self):
|
||||
logger.info('Extension "%s" is being loaded.' % __title__)
|
||||
|
||||
def on_unload(self):
|
||||
logger.info('Extension "%s" is being unloaded.' % __title__)
|
||||
|
||||
def on_episode_downloaded(self, episode):
|
||||
# exit if mutagen is not installed
|
||||
if not mutagen_installed:
|
||||
|
|
|
@ -45,11 +45,7 @@ __author__ = 'Bernd Schlapsi <brot@gmx.info>'
|
|||
|
||||
|
||||
DefaultConfig = {
|
||||
'extensions': {
|
||||
'tfh_shownotes': {
|
||||
'context_menu': True,
|
||||
}
|
||||
}
|
||||
'context_menu': True,
|
||||
}
|
||||
|
||||
TFH_TITLE = 'Tin Foil Hat'
|
||||
|
|
|
@ -130,6 +130,7 @@ class ExtensionMetadata(object):
|
|||
uis = filter(None, [x.strip() for x in self.only_for.split(',')])
|
||||
return any(getattr(gpodder.ui, ui.lower(), False) for ui in uis)
|
||||
|
||||
class MissingDependency(Exception): pass
|
||||
|
||||
class ExtensionContainer(object):
|
||||
"""An extension container wraps one extension module"""
|
||||
|
@ -147,6 +148,12 @@ class ExtensionContainer(object):
|
|||
self.parameters = None
|
||||
self.metadata = ExtensionMetadata(self, self._load_metadata(filename))
|
||||
|
||||
def require_command(self, command):
|
||||
result = util.find_command(command)
|
||||
if result is None:
|
||||
raise MissingDependency(command)
|
||||
return result
|
||||
|
||||
def _load_metadata(self, filename):
|
||||
if not filename or not os.path.exists(filename):
|
||||
return {}
|
||||
|
@ -204,7 +211,12 @@ class ExtensionContainer(object):
|
|||
util.delete_file(self.filename + 'c')
|
||||
|
||||
self.default_config = getattr(module_file, 'DefaultConfig', {})
|
||||
self.manager.core.config.register_defaults(self.default_config)
|
||||
if self.default_config:
|
||||
self.manager.core.config.register_defaults({
|
||||
'extensions': {
|
||||
self.name: self.default_config,
|
||||
}
|
||||
})
|
||||
self.config = getattr(self.manager.core.config.extensions, self.name)
|
||||
|
||||
self.module = module_file.gPodderExtension(self)
|
||||
|
|
Loading…
Reference in New Issue