command.c (5900B)
1 /* 2 * Copyright 2021-2024 Jacob R. Edwards 3 * 4 * ap -- audio player 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program. If not, see <https://www.gnu.org/licenses/>. 18 */ 19 20 #include <sys/socket.h> 21 22 #include <errno.h> 23 #include <limits.h> 24 #include <poll.h> 25 #include <regex.h> 26 #include <stdlib.h> 27 #include <string.h> 28 #include <unistd.h> 29 30 #include "aps.h" 31 #include "arg.h" 32 #include "buf.h" 33 #include "bug.h" 34 #include "command.h" 35 #include "find.h" 36 #include "queue.h" 37 #include "util.h" 38 39 char * 40 com_add(struct aps *aps, int fd, int argc, char **argv) 41 { 42 int i; 43 struct item *p; 44 45 p = NULL; 46 for (i = 0; i < argc; ++i) { 47 if (!(p = queue_add(aps, p, argv[i]))) 48 return errstr; 49 } 50 return NULL; 51 } 52 53 char * 54 com_remove(struct aps *aps, int fd, int argc, char **argv) 55 { 56 struct item *match, *next; 57 struct search search; 58 char *err; 59 60 if (!argc) { 61 if (aps_bufline(aps, fd, aps->queue->path)) 62 return errstr; 63 queue_remove(aps, aps->queue); 64 return NULL; 65 } 66 67 err = prepsearch(&search, aps->queue, *argv); 68 if (err) 69 return err; 70 71 while ((match = findnext(&search))) { 72 if (aps_bufline(aps, fd, match->path)) 73 return errstr; 74 75 if (match == search.end) { 76 search.end = NULL; 77 } 78 79 if (match == aps->queue) { 80 next = queue_remove(aps, match); 81 } else { 82 next = queue_remove(aps, match); 83 if (next == aps->queue) 84 match = NULL; 85 } 86 87 if (!search.end) { 88 search.end = next; 89 search.new = 1; 90 } 91 92 if (next == NULL) 93 break; 94 } 95 96 return NULL; 97 } 98 99 char * 100 com_list(struct aps *aps, int fd, int argc, char **argv) 101 { 102 struct item *item; 103 struct search search; 104 char *err; 105 106 err = prepsearch(&search, aps->queue, argc ? *argv : "/^"); 107 if (err) 108 return err; 109 110 if (aps->queue == NULL) 111 return NULL; 112 113 while ((item = findnext(&search))) { 114 if (aps_bufline(aps, fd, item->path)) 115 return errstr; 116 } 117 stopsearch(&search); 118 119 return NULL; 120 } 121 122 char * 123 com_seek(struct aps *aps, int fd, int argc, char **argv) 124 { 125 char *err; 126 127 if (!argc) 128 return "No pattern"; 129 130 if ((err = aps_seek(aps, *argv))) 131 return err; 132 if (aps_bufline(aps, fd, aps->queue->path)) 133 return errstr; 134 return NULL; 135 } 136 137 char * 138 com_play(struct aps *aps, int fd, int argc, char **argv) 139 { 140 char *err; 141 142 if (argc && (err = com_seek(aps, fd, argc, argv))) 143 return err; 144 if (pplay(aps->player, aps->queue->path)) 145 return errstr; 146 return NULL; 147 } 148 149 char * 150 com_pause(struct aps *aps, int fd, int argc, char **argv) 151 { 152 if (psuspend(aps->player)) 153 return errstr; 154 return NULL; 155 } 156 157 char * 158 com_stop(struct aps *aps, int fd, int argc, char **argv) 159 { 160 if (pstop(aps->player)) 161 return errstr; 162 return NULL; 163 } 164 165 char * 166 com_toggle(struct aps *aps, int fd, int argc, char **argv) 167 { 168 if (ptoggle(aps->player)) 169 return errstr; 170 return com_status(aps, fd, 0, NULL); 171 } 172 173 char * 174 com_name(struct aps *aps, int fd, int argc, char **argv) 175 { 176 if (!aps->queue) 177 return "Empty queue"; 178 if (aps_bufline(aps, fd, aps->queue->path)) 179 return errstr; 180 return NULL; 181 } 182 183 char * 184 com_next(struct aps *aps, int fd, int argc, char **argv) 185 { 186 if (!aps->queue) 187 return "Empty queue"; 188 if (aps_play(aps, aps->queue->next)) 189 return errstr; 190 if (aps_bufline(aps, fd, aps->queue->path)) 191 return errstr; 192 return NULL; 193 } 194 195 char * 196 com_previous(struct aps *aps, int fd, int argc, char **argv) 197 { 198 if (!aps->queue) 199 return "Empty queue"; 200 if (aps_play(aps, aps->queue->prev)) 201 return errstr; 202 if (aps_bufline(aps, fd, aps->queue->path)) 203 return errstr; 204 return NULL; 205 } 206 207 char * 208 com_status(struct aps *aps, int fd, int argc, char **argv) 209 { 210 char *status; 211 212 switch (aps->player->state) { 213 case OFF: 214 status = "off"; 215 break; 216 case RUNNING: 217 status = "running"; 218 break; 219 case STOPPED: 220 status = "stopped"; 221 break; 222 case SUSPENDED: 223 status = "suspended"; 224 break; 225 case FAILURE: 226 status = "failure"; 227 break; 228 case COMPLETE: 229 status = "complete"; 230 break; 231 default: 232 bug("impossible player state"); 233 } 234 235 if (aps_bufline(aps, fd, status)) 236 return errstr; 237 return NULL; 238 } 239 240 char * 241 com_log(struct aps *aps, int fd, int argc, char **argv) 242 { 243 return "Command not currently implemented"; 244 } 245 246 char * 247 com_player(struct aps *aps, int fd, int argc, char **argv) 248 { 249 int i; 250 struct player *new; 251 252 if (argc) { 253 new = pnew(argv); 254 if (new == NULL) 255 return errstr; 256 if (aps->player->state == STOPPED) 257 new->state = STOPPED; 258 259 pfree(aps->player); 260 aps->player = new; 261 return NULL; 262 } 263 264 for (i = 0; aps->player->argv[i]; ++i) 265 if (aps_bufword(aps, fd, aps->player->argv[i])) 266 return errstr; 267 return NULL; 268 } 269 270 char * 271 com_truncate(struct aps *aps, int fd, int argc, char **argv) 272 { 273 while (aps->queue && aps->queue->next != aps->queue) 274 queue_remove(aps, aps->queue->next); 275 276 if (!argc) 277 return NULL; 278 queue_remove(aps, aps->queue); 279 return com_add(aps, fd, argc, argv); 280 } 281 282 char * 283 com_terminate(struct aps *aps, int fd, int argc, char **argv) 284 { 285 aps->close = 1; 286 return NULL; 287 } 288 289 char * 290 com_commands(struct aps *aps, int fd, int argc, char **argv) 291 { 292 unsigned int i; 293 294 for (i = 0; i < aps->ncoms; ++i) 295 if (aps_bufline(aps, fd, aps->coms[i].name)) 296 return errstr; 297 return NULL; 298 } 299 300 char * 301 com_close(struct aps *aps, int fd, int argc, char **argv) 302 { 303 return aps_unname(aps) ? errstr : NULL; 304 } 305 306 char * 307 com_root(struct aps *aps, int fd, int argc, char **argv) 308 { 309 char buf[PATH_MAX]; 310 311 if (!getwd(buf)) 312 return errstr; 313 if (aps_bufline(aps, fd, buf)) 314 return errstr; 315 if (argc && chdir(argv[0])) 316 return errstr; 317 return NULL; 318 }