Deprecate the old-style command-line interface

Add a interim "sync" command to the "gpo" utility
to replace all the functionality of the old "gpodder"
CLI parameters (which had a "--sync" switch).
This commit is contained in:
Thomas Perl 2009-08-13 21:03:01 +02:00
parent c854935fc9
commit 806c719c4b
4 changed files with 47 additions and 209 deletions

View file

@ -62,6 +62,7 @@
------------------------------- -------------------------------
device Show information about your device device Show information about your device
sync Synchronize downloaded episodes to device
Helper commands Helper commands
--------------- ---------------
@ -93,6 +94,8 @@ if os.path.exists(src_dir) and os.path.exists(data_dir) and \
import gpodder import gpodder
_ = gpodder.gettext _ = gpodder.gettext
# This is the command-line interface to gPodder
gpodder.interface = gpodder.CLI
# Use only the gPodder API here, so this serves both as an example # Use only the gPodder API here, so this serves both as an example
# and as a motivation to provide all functionality in the API :) # and as a motivation to provide all functionality in the API :)
@ -216,6 +219,9 @@ class gPodderCli(object):
print count, 'episodes downloaded.' print count, 'episodes downloaded.'
return True return True
def sync(self):
api.synchronize_device()
return True
# ------------------------------------------------------------------- # -------------------------------------------------------------------

View file

@ -21,10 +21,13 @@
""" """
gPodder enables you to subscribe to RSS feeds and download gPodder enables you to subscribe to RSS feeds and download
podcast episodes from these feeds. gPodder can operate in podcast episodes from these feeds.
GUI mode and in CLI mode. Downloaded podcasts can either
be synchronized to portable MP3 players (including iPods) Downloaded podcasts can either be synchronized to portable
or played back on the user's desktop. MP3 players (including iPods) or played back on the user's
desktop.
See gpo(1) for the command-line interface.
""" """
import sys import sys
@ -91,53 +94,17 @@ if __name__ == '__main__':
action="store_true", dest="verbose", default=False, action="store_true", dest="verbose", default=False,
help=_("Print debugging output to stdout")) help=_("Print debugging output to stdout"))
parser.add_option("-t", "--local",
action="store_true", dest="local", default=False,
help='Deprecated.')
parser.add_option("-m", "--maemo", parser.add_option("-m", "--maemo",
action="store_true", dest="maemo", default=False, action="store_true", dest="maemo", default=False,
help=_("Start the Maemo user interface of gPodder")) help=_("Start the Maemo user interface of gPodder"))
parser.add_option("-l", "--list",
action="store_true", dest="list", default=False,
help=_("List all channel subscriptions"))
parser.add_option("-r", "--run",
action="store_true", dest="run", default=False,
help=_("Update channel list, download new podcasts"))
parser.add_option("-u", "--update",
action="store_true", dest="update", default=False,
help=_("Update channel list and exit"))
parser.add_option("-s", "--sync",
action="store_true", dest="sync", default=False,
help=_("Synchronize channels to configured device"))
parser.add_option("-a", "--add", dest="add",
help=_("Subscribe to channel from URL"), metavar="URL")
parser.add_option("-d", "--delete", dest="delete",
help=_("Delete channel specified by URL"), metavar="URL")
parser.add_option("-S", "--stats",
action="store_true", dest="stats", default=False,
help=_("Get sync statistics"))
(options, args) = parser.parse_args(sys.argv) (options, args) = parser.parse_args(sys.argv)
if options.maemo: if options.maemo:
gpodder.interface = gpodder.MAEMO gpodder.interface = gpodder.MAEMO
elif options.list or options.run or options.update or \
options.sync or options.add or options.delete:
gpodder.interface = gpodder.CLI
else: else:
gpodder.interface = gpodder.GUI gpodder.interface = gpodder.GUI
if options.local:
print >>sys.stderr, 'Ignoring deprecated option --local.'
if options.verbose: if options.verbose:
from gpodder.liblogger import enable_verbose from gpodder.liblogger import enable_verbose
enable_verbose() enable_verbose()
@ -155,22 +122,7 @@ if __name__ == '__main__':
# No D-Bus available :/ # No D-Bus available :/
remote_object = None remote_object = None
from gpodder import console if remote_object is not None:
if options.list:
console.list_channels()
elif options.run:
console.run()
elif options.update:
console.update()
elif options.sync:
console.sync_device()
elif options.add:
console.add_channel( options.add)
elif options.delete:
console.del_channel( options.delete)
elif options.stats:
console.sync_stats()
elif remote_object is not None:
# An instance of GUI is already running # An instance of GUI is already running
remote_object.show_gui_window(dbus_interface=gpodder.dbus_interface) remote_object.show_gui_window(dbus_interface=gpodder.dbus_interface)
else: else:

View file

@ -30,6 +30,7 @@ from gpodder.libpodcasts import PodcastChannel
from gpodder.libgpodder import db from gpodder.libgpodder import db
from gpodder.libgpodder import gl from gpodder.libgpodder import gl
from gpodder import download from gpodder import download
from gpodder import console
class Podcast(object): class Podcast(object):
"""API interface of gPodder podcasts """API interface of gPodder podcasts
@ -152,6 +153,13 @@ def create_podcast(url, title=None):
return None return None
def synchronize_device():
"""Synchronize episodes to a device
WARNING: API subject to change.
"""
console.synchronize_device(db, gl.config)
def finish(): def finish():
"""Persist changed data to the database file """Persist changed data to the database file

View file

@ -17,170 +17,42 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
import gpodder
from gpodder import util
from gpodder import download
from gpodder import sync
from gpodder import opml
from gpodder.libgpodder import gl
from gpodder.libgpodder import db
from gpodder.liblogger import msg
from libpodcasts import PodcastChannel
import time
import urllib
import sys import sys
import gpodder
from gpodder import sync
from gpodder.libpodcasts import PodcastChannel
_ = gpodder.gettext _ = gpodder.gettext
def list_channels(): def synchronize_device(db, config):
for channel in PodcastChannel.load_from_db(db, gl.config.download_dir): device = sync.open_device(config)
msg('podcast', urllib.unquote(channel.url))
def add_channel( url):
callback_error = lambda s: msg( 'error', s)
url = util.normalize_feed_url(url)
channels = PodcastChannel.load_from_db(db, gl.config.download_dir)
if url in (c.url for c in channels):
msg('error', _('Already added: %s'), urllib.unquote(url))
return
try:
channel = PodcastChannel.load(db, url, create=True, max_episodes=gl.config.max_episodes_per_feed, download_dir=gl.config.download_dir)
except:
msg( 'error', _('Could not load feed from URL: %s'), urllib.unquote( url))
return
if channel:
channels.append(channel)
exporter = opml.Exporter(gpodder.subscription_file)
exporter.write(channels)
db.commit()
msg('add', urllib.unquote(url))
else:
msg('error', _('Could not add podcast.'))
def del_channel( url):
url = util.normalize_feed_url( url)
channels = PodcastChannel.load_from_db(db, gl.config.download_dir)
keep_channels = []
for channel in channels:
if channel.url == url:
msg( 'delete', urllib.unquote( channel.url))
channel.remove_downloaded()
channel.delete()
else:
keep_channels.append( channel)
if len(keep_channels) < len(channels):
exporter = opml.Exporter(gpodder.subscription_file)
exporter.write(keep_channels)
db.commit()
else:
msg('error', _('Could not remove podcast.'))
def update():
sys.stdout.write(_('Updating podcast feeds...'))
sys.stdout.flush()
channels = PodcastChannel.load_from_db(db, gl.config.download_dir)
for channel in channels:
channel.update(gl.config.max_episodes_per_feed)
print _('done.')
db.commit()
return channels
def run():
channels = update()
new_episodes = 0
for channel in channels:
for episode in channel.get_new_episodes():
msg( 'downloading', urllib.unquote( episode.url))
task = download.DownloadTask(episode)
task.status = download.DownloadTask.QUEUED
task.run()
if task.status == task.DONE:
msg('done', 'Finished.')
elif task.status == task.FAILED:
msg('failed', 'Download error: %s' % task.error_message)
new_episodes += 1
if new_episodes == 0:
print _('No new episodes to download.')
elif new_episodes == 1:
print _('Downloaded one new episode.')
else:
print _('Downloaded %d new episodes.') % new_episodes
db.commit()
def sync_device():
device = sync.open_device(gl.config)
if device is None: if device is None:
msg('error', _('No device configured. Please use the GUI.')) print >>sys.stderr, _('No device configured.')
return False return False
callback_status = lambda s: msg('status', '%s', s) def msg(s):
device.register('status', callback_status) print >>sys.stderr, s
callback_done = lambda: msg('done', _('Synchronization finished.'))
device.register('done', callback_done) device.register('status', msg)
callback_progress = lambda i, n: msg('progress', _('Synchronizing: %d of %d') % (i, n)) callback_progress = lambda i, n: msg(_('Synchronizing: %d of %d') % (i, n))
device.register('progress', callback_progress) device.register('progress', callback_progress)
if not device.open(): if device.open():
msg('error', _('Cannot open device.')) channels = [c for c in PodcastChannel.load_from_db(db, \
return False config.download_dir) if c.sync_to_devices]
for channel in PodcastChannel.load_from_db(db, gl.config.download_dir): for channel in channels:
if not channel.sync_to_devices: episodes = [e for e in channel.get_downloaded_episodes() \
msg('info', _('Skipping podcast: %s') % channel.title) if e.was_downloaded(and_exists=True)]
continue device.add_tracks(episodes)
episodes_to_sync = []
for episode in channel.get_all_episodes():
if episode.was_downloaded(and_exists=True):
episodes_to_sync.append(episode)
device.add_tracks(episodes_to_sync)
db.commit() db.commit()
if not device.close(): device.close()
msg('error', _('Cannot close device.')) print >>sys.stderr, _('Device synchronized successfully.')
return False return True
def sync_stats():
size = 0
device = sync.open_device(gl.config)
if device is None:
msg('error', _('No device configured. Please use the GUI.'))
return False
for channel in PodcastChannel.load_from_db(db, gl.config.download_dir):
if not channel.sync_to_devices:
continue
for episode in channel.get_all_episodes():
if episode.was_downloaded(and_exists=True):
episode.calculate_filesize()
size += episode.length
msg('info', _('Free space on device: %s') % (util.format_filesize(device.get_free_space())))
msg('info', _('Size of episodes to sync: %s') % util.format_filesize(size))
difference = device.get_free_space() - size
if difference < 0:
msg('error', _('Need to free at least %s more') % util.format_filesize(abs(difference)))
return False
else: else:
msg('info', _('Free space after sync: %s') % util.format_filesize(abs(difference))) print >>sys.stderr, _('Error: Cannot open device!')
if not device.close():
msg('error', _('Cannot close device.'))
return False return False
return True