Commit Diff


commit - ec1fb0c7bde7316b21c4facdcd43af92792487b5
commit + a913de2162216a16a67cd8cf5ae0371c258aefc7
blob - 476254da7d3a25f7d19e3ceb0c90614e124764b3
blob + ad0bcba8dcef709152df7faf1fa2044a5c32b124
--- amused.c
+++ amused.c
@@ -394,6 +394,42 @@ main_play_song(const char *song)
 	imsg_compose_event(iev_player, IMSG_PLAY, 0, 0, fd,
 	    path, sizeof(path));
 	return 1;
+}
+
+void
+main_playlist_jump(struct imsgev *iev, struct imsg *imsg)
+{
+	size_t datalen;
+	char arg[PATH_MAX];
+	const char *song;
+
+	datalen = IMSG_DATA_SIZE(*imsg);
+	if (datalen != sizeof(arg)) {
+		main_senderr(iev, "wrong size");
+		return;
+	}
+
+	memcpy(arg, imsg->data, sizeof(arg));
+	if (arg[sizeof(arg)-1] != '\0') {
+		main_senderr(iev, "data corrupted");
+		return;
+	}
+
+	song = playlist_jump(arg);
+	if (song == NULL) {
+		main_senderr(iev, "not found");
+		return;
+	}
+
+	main_send_player(IMSG_STOP, -1, NULL, 0);
+	if (!main_play_song(song)) {
+		main_senderr(iev, "can't play");
+		playlist_dropcurrent();
+		main_playlist_advance();
+		return;
+	}
+
+	main_send_status(iev);
 }
 
 void
blob - a4afe1c5043cbec97e4d0b7c29aeec7c54574e29
blob + c0f29c807bdaa15952bf65eeb7b355086edbdfe6
--- amused.h
+++ amused.h
@@ -34,7 +34,7 @@ enum imsg_type {
 	IMSG_EOF,
 	IMSG_ERR,
 
-	IMSG_CTL_PLAY,
+	IMSG_CTL_PLAY,		/* with optional filename */
 	IMSG_CTL_TOGGLE_PLAY,
 	IMSG_CTL_PAUSE,
 	IMSG_CTL_STOP,
@@ -44,6 +44,7 @@ enum imsg_type {
 	IMSG_CTL_STATUS,
 	IMSG_CTL_NEXT,
 	IMSG_CTL_PREV,
+	IMSG_CTL_JUMP,
 
 	IMSG_CTL_BEGIN,
 	IMSG_CTL_ADD,		/* path to a file */
@@ -73,6 +74,7 @@ enum actions {
 	PREV,
 	NEXT,
 	LOAD,
+	JUMP,
 };
 
 struct ctl_command;
@@ -106,6 +108,7 @@ void		imsg_event_add(struct imsgev *iev);
 int		imsg_compose_event(struct imsgev *, uint16_t, uint32_t,
 		    pid_t, int, const void *, uint16_t);
 int		main_send_player(uint16_t, int, const void *, uint16_t);
+void		main_playlist_jump(struct imsgev *, struct imsg *);
 void		main_playlist_resume(void);
 void		main_playlist_advance(void);
 void		main_playlist_previous(void);
blob - 05a74efc2f6861eeb0eb8cc63e7826fb5e560538
blob + a84579341527eb8607efab9ae3b3f48a15889d8d
--- control.c
+++ control.c
@@ -323,6 +323,9 @@ control_dispatch_imsg(int fd, short event, void *bula)
 			main_send_player(IMSG_STOP, -1, NULL, 0);
 			main_playlist_previous();
 			break;
+		case IMSG_CTL_JUMP:
+			main_playlist_jump(&c->iev, &imsg);
+			break;
 		case IMSG_CTL_BEGIN:
 			if (control_state.tx != -1) {
 				main_senderr(&c->iev, "locked");
blob - cfa495be900127654257412b4d990727e73e85c0
blob + 6b25d9f3fed4ffd7e513feca47370059a1f94a09
--- ctl.c
+++ ctl.c
@@ -43,6 +43,7 @@ int	ctl_noarg(struct parse_result *, int, char **);
 int	ctl_add(struct parse_result *, int, char **);
 int	ctl_show(struct parse_result *, int, char **);
 int	ctl_load(struct parse_result *, int, char **);
+int	ctl_jump(struct parse_result *, int, char **);
 
 struct ctl_command ctl_commands[] = {
 	{ "play",	PLAY,		ctl_noarg,	"" },
@@ -57,6 +58,7 @@ struct ctl_command ctl_commands[] = {
 	{ "next",	NEXT,		ctl_noarg,	"" },
 	{ "prev",	PREV,		ctl_noarg,	"" },
 	{ "load",	LOAD,		ctl_load,	"[file]", 1 },
+	{ "jump",	JUMP,		ctl_jump,	"pattern" },
 	{ NULL },
 };
 
@@ -136,6 +138,17 @@ enqueue_tracks(char **files)
 	}
 
 	return enq == 0;
+}
+
+static int
+jump_req(const char *arg)
+{
+	char path[PATH_MAX];
+
+	memset(path, 0, sizeof(path));
+	strlcpy(path, arg, sizeof(path));
+	imsg_compose(ibuf, IMSG_CTL_JUMP, 0, 0, -1, path, sizeof(path));
+	return 0;
 }
 
 static void
@@ -374,6 +387,10 @@ ctlaction(struct parse_result *res)
 	case LOAD:
 		done = 0;
 		imsg_compose(ibuf, IMSG_CTL_BEGIN, 0, 0, -1, NULL, 0);
+		break;
+	case JUMP:
+		done = 0;
+		ret = jump_req(res->file);
 		break;
 	case NONE:
 		/* action not expected */
@@ -411,6 +428,7 @@ ctlaction(struct parse_result *res)
 			case STATUS:
 			case NEXT:
 			case PREV:
+			case JUMP:
 				done = show_status(&imsg, &ret);
 				break;
 			case LOAD:
@@ -484,6 +502,23 @@ ctl_load(struct parse_result *res, int argc, char **ar
 	return ctlaction(res);
 }
 
+int
+ctl_jump(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->file = argv[0];
+	return ctlaction(res);
+}
+
 static int
 sockconn(void)
 {
blob - f1a771837bb39ce5572ea229ebd85a682fb4e768
blob + 686e14fa39f3bb2032527d4639aef0424ce8813c
--- playlist.c
+++ playlist.c
@@ -14,6 +14,9 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <sys/types.h>
+
+#include <regex.h>
 #include <stdlib.h>
 #include <syslog.h>
 
@@ -160,3 +163,26 @@ playlist_dropcurrent(void)
 
 	playlist.songs[playlist.len] = NULL;
 }
+
+const char *
+playlist_jump(const char *arg)
+{
+	size_t i;
+	regex_t re;
+
+	if (regcomp(&re, arg, REG_ICASE | REG_NOSUB) != 0)
+		return NULL;
+
+	for (i = 0; i < playlist.len; ++i) {
+		if (regexec(&re, playlist.songs[i], 0, NULL, 0) == 0)
+			break;
+	}
+	regfree(&re);
+
+	if (i == playlist.len)
+		return NULL;
+
+	play_state = STATE_PLAYING;
+	play_off = i;
+	return playlist.songs[i];
+}
blob - a4fed13615d9a6b02734aa8c8573c5c71c0ff642
blob + 95978a15a59fdabc77eff797ba19b27535c9d8e1
--- playlist.h
+++ playlist.h
@@ -46,5 +46,6 @@ void			 playlist_reset(void);
 void			 playlist_free(struct playlist *);
 void			 playlist_truncate(void);
 void			 playlist_dropcurrent(void);
+const char		*playlist_jump(const char *);
 
 #endif