~benklop/+junk/lcdproc

« back to all changes in this revision

Viewing changes to server/input.c

  • Committer: Bazaar Package Importer
  • Author(s): Jose Luis Tallon
  • Date: 2006-07-23 20:23:48 UTC
  • mfrom: (3 sarge)
  • mto: (3.1.1 sid) (1.1.5 upstream)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20060723202348-3ngyais3pem8xyrm
Tags: upstream-0.5.0
ImportĀ upstreamĀ versionĀ 0.5.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 * This file is released under the GNU General Public License. Refer to the
6
6
 * COPYING file distributed with this package.
7
7
 *
8
 
 * Copyright    (c) 1999, William Ferrell, Scott Scriven
9
 
 *              (c) 2001, Rene Wagner
 
8
 * Copyright (c) 1999, William Ferrell, Scott Scriven
 
9
 *               2003, Joris Robijn
10
10
 *
11
11
 *
12
12
 * Handles keypad (and other?) input from the user.
13
13
 */
14
14
 
15
 
/*
16
 
 
17
 
  Currently, the keys are as follows:
18
 
 
19
 
  Context     Key      Function
20
 
  -------     ---      --------
21
 
  Normal               "normal" context is handled in this source file.
22
 
              A        Pause/Continue
23
 
              B        Back(Go to previous screen)
24
 
              C        Forward(Go to next screen)
25
 
              D        Open main menu
26
 
              E-Z      Sent to client, if any; ignored otherwise
27
 
 
28
 
 (menu keys are not handled here, but in the menu code)
29
 
  Menu
30
 
              A        Enter/select
31
 
              B        Up/Left
32
 
              C        Down/Right
33
 
              D        Exit/Cancel
34
 
              E-Z      Ignored
35
 
*/
36
15
 
37
16
 
38
17
#include <stdlib.h>
41
20
 
42
21
#include "shared/sockets.h"
43
22
#include "shared/report.h"
44
 
 
45
 
#include "drivers/lcd.h"
46
 
 
47
 
#include "client_data.h"
48
 
#include "clients.h"
49
 
#include "screen.h"
50
 
#include "widget.h"
 
23
#include "shared/configfile.h"
 
24
 
 
25
#include "drivers.h"
 
26
 
 
27
#include "client.h"
51
28
#include "screenlist.h"
52
 
#include "menus.h"
 
29
#include "menuscreens.h"
53
30
 
54
31
#include "input.h"
55
 
 
56
 
#define KeyWanted(a,b)  ((a) && strchr((a), (b)))
57
 
#define CurrentScreen   screenlist_current
58
 
#define FirstClient(a)  (client *)LL_GetFirst(a);
59
 
#define NextClient(a)   (client *)LL_GetNext(a);
60
 
 
 
32
#include "render.h" /* For server_msg* */
 
33
 
 
34
 
 
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;
 
41
 
 
42
/* Local functions */
61
43
int server_input (int key);
62
 
 
63
 
/* FIXME!  The server tends to crash when "E" is pressed..  (?!)
64
 
 * (but only when the joystick driver is the last one on the list...)
65
 
 */
66
 
 
67
 
/* Checks for keypad input, and dispatches it*/
 
44
void input_send_to_client (Client * c, const char * key);
 
45
void input_internal_key (const char * key);
 
46
 
 
47
 
 
48
int input_init()
 
49
{
 
50
        debug (RPT_DEBUG, "%s()", __FUNCTION__ );
 
51
 
 
52
        keylist = LL_new();
 
53
 
 
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"));
 
60
 
 
61
        return 0;
 
62
}
 
63
 
 
64
 
 
65
int input_shutdown()
 
66
{
 
67
        if (!keylist) {
 
68
                /* Program shutdown before completed startup */
 
69
                return -1;
 
70
        }
 
71
 
 
72
        free (keylist);
 
73
 
 
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);
 
79
 
 
80
        return 0;
 
81
}
 
82
 
 
83
 
68
84
int
69
85
handle_input ()
70
86
{
71
 
        char str[15];
72
 
        int key;
73
 
        screen *s;
74
 
        /*widget *w;*/
75
 
        client *c;
76
 
 
77
 
        if ((key = lcd_ptr->getkey ()) == 0)
78
 
                return 0;
79
 
 
80
 
        /*debug (RPT_DEBUG, "handle_input(%c)", (char) key);*/
81
 
 
82
 
        /* Sequence:
83
 
         *      Does the current screen want the key?
84
 
         *      IfTrue: handle and quit
85
 
         *      IfFalse:
86
 
         *          Let ALL clients handle it if they want
87
 
         *          Let Server handle it, too
88
 
         *
89
 
         * This leads to a unique situation:
90
 
         *     First: multiple clients may handle the same key in multiple ways
91
 
         *     Second: the server may handle the key differently yet
92
 
         *
93
 
         * Solution: Only the current screen can handle the key press.
94
 
         * Alternately, only one client can handle the key press.
95
 
         */
96
 
 
97
 
        /* TODO:  Interpret and translate keys!*/
98
 
 
99
 
        /* Give current screen a shot at the key first*/
100
 
        s = CurrentScreen ();
101
 
 
102
 
        if (KeyWanted(s->keys, key)) {
103
 
                /* This screen wants this key.  Tell it we got one*/
104
 
                snprintf(str, sizeof(str), "key %c\n", key);
105
 
                sock_send_string(s->parent->sock, str);
106
 
                /* Nobody else gets this key*/
107
 
        }
108
 
 
109
 
        /* if the current screen doesn't want it,
110
 
         * let the server have it...
111
 
         */
112
 
 
 
87
        const char * key;
 
88
        Screen * current_screen;
 
89
        Client * current_client;
 
90
        Client * target;
 
91
        KeyReservation * kr;
 
92
 
 
93
        debug (RPT_DEBUG, "%s()", __FUNCTION__ );
 
94
 
 
95
        current_screen = screenlist_current();
 
96
        if( current_screen )
 
97
                current_client = current_screen->client;
 
98
        else
 
99
                current_client = NULL;
 
100
 
 
101
        /* Handle all keypresses */
 
102
        while ((key = drivers_get_key ()) != NULL ) {
 
103
 
 
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 */
 
114
                }
 
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);
 
122
                }
 
123
        }
 
124
        return 0;
 
125
}
 
126
 
 
127
 
 
128
void input_send_to_client (Client * c, const char * key)
 
129
{
 
130
        char * s;
 
131
        size_t size = strlen(key) + sizeof("key %s\n"); // this is large enough
 
132
 
 
133
        debug (RPT_DEBUG, "%s( client=[%d], key=\"%.40s\" )", __FUNCTION__, c->sock, key);
 
134
 
 
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);
 
141
        }       
 
142
        else
 
143
                report(RPT_ERR, "%s: malloc failure", __FUNCTION__);
 
144
}
 
145
 
 
146
 
 
147
void
 
148
input_internal_key (const char * key)
 
149
{
 
150
        if( is_menu_key(key) || screenlist_current() == menuscreen ) {
 
151
                menuscreen_key_handler(key);
 
152
        }
113
153
        else {
114
 
                /* Give key to clients who want it*/
115
 
 
116
 
                c = FirstClient(clients);
117
 
 
118
 
                while (c) {
119
 
                        /* If the client should have this keypress...*/
120
 
                        if(KeyWanted(c->data->client_keys,key)) {
121
 
                                /* Send keypress to client*/
122
 
                                snprintf(str, sizeof(str), "key %c\n", key);
123
 
                                sock_send_string(c->sock, str);
124
 
                                break;  /* first come, first serve*/
125
 
                        };
126
 
                        c = NextClient(clients);
127
 
                } /* while clients*/
128
 
 
129
 
                /* Give server a shot at all keys*/
130
 
                server_input (key);
131
 
        }
132
 
 
133
 
        return 0;
134
 
}
135
 
 
136
 
int
137
 
server_input (int key)
138
 
{
139
 
        debug (RPT_INFO, "server_input(%c)", (char) key);
140
 
        report(RPT_INFO, "key %d pressed on device", key);
141
 
 
142
 
        switch ((char) key) {
143
 
                case INPUT_PAUSE_KEY:
144
 
                        if (screenlist_action == SCR_HOLD)
145
 
                                screenlist_action = 0;
146
 
                        else
147
 
                                screenlist_action = SCR_HOLD;
148
 
                        break;
149
 
                case INPUT_BACK_KEY:
150
 
                        screenlist_action = SCR_BACK;
151
 
                        screenlist_prev ();
152
 
                        break;
153
 
                case INPUT_FORWARD_KEY:
154
 
                        screenlist_action = SCR_SKIP;
155
 
                        screenlist_next ();
156
 
                        break;
157
 
                case INPUT_MAIN_MENU_KEY:
158
 
                        debug (RPT_DEBUG, "got the menu key!");
159
 
                        server_menu ();
160
 
                        break;
161
 
                default:
162
 
                        debug (RPT_DEBUG, "server_input: Unused key \"%c\" (%i)", (char) key, key);
163
 
                        break;
164
 
        }
165
 
 
166
 
        return 0;
 
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 );
 
161
                        }
 
162
                }
 
163
                else if( strcmp(key,prev_screen_key) == 0 ) {
 
164
                        screenlist_goto_prev ();
 
165
                        server_msg( "Prev", 4 );
 
166
                }
 
167
                else if( strcmp(key,next_screen_key) == 0 ) {
 
168
                        screenlist_goto_next ();
 
169
                        server_msg( "Next", 4 );
 
170
                }
 
171
                else if( strcmp(key,scroll_up_key) == 0 ) {
 
172
                }
 
173
                else if( strcmp(key,scroll_down_key) == 0 ) {
 
174
                }
 
175
        }
 
176
}
 
177
 
 
178
int input_reserve_key (const char * key, bool exclusive, Client * client)
 
179
{
 
180
        KeyReservation * kr;
 
181
 
 
182
        debug (RPT_DEBUG, "%s( key=\"%.40s\", exclusive=%d, client=[%d] )", __FUNCTION__, key, exclusive, (client?client->sock:-1));
 
183
 
 
184
        /* Find out if this key is already reserved in a way that interferes
 
185
         * with the new reservation.
 
186
         */
 
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;
 
192
                        }
 
193
                }
 
194
        }
 
195
 
 
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);
 
202
 
 
203
        report (RPT_INFO, "Key \"%.40s\" is now reserved in %s mode by client [%d]", key, (exclusive?"exclusive":"shared"), (client?client->sock:-1));
 
204
 
 
205
        return 0;
 
206
}
 
207
 
 
208
void input_release_key (const char * key, Client * client)
 
209
{
 
210
        KeyReservation * kr;
 
211
 
 
212
        debug (RPT_DEBUG, "%s( key=\"%.40s\", client=[%d] )", __FUNCTION__, key, (client?client->sock:-1));
 
213
 
 
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;
 
222
                }
 
223
        }
 
224
}
 
225
 
 
226
void input_release_client_keys (Client * client)
 
227
{
 
228
        KeyReservation * kr;
 
229
 
 
230
        debug (RPT_DEBUG, "%s( client=[%d] )", __FUNCTION__, (client?client->sock:-1));
 
231
 
 
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);
 
242
                }
 
243
        }
 
244
}
 
245
 
 
246
KeyReservation * input_find_key (const char * key, Client * client)
 
247
{
 
248
        KeyReservation * kr;
 
249
 
 
250
        debug (RPT_DEBUG, "%s( key=\"%.40s\", client=[%d] )", __FUNCTION__, key, (client?client->sock:-1));
 
251
 
 
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;
 
256
                        }
 
257
                }
 
258
        }
 
259
        return NULL;
167
260
}