gpodder/src/gpodder/dbusproxy.py

148 lines
5.3 KiB
Python

# -*- coding: utf-8 -*-
#
# gPodder - A media aggregator and podcast client
# Copyright (c) 2005-2018 The gPodder Team
#
# gPodder is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# gPodder is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# gpodder.dbusproxy - Expose Podcasts over D-Bus
# Based on a patch by Iwan van der Kleijn <iwanvanderkleyn@gmail.com>
# See also: http://gpodder.org/bug/699
import dbus
import dbus.service
import gpodder
from gpodder import util
def safe_str(txt):
if txt:
return txt.encode()
else:
return ''
def safe_first_line(txt):
txt = safe_str(txt)
lines = util.remove_html_tags(txt).strip().splitlines()
if not lines or lines[0] == '':
return ''
else:
return lines[0]
class DBusPodcastsProxy(dbus.service.Object):
""" Implements API accessible through D-Bus
Methods on DBusPodcastsProxy can be called by D-Bus clients. They implement
safe-guards to work safely over D-Bus while having type signatures applied
for parameter and return values.
"""
# DBusPodcastsProxy(lambda: self.channels, self.on_itemUpdate_activate(), self.playback_episodes, self.download_episode_list, bus_name)
def __init__(self, get_podcast_list,
check_for_updates, playback_episodes,
download_episodes, episode_from_uri,
bus_name):
self._get_podcasts = get_podcast_list
self._on_check_for_updates = check_for_updates
self._playback_episodes = playback_episodes
self._download_episodes = download_episodes
self._episode_from_uri = episode_from_uri
dbus.service.Object.__init__(self,
object_path=gpodder.dbus_podcasts_object_path,
bus_name=bus_name)
def _get_episode_refs(self, urls):
"""Get Episode instances associated with URLs"""
episodes = []
for p in self._get_podcasts():
for e in p.get_all_episodes():
if e.url in urls:
episodes.append(e)
return episodes
@dbus.service.method(dbus_interface=gpodder.dbus_podcasts, in_signature='', out_signature='a(ssss)')
def get_podcasts(self):
"""Get all podcasts in gPodder's subscription list"""
def podcast_to_tuple(podcast):
title = safe_str(podcast.title)
url = safe_str(podcast.url)
description = safe_first_line(podcast.description)
cover_file = ''
return (title, url, description, cover_file)
return [podcast_to_tuple(p) for p in self._get_podcasts()]
@dbus.service.method(dbus_interface=gpodder.dbus_podcasts, in_signature='s', out_signature='ss')
def get_episode_title(self, url):
episode = self._episode_from_uri(url)
if episode is not None:
return episode.title, episode.channel.title
return ('', '')
@dbus.service.method(dbus_interface=gpodder.dbus_podcasts, in_signature='s', out_signature='a(sssssbbb)')
def get_episodes(self, url):
"""Return all episodes of the podcast with the given URL"""
podcast = None
for channel in self._get_podcasts():
if channel.url == url:
podcast = channel
break
if podcast is None:
return []
def episode_to_tuple(episode):
title = safe_str(episode.title)
url = safe_str(episode.url)
description = safe_first_line(episode._text_description)
filename = safe_str(episode.download_filename)
file_type = safe_str(episode.file_type())
is_new = (episode.state == gpodder.STATE_NORMAL and episode.is_new)
is_downloaded = episode.was_downloaded(and_exists=True)
is_deleted = (episode.state == gpodder.STATE_DELETED)
return (title, url, description, filename, file_type, is_new, is_downloaded, is_deleted)
return [episode_to_tuple(e) for e in podcast.get_all_episodes()]
@dbus.service.method(dbus_interface=gpodder.dbus_podcasts, in_signature='as', out_signature='(bs)')
def play_or_download_episode(self, urls):
"""Play (or download) a list of episodes given by URL"""
episodes = self._get_episode_refs(urls)
if not episodes:
return (0, 'No episodes found')
to_playback = [e for e in episodes if e.was_downloaded(and_exists=True)]
to_download = [e for e in episodes if e not in to_playback]
if to_playback:
self._playback_episodes(to_playback)
if to_download:
self._download_episodes(to_download)
return (1, 'Success')
@dbus.service.method(dbus_interface=gpodder.dbus_podcasts, in_signature='', out_signature='')
def check_for_updates(self):
"""Check for new episodes or offer subscriptions"""
self._on_check_for_updates()