Skip to content

Commit 8135c9d

Browse files
committed
breeze: initial carousel support
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
1 parent 7aada2a commit 8135c9d

1 file changed

Lines changed: 132 additions & 18 deletions

File tree

breeze/breeze.c

Lines changed: 132 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,14 @@ typedef struct {
4747
/* Configuration */
4848
double latitude;
4949
double longitude;
50-
char *web_url;
50+
char **web_urls;
51+
int url_count;
52+
int current_url;
53+
54+
/* Carousel */
55+
int carousel_weather; /* Seconds to show weather (0 = disabled) */
56+
int carousel_url; /* Seconds to show each URL (0 = disabled) */
57+
guint carousel_timer;
5158

5259
/* Timer IDs */
5360
guint anim_timer;
@@ -229,16 +236,22 @@ static gboolean on_weather_tick(gpointer data)
229236
/* ------------------------------------------------------------------ */
230237

231238
static gboolean on_webview_timeout(gpointer data);
239+
static void load_next_url(void);
240+
static void carousel_restart(void);
232241

233242
static void show_web_view(void)
234243
{
244+
int timeout;
245+
235246
gtk_widget_hide(app.loading_label);
236247
app.web_loading = FALSE;
237248
gtk_stack_set_visible_child_name(GTK_STACK(app.stack), "web");
238249

239250
if (app.webview_timeout)
240251
g_source_remove(app.webview_timeout);
241-
app.webview_timeout = g_timeout_add_seconds(30, on_webview_timeout, NULL);
252+
253+
timeout = app.carousel_url ? app.carousel_url : 30;
254+
app.webview_timeout = g_timeout_add_seconds(timeout, on_webview_timeout, NULL);
242255
}
243256

244257
static gboolean on_webview_timeout(gpointer data)
@@ -249,9 +262,37 @@ static gboolean on_webview_timeout(gpointer data)
249262
gtk_widget_hide(app.loading_label);
250263
app.web_loading = FALSE;
251264
app.webview_timeout = 0;
265+
266+
if (app.carousel_weather)
267+
carousel_restart();
268+
252269
return G_SOURCE_REMOVE;
253270
}
254271

272+
static gboolean on_carousel_tick(gpointer data)
273+
{
274+
(void)data;
275+
const gchar *current = gtk_stack_get_visible_child_name(GTK_STACK(app.stack));
276+
277+
if (current && g_strcmp0(current, "weather") == 0) {
278+
/* Weather is showing -- load next URL */
279+
if (app.url_count > 0)
280+
load_next_url();
281+
}
282+
/* URL timeout handled by webview_timeout callback */
283+
284+
app.carousel_timer = 0;
285+
return G_SOURCE_REMOVE;
286+
}
287+
288+
static void carousel_restart(void)
289+
{
290+
if (app.carousel_timer)
291+
g_source_remove(app.carousel_timer);
292+
app.carousel_timer = g_timeout_add_seconds(app.carousel_weather,
293+
on_carousel_tick, NULL);
294+
}
295+
255296
static void on_web_load_changed(WebKitWebView *web_view,
256297
WebKitLoadEvent event, gpointer data)
257298
{
@@ -275,9 +316,22 @@ static gboolean on_key_press(GtkWidget *widget, GdkEventKey *event,
275316
return FALSE;
276317
}
277318

319+
static void load_next_url(void)
320+
{
321+
if (app.url_count == 0)
322+
return;
323+
324+
const char *url = app.web_urls[app.current_url];
325+
app.current_url = (app.current_url + 1) % app.url_count;
326+
327+
app.web_loading = TRUE;
328+
gtk_widget_show(app.loading_label);
329+
webkit_web_view_load_uri(WEBKIT_WEB_VIEW(app.web_view), url);
330+
}
331+
278332
static void toggle_web_view(void)
279333
{
280-
if (!app.web_url || !app.web_url[0])
334+
if (app.url_count == 0)
281335
return;
282336

283337
const gchar *current = gtk_stack_get_visible_child_name(GTK_STACK(app.stack));
@@ -289,6 +343,9 @@ static void toggle_web_view(void)
289343
app.webview_timeout = 0;
290344
}
291345
gtk_stack_set_visible_child_name(GTK_STACK(app.stack), "weather");
346+
347+
if (app.carousel_weather)
348+
carousel_restart();
292349
return;
293350
}
294351

@@ -300,10 +357,13 @@ static void toggle_web_view(void)
300357
return;
301358
}
302359

303-
/* Start loading, stay on weather view until page is ready */
304-
app.web_loading = TRUE;
305-
gtk_widget_show(app.loading_label);
306-
webkit_web_view_load_uri(WEBKIT_WEB_VIEW(app.web_view), app.web_url);
360+
/* Stop carousel timer during manual interaction */
361+
if (app.carousel_timer) {
362+
g_source_remove(app.carousel_timer);
363+
app.carousel_timer = 0;
364+
}
365+
366+
load_next_url();
307367
}
308368

309369
static gboolean on_button_press(GtkWidget *widget, GdkEventButton *event,
@@ -430,25 +490,41 @@ static void usage(const char *name)
430490
printf("Usage: %s [OPTIONS]\n"
431491
"\n"
432492
"Options:\n"
433-
" -f, --fullscreen Run in fullscreen mode\n"
434-
" -l, --location LOCATION City or Country,City (e.g., \"Stockholm\"\n"
435-
" or \"Sweden,Stockholm\"), geocoded via Open-Meteo\n"
436-
" --lat LATITUDE Latitude for weather (default: 59.3293)\n"
437-
" --lon LONGITUDE Longitude for weather (default: 18.0686)\n"
438-
" --url URL Web page URL shown on touch/click\n"
439-
" -h, --help Show this help message\n"
493+
" -f, --fullscreen Run in fullscreen mode\n"
494+
" -l, --location LOCATION City or Country,City (e.g., \"Stockholm\"\n"
495+
" or \"Sweden,Stockholm\"), geocoded via Open-Meteo\n"
496+
" --lat LATITUDE Latitude for weather (default: 59.3293)\n"
497+
" --lon LONGITUDE Longitude for weather (default: 18.0686)\n"
498+
" --url URL Web page URL (repeatable for carousel)\n"
499+
" --carousel-weather SECS Weather display time in carousel mode (default: 60)\n"
500+
" --carousel-url SECS URL display time in carousel mode (default: 30)\n"
501+
" -h, --help Show this help message\n"
440502
"\n"
441503
"Environment variables LATITUDE, LONGITUDE, LOCATION, and WEB_URL\n"
442504
"are used as fallbacks when options are not given.\n"
505+
"WEB_URL supports comma-separated URLs for carousel mode.\n"
506+
"CAROUSEL_WEATHER and CAROUSEL_URL set carousel intervals.\n"
507+
"\n"
508+
"Setting any carousel option enables automatic cycling between\n"
509+
"weather and web views. Without carousel options, touch/click\n"
510+
"manually toggles between views (cycling through URLs round-robin).\n"
443511
"\n"
444512
"Press Escape to exit.\n", name);
445513
}
446514

515+
static void add_url(const char *url)
516+
{
517+
app.url_count++;
518+
app.web_urls = realloc(app.web_urls, app.url_count * sizeof(char *));
519+
app.web_urls[app.url_count - 1] = strdup(url);
520+
}
521+
447522
static void parse_args(int argc, char *argv[])
448523
{
449524
/* Defaults from environment, then fallback */
450525
const char *env;
451526
const char *location = NULL;
527+
gboolean carousel_set = FALSE;
452528

453529
env = getenv("LATITUDE");
454530
app.latitude = env ? atof(env) : 59.3293; /* Stockholm */
@@ -459,8 +535,27 @@ static void parse_args(int argc, char *argv[])
459535
env = getenv("LOCATION");
460536
if (env) location = env;
461537

538+
/* Parse WEB_URL: comma-separated list */
462539
env = getenv("WEB_URL");
463-
app.web_url = env ? strdup(env) : NULL;
540+
if (env && env[0]) {
541+
char *copy = strdup(env);
542+
char *token = strtok(copy, ",");
543+
while (token) {
544+
/* Trim leading whitespace */
545+
while (*token == ' ') token++;
546+
if (*token)
547+
add_url(token);
548+
token = strtok(NULL, ",");
549+
}
550+
free(copy);
551+
}
552+
553+
/* Carousel env vars */
554+
env = getenv("CAROUSEL_WEATHER");
555+
if (env) { app.carousel_weather = atoi(env); carousel_set = TRUE; }
556+
557+
env = getenv("CAROUSEL_URL");
558+
if (env) { app.carousel_url = atoi(env); carousel_set = TRUE; }
464559

465560
app.fullscreen = FALSE;
466561

@@ -477,14 +572,27 @@ static void parse_args(int argc, char *argv[])
477572
} else if ((strcmp(argv[i], "--lon") == 0) && i + 1 < argc) {
478573
app.longitude = atof(argv[++i]);
479574
} else if ((strcmp(argv[i], "--url") == 0) && i + 1 < argc) {
480-
free(app.web_url);
481-
app.web_url = strdup(argv[++i]);
575+
add_url(argv[++i]);
576+
} else if ((strcmp(argv[i], "--carousel-weather") == 0) && i + 1 < argc) {
577+
app.carousel_weather = atoi(argv[++i]);
578+
carousel_set = TRUE;
579+
} else if ((strcmp(argv[i], "--carousel-url") == 0) && i + 1 < argc) {
580+
app.carousel_url = atoi(argv[++i]);
581+
carousel_set = TRUE;
482582
} else if (strcmp(argv[i], "--fullscreen") == 0 ||
483583
strcmp(argv[i], "-f") == 0) {
484584
app.fullscreen = TRUE;
485585
}
486586
}
487587

588+
/* Apply carousel defaults if any carousel option was set */
589+
if (carousel_set) {
590+
if (!app.carousel_weather)
591+
app.carousel_weather = 60;
592+
if (!app.carousel_url)
593+
app.carousel_url = 30;
594+
}
595+
488596
if (location) {
489597
double lat, lon;
490598

@@ -574,9 +682,15 @@ int main(int argc, char *argv[])
574682
app.clock_timer = g_timeout_add_seconds(1, on_clock_tick, NULL);
575683
app.weather_timer = g_timeout_add_seconds(300, on_weather_tick, NULL); /* 5 min */
576684

685+
/* Start carousel if enabled and URLs are configured */
686+
if (app.carousel_weather && app.url_count > 0)
687+
carousel_restart();
688+
577689
gtk_widget_show_all(app.window);
578690
gtk_main();
579691

580-
free(app.web_url);
692+
for (int i = 0; i < app.url_count; i++)
693+
free(app.web_urls[i]);
694+
free(app.web_urls);
581695
return 0;
582696
}

0 commit comments

Comments
 (0)