/* * screens_commands.c * This file is part of LCDd, the lcdproc server. * * This file is released under the GNU General Public License. Refer to the * COPYING file distributed with this package. * * Copyright (c) 1999, William Ferrell, Scott Scriven * 2002, Joris Robijn * * * This contains definitions for all the functions which clients can run. * The functions here are to be called only from parse.c's interpreter. * * The client's available function set is defined here, as is the syntax * for each command. * * This particular file defines actions concerning screens. * */ #include #include #include #include #include #include #include "shared/report.h" #include "shared/sockets.h" #include "client.h" #include "screen.h" #include "render.h" /*************************************************************** * Tells the server the client has another screen to offer * * usage: screen_add */ int screen_add_func (Client * c, int argc, char **argv) { int err = 0; Screen * s; if (!c->ack) return 1; if (argc != 2) { switch (argc) { case 1: sock_send_string (c->sock, "huh? Usage: screen_add \n"); break; default: sock_send_string (c->sock, "huh? Too many parameters...\n"); break; } return 0; } debug(RPT_DEBUG, "screen_add: Adding screen %s", argv[1]); s = client_find_screen (c, argv[1]); if (s) { sock_send_string(c->sock, "huh? Screen already exists\n"); return 0; } s = screen_create (argv[1], c); if (!s) { report(RPT_ERR, "screen_add_func: Error creating screen"); sock_send_string (c->sock, "huh? failed to create screen\n"); return 0; } err = client_add_screen (c, s); if (err == 0) { sock_send_string(c->sock, "success\n"); } else { report(RPT_WARNING, "screen_add_func: Error adding screen"); sock_send_string (c->sock, "huh? Failed to add screen\n"); } report(RPT_NOTICE, "added a screen (%s) to the display", s->id); return 0; } /**************************************************************** * Client requests that the server forget about a screen * * usage: screen_del */ int screen_del_func (Client * c, int argc, char **argv) { int err = 0; Screen * s; if (!c->ack) return 1; if (argc != 2) { if (argc == 1) sock_send_string (c->sock, "huh? Usage: screen_del \n"); else sock_send_string (c->sock, "huh? Too many parameters...\n"); return 0; } debug (RPT_DEBUG, "screen_del: Deleting screen %s", argv[1]); s = client_find_screen (c, argv[1]); if (!s) { sock_send_string(c->sock, "huh? Unknown screen id\n"); return 0; } err = client_remove_screen (c, s); if ( err == 0 ) sock_send_string(c->sock, "success\n"); else if (err < 0) { report(RPT_WARNING, "screen_del_func: Error removing screen"); sock_send_string(c->sock, "huh? Failed to remove screen\n"); } else sock_send_string (c->sock, "huh? Unknown screen id\n"); report(RPT_NOTICE, "removed a screen (%s) from the display", argv[1]); return 0; } /*************************************************************** * Configures info about a particular screen, such as its * name, priority, or duration * * usage: screen_set [ -priority ] [ -name ] [ -duration ] * [ -wid ] [ -hgt ] [ -heartbeat ] [ -cursor ] * [ -cursor_x ] [ -cursor_y ] */ int screen_set_func (Client * c, int argc, char **argv) { int i; int number; char *id; Screen * s; if (!c->ack) return 1; if (argc == 1) { sock_send_string (c->sock, "huh? Usage: screen_set [ -priority ] [ -name ] [ -duration ] [ -wid ] [ -hgt ] [ -heartbeat ]\n"); return 0; } else if (argc == 2) { sock_send_string (c->sock, "huh? What do you want to set?\n"); return 0; } id = argv[1]; s = client_find_screen (c, id); if (!s) { sock_send_string (c->sock, "huh? Unknown screen id\n"); return 0; } /* Handle the rest of the parameters*/ for (i = 2; i < argc; i++) { char *p; /* The following code allows us to use p for comparisions, * ignoring a (valid) single leading '-' - reduces string comparisons * by half. */ p = argv[i]; if (*p == '-') p++; /* Handle the "name" parameter*/ if (strcmp (p, "name") == 0) { if (argc > i + 1) { i++; debug (RPT_DEBUG, "screen_set: name=\"%s\"", argv[i]); /* set the name...*/ if (s->name) free (s->name); s->name = strdup (argv[i]); sock_send_string(c->sock, "success\n"); } else { sock_send_string (c->sock, "huh? -name requires a parameter\n"); } } /* Handle the "priority" parameter*/ else if (strcmp (p, "priority") == 0) { if (argc > i + 1) { i++; debug (RPT_DEBUG, "screen_set: priority=\"%s\"", argv[i]); /* set the priority...*/ number = atoi (argv[i]); if (number > 0) s->priority = number; sock_send_string(c->sock, "success\n"); } else { sock_send_string (c->sock, "huh? -priority requires a parameter\n"); } } /* Handle the "duration" parameter*/ else if (strcmp (p, "duration") == 0) { if (argc > i + 1) { i++; debug (RPT_DEBUG, "screen_set: duration=\"%s\"", argv[i]); /* set the duration...*/ number = atoi (argv[i]); if (number > 0) s->duration = number; sock_send_string(c->sock, "success\n"); } else { sock_send_string (c->sock, "huh? -duration requires a parameter\n"); } } /* Handle the "heartbeat" parameter*/ else if (strcmp (p, "heartbeat") == 0) { if (argc > i + 1) { i++; debug (RPT_DEBUG, "screen_set: heartbeat=\"%s\"", argv[i]); /* set the heartbeat type...*/ if (0 == strcmp (argv[i], "on")) s->heartbeat = HEARTBEAT_ON; else if (0 == strcmp (argv[i], "off")) s->heartbeat = HEARTBEAT_OFF; else if (0 == strcmp (argv[i], "open")) s->heartbeat = HEARTBEAT_OPEN; sock_send_string(c->sock, "success\n"); } else { sock_send_string (c->sock, "huh? -heartbeat requires a parameter\n"); } } /* Handle the "wid" parameter*/ else if (strcmp (p, "wid") == 0) { if (argc > i + 1) { i++; debug (RPT_DEBUG, "screen_set: wid=\"%s\"", argv[i]); /* set the duration...*/ number = atoi (argv[i]); if (number > 0) s->width = number; sock_send_string(c->sock, "success\n"); } else { sock_send_string (c->sock, "huh? -wid requires a parameter\n"); } } /* Handle the "hgt" parameter*/ else if (strcmp (p, "hgt") == 0) { if (argc > i + 1) { i++; debug (RPT_DEBUG, "screen_set: hgt=\"%s\"", argv[i]); /* set the duration...*/ number = atoi (argv[i]); if (number > 0) s->height = number; sock_send_string(c->sock, "success\n"); } else { sock_send_string (c->sock, "huh? -hgt requires a parameter\n"); } } /* Handle the "timeout" parameter*/ else if (strcmp (p, "timeout") == 0) { if (argc > i + 1) { i++; debug (RPT_DEBUG, "screen_set: timeout=\"%s\"", argv[i]); /* set the duration...*/ number = atoi (argv[i]); /* Add the timeout value (count of TIME_UNITS) * to struct, TIME_UNIT is 1/8th of a second */ if (number > 0) { s->timeout = number; report(RPT_NOTICE, "Timeout set."); } sock_send_string(c->sock, "success\n"); } else { sock_send_string (c->sock, "huh? -timeout requires a parameter\n"); } } /* Handle the "backlight" parameter*/ else if (strcmp (p, "backlight") == 0) { if (argc > i + 1) { i++; debug (RPT_DEBUG, "screen_set: backlight=\"%s\"", argv[i]); /* set the backlight status based on what the client has set*/ switch(c->backlight) { case BACKLIGHT_OPEN: if (strcmp ("on", argv[i]) == 0) s->backlight = BACKLIGHT_ON; if (strcmp ("off", argv[i]) == 0) s->backlight = BACKLIGHT_OFF; if (strcmp ("toggle", argv[i]) == 0) { if (s->backlight == BACKLIGHT_ON) s->backlight = BACKLIGHT_OFF; else if (s-backlight == BACKLIGHT_OFF) s->backlight = BACKLIGHT_ON; } if (strcmp ("blink", argv[i]) == 0) s->backlight |= BACKLIGHT_BLINK; if (strcmp ("flash", argv[i]) == 0) s->backlight |= BACKLIGHT_FLASH; break; default: /*If the backlight is not OPEN then inherit its state*/ s->backlight = c->backlight; break; } sock_send_string(c->sock, "success\n"); } else { sock_send_string (c->sock, "huh? -backlight requires a parameter\n"); } } /* Handle the "cursor" parameter */ else if (strcmp (p, "cursor") == 0) { if (argc > i + 1) { i++; debug (RPT_DEBUG, "screen_set: cursor=\"%s\"", argv[i]); /* set the heartbeat type...*/ if (0 == strcmp (argv[i], "off")) s->heartbeat = CURSOR_OFF; if (0 == strcmp (argv[i], "on")) s->cursor = CURSOR_DEFAULT_ON; if (0 == strcmp (argv[i], "under")) s->cursor = CURSOR_UNDER; if (0 == strcmp (argv[i], "block")) s->cursor = CURSOR_BLOCK; sock_send_string(c->sock, "success\n"); } else { sock_send_string (c->sock, "huh? -cursor requires a parameter\n"); } } /* Handle the "cursor_x" parameter */ else if (strcmp (p, "cursor_x") == 0) { if (argc > i + 1) { i++; debug (RPT_DEBUG, "screen_set: cursor_x=\"%s\"", argv[i]); /* set the position...*/ number = atoi (argv[i]); if (number > 0 && number <= s->width) { s->cursor_x = number; sock_send_string(c->sock, "success\n"); } else { sock_send_string(c->sock, "huh? Cursor position outside screen\n"); } } else { sock_send_string (c->sock, "huh? -cursor_x requires a parameter\n"); } } /* Handle the "cursor_y" parameter */ else if (strcmp (p, "cursor_y") == 0) { if (argc > i + 1) { i++; debug (RPT_DEBUG, "screen_set: cursor_y=\"%s\"", argv[i]); /* set the position...*/ number = atoi (argv[i]); if (number > 0 && number <= s->height) { s->cursor_y = number; sock_send_string(c->sock, "success\n"); } else { sock_send_string(c->sock, "huh? Cursor position outside screen\n"); } } else { sock_send_string (c->sock, "huh? -cursor_y requires a parameter\n"); } } else sock_send_string (c->sock, "huh? invalid parameter\n"); }/* done checking argv*/ return 0; } /********************************************************************** * Tells the server the client would like to accept keypresses * of a particular type when the given screen is active on the display * * screen_add_key */ int screen_add_key_func (Client * c, int argc, char **argv) { /*widget * w ;*/ /* Keys are stored on a WID_KEYS widget */ Screen * s ; /* Attached to a specific screen */ char * id ; /* Screen ID */ char * keys ; /* Keys wanted */ if (!c->ack) return 1; if (argc != 3) { switch (argc) { case 1: sock_send_string (c->sock, "huh? Usage: screen_add_key \n"); break; case 2: sock_send_string (c->sock, "huh? You must specify a key list\n"); break; default: sock_send_string (c->sock, "huh? Too many parameters...\n"); break; } return 0; } id = argv[1]; keys = argv[2]; debug(RPT_DEBUG, "screen_add_key: Adding key(s) %s to screen %s", keys, id); /* Find the screen*/ s = client_find_screen (c, id); if (!s) { sock_send_string (c->sock, "huh? Unknown screen id\n"); return 0; } /* Save the keys*/ if (!s->keys) { /* Save supplied key list*/ s->keys = strdup( keys ); } else { /* Add supplied keys to existing list * NOTE: There could be duplicates in the resulting list * That's OK, it's the existence of the key in the list * that's important. We'll be more careful in the delete * key function. */ char * new_keys ; new_keys = realloc( s->keys, strlen(s->keys) + strlen(keys) +1 ); if (new_keys) { strcpy (new_keys, s->keys); strcat (new_keys, keys ); free (s->keys); s->keys = new_keys; } else { report (RPT_WARNING, "screen_add_key: Allocation error"); sock_send_string(c->sock, "huh? Could not add new keys\n"); return 0; } } if (!s->keys) { sock_send_string(c->sock, "huh? failed\n"); } else sock_send_string(c->sock, "success\n"); return 0; } /************************************************************************* * Tells the server the client would NOT like to accept keypresses * of a particular type when the given screen is active on the display * * usage: screen_del_key */ int screen_del_key_func (Client * c, int argc, char **argv) { /*widget * w ;*/ /* Keys are stored on a WID_KEYS widget */ Screen * s ; /* Attached to a specific screen */ char * id ; /* Screen ID */ char * keys ; /* Keys wanted */ if (!c->ack) return 1; if (argc != 3) { switch (argc) { case 1: sock_send_string (c->sock, "huh? Usage: screen_del_key \n"); break; case 2: sock_send_string (c->sock, "huh? You must specify a key list\n"); break; default: sock_send_string (c->sock, "huh? Too many parameters\n"); break; } return 0; } id = argv[1] ; keys = argv[2] ; debug(RPT_DEBUG, "screen_del_key: Deleting key(s) %s from screen %s", keys, id); /* Find the screen*/ s = client_find_screen (c, id); if (!s) { sock_send_string (c->sock, "huh? Unknown screen id\n"); return 0; } /* Do we have keys?*/ if (s->keys) { /* Have keys, remove keys from the list * NOTE: We let malloc/realloc remember the length * of the allocated storage. If keys are later * added, realloc (in add_key above) will make * sure there is enough space at s->keys */ char * from ; char * to ; to = from = s->keys ; while( *from ) { /* Is this key to be deleted from the list?*/ if( strchr( keys, *from ) ) { /* Yes, skip it*/ ++from ; } else { /* No, save it*/ *to++ = *from++ ; } } to = '\0'; /* terminates the new keys string...*/ } sock_send_string(c->sock, "success\n"); return 0; }