Bump copyright year in readme.
[gpodder.git] / bin / gpodder
blob3e9b3ed92e9b63a83846dfb2e970fb59e777e6b1
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
5 # gPodder - A media aggregator and podcast client
6 # Copyright (c) 2005-2018 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 media feeds (RSS, Atom, YouTube,
24 Soundcloud and Vimeo) and automatically download new content.
26 This is the gPodder GUI. See gpo(1) for the command-line interface.
27 """
29 import gettext
30 import logging
31 import os
32 import os.path
33 import platform
34 import subprocess
35 import sys
36 from optparse import OptionGroup, OptionParser
38 logger = logging.getLogger(__name__)
40 try:
41     import dbus
42     from dbus.mainloop.glib import DBusGMainLoop
43     have_dbus = True
44 except ImportError:
45     print("""
46     Warning: python-dbus not found. Disabling D-Bus support.
47     """, file=sys.stderr)
48     have_dbus = False
51 def main():
52     # Paths to important files
53     gpodder_script = sys.argv[0]
54     gpodder_script = os.path.realpath(gpodder_script)
55     gpodder_dir = os.path.join(os.path.dirname(gpodder_script), '..')
56     prefix = os.path.abspath(os.path.normpath(gpodder_dir))
58     src_dir = os.path.join(prefix, 'src')
59     locale_dir = os.path.join(prefix, 'share', 'locale')
60     ui_folder = os.path.join(prefix, 'share', 'gpodder', 'ui')
61     images_folder = os.path.join(prefix, 'share', 'gpodder', 'images')
62     icon_file = os.path.join(prefix, 'share', 'icons', 'hicolor', 'scalable', 'apps', 'gpodder.svg')
64     if os.path.exists(os.path.join(src_dir, 'gpodder', '__init__.py')):
65         # Run gPodder from local source folder (not installed)
66         sys.path.insert(0, src_dir)
68     # on Mac OS X, read from the defaults database the locale of the user
69     if platform.system() == 'Darwin' and 'LANG' not in os.environ:
70         locale_cmd = ('defaults', 'read', 'NSGlobalDomain', 'AppleLocale')
71         process = subprocess.Popen(locale_cmd, stdout=subprocess.PIPE)
72         output, error_output = process.communicate()
73         # the output is a string like 'fr_FR', and we need 'fr_FR.utf-8'
74         user_locale = output.decode('utf-8').strip() + '.UTF-8'
75         os.environ['LANG'] = user_locale
76         print('Setting locale to', user_locale, file=sys.stderr)
78     # Set up the path to translation files
79     gettext.bindtextdomain('gpodder', locale_dir)
81     import gpodder  # isort:skip
83     gpodder.prefix = prefix
85     # Package managers can install the empty file {prefix}/share/gpodder/no-update-check to disable update checks
86     gpodder.no_update_check_file = os.path.join(prefix, 'share', 'gpodder', 'no-update-check')
88     # Enable i18n for gPodder translations
89     _ = gpodder.gettext
91     # Set up paths to folder with GtkBuilder files and gpodder.svg
92     gpodder.ui_folders.append(ui_folder)
93     gpodder.images_folder = images_folder
94     gpodder.icon_file = icon_file
96     s_usage = 'usage: %%prog [options]\n\n%s' % (__doc__.strip())
97     s_version = '%%prog %s' % (gpodder.__version__)
99     parser = OptionParser(usage=s_usage, version=s_version)
101     grp_subscriptions = OptionGroup(parser, "Subscriptions")
102     parser.add_option_group(grp_subscriptions)
104     grp_subscriptions.add_option('-s', '--subscribe', dest='subscribe',
105                                  metavar='URL',
106                                  help=_('subscribe to the feed at URL'))
108     grp_logging = OptionGroup(parser, "Logging")
109     parser.add_option_group(grp_logging)
111     grp_logging.add_option("-v", "--verbose",
112                            action="store_true", dest="verbose", default=False,
113                            help=_("print logging output on the console"))
115     grp_logging.add_option("-q", "--quiet",
116                            action="store_true", dest="quiet", default=False,
117                            help=_("reduce warnings on the console"))
119     grp_advanced = OptionGroup(parser, "Advanced")
120     parser.add_option_group(grp_advanced)
122     grp_advanced.add_option("--close-after-startup", action="store_true",
123                             help=_("exit once started up (for profiling)"))
125     # On Mac OS X, support the "psn" parameter for compatibility (bug 939)
126     if gpodder.ui.osx:
127         grp_advanced.add_option('-p', '--psn', dest='macpsn', metavar='PSN',
128                                 help=_('Mac OS X application process number'))
130     options, args = parser.parse_args(sys.argv)
132     gpodder.ui.gtk = True
133     gpodder.ui.python3 = True
135     desktop_session = os.environ.get('DESKTOP_SESSION', 'unknown').lower()
136     xdg_current_desktop = os.environ.get('XDG_CURRENT_DESKTOP', 'unknown').lower()
137     gpodder.ui.unity = (desktop_session in ('ubuntu', 'ubuntu-2d', 'unity')
138                         and xdg_current_desktop in ('unity', 'unity:unity7:ubuntu'))
140     from gpodder import log
141     log.setup(options.verbose, options.quiet)
143     if (not (gpodder.ui.win32 or gpodder.ui.osx) and
144             os.environ.get('DISPLAY', '') == '' and
145             os.environ.get('WAYLAND_DISPLAY', '') == ''):
146         logger.error('Cannot start gPodder: $DISPLAY or $WAYLAND_DISPLAY is not set.')
147         sys.exit(1)
149     if have_dbus:
150         # Try to find an already-running instance of gPodder
151         session_bus = dbus.SessionBus()
153         # Obtain a reference to an existing instance; don't call get_object if
154         # such an instance doesn't exist as it *will* create a new instance
155         if session_bus.name_has_owner(gpodder.dbus_bus_name):
156             try:
157                 remote_object = session_bus.get_object(
158                     gpodder.dbus_bus_name,
159                     gpodder.dbus_gui_object_path)
161                 # An instance of GUI is already running
162                 logger.info('Activating existing instance via D-Bus.')
163                 remote_object.show_gui_window(
164                     dbus_interface=gpodder.dbus_interface)
166                 if options.subscribe:
167                     remote_object.subscribe_to_url(options.subscribe)
169                 return
170             except dbus.exceptions.DBusException as dbus_exception:
171                 logger.info('Cannot connect to remote object.', exc_info=True)
173     if gpodder.ui.gtk:
174         from gpodder.gtkui import app
175         gpodder.ui_folders.insert(0, os.path.join(ui_folder, 'gtk'))
176         app.main(options)
177     else:
178         logger.error('No GUI selected.')
181 if __name__ == '__main__':
182     main()