prepare 3.11.1 release
[gpodder.git] / src / gpodder / __init__.py
blob73452f6fefd542e9bedb9199cda7519303397f26
1 # -*- coding: utf-8 -*-
3 # gPodder - A media aggregator and podcast client
4 # Copyright (c) 2005-2018 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 # This metadata block gets parsed by setup.py - use single quotes only
21 __tagline__ = 'Media aggregator and podcast client'
22 __author__ = 'Thomas Perl <thp@gpodder.org>'
23 __version__ = '3.11.1'
24 __date__ = '2023-02-17'
25 __copyright__ = '© 2005-2023 The gPodder Team'
26 __license__ = 'GNU General Public License, version 3 or later'
27 __url__ = 'http://gpodder.org/'
29 # Use public version part for __version_info__, see PEP 440
30 __public_version__, __local_version__ = next(
31 (v[0], v[1] if len(v) > 1 else '') for v in (__version__.split('+'),))
32 __version_info__ = tuple(int(x) for x in __public_version__.split('.'))
34 import gettext
35 import locale
36 import os
37 import platform
38 import socket
39 import sys
41 from gpodder.build_info import BUILD_TYPE
43 # Check if real hard dependencies are available
44 try:
45 import podcastparser
46 except ImportError:
47 print("""
48 Error: Module "podcastparser" (python-podcastparser) not found.
49 The podcastparser module can be downloaded from
50 http://gpodder.org/podcastparser/
52 From a source checkout, see https://gpodder.github.io/docs/run-from-git.html
53 """)
54 sys.exit(1)
55 del podcastparser
57 try:
58 import mygpoclient
59 except ImportError:
60 print("""
61 Error: Module "mygpoclient" (python-mygpoclient) not found.
62 The mygpoclient module can be downloaded from
63 http://gpodder.org/mygpoclient/
65 From a source checkout, see https://gpodder.github.io/docs/run-from-git.html
66 """)
67 sys.exit(1)
68 del mygpoclient
70 try:
71 import sqlite3
72 except ImportError:
73 print("""
74 Error: Module "sqlite3" not found.
75 Build Python with SQLite 3 support or get it from
76 http://code.google.com/p/pysqlite/
77 """)
78 sys.exit(1)
79 del sqlite3
82 # Is gpodder running in verbose mode?
83 verbose = False
84 # Is gpodder running in quiet mode?
85 quiet = False
88 # The User-Agent string for downloads
89 user_agent = 'gPodder/%s (+%s) %s' % (__version__, __url__, platform.system())
92 # Are we running in GUI or console mode?
93 class UI(object):
94 def __init__(self):
95 self.gtk = False
96 self.cli = False
99 ui = UI()
101 # D-Bus specific interface names
102 dbus_bus_name = 'org.gpodder'
103 dbus_gui_object_path = '/gui'
104 dbus_podcasts_object_path = '/podcasts'
105 dbus_interface = 'org.gpodder.interface'
106 dbus_podcasts = 'org.gpodder.podcasts'
107 dbus_session_bus = None
109 # Set "win32" to True if we are on Windows
110 ui.win32 = (platform.system() == 'Windows')
111 # Set "osx" to True if we are on Mac OS X
112 ui.osx = (platform.system() == 'Darwin')
113 # We assume it's a freedesktop.org system if it's not Windows or OS X
114 ui.freedesktop = not ui.win32 and not ui.osx
116 # i18n setup (will result in "gettext" to be available)
117 # Use _ = gpodder.gettext in modules to enable string translations
118 textdomain = 'gpodder'
119 locale_dir = gettext.bindtextdomain(textdomain)
121 if ui.win32:
122 # this must be done prior to gettext.translation to set the locale (see #484)
123 from gpodder.utilwin32locale import install
124 install(textdomain, locale_dir)
126 t = gettext.translation(textdomain, locale_dir, fallback=True)
128 gettext = t.gettext
129 ngettext = t.ngettext
131 del t
133 # Set up textdomain for Gtk.Builder (this accesses the C library functions)
134 if hasattr(locale, 'bindtextdomain'):
135 locale.bindtextdomain(textdomain, locale_dir)
137 del locale_dir
139 # Set up socket timeouts to fix bug 174
140 SOCKET_TIMEOUT = 60
141 socket.setdefaulttimeout(SOCKET_TIMEOUT)
142 del socket
143 SOCKET_TIMEOUT
145 # Variables reserved for GUI-specific use (will be set accordingly)
146 ui_folders = []
147 icon_file = None
148 images_folder = None
149 user_extensions = None
151 # Episode states used in the database
152 STATE_NORMAL, STATE_DOWNLOADED, STATE_DELETED = list(range(3))
154 # Paths (gPodder's home folder, config, db, download and data prefix)
155 home = None
156 config_file = None
157 database_file = None
158 downloads = None
159 prefix = None
161 ENV_HOME, ENV_DOWNLOADS = 'GPODDER_HOME', 'GPODDER_DOWNLOAD_DIR'
163 no_update_check_file = None
166 # Function to set a new gPodder home folder
167 def set_home(new_home):
168 global home, config_file, database_file, downloads
169 home = os.path.abspath(new_home)
171 config_file = os.path.join(home, 'Settings.json')
172 database_file = os.path.join(home, 'Database')
173 if ENV_DOWNLOADS not in os.environ:
174 downloads = os.path.join(home, 'Downloads')
177 def fixup_home(old_home):
178 if ui.osx or ui.win32:
179 if ui.osx:
180 new_home = os.path.expanduser(os.path.join('~', 'Library',
181 'Application Support', 'gPodder'))
182 elif BUILD_TYPE == 'windows-portable':
183 new_home = os.path.normpath(os.path.join(os.path.dirname(sys.executable), "..", "..", "config"))
184 old_home = new_home # force to config directory
185 print("D: windows-portable build; forcing home to config directory %s" % new_home, file=sys.stderr)
186 else: # ui.win32, not portable build
187 from gpodder.utilwin32ctypes import (
188 get_documents_folder, get_reg_current_user_string_value)
189 try:
190 # from old launcher, see
191 # https://github.com/gpodder/gpodder/blob/old/gtk2/tools/win32-launcher/folderselector.c
192 new_home = get_reg_current_user_string_value("Software\\gpodder.org\\gPodder", "GPODDER_HOME")
193 print("D: windows build; registry home = %s" % new_home, file=sys.stderr)
194 except Exception as e:
195 print("E: can't get GPODDER_HOME from registry: %s" % e, file=sys.stderr)
196 new_home = None
197 if new_home is None:
198 try:
199 new_home = os.path.join(get_documents_folder(), "gPodder")
200 print("D: windows build; documents home = %s" % new_home, file=sys.stderr)
201 except Exception as e:
202 print("E: can't get user's Documents folder: %s" % e, file=sys.stderr)
203 new_home = old_home
205 # Users who do not have the old home directory, or who have it but also
206 # have the new home directory (to cater to situations where the user
207 # might for some reason or the other have a ~/gPodder/ directory) get
208 # to use the new, more OS X-ish home.
209 if not os.path.exists(old_home) or os.path.exists(new_home):
210 return new_home
212 return old_home
215 # Default locations for configuration and data files
216 default_home = os.path.expanduser(os.path.join('~', 'gPodder'))
217 default_home = fixup_home(default_home)
218 set_home(os.environ.get(ENV_HOME, default_home))
220 if home != default_home:
221 print('Storing data in', home, '(GPODDER_HOME is set)', file=sys.stderr)
223 if ENV_DOWNLOADS in os.environ:
224 # Allow to relocate the downloads folder (pull request 4, bug 466)
225 downloads = os.environ[ENV_DOWNLOADS]
226 print('Storing downloads in %s (%s is set)' % (downloads,
227 ENV_DOWNLOADS), file=sys.stderr)
229 # Plugins to load by default
230 DEFAULT_PLUGINS = [
231 'gpodder.plugins.soundcloud',
235 def load_plugins():
236 """Load (non-essential) plugin modules
238 This loads a default set of plugins, but you can use
239 the environment variable "GPODDER_PLUGINS" to modify
240 the list of plugins."""
241 PLUGINS = os.environ.get('GPODDER_PLUGINS', None)
242 if PLUGINS is None:
243 PLUGINS = DEFAULT_PLUGINS
244 else:
245 PLUGINS = PLUGINS.split()
246 for plugin in PLUGINS:
247 try:
248 __import__(plugin)
249 except Exception as e:
250 print('Cannot load plugin: %s (%s)' % (plugin, e), file=sys.stderr)