Skip to content
This repository
Browse code

Merge pull request #14 from jhoffmannrim/master

Fix PlayWav to listen for Audio Device events
  • Loading branch information...
commit dbdc977b6941f8a983815ea8f5f9418ff6e0449d 2 parents add7366 + 4839043
Jonathan Hoffmann jhoffmannrim authored

Showing 1 changed file with 312 additions and 224 deletions. Show diff stats Hide diff stats

  1. +312 224 PlayWav/main.c
536 PlayWav/main.c
@@ -33,6 +33,7 @@
33 33
34 34 #include <bps/bps.h>
35 35 #include <bps/audiomixer.h>
  36 +#include <bps/audiodevice.h>
36 37 #include <bps/dialog.h>
37 38 #include <bps/navigator.h>
38 39
@@ -46,7 +47,11 @@ static char msg[MSG_SIZE];
46 47 const char *riff_id = "RIFF";
47 48 const char *wave_id = "WAVE";
48 49
49   -#define WAV_RELATIVE_PATH "/app/native/sample.wav"
  50 +#define WAV_RELATIVE_PATH "app/native/sample.wav"
  51 +
  52 +#define SUCCESS 0
  53 +#define FAILURE -1
  54 +
50 55
51 56 typedef struct
52 57 {
@@ -74,180 +79,115 @@ typedef struct
74 79 }
75 80 wave_hdr;
76 81
  82 +int card = -1;
  83 +
  84 +snd_pcm_t *pcm_handle;
  85 +snd_pcm_info_t info;
  86 +snd_pcm_channel_params_t pp;
  87 +snd_pcm_channel_setup_t setup;
  88 +snd_pcm_channel_info_t pi;
  89 +
  90 +snd_mixer_t *mixer_handle;
  91 +snd_mixer_group_t group;
  92 +
  93 +wave_hdr wav_header;
  94 +int sample_rate;
  95 +int sample_channels;
  96 +int sample_bits;
  97 +
77 98 int
78   -err (char *message)
  99 +err(char *message)
79 100 {
80   - snprintf (msg, MSG_SIZE, "%s\n%s", message, strerror(errno));
  101 + snprintf(msg, MSG_SIZE, "%s\n%s", message, strerror(errno));
81 102 show_dialog_message(msg);
82 103 return -1;
83 104 }
84 105
85 106 int
86   -find_tag (FILE * fp, const char *tag)
  107 +find_tag(FILE * fp, const char *tag)
87 108 {
88   - int ret_val = 0;
  109 + int ret_val = 0;
89 110 riff_tag tag_bfr = { "", 0 };
90 111
91   - // Keep reading until we find the tag or hit the EOF.
92   - while (fread ((unsigned char *) &tag_bfr, sizeof (tag_bfr), 1, fp))
93   - {
  112 + /* Keep reading until we find the tag or hit the EOF. */
  113 + while (fread((unsigned char *) &tag_bfr, sizeof(tag_bfr), 1, fp)) {
94 114
95   - // If this is our tag, set the length and break.
96   - if (strncmp (tag, tag_bfr.tag, sizeof tag_bfr.tag) == 0)
97   - {
98   - ret_val = ENDIAN_LE32 (tag_bfr.length);
  115 + /* If this is our tag, set the length and break. */
  116 + if (strncmp(tag, tag_bfr.tag, sizeof tag_bfr.tag) == 0) {
  117 + ret_val = ENDIAN_LE32(tag_bfr.length);
99 118 break;
100 119 }
101 120
102   - // Skip ahead the specified number of bytes in the stream
103   - fseek (fp, tag_bfr.length, SEEK_CUR);
  121 + /* Skip ahead the specified number of bytes in the stream */
  122 + fseek(fp, tag_bfr.length, SEEK_CUR);
104 123 }
105 124
106   - // Return the result of our operation
  125 + /* Return the result of our operation */
107 126 return (ret_val);
108 127 }
109 128
110 129 int
111   -check_hdr (FILE * fp)
  130 +check_hdr(FILE * fp)
112 131 {
113 132 riff_hdr riff_header = { "", 0 };
114 133
115   - // Read the header and, if successful, play the file
116   - // file or WAVE file.
117   - if (fread ((unsigned char *) &riff_header, sizeof (riff_hdr), 1, fp) == 0)
  134 + /* Read the header and make sure that this is indeed a Wave file. */
  135 + if (fread((unsigned char *) &riff_header, sizeof(riff_hdr), 1, fp) == 0)
118 136 return 0;
119 137
120   - if (strncmp (riff_header.Riff, riff_id, strlen (riff_id)) ||
121   - strncmp (riff_header.Wave, wave_id, strlen (wave_id)))
  138 + if (strncmp(riff_header.Riff, riff_id, strlen(riff_id)) ||
  139 + strncmp(riff_header.Wave, wave_id, strlen(wave_id)))
122 140 return -1;
123 141
124 142 return 0;
125 143 }
126 144
  145 +/*
  146 + * General setup of the libasound audio mixer and pcm components.
  147 + * Some of the settings are based on the format of the wav data.
  148 + */
127 149 int
128   -main (int argc, char **argv)
  150 +setup_snd(const char * name)
129 151 {
130   - int card = -1;
131   - int dev = 0;
132   - snd_pcm_t *pcm_handle;
133   - FILE *file;
134   - wave_hdr wav_header;
135   - int samples;
136   - int sample_rate;
137   - int sample_channels;
138   - int sample_bits;
139   - char *sample_buffer;
140   - int fragsize = -1;
141   -
142   - int rtn;
143   - int final_return_code = -1;
144   - snd_pcm_channel_info_t pi;
145   - snd_mixer_t *mixer_handle;
146   - snd_mixer_group_t group;
147   - snd_pcm_channel_params_t pp;
148   - snd_pcm_channel_setup_t setup;
149   - int bsize, bytes_read, total_written = 0;
150   - fd_set rfds, wfds;
151   - uint32_t voice_mask[] = { 0, 0, 0, 0 };
152   - snd_pcm_voice_conversion_t voice_conversion;
153   - int voice_override = 0;
154   - int num_frags = -1;
155   - char input_file[PATH_MAX];
156   - char cwd[PATH_MAX];
157   - int exit_application = 0;
158   -
159   - /*
160   - * Before we can listen for events from the BlackBerry Tablet OS platform
161   - * services, we need to initialize the BPS infrastructure
162   - */
163   - bps_initialize();
164   -
165   - if (setup_screen() != EXIT_SUCCESS) {
166   - printf("Unable to set up the screen. Exiting.");
167   - return 0;
  152 + int fragsize = -1;
  153 + int num_frags = -1;
  154 + int rtn;
  155 + char *dev_name;
  156 +
  157 + if (NULL == name) {
  158 + dev_name = "pcmPreferred";
  159 + } else {
  160 + dev_name = (char *) name;
168 161 }
169 162
170   - /*
171   - * Once the BPS infrastructure has been initialized we can register for
172   - * events from the various BlackBerry Tablet OS platform services. The
173   - * Navigator service manages and delivers application life cycle and
174   - * visibility events.
175   - * For this sample, we request Navigator events so we can track when
176   - * the system is terminating the application (NAVIGATOR_EXIT event). This allows
177   - * us to clean up application resources.
178   - */
179   - if (BPS_SUCCESS != navigator_request_events(0)) {
180   - fprintf(stderr, "Error requesting navigator events: %s", strerror(errno));
181   - exit(-1);
182   - }
183   -
184   - if (BPS_SUCCESS != dialog_request_events(0)) {
185   - fprintf(stderr, "Error requesting dialog events: %s", strerror(errno));
186   - exit(-1);
187   - }
188   - /*
189   - * Create and display the dialog.
190   - */
191   - create_dialog();
192   -
193   - if ((rtn = snd_pcm_open_preferred (&pcm_handle, &card, &dev, SND_PCM_OPEN_PLAYBACK)) < 0)
194   - {
195   - err ("device open");
196   - goto fail3;
197   - }
198   -
199   - getcwd(cwd, PATH_MAX);
200   - rtn = snprintf(input_file, PATH_MAX, "%s%s", cwd, WAV_RELATIVE_PATH);
201   - if (rtn > PATH_MAX - 1)
202   - {
203   - err ("File name and path too long");
204   - goto fail4;
205   - }
206   -
207   - if ((file = fopen (input_file, "r")) == 0)
208   - {
209   - err ("File open failed");
210   - goto fail4;
  163 + if ((rtn = snd_pcm_open_name(&pcm_handle, dev_name, SND_PCM_OPEN_PLAYBACK)) < 0) {
  164 + snprintf(msg, MSG_SIZE, "snd_pcm_open_name failed: %s\n", snd_strerror(rtn));
  165 + show_dialog_message(msg);
  166 + return FAILURE;
211 167 }
212 168
213   - if (check_hdr (file) == -1)
214   - {
215   - err ("check_hdr failed");
216   - goto fail5;
  169 + if ((rtn = snd_pcm_info(pcm_handle, &info)) < 0) {
  170 + snprintf(msg, MSG_SIZE, "snd_pcm_info failed: %s\n", snd_strerror(rtn));
  171 + goto setup_failure;
217 172 }
218   -
219   - samples = find_tag (file, "fmt ");
220   - fread (&wav_header, sizeof (wav_header), 1, file);
221   - fseek (file, (samples - sizeof (wave_hdr)), SEEK_CUR);
222   -
223   - sample_rate = ENDIAN_LE32 (wav_header.samples_per_sec);
224   - sample_channels = ENDIAN_LE16 (wav_header.channels);
225   - sample_bits = ENDIAN_LE16 (wav_header.bits_per_sample);
226   -
227   - snprintf(msg, MSG_SIZE, "SampleRate = %d, channels = %d, SampleBits = %d\n", sample_rate, sample_channels,
228   - sample_bits);
229   - show_dialog_message(msg);
  173 + card = info.card;
230 174
231 175 /* disabling mmap is not actually required in this example but it is included to
232 176 * demonstrate how it is used when it is required.
233 177 */
234   - if ((rtn = snd_pcm_plugin_set_disable (pcm_handle, PLUGIN_DISABLE_MMAP)) < 0)
235   - {
236   - snprintf(msg, MSG_SIZE, "snd_pcm_plugin_set_disable failed: %s\n", snd_strerror (rtn));
237   - show_dialog_message(msg);
238   - goto fail5;
  178 + if ((rtn = snd_pcm_plugin_set_disable(pcm_handle, PLUGIN_DISABLE_MMAP)) < 0) {
  179 + snprintf(msg, MSG_SIZE, "snd_pcm_plugin_set_disable failed: %s\n", snd_strerror(rtn));
  180 + goto setup_failure;
239 181 }
240 182
241   - memset (&pi, 0, sizeof (pi));
  183 + memset(&pi, 0, sizeof(pi));
242 184 pi.channel = SND_PCM_CHANNEL_PLAYBACK;
243   - if ((rtn = snd_pcm_plugin_info (pcm_handle, &pi)) < 0)
244   - {
245   - snprintf(msg, MSG_SIZE, "snd_pcm_plugin_info failed: %s\n", snd_strerror (rtn));
246   - show_dialog_message(msg);
247   - goto fail5;
  185 + if ((rtn = snd_pcm_plugin_info(pcm_handle, &pi)) < 0) {
  186 + snprintf(msg, MSG_SIZE, "snd_pcm_plugin_info failed: %s\n", snd_strerror(rtn));
  187 + goto setup_failure;
248 188 }
249 189
250   - memset (&pp, 0, sizeof (pp));
  190 + memset(&pp, 0, sizeof(pp));
251 191
252 192 pp.mode = SND_PCM_MODE_BLOCK;
253 193 pp.channel = SND_PCM_CHANNEL_PLAYBACK;
@@ -255,10 +195,10 @@ main (int argc, char **argv)
255 195 pp.stop_mode = SND_PCM_STOP_STOP;
256 196 pp.buf.block.frag_size = pi.max_fragment_size;
257 197
258   - if (fragsize != -1)
259   - {
  198 + if (fragsize != -1) {
260 199 pp.buf.block.frag_size = fragsize;
261 200 }
  201 +
262 202 pp.buf.block.frags_max = num_frags;
263 203 pp.buf.block.frags_min = 1;
264 204
@@ -266,9 +206,9 @@ main (int argc, char **argv)
266 206 pp.format.rate = sample_rate;
267 207 pp.format.voices = sample_channels;
268 208
269   - if (ENDIAN_LE16 (wav_header.format_tag) == 6)
  209 + if (ENDIAN_LE16(wav_header.format_tag) == 6)
270 210 pp.format.format = SND_PCM_SFMT_A_LAW;
271   - else if (ENDIAN_LE16 (wav_header.format_tag) == 7)
  211 + else if (ENDIAN_LE16(wav_header.format_tag) == 7)
272 212 pp.format.format = SND_PCM_SFMT_MU_LAW;
273 213 else if (sample_bits == 8)
274 214 pp.format.format = SND_PCM_SFMT_U8;
@@ -277,145 +217,293 @@ main (int argc, char **argv)
277 217 else
278 218 pp.format.format = SND_PCM_SFMT_S16_LE;
279 219
280   - strcpy (pp.sw_mixer_subchn_name, "Wave playback channel");
281   - if ((rtn = snd_pcm_plugin_params (pcm_handle, &pp)) < 0)
282   - {
283   - snprintf(msg, MSG_SIZE, "snd_pcm_plugin_params failed: %s\n", snd_strerror (rtn));
284   - show_dialog_message(msg);
285   - goto fail5;
286   - }
287   -
288   - if ((rtn = snd_pcm_plugin_prepare (pcm_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0) {
289   - snprintf(msg, MSG_SIZE, "snd_pcm_plugin_prepare failed: %s\n", snd_strerror (rtn));
290   - show_dialog_message(msg);
291   - goto fail5;
  220 + strcpy(pp.sw_mixer_subchn_name, "Wave playback channel");
  221 + if ((rtn = snd_pcm_plugin_params(pcm_handle, &pp)) < 0) {
  222 + snprintf(msg, MSG_SIZE, "snd_pcm_plugin_params failed: %s\n", snd_strerror(rtn));
  223 + goto setup_failure;
292 224 }
293 225
294   - if (voice_override)
295   - {
296   - snd_pcm_plugin_get_voice_conversion (pcm_handle, SND_PCM_CHANNEL_PLAYBACK,
297   - &voice_conversion);
298   - voice_conversion.matrix[0] = voice_mask[0];
299   - voice_conversion.matrix[1] = voice_mask[1];
300   - voice_conversion.matrix[2] = voice_mask[2];
301   - voice_conversion.matrix[3] = voice_mask[3];
302   - snd_pcm_plugin_set_voice_conversion (pcm_handle, SND_PCM_CHANNEL_PLAYBACK,
303   - &voice_conversion);
  226 + if ((rtn = snd_pcm_plugin_prepare(pcm_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0) {
  227 + snprintf(msg, MSG_SIZE, "snd_pcm_plugin_prepare failed: %s\n", snd_strerror(rtn));
  228 + goto setup_failure;
304 229 }
305 230
306   - memset (&setup, 0, sizeof (setup));
307   - memset (&group, 0, sizeof (group));
  231 + memset(&setup, 0, sizeof(setup));
  232 + memset(&group, 0, sizeof(group));
308 233 setup.channel = SND_PCM_CHANNEL_PLAYBACK;
309 234 setup.mixer_gid = &group.gid;
310 235
311   - if ((rtn = snd_pcm_plugin_setup (pcm_handle, &setup)) < 0)
312   - {
313   - snprintf(msg, MSG_SIZE, "snd_pcm_plugin_setup failed: %s\n", snd_strerror (rtn));
314   - show_dialog_message(msg);
315   - goto fail5;
  236 + if ((rtn = snd_pcm_plugin_setup(pcm_handle, &setup)) < 0) {
  237 + snprintf(msg, MSG_SIZE, "snd_pcm_plugin_setup failed: %s\n", snd_strerror(rtn));
  238 + goto setup_failure;
316 239 }
317 240
318   - if (group.gid.name[0] == 0)
319   - {
  241 + if (group.gid.name[0] == 0) {
320 242 snprintf(msg, MSG_SIZE, "Mixer Pcm Group [%s] Not Set \n", group.gid.name);
321   - show_dialog_message(msg);
322   - goto fail5;
  243 + goto setup_failure;
323 244 }
324 245
325   - if ((rtn = snd_mixer_open (&mixer_handle, card, setup.mixer_device)) < 0)
326   - {
327   - snprintf(msg, MSG_SIZE, "snd_mixer_open failed: %s\n", snd_strerror (rtn));
328   - show_dialog_message(msg);
329   - goto fail5;
  246 + if ((rtn = snd_mixer_open(&mixer_handle, card, setup.mixer_device)) < 0) {
  247 + snprintf(msg, MSG_SIZE, "snd_mixer_open failed: %s\n", snd_strerror(rtn));
  248 + goto setup_failure;
330 249 }
331 250
332 251 char tmp[MSG_SIZE];
333   - snprintf (msg, MSG_SIZE, "Format %s \n", snd_pcm_get_format_name (setup.format.format));
334   - snprintf (tmp, MSG_SIZE, "Frag Size %d \n", setup.buf.block.frag_size);
  252 + snprintf(msg, MSG_SIZE, "Format %s \n", snd_pcm_get_format_name(setup.format.format));
  253 + snprintf(tmp, MSG_SIZE, "Frag Size %d \n", setup.buf.block.frag_size);
335 254 strlcat(msg, tmp, MSG_SIZE);
336   - snprintf (tmp, MSG_SIZE, "Total Frags %d \n", setup.buf.block.frags);
  255 + snprintf(tmp, MSG_SIZE, "Total Frags %d \n", setup.buf.block.frags);
337 256 strlcat(msg, tmp, MSG_SIZE);
338   - snprintf (tmp, MSG_SIZE, "Rate %d \n", setup.format.rate);
  257 + snprintf(tmp, MSG_SIZE, "Rate %d \n", setup.format.rate);
339 258 strlcat(msg, tmp, MSG_SIZE);
340   - snprintf (tmp, MSG_SIZE, "Voices %d \n", setup.format.voices);
  259 + snprintf(tmp, MSG_SIZE, "Voices %d \n", setup.format.voices);
341 260 strlcat(msg, tmp, MSG_SIZE);
342   - snprintf (tmp, MSG_SIZE, "Mixer Pcm Group [%s]\n", group.gid.name);
  261 + snprintf(tmp, MSG_SIZE, "Mixer Pcm Group [%s]\n", group.gid.name);
343 262 strlcat(msg, tmp, MSG_SIZE);
344 263 show_dialog_message(msg);
345 264
  265 + return SUCCESS;
  266 +
  267 +setup_failure:
  268 + show_dialog_message(msg);
  269 + snd_pcm_close(pcm_handle);
  270 + return FAILURE;
  271 +}
  272 +
  273 +int
  274 +main(int argc, char **argv)
  275 +{
  276 + FILE *file;
  277 + int samples;
  278 + char *sample_buffer;
  279 +
  280 + int rtn, final_return_code = -1, exit_application = 0;
  281 +
  282 + int bsize, bytes_read, total_written = 0;
  283 + fd_set rfds, wfds;
  284 + char input_file[PATH_MAX];
  285 + char cwd[PATH_MAX];
  286 +
  287 +
  288 + /*
  289 + * Before we can listen for events from the BlackBerry Tablet OS platform
  290 + * services, we need to initialize the BPS infrastructure
  291 + */
  292 + bps_initialize();
  293 +
  294 + if (setup_screen() != EXIT_SUCCESS) {
  295 + printf("Unable to set up the screen. Exiting.");
  296 + exit(-1);
  297 + }
  298 +
  299 + /*
  300 + * Once the BPS infrastructure has been initialized we can register for
  301 + * events from the various BlackBerry Tablet OS platform services. The
  302 + * Navigator service manages and delivers application life cycle and
  303 + * visibility events.
  304 + *
  305 + * For this sample, we request Navigator events so we can track when
  306 + * the system is terminating the application (NAVIGATOR_EXIT event).
  307 + * This allows us to clean up application resources.
  308 + *
  309 + * We request Audio Device events because we want to make sure that
  310 + * we properly handle changes in audio output.
  311 + *
  312 + * We request dialog events to properly initialize the dialog
  313 + * subsystem in order to display status and error messages.
  314 + */
  315 + if (BPS_SUCCESS != navigator_request_events(0)) {
  316 + fprintf(stderr, "Error requesting navigator events: %s", strerror(errno));
  317 + exit(-1);
  318 + }
  319 +
  320 + if (BPS_SUCCESS != dialog_request_events(0)) {
  321 + fprintf(stderr, "Error requesting dialog events: %s", strerror(errno));
  322 + exit(-1);
  323 + }
  324 +
  325 + if (BPS_SUCCESS != audiodevice_request_events(0)) {
  326 + fprintf(stderr, "Error requesting audio device events: %s", strerror(errno));
  327 + exit(-1);
  328 + }
  329 +
  330 + /*
  331 + * Create and display the dialog.
  332 + */
  333 + create_dialog();
  334 +
  335 + /*
  336 + * Open and check the input file.
  337 + */
  338 + getcwd(cwd, PATH_MAX);
  339 + rtn = snprintf(input_file, PATH_MAX, "%s/%s", cwd, WAV_RELATIVE_PATH);
  340 + if (rtn > PATH_MAX - 1) {
  341 + err("File name and path too long");
  342 + goto fail1;
  343 + }
  344 +
  345 + if ((file = fopen(input_file, "r")) == 0) {
  346 + err("File open failed");
  347 + goto fail1;
  348 + }
  349 +
  350 + if (check_hdr(file) == -1) {
  351 + err("check_hdr failed");
  352 + goto fail2;
  353 + }
  354 +
  355 + /*
  356 + * Parse the headers in the wav file to figure out what kind of data we
  357 + * are dealing with in the file.
  358 + */
  359 + samples = find_tag(file, "fmt ");
  360 + fread(&wav_header, sizeof(wav_header), 1, file);
  361 + fseek(file,(samples - sizeof(wave_hdr)), SEEK_CUR);
  362 +
  363 + sample_rate = ENDIAN_LE32(wav_header.samples_per_sec);
  364 + sample_channels = ENDIAN_LE16(wav_header.channels);
  365 + sample_bits = ENDIAN_LE16(wav_header.bits_per_sample);
  366 +
  367 + snprintf(msg, MSG_SIZE, "SampleRate = %d, channels = %d, SampleBits = %d\n", sample_rate, sample_channels,
  368 + sample_bits);
  369 + show_dialog_message(msg);
  370 +
  371 + if (setup_snd(NULL)) {
  372 + goto fail2;
  373 + }
  374 +
346 375 bsize = setup.buf.block.frag_size;
347   - samples = find_tag (file, "data");
348   - sample_buffer = malloc (bsize);
349   - FD_ZERO (&rfds);
350   - FD_ZERO (&wfds);
  376 + samples = find_tag(file, "data");
  377 + sample_buffer = malloc(bsize);
  378 + if (!sample_buffer) {
  379 + goto fail3;
  380 + }
  381 +
  382 + FD_ZERO(&rfds);
  383 + FD_ZERO(&wfds);
351 384 bytes_read = 1;
352   - while (total_written < samples && bytes_read > 0)
353   - {
354   - if (tcgetpgrp (0) == getpid ())
355   - FD_SET (STDIN_FILENO, &rfds);
356   - FD_SET (snd_mixer_file_descriptor (mixer_handle), &rfds);
357   - FD_SET (snd_pcm_file_descriptor (pcm_handle, SND_PCM_CHANNEL_PLAYBACK), &wfds);
358   -
359   - rtn = max (snd_mixer_file_descriptor (mixer_handle),
360   - snd_pcm_file_descriptor (pcm_handle, SND_PCM_CHANNEL_PLAYBACK));
361   -
362   - if (select (rtn + 1, &rfds, &wfds, NULL, NULL) == -1)
363   - {
364   - err ("select");
365   - goto fail6;
  385 + while (total_written < samples && bytes_read > 0 ) {
  386 + bps_event_t *event = NULL;
  387 +
  388 + while (BPS_SUCCESS == bps_get_event(&event, 0) && event) {
  389 + /*
  390 + * If it is a NAVIGATOR_EXIT event then we are done so stop
  391 + * processing events, clean up and exit
  392 + */
  393 + if (bps_event_get_domain(event) == navigator_get_domain()) {
  394 + if (NAVIGATOR_EXIT == bps_event_get_code(event)) {
  395 + exit_application = 1;
  396 + goto success;
  397 + }
  398 + }
  399 +
  400 + if (bps_event_get_domain(event) == audiodevice_get_domain()) {
  401 + /*
  402 + * If it is a audio device event then it means a new audio device
  403 + * has been enabled and a switch is required. We close the old,
  404 + * open the new audio device using the path and get the card number so
  405 + * that we can close and re-open the mixer with the new card
  406 + * number.
  407 + */
  408 +
  409 + const char * audiodevice_path = audiodevice_event_get_path(event);
  410 +
  411 + if (NULL == audiodevice_path) {
  412 + snprintf(msg, MSG_SIZE, "audiodevice_event_get_path failed: %s\n", snd_strerror(rtn));
  413 + show_dialog_message(msg);
  414 + goto fail5;
  415 + }
  416 +
  417 + if ((rtn = snd_mixer_close(mixer_handle)) < 0) {
  418 + snprintf(msg, MSG_SIZE, "snd_mixer_close failed: %s\n", snd_strerror(rtn));
  419 + show_dialog_message(msg);
  420 + goto fail4;
  421 + }
  422 +
  423 + if ((rtn = snd_pcm_close(pcm_handle)) < 0) {
  424 + snprintf(msg, MSG_SIZE, "snd_pcm_close failed: %s\n", snd_strerror(rtn));
  425 + show_dialog_message(msg);
  426 + goto fail3;
  427 + }
  428 +
  429 + if (setup_snd(audiodevice_path)) {
  430 + /*
  431 + * setup_snd() closes pcm and mixer handles in the case of error so we
  432 + * skip clean up of the handles in the case of failure.
  433 + */
  434 + goto fail3;
  435 + }
  436 + }
  437 + }
  438 +
  439 + if (tcgetpgrp(0) == getpid())
  440 + FD_SET(STDIN_FILENO, &rfds);
  441 + FD_SET(snd_mixer_file_descriptor(mixer_handle), &rfds);
  442 + FD_SET(snd_pcm_file_descriptor(pcm_handle, SND_PCM_CHANNEL_PLAYBACK), &wfds);
  443 +
  444 + rtn = max(snd_mixer_file_descriptor(mixer_handle),
  445 + snd_pcm_file_descriptor(pcm_handle, SND_PCM_CHANNEL_PLAYBACK));
  446 +
  447 + if (select(rtn + 1, &rfds, &wfds, NULL, NULL) == -1) {
  448 + err("select");
  449 + goto fail5;
366 450 }
367 451
368   - if (FD_ISSET (snd_pcm_file_descriptor (pcm_handle, SND_PCM_CHANNEL_PLAYBACK), &wfds))
369   - {
  452 + if (FD_ISSET(snd_pcm_file_descriptor(pcm_handle, SND_PCM_CHANNEL_PLAYBACK), &wfds)) {
370 453 snd_pcm_channel_status_t status;
371   - int written = 0;
  454 + int written = 0;
372 455
373   - if ((bytes_read = fread (sample_buffer, 1, min (samples - total_written, bsize), file)) <= 0)
  456 + if ((bytes_read = fread(sample_buffer, 1, min(samples - total_written, bsize), file)) <= 0)
374 457 continue;
375   - written = snd_pcm_plugin_write (pcm_handle, sample_buffer, bytes_read);
376   - if (written < bytes_read)
377   - {
378   - memset (&status, 0, sizeof (status));
  458 + written = snd_pcm_plugin_write(pcm_handle, sample_buffer, bytes_read);
  459 + if (written < bytes_read) {
  460 + memset(&status, 0, sizeof(status));
379 461 status.channel = SND_PCM_CHANNEL_PLAYBACK;
380   - if (snd_pcm_plugin_status (pcm_handle, &status) < 0)
381   - {
  462 + if (snd_pcm_plugin_status(pcm_handle, &status) < 0) {
382 463 show_dialog_message("underrun: playback channel status error\n");
383   - goto fail6;
  464 + goto fail5;
384 465 }
385 466
386 467 if (status.status == SND_PCM_STATUS_READY ||
387   - status.status == SND_PCM_STATUS_UNDERRUN)
388   - {
389   - if (snd_pcm_plugin_prepare (pcm_handle, SND_PCM_CHANNEL_PLAYBACK) < 0)
390   - {
  468 + status.status == SND_PCM_STATUS_UNDERRUN) {
  469 + if (snd_pcm_plugin_prepare(pcm_handle, SND_PCM_CHANNEL_PLAYBACK) < 0) {
391 470 show_dialog_message("underrun: playback channel prepare error\n");
392   - goto fail6;
  471 + goto fail5;
393 472 }
394 473 }
395 474 if (written < 0)
396 475 written = 0;
397   - written += snd_pcm_plugin_write (pcm_handle, sample_buffer + written, bytes_read - written);
  476 + written += snd_pcm_plugin_write(pcm_handle, sample_buffer + written, bytes_read - written);
398 477 }
399 478 total_written += written;
400 479 }
401 480 }
402 481
403   - bytes_read = snd_pcm_plugin_flush (pcm_handle, SND_PCM_CHANNEL_PLAYBACK);
  482 +success:
  483 + bytes_read = snd_pcm_plugin_flush(pcm_handle, SND_PCM_CHANNEL_PLAYBACK);
404 484 final_return_code = 0;
405   -
406   -fail6:
407   - rtn = snd_mixer_close (mixer_handle);
  485 + /*
  486 + * there are return codes to these close calls, but we would do the same
  487 + * thing regardless of error or success so we do not check the return codes.
  488 + */
408 489 fail5:
409   - fclose (file);
  490 + snd_mixer_close(mixer_handle);
410 491 fail4:
411   - rtn = snd_pcm_close (pcm_handle);
  492 + snd_pcm_close(pcm_handle);
412 493 fail3:
  494 + free(sample_buffer);
  495 + sample_buffer = NULL;
  496 +fail2:
  497 + fclose(file);
  498 +fail1:
  499 +
413 500
414   - /*
415   - * Process Navigator events until we receive a NAVIGATOR_EXIT event.
416   - */
417 501 while (!exit_application) {
418 502 /*
  503 + * Something went wrong so there is probably an error message and
  504 + * we don't want to exit right away because we want the user to see
  505 + * the message in the dialog.
  506 + *
419 507 * Using a negative timeout (-1) in the call to bps_get_event(...)
420 508 * ensures that we don't busy wait by blocking until an event is
421 509 * available.
@@ -425,9 +513,8 @@ main (int argc, char **argv)
425 513
426 514 if (event) {
427 515 /*
428   - * If it is a NAVIGATOR_EXIT event then set the exit_application
429   - * flag so the application will stop processing events, clean up
430   - * and exit
  516 + * If it is a NAVIGATOR_EXIT event then we are done so stop
  517 + * processing events, clean up and exit
431 518 */
432 519 if (bps_event_get_domain(event) == navigator_get_domain()) {
433 520 if (NAVIGATOR_EXIT == bps_event_get_code(event)) {
@@ -436,6 +523,7 @@ main (int argc, char **argv)
436 523 }
437 524 }
438 525 }
  526 +
439 527 /*
440 528 * Destroy the dialog, if it exists and cleanup screen resources.
441 529 */

0 comments on commit dbdc977

Please sign in to comment.
Something went wrong with that request. Please try again.