Skip to content

Commit 439e583

Browse files
committed
clapper-app: Apply options from active window to newly created one
When a new window is created, apply all current values to it (volume, speed, set GStreamer elements, etc.). It would not be the best experience when user opens a new window, plays something and 100% volume is used in it.
1 parent 6fb25dd commit 439e583

File tree

3 files changed

+202
-131
lines changed

3 files changed

+202
-131
lines changed

src/bin/clapper-app/clapper-app-application.c

Lines changed: 155 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -67,30 +67,142 @@ typedef struct
6767
const gchar *accels[3];
6868
} ClapperAppShortcut;
6969

70-
struct ClapperAppOptions
71-
{
72-
gdouble volume;
73-
gdouble speed;
70+
static gboolean
71+
clapper_app_options_get (const gchar *key, const gchar *format, GVariantDict *options,
72+
GObject *src_object, GSettings *settings, gpointer output)
73+
{
74+
if (options && g_variant_dict_lookup (options, key, format, output)) {
75+
return TRUE;
76+
} else if (src_object) {
77+
g_object_get (src_object, key, output, NULL);
78+
return TRUE;
79+
} else if (settings) {
80+
g_settings_get (settings, key, format, output);
81+
return TRUE;
82+
}
7483

75-
gint progression_mode;
84+
return FALSE;
85+
}
7686

77-
gboolean fullscreen;
87+
static gboolean
88+
clapper_app_options_get_extra (const gchar *key, GVariantDict *options,
89+
const gchar *extra_value, GSettings *settings, gchar **output)
90+
{
91+
if (options && g_variant_dict_lookup (options, key, "s", output)) {
92+
return TRUE;
93+
} else if (extra_value) {
94+
*output = g_strdup (extra_value);
95+
return TRUE;
96+
} else if (settings) {
97+
*output = g_settings_get_string (settings, key);
98+
99+
/* Ensure non-empty string */
100+
if (*output) {
101+
if (strlen (*output) > 0)
102+
return TRUE;
103+
else
104+
g_clear_pointer (output, g_free);
105+
}
106+
}
78107

79-
gchar *video_filter;
80-
gchar *audio_filter;
108+
return FALSE;
109+
}
81110

82-
gchar *video_sink;
83-
gchar *audio_sink;
84-
};
111+
/*
112+
* Apply options to @dest_window. Option providers will be used in args order.
113+
* If any arg is %NULL it will not be used. For example, passing %NULL as
114+
* @settings will avoid restoring values to @dest_window from GSettings.
115+
*/
116+
static void
117+
clapper_app_apply_options_to_window (ClapperAppWindow *dest_window, GVariantDict *options,
118+
ClapperAppWindow *src_window, GSettings *settings)
119+
{
120+
ClapperPlayer *dest_player;
121+
ClapperAppWindowExtraOptions *src_extra_opts = NULL, *dest_extra_opts = NULL;
122+
GObject *src_player_obj = NULL;
123+
GObject *src_queue_obj = NULL;
124+
gchar *option_str;
125+
gdouble option_dbl;
126+
gint option_int;
127+
gboolean option_bool;
128+
129+
GST_DEBUG ("Applying options to window: %p", dest_window);
130+
131+
dest_player = clapper_app_window_get_player (dest_window);
132+
dest_extra_opts = clapper_app_window_get_extra_options (dest_window);
133+
134+
if (src_window) {
135+
src_player_obj = (GObject *) clapper_app_window_get_player (src_window);
136+
src_queue_obj = (GObject *) clapper_player_get_queue (CLAPPER_PLAYER_CAST (src_player_obj));
137+
src_extra_opts = clapper_app_window_get_extra_options (src_window);
138+
}
139+
140+
/* Apply player values, clamp them to be within allowed range */
141+
if (clapper_app_options_get ("volume", "d", options, src_player_obj, settings, &option_dbl))
142+
clapper_player_set_volume (dest_player, PERCENTAGE_ROUND (CLAMP (option_dbl, 0, 2.0)));
143+
if (clapper_app_options_get ("mute", "b", NULL, src_player_obj, settings, &option_bool))
144+
clapper_player_set_mute (dest_player, option_bool);
145+
if (clapper_app_options_get ("speed", "d", options, src_player_obj, settings, &option_dbl))
146+
clapper_player_set_speed (dest_player, PERCENTAGE_ROUND (CLAMP (option_dbl, 0.05, 2.0)));
147+
if (clapper_app_options_get ("progression-mode", "i", options, src_queue_obj, settings, &option_int))
148+
clapper_queue_set_progression_mode (clapper_player_get_queue (dest_player), CLAMP (option_int, 0, 4));
149+
if (clapper_app_options_get ("subtitles-enabled", "b", NULL, src_player_obj, settings, &option_bool))
150+
clapper_player_set_subtitles_enabled (dest_player, option_bool);
151+
152+
if (clapper_app_options_get_extra ("video-filter", options,
153+
(src_extra_opts) ? src_extra_opts->video_filter : NULL, NULL, &option_str)) {
154+
clapper_player_set_video_filter (dest_player, clapper_app_utils_make_element (option_str));
155+
g_free (dest_extra_opts->video_filter);
156+
dest_extra_opts->video_filter = option_str;
157+
}
158+
if (clapper_app_options_get_extra ("audio-filter", options,
159+
(src_extra_opts) ? src_extra_opts->audio_filter : NULL, NULL, &option_str)) {
160+
clapper_player_set_audio_filter (dest_player, clapper_app_utils_make_element (option_str));
161+
g_free (dest_extra_opts->audio_filter);
162+
dest_extra_opts->audio_filter = option_str;
163+
}
164+
if (clapper_app_options_get_extra ("video-sink", options,
165+
(src_extra_opts) ? src_extra_opts->video_sink : NULL, NULL, &option_str)) {
166+
clapper_player_set_video_sink (dest_player, clapper_app_utils_make_element (option_str));
167+
g_free (dest_extra_opts->video_sink);
168+
dest_extra_opts->video_sink = option_str;
169+
}
170+
if (clapper_app_options_get_extra ("audio-sink", options,
171+
(src_extra_opts) ? src_extra_opts->audio_sink : NULL, NULL, &option_str)) {
172+
clapper_player_set_audio_sink (dest_player, clapper_app_utils_make_element (option_str));
173+
g_free (dest_extra_opts->audio_sink);
174+
dest_extra_opts->audio_sink = option_str;
175+
}
176+
177+
/* Apply window options */
178+
if ((options && g_variant_dict_contains (options, "fullscreen"))
179+
|| (settings && g_settings_get_boolean (settings, "fullscreened")))
180+
gtk_window_fullscreen (GTK_WINDOW (dest_window));
181+
else if (settings && g_settings_get_boolean (settings, "maximized"))
182+
gtk_window_maximize (GTK_WINDOW (dest_window));
183+
184+
GST_DEBUG ("Options applied");
185+
}
85186

86187
static inline void
87-
_app_opts_free_contents (struct ClapperAppOptions *app_opts)
188+
_store_settings_from_window (ClapperAppApplication *self, ClapperAppWindow *app_window)
88189
{
89-
g_free (app_opts->video_filter);
90-
g_free (app_opts->audio_filter);
190+
ClapperPlayer *player = clapper_app_window_get_player (app_window);
191+
ClapperQueue *queue = clapper_player_get_queue (player);
192+
GtkWindow *window = GTK_WINDOW (app_window);
91193

92-
g_free (app_opts->video_sink);
93-
g_free (app_opts->audio_sink);
194+
GST_DEBUG ("Storing current configuration to GSettings");
195+
196+
g_settings_set_double (self->settings, "volume", clapper_player_get_volume (player));
197+
g_settings_set_boolean (self->settings, "mute", clapper_player_get_mute (player));
198+
g_settings_set_double (self->settings, "speed", clapper_player_get_speed (player));
199+
g_settings_set_boolean (self->settings, "subtitles-enabled", clapper_player_get_subtitles_enabled (player));
200+
g_settings_set_int (self->settings, "progression-mode", clapper_queue_get_progression_mode (queue));
201+
202+
g_settings_set_boolean (self->settings, "maximized", gtk_window_is_maximized (window));
203+
g_settings_set_boolean (self->settings, "fullscreened", gtk_window_is_fullscreen (window));
204+
205+
GST_DEBUG ("Configuration stored");
94206
}
95207

96208
static inline void
@@ -227,8 +339,13 @@ new_window (GSimpleAction *action, GVariant *param, gpointer user_data)
227339
/* Do not allow to open new windows during initial state,
228340
* there already is a free one to use */
229341
if (g_strcmp0 (child_name, "initial_state") != 0) {
230-
GtkWidget *window = clapper_app_window_new (gtk_app);
231-
gtk_window_present (GTK_WINDOW (window));
342+
ClapperAppWindow *src_window, *dest_window;
343+
344+
src_window = CLAPPER_APP_WINDOW_CAST (gtk_application_get_active_window (gtk_app));
345+
dest_window = CLAPPER_APP_WINDOW_CAST (clapper_app_window_new (gtk_app));
346+
347+
clapper_app_apply_options_to_window (dest_window, NULL, src_window, NULL);
348+
gtk_window_present (GTK_WINDOW (dest_window));
232349
}
233350
}
234351

@@ -267,75 +384,6 @@ show_about (GSimpleAction *action, GVariant *param, gpointer user_data)
267384
gtk_window_present (GTK_WINDOW (about_window));
268385
}
269386

270-
static inline void
271-
_apply_settings_to_window (ClapperAppApplication *self, ClapperAppWindow *app_window,
272-
const struct ClapperAppOptions *app_opts, gboolean restore)
273-
{
274-
ClapperPlayer *player = clapper_app_window_get_player (app_window);
275-
ClapperQueue *queue = clapper_player_get_queue (player);
276-
277-
GST_DEBUG ("Applying settings values to: %" GST_PTR_FORMAT, app_window);
278-
279-
if (app_opts->video_filter)
280-
clapper_player_set_video_filter (player, clapper_app_utils_make_element (app_opts->video_filter));
281-
if (app_opts->audio_filter)
282-
clapper_player_set_audio_filter (player, clapper_app_utils_make_element (app_opts->audio_filter));
283-
if (app_opts->video_sink)
284-
clapper_player_set_video_sink (player, clapper_app_utils_make_element (app_opts->video_sink));
285-
if (app_opts->audio_sink)
286-
clapper_player_set_audio_sink (player, clapper_app_utils_make_element (app_opts->audio_sink));
287-
288-
/* NOTE: Not using ternary operator to avoid accidental typecasting */
289-
if (app_opts->volume >= 0)
290-
clapper_player_set_volume (player, PERCENTAGE_ROUND (app_opts->volume));
291-
else if (restore)
292-
clapper_player_set_volume (player, PERCENTAGE_ROUND (g_settings_get_double (self->settings, "volume")));
293-
294-
if (restore)
295-
clapper_player_set_mute (player, g_settings_get_boolean (self->settings, "mute"));
296-
297-
if (app_opts->speed >= 0)
298-
clapper_player_set_speed (player, PERCENTAGE_ROUND (app_opts->speed));
299-
else if (restore)
300-
clapper_player_set_speed (player, PERCENTAGE_ROUND (g_settings_get_double (self->settings, "speed")));
301-
302-
if (restore)
303-
clapper_player_set_subtitles_enabled (player, g_settings_get_boolean (self->settings, "subtitles-enabled"));
304-
305-
if (app_opts->progression_mode >= 0)
306-
clapper_queue_set_progression_mode (queue, app_opts->progression_mode);
307-
else if (restore)
308-
clapper_queue_set_progression_mode (queue, g_settings_get_int (self->settings, "progression-mode"));
309-
310-
if (app_opts->fullscreen || (restore && g_settings_get_boolean (self->settings, "fullscreened")))
311-
gtk_window_fullscreen (GTK_WINDOW (app_window));
312-
else if (restore && g_settings_get_boolean (self->settings, "maximized"))
313-
gtk_window_maximize (GTK_WINDOW (app_window));
314-
315-
GST_DEBUG ("Configuration applied");
316-
}
317-
318-
static inline void
319-
_store_settings_from_window (ClapperAppApplication *self, ClapperAppWindow *app_window)
320-
{
321-
ClapperPlayer *player = clapper_app_window_get_player (app_window);
322-
ClapperQueue *queue = clapper_player_get_queue (player);
323-
GtkWindow *window = GTK_WINDOW (app_window);
324-
325-
GST_DEBUG ("Storing current configuration to GSettings");
326-
327-
g_settings_set_double (self->settings, "volume", clapper_player_get_volume (player));
328-
g_settings_set_boolean (self->settings, "mute", clapper_player_get_mute (player));
329-
g_settings_set_double (self->settings, "speed", clapper_player_get_speed (player));
330-
g_settings_set_boolean (self->settings, "subtitles-enabled", clapper_player_get_subtitles_enabled (player));
331-
g_settings_set_int (self->settings, "progression-mode", clapper_queue_get_progression_mode (queue));
332-
333-
g_settings_set_boolean (self->settings, "maximized", gtk_window_is_maximized (window));
334-
g_settings_set_boolean (self->settings, "fullscreened", gtk_window_is_fullscreen (window));
335-
336-
GST_DEBUG ("Configuration stored");
337-
}
338-
339387
GApplication *
340388
clapper_app_application_new (void)
341389
{
@@ -374,13 +422,19 @@ static void
374422
clapper_app_application_activate (GApplication *app)
375423
{
376424
ClapperAppApplication *self = CLAPPER_APP_APPLICATION_CAST (app);
425+
GtkApplication *gtk_app = GTK_APPLICATION (app);
377426
GtkWindow *window;
378427

379428
GST_INFO ("Activate");
380429
G_APPLICATION_CLASS (parent_class)->activate (app);
381430

382-
if (!(window = gtk_application_get_active_window (GTK_APPLICATION (app))))
383-
window = GTK_WINDOW (clapper_app_window_new (GTK_APPLICATION (app)));
431+
/* When activated through DBus command line does not run,
432+
* so create our first window here instead */
433+
if (!(window = gtk_application_get_active_window (gtk_app))) {
434+
window = GTK_WINDOW (clapper_app_window_new (gtk_app));
435+
clapper_app_apply_options_to_window (CLAPPER_APP_WINDOW_CAST (window),
436+
NULL, NULL, self->settings);
437+
}
384438

385439
if (self->need_init_state) {
386440
_assemble_initial_state (window);
@@ -416,66 +470,36 @@ static gint
416470
clapper_app_application_command_line (GApplication *app, GApplicationCommandLine *cmd_line)
417471
{
418472
ClapperAppApplication *self = CLAPPER_APP_APPLICATION_CAST (app);
419-
struct ClapperAppOptions app_opts = { 0, };
420-
GtkWindow *window = NULL;
473+
ClapperAppWindow *src_window = NULL, *dest_window = NULL;
474+
GtkApplication *gtk_app = GTK_APPLICATION (app);
421475
GVariantDict *options;
422476
GFile **files = NULL;
477+
GSettings *settings;
423478
gint n_files = 0;
424-
gboolean is_remote, restore, enqueue = FALSE;
425479

426480
GST_INFO ("Handling command line");
427481

428482
options = g_application_command_line_get_options_dict (cmd_line);
429-
is_remote = g_application_command_line_get_is_remote (cmd_line);
483+
dest_window = CLAPPER_APP_WINDOW_CAST (gtk_application_get_active_window (gtk_app));
430484

431-
/* Some options only make sense from remote invocation */
432-
if (is_remote) {
433-
if (g_variant_dict_contains (options, "new-window"))
434-
window = GTK_WINDOW (clapper_app_window_new (GTK_APPLICATION (app)));
485+
/* Restore settings only once by making them %NULL when run again */
486+
settings = (!dest_window) ? self->settings : NULL;
435487

436-
enqueue = g_variant_dict_contains (options, "enqueue");
488+
if (!dest_window || g_variant_dict_contains (options, "new-window")) {
489+
src_window = dest_window;
490+
dest_window = CLAPPER_APP_WINDOW_CAST (clapper_app_window_new (gtk_app));
437491
}
438492

439-
if (g_variant_dict_lookup (options, "volume", "d", &app_opts.volume))
440-
app_opts.volume = CLAMP (app_opts.volume, 0, 2.0); // clamp to allowed range
441-
else
442-
app_opts.volume = -1;
443-
444-
if (g_variant_dict_lookup (options, "speed", "d", &app_opts.speed))
445-
app_opts.speed = CLAMP (app_opts.speed, 0.05, 2.0); // clamp to allowed range
446-
else
447-
app_opts.speed = -1;
448-
449-
if (g_variant_dict_lookup (options, "progression-mode", "i", &app_opts.progression_mode))
450-
app_opts.progression_mode = CLAMP (app_opts.progression_mode, 0, 4); // clamp to possible modes
451-
else
452-
app_opts.progression_mode = -1;
453-
454-
app_opts.fullscreen = g_variant_dict_contains (options, "fullscreen");
455-
456-
g_variant_dict_lookup (options, "video-filter", "s", &app_opts.video_filter);
457-
g_variant_dict_lookup (options, "audio-filter", "s", &app_opts.audio_filter);
458-
459-
g_variant_dict_lookup (options, "video-sink", "s", &app_opts.video_sink);
460-
g_variant_dict_lookup (options, "audio-sink", "s", &app_opts.audio_sink);
493+
clapper_app_apply_options_to_window (dest_window, options, src_window, settings);
461494

462495
if (clapper_app_utils_files_from_command_line (cmd_line, &files, &n_files)) {
463-
g_application_open (app, files, n_files, (enqueue) ? "add-only" : "");
496+
g_application_open (app, files, n_files,
497+
(g_variant_dict_contains (options, "enqueue")) ? "add-only" : "");
464498
clapper_app_utils_files_free (files);
465499
} else {
466500
g_application_activate (app);
467501
}
468502

469-
/* We want to restore settings when starting main process
470-
* or a new window is being added from the remote one */
471-
restore = (!is_remote || window != NULL);
472-
473-
if (!window)
474-
window = gtk_application_get_active_window (GTK_APPLICATION (app));
475-
476-
_apply_settings_to_window (self, CLAPPER_APP_WINDOW_CAST (window), &app_opts, restore);
477-
_app_opts_free_contents (&app_opts);
478-
479503
return EXIT_SUCCESS;
480504
}
481505

0 commit comments

Comments
 (0)