commit 9fb9424225a739a0fbbfec5d31f21458126fd9c2 from: Omar Polo date: Wed Jul 13 08:32:44 2022 UTC add consume mode the consume mode implicitly drops the tracks from the playlist when played 'till the end (note that skipping over a track doesn't trigger the consume mode - yet?) commit - b557564cf8a4e8fe31e78e15b27616c2a30f3c81 commit + 9fb9424225a739a0fbbfec5d31f21458126fd9c2 blob - 22f2a01ed5e17bac1a328a1f69b5a87db3139530 blob + caaa7d9ba5d4a05422de196a4253184fbce37611 --- amused.1 +++ amused.1 @@ -58,6 +58,9 @@ The following commands are available: .Bl -tag -width Ds .It Cm add Ar Enqueue the given files. +.It Cm consume on|off +When consume mode is enabled the tracks are removed from the playlist +once played til the end. .It Cm flush Erase the playlist. .It Cm jump Ar pattern @@ -106,6 +109,9 @@ Jumped to a different song in the playlist. Added a song to the playlist. .It load Loaded a new playlist. +.It mode +Changed mode +.Pq repeat or consume . .It seek Seeked in the current track. .It unknown blob - 4d7957cecda7b5f2fd118d3c6a408773c513a5f4 blob + 9b5e69f366449dfed4f49652e7e81b5c5cec3fc4 --- amused.c +++ amused.c @@ -161,13 +161,17 @@ main_dispatch_player(int sig, short event, void *d) } log_warnx("%s; skipping %s", errstr, current_song); playlist_dropcurrent(); - /* fallthrough */ + main_playlist_advance(); + if (play_state == STATE_PLAYING) + control_notify(IMSG_CTL_NEXT); + else + control_notify(IMSG_CTL_STOP); + break; case IMSG_EOF: - if (repeat_one && current_song != NULL) { - if (main_play_song(current_song)) - break; + if (repeat_one && main_play_song(current_song)) + break; + else if (repeat_one || consume) playlist_dropcurrent(); - } main_playlist_advance(); if (play_state == STATE_PLAYING) control_notify(IMSG_CTL_NEXT); @@ -570,8 +574,9 @@ main_send_status(struct imsgev *iev) s.status = play_state; s.position = current_position; s.duration = current_duration; - s.rp.repeat_all = repeat_all; - s.rp.repeat_one = repeat_one; + s.mode.repeat_all = repeat_all; + s.mode.repeat_one = repeat_one; + s.mode.consume = consume; imsg_compose_event(iev, IMSG_CTL_STATUS, 0, 0, -1, &s, sizeof(s)); } blob - 11ac2583368d6c0ef18c232b16178c6977b0f86d blob + 588dcade69d138c72e8904a546dfe0ab1cd7d2b2 --- amused.h +++ amused.h @@ -45,7 +45,7 @@ enum imsg_type { IMSG_CTL_NEXT, IMSG_CTL_PREV, IMSG_CTL_JUMP, - IMSG_CTL_REPEAT, /* struct player_repeat */ + IMSG_CTL_MODE, /* struct player_mode */ IMSG_CTL_SEEK, /* struct player_seek */ IMSG_CTL_BEGIN, @@ -80,7 +80,7 @@ enum actions { NEXT, LOAD, JUMP, - REPEAT, + MODE, MONITOR, SEEK, }; @@ -93,9 +93,10 @@ struct player_seek { struct ctl_command; -struct player_repeat { +struct player_mode { int repeat_one; int repeat_all; + int consume; }; struct player_status { @@ -103,7 +104,7 @@ struct player_status { int status; int64_t position; int64_t duration; - struct player_repeat rp; + struct player_mode mode; }; struct parse_result { @@ -112,7 +113,7 @@ struct parse_result { FILE *fp; int pretty; int monitor[IMSG__LAST]; - struct player_repeat rep; + struct player_mode mode; struct player_seek seek; const char *status_format; struct ctl_command *ctl; blob - 0b9e7f0a14f2b475d0a8ee38c162acf2f3fa0ecb blob + e85d663a95e38a25f7fb412dafd703cf13ae6a3a --- control.c +++ control.c @@ -245,7 +245,7 @@ control_dispatch_imsg(int fd, short event, void *bula) { struct ctl_conn *c; struct imsg imsg; - struct player_repeat rp; + struct player_mode mode; struct player_seek seek; ssize_t n, off; @@ -347,16 +347,18 @@ control_dispatch_imsg(int fd, short event, void *bula) case IMSG_CTL_JUMP: main_playlist_jump(&c->iev, &imsg); break; - case IMSG_CTL_REPEAT: - if (IMSG_DATA_SIZE(imsg) != sizeof(rp)) { + case IMSG_CTL_MODE: + if (IMSG_DATA_SIZE(imsg) != sizeof(mode)) { log_warnx("%s: got wrong size", __func__); break; } - memcpy(&rp, imsg.data, sizeof(rp)); - if (rp.repeat_all != -1) - repeat_all = rp.repeat_all; - if (rp.repeat_one != -1) - repeat_one = rp.repeat_one; + memcpy(&mode, imsg.data, sizeof(mode)); + if (mode.repeat_all != -1) + repeat_all = mode.repeat_all; + if (mode.repeat_one != -1) + repeat_one = mode.repeat_one; + if (mode.consume != -1) + consume = mode.consume; control_notify(imsg.hdr.type); break; case IMSG_CTL_BEGIN: blob - f41f3e395f18b515e7357031685364e25bb537a2 blob + 3b01942b95ad0d506ded27942f2fd37969377e64 --- ctl.c +++ ctl.c @@ -44,12 +44,14 @@ static int ctl_show(struct parse_result *, int, char * static int ctl_load(struct parse_result *, int, char **); static int ctl_jump(struct parse_result *, int, char **); static int ctl_repeat(struct parse_result *, int, char **); +static int ctl_consume(struct parse_result *, int, char **); static int ctl_monitor(struct parse_result *, int, char **); static int ctl_seek(struct parse_result *, int, char **); static int ctl_status(struct parse_result *, int, char **); struct ctl_command ctl_commands[] = { { "add", ADD, ctl_add, "files..."}, + { "consume", MODE, ctl_consume, "one|all"}, { "flush", FLUSH, ctl_noarg, ""}, { "jump", JUMP, ctl_jump, "pattern"}, { "load", LOAD, ctl_load, "[file]"}, @@ -58,7 +60,7 @@ struct ctl_command ctl_commands[] = { { "pause", PAUSE, ctl_noarg, ""}, { "play", PLAY, ctl_noarg, ""}, { "prev", PREV, ctl_noarg, ""}, - { "repeat", REPEAT, ctl_repeat, "one|all on|off"}, + { "repeat", MODE, ctl_repeat, "one|all on|off"}, { "restart", RESTART, ctl_noarg, ""}, { "seek", SEEK, ctl_seek, "[+-]time[%]"}, { "show", SHOW, ctl_show, "[-p]"}, @@ -247,6 +249,8 @@ event_name(int type) return "add"; case IMSG_CTL_COMMIT: return "load"; + case IMSG_CTL_MODE: + return "mode"; case IMSG_CTL_SEEK: return "seek"; default: @@ -299,15 +303,18 @@ print_status(struct player_status *ps, const char *spe if (!strcmp(tok, "path")) { puts(ps->path); - } else if (!strcmp(tok, "repeat:oneline")) { + } else if (!strcmp(tok, "mode:oneline")) { printf("repeat one:%s ", - ps->rp.repeat_one ? "on" : "off"); - printf("all:%s\n", ps->rp.repeat_all ? "on" : "off"); + ps->mode.repeat_one ? "on" : "off"); + printf("all:%s ", ps->mode.repeat_all ? "on" : "off"); + printf("consume:%s\n", ps->mode.consume ? "on" : "off"); } else if (!strcmp(tok, "repeat")) { printf("repeat one %s\n", - ps->rp.repeat_one ? "on" : "off"); + ps->mode.repeat_one ? "on" : "off"); printf("repeat all %s\n", - ps->rp.repeat_all ? "on" : "off"); + ps->mode.repeat_all ? "on" : "off"); + printf("consume %s\n", + ps->mode.consume ? "on" : "off"); } else if (!strcmp(tok, "status")) { printf("%s %s\n", status, ps->path); } else if (!strcmp(tok, "time:oneline")) { @@ -416,9 +423,9 @@ ctlaction(struct parse_result *res) imsg_compose(ibuf, IMSG_CTL_JUMP, 0, 0, -1, path, sizeof(path)); break; - case REPEAT: - imsg_compose(ibuf, IMSG_CTL_REPEAT, 0, 0, -1, - &res->rep, sizeof(res->rep)); + case MODE: + imsg_compose(ibuf, IMSG_CTL_MODE, 0, 0, -1, + &res->mode, sizeof(res->mode)); break; case MONITOR: done = 0; @@ -672,15 +679,35 @@ ctl_repeat(struct parse_result *res, int argc, char ** else ctl_usage(res->ctl); - res->rep.repeat_one = -1; - res->rep.repeat_all = -1; + res->mode.repeat_one = -1; + res->mode.repeat_all = -1; + res->mode.consume = -1; if (!strcmp(argv[0], "one")) - res->rep.repeat_one = b; + res->mode.repeat_one = b; else if (!strcmp(argv[0], "all")) - res->rep.repeat_all = b; + res->mode.repeat_all = b; else + ctl_usage(res->ctl); + + return ctlaction(res); +} + +static int +ctl_consume(struct parse_result *res, int argc, char **argv) +{ + int ch; + + while ((ch = getopt(argc, argv, "")) != -1) + ctl_usage(res->ctl); + argc -= optind; + argv += optind; + + if (argc != 1) ctl_usage(res->ctl); + res->mode.repeat_one = -1; + res->mode.repeat_all = -1; + res->mode.consume = !strcmp(argv[0], "on"); return ctlaction(res); } @@ -699,7 +726,7 @@ ctl_monitor(struct parse_result *res, int argc, char * if (argc > 1) ctl_usage(res->ctl); - events = "play,pause,stop,next,prev,jump,repeat,add,load,seek"; + events = "play,pause,stop,next,prev,jump,mode,add,load,seek"; if (argc == 1) events = *argv; @@ -721,8 +748,8 @@ ctl_monitor(struct parse_result *res, int argc, char * res->monitor[IMSG_CTL_PREV] = 1; else if (!strcmp(tok, "jump")) res->monitor[IMSG_CTL_JUMP] = 1; - else if (!strcmp(tok, "repeat")) - res->monitor[IMSG_CTL_REPEAT] = 1; + else if (!strcmp(tok, "mode")) + res->monitor[IMSG_CTL_MODE] = 1; else if (!strcmp(tok, "add")) res->monitor[IMSG_CTL_ADD] = 1; else if (!strcmp(tok, "load")) blob - bf38c046e3d2ddc87a94439913eed4bea6109160 blob + 5192f23ddaaf415199b39af62f879c1027e6a66e --- playlist.c +++ playlist.c @@ -33,6 +33,7 @@ struct playlist playlist; enum play_state play_state; int repeat_one; int repeat_all = 1; +int consume; ssize_t play_off = -1; const char *current_song; int64_t current_position; blob - 661528a56a0c09521566e5336720e9e905af4240 blob + 2570ca8676264d8032ae2c0a4213e90c30c27875 --- playlist.h +++ playlist.h @@ -34,6 +34,7 @@ extern struct playlist playlist; extern enum play_state play_state; extern int repeat_one; extern int repeat_all; +extern int consume; extern ssize_t play_off; extern const char *current_song; extern int64_t current_position;