Wed Mar 4 13:34:49 2015 UTC ()
PR/49716: Henning Petersen: Use false and true on bool, fix sign in printf
formats.


(christos)
diff -r1.7 -r1.8 src/usr.bin/midirecord/midirecord.c

cvs diff -r1.7 -r1.8 src/usr.bin/midirecord/midirecord.c (switch to unified diff)

--- src/usr.bin/midirecord/midirecord.c 2015/03/01 09:56:54 1.7
+++ src/usr.bin/midirecord/midirecord.c 2015/03/04 13:34:49 1.8
@@ -1,805 +1,805 @@ @@ -1,805 +1,805 @@
1/* $NetBSD: midirecord.c,v 1.7 2015/03/01 09:56:54 mrg Exp $ */ 1/* $NetBSD: midirecord.c,v 1.8 2015/03/04 13:34:49 christos Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2014 Matthew R. Green 4 * Copyright (c) 2014 Matthew R. Green
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE. 26 * SUCH DAMAGE.
27 */ 27 */
28 28
29/* 29/*
30 * midirecord(1), similar to audiorecord(1). 30 * midirecord(1), similar to audiorecord(1).
31 */ 31 */
32 32
33#include <sys/cdefs.h> 33#include <sys/cdefs.h>
34 34
35#ifndef lint 35#ifndef lint
36__RCSID("$NetBSD: midirecord.c,v 1.7 2015/03/01 09:56:54 mrg Exp $"); 36__RCSID("$NetBSD: midirecord.c,v 1.8 2015/03/04 13:34:49 christos Exp $");
37#endif 37#endif
38 38
39#include <sys/param.h> 39#include <sys/param.h>
40#include <sys/midiio.h> 40#include <sys/midiio.h>
41#include <sys/ioctl.h> 41#include <sys/ioctl.h>
42#include <sys/time.h> 42#include <sys/time.h>
43#include <sys/uio.h> 43#include <sys/uio.h>
44 44
45#include <err.h> 45#include <err.h>
46#include <errno.h> 46#include <errno.h>
47#include <ctype.h> 47#include <ctype.h>
48#include <fcntl.h> 48#include <fcntl.h>
49#include <paths.h> 49#include <paths.h>
50#include <signal.h> 50#include <signal.h>
51#include <stdio.h> 51#include <stdio.h>
52#include <stdlib.h> 52#include <stdlib.h>
53#include <string.h> 53#include <string.h>
54#include <unistd.h> 54#include <unistd.h>
55#include <util.h> 55#include <util.h>
56#include <assert.h> 56#include <assert.h>
57#include <stdbool.h> 57#include <stdbool.h>
58 58
59#include "libaudio.h" 59#include "libaudio.h"
60 60
61static const char *midi_device; 61static const char *midi_device;
62static unsigned *filt_devnos = NULL; 62static unsigned *filt_devnos = NULL;
63static unsigned *filt_chans = NULL; 63static unsigned *filt_chans = NULL;
64static unsigned num_filt_devnos, num_filt_chans; 64static unsigned num_filt_devnos, num_filt_chans;
65static char *raw_output; 65static char *raw_output;
66static int midifd; 66static int midifd;
67static int aflag, qflag, oflag; 67static int aflag, qflag, oflag;
68static bool debug = false; 68static bool debug = false;
69int verbose; 69int verbose;
70static int outfd, rawfd = -1; 70static int outfd, rawfd = -1;
71static ssize_t data_size; 71static ssize_t data_size;
72static struct timeval record_time; 72static struct timeval record_time;
73static struct timeval start_time; 73static struct timeval start_time;
74static int tempo = 120; 74static int tempo = 120;
75static unsigned notes_per_beat = 24; 75static unsigned notes_per_beat = 24;
76static bool ignore_timer_fail = false; 76static bool ignore_timer_fail = false;
77static bool stdout_mode = false; 77static bool stdout_mode = false;
78 78
79static void debug_log(const char *, size_t, const char *, ...) 79static void debug_log(const char *, size_t, const char *, ...)
80 __printflike(3, 4); 80 __printflike(3, 4);
81static size_t midi_event_local_to_output(seq_event_t, u_char *, size_t); 81static size_t midi_event_local_to_output(seq_event_t, u_char *, size_t);
82static size_t midi_event_timer_wait_abs_to_output(seq_event_t, u_char *, 82static size_t midi_event_timer_wait_abs_to_output(seq_event_t, u_char *,
83 size_t); 83 size_t);
84static size_t midi_event_timer_to_output(seq_event_t, u_char *, size_t); 84static size_t midi_event_timer_to_output(seq_event_t, u_char *, size_t);
85static size_t midi_event_chn_common_to_output(seq_event_t, u_char *, size_t); 85static size_t midi_event_chn_common_to_output(seq_event_t, u_char *, size_t);
86static size_t midi_event_chn_voice_to_output(seq_event_t, u_char *, size_t); 86static size_t midi_event_chn_voice_to_output(seq_event_t, u_char *, size_t);
87static size_t midi_event_sysex_to_output(seq_event_t, u_char *, size_t); 87static size_t midi_event_sysex_to_output(seq_event_t, u_char *, size_t);
88static size_t midi_event_fullsize_to_output(seq_event_t, u_char *, size_t); 88static size_t midi_event_fullsize_to_output(seq_event_t, u_char *, size_t);
89static size_t midi_event_to_output(seq_event_t, u_char *, size_t); 89static size_t midi_event_to_output(seq_event_t, u_char *, size_t);
90static int timeleft(struct timeval *, struct timeval *); 90static int timeleft(struct timeval *, struct timeval *);
91static bool filter_array(unsigned, unsigned *, size_t); 91static bool filter_array(unsigned, unsigned *, size_t);
92static bool filter_dev(unsigned); 92static bool filter_dev(unsigned);
93static bool filter_chan(unsigned); 93static bool filter_chan(unsigned);
94static bool filter_devchan(unsigned, unsigned); 94static bool filter_devchan(unsigned, unsigned);
95static void parse_ints(const char *, unsigned **, unsigned *, const char *); 95static void parse_ints(const char *, unsigned **, unsigned *, const char *);
96static void cleanup(int) __dead; 96static void cleanup(int) __dead;
97static void rewrite_header(void); 97static void rewrite_header(void);
98static void write_midi_header(void); 98static void write_midi_header(void);
99static void write_midi_trailer(void); 99static void write_midi_trailer(void);
100static void usage(void) __dead; 100static void usage(void) __dead;
101 101
102#define PATH_DEV_MUSIC "/dev/music" 102#define PATH_DEV_MUSIC "/dev/music"
103 103
104int 104int
105main(int argc, char *argv[]) 105main(int argc, char *argv[])
106{ 106{
107 u_char *buffer; 107 u_char *buffer;
108 size_t bufsize = 0; 108 size_t bufsize = 0;
109 int ch, no_time_limit = 1; 109 int ch, no_time_limit = 1;
110 110
111 while ((ch = getopt(argc, argv, "aB:c:Dd:f:hn:oqr:t:T:V")) != -1) { 111 while ((ch = getopt(argc, argv, "aB:c:Dd:f:hn:oqr:t:T:V")) != -1) {
112 switch (ch) { 112 switch (ch) {
113 case 'a': 113 case 'a':
114 aflag++; 114 aflag++;
115 break; 115 break;
116 case 'B': 116 case 'B':
117 bufsize = strsuftoll("read buffer size", optarg, 117 bufsize = strsuftoll("read buffer size", optarg,
118 1, UINT_MAX); 118 1, UINT_MAX);
119 break; 119 break;
120 case 'c': 120 case 'c':
121 parse_ints(optarg, &filt_chans, &num_filt_chans, 121 parse_ints(optarg, &filt_chans, &num_filt_chans,
122 "channels"); 122 "channels");
123 break; 123 break;
124 case 'D': 124 case 'D':
125 debug++; 125 debug = true;
126 break; 126 break;
127 case 'd': 127 case 'd':
128 parse_ints(optarg, &filt_devnos, &num_filt_devnos, 128 parse_ints(optarg, &filt_devnos, &num_filt_devnos,
129 "devices"); 129 "devices");
130 break; 130 break;
131 case 'f': 131 case 'f':
132 midi_device = optarg; 132 midi_device = optarg;
133 ignore_timer_fail = true; 133 ignore_timer_fail = true;
134 break; 134 break;
135 case 'n': 135 case 'n':
136 decode_uint(optarg, &notes_per_beat); 136 decode_uint(optarg, &notes_per_beat);
137 break; 137 break;
138 case 'o': 138 case 'o':
139 oflag++; /* time stamp starts at proc start */ 139 oflag++; /* time stamp starts at proc start */
140 break; 140 break;
141 case 'q': 141 case 'q':
142 qflag++; 142 qflag++;
143 break; 143 break;
144 case 'r': 144 case 'r':
145 raw_output = optarg; 145 raw_output = optarg;
146 break; 146 break;
147 case 't': 147 case 't':
148 no_time_limit = 0; 148 no_time_limit = 0;
149 decode_time(optarg, &record_time); 149 decode_time(optarg, &record_time);
150 break; 150 break;
151 case 'T': 151 case 'T':
152 decode_int(optarg, &tempo); 152 decode_int(optarg, &tempo);
153 break; 153 break;
154 case 'V': 154 case 'V':
155 verbose++; 155 verbose++;
156 break; 156 break;
157 /* case 'h': */ 157 /* case 'h': */
158 default: 158 default:
159 usage(); 159 usage();
160 /* NOTREACHED */ 160 /* NOTREACHED */
161 } 161 }
162 } 162 }
163 argc -= optind; 163 argc -= optind;
164 argv += optind; 164 argv += optind;
165 165
166 if (argc != 1) 166 if (argc != 1)
167 usage(); 167 usage();
168 168
169 /* 169 /*
170 * work out the buffer size to use, and allocate it. don't allow it 170 * work out the buffer size to use, and allocate it. don't allow it
171 * to be too small. 171 * to be too small.
172 */ 172 */
173 if (bufsize < 32) 173 if (bufsize < 32)
174 bufsize = 32 * 1024; 174 bufsize = 32 * 1024;
175 buffer = malloc(bufsize); 175 buffer = malloc(bufsize);
176 if (buffer == NULL) 176 if (buffer == NULL)
177 err(1, "couldn't malloc buffer of %d size", (int)bufsize); 177 err(1, "couldn't malloc buffer of %d size", (int)bufsize);
178 178
179 /* 179 /*
180 * open the music device 180 * open the music device
181 */ 181 */
182 if (midi_device == NULL && (midi_device = getenv("MIDIDEVICE")) == NULL) 182 if (midi_device == NULL && (midi_device = getenv("MIDIDEVICE")) == NULL)
183 midi_device = PATH_DEV_MUSIC; 183 midi_device = PATH_DEV_MUSIC;
184 midifd = open(midi_device, O_RDONLY); 184 midifd = open(midi_device, O_RDONLY);
185 if (midifd < 0) 185 if (midifd < 0)
186 err(1, "failed to open %s", midi_device); 186 err(1, "failed to open %s", midi_device);
187 187
188 /* open the output file */ 188 /* open the output file */
189 if (argv[0][0] != '-' || argv[0][1] != '\0') { 189 if (argv[0][0] != '-' || argv[0][1] != '\0') {
190 int mode = O_CREAT|(aflag ? O_APPEND : O_TRUNC)|O_WRONLY; 190 int mode = O_CREAT|(aflag ? O_APPEND : O_TRUNC)|O_WRONLY;
191 191
192 outfd = open(*argv, mode, 0666); 192 outfd = open(*argv, mode, 0666);
193 if (outfd < 0) 193 if (outfd < 0)
194 err(1, "could not open %s", *argv); 194 err(1, "could not open %s", *argv);
195 } else { 195 } else {
196 stdout_mode = true; 196 stdout_mode = true;
197 outfd = STDOUT_FILENO; 197 outfd = STDOUT_FILENO;
198 } 198 }
199 199
200 /* open the raw output file */ 200 /* open the raw output file */
201 if (raw_output) { 201 if (raw_output) {
202 int mode = O_CREAT|(aflag ? O_APPEND : O_TRUNC)|O_WRONLY; 202 int mode = O_CREAT|(aflag ? O_APPEND : O_TRUNC)|O_WRONLY;
203 203
204 rawfd = open(raw_output, mode, 0666); 204 rawfd = open(raw_output, mode, 0666);
205 if (rawfd < 0) 205 if (rawfd < 0)
206 err(1, "could not open %s", raw_output); 206 err(1, "could not open %s", raw_output);
207 } 207 }
208 208
209 /* start the midi timer */ 209 /* start the midi timer */
210 if (ioctl(midifd, SEQUENCER_TMR_START, NULL) < 0) { 210 if (ioctl(midifd, SEQUENCER_TMR_START, NULL) < 0) {
211 if (ignore_timer_fail) 211 if (ignore_timer_fail)
212 warn("failed to start midi timer"); 212 warn("failed to start midi timer");
213 else 213 else
214 err(1, "failed to start midi timer"); 214 err(1, "failed to start midi timer");
215 } 215 }
216 216
217 /* set the timebase */ 217 /* set the timebase */
218 if (ioctl(midifd, SEQUENCER_TMR_TIMEBASE, &notes_per_beat) < 0) { 218 if (ioctl(midifd, SEQUENCER_TMR_TIMEBASE, &notes_per_beat) < 0) {
219 if (ignore_timer_fail) 219 if (ignore_timer_fail)
220 warn("SEQUENCER_TMR_TIMEBASE: notes_per_beat %d", 220 warn("SEQUENCER_TMR_TIMEBASE: notes_per_beat %d",
221 notes_per_beat); 221 notes_per_beat);
222 else 222 else
223 err(1, "SEQUENCER_TMR_TIMEBASE: notes_per_beat %d", 223 err(1, "SEQUENCER_TMR_TIMEBASE: notes_per_beat %d",
224 notes_per_beat); 224 notes_per_beat);
225 } 225 }
226 226
227 /* set the tempo */ 227 /* set the tempo */
228 if (ioctl(midifd, SEQUENCER_TMR_TEMPO, &tempo) < 0) { 228 if (ioctl(midifd, SEQUENCER_TMR_TEMPO, &tempo) < 0) {
229 if (ignore_timer_fail) 229 if (ignore_timer_fail)
230 warn("SEQUENCER_TMR_TIMEBASE: tempo %d", tempo); 230 warn("SEQUENCER_TMR_TIMEBASE: tempo %d", tempo);
231 else 231 else
232 err(1, "SEQUENCER_TMR_TIMEBASE: tempo %d", tempo); 232 err(1, "SEQUENCER_TMR_TIMEBASE: tempo %d", tempo);
233 } 233 }
234 234
235 signal(SIGINT, cleanup); 235 signal(SIGINT, cleanup);
236 236
237 data_size = 0; 237 data_size = 0;
238 238
239 if (verbose) 239 if (verbose)
240 fprintf(stderr, "tempo=%d notes_per_beat=%d\n", 240 fprintf(stderr, "tempo=%d notes_per_beat=%u\n",
241 tempo, notes_per_beat); 241 tempo, notes_per_beat);
242 242
243 if (!no_time_limit && verbose) 243 if (!no_time_limit && verbose)
244 fprintf(stderr, "recording for %lu seconds, %lu microseconds\n", 244 fprintf(stderr, "recording for %lu seconds, %lu microseconds\n",
245 (u_long)record_time.tv_sec, (u_long)record_time.tv_usec); 245 (u_long)record_time.tv_sec, (u_long)record_time.tv_usec);
246 246
247 /* Create a midi header. */ 247 /* Create a midi header. */
248 write_midi_header(); 248 write_midi_header();
249 249
250 (void)gettimeofday(&start_time, NULL); 250 (void)gettimeofday(&start_time, NULL);
251 while (no_time_limit || timeleft(&start_time, &record_time)) { 251 while (no_time_limit || timeleft(&start_time, &record_time)) {
252 seq_event_t e; 252 seq_event_t e;
253 size_t wrsize; 253 size_t wrsize;
254 size_t rdsize; 254 size_t rdsize;
255 255
256 rdsize = (size_t)read(midifd, &e, sizeof e); 256 rdsize = (size_t)read(midifd, &e, sizeof e);
257 if (rdsize == 0) 257 if (rdsize == 0)
258 break; 258 break;
259 259
260 if (rdsize != sizeof e) 260 if (rdsize != sizeof e)
261 err(1, "read failed"); 261 err(1, "read failed");
262 262
263 if (rawfd != -1 && write(rawfd, &e, sizeof e) != sizeof e) 263 if (rawfd != -1 && write(rawfd, &e, sizeof e) != sizeof e)
264 err(1, "write to raw file failed"); 264 err(1, "write to raw file failed");
265 265
266 /* convert 'e' into something useful for output */ 266 /* convert 'e' into something useful for output */
267 wrsize = midi_event_to_output(e, buffer, bufsize); 267 wrsize = midi_event_to_output(e, buffer, bufsize);
268 268
269 if (wrsize) { 269 if (wrsize) {
270 if ((size_t)write(outfd, buffer, wrsize) != wrsize) 270 if ((size_t)write(outfd, buffer, wrsize) != wrsize)
271 err(1, "write failed"); 271 err(1, "write failed");
272 data_size += wrsize; 272 data_size += wrsize;
273 } 273 }
274 } 274 }
275 cleanup(0); 275 cleanup(0);
276} 276}
277 277
278static void 278static void
279debug_log(const char *file, size_t line, const char *fmt, ...) 279debug_log(const char *file, size_t line, const char *fmt, ...)
280{ 280{
281 va_list ap; 281 va_list ap;
282 282
283 if (!debug) 283 if (!debug)
284 return; 284 return;
285 fprintf(stderr, "%s:%zd: ", file, line); 285 fprintf(stderr, "%s:%zu: ", file, line);
286 va_start(ap, fmt); 286 va_start(ap, fmt);
287 vfprintf(stderr, fmt, ap); 287 vfprintf(stderr, fmt, ap);
288 va_end(ap); 288 va_end(ap);
289 fprintf(stderr, "\n"); 289 fprintf(stderr, "\n");
290} 290}
291 291
292#define LOG(fmt...) \ 292#define LOG(fmt...) \
293 debug_log(__func__, __LINE__, fmt) 293 debug_log(__func__, __LINE__, fmt)
294 294
295 295
296/* 296/*
297 * handle a SEQ_LOCAL event. NetBSD /dev/music doesn't generate these. 297 * handle a SEQ_LOCAL event. NetBSD /dev/music doesn't generate these.
298 */ 298 */
299static size_t 299static size_t
300midi_event_local_to_output(seq_event_t e, u_char *buffer, size_t bufsize) 300midi_event_local_to_output(seq_event_t e, u_char *buffer, size_t bufsize)
301{ 301{
302 size_t size = 0; 302 size_t size = 0;
303 303
304 LOG("UNHANDLED SEQ_COCAL"); 304 LOG("UNHANDLED SEQ_COCAL");
305 305
306 return size; 306 return size;
307} 307}
308 308
309/* 309/*
310 * convert a midi absolute time event to a variable length delay 310 * convert a midi absolute time event to a variable length delay
311 */ 311 */
312static size_t 312static size_t
313midi_event_timer_wait_abs_to_output( 313midi_event_timer_wait_abs_to_output(
314 seq_event_t e, 314 seq_event_t e,
315 u_char *buffer, 315 u_char *buffer,
316 size_t bufsize) 316 size_t bufsize)
317{ 317{
318 static unsigned prev_div; 318 static unsigned prev_div;
319 unsigned cur_div; 319 unsigned cur_div;
320 unsigned val = 0, xdiv; 320 unsigned val = 0, xdiv;
321 int vallen = 0, i; 321 int vallen = 0, i;
322 322
323 if (prev_div == 0 && !oflag) 323 if (prev_div == 0 && !oflag)
324 prev_div = e.t_WAIT_ABS.divisions; 324 prev_div = e.t_WAIT_ABS.divisions;
325 cur_div = e.t_WAIT_ABS.divisions; 325 cur_div = e.t_WAIT_ABS.divisions;
326 326
327 xdiv = cur_div - prev_div; 327 xdiv = cur_div - prev_div;
328 if (xdiv) { 328 if (xdiv) {
329 while (xdiv) { 329 while (xdiv) {
330 uint32_t extra = val ? 0x80 : 0; 330 uint32_t extra = val ? 0x80 : 0;
331 331
332 val <<= 8; 332 val <<= 8;
333 val |= (xdiv & 0x7f) | extra; 333 val |= (xdiv & 0x7f) | extra;
334 xdiv >>= 7; 334 xdiv >>= 7;
335 vallen++; 335 vallen++;
336 } 336 }
337 } else 337 } else
338 vallen = 1; 338 vallen = 1;
339 339
340 for (i = 0; i < vallen; i++) { 340 for (i = 0; i < vallen; i++) {
341 buffer[i] = val & 0xff; 341 buffer[i] = val & 0xff;
342 val >>= 8; 342 val >>= 8;
343 } 343 }
344 for (; i < 4; i++) 344 for (; i < 4; i++)
345 buffer[i] = 0; 345 buffer[i] = 0;
346 LOG("TMR_WAIT_ABS: new div %x (cur %x prev %x): bufval (len=%u): " 346 LOG("TMR_WAIT_ABS: new div %x (cur %x prev %x): bufval (len=%u): "
347 "%02x:%02x:%02x:%02x", 347 "%02x:%02x:%02x:%02x",
348 cur_div - prev_div, cur_div, prev_div, 348 cur_div - prev_div, cur_div, prev_div,
349 vallen, buffer[0], buffer[1], buffer[2], buffer[3]);  349 vallen, buffer[0], buffer[1], buffer[2], buffer[3]);
350 350
351 prev_div = cur_div; 351 prev_div = cur_div;
352 352
353 return vallen; 353 return vallen;
354} 354}
355 355
356/* 356/*
357 * handle a SEQ_TIMING event. 357 * handle a SEQ_TIMING event.
358 */ 358 */
359static size_t 359static size_t
360midi_event_timer_to_output(seq_event_t e, u_char *buffer, size_t bufsize) 360midi_event_timer_to_output(seq_event_t e, u_char *buffer, size_t bufsize)
361{ 361{
362 size_t size = 0; 362 size_t size = 0;
363 363
364 LOG("SEQ_TIMING"); 364 LOG("SEQ_TIMING");
365 switch (e.timing.op) { 365 switch (e.timing.op) {
366 case TMR_WAIT_REL: 366 case TMR_WAIT_REL:
367 /* NetBSD /dev/music doesn't generate these. */ 367 /* NetBSD /dev/music doesn't generate these. */
368 LOG("UNHANDLED TMR_WAIT_REL: divisions: %x", e.t_WAIT_REL.divisions); 368 LOG("UNHANDLED TMR_WAIT_REL: divisions: %x", e.t_WAIT_REL.divisions);
369 break; 369 break;
370 370
371 case TMR_WAIT_ABS: 371 case TMR_WAIT_ABS:
372 size = midi_event_timer_wait_abs_to_output(e, buffer, bufsize); 372 size = midi_event_timer_wait_abs_to_output(e, buffer, bufsize);
373 break; 373 break;
374 374
375 case TMR_STOP: 375 case TMR_STOP:
376 case TMR_START: 376 case TMR_START:
377 case TMR_CONTINUE: 377 case TMR_CONTINUE:
378 case TMR_TEMPO: 378 case TMR_TEMPO:
379 case TMR_ECHO: 379 case TMR_ECHO:
380 case TMR_CLOCK: 380 case TMR_CLOCK:
381 case TMR_SPP: 381 case TMR_SPP:
382 case TMR_TIMESIG: 382 case TMR_TIMESIG:
383 /* NetBSD /dev/music doesn't generate these. */ 383 /* NetBSD /dev/music doesn't generate these. */
384 LOG("UNHANDLED timer op: %x", e.timing.op); 384 LOG("UNHANDLED timer op: %x", e.timing.op);
385 break; 385 break;
386  386
387 default: 387 default:
388 LOG("unknown timer op: %x", e.timing.op); 388 LOG("unknown timer op: %x", e.timing.op);
389 break; 389 break;
390 } 390 }
391 391
392 return size; 392 return size;
393} 393}
394 394
395/* 395/*
396 * handle a SEQ_CHN_COMMON event. 396 * handle a SEQ_CHN_COMMON event.
397 */ 397 */
398static size_t 398static size_t
399midi_event_chn_common_to_output(seq_event_t e, u_char *buffer, size_t bufsize) 399midi_event_chn_common_to_output(seq_event_t e, u_char *buffer, size_t bufsize)
400{ 400{
401 size_t size = 0; 401 size_t size = 0;
402 402
403 assert(e.common.channel < 16); 403 assert(e.common.channel < 16);
404 LOG("SEQ_CHN_COMMON"); 404 LOG("SEQ_CHN_COMMON");
405 405
406 if (filter_devchan(e.common.device, e.common.channel)) 406 if (filter_devchan(e.common.device, e.common.channel))
407 return 0; 407 return 0;
408 408
409 switch (e.common.op) { 409 switch (e.common.op) {
410 case MIDI_CTL_CHANGE: 410 case MIDI_CTL_CHANGE:
411 buffer[0] = MIDI_CTL_CHANGE | e.c_CTL_CHANGE.channel; 411 buffer[0] = MIDI_CTL_CHANGE | e.c_CTL_CHANGE.channel;
412 buffer[1] = e.c_CTL_CHANGE.controller; 412 buffer[1] = e.c_CTL_CHANGE.controller;
413 buffer[2] = e.c_CTL_CHANGE.value; 413 buffer[2] = e.c_CTL_CHANGE.value;
414 LOG("MIDI_CTL_CHANGE: channel %x ctrl %x val %x", 414 LOG("MIDI_CTL_CHANGE: channel %x ctrl %x val %x",
415 e.c_CTL_CHANGE.channel, e.c_CTL_CHANGE.controller, 415 e.c_CTL_CHANGE.channel, e.c_CTL_CHANGE.controller,
416 e.c_CTL_CHANGE.value); 416 e.c_CTL_CHANGE.value);
417 size = 3; 417 size = 3;
418 break; 418 break;
419 419
420 case MIDI_PGM_CHANGE: 420 case MIDI_PGM_CHANGE:
421 buffer[0] = MIDI_PGM_CHANGE | e.c_PGM_CHANGE.channel; 421 buffer[0] = MIDI_PGM_CHANGE | e.c_PGM_CHANGE.channel;
422 buffer[1] = e.c_PGM_CHANGE.program; 422 buffer[1] = e.c_PGM_CHANGE.program;
423 LOG("MIDI_PGM_CHANGE: channel %x program %x", 423 LOG("MIDI_PGM_CHANGE: channel %x program %x",
424 e.c_PGM_CHANGE.channel, e.c_PGM_CHANGE.program); 424 e.c_PGM_CHANGE.channel, e.c_PGM_CHANGE.program);
425 size = 2; 425 size = 2;
426 break; 426 break;
427 427
428 case MIDI_CHN_PRESSURE: 428 case MIDI_CHN_PRESSURE:
429 buffer[0] = MIDI_CHN_PRESSURE | e.c_CHN_PRESSURE.channel; 429 buffer[0] = MIDI_CHN_PRESSURE | e.c_CHN_PRESSURE.channel;
430 buffer[1] = e.c_CHN_PRESSURE.pressure; 430 buffer[1] = e.c_CHN_PRESSURE.pressure;
431 LOG("MIDI_CHN_PRESSURE: channel %x pressure %x", 431 LOG("MIDI_CHN_PRESSURE: channel %x pressure %x",
432 e.c_CHN_PRESSURE.channel, e.c_CHN_PRESSURE.pressure); 432 e.c_CHN_PRESSURE.channel, e.c_CHN_PRESSURE.pressure);
433 size = 2; 433 size = 2;
434 break; 434 break;
435 435
436 case MIDI_PITCH_BEND: 436 case MIDI_PITCH_BEND:
437 buffer[0] = MIDI_PITCH_BEND | e.c_PITCH_BEND.channel; 437 buffer[0] = MIDI_PITCH_BEND | e.c_PITCH_BEND.channel;
438 /* 14 bits split over 2 data bytes, lsb first */ 438 /* 14 bits split over 2 data bytes, lsb first */
439 buffer[1] = e.c_PITCH_BEND.value & 0x7f; 439 buffer[1] = e.c_PITCH_BEND.value & 0x7f;
440 buffer[2] = (e.c_PITCH_BEND.value >> 7) & 0x7f; 440 buffer[2] = (e.c_PITCH_BEND.value >> 7) & 0x7f;
441 LOG("MIDI_PITCH_BEND: channel %x val %x", 441 LOG("MIDI_PITCH_BEND: channel %x val %x",
442 e.c_PITCH_BEND.channel, e.c_PITCH_BEND.value); 442 e.c_PITCH_BEND.channel, e.c_PITCH_BEND.value);
443 size = 3; 443 size = 3;
444 break; 444 break;
445 445
446 default: 446 default:
447 LOG("unknown common op: %x", e.voice.op); 447 LOG("unknown common op: %x", e.voice.op);
448 break; 448 break;
449 } 449 }
450 450
451 return size; 451 return size;
452} 452}
453 453
454/* 454/*
455 * handle a SEQ_CHN_VOICE event. 455 * handle a SEQ_CHN_VOICE event.
456 */ 456 */
457static size_t 457static size_t
458midi_event_chn_voice_to_output(seq_event_t e, u_char *buffer, size_t bufsize) 458midi_event_chn_voice_to_output(seq_event_t e, u_char *buffer, size_t bufsize)
459{ 459{
460 size_t size = 0; 460 size_t size = 0;
461 461
462 assert(e.common.channel < 16); 462 assert(e.common.channel < 16);
463 LOG("SEQ_CHN_VOICE"); 463 LOG("SEQ_CHN_VOICE");
464 464
465 if (filter_devchan(e.voice.device, e.voice.channel)) 465 if (filter_devchan(e.voice.device, e.voice.channel))
466 return 0; 466 return 0;
467 467
468 switch (e.voice.op) { 468 switch (e.voice.op) {
469 case MIDI_NOTEOFF: 469 case MIDI_NOTEOFF:
470 buffer[0] = MIDI_NOTEOFF | e.c_NOTEOFF.channel; 470 buffer[0] = MIDI_NOTEOFF | e.c_NOTEOFF.channel;
471 buffer[1] = e.c_NOTEOFF.key; 471 buffer[1] = e.c_NOTEOFF.key;
472 buffer[2] = e.c_NOTEOFF.velocity; 472 buffer[2] = e.c_NOTEOFF.velocity;
473 473
474 LOG("MIDI_NOTEOFF: channel %x key %x velocity %x", 474 LOG("MIDI_NOTEOFF: channel %x key %x velocity %x",
475 e.c_NOTEOFF.channel, e.c_NOTEOFF.key, e.c_NOTEOFF.velocity); 475 e.c_NOTEOFF.channel, e.c_NOTEOFF.key, e.c_NOTEOFF.velocity);
476 size = 3; 476 size = 3;
477 break; 477 break;
478 478
479 case MIDI_NOTEON: 479 case MIDI_NOTEON:
480 buffer[0] = MIDI_NOTEON | e.c_NOTEON.channel; 480 buffer[0] = MIDI_NOTEON | e.c_NOTEON.channel;
481 buffer[1] = e.c_NOTEON.key; 481 buffer[1] = e.c_NOTEON.key;
482 buffer[2] = e.c_NOTEON.velocity; 482 buffer[2] = e.c_NOTEON.velocity;
483 483
484 LOG("MIDI_NOTEON: channel %x key %x velocity %x", 484 LOG("MIDI_NOTEON: channel %x key %x velocity %x",
485 e.c_NOTEON.channel, e.c_NOTEON.key, e.c_NOTEON.velocity); 485 e.c_NOTEON.channel, e.c_NOTEON.key, e.c_NOTEON.velocity);
486 size = 3; 486 size = 3;
487 break; 487 break;
488 488
489 case MIDI_KEY_PRESSURE: 489 case MIDI_KEY_PRESSURE:
490 buffer[0] = MIDI_KEY_PRESSURE | e.c_KEY_PRESSURE.channel; 490 buffer[0] = MIDI_KEY_PRESSURE | e.c_KEY_PRESSURE.channel;
491 buffer[1] = e.c_KEY_PRESSURE.key; 491 buffer[1] = e.c_KEY_PRESSURE.key;
492 buffer[2] = e.c_KEY_PRESSURE.pressure; 492 buffer[2] = e.c_KEY_PRESSURE.pressure;
493 493
494 LOG("MIDI_KEY_PRESSURE: channel %x key %x pressure %x", 494 LOG("MIDI_KEY_PRESSURE: channel %x key %x pressure %x",
495 e.c_KEY_PRESSURE.channel, e.c_KEY_PRESSURE.key, 495 e.c_KEY_PRESSURE.channel, e.c_KEY_PRESSURE.key,
496 e.c_KEY_PRESSURE.pressure); 496 e.c_KEY_PRESSURE.pressure);
497 size = 3; 497 size = 3;
498 break; 498 break;
499 499
500 default: 500 default:
501 LOG("unknown voice op: %x", e.voice.op); 501 LOG("unknown voice op: %x", e.voice.op);
502 break; 502 break;
503 } 503 }
504 504
505 return size; 505 return size;
506} 506}
507 507
508/* 508/*
509 * handle a SEQ_SYSEX event. NetBSD /dev/music doesn't generate these. 509 * handle a SEQ_SYSEX event. NetBSD /dev/music doesn't generate these.
510 */ 510 */
511static size_t 511static size_t
512midi_event_sysex_to_output(seq_event_t e, u_char *buffer, size_t bufsize) 512midi_event_sysex_to_output(seq_event_t e, u_char *buffer, size_t bufsize)
513{ 513{
514 size_t size = 0; 514 size_t size = 0;
515 515
516 LOG("UNHANDLED SEQ_SYSEX"); 516 LOG("UNHANDLED SEQ_SYSEX");
517 517
518 return size; 518 return size;
519} 519}
520 520
521/* 521/*
522 * handle a SEQ_FULLSIZE event. NetBSD /dev/music doesn't generate these. 522 * handle a SEQ_FULLSIZE event. NetBSD /dev/music doesn't generate these.
523 */ 523 */
524static size_t 524static size_t
525midi_event_fullsize_to_output(seq_event_t e, u_char *buffer, size_t bufsize) 525midi_event_fullsize_to_output(seq_event_t e, u_char *buffer, size_t bufsize)
526{ 526{
527 size_t size = 0; 527 size_t size = 0;
528 528
529 LOG("UNHANDLED SEQ_FULLSIZE"); 529 LOG("UNHANDLED SEQ_FULLSIZE");
530 530
531 return size; 531 return size;
532} 532}
533 533
534/* 534/*
535 * main handler for MIDI events. 535 * main handler for MIDI events.
536 */ 536 */
537static size_t 537static size_t
538midi_event_to_output(seq_event_t e, u_char *buffer, size_t bufsize) 538midi_event_to_output(seq_event_t e, u_char *buffer, size_t bufsize)
539{ 539{
540 size_t size = 0; 540 size_t size = 0;
541 541
542 /* XXX so far we only process 4 byte returns */ 542 /* XXX so far we only process 4 byte returns */
543 assert(bufsize >= 4); 543 assert(bufsize >= 4);
544 544
545 LOG("event: %02x:%02x:%02x:%02x %02x:%02x:%02x:%02x", e.tag, 545 LOG("event: %02x:%02x:%02x:%02x %02x:%02x:%02x:%02x", e.tag,
546 e.unknown.byte[0], e.unknown.byte[1], 546 e.unknown.byte[0], e.unknown.byte[1],
547 e.unknown.byte[2], e.unknown.byte[3], 547 e.unknown.byte[2], e.unknown.byte[3],
548 e.unknown.byte[4], e.unknown.byte[5], 548 e.unknown.byte[4], e.unknown.byte[5],
549 e.unknown.byte[6]); 549 e.unknown.byte[6]);
550 550
551 switch (e.tag) { 551 switch (e.tag) {
552 case SEQ_LOCAL: 552 case SEQ_LOCAL:
553 size = midi_event_local_to_output(e, buffer, bufsize); 553 size = midi_event_local_to_output(e, buffer, bufsize);
554 break; 554 break;
555 555
556 case SEQ_TIMING: 556 case SEQ_TIMING:
557 size = midi_event_timer_to_output(e, buffer, bufsize); 557 size = midi_event_timer_to_output(e, buffer, bufsize);
558 break; 558 break;
559 559
560 case SEQ_CHN_COMMON: 560 case SEQ_CHN_COMMON:
561 size = midi_event_chn_common_to_output(e, buffer, bufsize); 561 size = midi_event_chn_common_to_output(e, buffer, bufsize);
562 break; 562 break;
563 563
564 case SEQ_CHN_VOICE: 564 case SEQ_CHN_VOICE:
565 size = midi_event_chn_voice_to_output(e, buffer, bufsize); 565 size = midi_event_chn_voice_to_output(e, buffer, bufsize);
566 break; 566 break;
567 567
568 case SEQ_SYSEX: 568 case SEQ_SYSEX:
569 size = midi_event_sysex_to_output(e, buffer, bufsize); 569 size = midi_event_sysex_to_output(e, buffer, bufsize);
570 break; 570 break;
571 571
572 case SEQ_FULLSIZE: 572 case SEQ_FULLSIZE:
573 size = midi_event_fullsize_to_output(e, buffer, bufsize); 573 size = midi_event_fullsize_to_output(e, buffer, bufsize);
574 break; 574 break;
575 575
576 default: 576 default:
577 errx(1, "don't understand midi tag %x", e.tag); 577 errx(1, "don't understand midi tag %x", e.tag);
578 } 578 }
579 579
580 return size; 580 return size;
581} 581}
582 582
583static bool 583static bool
584filter_array(unsigned val, unsigned *array, size_t arraylen) 584filter_array(unsigned val, unsigned *array, size_t arraylen)
585{ 585{
586 586
587 if (array == NULL) 587 if (array == NULL)
588 return false; 588 return false;
589 589
590 for (; arraylen; arraylen--) 590 for (; arraylen; arraylen--)
591 if (array[arraylen - 1] == val) 591 if (array[arraylen - 1] == val)
592 return false; 592 return false;
593 593
594 return true; 594 return true;
595} 595}
596 596
597static bool 597static bool
598filter_dev(unsigned device) 598filter_dev(unsigned device)
599{ 599{
600 600
601 if (filter_array(device, filt_devnos, num_filt_devnos)) 601 if (filter_array(device, filt_devnos, num_filt_devnos))
602 return true; 602 return true;
603 603
604 return false; 604 return false;
605} 605}
606 606
607static bool 607static bool
608filter_chan(unsigned channel) 608filter_chan(unsigned channel)
609{ 609{
610 610
611 if (filter_array(channel, filt_chans, num_filt_chans)) 611 if (filter_array(channel, filt_chans, num_filt_chans))
612 return true; 612 return true;
613 613
614 return false; 614 return false;
615} 615}
616 616
617static bool 617static bool
618filter_devchan(unsigned device, unsigned channel) 618filter_devchan(unsigned device, unsigned channel)
619{ 619{
620 620
621 if (filter_dev(device) || filter_chan(channel)) 621 if (filter_dev(device) || filter_chan(channel))
622 return true; 622 return true;
623 623
624 return false; 624 return false;
625} 625}
626 626
627static int 627static int
628timeleft(struct timeval *start_tvp, struct timeval *record_tvp) 628timeleft(struct timeval *start_tvp, struct timeval *record_tvp)
629{ 629{
630 struct timeval now, diff; 630 struct timeval now, diff;
631 631
632 (void)gettimeofday(&now, NULL); 632 (void)gettimeofday(&now, NULL);
633 timersub(&now, start_tvp, &diff); 633 timersub(&now, start_tvp, &diff);
634 timersub(record_tvp, &diff, &now); 634 timersub(record_tvp, &diff, &now);
635 635
636 return (now.tv_sec > 0 || (now.tv_sec == 0 && now.tv_usec > 0)); 636 return (now.tv_sec > 0 || (now.tv_sec == 0 && now.tv_usec > 0));
637} 637}
638 638
639static void 639static void
640parse_ints(const char *str, unsigned **arrayp, unsigned *sizep, const char *msg) 640parse_ints(const char *str, unsigned **arrayp, unsigned *sizep, const char *msg)
641{ 641{
642 unsigned count = 1, u, longest = 0, c = 0; 642 unsigned count = 1, u, longest = 0, c = 0;
643 unsigned *ip; 643 unsigned *ip;
644 const char *s, *os; 644 const char *s, *os;
645 char *num_buf; 645 char *num_buf;
646 646
647 /* 647 /*
648 * count all the comma separated values, and figre out 648 * count all the comma separated values, and figre out
649 * the longest one. 649 * the longest one.
650 */ 650 */
651 for (s = str; *s; s++) { 651 for (s = str; *s; s++) {
652 c++; 652 c++;
653 if (*s == ',') { 653 if (*s == ',') {
654 count++; 654 count++;
655 if (c > longest) 655 if (c > longest)
656 longest = c; 656 longest = c;
657 c = 0; 657 c = 0;
658 } 658 }
659 } 659 }
660 *sizep = count; 660 *sizep = count;
661 661
662 num_buf = malloc(longest + 1); 662 num_buf = malloc(longest + 1);
663 ip = malloc(sizeof(*ip) * count); 663 ip = malloc(sizeof(*ip) * count);
664 if (!ip || !num_buf) 664 if (!ip || !num_buf)
665 errx(1, "malloc failed"); 665 errx(1, "malloc failed");
666 666
667 for (count = 0, s = os = str, u = 0; *s; s++) { 667 for (count = 0, s = os = str, u = 0; *s; s++) {
668 if (*s == ',') { 668 if (*s == ',') {
669 num_buf[u] = '\0'; 669 num_buf[u] = '\0';
670 decode_uint(num_buf, &ip[count++]); 670 decode_uint(num_buf, &ip[count++]);
671 os = s + 1; 671 os = s + 1;
672 u = 0; 672 u = 0;
673 } else 673 } else
674 num_buf[u++] = *s; 674 num_buf[u++] = *s;
675 } 675 }
676 num_buf[u] = '\0'; 676 num_buf[u] = '\0';
677 decode_uint(num_buf, &ip[count++]); 677 decode_uint(num_buf, &ip[count++]);
678 *arrayp = ip; 678 *arrayp = ip;
679 679
680 if (verbose) { 680 if (verbose) {
681 fprintf(stderr, "Filtering %s in:", msg); 681 fprintf(stderr, "Filtering %s in:", msg);
682 for (size_t i = 0; i < *sizep; i++) 682 for (size_t i = 0; i < *sizep; i++)
683 fprintf(stderr, " %u", ip[i]); 683 fprintf(stderr, " %u", ip[i]);
684 fprintf(stderr, "\n"); 684 fprintf(stderr, "\n");
685 } 685 }
686 686
687 free(num_buf); 687 free(num_buf);
688} 688}
689 689
690static void 690static void
691cleanup(int signo) 691cleanup(int signo)
692{ 692{
693 693
694 write_midi_trailer(); 694 write_midi_trailer();
695 rewrite_header(); 695 rewrite_header();
696 696
697 if (ioctl(midifd, SEQUENCER_TMR_STOP, NULL) < 0) { 697 if (ioctl(midifd, SEQUENCER_TMR_STOP, NULL) < 0) {
698 if (ignore_timer_fail) 698 if (ignore_timer_fail)
699 warn("failed to stop midi timer"); 699 warn("failed to stop midi timer");
700 else 700 else
701 err(1, "failed to stop midi timer"); 701 err(1, "failed to stop midi timer");
702 } 702 }
703 703
704 close(outfd); 704 close(outfd);
705 close(midifd); 705 close(midifd);
706 if (signo != 0) 706 if (signo != 0)
707 (void)raise_default_signal(signo); 707 (void)raise_default_signal(signo);
708 708
709 exit(0); 709 exit(0);
710} 710}
711 711
712static void 712static void
713rewrite_header(void) 713rewrite_header(void)
714{ 714{
715 715
716 /* can't do this here! */ 716 /* can't do this here! */
717 if (stdout_mode) 717 if (stdout_mode)
718 return; 718 return;
719 719
720 if (lseek(outfd, (off_t)0, SEEK_SET) == (off_t)-1) 720 if (lseek(outfd, (off_t)0, SEEK_SET) == (off_t)-1)
721 err(1, "could not seek to start of file for header rewrite"); 721 err(1, "could not seek to start of file for header rewrite");
722 write_midi_header(); 722 write_midi_header();
723} 723}
724 724
725#define BYTE1(x) ((x) & 0xff) 725#define BYTE1(x) ((x) & 0xff)
726#define BYTE2(x) (((x) >> 8) & 0xff) 726#define BYTE2(x) (((x) >> 8) & 0xff)
727#define BYTE3(x) (((x) >> 16) & 0xff) 727#define BYTE3(x) (((x) >> 16) & 0xff)
728#define BYTE4(x) (((x) >> 24) & 0xff) 728#define BYTE4(x) (((x) >> 24) & 0xff)
729 729
730static void 730static void
731write_midi_header(void) 731write_midi_header(void)
732{ 732{
733 unsigned char header[] = { 733 unsigned char header[] = {
734 'M', 'T', 'h', 'd', 734 'M', 'T', 'h', 'd',
735 0, 0, 0, 6, 735 0, 0, 0, 6,
736 0, 1, 736 0, 1,
737 0, 0, /* ntracks */ 737 0, 0, /* ntracks */
738 0, 0, /* notes per beat */ 738 0, 0, /* notes per beat */
739 }; 739 };
740 /* XXX only support one track so far */ 740 /* XXX only support one track so far */
741 unsigned ntracks = 1; 741 unsigned ntracks = 1;
742 unsigned char track[] = { 742 unsigned char track[] = {
743 'M', 'T', 'r', 'k', 743 'M', 'T', 'r', 'k',
744 0, 0, 0, 0, 744 0, 0, 0, 0,
745 }; 745 };
746 unsigned char bpm[] = { 746 unsigned char bpm[] = {
747 0, 0xff, 0x51, 0x3, 747 0, 0xff, 0x51, 0x3,
748 0, 0, 0, /* inverse tempo */ 748 0, 0, 0, /* inverse tempo */
749 }; 749 };
750 unsigned total_size = data_size + sizeof header + sizeof track + sizeof bpm; 750 unsigned total_size = data_size + sizeof header + sizeof track + sizeof bpm;
751 751
752 header[10] = BYTE2(ntracks); 752 header[10] = BYTE2(ntracks);
753 header[11] = BYTE1(ntracks); 753 header[11] = BYTE1(ntracks);
754 header[12] = BYTE2(notes_per_beat); 754 header[12] = BYTE2(notes_per_beat);
755 header[13] = BYTE1(notes_per_beat); 755 header[13] = BYTE1(notes_per_beat);
756 756
757 track[4] = BYTE4(total_size); 757 track[4] = BYTE4(total_size);
758 track[5] = BYTE3(total_size); 758 track[5] = BYTE3(total_size);
759 track[6] = BYTE2(total_size); 759 track[6] = BYTE2(total_size);
760 track[7] = BYTE1(total_size); 760 track[7] = BYTE1(total_size);
761 761
762#define TEMPO_INV(x) (60000000UL / (x)) 762#define TEMPO_INV(x) (60000000UL / (x))
763 bpm[4] = BYTE3(TEMPO_INV(tempo)); 763 bpm[4] = BYTE3(TEMPO_INV(tempo));
764 bpm[5] = BYTE2(TEMPO_INV(tempo)); 764 bpm[5] = BYTE2(TEMPO_INV(tempo));
765 bpm[6] = BYTE1(TEMPO_INV(tempo)); 765 bpm[6] = BYTE1(TEMPO_INV(tempo));
766 766
767 if (write(outfd, header, sizeof header) != sizeof header) 767 if (write(outfd, header, sizeof header) != sizeof header)
768 err(1, "write of header failed"); 768 err(1, "write of header failed");
769 if (write(outfd, track, sizeof track) != sizeof track) 769 if (write(outfd, track, sizeof track) != sizeof track)
770 err(1, "write of track header failed"); 770 err(1, "write of track header failed");
771 if (write(outfd, bpm, sizeof bpm) != sizeof bpm) 771 if (write(outfd, bpm, sizeof bpm) != sizeof bpm)
772 err(1, "write of bpm header failed"); 772 err(1, "write of bpm header failed");
773 773
774 LOG("wrote header: ntracks=%u notes_per_beat=%u tempo=%d total_size=%u", 774 LOG("wrote header: ntracks=%u notes_per_beat=%u tempo=%d total_size=%u",
775 ntracks, notes_per_beat, tempo, total_size); 775 ntracks, notes_per_beat, tempo, total_size);
776} 776}
777 777
778static void 778static void
779write_midi_trailer(void) 779write_midi_trailer(void)
780{ 780{
781 unsigned char trailer[] = { 781 unsigned char trailer[] = {
782 0, 0xff, 0x2f, 0, 782 0, 0xff, 0x2f, 0,
783 }; 783 };
784 784
785 if (write(outfd, trailer, sizeof trailer) != sizeof trailer) 785 if (write(outfd, trailer, sizeof trailer) != sizeof trailer)
786 err(1, "write of trailer failed"); 786 err(1, "write of trailer failed");
787} 787}
788 788
789static void 789static void
790usage(void) 790usage(void)
791{ 791{
792 792
793 fprintf(stderr, "Usage: %s [-aDfhqV] [options] {outfile|-}\n", 793 fprintf(stderr, "Usage: %s [-aDfhqV] [options] {outfile|-}\n",
794 getprogname()); 794 getprogname());
795 fprintf(stderr, "Options:\n" 795 fprintf(stderr, "Options:\n"
796 "\t-B buffer size\n" 796 "\t-B buffer size\n"
797 "\t-c channels\n" 797 "\t-c channels\n"
798 "\t-d devices\n" 798 "\t-d devices\n"
799 "\t-f sequencerdev\n" 799 "\t-f sequencerdev\n"
800 "\t-n notesperbeat\n" 800 "\t-n notesperbeat\n"
801 "\t-r raw_output\n" 801 "\t-r raw_output\n"
802 "\t-T tempo\n" 802 "\t-T tempo\n"
803 "\t-t recording time\n"); 803 "\t-t recording time\n");
804 exit(EXIT_FAILURE); 804 exit(EXIT_FAILURE);
805} 805}