.SH SYNOPSIS
.B arecordmidi2
-\-p client:port[,...] [options] midi2file
+[options] midi2file
.SH DESCRIPTION
.B arecordmidi2
name. A port is specified by its number; for port 0 of a client, the
":0" part of the port specification can be omitted.
+\fBarecordmidi2\fP creates a UMP Endpoint containing the same number
+of Function Blocks as specified by this option, each of which is
+connected to the specified port as a source.
+
+When no source ports are specified with \fI\-p\fP option,
+\fBarecordmidi2\fP creates a UMP Endpoint with full 16 Function Blocks
+and records from those inputs. User can connect the sequencer ports
+freely via \fBaconnect\fP, for example. This mode can be used
+together with the interactive mode via \fI\-r\fP option.
+
.TP
.I \-b,\-\-bpm=beats
Sets the musical tempo of the MIDI file, in beats per minute.
MIDI 1.0 and MIDI 2.0 protocol, respectively.
Default is 1.
+.TP
+.I \-r,\-\-interactive
+Run in the interactive mode. \fBarecordmidi2\fP waits for a RETURN
+key input from the terminal to start the recording. After starting,
+the recording ends when another RETURN key is input from the
+terminal. The received events before the start of recording are
+discarded.
+
.SH SEE ALSO
arecordmidi(1)
.br
snd_ump_endpoint_info_t *ep;
snd_ump_block_info_t *blk;
snd_seq_port_info_t *pinfo;
+ int num_groups;
int i, err;
+ /* in passive mode, create full 16 groups */
+ if (port_count)
+ num_groups = port_count;
+ else
+ num_groups = 16;
+
/* create a UMP Endpoint */
snd_ump_endpoint_info_alloca(&ep);
snd_ump_endpoint_info_set_name(ep, "arecordmidi2");
snd_ump_endpoint_info_set_protocol_caps(ep, SND_UMP_EP_INFO_PROTO_MIDI2);
snd_ump_endpoint_info_set_protocol(ep, SND_UMP_EP_INFO_PROTO_MIDI2);
}
- snd_ump_endpoint_info_set_num_blocks(ep, port_count);
+ snd_ump_endpoint_info_set_num_blocks(ep, num_groups);
- err = snd_seq_create_ump_endpoint(seq, ep, port_count);
+ err = snd_seq_create_ump_endpoint(seq, ep, num_groups);
check_snd("create UMP endpoint", err);
/* create UMP Function Blocks */
snd_ump_block_info_alloca(&blk);
- for (i = 0; i < port_count; i++) {
+ for (i = 0; i < num_groups; i++) {
char blkname[32];
sprintf(blkname, "Group %d", i + 1);
/* toggle timestamping for all input ports */
snd_seq_port_info_alloca(&pinfo);
- for (i = 0; i <= port_count; i++) {
+ for (i = 0; i <= num_groups; i++) {
err = snd_seq_get_port_info(seq, i, pinfo);
check_snd("get port info", err);
snd_seq_port_info_set_timestamping(pinfo, 1);
/* first DCS */
write_dcs(file, 0);
write_dctpq(file);
+}
- /* start bar */
+/* write start bar */
+static void start_bar(FILE *file)
+{
write_start_clip(file);
write_tempo(file);
write_time_sig(file);
" -t,--ticks=ticks resolution in ticks per beat or frame\n"
" -i,--timesig=nn:dd time signature\n"
" -n,--num-events=events fixed number of events to record, then exit\n"
- " -u,--ump=version UMP MIDI version (1 or 2)\n",
+ " -u,--ump=version UMP MIDI version (1 or 2)\n"
+ " -r,--interactive Interactive mode\n",
argv0);
}
int main(int argc, char *argv[])
{
- static const char short_options[] = "hVp:b:t:n:u:";
+ static const char short_options[] = "hVp:b:t:n:u:r";
static const struct option long_options[] = {
{"help", 0, NULL, 'h'},
{"version", 0, NULL, 'V'},
{"timesig", 1, NULL, 'i'},
{"num-events", 1, NULL, 'n'},
{"ump", 1, NULL, 'u'},
+ {"interactive", 0, NULL, 'r'},
{0}
};
/* If |num_events| isn't specified, leave it at 0. */
long num_events = 0;
long events_received = 0;
+ int start = 0;
+ int interactive = 0;
init_seq();
if (midi_version != 1 && midi_version != 2)
fatal("Invalid MIDI version %d\n", midi_version);
break;
+ case 'r':
+ interactive = 1;
+ break;
default:
help(argv[0]);
return 1;
}
}
- if (port_count < 1) {
- fputs("Pleast specify a source port with --port.\n", stderr);
- return 1;
- }
-
if (optind >= argc) {
fputs("Please specify a file to record to.\n", stderr);
return 1;
create_queue();
create_ump_client();
- connect_ports();
+ if (port_count)
+ connect_ports();
filename = argv[optind];
fatal("Cannot open %s - %s", filename, strerror(errno));
write_file_header(file);
+ if (interactive) {
+ printf("Press RETURN to start recording:");
+ fflush(stdout);
+ } else {
+ start_bar(file);
+ start = 1;
+ }
err = snd_seq_start_queue(seq, queue, NULL);
check_snd("start queue", err);
signal(SIGTERM, sighandler);
npfds = snd_seq_poll_descriptors_count(seq, POLLIN);
- pfds = alloca(sizeof(*pfds) * npfds);
+ pfds = alloca(sizeof(*pfds) * (npfds + 1));
for (;;) {
snd_seq_poll_descriptors(seq, pfds, npfds, POLLIN);
- if (poll(pfds, npfds, -1) < 0)
- break;
+ if (interactive) {
+ pfds[npfds].fd = STDIN_FILENO;
+ pfds[npfds].events = POLLIN | POLLERR | POLLNVAL;
+ if (poll(pfds, npfds + 1, -1) < 0)
+ break;
+ if (pfds[npfds].revents & POLLIN) {
+ while (!feof(stdin) && getchar() != '\n')
+ ;
+ if (!start) {
+ start_bar(file);
+ start = 1;
+ printf("Press RETURN to stop recording:");
+ fflush(stdout);
+ continue;
+ } else {
+ stop = 1;
+ }
+ }
+ } else {
+ if (poll(pfds, npfds, -1) < 0)
+ break;
+ }
+
do {
snd_seq_ump_event_t *event;
err = snd_seq_ump_event_input(seq, &event);
if (err < 0)
break;
- if (event) {
+ if (start && event) {
record_event(file, event);
events_received++;
}