Use dict-based format strings for numbers (bug 1165)
[gpodder.git] / bin / gpodder
blob55c8c438f898219b8ea263bb249ef920f31f36c3
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
5 # gPodder - A media aggregator and podcast client
6 # Copyright (c) 2005-2010 Thomas Perl and the gPodder Team
8 # gPodder is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 3 of the License, or
11 # (at your option) any later version.
13 # gPodder is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this program. If not, see <http://www.gnu.org/licenses/>.
22 """
23 gPodder enables you to subscribe to RSS feeds and download
24 podcast episodes from these feeds.
26 Downloaded podcasts can either be synchronized to portable
27 MP3 players (including iPods) or played back on the user's
28 desktop.
30 The Maemo 4 and Maemo 5 environments will be automatically
31 detected, and a suitable UI will be used. You can override
32 this behaviour with the --maemo and --fremantle switches.
34 See gpo(1) for the command-line interface.
35 """
37 import sys
38 import os
39 import os.path
40 import platform
42 import gettext
44 import subprocess
46 try:
47 import dbus
48 import dbus.glib
49 have_dbus = True
50 except ImportError:
51 print >>sys.stderr, """
52 Warning: python-dbus not found. Disabling D-Bus support.
53 """
54 have_dbus = False
56 from optparse import OptionParser
58 if __name__ == '__main__':
59 # Paths to important files
60 gpodder_script = sys.argv[0]
61 while os.path.islink(gpodder_script):
62 gpodder_script = os.readlink(gpodder_script)
63 gpodder_dir = os.path.join(os.path.dirname(gpodder_script), '..')
64 prefix = os.path.abspath(os.path.normpath(gpodder_dir))
66 src_dir = os.path.join(prefix, 'src')
67 data_dir = os.path.join(prefix, 'data')
68 locale_dir = os.path.join(prefix, 'share', 'locale')
69 ui_folder = os.path.join(prefix, 'share', 'gpodder', 'ui')
70 credits_file = os.path.join(prefix, 'share', 'gpodder', 'credits.txt')
71 images_folder = os.path.join(prefix, 'share', 'gpodder')
72 icon_file = os.path.join(prefix, 'share', 'icons', 'hicolor', 'scalable', 'apps', 'gpodder.svg')
74 # The existence of this file tells us we're running on Maemo
75 maemo_file = os.path.join(prefix, 'share', 'applications', 'hildon', 'gpodder.desktop')
77 if os.path.exists(src_dir) and os.path.exists(data_dir) and \
78 not prefix.startswith('/usr'):
79 # Run gPodder from local source folder (not installed)
80 print >>sys.stderr, 'Using modules from', src_dir
81 sys.path.insert(0, src_dir)
82 print >>sys.stderr, 'Using resources from', data_dir
83 locale_dir = os.path.join(data_dir, 'locale')
84 ui_folder = os.path.join(data_dir, 'ui')
85 credits_file = os.path.join(data_dir, 'credits.txt')
86 images_folder = os.path.join(data_dir, 'images')
87 icon_file = os.path.join(data_dir, 'gpodder.svg')
89 # on Mac OS X, read from the defaults database the locale of the user
90 if platform.system() == 'Darwin' and 'LANG' not in os.environ:
91 locale_cmd = ('defaults', 'read', 'NSGlobalDomain', 'AppleLocale')
92 process = subprocess.Popen(locale_cmd, stdout=subprocess.PIPE)
93 output, error_output = process.communicate()
94 # the output is a string like 'fr_FR', and we need 'fr_FR.utf-8'
95 user_locale = output.strip() + '.UTF-8'
96 os.environ['LANG'] = user_locale
97 print >>sys.stderr, 'Setting locale to', user_locale
99 # Set up the path to translation files
100 gettext.bindtextdomain('gpodder', locale_dir)
102 import gpodder
104 # Enable i18n for gPodder translations
105 _ = gpodder.gettext
107 # Set up paths to folder with GtkBuilder files and gpodder.svg
108 gpodder.ui_folders.append(ui_folder)
109 gpodder.credits_file = credits_file
110 gpodder.images_folder = images_folder
111 gpodder.icon_file = icon_file
113 s_usage = 'usage: %%prog [options]\n\n%s' % ( __doc__.strip() )
114 s_version = '%%prog %s' % ( gpodder.__version__ )
116 parser = OptionParser( usage = s_usage, version = s_version)
118 parser.add_option("-v", "--verbose",
119 action="store_true", dest="verbose", default=False,
120 help=_("Print debugging output to stdout"))
122 parser.add_option("-m", "--maemo",
123 action="store_true", dest="diablo", default=False,
124 help=_("Force using the Maemo 4 user interface"))
126 parser.add_option("-f", "--fremantle",
127 action="store_true", dest="fremantle", default=False,
128 help=_("Force using the Maemo 5 user interface"))
130 parser.add_option('-s', '--subscribe', dest='subscribe', metavar='URL',
131 help=_('Subscribe to the given URL'))
133 # On Mac OS X, support the "psn" parameter for compatibility (bug 939)
134 if sys.platform == 'darwin':
135 parser.add_option('-p', '--psn', dest='macpsn', metavar='PSN',
136 help=_('Mac OS X application process number'))
138 (options, args) = parser.parse_args(sys.argv)
140 # Detect if we are running on Maemo 5 and if it's the case, do
141 # force the "fremantle" option on automatically, so that clueless
142 # users won't be reporting bogus bugs if they try to start gPodder
143 # from the command line without the "--fremantle" switch :)
144 if not options.fremantle and not options.diablo:
145 try:
146 etc_issue = open('/etc/issue').read()
147 if 'Maemo 5' in etc_issue:
148 options.fremantle = True
149 print >>sys.stderr, 'Auto-detected: Maemo 5 (--fremantle)'
150 elif 'Internet Tablet OS: maemo Linux based OS2008' in etc_issue:
151 options.diablo = True
152 print >>sys.stderr, 'Auto-detected: Maemo OS2008 (--maemo)'
154 del etc_issue
155 except:
156 pass
158 if options.fremantle or options.diablo:
159 gpodder.icon_file = gpodder.icon_file.replace('.svg', '.png')
161 if options.fremantle:
162 gpodder.ui.fremantle = True
163 gpodder.ui_folders.insert(0, os.path.join(ui_folder, 'frmntl'))
164 elif options.diablo or os.path.exists(maemo_file):
165 gpodder.ui.diablo = True
166 gpodder.ui_folders.insert(0, os.path.join(ui_folder, 'maemo'))
167 else:
168 gpodder.ui.desktop = True
169 gpodder.ui_folders.insert(0, os.path.join(ui_folder, 'desktop'))
171 if options.verbose:
172 from gpodder.liblogger import enable_verbose
173 enable_verbose()
175 if have_dbus:
176 # Try to find an already-running instance of gPodder
177 session_bus = dbus.SessionBus()
179 # Obtain a reference to an existing instance; don't call get_object if
180 # such an instance doesn't exist as it *will* create a new instance
181 if session_bus.name_has_owner(gpodder.dbus_bus_name):
182 try:
183 remote_object = session_bus.get_object(gpodder.dbus_bus_name, \
184 gpodder.dbus_gui_object_path)
185 except dbus.exceptions.DBusException:
186 remote_object = None
187 else:
188 remote_object = None
189 else:
190 # No D-Bus available :/
191 remote_object = None
193 if remote_object is not None:
194 # An instance of GUI is already running
195 print >>sys.stderr, 'Existing instance running - activating via D-Bus.'
196 remote_object.show_gui_window(dbus_interface=gpodder.dbus_interface)
197 if options.subscribe:
198 remote_object.subscribe_to_url(options.subscribe)
199 else:
200 # gPodder is not yet running - create new instance
201 from gpodder import gui
203 # check if we have an X11 connection (but not on Windows)
204 if platform.system() != 'Windows' and \
205 not os.environ.get('DISPLAY', None):
206 print >>sys.stderr, 'Cannot start gPodder: $DISPLAY is not set.'
207 sys.exit(1)
209 if gpodder.ui.maemo:
210 # Reduce our nice value to zero if we're on Maemo to
211 # make the tablet not kill itself while updating feeds
212 if os.nice(0) < 0:
213 os.nice(-os.nice(0))
215 gui.main(options)