This is a sample application that captures (i.e. records) audio data:
/* * $QNXLicenseC: * Copyright 2007, QNX Software Systems. All Rights Reserved. * * You must obtain a written license from and pay applicable license fees to QNX * Software Systems before you may reproduce, modify or distribute this software, * or any work that includes all or part of this software. Free development * licenses are available for evaluation and non-commercial purposes. For more * information visit http://licensing.qnx.com or email licensing@qnx.com. * * This file may contain contributions from others. Please review this entire * file for other proprietary rights or license notices, as well as the QNX * Development Suite License Guide at http://licensing.qnx.com/license-guide/ * for other information. * $ */ #include <errno.h> #include <fcntl.h> #include <gulliver.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/ioctl.h> #include <sys/select.h> #include <sys/stat.h> #include <sys/termio.h> #include <sys/types.h> #include <unistd.h> #include <sys/asoundlib.h> /* *INDENT-OFF* */ struct { char riff_id[4]; char wave_len[4]; struct { char fmt_id[8]; char fmt_len[4]; struct { char format_tag[2]; char voices[2]; char rate[4]; char char_per_sec[4]; char block_align[2]; char bits_per_sample[2]; } fmt; struct { char data_id[4]; char data_len[4]; } data; } wave; } riff_hdr = { {'R', 'I', 'F', 'F' }, {sizeof (riff_hdr.wave), 0, 0, 0 }, { {'W', 'A', 'V', 'E', 'f', 'm', 't', ' ' }, {sizeof (riff_hdr.wave.fmt), 0, 0, 0 }, { {1, 0 }, {0, 0 }, {0, 0, 0, 0 }, {0, 0, 0, 0 }, {0, 0 }, {0, 0 } }, { {'d', 'a', 't', 'a' }, {0, 0, 0, 0 } } } }; /* *INDENT-ON* */ int err (char *msg) { perror (msg); return -1; } int dev_raw (int fd) { struct termios termios_p; if (tcgetattr (fd, &termios_p)) return (-1); termios_p.c_cc[VMIN] = 1; termios_p.c_cc[VTIME] = 0; termios_p.c_lflag &= ~(ECHO | ICANON | ISIG | ECHOE | ECHOK | ECHONL); termios_p.c_oflag &= ~(OPOST); return (tcsetattr (fd, TCSANOW, &termios_p)); } int dev_unraw (int fd) { struct termios termios_p; if (tcgetattr (fd, &termios_p)) return (-1); termios_p.c_lflag |= (ECHO | ICANON | ISIG | ECHOE | ECHOK | ECHONL); termios_p.c_oflag |= (OPOST); return (tcsetattr (fd, TCSAFLUSH, &termios_p)); } //***************************************************************************** /* *INDENT-OFF* */ #ifdef __USAGE %C[Options] * Options: -8 use 8 bit mode (16 bit default) -a[card#:]<dev#> the card & device number to record from -m record in mono (stereo default) -r <rate> record at rate (44100 default | 48000 44100 22050 11025) -t <sec> seconds to record (5 seconds default) #endif /* *INDENT-ON* */ //***************************************************************************** int main (int argc, char **argv) { int card = -1; int dev = 0; snd_pcm_t *pcm_handle; FILE *file1; int mSamples; int mSampleRate; int mSampleChannels; int mSampleBits; int mSampleTime; char *mSampleBfr1; int fragsize = -1; int verbose = 0; int rtn; snd_pcm_channel_info_t pi; snd_mixer_t *mixer_handle; snd_mixer_group_t group; snd_pcm_channel_params_t pp; snd_pcm_channel_setup_t setup; int bsize, n, N = 0, c; fd_set rfds; mSampleRate = 44100; mSampleChannels = 2; mSampleBits = 16; mSampleTime = 5; while ((c = getopt (argc, argv, "8a:f:mr:t:v")) != EOF) { switch (c) { case '8': mSampleBits = 8; break; case 'a': if (strchr (optarg, ':')) { card = atoi (optarg); dev = atoi (strchr (optarg, ':') + 1); } else dev = atoi (optarg); printf ("Using card %d device %d \n", card, dev); break; case 'f': fragsize = atoi (optarg); break; case 'm': mSampleChannels = 1; break; case 'r': mSampleRate = atoi (optarg); break; case 't': mSampleTime = atoi (optarg); break; case 'v': verbose = 1; break; default: return 1; } } setvbuf (stdin, NULL, _IONBF, 0); if (card == -1) { if ((rtn = snd_pcm_open_preferred (&pcm_handle, &card, &dev, SND_PCM_OPEN_CAPTURE)) < 0) return err ("device open"); } else { if ((rtn = snd_pcm_open (&pcm_handle, card, dev, SND_PCM_OPEN_CAPTURE)) < 0) return err ("device open"); } if (argc < 2) return err ("no file specified"); if ((file1 = fopen (argv[optind], "w")) == 0) return err ("file open #1"); mSamples = mSampleRate * mSampleChannels * mSampleBits / 8 * mSampleTime; *(short *) riff_hdr.wave.fmt.voices = ENDIAN_LE16 (mSampleChannels); *(long *) riff_hdr.wave.fmt.rate = ENDIAN_LE32 (mSampleRate); *(long *) riff_hdr.wave.fmt.char_per_sec = ENDIAN_LE32 (mSampleRate * mSampleChannels * mSampleBits / 8); *(short *) riff_hdr.wave.fmt.block_align = ENDIAN_LE16 (mSampleChannels * mSampleBits / 8); *(short *) riff_hdr.wave.fmt.bits_per_sample = ENDIAN_LE16 (mSampleBits); *(long *) riff_hdr.wave.data.data_len = ENDIAN_LE32 (mSamples); *(long *) riff_hdr.wave_len = ENDIAN_LE32 (mSamples + sizeof (riff_hdr) - 8); fwrite (&riff_hdr, 1, sizeof (riff_hdr), file1); printf ("SampleRate = %d, Channels = %d, SampleBits = %d\n", mSampleRate, mSampleChannels, mSampleBits); /* disabling mmap is not actually required in this example but it is included to * demonstrate how it is used when it is required. */ if ((rtn = snd_pcm_plugin_set_disable (pcm_handle, PLUGIN_DISABLE_MMAP)) < 0) { fprintf (stderr, "snd_pcm_plugin_set_disable failed: %s\n", snd_strerror (rtn)); return -1; } memset (&pi, 0, sizeof (pi)); pi.channel = SND_PCM_CHANNEL_CAPTURE; if ((rtn = snd_pcm_plugin_info (pcm_handle, &pi)) < 0) { fprintf (stderr, "snd_pcm_plugin_info failed: %s\n", snd_strerror (rtn)); return -1; } memset (&pp, 0, sizeof (pp)); pp.mode = SND_PCM_MODE_BLOCK; pp.channel = SND_PCM_CHANNEL_CAPTURE; pp.start_mode = SND_PCM_START_DATA; pp.stop_mode = SND_PCM_STOP_STOP; pp.buf.block.frag_size = pi.max_fragment_size; if (fragsize != -1) pp.buf.block.frag_size = fragsize; pp.buf.block.frags_max = -1; pp.buf.block.frags_min = 1; pp.format.interleave = 1; pp.format.rate = mSampleRate; pp.format.voices = mSampleChannels; if (mSampleBits == 8) pp.format.format = SND_PCM_SFMT_U8; else pp.format.format = SND_PCM_SFMT_S16_LE; if ((rtn = snd_pcm_plugin_params (pcm_handle, &pp)) < 0) { fprintf (stderr, "snd_pcm_plugin_params failed: %s\n", snd_strerror (rtn)); return -1; } if ((rtn = snd_pcm_plugin_prepare (pcm_handle, SND_PCM_CHANNEL_CAPTURE)) < 0) fprintf (stderr, "snd_pcm_plugin_prepare failed: %s\n", snd_strerror (rtn)); memset (&setup, 0, sizeof (setup)); memset (&group, 0, sizeof (group)); setup.channel = SND_PCM_CHANNEL_CAPTURE; setup.mixer_gid = &group.gid; if ((rtn = snd_pcm_plugin_setup (pcm_handle, &setup)) < 0) { fprintf (stderr, "snd_pcm_plugin_setup failed: %s\n", snd_strerror (rtn)); return -1; } printf ("Format %s \n", snd_pcm_get_format_name (setup.format.format)); printf ("Frag Size %d \n", setup.buf.block.frag_size); printf ("Rate %d \n", setup.format.rate); bsize = setup.buf.block.frag_size; if (group.gid.name[0] == 0) { printf ("Mixer Pcm Group [%s] Not Set \n", group.gid.name); printf ("***>>>> Input Gain Controls Disabled <<<<*** \n"); } else printf ("Mixer Pcm Group [%s]\n", group.gid.name); if ((rtn = snd_mixer_open (&mixer_handle, card, setup.mixer_device)) < 0) { fprintf (stderr, "snd_mixer_open failed: %s\n", snd_strerror (rtn)); return -1; } mSampleBfr1 = malloc (bsize); FD_ZERO (&rfds); n = 1; while (N < mSamples && n > 0) { FD_SET (STDIN_FILENO, &rfds); FD_SET (snd_mixer_file_descriptor (mixer_handle), &rfds); FD_SET (snd_pcm_file_descriptor (pcm_handle, SND_PCM_CHANNEL_CAPTURE), &rfds); rtn = max (snd_mixer_file_descriptor (mixer_handle), snd_pcm_file_descriptor (pcm_handle, SND_PCM_CHANNEL_CAPTURE)); if (select (rtn + 1, &rfds, NULL, NULL, NULL) == -1) return err ("select"); if (FD_ISSET (STDIN_FILENO, &rfds)) { dev_raw (fileno (stdin)); c = getc (stdin); dev_unraw (fileno (stdin)); if (c != EOF) { if (group.gid.name[0] != 0) { if ((rtn = snd_mixer_group_read (mixer_handle, &group)) < 0) fprintf (stderr, "snd_mixer_group_read failed: %s\n", snd_strerror (rtn)); switch (c) { case 'q': group.volume.names.front_left += 1; break; case 'a': group.volume.names.front_left -= 1; break; case 'w': group.volume.names.front_left += 1; group.volume.names.front_right += 1; break; case 's': group.volume.names.front_left -= 1; group.volume.names.front_right -= 1; break; case 'e': group.volume.names.front_right += 1; break; case 'd': group.volume.names.front_right -= 1; break; } if (group.volume.names.front_left > group.max) group.volume.names.front_left = group.max; if (group.volume.names.front_left < group.min) group.volume.names.front_left = group.min; if (group.volume.names.front_right > group.max) group.volume.names.front_right = group.max; if (group.volume.names.front_right < group.min) group.volume.names.front_right = group.min; if ((rtn = snd_mixer_group_write (mixer_handle, &group)) < 0) fprintf (stderr, "snd_mixer_group_write failed: %s\n", snd_strerror (rtn)); printf ("Volume Now at %d:%d \n", 100 * (group.volume.names.front_left - group.min) / (group.max - group.min), 100 * (group.volume.names.front_right - group.min) / (group.max - group.min)); } } else exit (0); } if (FD_ISSET (snd_mixer_file_descriptor (mixer_handle), &rfds)) { snd_mixer_callbacks_t callbacks = { 0, 0, 0, 0 }; snd_mixer_read (mixer_handle, &callbacks); } if (FD_ISSET (snd_pcm_file_descriptor (pcm_handle, SND_PCM_CHANNEL_CAPTURE), &rfds)) { snd_pcm_channel_status_t status; int read = 0; read = snd_pcm_plugin_read (pcm_handle, mSampleBfr1, bsize); if (verbose) printf ("bytes read = %d \n", read); if (read < n) { memset (&status, 0, sizeof (status)); status.channel = SND_PCM_CHANNEL_CAPTURE; if (snd_pcm_plugin_status (pcm_handle, &status) < 0) { fprintf (stderr, "overrun: capture channel status error\n"); exit (1); } if (status.status == SND_PCM_STATUS_READY || status.status == SND_PCM_STATUS_OVERRUN) { if (snd_pcm_plugin_prepare (pcm_handle, SND_PCM_CHANNEL_CAPTURE) < 0) { fprintf (stderr, "overrun: capture channel prepare error\n"); exit (1); } } } fwrite (mSampleBfr1, 1, read, file1); N += read; } } n = snd_pcm_plugin_flush (pcm_handle, SND_PCM_CHANNEL_CAPTURE); rtn = snd_mixer_close (mixer_handle); rtn = snd_pcm_close (pcm_handle); fclose (file1); return (0); }