Base: LCDproc 0.5.2
[lcdproc-de200c.git] / server / input.c
blob3bcac7344d9dc76dcf137972d2593dd80fc0a33e
1 /*
2 * input.c
3 * This file is part of LCDd, the lcdproc server.
5 * This file is released under the GNU General Public License. Refer to the
6 * COPYING file distributed with this package.
8 * Copyright (c) 1999, William Ferrell, Scott Scriven
9 * 2003, Joris Robijn
12 * Handles keypad (and other?) input from the user.
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <string.h>
21 #include "shared/sockets.h"
22 #include "shared/report.h"
23 #include "shared/configfile.h"
25 #include "drivers.h"
27 #include "client.h"
28 #include "screenlist.h"
29 #include "menuscreens.h"
31 #include "input.h"
32 #include "render.h" /* For server_msg* */
35 LinkedList *keylist;
36 char *toggle_rotate_key;
37 char *prev_screen_key;
38 char *next_screen_key;
39 char *scroll_up_key;
40 char *scroll_down_key;
42 /* Local functions */
43 int server_input(int key);
44 void input_send_to_client(Client *c, const char *key);
45 void input_internal_key(const char *key);
48 int input_init(void)
50 debug(RPT_DEBUG, "%s()", __FUNCTION__);
52 keylist = LL_new();
54 /* Get rotate/scroll keys from config file */
55 toggle_rotate_key = strdup(config_get_string("server", "ToggleRotateKey", 0, "Enter"));
56 prev_screen_key = strdup(config_get_string("server", "PrevScreenKey", 0, "Left"));
57 next_screen_key = strdup(config_get_string("server", "NextScreenKey", 0, "Right"));
58 scroll_up_key = strdup(config_get_string("server", "ScrollUpKey", 0, "Up"));
59 scroll_down_key = strdup(config_get_string("server", "ScrollDownKey", 0, "Down"));
61 return 0;
65 int input_shutdown()
67 if (!keylist) {
68 /* Program shutdown before completed startup */
69 return -1;
72 free(keylist);
74 free(toggle_rotate_key);
75 free(prev_screen_key);
76 free(next_screen_key);
77 free(scroll_up_key);
78 free(scroll_down_key);
80 return 0;
84 int
85 handle_input(void)
87 const char *key;
88 Screen *current_screen;
89 Client *current_client;
90 Client *target;
91 KeyReservation *kr;
93 debug(RPT_DEBUG, "%s()", __FUNCTION__);
95 current_screen = screenlist_current();
96 if (current_screen)
97 current_client = current_screen->client;
98 else
99 current_client = NULL;
101 /* Handle all keypresses */
102 while ((key = drivers_get_key()) != NULL) {
104 /* Find what client wants the key */
105 kr = input_find_key(key, current_client);
106 if (kr) {
107 /* A hit ! */
108 report(RPT_DEBUG, "%s: reserved key: \"%.40s\"", __FUNCTION__, key);
109 target = kr->client;
110 } else {
111 report(RPT_DEBUG, "%s: left over key: \"%.40s\"", __FUNCTION__, key);
112 /*target = current_client;*/
113 target = NULL; /* left-over keys are always for internal client */
115 if (target == NULL) {
116 report(RPT_DEBUG, "%s: key is for internal client", __FUNCTION__);
117 input_internal_key(key);
118 } else {
119 /* It's an external client */
120 report(RPT_DEBUG, "%s: key is for external client on socket %d", __FUNCTION__, target->sock);
121 input_send_to_client(target, key);
124 return 0;
128 void input_send_to_client(Client *c, const char *key)
130 char *s;
131 size_t size = strlen(key) + sizeof("key %s\n"); // this is large enough
133 debug(RPT_DEBUG, "%s(client=[%d], key=\"%.40s\")", __FUNCTION__, c->sock, key);
135 /* Allocate just as much as we need */
136 s = calloc(1, size);
137 if (s != NULL) {
138 snprintf(s, size, "key %s\n", key);
139 sock_send_string(c->sock, s);
140 free(s);
142 else
143 report(RPT_ERR, "%s: malloc failure", __FUNCTION__);
147 void
148 input_internal_key(const char *key)
150 if (is_menu_key(key) || screenlist_current() == menuscreen) {
151 menuscreen_key_handler(key);
153 else {
154 /* Keys are for scrolling or rotating */
155 if (strcmp(key,toggle_rotate_key) == 0) {
156 autorotate = !autorotate;
157 if (autorotate) {
158 server_msg("Rotate", 4);
159 } else {
160 server_msg("Hold", 4);
163 else if (strcmp(key,prev_screen_key) == 0) {
164 screenlist_goto_prev();
165 server_msg("Prev", 4);
167 else if (strcmp(key,next_screen_key) == 0) {
168 screenlist_goto_next();
169 server_msg("Next", 4);
171 else if (strcmp(key,scroll_up_key) == 0) {
173 else if (strcmp(key,scroll_down_key) == 0) {
178 int input_reserve_key(const char *key, bool exclusive, Client *client)
180 KeyReservation *kr;
182 debug(RPT_DEBUG, "%s(key=\"%.40s\", exclusive=%d, client=[%d])", __FUNCTION__, key, exclusive, (client?client->sock:-1));
184 /* Find out if this key is already reserved in a way that interferes
185 * with the new reservation.
187 for (kr = LL_GetFirst(keylist); kr; kr = LL_GetNext(keylist)) {
188 if (strcmp(kr->key, key) == 0) {
189 if (kr->exclusive || exclusive) {
190 /* Sorry ! */
191 return -1;
196 /* We can now safely add it ! */
197 kr = malloc(sizeof(KeyReservation));
198 kr->key = strdup(key);
199 kr->exclusive = exclusive;
200 kr->client = client;
201 LL_Push(keylist, kr);
203 report(RPT_INFO, "Key \"%.40s\" is now reserved in %s mode by client [%d]", key, (exclusive?"exclusive":"shared"), (client?client->sock:-1));
205 return 0;
208 void input_release_key(const char *key, Client *client)
210 KeyReservation *kr;
212 debug(RPT_DEBUG, "%s(key=\"%.40s\", client=[%d])", __FUNCTION__, key, (client?client->sock:-1));
214 for (kr = LL_GetFirst(keylist); kr; kr = LL_GetNext(keylist)) {
215 if (kr->client == client
216 && strcmp(kr->key, key) == 0) {
217 free(kr->key);
218 free(kr);
219 LL_DeleteNode(keylist);
220 report(RPT_INFO, "Key \"%.40s\" was reserved in %s mode by client [%d] and is now released", key, (kr->exclusive?"exclusive":"shared"), (client?client->sock:-1));
221 return;
226 void input_release_client_keys(Client *client)
228 KeyReservation *kr;
230 debug(RPT_DEBUG, "%s(client=[%d])", __FUNCTION__, (client?client->sock:-1));
232 kr=LL_GetFirst(keylist);
233 while (kr) {
234 if (kr->client == client) {
235 report(RPT_INFO, "Key \"%.40s\" was reserved in %s mode by client [%d] and is now released", kr->key, (kr->exclusive?"exclusive":"shared"), (client?client->sock:-1));
236 free(kr->key);
237 free(kr);
238 LL_DeleteNode(keylist);
239 kr = LL_Get(keylist);
240 } else {
241 kr = LL_GetNext(keylist);
246 KeyReservation *input_find_key(const char *key, Client *client)
248 KeyReservation *kr;
250 debug(RPT_DEBUG, "%s(key=\"%.40s\", client=[%d])", __FUNCTION__, key, (client?client->sock:-1));
252 for (kr = LL_GetFirst(keylist); kr; kr = LL_GetNext(keylist)) {
253 if (strcmp(kr->key, key) == 0) {
254 if (kr->exclusive || client==kr->client) {
255 return kr;
259 return NULL;