Files
g15daemon/g15daemon/linked_lists.c
T

213 lines
6.2 KiB
C

/*
This file is part of g15daemon.
g15daemon is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
g15daemon is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with g15daemon; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
(c) 2006-2008 Mike Lampard, Philip Lawatsch, and others
$Revision: 451 $ - $Date: 2008-01-25 15:15:04 +1030 (Fri, 25 Jan 2008) $ $Author: mlampard $
This daemon listens on localhost port 15550 for client connections,
and arbitrates LCD display. Allows for multiple simultaneous clients.
Client screens can be cycled through by pressing the 'L1' key.
*/
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <g15daemon.h>
#include <libg15.h>
extern lcd_t *keyhandler;
extern unsigned int client_handles_keys;
extern plugin_info_t *generic_info;
lcd_t static * ll_create_lcd () {
lcd_t *lcd = g15daemon_xmalloc (sizeof (lcd_t));
lcd->max_x = LCD_WIDTH;
lcd->max_y = LCD_HEIGHT;
lcd->backlight_state = G15_BRIGHTNESS_MEDIUM;
lcd->mkey_state = 0;
lcd->contrast_state = G15_CONTRAST_MEDIUM;
lcd->state_changed = 1;
lcd->usr_foreground = 0;
lcd->g15plugin = g15daemon_xmalloc(sizeof (plugin_s));
lcd->g15plugin->plugin_handle = NULL;
lcd->g15plugin->info = (void*)&generic_info;
return (lcd);
}
static void ll_quit_lcd (lcd_t * lcd) {
free (lcd->g15plugin);
free (lcd);
}
/* initialise a new masterlist, and add an initial node at the tail (used for the clock) */
g15daemon_t *ll_lcdlist_init () {
g15daemon_t *masterlist = NULL;
pthread_mutex_init(&lcdlist_mutex, NULL);
pthread_mutex_lock(&lcdlist_mutex);
masterlist = g15daemon_xmalloc(sizeof(g15daemon_t));
masterlist->head = g15daemon_xmalloc(sizeof(lcdnode_t));
masterlist->tail = masterlist->head;
masterlist->current = masterlist->head;
masterlist->head->lcd = ll_create_lcd();
masterlist->head->lcd->mkey_state = 0;
masterlist->head->lcd->masterlist = masterlist;
/* first screen is the clock/menu */
masterlist->head->lcd->g15plugin->info = NULL;
masterlist->head->prev = masterlist->head;
masterlist->head->next = masterlist->head;
masterlist->head->list = masterlist;
masterlist->keyboard_handler = NULL;
masterlist->numclients = 0;
pthread_mutex_unlock(&lcdlist_mutex);
return masterlist;
}
lcdnode_t *g15daemon_lcdnode_add(g15daemon_t **masterlist) {
lcdnode_t *new = NULL;
pthread_mutex_lock(&lcdlist_mutex);
new = g15daemon_xmalloc(sizeof(lcdnode_t));
new->prev = (*masterlist)->head;
new->next = (*masterlist)->tail;
new->lcd = ll_create_lcd();
new->lcd->masterlist = (*masterlist);
new->last_priority = NULL;
new->list = *masterlist;
(*masterlist)->head->next=new;
(*masterlist)->current = new;
(*masterlist)->head = new;
(*masterlist)->head->list = *masterlist;
(*masterlist)->numclients++;
pthread_mutex_unlock(&lcdlist_mutex);
return new;
}
/* cycle through connected client displays */
void g15daemon_lcdnode_cycle(g15daemon_t *masterlist)
{
lcdnode_t *current_screen = NULL;
pthread_mutex_lock(&lcdlist_mutex);
skip:
current_screen = masterlist->current;
g15daemon_send_event(current_screen->lcd, G15_EVENT_VISIBILITY_CHANGED, SCR_HIDDEN);
do
{
masterlist->current->lcd->usr_foreground=0;
if(masterlist->tail == masterlist->current){
masterlist->current = masterlist->head;
}else{
masterlist->current = masterlist->current->prev;
}
}
while (current_screen != masterlist->current);
if(masterlist->tail == masterlist->current) {
masterlist->current = masterlist->head;
} else {
masterlist->current = masterlist->current->prev;
}
if(masterlist->current->lcd->never_select==1) {
goto skip;
}
masterlist->current->last_priority = masterlist->current;
pthread_mutex_unlock(&lcdlist_mutex);
masterlist->current->lcd->usr_foreground=1;
g15daemon_send_event(masterlist->current->lcd, G15_EVENT_VISIBILITY_CHANGED, SCR_VISIBLE);
}
void g15daemon_lcdnode_remove (lcdnode_t *oldnode) {
g15daemon_t **masterlist = NULL;
lcdnode_t **prev = NULL;
lcdnode_t **next = NULL;
pthread_mutex_lock(&lcdlist_mutex);
masterlist = &oldnode->list;
prev = &oldnode->prev;
next = &oldnode->next;
ll_quit_lcd(oldnode->lcd);
(*masterlist)->numclients--;
if((*masterlist)->current == oldnode) {
if((*masterlist)->current!=(*masterlist)->head){
(*masterlist)->current = oldnode->next;
} else {
(*masterlist)->current = oldnode->prev;
}
(*masterlist)->current->lcd->state_changed = 1;
}
if(&oldnode->lcd == (void*)keyhandler) {
client_handles_keys = 0;
keyhandler = NULL;
g15daemon_log(LOG_WARNING,"Client key handler quit, going back to defaults");
}
if((*masterlist)->head!=oldnode){
(*next)->prev = oldnode->prev;
(*prev)->next = oldnode->next;
}else{
(*prev)->next = (*masterlist)->tail;
(*masterlist)->head = oldnode->prev;
}
g15daemon_send_refresh((*masterlist)->current->lcd);
free(oldnode);
pthread_mutex_unlock(&lcdlist_mutex);
}
void ll_lcdlist_destroy(g15daemon_t **masterlist) {
int i = 0;
while ((*masterlist)->head != (*masterlist)->tail) {
i++;
g15daemon_lcdnode_remove((*masterlist)->head);
}
free((*masterlist)->tail->lcd);
free((*masterlist)->tail);
free(*masterlist);
pthread_mutex_destroy(&lcdlist_mutex);
}