Commit Diff


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;