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
12 * All actions that can be performed on the list of screens.
13 * This file also manages the rotation of screens.
20 #include "shared/LL.h"
21 #include "shared/sockets.h"
22 #include "shared/report.h"
23 #include "screenlist.h"
26 #include "main.h" /* for timer */
29 int compare_priority(void *one
, void *two
);
31 bool autorotate
= 1; /* If on, INFO and FOREGROUND screens will rotate */
32 LinkedList
*screenlist
= NULL
;
33 Screen
*current_screen
= NULL
;
34 long int current_screen_start_time
= 0;
40 report(RPT_DEBUG
, "%s()", __FUNCTION__
);
42 screenlist
= LL_new();
44 report(RPT_ERR
, "%s: Error allocating", __FUNCTION__
);
52 screenlist_shutdown(void)
54 report(RPT_DEBUG
, "%s()", __FUNCTION__
);
57 /* Program shutdown before completed startup */
60 LL_Destroy(screenlist
);
67 screenlist_add(Screen
*s
)
71 return LL_Push(screenlist
, s
);
76 screenlist_remove(Screen
*s
)
78 debug(RPT_DEBUG
, "%s(s=[%.40s])", __FUNCTION__
, s
->id
);
83 /* Are we trying to remove the current screen ? */
84 if (s
== current_screen
) {
85 screenlist_goto_next();
86 if (s
== current_screen
) {
87 /* Hmm, no other screen had same priority */
88 void *res
= LL_Remove(screenlist
, s
);
89 /* And now once more */
90 screenlist_goto_next();
91 return (res
== NULL
) ? -1 : 0;
94 return (LL_Remove(screenlist
, s
) == NULL
) ? -1 : 0;
99 screenlist_process(void)
104 report(RPT_DEBUG
, "%s()", __FUNCTION__
);
109 /* Sort the list acfording to priority class */
110 LL_Sort(screenlist
, compare_priority
);
111 f
= LL_GetFirst(screenlist
);
113 /**** First we need to check out the current situation. ****/
115 /* Check whether there is an active screen */
116 s
= screenlist_current();
118 /* We have no active screen yet.
119 * Try to switch to the first screen in the list... */
123 /* There was no screen in the list */
126 screenlist_switch(s
);
130 /* There already was an active screen.
131 * Check to see if it has an expiry time. If so, decrease it
132 * and then check to see if it has expired. Remove the screen
134 if (s
->timeout
!= -1) {
136 report(RPT_DEBUG
, "Active screen [%.40s] has timeout->%d", s
->id
, s
->timeout
);
137 if (s
->timeout
<= 0) {
138 /* Expired, we can destroy it */
139 report(RPT_DEBUG
, "Removing expired screen [%.40s]", s
->id
);
140 client_remove_screen(s
->client
, s
);
146 /**** OK, current situation examined. We can now see if we need to switch. */
148 /* Is there a screen of a higher priority class than the
150 if (f
->priority
> s
->priority
) {
151 /* Yes, switch to that screen, job done */
152 screenlist_switch(f
);
156 /* Current screen has been visible long enough and is it of 'normal'
159 if (autorotate
&& (timer
- current_screen_start_time
>= s
->duration
)
160 && s
->priority
> PRI_BACKGROUND
&& s
->priority
<= PRI_FOREGROUND
) {
162 screenlist_goto_next();
168 screenlist_switch(Screen
*s
)
175 report(RPT_DEBUG
, "%s(s=[%.40s])", __FUNCTION__
, s
->id
);
177 if (s
== current_screen
) {
178 /* Nothing to be done */
182 if (current_screen
) {
183 c
= current_screen
->client
;
185 /* Tell the client we're not listening any more...*/
186 snprintf(str
, sizeof(str
), "ignore %s\n", current_screen
->id
);
187 sock_send_string(c
->sock
, str
);
189 /* It's a server screen, no need to inform it. */
194 /* Tell the client we're paying attention...*/
195 snprintf(str
, sizeof(str
), "listen %s\n", s
->id
);
196 sock_send_string(c
->sock
, str
);
198 /* It's a server screen, no need to inform it. */
200 report(RPT_INFO
, "%s: switched to screen [%.40s]", __FUNCTION__
, s
->id
);
202 current_screen_start_time
= timer
;
207 screenlist_current(void)
209 return current_screen
;
214 screenlist_goto_next(void)
218 debug(RPT_DEBUG
, "%s()", __FUNCTION__
);
223 /* Find current screen in screenlist */
224 for (s
= LL_GetFirst(screenlist
); s
&& s
!= current_screen
; s
= LL_GetNext(screenlist
));
226 /* One step forward */
227 s
= LL_GetNext(screenlist
);
228 if (!s
|| s
->priority
< current_screen
->priority
) {
229 /* To far, go back to start of screenlist */
230 s
= LL_GetFirst(screenlist
);
232 screenlist_switch(s
);
238 screenlist_goto_prev(void)
242 debug(RPT_DEBUG
, "%s()", __FUNCTION__
);
247 /* Find current screen in screenlist */
248 for (s
= LL_GetFirst(screenlist
); s
&& s
!= current_screen
; s
= LL_GetNext(screenlist
));
251 s
= LL_GetPrev(screenlist
);
253 /* We're at the start of the screenlist. We should find the
254 * last screen with the same priority as the first screen.
256 Screen
*f
= LL_GetFirst(screenlist
);
260 while ((n
= LL_GetNext(screenlist
)) && n
->priority
== f
->priority
) {
264 screenlist_switch(s
);
268 /* Internal function for sorting. */
270 compare_priority(void *one
, void *two
)
274 /*debug(RPT_DEBUG, "compare_priority: %8x %8x", one, two);*/
284 /*debug(RPT_DEBUG, "compare_priority: done?");*/
286 return (b
->priority
- a
->priority
);