Initialize woodchuck using hooks, improve "gpo"
Instead of initializing woodchuck explicitly, let the hooks module know then the UI has been initialized, and provide some callbacks (that Woodchuck needs, but which could be used by other hook scripts) and the model.
This commit is contained in:
parent
25f1b0a267
commit
956ac7d9b1
46
bin/gpo
46
bin/gpo
|
@ -87,8 +87,6 @@ if os.path.exists(src_dir) and os.path.exists(data_dir) and \
|
|||
import gpodder
|
||||
_ = gpodder.gettext
|
||||
|
||||
from gpodder.plugins import woodchuck
|
||||
|
||||
# Platform detection (i.e. Maemo 5, etc..)
|
||||
gpodder.detect_platform()
|
||||
|
||||
|
@ -132,10 +130,17 @@ class gPodderCli(object):
|
|||
def __init__(self):
|
||||
self.client = api.PodcastClient()
|
||||
self._current_action = ''
|
||||
gpodder.user_hooks.on_ui_initialized(self.client.core.model,
|
||||
self.hooks_podcast_update_cb,
|
||||
self.hooks_episode_download_cb)
|
||||
|
||||
# Initialize Woodchuck so that we can register new podcasts,
|
||||
# etc., but don't request any callbacks.
|
||||
woodchuck.init(self.client.core.model)
|
||||
def hooks_podcast_update_cb(self, podcast):
|
||||
self._info(_('Podcast update requested by hooks.'))
|
||||
self._update_podcast(podcast)
|
||||
|
||||
def hooks_episode_download_cb(self, episode):
|
||||
self._info(_('Episode download requested by hooks.'))
|
||||
self._download_episode(episode)
|
||||
|
||||
def _start_action(self, msg, *args):
|
||||
line = msg % args
|
||||
|
@ -265,24 +270,22 @@ class gPodderCli(object):
|
|||
|
||||
return True
|
||||
|
||||
def _update_podcast(self, podcast):
|
||||
self._start_action('Updating %s', podcast.title)
|
||||
try:
|
||||
podcast.update()
|
||||
self._finish_action()
|
||||
except Exception, e:
|
||||
self._finish_action(False)
|
||||
|
||||
@FirstArgumentIsPodcastURL
|
||||
def update(self, url=None):
|
||||
for podcast in self.client.get_podcasts():
|
||||
if url is None and podcast.update_enabled():
|
||||
self._start_action('Updating %s', podcast.title)
|
||||
try:
|
||||
podcast.update()
|
||||
self._finish_action()
|
||||
except Exception, e:
|
||||
self._finish_action(False)
|
||||
self._update_podcast(podcast)
|
||||
elif podcast.url == url:
|
||||
# Don't need to check for update_enabled()
|
||||
self._start_action('Updating %s', podcast.title)
|
||||
try:
|
||||
podcast.update()
|
||||
self._finish_action()
|
||||
except Exception, e:
|
||||
self._finish_action(False)
|
||||
self._update_podcast(podcast)
|
||||
|
||||
return True
|
||||
|
||||
|
@ -317,6 +320,11 @@ class gPodderCli(object):
|
|||
self.client.commit()
|
||||
return True
|
||||
|
||||
def _download_episode(self, episode):
|
||||
self._start_action('Downloading %s', episode.title)
|
||||
episode.download(self._update_action)
|
||||
self._finish_action()
|
||||
|
||||
@FirstArgumentIsPodcastURL
|
||||
def download(self, url=None):
|
||||
count = 0
|
||||
|
@ -328,9 +336,7 @@ class gPodderCli(object):
|
|||
if not podcast_printed:
|
||||
print inblue(podcast.title)
|
||||
podcast_printed = True
|
||||
self._start_action('Downloading %s', episode.title)
|
||||
episode.download(self._update_action)
|
||||
self._finish_action()
|
||||
self._download_episode(episode)
|
||||
count += 1
|
||||
|
||||
print count, 'episodes downloaded.'
|
||||
|
|
|
@ -38,12 +38,12 @@ class Core(object):
|
|||
# Initialize the gPodder home directory
|
||||
util.make_directory(gpodder.home)
|
||||
|
||||
# Load installed/configured plugins
|
||||
gpodder.load_plugins()
|
||||
|
||||
# Load hook modules and install the hook manager
|
||||
gpodder.user_hooks = hooks.HookManager()
|
||||
|
||||
# Load installed/configured plugins
|
||||
gpodder.load_plugins()
|
||||
|
||||
# Open the database and configuration file
|
||||
self.db = database_class(gpodder.database_file)
|
||||
self.model = model_class(self.db)
|
||||
|
|
|
@ -51,7 +51,6 @@ from gpodder import download
|
|||
from gpodder import my
|
||||
from gpodder import youtube
|
||||
from gpodder import player
|
||||
from gpodder.plugins import woodchuck
|
||||
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -209,11 +208,9 @@ class gPodder(BuilderWidget, dbus.service.Object):
|
|||
self.active_channel = None
|
||||
self.channels = self.model.get_podcasts()
|
||||
|
||||
# Initialize woodchuck after a short timeout period
|
||||
gobject.timeout_add(1000, woodchuck.init,
|
||||
self.channels,
|
||||
self.woodchuck_channel_update_cb,
|
||||
self.woodchuck_episode_download_cb)
|
||||
gpodder.user_hooks.on_ui_initialized(self.model,
|
||||
self.hooks_podcast_update_cb,
|
||||
self.hooks_episode_download_cb)
|
||||
|
||||
# Check if the user has downloaded any podcast with an external program
|
||||
# and mark episodes as downloaded / move them away (bug 902)
|
||||
|
@ -3362,13 +3359,13 @@ class gPodder(BuilderWidget, dbus.service.Object):
|
|||
|
||||
return False
|
||||
|
||||
def woodchuck_channel_update_cb(self, channel):
|
||||
logger.debug('woodchuck_channel_update_cb(%s)', channel)
|
||||
self.update_feed_cache(channels=[channel],
|
||||
show_new_episodes_dialog=False)
|
||||
def hooks_podcast_update_cb(self, podcast):
|
||||
logger.debug('hooks_podcast_update_cb(%s)', podcast)
|
||||
self.update_feed_cache(channels=[podcast],
|
||||
show_new_episodes_dialog=False)
|
||||
|
||||
def woodchuck_episode_download_cb(self, episode):
|
||||
logger.debug('woodchuck_episode_download_cb(%s)', episode)
|
||||
def hooks_episode_download_cb(self, episode):
|
||||
logger.debug('hooks_episode_download_cb(%s)', episode)
|
||||
self.download_episode_list(episodes=[episode])
|
||||
|
||||
def main(options=None):
|
||||
|
|
|
@ -93,6 +93,15 @@ class HookManager(object):
|
|||
"""
|
||||
self.modules.append((None, obj))
|
||||
|
||||
def unregister_hooks(self, obj):
|
||||
"""
|
||||
Unregister a previously registered object.
|
||||
"""
|
||||
if (None, obj) in self.modules:
|
||||
self.modules.remove((None, obj))
|
||||
else:
|
||||
logger.warn('Unregistered hook which was not registered.')
|
||||
|
||||
def _load_module(self, filepath):
|
||||
"""Load a Python module by filename
|
||||
|
||||
|
@ -114,6 +123,17 @@ class HookManager(object):
|
|||
# the same function defined in them. If the handler functions here contain
|
||||
# any code, it will be called after all the hooks have been called.
|
||||
|
||||
@call_hooks
|
||||
def on_ui_initialized(self, model, update_podcast_callback,
|
||||
download_episode_callback):
|
||||
"""Called when the user interface is initialized.
|
||||
|
||||
@param model: A gpodder.model.Model instance
|
||||
@param update_podcast_callback: Function to update a podcast feed
|
||||
@param download_episode_callback: Function to download an episode
|
||||
"""
|
||||
pass
|
||||
|
||||
@call_hooks
|
||||
def on_podcast_subscribe(self, podcast):
|
||||
"""Called when the user subscribes to a new podcast feed.
|
||||
|
|
|
@ -878,6 +878,8 @@ class PodcastChannel(PodcastModelObject):
|
|||
|
||||
tmp.save()
|
||||
|
||||
gpodder.user_hooks.on_podcast_subscribe(tmp)
|
||||
|
||||
return tmp
|
||||
|
||||
def episode_factory(self, d):
|
||||
|
@ -1104,7 +1106,6 @@ class PodcastChannel(PodcastModelObject):
|
|||
self.db.commit()
|
||||
|
||||
def delete(self):
|
||||
gpodder.user_hooks.on_podcast_delete(self)
|
||||
self.db.delete_podcast(self)
|
||||
self.model._remove_podcast(self)
|
||||
|
||||
|
@ -1112,9 +1113,6 @@ class PodcastChannel(PodcastModelObject):
|
|||
if self.download_folder is None:
|
||||
self.get_save_dir()
|
||||
|
||||
if self.id is None:
|
||||
gpodder.user_hooks.on_podcast_subscribe(self)
|
||||
|
||||
gpodder.user_hooks.on_podcast_save(self)
|
||||
|
||||
self._clear_changes()
|
||||
|
@ -1268,10 +1266,10 @@ class Model(object):
|
|||
def _append_podcast(self, podcast):
|
||||
if podcast not in self.children:
|
||||
self.children.append(podcast)
|
||||
# XXX: Sort?
|
||||
|
||||
def _remove_podcast(self, podcast):
|
||||
self.children.remove(podcast)
|
||||
gpodder.user_hooks.on_podcast_delete(self)
|
||||
|
||||
def get_podcasts(self):
|
||||
def podcast_factory(dct, db):
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# gPodder - A media aggregator and podcast client
|
||||
# Copyright (c) 2005-2011 Thomas Perl and the gPodder Team
|
||||
# Copyright (c) 2011 Neal H. Walfield
|
||||
#
|
||||
# gPodder is free software; you can redistribute it and/or modify
|
||||
|
@ -454,39 +458,53 @@ def check_subscriptions():
|
|||
w.stream_unregister(id)
|
||||
yield
|
||||
|
||||
def init(model=None, podcast_update=None, episode_download=None):
|
||||
"""
|
||||
Connect to the woodchuck server and initialize any state.
|
||||
class WoodchuckLoader():
|
||||
def on_ui_initialized(self, model, update_podcast_callback,
|
||||
download_episode_callback):
|
||||
"""
|
||||
Connect to the woodchuck server and initialize any state.
|
||||
|
||||
model is an instance of the podcast model.
|
||||
model is an instance of the podcast model.
|
||||
|
||||
podcast_update is a function that is passed a single argument: the
|
||||
PodcastPodcast that should be updated.
|
||||
podcast_update is a function that is passed a single argument: the
|
||||
PodcastPodcast that should be updated.
|
||||
|
||||
episode_download is a function that is passed a single argument:
|
||||
the PodcastEpisode that should be downloaded.
|
||||
episode_download is a function that is passed a single argument:
|
||||
the PodcastEpisode that should be downloaded.
|
||||
|
||||
If podcast_update and episode_download are None, then Woodchuck
|
||||
upcalls will be disabled. In this case, you don't need to specify
|
||||
the list of podcasts. Just specify None.
|
||||
"""
|
||||
if not woodchuck_imported:
|
||||
return
|
||||
If podcast_update and episode_download are None, then Woodchuck
|
||||
upcalls will be disabled. In this case, you don't need to specify
|
||||
the list of podcasts. Just specify None.
|
||||
"""
|
||||
logger.info('Got on_ui_initialized. Setting up woodchuck..')
|
||||
|
||||
global _main_thread
|
||||
_main_thread = threading.currentThread()
|
||||
global woodchuck_loader
|
||||
gpodder.user_hooks.unregister_hooks(woodchuck_loader)
|
||||
woodchuck_loader = None
|
||||
|
||||
global w
|
||||
w = mywoodchuck(model, podcast_update, episode_download)
|
||||
if not woodchuck_imported:
|
||||
return
|
||||
|
||||
if not w.available():
|
||||
logger.info(
|
||||
"Woodchuck support disabled: unable to contact Woodchuck server.")
|
||||
print "Woodchuck support disabled: unable to contact Woodchuck server."
|
||||
return
|
||||
global _main_thread
|
||||
_main_thread = threading.currentThread()
|
||||
|
||||
logger.info("Woodchuck appears to be available.")
|
||||
global woodchuck_instance
|
||||
woodchuck_instance = mywoodchuck(model,
|
||||
update_podcast_callback,
|
||||
download_episode_callback)
|
||||
|
||||
gpodder.user_hooks.register_hooks(w)
|
||||
if not woodchuck_instance.available():
|
||||
logger.warn('Unable to contact Woodchuck server. Disabling.')
|
||||
return
|
||||
|
||||
logger.info('Connected to Woodchuck server.')
|
||||
|
||||
gpodder.user_hooks.register_hooks(woodchuck_instance)
|
||||
|
||||
idle_add(check_subscriptions)
|
||||
|
||||
woodchuck_loader = WoodchuckLoader()
|
||||
woodchuck_instance = None
|
||||
|
||||
gpodder.user_hooks.register_hooks(woodchuck_loader)
|
||||
|
||||
idle_add(check_subscriptions)
|
||||
|
|
|
@ -44,8 +44,6 @@ from gpodder.qmlui import model
|
|||
from gpodder.qmlui import helper
|
||||
from gpodder.qmlui import images
|
||||
|
||||
from gpodder.plugins import woodchuck
|
||||
|
||||
import logging
|
||||
logger = logging.getLogger("qmlui")
|
||||
|
||||
|
@ -418,6 +416,10 @@ class qtPodder(QObject):
|
|||
self.db = self.core.db
|
||||
self.model = self.core.model
|
||||
|
||||
gpodder.user_hooks.on_ui_initialized(self.model,
|
||||
self.hooks_podcast_update_cb,
|
||||
self.hooks_episode_download_cb)
|
||||
|
||||
self.view = DeclarativeView()
|
||||
self.view.closing.connect(self.on_quit)
|
||||
self.view.setResizeMode(QDeclarativeView.SizeRootObjectToView)
|
||||
|
@ -531,9 +533,6 @@ class qtPodder(QObject):
|
|||
podcasts = map(model.QPodcast, self.model.get_podcasts())
|
||||
self.podcast_model.set_podcasts(self.db, podcasts)
|
||||
|
||||
woodchuck.init(self.model, self.woodchuck_podcast_update_cb,
|
||||
self.woodchuck_episode_download_cb)
|
||||
|
||||
def wrap_episode(self, podcast, episode):
|
||||
try:
|
||||
return self.active_episode_wrappers[episode.id]
|
||||
|
@ -566,27 +565,24 @@ class qtPodder(QObject):
|
|||
return podcasts[0]
|
||||
return None
|
||||
|
||||
def woodchuck_podcast_update_cb(self, podcast):
|
||||
logger.debug("woodchuck_podcast_update_cb(%s)", str(podcast))
|
||||
def hooks_podcast_update_cb(self, podcast):
|
||||
logger.debug('hooks_podcast_update_cb(%s)', podcast)
|
||||
try:
|
||||
qpodcast = self.podcast_to_qpodcast(podcast)
|
||||
if qpodcast is not None:
|
||||
qpodcast.qupdate(
|
||||
finished_callback=self.controller.update_subset_stats)
|
||||
except Exception, e:
|
||||
logger.exception("woodchuck_podcast_update_cb(%s): %s",
|
||||
str(podcast), str(e))
|
||||
logger.exception('hooks_podcast_update_cb(%s): %s', podcast, e)
|
||||
|
||||
def woodchuck_episode_download_cb(self, episode):
|
||||
logger.debug("woodchuck_episode_download_cb(%s: %s)",
|
||||
str(episode), type(episode))
|
||||
def hooks_episode_download_cb(self, episode):
|
||||
logger.debug('hooks_episode_download_cb(%s)', episode)
|
||||
try:
|
||||
qpodcast = self.podcast_to_qpodcast(episode.channel)
|
||||
qepisode = self.wrap_episode(qpodcast, episode)
|
||||
qepisode.qdownload(self.config, self.controller.update_subset_stats)
|
||||
self.controller.downloadEpisode(qepisode)
|
||||
except Exception, e:
|
||||
logger.exception("woodchuck_episode_download_cb(%s): %s",
|
||||
str(episode), str(e))
|
||||
logger.exception('hooks_episode_download_cb(%s): %s', episode, e)
|
||||
|
||||
def main(args):
|
||||
gui = qtPodder(args, core.Core())
|
||||
|
|
Loading…
Reference in New Issue