Home | History | Annotate | Download | only in test
      1 
      2 #ifdef USE_PCM // XXX not yet
      3 /*
      4  *  PCM timer layer
      5  */
      6 
      7 int pcard = 0;
      8 int pdevice = 0;
      9 int period_size = 1024;
     10 
     11 void set_hwparams(snd_pcm_t *phandle)
     12 {
     13 	int err;
     14 	snd_pcm_hw_params_t *params;
     15 
     16 	err = snd_output_stdio_attach(&log, stderr, 0);
     17 	if (err < 0) {
     18 		fprintf(stderr, "cannot attach output stdio\n");
     19 		exit(0);
     20 	}
     21 
     22 	snd_pcm_hw_params_alloca(&params);
     23 	err = snd_pcm_hw_params_any(phandle, params);
     24 	if (err < 0) {
     25 		fprintf(stderr, "Broken configuration for this PCM: no configurations available\n");
     26 		exit(0);
     27 	}
     28 
     29 	err = snd_pcm_hw_params_set_access(phandle, params,
     30 					   SND_PCM_ACCESS_RW_INTERLEAVED);
     31 	if (err < 0) {
     32 		fprintf(stderr, "Access type not available\n");
     33 		exit(0);
     34 	}
     35 	err = snd_pcm_hw_params_set_format(phandle, params, SND_PCM_FORMAT_S16_LE);
     36 	if (err < 0) {
     37 		fprintf(stderr, "cannot set format\n");
     38 		exit(0);
     39 	}
     40 	err = snd_pcm_hw_params_set_channels(phandle, params, 2);
     41 	if (err < 0) {
     42 		fprintf(stderr, "cannot set channels 2\n");
     43 		exit(0);
     44 	}
     45 	err = snd_pcm_hw_params_set_rate_near(phandle, params, 44100, 0);
     46 	if (err < 0) {
     47 		fprintf(stderr, "cannot set rate\n");
     48 		exit(0);
     49 	}
     50 	err = snd_pcm_hw_params_set_period_size_near(phandle, params, period_size);
     51 	if (err < 0) {
     52 		fprintf(stderr, "cannot set period size\n");
     53 		exit(0);
     54 	}
     55 	err = snd_pcm_hw_params(phandle, params);
     56 	if (err < 0) {
     57 		fprintf(stderr, "Unable to install hw params:\n");
     58 		exit(0);
     59 	}
     60 	snd_pcm_hw_params_dump(params, log);
     61 }
     62 
     63 #endif
     64 /*
     65  *  Simple event sender
     66  */
     67 
     68 void event_sender_start_timer(snd_seq_t *handle,
     69 			      int client ATTRIBUTE_UNUSED,
     70 			      int queue,
     71 			      snd_pcm_t *phandle ATTRIBUTE_UNUSED)
     72 {
     73 	int err;
     74 
     75 #ifdef USE_PCM
     76 	if (phandle) {
     77 		snd_pcm_playback_info_t pinfo;
     78 		snd_seq_queue_timer_t qtimer;
     79 
     80 		if ((err = snd_pcm_playback_info(phandle, &pinfo)) < 0) {
     81 			fprintf(stderr, "Playback info error: %s\n", snd_strerror(err));
     82 			exit(0);
     83 		}
     84 		bzero(&qtimer, sizeof(qtimer));
     85 		qtimer.type = SND_SEQ_TIMER_MASTER;
     86 		/* note: last bit from the subdevices specifies playback */
     87 		/* or capture direction for the timer specification */
     88 		qtimer.number = SND_TIMER_PCM(pcard, pdevice, pinfo.subdevice << 1);
     89 		if ((err = snd_seq_set_queue_timer(handle, queue, &qtimer)) < 0) {
     90 			fprintf(stderr, "Sequencer PCM timer setup failed: %s\n", snd_strerror(err));
     91 			exit(0);
     92 		}
     93 	}
     94 #endif
     95 	if ((err = snd_seq_start_queue(handle, queue, NULL))<0)
     96 		fprintf(stderr, "Timer event output error: %s\n", snd_strerror(err));
     97 	snd_seq_drain_output(handle);
     98 }
     99 
    100 void event_sender_filter(snd_seq_t *handle)
    101 {
    102 	int err;
    103 
    104 	if ((err = snd_seq_set_client_event_filter(handle, SND_SEQ_EVENT_ECHO)) < 0) {
    105 		fprintf(stderr, "Unable to set client info: %s\n", snd_strerror(err));
    106 		return;
    107 	}
    108 }
    109 
    110 void send_event(snd_seq_t *handle, int queue, int client, int port,
    111                 snd_seq_addr_t *dest, int *time)
    112 {
    113 	int err;
    114 	snd_seq_event_t ev;
    115 
    116 	bzero(&ev, sizeof(ev));
    117 	ev.queue = queue;
    118 	ev.source.client = ev.dest.client = client;
    119 	ev.source.port = ev.dest.port = port;
    120 	ev.flags = SND_SEQ_TIME_STAMP_REAL | SND_SEQ_TIME_MODE_ABS;
    121 	ev.time.time.tv_sec = *time; (*time)++;
    122 	ev.type = SND_SEQ_EVENT_ECHO;
    123 	if ((err = snd_seq_event_output(handle, &ev))<0)
    124 		fprintf(stderr, "Event output error: %s\n", snd_strerror(err));
    125 	ev.dest = *dest;
    126 	ev.type = SND_SEQ_EVENT_PGMCHANGE;
    127 	ev.data.control.channel = 0;
    128 	ev.data.control.value = 16;
    129 	if ((err = snd_seq_event_output(handle, &ev))<0)
    130 		fprintf(stderr, "Event output error: %s\n", snd_strerror(err));
    131 	ev.type = SND_SEQ_EVENT_NOTE;
    132 	ev.data.note.channel = 0;
    133 	ev.data.note.note = 64 + (queue*2);
    134 	ev.data.note.velocity = 127;
    135 	ev.data.note.off_velocity = 127;
    136 	ev.data.note.duration = 500;	/* 0.5sec */
    137 	if ((err = snd_seq_event_output(handle, &ev))<0)
    138 		fprintf(stderr, "Event output error: %s\n", snd_strerror(err));
    139 	if ((err = snd_seq_drain_output(handle))<0)
    140 		fprintf(stderr, "Event drain error: %s\n", snd_strerror(err));
    141 }
    142 
    143 void event_sender(snd_seq_t *handle, int argc, char *argv[])
    144 {
    145 	snd_seq_event_t *ev;
    146 	snd_seq_port_info_t *pinfo;
    147 	snd_seq_port_subscribe_t *sub;
    148 	snd_seq_addr_t addr;
    149 	struct pollfd *pfds;
    150 	int client, port, queue, max, err, v1, v2, time = 0, pcm_flag = 0;
    151 	char *ptr;
    152 	snd_pcm_t *phandle = NULL;
    153 
    154 	if (argc < 1) {
    155 		fprintf(stderr, "Invalid destination...\n");
    156 		return;
    157 	}
    158 
    159 	if ((client = snd_seq_client_id(handle))<0) {
    160 		fprintf(stderr, "Cannot determine client number: %s\n", snd_strerror(client));
    161 		return;
    162 	}
    163 	printf("Client ID = %i\n", client);
    164 	if ((queue = snd_seq_alloc_queue(handle))<0) {
    165 		fprintf(stderr, "Cannot allocate queue: %s\n", snd_strerror(queue));
    166 		return;
    167 	}
    168 	printf("Queue ID = %i\n", queue);
    169 	event_sender_filter(handle);
    170 	if ((err = snd_seq_nonblock(handle, 1))<0)
    171 		fprintf(stderr, "Cannot set nonblock mode: %s\n", snd_strerror(err));
    172 
    173 	snd_seq_port_info_alloca(&pinfo);
    174 	snd_seq_port_info_set_capability(pinfo, SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_READ);
    175 	snd_seq_port_info_set_name(pinfo, "Output");
    176 	if ((err = snd_seq_create_port(handle, pinfo)) < 0) {
    177 		fprintf(stderr, "Cannot create output port: %s\n", snd_strerror(err));
    178 		return;
    179 	}
    180 	port = snd_seq_port_info_get_port(pinfo);
    181 
    182 	snd_seq_port_subscribe_alloca(&sub);
    183 	addr.client = client;
    184 	addr.port = port;
    185 	snd_seq_port_subscribe_set_sender(sub, &addr);
    186 
    187 	for (max = 0; max < argc; max++) {
    188 		ptr = argv[max];
    189 		if (!ptr)
    190 			continue;
    191 		if (!strcmp(ptr, "pcm")) {
    192 			pcm_flag = 1;
    193 			continue;
    194 		}
    195 		if (sscanf(ptr, "%i.%i", &v1, &v2) != 2) {
    196 			fprintf(stderr, "Wrong argument '%s'...\n", argv[max]);
    197 			return;
    198 		}
    199 		addr.client = v1;
    200 		addr.port = v2;
    201 		snd_seq_port_subscribe_set_dest(sub, &addr);
    202 		if ((err = snd_seq_subscribe_port(handle, sub))<0) {
    203 			fprintf(stderr, "Cannot subscribe port %i from client %i: %s\n", v2, v1, snd_strerror(err));
    204 			return;
    205 		}
    206 	}
    207 
    208 	printf("Destination client = %i, port = %i\n", addr.client, addr.port);
    209 
    210 #ifdef USE_PCM
    211 	if (pcm_flag) {
    212 		if ((err = snd_pcm_open(&phandle, "default", SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
    213 			fprintf(stderr, "Playback open error: %s\n", snd_strerror(err));
    214 			exit(0);
    215 		}
    216 		set_hwparams(phandle);
    217 		pbuf = calloc(1, period_size * 4);
    218 		if (pbuf == NULL) {
    219 			fprintf(stderr, "No enough memory...\n");
    220 			exit(0);
    221 		}
    222 	}
    223 #endif
    224 	event_sender_start_timer(handle, client, queue, phandle);
    225 
    226 	/* send the first event */
    227 	send_event(handle, queue, client, port, &addr, &time);
    228 #ifdef USE_PCM
    229 	if (phandle)
    230 		max += snd_pcm_poll_descriptors_count(phandle);
    231 #endif
    232 	pfds = alloca(sizeof(*pfds) * max);
    233 	while (1) {
    234 		int nseqs = snd_seq_poll_descriptors_count(handle, POLLOUT|POLLIN);
    235 		if (snd_seq_event_output_pending(handle))
    236 			snd_seq_poll_descriptors(handle, pfds, nseqs, POLLOUT|POLLIN);
    237 		else
    238 			snd_seq_poll_descriptors(handle, pfds, nseqs, POLLIN);
    239 		max = nseqs;
    240 #ifdef USE_PCM
    241 		if (phandle) {
    242 			int pmax = snd_pcm_poll_descriptors_count(phandle);
    243 			snd_seq_poll_descriptors(phandle, pfds + max, pmax);
    244 			max += pmax;
    245 		}
    246 #endif
    247 		if (poll(pfds, max, -1) < 0)
    248 			break;
    249 #ifdef USE_PCM
    250 		if (phandle && (pfds[nseqs].revents & POLLOUT)) {
    251 			if (snd_pcm_writei(phandle, pbuf, period_size) != period_size) {
    252 				fprintf(stderr, "Playback write error!!\n");
    253 				exit(0);
    254 			}
    255 		}
    256 #endif
    257 		if (pfds[0].revents & POLLOUT)
    258 			snd_seq_drain_output(handle);
    259 		if (pfds[0].revents & POLLIN) {
    260 			do {
    261 				if ((err = snd_seq_event_input(handle, &ev))<0)
    262 					break;
    263 				if (!ev)
    264 					continue;
    265 				if (ev->type == SND_SEQ_EVENT_ECHO)
    266 					send_event(handle, queue, client, port, &addr, &time);
    267 				decode_event(ev);
    268 				snd_seq_free_event(ev);
    269 			} while (err > 0);
    270 		}
    271 	}
    272 }
    273