change license from GPLv3 to GPLv3 or later
[mmq.git] / mmq-player.c
blob08e8daab27af156c8b552496187351593c2d4f3d
1 #include "mmq.h"
2 #include "fixeddec/fixeddec.h"
4 #ifndef MMQ_MQUEUE
5 # define MMQ_MQUEUE "/mmq"
6 #endif
8 #ifndef MMQ_MSGSIZE
9 # define MMQ_MSGSIZE 256
10 #endif
12 #ifndef MMQ_MAXMSG
13 # define MMQ_MAXMSG 10 /* Linux 2.6 default */
14 #endif
16 enum player_state g_state;
17 long g_seek_msec;
18 static struct mq_attr attr;
19 static mqd_t mq;
22 * we only have two opcodes for messages in the queue, signals handle
23 * everything else
25 enum opcode {
26 OP_PLAY_PATH = '=', /* path to an audio file */
27 OP_SEEK_PRE = ':' /* seek point for next song before playback */
30 static void next_handler(UNUSED int signum)
32 g_state = STATE_NEXT;
33 emit("^\n");
36 static void sig_init(void)
38 struct sigaction sa;
40 memset(&sa, 0, sizeof(struct sigaction));
41 sigemptyset(&sa.sa_mask);
42 sa.sa_flags = SA_RESTART;
43 sa.sa_handler = next_handler;
44 sigaction(SIGUSR1, &sa, NULL);
47 static void set_mq_nonblock(int nb)
49 attr.mq_flags = nb ? O_NONBLOCK : 0;
51 if (mq_setattr(mq, &attr, NULL) < 0)
52 die("mq_setattr: %s\n", strerror(errno));
55 static void read_seek_point(char *buf, ssize_t len)
57 buf[len] = '\0';
58 g_seek_msec = strtol(buf, NULL, 10);
60 emit(":%ld\n", g_seek_msec);
63 static void play_path(char *buf, ssize_t len)
65 g_state = STATE_PLAY;
66 buf[len] = '\n';
67 write(STDOUT_FILENO, buf - 1, len + 2);
68 buf[len] = '\0';
69 fixeddec_play(buf, len);
70 emit(".\n");
71 if (g_state == STATE_NEXT)
72 audio_close(0);
75 static void unknown(const char *buf, ssize_t len)
77 warn("unknown message received:\n");
78 write(2, buf, len);
79 warn("\n-------------------------\n");
82 /* lets try to get away without accepting command-line arguments... */
83 int main(void)
85 char tmp[MMQ_MSGSIZE + 1];
86 ssize_t r;
88 attr.mq_msgsize = MMQ_MSGSIZE;
89 attr.mq_maxmsg = MMQ_MAXMSG;
91 mq = mq_open(MMQ_MQUEUE, O_CREAT|O_RDONLY, 0666, &attr);
92 if (mq == (mqd_t)-1)
93 die("mq_open(%s): %s\n", MMQ_MQUEUE, strerror(errno));
95 sig_init();
96 for (;;) {
97 r = mq_receive(mq, tmp, attr.mq_msgsize, NULL);
98 if (r == 0 || (r < 0 && errno == EINTR)) {
99 /* ignore */
100 } else if (r < 0) {
101 int err = errno;
103 if (err == EAGAIN) {
104 audio_close(1);
105 set_mq_nonblock(0);
106 } else {
107 die("mq_receive: %s\n", strerror(err));
109 } else {
110 assert(r > 0 && "r is not positive");
111 switch (*tmp) {
112 case OP_SEEK_PRE:
113 read_seek_point(tmp + 1, r - 1);
114 break;
115 case OP_PLAY_PATH:
116 play_path(tmp + 1, r - 1);
117 set_mq_nonblock(1);
118 break;
119 default: unknown(tmp, r);
124 return 0;