butt/src/tray_agent.cpp
audioprog 031ca812ad init
2025-08-13 22:05:17 +02:00

237 lines
6 KiB
C++

// tray agent functions for butt
//
// Copyright 2007-2021 by Daniel Noethen.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
#ifdef WIN32
#include <windows.h>
#include <string>
#include <FL/x.H>
#include "flgui.h"
#include "cfg.h"
#include "config.h"
#include "butt.h"
#include "sha256.h"
#include "tray_agent.h"
#define AGENT_CLASS "AutoHotkeyGUI"
#define AGENT_TITLE "buttTrayAgent11-03-2021"
#define AGENT_SHA256 "80015491aabc0b6a3470cd375d8304a5b4446b2ee88929e552c03676ca877f53"
#define AGENT_EXECUTABLE "butt_agent.exe"
static char song_buf[512];
static int check_hash(void)
{
char agent_sha256[65];
const int salt = 0xA50D;
if (sha256_file((char *)AGENT_EXECUTABLE, agent_sha256, salt) == 0) {
// #warning "REMOVE THIS RETURN FOR PRODUCTION"
// printf("agent hash: %s\n", agent_sha256);
// return 0;
// #warning "REMOVE THIS RETURN FOR PRODUCTION"
if (strncmp(agent_sha256, AGENT_SHA256, 64) == 0) {
return 0; // correct hash found
}
}
return 1; // error
}
static int send_msg(char *cmsg)
{
COPYDATASTRUCT MyCDS;
wchar_t wmsg[512];
// Convert normal char array to wide char array
mbstowcs(wmsg, cmsg, 512);
MyCDS.dwData = 0;
MyCDS.cbData = sizeof(wmsg);
MyCDS.lpData = &wmsg;
// Get handle of butt main window
HWND hwButt = fl_xid(fl_g->window_main);
HWND hwAgent;
if (tray_agent_is_running(&hwAgent) == 1) {
SendMessage(hwAgent, WM_COPYDATA, (WPARAM)(HWND)hwButt, (LPARAM)(LPVOID)&MyCDS);
return 0;
}
else {
return 1;
}
}
int tray_agent_start(void)
{
char command[32];
STARTUPINFOA si;
PROCESS_INFORMATION pi;
// Do not start if it is already running
if (tray_agent_is_running(NULL) == 1) {
return 1;
}
if (check_hash() != 0) {
return 1; // agent has wrong hash. Do not execute it!
}
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
snprintf(command, sizeof(command), "%s -s", AGENT_EXECUTABLE);
if (CreateProcessA(NULL, command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi) != 0) {
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
struct timespec wait_50ms;
wait_50ms.tv_sec = 0;
wait_50ms.tv_nsec = (50 * 1000 * 1000);
// Wait max 40*50 ms = 2 seconds until agent has been started
int timed_out = 1;
for (int i = 0; i < 40; i++) {
if (tray_agent_is_running(NULL) == 1) {
timed_out = 0;
break;
}
nanosleep(&wait_50ms, NULL);
}
if (timed_out == 1) {
return 1; // error: tray agent still not running
}
else {
return 0;
}
}
else {
return 1;
}
}
int tray_agent_is_running(HWND *hwAgent)
{
HWND hwWindow = FindWindow(AGENT_CLASS, AGENT_TITLE);
if (hwWindow != NULL) {
if (hwAgent != NULL) {
*hwAgent = hwWindow;
}
return 1;
}
else {
return 0;
}
}
void tray_agent_set_song(char *song)
{
snprintf(song_buf, sizeof(song_buf), "%s", song);
}
int tray_agent_send_cmd(int cmd)
{
char msg[512];
char tray_title[128];
char custom_window_title[128];
int minimize;
int pid = GetCurrentProcessId();
if (cfg.gui.window_title[0] != '\0') {
snprintf(custom_window_title, sizeof(custom_window_title), "%s", cfg.gui.window_title);
}
else {
snprintf(custom_window_title, sizeof(custom_window_title), "dummy");
}
if (cfg.main.num_of_srv > 0) {
snprintf(tray_title, sizeof(tray_title), "%s", cfg.srv[cfg.selected_srv]->name);
}
else {
snprintf(tray_title, sizeof(tray_title), "%s", "no server");
}
switch (cmd) {
case TA_MINIMIZE:
// Start agent when minimizing and agent is not running yet
if (tray_agent_is_running(NULL) == 0) {
if (tray_agent_start() != 0) {
return 1; // Tray agent could not be started
}
}
minimize = 1;
snprintf(msg, sizeof(msg), "%s\t%d\t%d\t%s\t%d\t%s", VERSION, minimize, pid, tray_title, connected, custom_window_title);
break;
case TA_START:
case TA_SERVER_NAME:
case TA_CONNECT_STATE:
minimize = 0;
snprintf(msg, sizeof(msg), "%s\t%d\t%d\t%s\t%d\t%s", VERSION, minimize, pid, tray_title, connected, custom_window_title);
break;
case TA_SONG_UPDATE:
minimize = 0;
snprintf(msg, sizeof(msg), "%s\t%d\t%d\t%s\t%d\t%s\t%s", VERSION, minimize, pid, tray_title, connected, custom_window_title, song_buf);
break;
default:
return 1;
}
int ret = send_msg(msg);
if ((ret == 0) && (minimize == 1)) {
if (fl_g->window_cfg->shown()) // Close settings window when minimizing to tray
{
fl_g->window_cfg->hide();
Fl::remove_timeout(&cfg_win_pos_timer);
}
}
return ret;
}
int tray_agent_stop(void)
{
char command[32];
STARTUPINFOA si;
PROCESS_INFORMATION pi;
if (check_hash() != 0) {
return 1; // Agent has wrong hash. Do not execute it!
}
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
snprintf(command, sizeof(command), "%s -q", AGENT_EXECUTABLE);
if (CreateProcessA(NULL, command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi) != 0) {
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 0;
}
else {
return 1; // CreateProcessA failed
}
}
#endif // ifdef WIN32