Base: LCDproc 0.5.2
[lcdproc-de200c.git] / server / drivers.c
blobc7914d4911bfd0f2e1c8a061c154a653cc1ebee9
1 /** \file drivers.c
2 * Manage the lists of loaded drivers and perform actions on all drivers.
3 */
5 /* This file is part of LCDd, the lcdproc server.
7 * This file is released under the GNU General Public License. Refer to the
8 * COPYING file distributed with this package.
10 * Copyright(c) 2001, Joris Robijn
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <unistd.h>
19 #include <string.h>
20 #include <sys/errno.h>
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
26 #include "shared/LL.h"
27 #include "shared/report.h"
28 #include "shared/configfile.h"
30 #include "drivers.h"
31 #include "driver.h"
32 #include "drivers/lcd.h"
33 #include "widget.h"
34 /* lcd.h is used for the driver API definition */
37 LinkedList *loaded_drivers = NULL; /**< list of loaded drivers */
38 DisplayProps *display_props = NULL; /**< properties of the display */
40 #define ForAllDrivers(drv) for (drv = LL_GetFirst(loaded_drivers); drv; drv = LL_GetNext(loaded_drivers))
43 /**
44 * Load driver based on "DriverPath" config setting and section name or
45 * "File" configuration setting in the driver's section.
46 * \param name Driver section name.
47 * \retval <0 error.
48 * \retval 0 OK, driver is an input driver only.
49 * \retval 1 OK, driver is an output driver.
50 * \retval 2 OK, driver is an output driver that needs to run in the foreground.
52 int
53 drivers_load_driver(const char *name)
55 Driver *driver;
56 const char *s;
57 char *driverpath;
58 char *filename;
60 debug(RPT_DEBUG, "%s(name=\"%.40s\")", __FUNCTION__, name);
62 /* First driver ? */
63 if (!loaded_drivers) {
64 /* Create linked list */
65 loaded_drivers = LL_new();
66 if (!loaded_drivers) {
67 report(RPT_ERR, "Error allocating driver list.");
68 return -1;
72 /* Retrieve data from config file */
73 s = config_get_string("server", "DriverPath", 0, "");
74 driverpath = malloc(strlen(s) + 1);
75 strcpy(driverpath, s);
77 s = config_get_string(name, "File", 0, NULL);
78 if (s) {
79 filename = malloc(strlen(driverpath) + strlen(s) + 1);
80 strcpy(filename, driverpath);
81 strcat(filename, s);
82 } else {
83 filename = malloc(strlen(driverpath) + strlen(name) + strlen(MODULE_EXTENSION) + 1);
84 strcpy(filename, driverpath);
85 strcat(filename, name);
86 strcat(filename, MODULE_EXTENSION);
89 /* Load the module */
90 driver = driver_load(name, filename);
91 if (driver == NULL) {
92 /* It failed. The message has already been given by driver_load() */
93 report(RPT_INFO, "Module %.40s could not be loaded", filename);
94 free(driverpath);
95 free(filename);
96 return -1;
99 /* Add driver to list */
100 LL_Push(loaded_drivers, driver);
102 free(driverpath);
103 free(filename);
105 /* If first driver, store display properties */
106 if (driver_does_output(driver) && !display_props) {
107 if (driver->width(driver) <= 0 || driver->width(driver) > LCD_MAX_WIDTH
108 || driver->height(driver) <= 0 || driver->height(driver) > LCD_MAX_HEIGHT) {
109 report(RPT_ERR, "Driver [%.40s] has invalid display size", driver->name);
112 /* Allocate new DisplayProps structure */
113 display_props = malloc(sizeof(DisplayProps));
114 display_props->width = driver->width(driver);
115 display_props->height = driver->height(driver);
117 if (driver->cellwidth != NULL && display_props->cellwidth > 0)
118 display_props->cellwidth = driver->cellwidth(driver);
119 else
120 display_props->cellwidth = LCD_DEFAULT_CELLWIDTH;
122 if (driver->cellheight != NULL && driver->cellheight(driver) > 0)
123 display_props->cellheight = driver->cellheight(driver);
124 else
125 display_props->cellheight = LCD_DEFAULT_CELLHEIGHT;
128 /* Return the driver type */
129 if (driver_does_output(driver)) {
130 if (driver_stay_in_foreground(driver))
131 return 2;
132 else
133 return 1;
135 return 0;
140 * Unload all loaded drivers.
141 * \retval 0
144 drivers_unload_all(void)
146 Driver *driver;
148 debug(RPT_DEBUG, "%s()", __FUNCTION__);
150 while ((driver = LL_Pop(loaded_drivers)) != NULL) {
151 driver_unload(driver);
154 return 0;
159 * Get information from loaded drivers.
160 * \return Pointer to information string of first driver with get_info() function defined,
161 * or the empty string if no driver has a get_info() function.
163 const char *
164 drivers_get_info(void)
166 Driver *drv;
168 debug(RPT_DEBUG, "%s()", __FUNCTION__);
170 ForAllDrivers(drv) {
171 if (drv->get_info) {
172 return drv->get_info(drv);
175 return "";
180 * Clear screen on all loaded drivers.
181 * Call clear() function of all loaded drivers that have a clear() function defined.
183 void
184 drivers_clear(void)
186 Driver *drv;
188 debug(RPT_DEBUG, "%s()", __FUNCTION__);
190 ForAllDrivers(drv) {
191 if (drv->clear)
192 drv->clear(drv);
198 * Flush data on all loaded drivers to LCDs.
199 * Call flush() function of all loaded drivers that have a flush() function defined.
201 void
202 drivers_flush(void)
204 Driver *drv;
206 debug(RPT_DEBUG, "%s()", __FUNCTION__);
208 ForAllDrivers(drv) {
209 if (drv->flush)
210 drv->flush(drv);
216 * Write string to all loaded drivers.
217 * Call string() function of all loaded drivers that have a flush() function defined.
218 * \param x Horizontal character position (column).
219 * \param y Vertical character position (row).
220 * \param string String that gets written.
222 void
223 drivers_string(int x, int y, const char *string)
225 Driver *drv;
227 debug(RPT_DEBUG, "%s(x=%d, y=%d, string=\"%.40s\")", __FUNCTION__, x, y, string);
229 ForAllDrivers(drv) {
230 if (drv->string)
231 drv->string(drv, x, y, string);
237 * Write a character to all loaded drivers.
238 * Call chr() function of all loaded drivers that have a chr() function defined.
239 * \param x Horizontal character position (column).
240 * \param y Vertical character position (row).
241 * \param c Character that gets written.
243 void
244 drivers_chr(int x, int y, char c)
246 Driver *drv;
248 debug(RPT_DEBUG, "%s(x=%d, y=%d, c='%c')", __FUNCTION__, x, y, c);
250 ForAllDrivers(drv) {
251 if (drv->chr)
252 drv->chr(drv, x, y, c);
258 * Draw a vertical bar to all drivers.
259 * For drivers that define a vbar() function, call it;
260 * otherwise call the general driver_alt_vbar() function from the server core.
261 * \param x Horizontal character position (column) of the starting point.
262 * \param y Vertical character position (row) of the starting point.
263 * \param len Number of characters that the bar is long at 100%
264 * \param promille Current length level of the bar in promille.
265 * \param pattern Options (currently unused).
267 void
268 drivers_vbar(int x, int y, int len, int promille, int pattern)
270 Driver *drv;
272 debug(RPT_DEBUG, "%s(x=%d, y=%d, len=%d, promille=%d, pattern=%d)",
273 __FUNCTION__, x, y, len, promille, pattern);
275 /* NEW FUNCTIONS
277 * We need more data in the widget. Requires language update...
281 ForAllDrivers(drv) {
282 if (drv->vbar)
283 drv->vbar(drv, x, y, len, promille, pattern);
284 else
285 driver_alt_vbar(drv, x, y, len, promille, pattern);
291 * Draw a horizontal bar to all drivers.
292 * For drivers that define a hbar() function, call it;
293 * otherwise call the general driver_alt_hbar() function from the server core.
294 * \param x Horizontal character position (column) of the starting point.
295 * \param y Vertical character position (row) of the starting point.
296 * \param len Number of characters that the bar is long at 100%
297 * \param promille Current length level of the bar in promille.
298 * \param pattern Options (currently unused).
300 void
301 drivers_hbar(int x, int y, int len, int promille, int pattern)
303 Driver *drv;
305 debug(RPT_DEBUG, "%s(x=%d, y=%d, len=%d, promille=%d, pattern=%d)",
306 __FUNCTION__, x, y, len, promille, pattern);
308 ForAllDrivers(drv) {
309 if (drv->hbar)
310 drv->hbar(drv, x, y, len, promille, pattern);
311 else
312 driver_alt_hbar(drv, x, y, len, promille, pattern);
318 * Write a big number to all output drivers.
319 * For drivers that define a num() function, call it;
320 * otherwise call the general driver_alt_num() function from the server core.
321 * \param x Horizontal character position (column).
322 * \param num Character to write (0 - 10 with 10 representing ':')
324 void
325 drivers_num(int x, int num)
327 Driver *drv;
329 debug(RPT_DEBUG, "%s(x=%d, num=%d)", __FUNCTION__, x, num);
331 ForAllDrivers(drv) {
332 if (drv->num)
333 drv->num(drv, x, num);
334 else
335 driver_alt_num(drv, x, num);
341 * Perform heartbeat on all drivers.
342 * For drivers that define a heartbeat() function, call it;
343 * otherwise call the general driver_alt_heartbeat() function from the server core.
344 * \param state Heartbeat state.
346 void
347 drivers_heartbeat(int state)
349 Driver *drv;
351 debug(RPT_DEBUG, "%s(state=%d)", __FUNCTION__, state);
353 ForAllDrivers(drv) {
354 if (drv->heartbeat)
355 drv->heartbeat(drv, state);
356 else
357 driver_alt_heartbeat(drv, state);
363 * Write icon to all drivers.
364 * For drivers that define a icon() function, call it;
365 * otherwise call the general driver_alt_icon() function from the server core.
366 * If the driver's locally defined icon() function returns -1, then also
367 * call the server core's driver_alt_icon().
368 * \param x Horizontal character position (column).
369 * \param y Vertical character position (row).
370 * \param icon synbolic value representing the icon.
372 void
373 drivers_icon(int x, int y, int icon)
375 Driver *drv;
377 debug(RPT_DEBUG, "%s(x=%d, y=%d, icon=ICON_%s)", __FUNCTION__, x, y, widget_icon_to_iconname(icon));
379 ForAllDrivers(drv) {
380 /* Does the driver have the icon function ? */
381 if (drv->icon) {
382 /* Try driver call */
383 if (drv->icon(drv, x, y, icon) == -1) {
384 /* do alternative call if driver's function does not know the icon */
385 driver_alt_icon(drv, x, y, icon);
387 } else {
388 /* Also do alternative call if the driver does not have icon function */
389 driver_alt_icon(drv, x, y, icon);
396 * Set cursor on all loaded drivers.
397 * For drivers that define a cursor() function, call it;
398 * otherwise call the general driver_alt_cursor() function from the server core.
399 * \param x Horizontal cursor position (column).
400 * \param y Vertical cursor position (row).
401 * \param state New cursor state.
403 void
404 drivers_cursor(int x, int y, int state)
406 Driver *drv;
408 debug(RPT_DEBUG, "%s(x=%d, y=%d, state=%d)", __FUNCTION__, x, y, state);
410 ForAllDrivers(drv) {
411 if (drv->cursor)
412 drv->cursor(drv, x, y, state);
413 else
414 driver_alt_cursor(drv, x, y, state);
420 * Set backlight on all drivers.
421 * Call backlight() function of all drivers that have a backlight() function defined.
422 * \param state New backlight status.
424 void
425 drivers_backlight(int state)
427 Driver *drv;
429 debug(RPT_DEBUG, "%s(state=%d)", __FUNCTION__, state);
431 ForAllDrivers(drv) {
432 if (drv->backlight)
433 drv->backlight(drv, state);
439 * Set output on all drivers.
440 * Call ouptput() function of all drivers that have an ouptput() function defined.
441 * \param state New ouptut status.
443 void
444 drivers_output(int state)
446 Driver *drv;
448 debug(RPT_DEBUG, "%s(state=%d)", __FUNCTION__, state);
450 ForAllDrivers(drv) {
451 if (drv->output)
452 drv->output(drv, state);
458 * Get key presses from loaded drivers.
459 * \return Pointer to key string for first driver ithat has a get_key() function defined
460 * and for which the get_key() function returns a key; otherwise \c NULL.
462 const char *
463 drivers_get_key(void)
465 /* Find the first input keystroke, if any */
466 Driver *drv;
467 const char *keystroke;
469 debug(RPT_DEBUG, "%s()", __FUNCTION__);
471 ForAllDrivers(drv) {
472 if (drv->get_key) {
473 keystroke = drv->get_key(drv);
474 if (keystroke != NULL) {
475 report(RPT_INFO, "Driver [%.40s] generated keystroke %.40s", drv->name, keystroke);
476 return keystroke;
480 return NULL;