2 * Copyright (c) 2013, TOYOTA MOTOR CORPORATION.
4 * This program is licensed under the terms and conditions of the
5 * Apache License, version 2.0. The full text of the Apache License is at
6 * http://www.apache.org/licenses/LICENSE-2.0
10 * @brief Sound Sample APP
11 * Test use with which sound is sounded
17 * TP using PulseAudio with wavfile
26 #include <pulse/mainloop.h>
27 #include <pulse/context.h>
28 #include <pulse/stream.h>
29 #include <pulse/error.h>
31 #include "soundsample_yswavfile.h"
33 //#include "app_log.h"
34 #include "ico_apf_log.h"
35 #include "soundsample.h"
37 #define ICO_PA_STREAM_PAUSE (1)
38 #define ICO_PA_STREAM_RESUME (0)
42 int pulse_main(struct audio_config_t *audio_config, int filedes);
46 static int ReadFiledes;
47 #define REPEAT_FLG 1 /* ON:0 ,OFF:1 */
49 static YSRESULT YsPulseAudioWaitForConnectionEstablished(pa_context *
55 time_t timeLimit = time(NULL) + timeOut;
56 while (timeLimit >= time(NULL)) {
57 pa_mainloop_iterate(paMainLoop, 0, NULL);
58 if (PA_CONTEXT_READY == pa_context_get_state(paContext)) {
65 static void event_input_callback(pa_mainloop_api *a, pa_io_event *e, int fd,
66 pa_io_event_flags_t f, void *userdata)
69 uim_debug("event_input_callback: Enter");
72 memset(buff, 0x00, sizeof(buff));
74 /* From a pipe to reading */
75 read(ReadFiledes, buff, sizeof(buff));
76 uim_debug("buff :%s", buff);
80 uim_debug("Stop directions reception");
85 uim_debug("Pause directions reception");
87 if (0 == pa_stream_is_corked((pa_stream *) userdata)) {
88 pa_stream_cork((pa_stream *) userdata, ICO_PA_STREAM_PAUSE, NULL,
90 uim_debug("pa_stream_cork(PAUSE)");
92 uim_debug("sleep end");
95 pa_stream_cork((pa_stream *) userdata, ICO_PA_STREAM_RESUME, NULL,
97 uim_debug("pa_stream_cork(RESUME)");
99 uim_debug("sleep end");
104 uim_debug("Err Reception range outside");
108 uim_debug("event_input_callback: Leave");
111 int pulse_main(struct audio_config_t *audio_config, int filedes)
113 char *server_ip = NULL;
114 char *device_name = NULL;
116 int volume_set2 = -1;
117 char *app_name = NULL;
118 char *stream_name = NULL;
120 pa_cvolume *cvolume = NULL;
122 char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
127 ReadFiledes = filedes;
130 if (audio_config == NULL) {
131 uim_debug("Param Err");
135 if (YSOK != wavFile.LoadWav(audio_config->wavfile_path)) {
136 // fprintf(stderr, "Cannot open wave file.\n");
137 uim_debug("Cannot open wave file.");
141 if (audio_config->volume1 != -1) {
142 cvolume = (pa_cvolume *) malloc(sizeof(pa_cvolume));
148 server_ip = audio_config->server_ip;
149 device_name = audio_config->device_name;
150 volume_set = audio_config->volume1;
151 volume_set2 = audio_config->volume2;
152 app_name = audio_config->app_name;
153 stream_name = audio_config->stream_name;
155 uim_debug("Before Resampling:");
156 uim_debug("Bit per sample: %d", wavFile.BitPerSample());
157 uim_debug("Stereo: %d", wavFile.Stereo());
158 uim_debug("Playback Rate: %d", wavFile.PlayBackRate());
159 uim_debug("Signed: %d", wavFile.IsSigned());
161 wavFile.ConvertTo16Bit();
162 wavFile.ConvertToSigned();
163 // wavFile.ConvertToStereo();
164 wavFile.Resample(44100);
165 // wavFile.ConvertToMono();
167 uim_debug("After Resampling:");
168 uim_debug("Bit per sample: %d", wavFile.BitPerSample());
169 uim_debug("Stereo: %d", wavFile.Stereo());
170 uim_debug("Playback Rate: %d", wavFile.PlayBackRate());
171 uim_debug("Signed: %d", wavFile.IsSigned());
173 pa_mainloop *paMainLoop = pa_mainloop_new();
174 if (NULL == paMainLoop) {
175 // fprintf(stderr,"Cannot create main loop.\n");
176 uim_debug("Cannot create main loop.");
179 uim_debug("pa_mainloop_new()");
181 pa_context *paContext = pa_context_new(pa_mainloop_get_api(paMainLoop),
183 if (NULL == paContext) {
184 // fprintf(stderr,"Cannot create context.\n");
185 uim_debug("Cannot create context.");
188 uim_debug("pa_context_new()");
190 // pa_context_set_state_callback(paContext,YsPulseAudioConnectionCallBack,NULL);
191 pa_context_connect(paContext, server_ip, (pa_context_flags_t) 0, NULL);
192 uim_debug("pa_context_connect()");
194 YsPulseAudioWaitForConnectionEstablished(paContext, paMainLoop, 5);
196 pa_sample_format_t format = PA_SAMPLE_U8;
197 switch (wavFile.BitPerSample()) {
199 if (YSTRUE == wavFile.IsSigned()) {
200 wavFile.ConvertToUnsigned();
202 format = PA_SAMPLE_U8;
205 if (YSTRUE != wavFile.IsSigned()) {
206 wavFile.ConvertToSigned();
208 format = PA_SAMPLE_S16LE;
211 const int rate = wavFile.PlayBackRate();
212 const int nChannel = (YSTRUE == wavFile.Stereo()? 2 : 1);
214 const pa_sample_spec ss = {
220 pa_channel_map_init_auto(&cmap, nChannel, PA_CHANNEL_MAP_ALSA);
221 uim_debug("pa_channel_map_init_auto()");
222 uim_debug("map: <%s>", pa_channel_map_snprint(cm, sizeof(cm), &cmap));
224 if (NULL != cvolume) {
227 for (i = 0; i < PA_CHANNELS_MAX; i++) {
229 if (-1 != volume_set2) {
230 cvolume->values[i] = volume_set2;
234 cvolume->values[i] = volume_set;
236 uim_debug("volume[%d]_%d", i, cvolume->values[i]);
238 cvolume->channels = nChannel;
241 unsigned int playBackPtr = 0;
242 YSBOOL checkForUnderflow = YSTRUE;
243 // time_t t0 = time(NULL);
244 time_t prevT = time(NULL) - 1;
246 uim_debug("enter mainloop");
249 static pa_io_event *stdio_event = NULL;
250 static pa_mainloop_api *mainloop_api = pa_mainloop_get_api(paMainLoop);
252 paStream = pa_stream_new(paContext, stream_name, &ss, &cmap);
253 if (NULL != paStream) {
254 uim_debug("Stream created! Getting there!");
257 uim_debug("Stream created : NG");
261 uim_debug("pa_stream_new()");
263 if (!(stdio_event = mainloop_api->io_new(mainloop_api, ReadFiledes,
265 event_input_callback,
267 uim_debug("io_new() failed()");
271 pa_stream_connect_playback(paStream, device_name, NULL,
272 (pa_stream_flags_t) 0, cvolume, NULL);
273 uim_debug("pa_stream_connect_playback()");
276 for (loopcnt = 0; ExitFlg != 1; loopcnt++) {
277 if (st != pa_stream_get_state(paStream)) {
278 st = pa_stream_get_state(paStream);
280 uim_debug("TURN(%6d)_", loopcnt);
282 switch (pa_stream_get_state(paStream)) {
283 case PA_STREAM_UNCONNECTED:
284 uim_debug("PA_STREAM_UNCONNECTED");
286 case PA_STREAM_CREATING:
287 uim_debug("PA_STREAM_CREATING");
289 case PA_STREAM_READY:
290 uim_debug("PA_STREAM_READY");
292 case PA_STREAM_FAILED:
293 uim_debug("PA_STREAM_FAILED");
295 case PA_STREAM_TERMINATED:
296 uim_debug("PA_STREAM_TERMINATED");
301 if (time(NULL) != prevT) {
302 /* uim_debug("Ping..."); */
306 if (PA_STREAM_READY == pa_stream_get_state(paStream)) {
307 const size_t writableSize = pa_stream_writable_size(paStream);
308 const size_t sizeRemain = wavFile.SizeInByte() - playBackPtr;
309 const size_t writeSize =
310 (sizeRemain < writableSize ? sizeRemain : writableSize);
313 pa_stream_write(paStream, wavFile.DataPointer() + playBackPtr,
314 writeSize, NULL, 0, PA_SEEK_RELATIVE);
315 playBackPtr += writeSize;
316 uim_debug("pa_stream_write()_%d", (int) writeSize);
320 if ((wavFile.SizeInByte() <= playBackPtr) &&
321 (0 <= pa_stream_get_underflow_index(paStream)) &&
322 (YSTRUE == checkForUnderflow)) {
324 ("Underflow detected. (Probably the playback is done.)");
330 pa_mainloop_iterate(paMainLoop, 0, NULL);
333 uim_debug("STREAM is END.");
335 pa_stream_disconnect(paStream);
336 uim_debug("pa_stream_disconnect()");
338 pa_stream_unref(paStream);
339 uim_debug("pa_stream_unref()");
342 uim_debug("leave mainloop");
344 if (NULL != cvolume) {
348 pa_context_disconnect(paContext);
349 uim_debug("pa_context_disconnect()");
351 pa_context_unref(paContext);
352 uim_debug("pa_context_unref()");
354 pa_mainloop_free(paMainLoop);
355 uim_debug("pa_mainloop_free()");
357 uim_debug("The End");