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(¶ms); 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