Blame test/seq-sender.c

Packit Service db8eaa
Packit Service db8eaa
#ifdef USE_PCM // XXX not yet
Packit Service db8eaa
/*
Packit Service db8eaa
 *  PCM timer layer
Packit Service db8eaa
 */
Packit Service db8eaa
Packit Service db8eaa
int pcard = 0;
Packit Service db8eaa
int pdevice = 0;
Packit Service db8eaa
int period_size = 1024;
Packit Service db8eaa
Packit Service db8eaa
void set_hwparams(snd_pcm_t *phandle)
Packit Service db8eaa
{
Packit Service db8eaa
	int err;
Packit Service db8eaa
	snd_pcm_hw_params_t *params;
Packit Service db8eaa
Packit Service db8eaa
	err = snd_output_stdio_attach(&log, stderr, 0);
Packit Service db8eaa
	if (err < 0) {
Packit Service db8eaa
		fprintf(stderr, "cannot attach output stdio\n");
Packit Service db8eaa
		exit(0);
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	snd_pcm_hw_params_alloca(&params);
Packit Service db8eaa
	err = snd_pcm_hw_params_any(phandle, params);
Packit Service db8eaa
	if (err < 0) {
Packit Service db8eaa
		fprintf(stderr, "Broken configuration for this PCM: no configurations available\n");
Packit Service db8eaa
		exit(0);
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	err = snd_pcm_hw_params_set_access(phandle, params,
Packit Service db8eaa
					   SND_PCM_ACCESS_RW_INTERLEAVED);
Packit Service db8eaa
	if (err < 0) {
Packit Service db8eaa
		fprintf(stderr, "Access type not available\n");
Packit Service db8eaa
		exit(0);
Packit Service db8eaa
	}
Packit Service db8eaa
	err = snd_pcm_hw_params_set_format(phandle, params, SND_PCM_FORMAT_S16_LE);
Packit Service db8eaa
	if (err < 0) {
Packit Service db8eaa
		fprintf(stderr, "cannot set format\n");
Packit Service db8eaa
		exit(0);
Packit Service db8eaa
	}
Packit Service db8eaa
	err = snd_pcm_hw_params_set_channels(phandle, params, 2);
Packit Service db8eaa
	if (err < 0) {
Packit Service db8eaa
		fprintf(stderr, "cannot set channels 2\n");
Packit Service db8eaa
		exit(0);
Packit Service db8eaa
	}
Packit Service db8eaa
	err = snd_pcm_hw_params_set_rate_near(phandle, params, 44100, 0);
Packit Service db8eaa
	if (err < 0) {
Packit Service db8eaa
		fprintf(stderr, "cannot set rate\n");
Packit Service db8eaa
		exit(0);
Packit Service db8eaa
	}
Packit Service db8eaa
	err = snd_pcm_hw_params_set_period_size_near(phandle, params, period_size);
Packit Service db8eaa
	if (err < 0) {
Packit Service db8eaa
		fprintf(stderr, "cannot set period size\n");
Packit Service db8eaa
		exit(0);
Packit Service db8eaa
	}
Packit Service db8eaa
	err = snd_pcm_hw_params(phandle, params);
Packit Service db8eaa
	if (err < 0) {
Packit Service db8eaa
		fprintf(stderr, "Unable to install hw params:\n");
Packit Service db8eaa
		exit(0);
Packit Service db8eaa
	}
Packit Service db8eaa
	snd_pcm_hw_params_dump(params, log);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
#endif
Packit Service db8eaa
/*
Packit Service db8eaa
 *  Simple event sender
Packit Service db8eaa
 */
Packit Service db8eaa
Packit Service db8eaa
void event_sender_start_timer(snd_seq_t *handle,
Packit Service db8eaa
			      int client ATTRIBUTE_UNUSED,
Packit Service db8eaa
			      int queue,
Packit Service db8eaa
			      snd_pcm_t *phandle ATTRIBUTE_UNUSED)
Packit Service db8eaa
{
Packit Service db8eaa
	int err;
Packit Service db8eaa
	
Packit Service db8eaa
#ifdef USE_PCM
Packit Service db8eaa
	if (phandle) {
Packit Service db8eaa
		snd_pcm_playback_info_t pinfo;
Packit Service db8eaa
		snd_seq_queue_timer_t qtimer;
Packit Service db8eaa
Packit Service db8eaa
		if ((err = snd_pcm_playback_info(phandle, &pinfo)) < 0) {
Packit Service db8eaa
			fprintf(stderr, "Playback info error: %s\n", snd_strerror(err));
Packit Service db8eaa
			exit(0);
Packit Service db8eaa
		}
Packit Service db8eaa
		bzero(&qtimer, sizeof(qtimer));
Packit Service db8eaa
		qtimer.type = SND_SEQ_TIMER_MASTER;
Packit Service db8eaa
		/* note: last bit from the subdevices specifies playback */
Packit Service db8eaa
		/* or capture direction for the timer specification */
Packit Service db8eaa
		qtimer.number = SND_TIMER_PCM(pcard, pdevice, pinfo.subdevice << 1);
Packit Service db8eaa
		if ((err = snd_seq_set_queue_timer(handle, queue, &qtimer)) < 0) {
Packit Service db8eaa
			fprintf(stderr, "Sequencer PCM timer setup failed: %s\n", snd_strerror(err));
Packit Service db8eaa
			exit(0);
Packit Service db8eaa
		}
Packit Service db8eaa
	}	
Packit Service db8eaa
#endif
Packit Service db8eaa
	if ((err = snd_seq_start_queue(handle, queue, NULL))<0)
Packit Service db8eaa
		fprintf(stderr, "Timer event output error: %s\n", snd_strerror(err));
Packit Service db8eaa
	snd_seq_drain_output(handle);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
void event_sender_filter(snd_seq_t *handle)
Packit Service db8eaa
{
Packit Service db8eaa
	int err;
Packit Service db8eaa
Packit Service db8eaa
	if ((err = snd_seq_set_client_event_filter(handle, SND_SEQ_EVENT_ECHO)) < 0) {
Packit Service db8eaa
		fprintf(stderr, "Unable to set client info: %s\n", snd_strerror(err));
Packit Service db8eaa
		return;
Packit Service db8eaa
	}
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
void send_event(snd_seq_t *handle, int queue, int client, int port,
Packit Service db8eaa
                snd_seq_addr_t *dest, int *time)
Packit Service db8eaa
{
Packit Service db8eaa
	int err;
Packit Service db8eaa
	snd_seq_event_t ev;
Packit Service db8eaa
	
Packit Service db8eaa
	bzero(&ev, sizeof(ev));
Packit Service db8eaa
	ev.queue = queue;
Packit Service db8eaa
	ev.source.client = ev.dest.client = client;
Packit Service db8eaa
	ev.source.port = ev.dest.port = port;
Packit Service db8eaa
	ev.flags = SND_SEQ_TIME_STAMP_REAL | SND_SEQ_TIME_MODE_ABS;
Packit Service db8eaa
	ev.time.time.tv_sec = *time; (*time)++;
Packit Service db8eaa
	ev.type = SND_SEQ_EVENT_ECHO;
Packit Service db8eaa
	if ((err = snd_seq_event_output(handle, &ev))<0)
Packit Service db8eaa
		fprintf(stderr, "Event output error: %s\n", snd_strerror(err));
Packit Service db8eaa
	ev.dest = *dest;
Packit Service db8eaa
	ev.type = SND_SEQ_EVENT_PGMCHANGE;
Packit Service db8eaa
	ev.data.control.channel = 0;
Packit Service db8eaa
	ev.data.control.value = 16;
Packit Service db8eaa
	if ((err = snd_seq_event_output(handle, &ev))<0)
Packit Service db8eaa
		fprintf(stderr, "Event output error: %s\n", snd_strerror(err));
Packit Service db8eaa
	ev.type = SND_SEQ_EVENT_NOTE;
Packit Service db8eaa
	ev.data.note.channel = 0;
Packit Service db8eaa
	ev.data.note.note = 64 + (queue*2);
Packit Service db8eaa
	ev.data.note.velocity = 127;
Packit Service db8eaa
	ev.data.note.off_velocity = 127;
Packit Service db8eaa
	ev.data.note.duration = 500;	/* 0.5sec */
Packit Service db8eaa
	if ((err = snd_seq_event_output(handle, &ev))<0)
Packit Service db8eaa
		fprintf(stderr, "Event output error: %s\n", snd_strerror(err));
Packit Service db8eaa
	if ((err = snd_seq_drain_output(handle))<0)
Packit Service db8eaa
		fprintf(stderr, "Event drain error: %s\n", snd_strerror(err));
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
void event_sender(snd_seq_t *handle, int argc, char *argv[])
Packit Service db8eaa
{
Packit Service db8eaa
	snd_seq_event_t *ev;
Packit Service db8eaa
	snd_seq_port_info_t *pinfo;
Packit Service db8eaa
	snd_seq_port_subscribe_t *sub;
Packit Service db8eaa
	snd_seq_addr_t addr;
Packit Service db8eaa
	struct pollfd *pfds;
Packit Service db8eaa
	int client, port, queue, max, err, v1, v2, time = 0, pcm_flag = 0;
Packit Service db8eaa
	char *ptr;
Packit Service db8eaa
	snd_pcm_t *phandle = NULL;
Packit Service db8eaa
Packit Service db8eaa
	if (argc < 1) {
Packit Service db8eaa
		fprintf(stderr, "Invalid destination...\n");
Packit Service db8eaa
		return;
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	if ((client = snd_seq_client_id(handle))<0) {
Packit Service db8eaa
		fprintf(stderr, "Cannot determine client number: %s\n", snd_strerror(client));
Packit Service db8eaa
		return;
Packit Service db8eaa
	}
Packit Service db8eaa
	printf("Client ID = %i\n", client);
Packit Service db8eaa
	if ((queue = snd_seq_alloc_queue(handle))<0) {
Packit Service db8eaa
		fprintf(stderr, "Cannot allocate queue: %s\n", snd_strerror(queue));
Packit Service db8eaa
		return;
Packit Service db8eaa
	}
Packit Service db8eaa
	printf("Queue ID = %i\n", queue);
Packit Service db8eaa
	event_sender_filter(handle);
Packit Service db8eaa
	if ((err = snd_seq_nonblock(handle, 1))<0)
Packit Service db8eaa
		fprintf(stderr, "Cannot set nonblock mode: %s\n", snd_strerror(err));
Packit Service db8eaa
Packit Service db8eaa
	snd_seq_port_info_alloca(&pinfo);
Packit Service db8eaa
	snd_seq_port_info_set_capability(pinfo, SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_READ);
Packit Service db8eaa
	snd_seq_port_info_set_name(pinfo, "Output");
Packit Service db8eaa
	if ((err = snd_seq_create_port(handle, pinfo)) < 0) {
Packit Service db8eaa
		fprintf(stderr, "Cannot create output port: %s\n", snd_strerror(err));
Packit Service db8eaa
		return;
Packit Service db8eaa
	}
Packit Service db8eaa
	port = snd_seq_port_info_get_port(pinfo);
Packit Service db8eaa
Packit Service db8eaa
	snd_seq_port_subscribe_alloca(&sub);
Packit Service db8eaa
	addr.client = client;
Packit Service db8eaa
	addr.port = port;
Packit Service db8eaa
	snd_seq_port_subscribe_set_sender(sub, &addr);
Packit Service db8eaa
Packit Service db8eaa
	for (max = 0; max < argc; max++) {
Packit Service db8eaa
		ptr = argv[max];
Packit Service db8eaa
		if (!ptr)
Packit Service db8eaa
			continue;
Packit Service db8eaa
		if (!strcmp(ptr, "pcm")) {
Packit Service db8eaa
			pcm_flag = 1;
Packit Service db8eaa
			continue;
Packit Service db8eaa
		}
Packit Service db8eaa
		if (sscanf(ptr, "%i.%i", &v1, &v2) != 2) {
Packit Service db8eaa
			fprintf(stderr, "Wrong argument '%s'...\n", argv[max]);
Packit Service db8eaa
			return;
Packit Service db8eaa
		}
Packit Service db8eaa
		addr.client = v1;
Packit Service db8eaa
		addr.port = v2;
Packit Service db8eaa
		snd_seq_port_subscribe_set_dest(sub, &addr);
Packit Service db8eaa
		if ((err = snd_seq_subscribe_port(handle, sub))<0) {
Packit Service db8eaa
			fprintf(stderr, "Cannot subscribe port %i from client %i: %s\n", v2, v1, snd_strerror(err));
Packit Service db8eaa
			return;
Packit Service db8eaa
		}
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	printf("Destination client = %i, port = %i\n", addr.client, addr.port);
Packit Service db8eaa
Packit Service db8eaa
#ifdef USE_PCM
Packit Service db8eaa
	if (pcm_flag) {
Packit Service db8eaa
		if ((err = snd_pcm_open(&phandle, "default", SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
Packit Service db8eaa
			fprintf(stderr, "Playback open error: %s\n", snd_strerror(err));
Packit Service db8eaa
			exit(0);
Packit Service db8eaa
		}
Packit Service db8eaa
		set_hwparams(phandle);
Packit Service db8eaa
		pbuf = calloc(1, period_size * 4);
Packit Service db8eaa
		if (pbuf == NULL) {
Packit Service db8eaa
			fprintf(stderr, "No enough memory...\n");
Packit Service db8eaa
			exit(0);
Packit Service db8eaa
		}
Packit Service db8eaa
	}
Packit Service db8eaa
#endif
Packit Service db8eaa
	event_sender_start_timer(handle, client, queue, phandle);
Packit Service db8eaa
	
Packit Service db8eaa
	/* send the first event */
Packit Service db8eaa
	send_event(handle, queue, client, port, &addr, &time);
Packit Service db8eaa
#ifdef USE_PCM
Packit Service db8eaa
	if (phandle)
Packit Service db8eaa
		max += snd_pcm_poll_descriptors_count(phandle);
Packit Service db8eaa
#endif
Packit Service db8eaa
	pfds = alloca(sizeof(*pfds) * max);
Packit Service db8eaa
	while (1) {
Packit Service db8eaa
		int nseqs = snd_seq_poll_descriptors_count(handle, POLLOUT|POLLIN);
Packit Service db8eaa
		if (snd_seq_event_output_pending(handle))
Packit Service db8eaa
			snd_seq_poll_descriptors(handle, pfds, nseqs, POLLOUT|POLLIN);
Packit Service db8eaa
		else
Packit Service db8eaa
			snd_seq_poll_descriptors(handle, pfds, nseqs, POLLIN);
Packit Service db8eaa
		max = nseqs;
Packit Service db8eaa
#ifdef USE_PCM
Packit Service db8eaa
		if (phandle) {
Packit Service db8eaa
			int pmax = snd_pcm_poll_descriptors_count(phandle);
Packit Service db8eaa
			snd_seq_poll_descriptors(phandle, pfds + max, pmax);
Packit Service db8eaa
			max += pmax;
Packit Service db8eaa
		}
Packit Service db8eaa
#endif
Packit Service db8eaa
		if (poll(pfds, max, -1) < 0)
Packit Service db8eaa
			break;
Packit Service db8eaa
#ifdef USE_PCM
Packit Service db8eaa
		if (phandle && (pfds[nseqs].revents & POLLOUT)) {
Packit Service db8eaa
			if (snd_pcm_writei(phandle, pbuf, period_size) != period_size) {
Packit Service db8eaa
				fprintf(stderr, "Playback write error!!\n");
Packit Service db8eaa
				exit(0);
Packit Service db8eaa
			}
Packit Service db8eaa
		}
Packit Service db8eaa
#endif
Packit Service db8eaa
		if (pfds[0].revents & POLLOUT)
Packit Service db8eaa
			snd_seq_drain_output(handle);
Packit Service db8eaa
		if (pfds[0].revents & POLLIN) {
Packit Service db8eaa
			do {
Packit Service db8eaa
				if ((err = snd_seq_event_input(handle, &ev))<0)
Packit Service db8eaa
					break;
Packit Service db8eaa
				if (!ev)
Packit Service db8eaa
					continue;
Packit Service db8eaa
				if (ev->type == SND_SEQ_EVENT_ECHO)
Packit Service db8eaa
					send_event(handle, queue, client, port, &addr, &time);
Packit Service db8eaa
				decode_event(ev);
Packit Service db8eaa
				snd_seq_free_event(ev);
Packit Service db8eaa
			} while (err > 0);
Packit Service db8eaa
		}
Packit Service db8eaa
	}
Packit Service db8eaa
}