1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <pthread.h>
#include <gtk/gtk.h>
#include "info.h"
#include "server.h"
#include "grab.h"
static GtkStatusIcon *tray_icon;
static GtkWidget *menu;
static pthread_t grab_thread;
static pthread_t server_thread;
void tray_icon_on_click(GtkStatusIcon *status_icon, gpointer user_data) {
// left-click
}
void tray_icon_on_menu(GtkStatusIcon *status_icon, guint button, guint activate_time, gpointer user_data) {
// right-click
gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, button, activate_time);
}
void menu_about(GtkWidget *widget, gpointer data) {
GtkWidget *about_dialog;
const gchar *authors[] = {
APP_AUTHOR,
NULL
};
about_dialog = gtk_about_dialog_new();
gtk_about_dialog_set_version((GtkAboutDialog *)about_dialog, APP_VERSION);
gtk_about_dialog_set_authors((GtkAboutDialog *)about_dialog, authors);
gtk_about_dialog_set_comments((GtkAboutDialog *)about_dialog, (const gchar *)APP_ABOUT);
gtk_about_dialog_set_name((GtkAboutDialog *)about_dialog, APP_NAME);
gtk_about_dialog_set_website((GtkAboutDialog *)about_dialog, APP_URL);
g_signal_connect_swapped(about_dialog, "response", G_CALLBACK(gtk_widget_hide), about_dialog);
gtk_widget_show(about_dialog);
}
void menu_quit(GtkWidget *widget, gpointer data) {
exit(0);
}
void create_tray_icon() {
tray_icon = gtk_status_icon_new();
g_signal_connect(G_OBJECT(tray_icon), "activate",
G_CALLBACK(tray_icon_on_click), NULL);
g_signal_connect(G_OBJECT(tray_icon), "popup-menu",
G_CALLBACK(tray_icon_on_menu), NULL);
gtk_status_icon_set_from_icon_name(tray_icon, "vkpc");
gtk_status_icon_set_tooltip(tray_icon, APP_NAME);
gtk_status_icon_set_visible(tray_icon, true);
}
void create_menu() {
GtkWidget *item;
menu = gtk_menu_new();
// About
item = gtk_image_menu_item_new_from_stock(GTK_STOCK_DIALOG_INFO, NULL);
gtk_menu_item_set_label((GtkMenuItem *)item, "About");
g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(menu_about), NULL);
gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
gtk_widget_show(item);
// Quit
item = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, NULL);
gtk_menu_item_set_label((GtkMenuItem *)item, "Quit");
g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(menu_quit), NULL);
gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
gtk_widget_show(item);
}
void handle_hotkeys(enum HotkeyEvent e) {
printf("[handle_hotkeys] e: %d\n", e);
pthread_mutex_lock(&server_command_mutex);
switch (e) {
case HK_PLAY:
server_command = PLAY;
break;
case HK_PAUSE:
server_command = PAUSE;
break;
case HK_NEXT:
server_command = NEXT;
break;
case HK_PREV:
server_command = PREV;
break;
default:
break;
}
pthread_mutex_unlock(&server_command_mutex);
}
void start_grab() {
int rc = pthread_create(&grab_thread, NULL, (void *)grab_init, handle_hotkeys);
if (rc) {
fprintf(stderr, "ERROR creating grab_thread, code = %d\n", rc);
exit(-1);
}
}
void start_server() {
int rc = pthread_create(&server_thread, NULL, (void *)server_init, NULL);
if (rc) {
fprintf(stderr, "ERROR creating server_thread, code = %d\n", rc);
exit(-1);
}
}
int main(int argc, char **argv) {
pthread_mutex_init(&server_command_mutex, NULL);
start_grab();
start_server();
gtk_init(&argc, &argv);
create_tray_icon();
create_menu();
gtk_main();
return 0;
}
|