A lot of modernizing.

This commit is contained in:
Johannes Findeisen 2026-07-15 23:18:48 +02:00
commit 5f4ce7f655
8 changed files with 69 additions and 254 deletions

View file

@ -1,6 +0,0 @@
cmake_minimum_required(VERSION 3.26)
project(spacetray C)
set(CMAKE_C_STANDARD 11)
add_executable(spacetray spacetray.c)

View file

@ -9,15 +9,3 @@ clean:
run:
./bin/spacetray
all2:
$(CC) -Wall -g `pkg-config --cflags --libs gtk+-2.0 --libs appindicator-0.1 --libs libcurl --libs json-c --libs libnotify` -DLIBNOTIFY -o bin/spacetray2 spacetray2.c
nonotify2:
$(CC) -Wall -g `pkg-config --cflags --libs gtk+-2.0 --libs appindicator-0.1 --libs libcurl --libs json-c` -o bin/spacetray2 spacetray2.c
clean2:
rm -f ./bin/spacetray2
run2:
./bin/spacetray2

View file

@ -1 +0,0 @@
pygobject==3.46.0

View file

View file

@ -3,7 +3,6 @@
*
* Author: hanez <you@hanez.org>
* Website: https://hanez.org/project/spacetray/
* Contributors: atari, beh, eisbaer and Haeger
*
* License (MIT License):
*
@ -13,9 +12,19 @@
*/
#include <curl/curl.h>
#define GLIB_DISABLE_DEPRECATION_WARNINGS
#define GDK_PIXBUF_ENABLE_BACKWARDS_COMPATIBILITY
#include <gtk/gtk.h>
#include <gdk-pixbuf/gdk-pixdata.h>
#include <json.h>
#ifdef G_GNUC_BEGIN_IGNORE_DEPRECATIONS
#define IGNORE_DEPRECATIONS_START G_GNUC_BEGIN_IGNORE_DEPRECATIONS
#define IGNORE_DEPRECATIONS_END G_GNUC_END_IGNORE_DEPRECATIONS
#else
#define IGNORE_DEPRECATIONS_START
#define IGNORE_DEPRECATIONS_END
#endif
#if LIBNOTIFY
#include <libnotify/notify.h>
#endif
@ -23,6 +32,8 @@
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <pthread.h>
#include <unistd.h>
#include "themes/lock.h"
@ -32,7 +43,7 @@ struct string {
};
static char *name = "SpaceAPI widget for UNIX";
static char *statusurl = "https://www.hamburg.ccc.de/dooris/status.json";
static char *statusurl = NULL;
static char *agent = "Spacetray/0.42";
// The delay for polling the dooris service. Adjust this before compiling
@ -40,10 +51,24 @@ static int delay = 1000; // ms. aka 15 minutes
bool door_open = false;
bool old_door_open = false;
int door_last_change = 0;
void do_it();
void invoke_notification();
gboolean do_it_wrapper(gpointer data) {
do_it();
return FALSE;
}
void *status_update_thread(void *arg) {
while (1) {
sleep(delay);
g_idle_add(do_it_wrapper, NULL);
}
return NULL;
}
GtkStatusIcon *tray_icon;
void init_string(struct string *s) {
@ -79,8 +104,6 @@ void get_bouncer_data() {
struct json_object *leaf_json_object;
bool door_status;
int door_last_change;
struct string s;
printf("Called get_bouncer_data()\n");
@ -123,14 +146,8 @@ void get_bouncer_data() {
leaf_json_object = json_object_object_get(door_json_object, "lastchange");
door_last_change = json_object_get_int(leaf_json_object);
// free door object
json_object_put(door_json_object);
// free leaf object
//json_object_put(leaf_json_object);
// free response object
// json_object_put(response_json_object);
json_object_put(response_json_object);
printf("Door status: = %d\n", door_status);
printf("Door last change: = %d\n", door_last_change);
@ -143,12 +160,17 @@ void get_bouncer_data() {
}
void invoke_notification() {
char door[20];
char door[128];
char date_str[64];
time_t last_change_time = (time_t)door_last_change;
struct tm *tm_info = localtime(&last_change_time);
strftime(date_str, sizeof(date_str), "%Y-%m-%d %H:%M:%S", tm_info);
if (door_open == true) {
snprintf(door, 20, "Door open...");
snprintf(door, sizeof(door), "Door open since %s", date_str);
} else {
snprintf(door, 20, "Door closed...");
snprintf(door, sizeof(door), "Door closed since %s", date_str);
}
gtk_status_icon_set_tooltip(tray_icon, door);
@ -156,20 +178,23 @@ void invoke_notification() {
#if LIBNOTIFY
NotifyNotification *n;
notify_init(name);
n = notify_notification_new(name, door, NULL);
//notify_notification_set_timeout(n, 10000);
if (door_open == true) {
IGNORE_DEPRECATIONS_START
notify_notification_set_icon_from_pixbuf(n, gdk_pixbuf_from_pixdata(
&icon_closed_pixbuf,
&icon_open_pixbuf,
true,
NULL));
IGNORE_DEPRECATIONS_END
} else {
IGNORE_DEPRECATIONS_START
notify_notification_set_icon_from_pixbuf(n, gdk_pixbuf_from_pixdata(
&icon_closed_pixbuf,
true,
NULL));
IGNORE_DEPRECATIONS_END
}
notify_notification_show(n, NULL);
g_object_unref(G_OBJECT(n));
@ -179,31 +204,50 @@ void invoke_notification() {
void set_status() {
if (door_open == true) {
printf("Set to status: open\n");
IGNORE_DEPRECATIONS_START
gtk_status_icon_set_from_pixbuf(tray_icon,
gdk_pixbuf_from_pixdata(&icon_open_pixbuf,
true,
NULL));
IGNORE_DEPRECATIONS_END
} else {
printf("Set to status: closed\n");
IGNORE_DEPRECATIONS_START
gtk_status_icon_set_from_pixbuf(tray_icon,
gdk_pixbuf_from_pixdata(&icon_closed_pixbuf,
true,
NULL));
IGNORE_DEPRECATIONS_END
}
}
void do_it() {
static bool first_run = true;
get_bouncer_data();
set_status();
if (door_open != old_door_open) {
if (!first_run && door_open != old_door_open) {
invoke_notification();
}
first_run = false;
}
int main(int argc, char **argv) {
pthread_t thread_id;
if (argc != 2) {
fprintf(stderr, "Usage: %s <statusurl>\n", argv[0]);
return 1;
}
statusurl = argv[1];
gtk_init(&argc, &argv);
#if LIBNOTIFY
notify_init(name);
#endif
tray_icon = gtk_status_icon_new();
g_signal_connect(G_OBJECT(tray_icon), "activate",
G_CALLBACK(do_it), NULL);
@ -220,7 +264,12 @@ int main(int argc, char **argv) {
//invoke_notification();
//gtk_timeout_add(delay, (GtkFunction)do_it, (gpointer)NULL);
guint xxx = g_timeout_add_seconds(1000, (GSourceFunc)do_it, (gpointer)NULL);
// guint xxx = g_timeout_add_seconds(1000, (GSourceFunc)do_it, (gpointer)NULL);
if (pthread_create(&thread_id, NULL, status_update_thread, NULL) != 0) {
fprintf(stderr, "Error creating thread\n");
return 1;
}
gtk_main();

View file

@ -1,47 +0,0 @@
#!/usr/bin/env python
#
# Copyright 2023 Johannes Findeisen <you@hanez.org>.
#
import gi
import sys
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
gi.require_version('AppIndicator3', '0.1')
from gi.repository import AppIndicator3 as AppIndicator
__VERSION__ = "0.0.3"
def menuitem_response(w, label):
print(label)
def exit_app():
sys.exit()
if __name__ == "__main__":
ind = AppIndicator.Indicator.new("example-simple-client",
"indicator-messages",
AppIndicator.IndicatorCategory.APPLICATION_STATUS)
ind.set_status(AppIndicator.IndicatorStatus.ACTIVE)
ind.set_attention_icon("indicator-messages-new")
# create a menu
menu = Gtk.Menu()
# create some sub menus
for i in range(3):
label = "Test-sub-menu - %d" % i
menu_items = Gtk.MenuItem(label=label)
menu.append(menu_items)
# this is where you would connect your menu item up with a function:
menu_items.connect("activate", menuitem_response, label)
# show the items
menu_items.show()
ind.set_menu(menu)
Gtk.main()

View file

@ -1,168 +0,0 @@
#include <gtk/gtk.h>
#include <libappindicator/app-indicator.h>
static void activate_action (GtkAction *action);
static GtkActionEntry entries[] = {
{ "FileMenu", NULL, "_File" },
{ "New", "document-new", "_New", "<control>N",
"Create a new file", G_CALLBACK (activate_action) },
{ "Open", "document-open", "_Open", "<control>O",
"Open a file", G_CALLBACK (activate_action) },
{ "Save", "document-save", "_Save", "<control>S",
"Save file", G_CALLBACK (activate_action) },
{ "Quit", "application-exit", "_Quit", "<control>Q",
"Exit the application", G_CALLBACK (gtk_main_quit) },
};
static guint n_entries = G_N_ELEMENTS (entries);
static const gchar *ui_info =
"<ui>"
" <menubar name='MenuBar'>"
" <menu action='FileMenu'>"
" <menuitem action='New'/>"
" <menuitem action='Open'/>"
" <menuitem action='Save'/>"
" <separator/>"
" <menuitem action='Quit'/>"
" </menu>"
" </menubar>"
" <popup name='IndicatorPopup'>"
" <menuitem action='New' />"
" <menuitem action='Open' />"
" <menuitem action='Save' />"
" <menuitem action='Quit' />"
" </popup>"
"</ui>";
static void
activate_action (GtkAction *action)
{
const gchar *name = gtk_action_get_name (action);
GtkWidget *dialog;
dialog = gtk_message_dialog_new (NULL,
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_CLOSE,
"You activated action: \"%s\"",
name);
g_signal_connect (dialog, "response",
G_CALLBACK (gtk_widget_destroy), NULL);
gtk_widget_show (dialog);
}
int main (int argc, char **argv)
{
GtkWidget *window;
GtkWidget *menubar;
GtkWidget *table;
GtkWidget *sw;
GtkWidget *contents;
GtkWidget *statusbar;
GtkWidget *indicator_menu;
GtkActionGroup *action_group;
GtkUIManager *uim;
AppIndicator *indicator;
GError *error = NULL;
gtk_init (&argc, &argv);
/* main window */
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Indicator Demo");
gtk_window_set_icon_name (GTK_WINDOW (window), "indicator-messages-new");
g_signal_connect (G_OBJECT (window),
"destroy",
G_CALLBACK (gtk_main_quit),
NULL);
table = gtk_table_new (1, 5, FALSE);
gtk_container_add (GTK_CONTAINER (window), table);
/* Menus */
action_group = gtk_action_group_new ("AppActions");
gtk_action_group_add_actions (action_group,
entries, n_entries,
window);
uim = gtk_ui_manager_new ();
g_object_set_data_full (G_OBJECT (window),
"ui-manager", uim,
g_object_unref);
gtk_ui_manager_insert_action_group (uim, action_group, 0);
gtk_window_add_accel_group (GTK_WINDOW (window),
gtk_ui_manager_get_accel_group (uim));
if (!gtk_ui_manager_add_ui_from_string (uim, ui_info, -1, &error))
{
g_message ("Failed to build menus: %s\n", error->message);
g_error_free (error);
error = NULL;
}
menubar = gtk_ui_manager_get_widget (uim, "/ui/MenuBar");
gtk_widget_show (menubar);
gtk_table_attach (GTK_TABLE (table),
menubar,
0, 1, 0, 1,
GTK_EXPAND | GTK_FILL, 0,
0, 0);
/* Document */
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
GTK_SHADOW_IN);
gtk_table_attach (GTK_TABLE (table),
sw,
/* X direction */ /* Y direction */
0, 1, 3, 4,
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
0, 0);
gtk_window_set_default_size (GTK_WINDOW (window),
200, 200);
contents = gtk_text_view_new ();
gtk_widget_grab_focus (contents);
gtk_container_add (GTK_CONTAINER (sw),
contents);
/* Create statusbar */
statusbar = gtk_statusbar_new ();
gtk_table_attach (GTK_TABLE (table),
statusbar,
/* X direction */ /* Y direction */
0, 1, 4, 5,
GTK_EXPAND | GTK_FILL, 0,
0, 0);
/* Show the window */
gtk_widget_show_all (window);
/* Indicator */
indicator = app_indicator_new ("example-simple-client",
"indicator-messages",
APP_INDICATOR_CATEGORY_APPLICATION_STATUS);
indicator_menu = gtk_ui_manager_get_widget (uim, "/ui/IndicatorPopup");
app_indicator_set_status (indicator, APP_INDICATOR_STATUS_ACTIVE);
app_indicator_set_attention_icon (indicator, "indicator-messages-new");
app_indicator_set_menu (indicator, GTK_MENU (indicator_menu));
gtk_main ();
return 0;
}

View file

@ -6,7 +6,7 @@ static const GdkPixdata icon_open_pixbuf = {
52, /* width */
48, /* height */
/* pixel_data: */
"\202\0\0\0\0\4\200\0\0\6\200\0\0\221\200\0\0\337\200\0\0\362\251\200"
(guint8 *)"\202\0\0\0\0\4\200\0\0\6\200\0\0\221\200\0\0\337\200\0\0\362\251\200"
"\0\0\365\3\201\0\0\354\200\0\0\316\177\0\0L\203\0\0\0\0\5\177\0\0(\200"
"\0\0\362\200\0\0\377\201\1\1\376\203\4\4\376\227\202\4\4\377\222\202"
"\5\5\377\11\203\4\4\376\200\0\0\377\177\0\0\377\201\1\1\270\0\0\0\0\0"
@ -320,7 +320,7 @@ static const GdkPixdata icon_closed_pixbuf = {
52, /* width */
48, /* height */
/* pixel_data: */
"\202\0\0\0\0\3/M\30+.P\25\263.Q\25\332\251-P\26\343\3-P\27\337-P\26\310"
(guint8 *)"\202\0\0\0\0\3/M\30+.P\25\263.Q\25\332\251-P\26\343\3-P\27\337-P\26\310"
".O\26j\204\0\0\0\0\1.Q\25\233\202-P\26\377\1-P\26\376\236.Q\30\376\213"
"/Q\30\376\12.Q\30\376-Q\27\377-P\26\377-Q\26\3441U\30\25\0\0\0\0-Q\25"
"x-P\26\3770R\31\377Ih6\377\214Rn@\377\1Sn@\377\202SnA\377\202SoB\377"