1 /* 2 * This file is part of g15daemon. 3 * 4 * g15daemon is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * g15daemon is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with g15daemon; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 * 18 * (c) 2006-2021 Mike Lampard, Philip Lawatsch, Daniel Menelkir and others 19 * 20 * This daemon listens on localhost port 15550 for client connections, 21 * and arbitrates LCD display. Allows for multiple simultaneous clients. 22 * Client screens can be cycled through by pressing the 'L1' key. 23 */ 24 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <pthread.h> 28 #include <g15daemon.h> 29 #include <libg15.h> 30 31 extern lcd_t *keyhandler; 32 extern unsigned int client_handles_keys; 33 extern plugin_info_t *generic_info; 34 35 lcd_t static * ll_create_lcd () { 36 lcd_t *lcd = g15daemon_xmalloc (sizeof (lcd_t)); 37 lcd->max_x = LCD_WIDTH; 38 lcd->max_y = LCD_HEIGHT; 39 lcd->backlight_state = G15_BRIGHTNESS_MEDIUM; 40 lcd->mkey_state = 0; 41 lcd->contrast_state = G15_CONTRAST_MEDIUM; 42 lcd->state_changed = 1; 43 lcd->usr_foreground = 0; 44 lcd->g15plugin = g15daemon_xmalloc(sizeof (plugin_s)); 45 lcd->g15plugin->plugin_handle = NULL; 46 lcd->g15plugin->info = (void*)&generic_info; 47 return (lcd); 48 } 49 50 static void ll_quit_lcd (lcd_t * lcd) { 51 free (lcd->g15plugin); 52 free (lcd); 53 } 54 55 /* initialise a new masterlist, and add an initial node at the tail (used for the clock) */ 56 g15daemon_t *ll_lcdlist_init () { 57 g15daemon_t *masterlist = NULL; 58 pthread_mutex_init(&lcdlist_mutex, NULL); 59 pthread_mutex_lock(&lcdlist_mutex); 60 masterlist = g15daemon_xmalloc(sizeof(g15daemon_t)); 61 masterlist->head = g15daemon_xmalloc(sizeof(lcdnode_t)); 62 masterlist->tail = masterlist->head; 63 masterlist->current = masterlist->head; 64 masterlist->head->lcd = ll_create_lcd(); 65 masterlist->head->lcd->mkey_state = 0; 66 masterlist->head->lcd->masterlist = masterlist; 67 /* first screen is the clock/menu */ 68 masterlist->head->lcd->g15plugin->info = NULL; 69 masterlist->head->prev = masterlist->head; 70 masterlist->head->next = masterlist->head; 71 masterlist->head->list = masterlist; 72 masterlist->keyboard_handler = NULL; 73 masterlist->numclients = 0; 74 pthread_mutex_unlock(&lcdlist_mutex); 75 return masterlist; 76 } 77 78 lcdnode_t *g15daemon_lcdnode_add(g15daemon_t **masterlist) { 79 lcdnode_t *new = NULL; 80 pthread_mutex_lock(&lcdlist_mutex); 81 new = g15daemon_xmalloc(sizeof(lcdnode_t)); 82 new->prev = (*masterlist)->head; 83 new->next = (*masterlist)->tail; 84 new->lcd = ll_create_lcd(); 85 new->lcd->masterlist = (*masterlist); 86 new->last_priority = NULL; 87 new->list = *masterlist; 88 (*masterlist)->head->next=new; 89 (*masterlist)->current = new; 90 (*masterlist)->head = new; 91 (*masterlist)->head->list = *masterlist; 92 (*masterlist)->numclients++; 93 pthread_mutex_unlock(&lcdlist_mutex); 94 return new; 95 } 96 97 /* cycle through connected client displays */ 98 void g15daemon_lcdnode_cycle(g15daemon_t *masterlist){ 99 lcdnode_t *current_screen = NULL; 100 pthread_mutex_lock(&lcdlist_mutex); 101 skip: 102 current_screen = masterlist->current; 103 g15daemon_send_event(current_screen->lcd, G15_EVENT_VISIBILITY_CHANGED, SCR_HIDDEN); 104 do{ 105 masterlist->current->lcd->usr_foreground=0; 106 if(masterlist->tail == masterlist->current){ 107 masterlist->current = masterlist->head; 108 } 109 else{ 110 masterlist->current = masterlist->current->prev; 111 } 112 } 113 while (current_screen != masterlist->current); 114 if(masterlist->tail == masterlist->current) { 115 masterlist->current = masterlist->head; 116 } 117 else { 118 masterlist->current = masterlist->current->prev; 119 } 120 if(masterlist->current->lcd->never_select==1) { 121 goto skip; 122 } 123 masterlist->current->last_priority = masterlist->current; 124 pthread_mutex_unlock(&lcdlist_mutex); 125 masterlist->current->lcd->usr_foreground=1; 126 g15daemon_send_event(masterlist->current->lcd, G15_EVENT_VISIBILITY_CHANGED, SCR_VISIBLE); 127 } 128 129 void g15daemon_lcdnode_remove (lcdnode_t *oldnode) { 130 g15daemon_t **masterlist = NULL; 131 lcdnode_t **prev = NULL; 132 lcdnode_t **next = NULL; 133 pthread_mutex_lock(&lcdlist_mutex); 134 masterlist = &oldnode->list; 135 prev = &oldnode->prev; 136 next = &oldnode->next; 137 ll_quit_lcd(oldnode->lcd); 138 (*masterlist)->numclients--; 139 if((*masterlist)->current == oldnode) { 140 if((*masterlist)->current!=(*masterlist)->head){ 141 (*masterlist)->current = oldnode->next; 142 } 143 else { 144 (*masterlist)->current = oldnode->prev; 145 } 146 (*masterlist)->current->lcd->state_changed = 1; 147 } 148 if(&oldnode->lcd == (void*)keyhandler) { 149 client_handles_keys = 0; 150 keyhandler = NULL; 151 g15daemon_log(LOG_WARNING,"Client key handler quit, going back to defaults"); 152 } 153 if((*masterlist)->head!=oldnode){ 154 (*next)->prev = oldnode->prev; 155 (*prev)->next = oldnode->next; 156 } 157 else{ 158 (*prev)->next = (*masterlist)->tail; 159 (*masterlist)->head = oldnode->prev; 160 } 161 g15daemon_send_refresh((*masterlist)->current->lcd); 162 free(oldnode); 163 pthread_mutex_unlock(&lcdlist_mutex); 164 } 165 166 void ll_lcdlist_destroy(g15daemon_t **masterlist) { 167 int i = 0; 168 while ((*masterlist)->head != (*masterlist)->tail) { 169 i++; 170 g15daemon_lcdnode_remove((*masterlist)->head); 171 } 172 free((*masterlist)->tail->lcd); 173 free((*masterlist)->tail); 174 free(*masterlist); 175 pthread_mutex_destroy(&lcdlist_mutex); 176 } 177 178