Delay live search to be more responsive
[gpodder.git] / src / gpodder / api.py
blob8d0167eeca269c49b44f5624a89d54b481a32749
1 # -*- coding: utf-8 -*-
3 # gPodder - A media aggregator and podcast client
4 # Copyright (c) 2005-2010 Thomas Perl and the gPodder Team
6 # gPodder is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3 of the License, or
9 # (at your option) any later version.
11 # gPodder is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
20 """Public developer API for gPodder
22 This module provides a nicely documented API for developers to
23 integrate podcast functionality into their applications.
24 """
26 import gpodder
27 from gpodder import util
28 from gpodder import opml
29 from gpodder.model import PodcastChannel
30 from gpodder import download
31 from gpodder import console
33 from gpodder import dbsqlite
34 from gpodder import config
35 from gpodder import youtube
37 class Podcast(object):
38 """API interface of gPodder podcasts
40 This is the API specification of podcast objects that
41 are returned from API functions.
43 Public attributes:
44 title
45 url
46 """
47 def __init__(self, _podcast, _manager):
48 """For internal use only."""
49 self._podcast = _podcast
50 self._manager = _manager
51 self.title = self._podcast.title
52 self.url = self._podcast.url
54 def get_episodes(self):
55 """Get all episodes that belong to this podcast
57 Returns a list of Episode objects that belong to this podcast."""
58 return [Episode(e, self._manager) for e in self._podcast.get_all_episodes()]
60 def rename(self, title):
61 """Set a new title for this podcast
63 Sets a new title for this podcast that will be available
64 as the "title" attribute of this object."""
65 self._podcast.set_custom_title(title)
66 self.title = self._podcast.title
67 self._podcast.save()
69 def delete(self):
70 """Remove this podcast from the subscription list
72 Removes the subscription and all downloaded episodes.
73 """
74 self._podcast.remove_downloaded()
75 self._podcast.delete()
76 self._podcast = None
78 def update_enabled(self):
79 """Check if this feed has updates enabled
81 This function will return True if the podcast has feed
82 updates enabled. If the user pauses a subscription, the
83 feed updates are disabled, and the podcast should be
84 excluded from automatic updates.
85 """
86 return self._podcast.feed_update_enabled
88 def update(self):
89 """Updates this podcast by downloading the feed
91 Downloads the podcast feed (using the feed cache), and
92 adds new episodes and updated information to the database.
93 """
94 self._podcast.update(self._manager._config.max_episodes_per_feed, \
95 self._manager._config.mimetype_prefs)
97 def feed_update_status_msg(self):
98 """Show the feed update status
100 Display the feed update current status.
102 if self._podcast.feed_update_enabled:
103 return "enabled"
104 else:
105 return "disabled"
107 def feed_update_status(self):
108 """Return the feed update status
110 Return the feed update current status.
112 return self._podcast.feed_update_enabled
114 def disable(self):
115 """Toogle the feed update to disable
117 Change the feed update status to disable only if currently enable.
119 if self._podcast.feed_update_enabled:
120 self._podcast.feed_update_enabled = False
121 self._podcast.save()
123 def enable(self):
124 """Toogle the feed update to disable
126 Change the feed update status to disable only if currently enable.
128 if not self._podcast.feed_update_enabled:
129 self._podcast.feed_update_enabled = True
130 self._podcast.save()
132 class Episode(object):
133 """API interface of gPodder episodes
135 This is the API specification of episode objects that
136 are returned from API functions.
138 Public attributes:
139 title
141 is_new
142 is_downloaded
143 is_deleted
145 def __init__(self, _episode, _manager):
146 """For internal use only."""
147 self._episode = _episode
148 self._manager = _manager
149 self.title = self._episode.title
150 self.url = self._episode.url
151 self.is_new = (self._episode.state == gpodder.STATE_NORMAL and \
152 not self._episode.is_played)
153 self.is_downloaded = (self._episode.state == gpodder.STATE_DOWNLOADED)
154 self.is_deleted = (self._episode.state == gpodder.STATE_DELETED)
156 def download(self, callback=None):
157 """Downloads the episode to a local file
159 This will run the download in the same thread, so be sure
160 to call this method from a worker thread in case you have
161 a GUI running as a frontend."""
162 task = download.DownloadTask(self._episode, self._manager._config)
163 if callback is not None:
164 task.add_progress_callback(callback)
165 task.status = download.DownloadTask.QUEUED
166 task.run()
169 class PodcastClient(object):
170 def __init__(self):
171 """Create a new gPodder API instance
173 Connects to the database and loads the configuration.
175 util.make_directory(gpodder.home)
176 gpodder.load_plugins()
178 self._db = dbsqlite.Database(gpodder.database_file)
179 self._config = config.Config(gpodder.config_file)
181 def get_podcasts(self):
182 """Get a list of Podcast objects
184 Returns all the subscribed podcasts from gPodder.
186 return [Podcast(p, self) for p in PodcastChannel.load_from_db(self._db, self._config.download_dir)]
188 def get_podcast(self, url):
189 """Get a specific podcast by URL
191 Returns a podcast object for the URL or None if
192 the podcast has not been subscribed to.
194 url = util.normalize_feed_url(url)
195 channel = PodcastChannel.load(self._db, url, create=False, download_dir=self._config.download_dir)
196 if channel is None:
197 return None
198 else:
199 return Podcast(channel, self)
201 def create_podcast(self, url, title=None):
202 """Subscribe to a new podcast
204 Add a subscription for "url", optionally
205 renaming the podcast to "title" and return
206 the resulting object.
208 url = util.normalize_feed_url(url)
209 podcast = PodcastChannel.load(self._db, url, create=True, \
210 max_episodes=self._config.max_episodes_per_feed, \
211 download_dir=self._config.download_dir, \
212 allow_empty_feeds=self._config.allow_empty_feeds, \
213 mimetype_prefs=self._config.mimetype_prefs)
214 if podcast is not None:
215 if title is not None:
216 podcast.set_custom_title(title)
217 podcast.save()
218 return Podcast(podcast, self)
220 return None
222 def synchronize_device(self):
223 """Synchronize episodes to a device
225 WARNING: API subject to change.
227 console.synchronize_device(self._db, self._config)
229 def finish(self):
230 """Persist changed data to the database file
232 This has to be called from the API user after
233 data-changing actions have been carried out.
235 podcasts = PodcastChannel.load_from_db(self._db, self._config.download_dir)
236 exporter = opml.Exporter(gpodder.subscription_file)
237 exporter.write(podcasts)
238 self._db.commit()
239 return True
241 def youtube_url_resolver(self, url):
242 """Resolve the Youtube URL
244 WARNING: API subject to change.
246 yurl = youtube.get_real_download_url(url, \
247 self._config.youtube_preferred_fmt_id)
249 return yurl