ap

Queue manager meant to be used as an audio player
git clone git://jacobedwards.org/ap
Log | Files | Refs | README | LICENSE

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 }