2001-12-27 23:30:36 +00:00
|
|
|
/*
|
|
|
|
|
* screenlist.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
|
2003-02-27 21:20:20 +00:00
|
|
|
* 2003, Joris Robijn
|
2001-12-27 23:30:36 +00:00
|
|
|
*
|
|
|
|
|
*
|
2003-02-27 21:20:20 +00:00
|
|
|
* All actions that can be performed on the list of screens.
|
|
|
|
|
* This file also manages the rotation of screens.
|
2001-12-27 23:30:36 +00:00
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
1999-12-09 23:15:14 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
2001-05-25 03:14:27 +00:00
|
|
|
#include "shared/LL.h"
|
|
|
|
|
#include "shared/sockets.h"
|
2001-11-29 14:09:13 +00:00
|
|
|
#include "shared/report.h"
|
1999-12-09 23:15:14 +00:00
|
|
|
#include "screenlist.h"
|
|
|
|
|
#include "screen.h"
|
|
|
|
|
|
2002-08-04 20:58:51 +00:00
|
|
|
#include "main.h" /* for timer */
|
|
|
|
|
|
2003-02-27 21:20:20 +00:00
|
|
|
/* Local functions */
|
2007-04-02 21:29:53 +00:00
|
|
|
int compare_priority(void *one, void *two);
|
1999-12-09 23:15:14 +00:00
|
|
|
|
2003-02-27 21:20:20 +00:00
|
|
|
bool autorotate = 1; /* If on, INFO and FOREGROUND screens will rotate */
|
2002-08-04 20:58:51 +00:00
|
|
|
LinkedList *screenlist = NULL;
|
2007-04-02 21:29:53 +00:00
|
|
|
Screen *current_screen = NULL;
|
2003-02-27 21:20:20 +00:00
|
|
|
long int current_screen_start_time = 0;
|
1999-12-09 23:15:14 +00:00
|
|
|
|
|
|
|
|
|
2000-03-30 20:20:41 +00:00
|
|
|
int
|
2007-04-02 21:29:53 +00:00
|
|
|
screenlist_init(void)
|
1999-12-09 23:15:14 +00:00
|
|
|
{
|
2007-04-02 21:29:53 +00:00
|
|
|
report(RPT_DEBUG, "%s()", __FUNCTION__);
|
2000-03-30 20:20:41 +00:00
|
|
|
|
2007-04-02 21:29:53 +00:00
|
|
|
screenlist = LL_new();
|
2000-04-03 22:13:57 +00:00
|
|
|
if (!screenlist) {
|
2003-02-27 21:20:20 +00:00
|
|
|
report(RPT_ERR, "%s: Error allocating", __FUNCTION__);
|
2000-04-03 22:13:57 +00:00
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
1999-12-09 23:15:14 +00:00
|
|
|
}
|
|
|
|
|
|
2003-02-27 21:20:20 +00:00
|
|
|
|
2000-03-30 20:20:41 +00:00
|
|
|
int
|
2007-04-02 21:29:53 +00:00
|
|
|
screenlist_shutdown(void)
|
1999-12-09 23:15:14 +00:00
|
|
|
{
|
2007-04-02 21:29:53 +00:00
|
|
|
report(RPT_DEBUG, "%s()", __FUNCTION__);
|
2000-03-30 20:20:41 +00:00
|
|
|
|
2007-04-02 21:29:53 +00:00
|
|
|
if (!screenlist) {
|
2002-08-04 20:58:51 +00:00
|
|
|
/* Program shutdown before completed startup */
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
2007-04-02 21:29:53 +00:00
|
|
|
LL_Destroy(screenlist);
|
2000-03-30 20:20:41 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
return 0;
|
1999-12-09 23:15:14 +00:00
|
|
|
}
|
|
|
|
|
|
2003-02-27 21:20:20 +00:00
|
|
|
|
|
|
|
|
int
|
2007-04-02 21:29:53 +00:00
|
|
|
screenlist_add(Screen *s)
|
2003-02-27 21:20:20 +00:00
|
|
|
{
|
|
|
|
|
if (!screenlist)
|
|
|
|
|
return -1;
|
2007-04-02 21:29:53 +00:00
|
|
|
return LL_Push(screenlist, s);
|
2003-02-27 21:20:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2000-03-30 20:20:41 +00:00
|
|
|
int
|
2007-04-02 21:29:53 +00:00
|
|
|
screenlist_remove(Screen *s)
|
1999-12-09 23:15:14 +00:00
|
|
|
{
|
2007-04-02 21:29:53 +00:00
|
|
|
debug(RPT_DEBUG, "%s(s=[%.40s])", __FUNCTION__, s->id);
|
2000-03-30 20:20:41 +00:00
|
|
|
|
2003-02-27 21:20:20 +00:00
|
|
|
if (!screenlist)
|
2000-04-03 22:13:57 +00:00
|
|
|
return -1;
|
2003-02-27 21:20:20 +00:00
|
|
|
|
|
|
|
|
/* Are we trying to remove the current screen ? */
|
|
|
|
|
if (s == current_screen) {
|
2007-04-02 21:29:53 +00:00
|
|
|
screenlist_goto_next();
|
2003-02-27 21:20:20 +00:00
|
|
|
if (s == current_screen) {
|
|
|
|
|
/* Hmm, no other screen had same priority */
|
2007-04-02 21:29:53 +00:00
|
|
|
void *res = LL_Remove(screenlist, s);
|
2003-02-27 21:20:20 +00:00
|
|
|
/* And now once more */
|
2007-04-02 21:29:53 +00:00
|
|
|
screenlist_goto_next();
|
2003-02-27 21:20:20 +00:00
|
|
|
return (res == NULL) ? -1 : 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
2007-04-02 21:29:53 +00:00
|
|
|
return (LL_Remove(screenlist, s) == NULL) ? -1 : 0;
|
1999-12-09 23:15:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2002-08-04 20:58:51 +00:00
|
|
|
void
|
2007-04-02 21:29:53 +00:00
|
|
|
screenlist_process(void)
|
1999-12-09 23:15:14 +00:00
|
|
|
{
|
2007-04-02 21:29:53 +00:00
|
|
|
Screen *s;
|
|
|
|
|
Screen *f;
|
2002-08-04 20:58:51 +00:00
|
|
|
|
2007-04-02 21:29:53 +00:00
|
|
|
report(RPT_DEBUG, "%s()", __FUNCTION__);
|
2000-03-30 20:20:41 +00:00
|
|
|
|
2003-02-27 21:20:20 +00:00
|
|
|
if (!screenlist)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* Sort the list acfording to priority class */
|
2007-04-02 21:29:53 +00:00
|
|
|
LL_Sort(screenlist, compare_priority);
|
2003-02-27 21:20:20 +00:00
|
|
|
f = LL_GetFirst(screenlist);
|
|
|
|
|
|
|
|
|
|
/**** First we need to check out the current situation. ****/
|
|
|
|
|
|
|
|
|
|
/* Check whether there is an active screen */
|
2007-04-02 21:29:53 +00:00
|
|
|
s = screenlist_current();
|
2002-08-04 20:58:51 +00:00
|
|
|
if (!s) {
|
2003-02-27 21:20:20 +00:00
|
|
|
/* We have no active screen yet.
|
|
|
|
|
* Try to switch to the first screen in the list... */
|
2002-08-04 20:58:51 +00:00
|
|
|
|
2003-02-27 21:20:20 +00:00
|
|
|
s = f;
|
2002-08-04 20:58:51 +00:00
|
|
|
if (!s) {
|
|
|
|
|
/* There was no screen in the list */
|
|
|
|
|
return;
|
|
|
|
|
}
|
2007-04-02 21:29:53 +00:00
|
|
|
screenlist_switch(s);
|
2003-02-27 21:20:20 +00:00
|
|
|
return;
|
2002-08-04 20:58:51 +00:00
|
|
|
}
|
2003-02-27 21:20:20 +00:00
|
|
|
else {
|
|
|
|
|
/* There already was an active screen.
|
|
|
|
|
* Check to see if it has an expiry time. If so, decrease it
|
|
|
|
|
* and then check to see if it has expired. Remove the screen
|
|
|
|
|
* if expired. */
|
|
|
|
|
if (s->timeout != -1) {
|
|
|
|
|
--(s->timeout);
|
|
|
|
|
report(RPT_DEBUG, "Active screen [%.40s] has timeout->%d", s->id, s->timeout);
|
|
|
|
|
if (s->timeout <= 0) {
|
|
|
|
|
/* Expired, we can destroy it */
|
|
|
|
|
report(RPT_DEBUG, "Removing expired screen [%.40s]", s->id);
|
2007-04-02 21:29:53 +00:00
|
|
|
client_remove_screen(s->client, s);
|
|
|
|
|
screen_destroy(s);
|
2003-02-27 21:20:20 +00:00
|
|
|
}
|
2002-08-04 20:58:51 +00:00
|
|
|
}
|
|
|
|
|
}
|
2003-02-27 21:20:20 +00:00
|
|
|
|
|
|
|
|
/**** OK, current situation examined. We can now see if we need to switch. */
|
|
|
|
|
|
|
|
|
|
/* Is there a screen of a higher priority class than the
|
|
|
|
|
* current one ? */
|
|
|
|
|
if (f->priority > s->priority) {
|
|
|
|
|
/* Yes, switch to that screen, job done */
|
|
|
|
|
screenlist_switch(f);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Current screen has been visible long enough and is it of 'normal'
|
|
|
|
|
* priority ?
|
|
|
|
|
*/
|
|
|
|
|
if (autorotate && (timer - current_screen_start_time >= s->duration)
|
|
|
|
|
&& s->priority > PRI_BACKGROUND && s->priority <= PRI_FOREGROUND) {
|
|
|
|
|
/* Ah, rotate! */
|
|
|
|
|
screenlist_goto_next();
|
2002-08-04 20:58:51 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-02-27 21:20:20 +00:00
|
|
|
|
2002-08-04 20:58:51 +00:00
|
|
|
void
|
2007-04-02 21:29:53 +00:00
|
|
|
screenlist_switch(Screen *s)
|
2002-08-04 20:58:51 +00:00
|
|
|
{
|
2007-04-02 21:29:53 +00:00
|
|
|
Client *c;
|
2002-08-04 20:58:51 +00:00
|
|
|
char str[256];
|
|
|
|
|
|
|
|
|
|
if (!s) return;
|
|
|
|
|
|
2007-04-02 21:29:53 +00:00
|
|
|
report(RPT_DEBUG, "%s(s=[%.40s])", __FUNCTION__, s->id);
|
2002-08-04 20:58:51 +00:00
|
|
|
|
|
|
|
|
if (s == current_screen) {
|
|
|
|
|
/* Nothing to be done */
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (current_screen) {
|
|
|
|
|
c = current_screen->client;
|
|
|
|
|
if (c) {
|
|
|
|
|
/* Tell the client we're not listening any more...*/
|
2007-04-02 21:29:53 +00:00
|
|
|
snprintf(str, sizeof(str), "ignore %s\n", current_screen->id);
|
|
|
|
|
sock_send_string(c->sock, str);
|
2002-08-04 20:58:51 +00:00
|
|
|
} else {
|
|
|
|
|
/* It's a server screen, no need to inform it. */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
c = s->client;
|
|
|
|
|
if (c) {
|
|
|
|
|
/* Tell the client we're paying attention...*/
|
2007-04-02 21:29:53 +00:00
|
|
|
snprintf(str, sizeof(str), "listen %s\n", s->id);
|
|
|
|
|
sock_send_string(c->sock, str);
|
2002-08-04 20:58:51 +00:00
|
|
|
} else {
|
|
|
|
|
/* It's a server screen, no need to inform it. */
|
|
|
|
|
}
|
2007-04-02 21:29:53 +00:00
|
|
|
report(RPT_INFO, "%s: switched to screen [%.40s]", __FUNCTION__, s->id);
|
2002-08-04 20:58:51 +00:00
|
|
|
current_screen = s;
|
|
|
|
|
current_screen_start_time = timer;
|
1999-12-09 23:15:14 +00:00
|
|
|
}
|
|
|
|
|
|
2003-02-27 21:20:20 +00:00
|
|
|
|
2002-04-26 00:00:31 +00:00
|
|
|
Screen *
|
2007-04-02 21:29:53 +00:00
|
|
|
screenlist_current(void)
|
1999-12-09 23:15:14 +00:00
|
|
|
{
|
2002-08-04 20:58:51 +00:00
|
|
|
return current_screen;
|
1999-12-09 23:15:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2003-02-27 21:20:20 +00:00
|
|
|
int
|
2007-04-02 21:29:53 +00:00
|
|
|
screenlist_goto_next(void)
|
1999-12-09 23:15:14 +00:00
|
|
|
{
|
2002-04-26 00:00:31 +00:00
|
|
|
Screen *s;
|
2000-03-30 20:20:41 +00:00
|
|
|
|
2007-04-02 21:29:53 +00:00
|
|
|
debug(RPT_DEBUG, "%s()", __FUNCTION__);
|
2000-03-30 20:20:41 +00:00
|
|
|
|
2003-02-27 21:20:20 +00:00
|
|
|
if (!current_screen)
|
|
|
|
|
return -1;
|
1999-12-09 23:15:14 +00:00
|
|
|
|
2003-02-27 21:20:20 +00:00
|
|
|
/* Find current screen in screenlist */
|
2007-04-02 21:29:53 +00:00
|
|
|
for (s = LL_GetFirst(screenlist); s && s != current_screen; s = LL_GetNext(screenlist));
|
1999-12-09 23:15:14 +00:00
|
|
|
|
2003-02-27 21:20:20 +00:00
|
|
|
/* One step forward */
|
|
|
|
|
s = LL_GetNext(screenlist);
|
2007-04-02 21:29:53 +00:00
|
|
|
if (!s || s->priority < current_screen->priority) {
|
2003-02-27 21:20:20 +00:00
|
|
|
/* To far, go back to start of screenlist */
|
|
|
|
|
s = LL_GetFirst(screenlist);
|
|
|
|
|
}
|
2007-04-02 21:29:53 +00:00
|
|
|
screenlist_switch(s);
|
2003-02-27 21:20:20 +00:00
|
|
|
return 0;
|
1999-12-09 23:15:14 +00:00
|
|
|
}
|
|
|
|
|
|
2003-02-27 21:20:20 +00:00
|
|
|
|
|
|
|
|
int
|
2007-04-02 21:29:53 +00:00
|
|
|
screenlist_goto_prev(void)
|
1999-12-09 23:15:14 +00:00
|
|
|
{
|
2002-04-26 00:00:31 +00:00
|
|
|
Screen *s;
|
1999-12-09 23:15:14 +00:00
|
|
|
|
2007-04-02 21:29:53 +00:00
|
|
|
debug(RPT_DEBUG, "%s()", __FUNCTION__);
|
2002-07-14 20:30:33 +00:00
|
|
|
|
2003-02-27 21:20:20 +00:00
|
|
|
if (!current_screen)
|
|
|
|
|
return -1;
|
1999-12-09 23:15:14 +00:00
|
|
|
|
2003-02-27 21:20:20 +00:00
|
|
|
/* Find current screen in screenlist */
|
2007-04-02 21:29:53 +00:00
|
|
|
for (s = LL_GetFirst(screenlist); s && s != current_screen; s = LL_GetNext(screenlist));
|
2000-03-30 20:20:41 +00:00
|
|
|
|
2003-02-27 21:20:20 +00:00
|
|
|
/* One step back */
|
|
|
|
|
s = LL_GetPrev(screenlist);
|
2007-04-02 21:29:53 +00:00
|
|
|
if (!s) {
|
2003-02-27 21:20:20 +00:00
|
|
|
/* We're at the start of the screenlist. We should find the
|
|
|
|
|
* last screen with the same priority as the first screen.
|
|
|
|
|
*/
|
2007-04-02 21:29:53 +00:00
|
|
|
Screen *f = LL_GetFirst(screenlist);
|
|
|
|
|
Screen *n;
|
2000-03-30 20:20:41 +00:00
|
|
|
|
2003-02-27 21:20:20 +00:00
|
|
|
s = f;
|
2007-04-02 21:29:53 +00:00
|
|
|
while ((n = LL_GetNext(screenlist)) && n->priority == f->priority) {
|
2003-02-27 21:20:20 +00:00
|
|
|
s = n;
|
|
|
|
|
}
|
|
|
|
|
}
|
2007-04-02 21:29:53 +00:00
|
|
|
screenlist_switch(s);
|
2003-02-27 21:20:20 +00:00
|
|
|
return 0;
|
1999-12-09 23:15:14 +00:00
|
|
|
}
|
|
|
|
|
|
2003-02-27 21:20:20 +00:00
|
|
|
/* Internal function for sorting. */
|
2000-03-30 20:20:41 +00:00
|
|
|
int
|
2007-04-02 21:29:53 +00:00
|
|
|
compare_priority(void *one, void *two)
|
1999-12-09 23:15:14 +00:00
|
|
|
{
|
2002-04-26 00:00:31 +00:00
|
|
|
Screen *a, *b;
|
1999-12-09 23:15:14 +00:00
|
|
|
|
2001-12-30 00:15:25 +00:00
|
|
|
/*debug(RPT_DEBUG, "compare_priority: %8x %8x", one, two);*/
|
2000-03-30 20:20:41 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
if (!one)
|
|
|
|
|
return 0;
|
|
|
|
|
if (!two)
|
|
|
|
|
return 0;
|
2000-03-30 20:20:41 +00:00
|
|
|
|
2002-04-26 00:00:31 +00:00
|
|
|
a = (Screen *) one;
|
|
|
|
|
b = (Screen *) two;
|
1999-12-09 23:15:14 +00:00
|
|
|
|
2001-12-30 00:15:25 +00:00
|
|
|
/*debug(RPT_DEBUG, "compare_priority: done?");*/
|
1999-12-09 23:15:14 +00:00
|
|
|
|
2003-02-27 21:20:20 +00:00
|
|
|
return (b->priority - a->priority);
|
1999-12-09 23:15:14 +00:00
|
|
|
}
|