OSDN Git Service

Android: add makefile and config.h
[android-x86/external-alsa-lib.git] / test / seq-sender.c
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 }