int main(int argc, char *argv[]) { writei_func = snd_pcm_writei; int err; char *pcm_name = "default"; snd_pcm_info_t *info; snd_pcm_info_alloca(&info); stream = SND_PCM_STREAM_PLAYBACK; err = snd_pcm_open(&handle, pcm_name, stream, open_mode); if (err < 0) { // error(_("audio open error: %s"), snd_strerror(err)); return 1; } if ((err = snd_pcm_info(handle, info)) < 0) { // error(_("info error: %s"), snd_strerror(err)); return 1; } snd_pcm_nonblock(handle, 0); printf("set_params!!\n"); // set_params(); //playbackv(&argv[1], argc0); printf("playback!!\n"); playback(argv[1]); return 0; }
int do_play(char* file_name) { char *pcm_name = "default"; int tmp, err, c; snd_pcm_info_t *info; snd_pcm_info_alloca(&info); err = snd_output_stdio_attach(&log, stderr, 0); assert(err >= 0); stream = SND_PCM_STREAM_PLAYBACK; chunk_size = -1; rhwparams.format = DEFAULT_FORMAT; rhwparams.rate = DEFAULT_SPEED; rhwparams.channels = 1; err = snd_pcm_open(&handle, pcm_name, stream, open_mode); if (err < 0) { error(_("audio open error: %s"), snd_strerror(err)); return 1; } if ((err = snd_pcm_info(handle, info)) < 0) { error(_("info error: %s"), snd_strerror(err)); return 1; } if (nonblock) { err = snd_pcm_nonblock(handle, 1); if (err < 0) { error(_("nonblock setting error: %s"), snd_strerror(err)); return 1; } } chunk_size = 1024; hwparams = rhwparams; audiobuf = (u_char *)malloc(1024); if (audiobuf == NULL) { error(_("not enough memory")); return 1; } signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); signal(SIGABRT, signal_handler); playback(file_name); snd_pcm_close(handle); free(audiobuf); snd_output_close(log); snd_config_update_free_global(); return EXIT_SUCCESS; }
static int snd_pcm_plug_info(snd_pcm_t *pcm, snd_pcm_info_t *info) { snd_pcm_plug_t *plug = pcm->private_data; snd_pcm_t *slave = plug->req_slave; int err; if ((err = snd_pcm_info(slave, info)) < 0) return err; return 0; }
static void DumpDevice (vlc_object_t *obj, snd_pcm_t *pcm) { snd_pcm_info_t *info; Dump (obj, " ", snd_pcm_dump, pcm); snd_pcm_info_alloca (&info); if (snd_pcm_info (pcm, info) == 0) { msg_Dbg (obj, " device name : %s", snd_pcm_info_get_name (info)); msg_Dbg (obj, " device ID : %s", snd_pcm_info_get_id (info)); msg_Dbg (obj, " subdevice name: %s", snd_pcm_info_get_subdevice_name (info)); } }
/*---------------------------------------------------------------------------- ** ALSA_AddCommonDevice ** ** Perform Alsa initialization common to both capture and playback ** ** Side Effect: ww->pcname and ww->ctlname may need to be freed. ** ** Note: this was originally coded by using snd_pcm_name(pcm), until ** I discovered that with at least one version of alsa lib, ** the use of a pcm named default:0 would cause snd_pcm_name() to fail. ** So passing the name in is logically extraneous. Sigh. */ static int ALSA_AddCommonDevice(snd_ctl_t *ctl, snd_pcm_t *pcm, const char *pcmname, WINE_WAVEDEV *ww) { snd_pcm_info_t *infop; int rc; infop = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, snd_pcm_info_sizeof() ); if ((rc = snd_pcm_info(pcm, infop)) < 0) { HeapFree( GetProcessHeap(), 0, infop ); return rc; } if (pcm && pcmname) ww->pcmname = ALSA_strdup(pcmname); else { HeapFree( GetProcessHeap(), 0, infop ); return -1; } if (ctl && snd_ctl_name(ctl)) ww->ctlname = ALSA_strdup(snd_ctl_name(ctl)); strcpy(ww->interface_name, "winealsa: "); memcpy(ww->interface_name + strlen(ww->interface_name), ww->pcmname, min(strlen(ww->pcmname), sizeof(ww->interface_name) - strlen("winealsa: "))); strcpy(ww->ds_desc.szDrvname, "winealsa.drv"); memcpy(ww->ds_desc.szDesc, snd_pcm_info_get_name(infop), min( (sizeof(ww->ds_desc.szDesc) - 1), strlen(snd_pcm_info_get_name(infop))) ); ww->ds_caps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN; ww->ds_caps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX; ww->ds_caps.dwPrimaryBuffers = 1; HeapFree( GetProcessHeap(), 0, infop ); return 0; }
gchar * gst_alsa_find_device_name (GstObject * obj, const gchar * device, snd_pcm_t * handle, snd_pcm_stream_t stream) { gchar *ret = NULL; if (device != NULL) { gchar *dev, *comma; gint devnum; GST_LOG_OBJECT (obj, "Trying to get device name from string '%s'", device); /* only want name:card bit, but not devices and subdevices */ dev = g_strdup (device); if ((comma = strchr (dev, ','))) { *comma = '\0'; devnum = atoi (comma + 1); ret = gst_alsa_find_device_name_no_handle (obj, dev, devnum, stream); } g_free (dev); } if (ret == NULL && handle != NULL) { snd_pcm_info_t *info; GST_LOG_OBJECT (obj, "Trying to get device name from open handle"); snd_pcm_info_malloc (&info); snd_pcm_info (handle, info); ret = g_strdup (snd_pcm_info_get_name (info)); snd_pcm_info_free (info); } GST_LOG_OBJECT (obj, "Device name for device '%s': %s", GST_STR_NULL (device), GST_STR_NULL (ret)); return ret; }
void CAESinkALSA::EnumerateDevice(AEDeviceInfoList &list, const std::string &device, const std::string &description, snd_config_t *config) { snd_pcm_t *pcmhandle = NULL; if (!OpenPCMDevice(device, "", ALSA_MAX_CHANNELS, &pcmhandle, config)) return; snd_pcm_info_t *pcminfo; snd_pcm_info_alloca(&pcminfo); memset(pcminfo, 0, snd_pcm_info_sizeof()); int err = snd_pcm_info(pcmhandle, pcminfo); if (err < 0) { CLog::Log(LOGINFO, "CAESinkALSA - Unable to get pcm_info for \"%s\"", device.c_str()); snd_pcm_close(pcmhandle); } int cardNr = snd_pcm_info_get_card(pcminfo); CAEDeviceInfo info; info.m_deviceName = device; info.m_deviceType = AEDeviceTypeFromName(device); if (cardNr >= 0) { /* "HDA NVidia", "HDA Intel", "HDA ATI HDMI", "SB Live! 24-bit External", ... */ char *cardName; if (snd_card_get_name(cardNr, &cardName) == 0) info.m_displayName = cardName; if (info.m_deviceType == AE_DEVTYPE_HDMI && info.m_displayName.size() > 5 && info.m_displayName.substr(info.m_displayName.size()-5) == " HDMI") { /* We already know this is HDMI, strip it */ info.m_displayName.erase(info.m_displayName.size()-5); } /* "CONEXANT Analog", "USB Audio", "HDMI 0", "ALC889 Digital" ... */ std::string pcminfoName = snd_pcm_info_get_name(pcminfo); /* * Filter "USB Audio", in those cases snd_card_get_name() is more * meaningful already */ if (pcminfoName != "USB Audio") info.m_displayNameExtra = pcminfoName; if (info.m_deviceType == AE_DEVTYPE_HDMI) { /* replace, this was likely "HDMI 0" */ info.m_displayNameExtra = "HDMI"; int dev = snd_pcm_info_get_device(pcminfo); if (dev >= 0) { /* lets see if we can get ELD info */ snd_ctl_t *ctlhandle; std::stringstream sstr; sstr << "hw:" << cardNr; std::string strHwName = sstr.str(); if (snd_ctl_open_lconf(&ctlhandle, strHwName.c_str(), 0, config) == 0) { snd_hctl_t *hctl; if (snd_hctl_open_ctl(&hctl, ctlhandle) == 0) { snd_hctl_load(hctl); bool badHDMI = false; if (!GetELD(hctl, dev, info, badHDMI)) CLog::Log(LOGDEBUG, "CAESinkALSA - Unable to obtain ELD information for device \"%s\" (not supported by device, or kernel older than 3.2)", device.c_str()); /* snd_hctl_close also closes ctlhandle */ snd_hctl_close(hctl); if (badHDMI) { /* * Warn about disconnected devices, but keep them enabled * Detection can go wrong on Intel, Nvidia and on all * AMD (fglrx) hardware, so it is not safe to close those * handles */ CLog::Log(LOGDEBUG, "CAESinkALSA - HDMI device \"%s\" may be unconnected (no ELD data)", device.c_str()); } } else { snd_ctl_close(ctlhandle); } } } } else if (info.m_deviceType == AE_DEVTYPE_IEC958) { /* append instead of replace, pcminfoName is useful for S/PDIF */ if (!info.m_displayNameExtra.empty()) info.m_displayNameExtra += ' '; info.m_displayNameExtra += "S/PDIF"; } else if (info.m_displayNameExtra.empty()) { /* for USB audio, it gets a bit confusing as there is * - "SB Live! 24-bit External" * - "SB Live! 24-bit External, S/PDIF" * so add "Analog" qualifier to the first one */ info.m_displayNameExtra = "Analog"; } /* "default" is a device that will be used for all inputs, while * "@" will be mangled to front/default/surroundXX as necessary */ if (device == "@" || device == "default") { /* Make it "Default (whatever)" */ info.m_displayName = "Default (" + info.m_displayName + (info.m_displayNameExtra.empty() ? "" : " " + info.m_displayNameExtra + ")"); info.m_displayNameExtra = ""; } } else { /* virtual devices: "default", "pulse", ... */ /* description can be e.g. "PulseAudio Sound Server" - for hw devices it is * normally uninteresting, like "HDMI Audio Output" or "Default Audio Device", * so we only use it for virtual devices that have no better display name */ info.m_displayName = description; } snd_pcm_hw_params_t *hwparams; snd_pcm_hw_params_alloca(&hwparams); memset(hwparams, 0, snd_pcm_hw_params_sizeof()); /* ensure we can get a playback configuration for the device */ if (snd_pcm_hw_params_any(pcmhandle, hwparams) < 0) { CLog::Log(LOGINFO, "CAESinkALSA - No playback configurations available for device \"%s\"", device.c_str()); snd_pcm_close(pcmhandle); return; } /* detect the available sample rates */ for (unsigned int *rate = ALSASampleRateList; *rate != 0; ++rate) if (snd_pcm_hw_params_test_rate(pcmhandle, hwparams, *rate, 0) >= 0) info.m_sampleRates.push_back(*rate); /* detect the channels available */ int channels = 0; for (int i = ALSA_MAX_CHANNELS; i >= 1; --i) { /* Reopen the device if needed on the special "surroundXX" cases */ if (info.m_deviceType == AE_DEVTYPE_PCM && (i == 8 || i == 6 || i == 4)) OpenPCMDevice(device, "", i, &pcmhandle, config); if (snd_pcm_hw_params_test_channels(pcmhandle, hwparams, i) >= 0) { channels = i; break; } } if (device == "default" && channels == 2) { /* This looks like the ALSA standard default stereo dmix device, we * probably want to use "@" instead to get surroundXX. */ snd_pcm_close(pcmhandle); EnumerateDevice(list, "@", description, config); return; } CAEChannelInfo alsaChannels; for (int i = 0; i < channels; ++i) { if (!info.m_channels.HasChannel(ALSAChannelMap[i])) info.m_channels += ALSAChannelMap[i]; alsaChannels += ALSAChannelMap[i]; } /* remove the channels from m_channels that we cant use */ info.m_channels.ResolveChannels(alsaChannels); /* detect the PCM sample formats that are available */ for (enum AEDataFormat i = AE_FMT_MAX; i > AE_FMT_INVALID; i = (enum AEDataFormat)((int)i - 1)) { if (AE_IS_RAW(i) || i == AE_FMT_MAX) continue; snd_pcm_format_t fmt = AEFormatToALSAFormat(i); if (fmt == SND_PCM_FORMAT_UNKNOWN) continue; if (snd_pcm_hw_params_test_format(pcmhandle, hwparams, fmt) >= 0) info.m_dataFormats.push_back(i); } snd_pcm_close(pcmhandle); list.push_back(info); }
static int aplaypop_open(void) { int err; snd_pcm_t *handle; if (pcm_handle) return 0; snd_pcm_info_t *info; snd_pcm_info_alloca(&info); snd_output_t *log; err = snd_output_stdio_attach(&log, stderr, 0); assert(err == 0); err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0); if (err != 0) { fprintf(stderr, "snd_pcm_open(): %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } err = snd_pcm_nonblock(handle, 0); if (err != 0) { fprintf(stderr, "snd_pcm_nonblock(): %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } err = snd_pcm_info(handle, info); if (err != 0) { fprintf(stderr, "snd_pcm_info(): %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } // DOESN'T WORK! err = snd_pcm_set_params(handle, SND_PCM_FORMAT_S16_LE, SND_PCM_ACCESS_RW_INTERLEAVED, CHANNELS, RATE, 1, 50000); if (err != 0) { fprintf(stderr, "snd_pcm_set_params(): %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } // RIGHT WAY: snd_pcm_hw_params_t *hwparams; snd_pcm_sw_params_t *swparams; snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE; unsigned int channels = CHANNELS; unsigned int rate = RATE; snd_pcm_hw_params_alloca(&hwparams); snd_pcm_sw_params_alloca(&swparams); err = snd_pcm_hw_params_any(handle, hwparams); if (err != 0) { fprintf(stderr, "Broken configuration for this PCM: %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); if (err != 0) { fprintf(stderr, "snd_pcm_hw_params_set_access(): %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } err = snd_pcm_hw_params_set_format(handle, hwparams, format); if (err != 0) { fprintf(stderr, "snd_pcm_hw_params_set_format(): %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } err = snd_pcm_hw_params_set_channels(handle, hwparams, channels); if (err != 0) { fprintf(stderr, "snd_pcm_hw_params_set_channels(): %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &rate, 0); if (err != 0) { fprintf(stderr, "snd_pcm_hw_params_set_rate_near(): %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } /* unsigned buffer_time = 0; snd_pcm_uframes_t buffer_frames = 0; if (buffer_time == 0 && buffer_frames == 0) { err = snd_pcm_hw_params_get_buffer_time_max(hwparams, &buffer_time, 0); assert(err == 0); if (buffer_time > 500000) buffer_time = 500000; } unsigned period_time = 0; snd_pcm_uframes_t period_frames = 0; if (period_time == 0 && period_frames == 0) { if (buffer_time > 0) period_time = buffer_time / 4; else period_frames = buffer_frames / 4; } if (period_time > 0) err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, 0); else err = snd_pcm_hw_params_set_period_size_near(handle, hwparams, &period_frames, 0); assert(err == 0); if (buffer_time > 0) err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, 0); else err = snd_pcm_hw_params_set_buffer_size_near(handle, hwparams, &buffer_frames); assert(err == 0); int monotonic = snd_pcm_hw_params_is_monotonic(hwparams); int can_pause = snd_pcm_hw_params_can_pause(hwparams); */ err = snd_pcm_hw_params(handle, hwparams); if (err != 0) { fprintf(stderr, "snd_pcm_hw_params(): %s\n", snd_strerror(err)); snd_pcm_hw_params_dump(hwparams, log); exit(EXIT_FAILURE); } snd_pcm_uframes_t chunk_size = 0; snd_pcm_hw_params_get_period_size(hwparams, &chunk_size, 0); snd_pcm_uframes_t buffer_size; snd_pcm_hw_params_get_buffer_size(hwparams, &buffer_size); if (chunk_size == buffer_size) { fprintf(stderr, "Can't use period equal to buffer size (%lu == %lu)", chunk_size, buffer_size); exit(EXIT_FAILURE); } snd_pcm_sw_params_current(handle, swparams); err = snd_pcm_sw_params_set_avail_min(handle, swparams, chunk_size); assert(err == 0); /* round up to closest transfer boundary */ int start_delay = 0; snd_pcm_uframes_t start_threshold; if (start_delay <= 0) start_threshold = buffer_size + (double) rate * start_delay / 1000000; else start_threshold = (double) rate * start_delay / 1000000; start_threshold = start_threshold < 1 ? 1 : start_threshold > buffer_size ? buffer_size : start_threshold; err = snd_pcm_sw_params_set_start_threshold(handle, swparams, start_threshold); assert(err == 0); int stop_delay = 0; snd_pcm_uframes_t stop_threshold; if (stop_delay <= 0) stop_threshold = buffer_size + (double) rate * stop_delay / 1000000; else stop_threshold = (double) rate * stop_delay / 1000000; err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, stop_threshold); assert(err == 0); err = snd_pcm_sw_params(handle, swparams); if (err != 0) { fprintf(stderr, "snd_pcm_sw_params(): %s\n", snd_strerror(err)); snd_pcm_sw_params_dump(swparams, log); exit(EXIT_FAILURE); } // END OF THE RIGHT WAY // snd_pcm_dump(handle, log); size_t bits_per_sample = snd_pcm_format_physical_width(format); size_t bits_per_frame = bits_per_sample * channels; size_t chunk_bytes = chunk_size * bits_per_frame / 8; //audiobuf = realloc(audiobuf, chunk_bytes); fprintf(stderr, "%s: %s, Rate %d Hz, Channels=%u\n", snd_pcm_format_name(format), snd_pcm_format_description(format), rate, channels); fprintf(stderr, " bits_per_sample=%u, bits_per_frame=%u, chunk_bytes=%u\n", bits_per_sample, bits_per_frame, chunk_bytes); frame_bytes = bits_per_frame / 8; pcm_handle = handle; return 0; }
int run(char *filename) { capture_stop = 0; char *pcm_name = "default"; int tmp, err; snd_pcm_info_t *info; snd_pcm_info_alloca(&info); err = snd_output_stdio_attach(&log, stderr, 0); assert(err >= 0); file_type = FORMAT_DEFAULT; stream = SND_PCM_STREAM_CAPTURE; file_type = FORMAT_WAVE; command = "arecord"; start_delay = 1; chunk_size = -1; rhwparams.format = DEFAULT_FORMAT; rhwparams.rate = DEFAULT_SPEED; rhwparams.channels = 1; file_type = FORMAT_WAVE; // cdr: // rhwparams.format = SND_PCM_FORMAT_S16_BE; rhwparams.format = file_type == FORMAT_AU ? SND_PCM_FORMAT_S16_BE : SND_PCM_FORMAT_S16_LE; rhwparams.rate = 44100; rhwparams.channels = 2; err = snd_pcm_open(&handle, pcm_name, stream, open_mode); if (err < 0) { error(_("audio open error: %s"), snd_strerror(err)); return 1; } if ((err = snd_pcm_info(handle, info)) < 0) { error(_("info error: %s"), snd_strerror(err)); return 1; } if (nonblock) { err = snd_pcm_nonblock(handle, 1); if (err < 0) { error(_("nonblock setting error: %s"), snd_strerror(err)); return 1; } } chunk_size = 1024; hwparams = rhwparams; audiobuf = (u_char *)malloc(1024); if (audiobuf == NULL) { error(_("not enough memory")); return 1; } writei_func = snd_pcm_writei; readi_func = snd_pcm_readi; writen_func = snd_pcm_writen; readn_func = snd_pcm_readn; //signal(SIGINT, signal_handler); //signal(SIGTERM, signal_handler); //signal(SIGABRT, signal_handler); capture(filename); if (fmt_rec_table[file_type].end) { fmt_rec_table[file_type].end(fd); fd = -1; } stream = -1; if (fd > 1) { close(fd); fd = -1; } if (handle) { snd_pcm_close(handle); handle = NULL; } //snd_pcm_close(handle); //free(audiobuf); //snd_output_close(log); //snd_config_update_free_global(); return EXIT_SUCCESS; }
// for each ALSA device, call iterator. userData is passed to the iterator // returns total number of iterations int iteratePCMDevices(DeviceIteratorPtr iterator, void* userData) { int count = 0; int subdeviceCount; int card, dev, subDev; char devname[16]; int err; snd_ctl_t *handle; snd_pcm_t *pcm; snd_pcm_info_t* pcminfo; snd_ctl_card_info_t *cardinfo, *defcardinfo = NULL; UINT32 deviceID; int doContinue = TRUE; snd_pcm_info_malloc(&pcminfo); snd_ctl_card_info_malloc(&cardinfo); // 1st try "default" device err = snd_pcm_open(&pcm, ALSA_DEFAULT_DEVICE_NAME, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); if (err < 0) { // try with the other direction err = snd_pcm_open(&pcm, ALSA_DEFAULT_DEVICE_NAME, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK); } if (err < 0) { ERROR1("ERROR: snd_pcm_open (\"default\"): %s\n", snd_strerror(err)); } else { err = snd_pcm_info(pcm, pcminfo); snd_pcm_close(pcm); if (err < 0) { ERROR1("ERROR: snd_pcm_info (\"default\"): %s\n", snd_strerror(err)); } else { // try to get card info card = snd_pcm_info_get_card(pcminfo); if (card >= 0) { sprintf(devname, ALSA_HARDWARE_CARD, card); if (snd_ctl_open(&handle, devname, SND_CTL_NONBLOCK) >= 0) { if (snd_ctl_card_info(handle, cardinfo) >= 0) { defcardinfo = cardinfo; } snd_ctl_close(handle); } } // call callback function for the device if (iterator != NULL) { doContinue = (*iterator)(ALSA_DEFAULT_DEVICE_ID, pcminfo, defcardinfo, userData); } count++; } } // iterate cards card = -1; while (doContinue) { if (snd_card_next(&card) < 0) { break; } if (card < 0) { break; } sprintf(devname, ALSA_HARDWARE_CARD, card); TRACE1("Opening alsa device \"%s\"...\n", devname); err = snd_ctl_open(&handle, devname, SND_CTL_NONBLOCK); if (err < 0) { ERROR2("ERROR: snd_ctl_open, card=%d: %s\n", card, snd_strerror(err)); } else { err = snd_ctl_card_info(handle, cardinfo); if (err < 0) { ERROR2("ERROR: snd_ctl_card_info, card=%d: %s\n", card, snd_strerror(err)); } else { dev = -1; while (doContinue) { if (snd_ctl_pcm_next_device(handle, &dev) < 0) { ERROR0("snd_ctl_pcm_next_device\n"); } if (dev < 0) { break; } snd_pcm_info_set_device(pcminfo, dev); snd_pcm_info_set_subdevice(pcminfo, 0); snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_PLAYBACK); err = snd_ctl_pcm_info(handle, pcminfo); if (err == -ENOENT) { // try with the other direction snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_CAPTURE); err = snd_ctl_pcm_info(handle, pcminfo); } if (err < 0) { if (err != -ENOENT) { ERROR2("ERROR: snd_ctl_pcm_info, card=%d: %s", card, snd_strerror(err)); } } else { subdeviceCount = needEnumerateSubdevices(ALSA_PCM) ? snd_pcm_info_get_subdevices_count(pcminfo) : 1; if (iterator!=NULL) { for (subDev = 0; subDev < subdeviceCount; subDev++) { deviceID = encodeDeviceID(card, dev, subDev); doContinue = (*iterator)(deviceID, pcminfo, cardinfo, userData); count++; if (!doContinue) { break; } } } else { count += subdeviceCount; } } } // of while(doContinue) } snd_ctl_close(handle); } } snd_ctl_card_info_free(cardinfo); snd_pcm_info_free(pcminfo); return count; }
/*----------------------------------------------------------------------- Initialise ALSA and sets the sampling rate and audio format. --------------------------------------------------------------------------*/ snd_pcm_t* alsa_init() { char *pcm_name = "default"; int tmp, err, c; int do_device_list = 0, do_pcm_list = 0; snd_pcm_info_t *info; snd_pcm_info_alloca(&info); err = snd_output_stdio_attach(&log, stderr, 0); assert(err >= 0); stream = SND_PCM_STREAM_PLAYBACK; rhwparams.format = DEFAULT_FORMAT; rhwparams.rate = DEFAULT_SPEED; rhwparams.channels = 1; file_type = FORMAT_RAW; rhwparams.format = SND_PCM_FORMAT_S16_LE; rhwparams.rate = 16000; rhwparams.channels = 1; err = snd_pcm_open(&handle, pcm_name, stream, open_mode); if (err < 0) { error("audio open error: %s", snd_strerror(err)); return 1; } if ((err = snd_pcm_info(handle, info)) < 0) { error("info error: %s", snd_strerror(err)); return 1; } if (nonblock) { err = snd_pcm_nonblock(handle, 1); if (err < 0) { error("nonblock setting error: %s", snd_strerror(err)); return 1; } } chunk_size = 1024; hwparams = rhwparams; audiobuf = (u_char *)malloc(1024); if (audiobuf == NULL) { error("not enough memory"); return 1; } if (mmap_flag) { writei_func = snd_pcm_mmap_writei; readi_func = snd_pcm_mmap_readi; writen_func = snd_pcm_mmap_writen; readn_func = snd_pcm_mmap_readn; } else { writei_func = snd_pcm_writei; readi_func = snd_pcm_readi; writen_func = snd_pcm_writen; readn_func = snd_pcm_readn; } signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); signal(SIGABRT, signal_handler); return handle; }
int snd_pcm_generic_info(snd_pcm_t *pcm, snd_pcm_info_t * info) { snd_pcm_generic_t *generic = pcm->private_data; return snd_pcm_info(generic->slave, info); }
/* open & setup audio device return: 1=success 0=fail */ static int init(int rate_hz, int channels, int format, int flags) { int err; int cards = -1; snd_pcm_channel_params_t params; snd_pcm_channel_setup_t setup; snd_pcm_info_t info; snd_pcm_channel_info_t chninfo; mp_msg(MSGT_AO, MSGL_INFO, MSGTR_AO_ALSA5_InitInfo, rate_hz, channels, af_fmt2str_short(format)); alsa_handler = NULL; mp_msg(MSGT_AO, MSGL_V, "alsa-init: compiled for ALSA-%s (%d)\n", SND_LIB_VERSION_STR, SND_LIB_VERSION); if ((cards = snd_cards()) < 0) { mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_SoundCardNotFound); return 0; } ao_data.format = format; ao_data.channels = channels; ao_data.samplerate = rate_hz; ao_data.bps = ao_data.samplerate*ao_data.channels; ao_data.outburst = OUTBURST; ao_data.buffersize = 16384; memset(&alsa_format, 0, sizeof(alsa_format)); switch (format) { case AF_FORMAT_S8: alsa_format.format = SND_PCM_SFMT_S8; break; case AF_FORMAT_U8: alsa_format.format = SND_PCM_SFMT_U8; break; case AF_FORMAT_U16_LE: alsa_format.format = SND_PCM_SFMT_U16_LE; break; case AF_FORMAT_U16_BE: alsa_format.format = SND_PCM_SFMT_U16_BE; break; case AF_FORMAT_AC3_LE: case AF_FORMAT_S16_LE: alsa_format.format = SND_PCM_SFMT_S16_LE; break; case AF_FORMAT_AC3_BE: case AF_FORMAT_S16_BE: alsa_format.format = SND_PCM_SFMT_S16_BE; break; default: alsa_format.format = SND_PCM_SFMT_MPEG; break; } switch(alsa_format.format) { case SND_PCM_SFMT_S16_LE: case SND_PCM_SFMT_U16_LE: ao_data.bps *= 2; break; case -1: mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_InvalidFormatReq,af_fmt2str_short(format)); return 0; default: break; } switch(rate_hz) { case 8000: alsa_rate = SND_PCM_RATE_8000; break; case 11025: alsa_rate = SND_PCM_RATE_11025; break; case 16000: alsa_rate = SND_PCM_RATE_16000; break; case 22050: alsa_rate = SND_PCM_RATE_22050; break; case 32000: alsa_rate = SND_PCM_RATE_32000; break; case 44100: alsa_rate = SND_PCM_RATE_44100; break; case 48000: alsa_rate = SND_PCM_RATE_48000; break; case 88200: alsa_rate = SND_PCM_RATE_88200; break; case 96000: alsa_rate = SND_PCM_RATE_96000; break; case 176400: alsa_rate = SND_PCM_RATE_176400; break; case 192000: alsa_rate = SND_PCM_RATE_192000; break; default: alsa_rate = SND_PCM_RATE_CONTINUOUS; break; } alsa_format.rate = ao_data.samplerate; alsa_format.voices = ao_data.channels; alsa_format.interleave = 1; if ((err = snd_pcm_open(&alsa_handler, 0, 0, SND_PCM_OPEN_PLAYBACK)) < 0) { mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_PlayBackError, snd_strerror(err)); return 0; } if ((err = snd_pcm_info(alsa_handler, &info)) < 0) { mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_PcmInfoError, snd_strerror(err)); return 0; } mp_msg(MSGT_AO, MSGL_INFO, MSGTR_AO_ALSA5_SoundcardsFound, cards, info.name); if (info.flags & SND_PCM_INFO_PLAYBACK) { memset(&chninfo, 0, sizeof(chninfo)); chninfo.channel = SND_PCM_CHANNEL_PLAYBACK; if ((err = snd_pcm_channel_info(alsa_handler, &chninfo)) < 0) { mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_PcmChanInfoError, snd_strerror(err)); return 0; } #ifndef __QNX__ if (chninfo.buffer_size) ao_data.buffersize = chninfo.buffer_size; #endif mp_msg(MSGT_AO, MSGL_V, "alsa-init: setting preferred buffer size from driver: %d bytes\n", ao_data.buffersize); } memset(¶ms, 0, sizeof(params)); params.channel = SND_PCM_CHANNEL_PLAYBACK; params.mode = SND_PCM_MODE_STREAM; params.format = alsa_format; params.start_mode = SND_PCM_START_DATA; params.stop_mode = SND_PCM_STOP_ROLLOVER; params.buf.stream.queue_size = ao_data.buffersize; params.buf.stream.fill = SND_PCM_FILL_NONE; if ((err = snd_pcm_channel_params(alsa_handler, ¶ms)) < 0) { mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_CantSetParms, snd_strerror(err)); return 0; } memset(&setup, 0, sizeof(setup)); setup.channel = SND_PCM_CHANNEL_PLAYBACK; setup.mode = SND_PCM_MODE_STREAM; setup.format = alsa_format; setup.buf.stream.queue_size = ao_data.buffersize; setup.msbits_per_sample = ao_data.bps; if ((err = snd_pcm_channel_setup(alsa_handler, &setup)) < 0) { mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_CantSetChan, snd_strerror(err)); return 0; } if ((err = snd_pcm_channel_prepare(alsa_handler, SND_PCM_CHANNEL_PLAYBACK)) < 0) { mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_ChanPrepareError, snd_strerror(err)); return 0; } mp_msg(MSGT_AO, MSGL_INFO, "AUDIO: %d Hz/%d channels/%d bps/%d bytes buffer/%s\n", ao_data.samplerate, ao_data.channels, ao_data.bps, ao_data.buffersize, snd_pcm_get_format_name(alsa_format.format)); return 1; }
/* * General setup of the libasound audio mixer and pcm components. * Some of the settings are based on the format of the wav data. */ int setup_snd(const char * name) { int fragsize = -1; int num_frags = -1; int rtn; char *dev_name; if (NULL == name) { dev_name = "pcmPreferred"; } else { dev_name = (char *) name; } if ((rtn = snd_pcm_open_name(&pcm_handle, dev_name, SND_PCM_OPEN_PLAYBACK)) < 0) { snprintf(msg, MSG_SIZE, "snd_pcm_open_name failed: %s\n", snd_strerror(rtn)); show_dialog_message(msg); return FAILURE; } if ((rtn = snd_pcm_info(pcm_handle, &info)) < 0) { snprintf(msg, MSG_SIZE, "snd_pcm_info failed: %s\n", snd_strerror(rtn)); goto setup_failure; } card = info.card; /* 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) { snprintf(msg, MSG_SIZE, "snd_pcm_plugin_set_disable failed: %s\n", snd_strerror(rtn)); goto setup_failure; } memset(&pi, 0, sizeof(pi)); pi.channel = SND_PCM_CHANNEL_PLAYBACK; if ((rtn = snd_pcm_plugin_info(pcm_handle, &pi)) < 0) { snprintf(msg, MSG_SIZE, "snd_pcm_plugin_info failed: %s\n", snd_strerror(rtn)); goto setup_failure; } memset(&pp, 0, sizeof(pp)); pp.mode = SND_PCM_MODE_BLOCK; pp.channel = SND_PCM_CHANNEL_PLAYBACK; pp.start_mode = SND_PCM_START_FULL; 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 = num_frags; pp.buf.block.frags_min = 1; pp.format.interleave = 1; pp.format.rate = sample_rate; pp.format.voices = sample_channels; if (ENDIAN_LE16(wav_header.format_tag) == 6) pp.format.format = SND_PCM_SFMT_A_LAW; else if (ENDIAN_LE16(wav_header.format_tag) == 7) pp.format.format = SND_PCM_SFMT_MU_LAW; else if (sample_bits == 8) pp.format.format = SND_PCM_SFMT_U8; else if (sample_bits == 24) pp.format.format = SND_PCM_SFMT_S24; else pp.format.format = SND_PCM_SFMT_S16_LE; strcpy(pp.sw_mixer_subchn_name, "Wave playback channel"); if ((rtn = snd_pcm_plugin_params(pcm_handle, &pp)) < 0) { snprintf(msg, MSG_SIZE, "snd_pcm_plugin_params failed: %s\n", snd_strerror(rtn)); goto setup_failure; } if ((rtn = snd_pcm_plugin_prepare(pcm_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0) { snprintf(msg, MSG_SIZE, "snd_pcm_plugin_prepare failed: %s\n", snd_strerror(rtn)); goto setup_failure; } memset(&setup, 0, sizeof(setup)); memset(&group, 0, sizeof(group)); setup.channel = SND_PCM_CHANNEL_PLAYBACK; setup.mixer_gid = &group.gid; if ((rtn = snd_pcm_plugin_setup(pcm_handle, &setup)) < 0) { snprintf(msg, MSG_SIZE, "snd_pcm_plugin_setup failed: %s\n", snd_strerror(rtn)); goto setup_failure; } if (group.gid.name[0] == 0) { snprintf(msg, MSG_SIZE, "Mixer Pcm Group [%s] Not Set \n", group.gid.name); goto setup_failure; } if ((rtn = snd_mixer_open(&mixer_handle, card, setup.mixer_device)) < 0) { snprintf(msg, MSG_SIZE, "snd_mixer_open failed: %s\n", snd_strerror(rtn)); goto setup_failure; } char tmp[MSG_SIZE]; snprintf(msg, MSG_SIZE, "Format %s \n", snd_pcm_get_format_name(setup.format.format)); snprintf(tmp, MSG_SIZE, "Frag Size %d \n", setup.buf.block.frag_size); strlcat(msg, tmp, MSG_SIZE); snprintf(tmp, MSG_SIZE, "Total Frags %d \n", setup.buf.block.frags); strlcat(msg, tmp, MSG_SIZE); snprintf(tmp, MSG_SIZE, "Rate %d \n", setup.format.rate); strlcat(msg, tmp, MSG_SIZE); snprintf(tmp, MSG_SIZE, "Voices %d \n", setup.format.voices); strlcat(msg, tmp, MSG_SIZE); snprintf(tmp, MSG_SIZE, "Mixer Pcm Group [%s]\n", group.gid.name); strlcat(msg, tmp, MSG_SIZE); show_dialog_message(msg); return SUCCESS; setup_failure: show_dialog_message(msg); snd_pcm_close(pcm_handle); return FAILURE; }
static int alsa_setup(struct snd_format* f) { int err; snd_pcm_hw_params_t* hwparams; snd_pcm_sw_params_t* swparams; unsigned int alsa_buffer_time, alsa_period_time; snd_pcm_uframes_t alsa_buffer_size, alsa_period_size; free(outputf); outputf = snd_format_alloc(f->rate, f->channels); printf(" Opening device %s ... ", alsa_cb.pcm_device); if((err = snd_pcm_open(&alsa_pcm, alsa_cb.pcm_device, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) { printf("alsa_setup(): Failed to open pcm device (%s): %s\n", alsa_cb.pcm_device, snd_strerror(-err)); alsa_pcm = NULL; free(outputf); outputf = NULL; return -1; } /* doesn't care about non-blocking */ /* snd_pcm_nonblock(alsa_pcm, 0); */ if(0) { //debug snd_pcm_info_t* info; int alsa_card, alsa_device, alsa_subdevice; snd_pcm_info_alloca(&info); snd_pcm_info(alsa_pcm, info); alsa_card = snd_pcm_info_get_card(info); alsa_device = snd_pcm_info_get_device(info); alsa_subdevice = snd_pcm_info_get_subdevice(info); printf("Card %i, Device %i, Subdevice %i\n", alsa_card, alsa_device, alsa_subdevice); } snd_pcm_hw_params_alloca(&hwparams); if((err = snd_pcm_hw_params_any(alsa_pcm, hwparams)) < 0) { printf("alsa_setup(): No configuration available for " "playback: %s\n", snd_strerror(-err)); return -1; } if((err = snd_pcm_hw_params_set_access(alsa_pcm, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { printf("alsa_setup(): Cannot set direct write mode: %s\n", snd_strerror(-err)); return -1; } if((err = snd_pcm_hw_params_set_format(alsa_pcm, hwparams, outputf->format)) < 0) { printf("alsa_setup(): Sample format not " "available for playback: %s\n", snd_strerror(-err)); return -1; } if((err = snd_pcm_hw_params_set_channels_near(alsa_pcm, hwparams, &outputf->channels)) < 0) { printf ("alsa_setup(): snd_pcm_hw_params_set_channels_near failed: %s.\n", snd_strerror(-err)); return -1; } snd_pcm_hw_params_set_rate_near(alsa_pcm, hwparams, &outputf->rate, 0); if(outputf->rate == 0) { printf("alsa_setup(): No usable samplerate available.\n"); return -1; } outputf->sample_bits = snd_pcm_format_physical_width(outputf->format); outputf->bps = (outputf->rate * outputf->sample_bits * outputf->channels) >> 3; alsa_buffer_time = alsa_cb.buffer_time * 1000; if((err = snd_pcm_hw_params_set_buffer_time_near(alsa_pcm, hwparams, &alsa_buffer_time, 0)) < 0) { printf("alsa_setup(): Set buffer time failed: %s.\n", snd_strerror(-err)); return -1; } alsa_period_time = alsa_cb.period_time * 1000; if((err = snd_pcm_hw_params_set_period_time_near(alsa_pcm, hwparams, &alsa_period_time, 0)) < 0) { printf("alsa_setup(): Set period time failed: %s.\n", snd_strerror(-err)); return -1; } if(snd_pcm_hw_params(alsa_pcm, hwparams) < 0) { printf("alsa_setup(): Unable to install hw params\n"); return -1; } if((err = snd_pcm_hw_params_get_buffer_size(hwparams, &alsa_buffer_size)) < 0) { printf("alsa_setup(): snd_pcm_hw_params_get_buffer_size() " "failed: %s\n", snd_strerror(-err)); return -1; } if((err = snd_pcm_hw_params_get_period_size(hwparams, &alsa_period_size, 0)) < 0) { printf("alsa_setup(): snd_pcm_hw_params_get_period_size() " "failed: %s\n", snd_strerror(-err)); return -1; } snd_pcm_sw_params_alloca(&swparams); snd_pcm_sw_params_current(alsa_pcm, swparams); if((err = snd_pcm_sw_params_set_start_threshold(alsa_pcm, swparams, alsa_buffer_size - alsa_period_size) < 0)) printf("alsa_setup(): setting start " "threshold failed: %s\n", snd_strerror(-err)); if(snd_pcm_sw_params(alsa_pcm, swparams) < 0) { printf("alsa_setup(): Unable to install sw params\n"); return -1; } hw_buffer_size = snd_pcm_frames_to_bytes(alsa_pcm, alsa_buffer_size); hw_period_size = snd_pcm_frames_to_bytes(alsa_pcm, alsa_period_size); if(inputf->bps != outputf->bps) { int align = (inputf->sample_bits * inputf->channels) / 8; hw_buffer_size_in = ((u_int) hw_buffer_size * inputf->bps + outputf->bps / 2) / outputf->bps; hw_period_size_in = ((u_int) hw_period_size * inputf->bps + outputf->bps / 2) / outputf->bps; hw_buffer_size_in -= hw_buffer_size_in % align; hw_period_size_in -= hw_period_size_in % align; } else { hw_buffer_size_in = hw_buffer_size; hw_period_size_in = hw_period_size; } #if 0 printf("Device setup: buffer time: %i, size: %i.\n", alsa_buffer_time, hw_buffer_size); printf("Device setup: period time: %i, size: %i.\n", alsa_period_time, hw_period_size); printf("bits per sample: %i; frame size: %i; Bps: %i\n", snd_pcm_format_physical_width(outputf->format), snd_pcm_frames_to_bytes(alsa_pcm, 1), outputf->bps); #endif printf("success.\n"); return 0; }
int pcm_shm_cmd(volatile snd_pcm_shm_ctrl_t *ctrl) { snd_pcm_info((snd_pcm_info_t *) &ctrl->info); }