A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 290 lines 6.6 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2014 by Michael Sevakis 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * as published by the Free Software Foundation; either version 2 15 * of the License, or (at your option) any later version. 16 * 17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 * KIND, either express or implied. 19 * 20 ****************************************************************************/ 21#include <stddef.h> 22#include "linked_list.h" 23 24 25/** (L)inked (L)ist **/ 26 27/** 28 * Helper to find the node previous to 'find' 29 * 30 * returns: NULL if 'find' is the first node 31 * last node if the 'find' isn't found in the list 32 */ 33static struct ll_node * ll_search_prev(struct ll_head *list, 34 struct ll_node *find) 35{ 36 struct ll_node *prev = NULL; 37 struct ll_node *node = list->head; 38 39 while (node != NULL && node != find) 40 { 41 prev = node; 42 node = node->next; 43 } 44 45 return prev; 46} 47 48/** 49 * Adds a node to s singly-linked list using "insert next" 50 */ 51void ll_insert_next(struct ll_head *list, struct ll_node *node, 52 struct ll_node *newnode) 53{ 54 struct ll_node **nodep = node != NULL ? &node->next : &list->head; 55 struct ll_node *next = *nodep; 56 57 newnode->next = next; 58 *nodep = newnode; 59 60 if (next == NULL) 61 list->tail = newnode; 62} 63 64/** 65 * Adds a node to a singly-linked list using "insert first" 66 */ 67void ll_insert_first(struct ll_head *list, struct ll_node *node) 68{ 69 struct ll_node *head = list->head; 70 71 node->next = head; 72 list->head = node; 73 74 if (head == NULL) 75 list->tail = node; 76} 77 78/** 79 * Adds a node to a singly-linked list using "insert last" 80 */ 81void ll_insert_last(struct ll_head *list, struct ll_node *node) 82{ 83 struct ll_node *tail = list->tail; 84 85 node->next = NULL; 86 list->tail = node; 87 88 if (tail == NULL) 89 list->head = node; 90 else 91 tail->next = node; 92} 93 94/** 95 * Removes the node after "node"; if there is none, nothing is changed 96 */ 97void ll_remove_next(struct ll_head *list, struct ll_node *node) 98{ 99 struct ll_node **nodep = node != NULL ? &node->next : &list->head; 100 struct ll_node *next = *nodep; 101 102 if (next != NULL) 103 { 104 next = next->next; 105 *nodep = next; 106 107 if (next == NULL) 108 list->tail = node; 109 } 110} 111 112/** 113 * Removes the first node in the list 114 */ 115void ll_remove_first(struct ll_head *list) 116{ 117 struct ll_node *node = list->head->next; 118 119 list->head = node; 120 121 if (node == NULL) 122 list->tail = NULL; 123} 124 125/** 126 * Removes the node from the list 127 */ 128void ll_remove(struct ll_head *list, struct ll_node *node) 129{ 130 ll_remove_next(list, ll_search_prev(list, node)); 131} 132 133 134/** (L)inked (L)ist (D)ouble **/ 135 136void lld_insert_next(struct lld_head *list, struct lld_node *node, 137 struct lld_node *newnode) 138{ 139 struct lld_node **nodep = node != NULL ? &node->next : &list->head; 140 struct lld_node *next = *nodep; 141 142 newnode->next = next; 143 newnode->prev = node; 144 *nodep = newnode; 145 146 if (next == NULL) 147 list->tail = newnode; 148 else 149 next->prev = newnode; 150} 151 152void lld_insert_prev(struct lld_head *list, struct lld_node *node, 153 struct lld_node *newnode) 154{ 155 struct lld_node **nodep = node != NULL ? &node->prev : &list->tail; 156 struct lld_node *prev = *nodep; 157 158 newnode->next = node; 159 newnode->prev = prev; 160 *nodep = newnode; 161 162 if (prev == NULL) 163 list->head = newnode; 164 else 165 prev->next = newnode; 166} 167 168/** 169 * Adds a node to a doubly-linked list using "insert first" 170 */ 171void lld_insert_first(struct lld_head *list, struct lld_node *node) 172{ 173 struct lld_node *head = list->head; 174 175 list->head = node; 176 177 if (head == NULL) 178 list->tail = node; 179 else 180 head->prev = node; 181 182 node->next = head; 183 node->prev = NULL; 184} 185 186/** 187 * Adds a node to a doubly-linked list using "insert last" 188 */ 189void lld_insert_last(struct lld_head *list, struct lld_node *node) 190{ 191 struct lld_node *tail = list->tail; 192 193 list->tail = node; 194 195 if (tail == NULL) 196 list->head = node; 197 else 198 tail->next = node; 199 200 node->next = NULL; 201 node->prev = tail; 202} 203 204/** 205 * Removes a node from a doubly-linked list 206 */ 207void lld_remove(struct lld_head *list, struct lld_node *node) 208{ 209 struct lld_node *next = node->next; 210 struct lld_node *prev = node->prev; 211 212 if (prev == NULL) 213 list->head = next; 214 else 215 prev->next = next; 216 217 if (next == NULL) 218 list->tail = prev; 219 else 220 next->prev = prev; 221} 222 223 224/** (L)inked (L)ist (D)ouble (C)ircular **/ 225 226/** 227 * Helper that inserts a node into a doubly-link circular list; does not 228 * affect list->head, just returns its state 229 */ 230static inline struct lldc_node * lldc_insert(struct lldc_head *list, 231 struct lldc_node *node) 232{ 233 struct lldc_node *head = list->head; 234 235 if (head == NULL) 236 { 237 node->prev = node; 238 node->next = node; 239 } 240 else 241 { 242 node->prev = head->prev; 243 node->next = head; 244 head->prev->next = node; 245 head->prev = node; 246 } 247 248 return head; 249} 250 251/** 252 * Adds a node to a doubly-linked circular list using "insert first" 253 */ 254void lldc_insert_first(struct lldc_head *list, struct lldc_node *node) 255{ 256 lldc_insert(list, node); 257 list->head = node; 258} 259 260/** 261 * Adds a node to a doubly-linked circular list using "insert last" 262 */ 263void lldc_insert_last(struct lldc_head *list, struct lldc_node *node) 264{ 265 if (lldc_insert(list, node) == NULL) 266 list->head = node; 267} 268 269/** 270 * Removes a node from a doubly-linked circular list 271 */ 272void lldc_remove(struct lldc_head *list, struct lldc_node *node) 273{ 274 struct lldc_node *next = node->next; 275 276 if (node == list->head) 277 { 278 if (node == next) 279 { 280 list->head = NULL; 281 return; 282 } 283 284 list->head = next; 285 } 286 287 struct lldc_node *prev = node->prev; 288 next->prev = prev; 289 prev->next = next; 290}