Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-3.0-or-later
2 : : // SPDX-FileCopyrightText: Andy Holmes <andrew.g.r.holmes@gmail.com>
3 : :
4 : : #define G_LOG_DOMAIN "valent-global"
5 : :
6 : : #include "config.h"
7 : :
8 : : #include <time.h>
9 : :
10 : : #include <gio/gio.h>
11 : : #include <libpeas.h>
12 : : #include <libportal/portal.h>
13 : :
14 : : #include "valent-global.h"
15 : : #include "valent-version.h"
16 : :
17 : :
18 : : static GThread *main_thread;
19 : : static PeasEngine *default_engine = NULL;
20 : :
21 : :
22 : : /*
23 : : * libvalent Constructor
24 : : */
25 : : #ifndef __has_attribute
26 : : # define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */
27 : : #endif
28 : : #if __has_attribute(constructor)
29 : : static void __attribute__((constructor))
30 : 68 : valent_init_ctor (void)
31 : : {
32 : 68 : main_thread = g_thread_self ();
33 : 68 : }
34 : : #else
35 : : # error Your platform/compiler is missing constructor support
36 : : #endif
37 : :
38 : :
39 : : /**
40 : : * valent_get_main_thread: (skip)
41 : : *
42 : : * Get the main thread.
43 : : *
44 : : * Use the macro `VALENT_IS_MAIN_THREAD()` to determine whether or not the code
45 : : * is currently running on the main thread.
46 : : *
47 : : * Returns: (transfer none): a `GThread`
48 : : *
49 : : * Since: 1.0
50 : : */
51 : : GThread *
52 : 4254 : valent_get_main_thread (void)
53 : : {
54 : 4254 : return main_thread;
55 : : }
56 : :
57 : : /**
58 : : * valent_get_plugin_engine:
59 : : *
60 : : * Get the global `PeasEngine`.
61 : : *
62 : : * The first call to this function initializes the `PeasEngine` and adds
63 : : * `resource:///plugins` to the search path, where embedded plugins should be
64 : : * registered. If running in a Flatpak, `/app/extensions/lib/valent/plugins`
65 : : * will also be added to the search path for Flatpak extensions.
66 : : *
67 : : * Returns: (transfer none): a `PeasEngine`
68 : : *
69 : : * Since: 1.0
70 : : */
71 : : PeasEngine *
72 : 421 : valent_get_plugin_engine (void)
73 : : {
74 [ + + ]: 421 : if (default_engine == NULL)
75 : : {
76 : 57 : const char *loaders_env = NULL;
77 : 57 : unsigned int n_plugins = 0;
78 : :
79 : 57 : default_engine = peas_engine_get_default ();
80 : 57 : g_object_add_weak_pointer (G_OBJECT (default_engine),
81 : : (gpointer)&default_engine);
82 : :
83 : : /* Optional Loaders */
84 : 57 : loaders_env = g_getenv ("VALENT_PLUGIN_LOADERS");
85 : :
86 [ - + - - ]: 57 : if (loaders_env != NULL && *loaders_env != '\0')
87 : : {
88 : 57 : g_auto (GStrv) loaders = NULL;
89 [ # # ]: 0 : g_autoptr (GError) error = NULL;
90 : :
91 : 0 : loaders = g_strsplit (loaders_env, ",", -1);
92 : :
93 [ # # ]: 0 : if (g_strv_contains ((const char * const *)loaders, "python3"))
94 : 0 : peas_engine_enable_loader (default_engine, "python3");
95 : :
96 [ # # ]: 0 : if (error != NULL)
97 : : g_warning ("Disabling Python3 plugins: %s", error->message);
98 : : }
99 : :
100 : : /* Default Paths */
101 : 57 : peas_engine_add_search_path (default_engine, "resource:///plugins", NULL);
102 : :
103 [ - + ]: 57 : if (xdp_portal_running_under_flatpak ())
104 : : {
105 : 0 : g_autofree char *flatpak_dir = NULL;
106 : :
107 : 0 : flatpak_dir = g_build_filename ("/app", "extensions", "lib",
108 : : "valent", "plugins", NULL);
109 : 0 : peas_engine_add_search_path (default_engine, flatpak_dir, NULL);
110 : : }
111 : :
112 : : /* Load plugins in the default paths automatically */
113 : 57 : n_plugins = g_list_model_get_n_items (G_LIST_MODEL (default_engine));
114 : :
115 [ + + ]: 423 : for (unsigned int i = 0; i < n_plugins; i++)
116 : : {
117 : 366 : g_autoptr (PeasPluginInfo) info = NULL;
118 : :
119 : 366 : info = g_list_model_get_item (G_LIST_MODEL (default_engine), i);
120 [ + - ]: 366 : peas_engine_load_plugin (default_engine, info);
121 : : }
122 : : }
123 : :
124 : 421 : return default_engine;
125 : : }
126 : :
127 : : /**
128 : : * valent_get_user_directory:
129 : : * @directory: a `GUserDirectory`
130 : : *
131 : : * Returns the full path of a special directory using its logical id.
132 : : *
133 : : * This function is a safe wrapper around [func@GLib.get_user_special_dir] that
134 : : * always returns a valid path to an existing directory. The fallback path used
135 : : * is the return value of [func@GLib.get_home_dir].
136 : : *
137 : : * Returns: (transfer none): the path to the specified special directory
138 : : *
139 : : * Since: 1.0
140 : : */
141 : : const char *
142 : 12 : valent_get_user_directory (GUserDirectory directory)
143 : : {
144 : 12 : const char *path = NULL;
145 : :
146 [ + - ]: 12 : g_return_val_if_fail (directory >= G_USER_DIRECTORY_DESKTOP &&
147 : : directory < G_USER_N_DIRECTORIES, NULL);
148 : :
149 [ + - ]: 12 : if ((path = g_get_user_special_dir (directory)) == NULL)
150 : 12 : path = g_get_home_dir ();
151 : :
152 [ - + ]: 12 : if (g_mkdir_with_parents (path, 0755) == -1)
153 : 0 : g_warning ("%s(): [%s]: %s", G_STRFUNC, path, g_strerror (errno));
154 : :
155 : : return path;
156 : : }
157 : :
158 : : /**
159 : : * valent_get_user_file:
160 : : * @dirname: a directory path
161 : : * @basename: (type filename): a file name
162 : : * @unique: whether the resulting filepath should be unique
163 : : *
164 : : * A convenience for creating a [iface@Gio.File].
165 : : *
166 : : * If @unique is true, the returned file is guaranteed not to exist. If
167 : : * @basename exists in @dirname, the resulting file's name will have a
168 : : * parenthesized number appended to it (e.g. `image.png (2)`).
169 : : *
170 : : * Returns: (transfer full): a `GFile`
171 : : *
172 : : * Since: 1.0
173 : : */
174 : : GFile *
175 : 13 : valent_get_user_file (const char *dirname,
176 : : const char *basename,
177 : : gboolean unique)
178 : : {
179 : 26 : g_autofree char *basepath = NULL;
180 : 13 : g_autofree char *filepath = NULL;
181 : 13 : unsigned int copy_num = 0;
182 : :
183 [ + - ]: 13 : g_return_val_if_fail (dirname != NULL, NULL);
184 [ - + ]: 13 : g_return_val_if_fail (basename != NULL, NULL);
185 : :
186 : 13 : basepath = g_build_filename (dirname, basename, NULL);
187 [ - + ]: 13 : filepath = g_strdup (basepath);
188 : :
189 : : /* If a unique path is requested, loop until we find a free name */
190 [ + + + + ]: 19 : while (unique && g_file_test (filepath, G_FILE_TEST_EXISTS))
191 : : {
192 : 6 : g_free (filepath);
193 : 6 : filepath = g_strdup_printf ("%s (%d)", basepath, ++copy_num);
194 : : }
195 : :
196 : 13 : return g_file_new_for_path (filepath);
197 : : }
198 : :
199 : : /**
200 : : * valent_timestamp_ms:
201 : : *
202 : : * Get a current UNIX epoch timestamp in milliseconds.
203 : : *
204 : : * This timestamp format is used in several parts of the KDE Connect protocol.
205 : : *
206 : : * Returns: a 64-bit timestamp
207 : : *
208 : : * Since: 1.0
209 : : */
210 : : int64_t
211 : 353 : valent_timestamp_ms (void)
212 : : {
213 : : #ifdef HAVE_CLOCK_GETTIME
214 : 353 : struct timespec ts;
215 : :
216 : 353 : clock_gettime (CLOCK_REALTIME, &ts);
217 : :
218 : 353 : return (ts.tv_sec * 1000L) + ts.tv_nsec / 1000000L;
219 : : #else
220 : : struct timeval tv;
221 : :
222 : : gettimeofday (&tv, NULL);
223 : :
224 : : return (tv.tv_sec * 1000L) + tv.tv_usec / 1000L;
225 : : #endif /* HAVE_CLOCK_GETTIME */
226 : : }
227 : :
|