1
1
Fork 0
mirror of https://github.com/redocnib/docker-tray synced 2024-05-07 23:06:12 +02:00
docker-tray/docker-service-tray.cc
2021-04-17 18:05:04 +05:30

186 lines
4.5 KiB
C++

//g++ docker-service-tray.cc -o docker-tray `pkg-config --cflags --libs gtk+-3.0 appindicator3-0.1` -lsystemd
#include <iostream>
#include <mutex>
#include <string>
#include <cctype>
#include <unistd.h> //Header file for sleep(). man 3 sleep for details.
#include <pthread.h>
#include <systemd/sd-bus.h>
#include <libgen.h>
#define TRAY_APPINDICATOR 1
#include "tray.h"
using namespace std;
static void docker_switch_db(struct tray_menu *item);
static void quit_cb(struct tray_menu *item);
std::mutex mtx;
void *sdbusHookServiceAsync(void *vargp);
static struct tray tray = {
.menu =
(struct tray_menu[]){
{.text = "Please Wait...", .cb = docker_switch_db},
{.text = "Quit",
.cb = quit_cb},
{.text = NULL}},
};
bool QUITTING = false; //Shared state for thread, no mutex for now
string TRAY_ICON1 = "active.png";
string TRAY_ICON2 = "inactive.png";
string TRAY_ICON3 = "unknown.png";
/* Application Entry Point */
int main()
{
char exePath[PATH_MAX];
ssize_t len = ::readlink("/proc/self/exe", exePath, sizeof(exePath));
if (len == -1 || len == sizeof(exePath))
len = 0;
exePath[len] = '\0';
string base_path = dirname(exePath);
TRAY_ICON1 = base_path + "/icons/active.png";
TRAY_ICON2 = base_path + "/icons/inactive.png";
TRAY_ICON3 = base_path + "/icons/unknown.png";
tray.icon = const_cast<char *>(TRAY_ICON3.c_str());
if (tray_init(&tray) < 0)
{
printf("failed to create tray\n");
return 1;
}
pthread_t thread_id;
pthread_create(&thread_id, NULL, sdbusHookServiceAsync, NULL);
while (tray_loop(1) == 0)
{
//Tray Updates
}
(void)pthread_join(thread_id, NULL);
return 0;
}
/*
Threaded sd_bus event lister
*/
void *sdbusHookServiceAsync(void *vargp)
{
sd_bus *bus = NULL;
sd_bus_error err = SD_BUS_ERROR_NULL;
char *msg = NULL;
sd_bus_message *m = NULL;
void *userdata = NULL;
sd_bus_default_system(&bus);
sd_bus_match_signal(
bus, /* bus */
NULL, /* slot */
NULL, /* sender */
"/org/freedesktop/systemd1/unit/docker_2eservice", /* path */
"org.freedesktop.DBus.Properties", /* interface */
"PropertiesChanged", /* member */
NULL, //message_callback , /* callback */
userdata);
while (!QUITTING)
{
mtx.lock();
m = NULL;
int r = sd_bus_process(bus, &m);
if (r < 0)
{
printf("Failed to process requests: %d", r);
mtx.unlock();
continue;
}
else if (r == 0)
{
r = sd_bus_wait(bus, 1000000);
if (r < 0)
printf("Failed to wait: %d", r);
mtx.unlock();
continue;
}
if (!m){
mtx.unlock();
continue;
}
sd_bus_get_property_string(
bus, /* bus */
"org.freedesktop.systemd1", /* destination */
"/org/freedesktop/systemd1/unit/docker_2eservice", /* path */
"org.freedesktop.systemd1.Unit", /* interface */
"ActiveState", /* member */ &err, &msg);
printf("State Update From Service: %s\n", msg);
unsigned state = 0;
if (strcmp(msg, "inactive") >= 0)
state = 1;
else if (strcmp(msg, "active") >= 0)
state = 2;
switch (state)
{
case 0: //Processing
tray.icon = const_cast<char *>(TRAY_ICON3.c_str());
tray.menu[0].text = strcat(msg, "...");
tray.menu[0].disabled = 1;
break;
case 1: //Inactive
tray.icon = const_cast<char *>(TRAY_ICON2.c_str());
tray.menu[0].text = "Start Docker Service";
tray.menu[0].disabled = 0;
break;
case 2: //Active
tray.icon = const_cast<char *>(TRAY_ICON1.c_str());
tray.menu[0].text = "Stop Docker Service";
tray.menu[0].disabled = 0;
}
tray_update(&tray);
sd_bus_message_unref(m);
free(msg);
mtx.unlock();
}
sd_bus_error_free(&err);
sd_bus_unref(bus);
return NULL;
}
/*
Tray Callbacks
*/
static void docker_switch_db(struct tray_menu *item)
{
(void)item;
if (strcmp(tray.icon, const_cast<char *>(TRAY_ICON1.c_str())) == 0)
{
system("systemctl stop docker");
}
else
{
system("systemctl start docker");
}
//tray_update(&tray);
}
static void quit_cb(struct tray_menu *item)
{
(void)item;
tray_exit();
QUITTING = true;
}