Commit Diff


commit - 0977e96a0236af26cfd4663bce2dad656fa1ef07
commit + 19d6b4807a58ea0e289b006d0ae48224ee106526
blob - a1440c4adf728330cd07d0e83bb931373d36c517
blob + 476254da7d3a25f7d19e3ceb0c90614e124764b3
--- amused.c
+++ amused.c
@@ -463,8 +463,16 @@ main_restart_track(void)
 }
 
 void
-main_enqueue(struct imsgev *iev, struct imsg *imsg)
+main_senderr(struct imsgev *iev, const char *msg)
 {
+	imsg_compose_event(iev, IMSG_CTL_ERR, 0, 0, -1,
+	    msg, strlen(msg)+1);
+}
+
+void
+main_enqueue(int tx, struct playlist *px, struct imsgev *iev,
+    struct imsg *imsg)
+{
 	size_t datalen;
 	char path[PATH_MAX] = { 0 };
 	const char *err = NULL;
@@ -481,7 +489,10 @@ main_enqueue(struct imsgev *iev, struct imsg *imsg)
 		goto err;
 	}
 
-	playlist_enqueue(path);
+	if (px)
+		playlist_push(px, path);
+	else
+		playlist_enqueue(path);
 	imsg_compose_event(iev, IMSG_CTL_ADD, 0, 0, -1, path, sizeof(path));
 	return;
 err:
blob - 2475ee20926c8e17979c97b4e5c97b23998e2707
blob + e84265e2e63261847f752998621a9686b65f1344
--- amused.h
+++ amused.h
@@ -39,13 +39,16 @@ enum imsg_type {
 	IMSG_CTL_PAUSE,
 	IMSG_CTL_STOP,
 	IMSG_CTL_RESTART,
-	IMSG_CTL_ADD,
 	IMSG_CTL_FLUSH,
 	IMSG_CTL_SHOW,
 	IMSG_CTL_STATUS,
 	IMSG_CTL_NEXT,
 	IMSG_CTL_PREV,
 
+	IMSG_CTL_BEGIN,
+	IMSG_CTL_ADD,		/* path to a file */
+	IMSG_CTL_COMMIT,
+
 	IMSG_CTL_ERR,
 };
 
@@ -94,6 +97,8 @@ struct player_status {
 	int	status;
 };
 
+struct playlist;
+
 /* amused.c */
 void		spawn_daemon(void);
 void		imsg_event_add(struct imsgev *iev);
@@ -104,7 +109,8 @@ void		main_playlist_resume(void);
 void		main_playlist_advance(void);
 void		main_playlist_previous(void);
 void		main_restart_track(void);
-void		main_enqueue(struct imsgev *, struct imsg *);
+void		main_senderr(struct imsgev *, const char *);
+void		main_enqueue(int, struct playlist *, struct imsgev *, struct imsg *);
 void		main_send_playlist(struct imsgev *);
 void		main_send_status(struct imsgev *);
 
blob - d8e0f626db6bc19c15243ab660931a65ec79ca46
blob + 05a74efc2f6861eeb0eb8cc63e7826fb5e560538
--- control.c
+++ control.c
@@ -45,7 +45,9 @@ struct {
 	struct event	ev;
 	struct event	evt;
 	int		fd;
-} control_state = {.fd = -1};
+	struct playlist	play;
+	pid_t		tx;
+} control_state = {.fd = -1, .tx = -1};
 
 struct ctl_conn {
 	TAILQ_ENTRY(ctl_conn)	entry;
@@ -201,6 +203,12 @@ control_close(int fd)
 	if ((c = control_connbyfd(fd)) == NULL) {
 		log_warnx("%s: fd %d: not found", __func__, fd);
 		return;
+	}
+
+	/* abort the transaction if running by this user */
+	if (c->iev.ibuf.pid == control_state.tx) {
+		playlist_free(&control_state.play);
+		control_state.tx = -1;
 	}
 
 	msgbuf_clear(&c->iev.ibuf.w);
@@ -298,9 +306,6 @@ control_dispatch_imsg(int fd, short event, void *bula)
 			main_send_player(IMSG_STOP, -1, NULL, 0);
 			main_restart_track();
 			break;
-		case IMSG_CTL_ADD:
-			main_enqueue(&c->iev, &imsg);
-			break;
 		case IMSG_CTL_FLUSH:
 			playlist_truncate();
 			break;
@@ -318,6 +323,36 @@ control_dispatch_imsg(int fd, short event, void *bula)
 			main_send_player(IMSG_STOP, -1, NULL, 0);
 			main_playlist_previous();
 			break;
+		case IMSG_CTL_BEGIN:
+			if (control_state.tx != -1) {
+				main_senderr(&c->iev, "locked");
+				break;
+			}
+			control_state.tx = c->iev.ibuf.pid;
+			imsg_compose_event(&c->iev, IMSG_CTL_BEGIN, 0, 0, -1,
+			    NULL, 0);
+			break;
+		case IMSG_CTL_ADD:
+			if (control_state.tx != -1 &&
+			    control_state.tx != c->iev.ibuf.pid) {
+				main_senderr(&c->iev, "locked");
+				break;
+			}
+			main_enqueue(control_state.tx != -1,
+			   &control_state.play,&c->iev, &imsg);
+			break;
+		case IMSG_CTL_COMMIT:
+			if (control_state.tx != c->iev.ibuf.pid) {
+				main_senderr(&c->iev, "locked");
+				break;
+			}
+			playlist_swap(&control_state.play);
+			memset(&control_state.play, 0,
+			    sizeof(control_state.play));
+			control_state.tx = -1;
+			imsg_compose_event(&c->iev, IMSG_CTL_COMMIT, 0, 0, -1,
+			    NULL, 0);
+			break;
 		default:
 			log_debug("%s: error handling imsg %d", __func__,
 			    imsg.hdr.type);