1 /* 2 * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/> 3 * (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com> 4 * 5 * This file is part of lsp-plugins 6 * Created on: 12 июн. 2017 г. 7 * 8 * lsp-plugins is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU Lesser General Public License as published by 10 * the Free Software Foundation, either version 3 of the License, or 11 * any later version. 12 * 13 * lsp-plugins is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public License 19 * along with lsp-plugins. If not, see <https://www.gnu.org/licenses/>. 20 */ 21 22 #include <ui/tk/tk.h> 23 24 #define ID_GEN_MASK 0x7fffff 25 26 namespace lsp 27 { 28 namespace tk 29 { LSPSlot()30 LSPSlot::LSPSlot() 31 { 32 pRoot = NULL; 33 nID = 0; 34 } 35 ~LSPSlot()36 LSPSlot::~LSPSlot() 37 { 38 unbind_all(); 39 } 40 find_item(ui_handler_id_t id)41 inline LSPSlot::handler_item_t *LSPSlot::find_item(ui_handler_id_t id) 42 { 43 handler_item_t *ptr = pRoot; 44 45 while (ptr != NULL) 46 { 47 if (ptr->nID == id) 48 break; 49 ptr = ptr->pNext; 50 } 51 return ptr; 52 } 53 bind(ui_event_handler_t handler,void * arg,bool enabled)54 ui_handler_id_t LSPSlot::bind(ui_event_handler_t handler, void *arg, bool enabled) 55 { 56 return bind(handler, false, arg, enabled); 57 } 58 intercept(ui_event_handler_t handler,void * arg,bool enabled)59 ui_handler_id_t LSPSlot::intercept(ui_event_handler_t handler, void *arg, bool enabled) 60 { 61 return bind(handler, true, arg, enabled); 62 } 63 bind(ui_event_handler_t handler,bool intercept,void * arg,bool enabled)64 ui_handler_id_t LSPSlot::bind(ui_event_handler_t handler, bool intercept, void *arg, bool enabled) 65 { 66 // Check data 67 if (handler == NULL) 68 return - STATUS_BAD_ARGUMENTS; 69 70 // Now try to allocate new data 71 handler_item_t *item = new handler_item_t; 72 if (item == NULL) 73 return - STATUS_NO_MEM; 74 75 // Generate handler identifier 76 do 77 { 78 item->nID = nID; 79 nID = (nID + 1) & ID_GEN_MASK; 80 } while (find_item(item->nID) != NULL); 81 82 // Initialize item and bind it 83 size_t mask = (intercept) ? BIND_DFL : BIND_DFL | BIND_INTERCEPT; 84 item->nFlags = (enabled) ? mask | BIND_ENABLED : mask; 85 item->pHandler = handler; 86 item->pPtr = arg; 87 item->pNext = pRoot; 88 pRoot = item; 89 90 return item->nID; 91 } 92 unbind(ui_handler_id_t id)93 status_t LSPSlot::unbind(ui_handler_id_t id) 94 { 95 // Check data 96 if (id < 0) 97 return STATUS_BAD_ARGUMENTS; 98 99 handler_item_t *ptr = pRoot; 100 handler_item_t *prev = NULL; 101 102 while (ptr != NULL) 103 { 104 if (ptr->nID == id) 105 { 106 // Unbind handler and remove it 107 if (prev == NULL) 108 pRoot = ptr->pNext; 109 else 110 prev->pNext = ptr->pNext; 111 delete ptr; 112 return STATUS_OK; 113 } 114 prev = ptr; 115 ptr = ptr->pNext; 116 } 117 return STATUS_NOT_FOUND; 118 } 119 unbind(ui_event_handler_t handler,void * arg)120 ui_handler_id_t LSPSlot::unbind(ui_event_handler_t handler, void *arg) 121 { 122 // Check data 123 if (handler == NULL) 124 return - STATUS_BAD_ARGUMENTS; 125 126 handler_item_t *ptr = pRoot; 127 handler_item_t *prev = NULL; 128 129 while (ptr != NULL) 130 { 131 if ((ptr->pHandler == handler) && (ptr->pPtr == arg)) 132 { 133 // Unbind handler and remove it 134 ui_handler_id_t id = ptr->nID; 135 if (prev == NULL) 136 pRoot = ptr->pNext; 137 else 138 prev->pNext = ptr->pNext; 139 delete ptr; 140 return id; 141 } 142 prev = ptr; 143 ptr = ptr->pNext; 144 } 145 return - STATUS_NOT_FOUND; 146 } 147 unbind_all()148 size_t LSPSlot::unbind_all() 149 { 150 handler_item_t *ptr = pRoot; 151 handler_item_t *next = NULL; 152 size_t removed = 0; 153 154 while (ptr != NULL) 155 { 156 next = ptr->pNext; 157 delete ptr; 158 ptr = next; 159 removed ++; 160 } 161 162 return removed; 163 } 164 disable(ui_handler_id_t id)165 status_t LSPSlot::disable(ui_handler_id_t id) 166 { 167 // Check data 168 if (id < 0) 169 return STATUS_BAD_ARGUMENTS; 170 171 handler_item_t *ptr = find_item(id); 172 if (ptr == NULL) 173 return STATUS_NOT_FOUND; 174 175 ptr->nFlags &= ~BIND_ENABLED; 176 return STATUS_OK; 177 } 178 disable_all()179 size_t LSPSlot::disable_all() 180 { 181 return disable_all(true, true); 182 } 183 disable_all_interceptors()184 size_t LSPSlot::disable_all_interceptors() 185 { 186 return disable_all(false, true); 187 } 188 disable_all_bindings()189 size_t LSPSlot::disable_all_bindings() 190 { 191 return disable_all(true, false); 192 } 193 disable_all(bool handler,bool interceptor)194 size_t LSPSlot::disable_all(bool handler, bool interceptor) 195 { 196 if ((!handler) && (!interceptor)) 197 return 0; 198 199 handler_item_t *ptr = pRoot; 200 size_t disabled = 0; 201 size_t mask = (handler && interceptor) ? BIND_ENABLED : BIND_ENABLED | BIND_INTERCEPT; 202 size_t check = ((!handler) && interceptor) ? BIND_INTERCEPT | BIND_ENABLED : BIND_ENABLED; 203 204 while (ptr != NULL) 205 { 206 if ((ptr->nFlags & mask) == check) 207 { 208 ptr->nFlags &= ~BIND_ENABLED; 209 disabled ++; 210 } 211 ptr = ptr->pNext; 212 } 213 214 return disabled; 215 } 216 enable(ui_handler_id_t id)217 status_t LSPSlot::enable(ui_handler_id_t id) 218 { 219 // Check data 220 if (id < 0) 221 return STATUS_BAD_ARGUMENTS; 222 223 handler_item_t *ptr = find_item(id); 224 if (ptr == NULL) 225 return STATUS_NOT_FOUND; 226 227 ptr->nFlags |= BIND_ENABLED; 228 return STATUS_OK; 229 } 230 enable_all(bool handler,bool interceptor)231 size_t LSPSlot::enable_all(bool handler, bool interceptor) 232 { 233 handler_item_t *ptr = pRoot; 234 size_t enabled = 0; 235 size_t mask = (handler && interceptor) ? BIND_ENABLED : BIND_ENABLED | BIND_INTERCEPT; 236 size_t check = ((!handler) && interceptor) ? BIND_INTERCEPT : 0; 237 238 while (ptr != NULL) 239 { 240 if ((ptr->nFlags & mask) == check) 241 { 242 ptr->nFlags |= BIND_ENABLED; 243 enabled ++; 244 } 245 ptr = ptr->pNext; 246 } 247 248 return enabled; 249 } 250 enable_all()251 size_t LSPSlot::enable_all() 252 { 253 return enable_all(true, true); 254 } 255 enable_all_bindings()256 size_t LSPSlot::enable_all_bindings() 257 { 258 return enable_all(true, false); 259 } 260 enable_all_interceptors()261 size_t LSPSlot::enable_all_interceptors() 262 { 263 return enable_all(false, true); 264 } 265 execute(LSPWidget * sender,void * data)266 status_t LSPSlot::execute(LSPWidget *sender, void *data) 267 { 268 // First iteration, iterate all interceptors 269 for (handler_item_t *ptr = pRoot; ptr != NULL; ptr = ptr->pNext) 270 { 271 // Execute handler in the chain 272 if ((ptr->nFlags & (BIND_ENABLED | BIND_INTERCEPT)) == (BIND_ENABLED | BIND_INTERCEPT)) 273 { 274 status_t result = ptr->pHandler(sender, ptr->pPtr, data); 275 if (result != STATUS_OK) 276 return STATUS_OK; 277 } 278 } 279 280 // Second iteration, iterate all handlers 281 for (handler_item_t *ptr = pRoot; ptr != NULL; ptr = ptr->pNext) 282 { 283 // Execute handler in the chain 284 if ((ptr->nFlags & (BIND_ENABLED | BIND_INTERCEPT)) == BIND_ENABLED) 285 { 286 status_t result = ptr->pHandler(sender, ptr->pPtr, data); 287 if (result != STATUS_OK) 288 return result; 289 } 290 } 291 292 return STATUS_OK; 293 } 294 295 } 296 } /* namespace lsp */ 297