/*---------------------------------------------------------------------------- ** 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; }
static int handle_event(int hwdep_fd, snd_ctl_t *ctl) { snd_ctl_event_t *event; unsigned int mask; int err; snd_ctl_event_alloca(&event); err = snd_ctl_read(ctl, event); if (err < 0) { fprintf(stderr, "Cannot read event from ctl %s\n", snd_ctl_name(ctl)); return err; } if (snd_ctl_event_get_type(event) != SND_CTL_EVENT_ELEM) { return 0; } // Filter events mask = snd_ctl_event_elem_get_mask(event); if (mask & SND_CTL_EVENT_MASK_VALUE) { const char *event_name = snd_ctl_event_elem_get_name(event); if (!strcmp(event_name, HEADPHONE_SWITCH_NAME)) { // If headphones were plugged, mute LFE set_headphones_plugged(&headphones_plugged); if (headphones_plugged) { set_lfe_volume(hwdep_fd, 0); } } else if (!headphones_plugged && !strcmp(event_name, MASTER_VOLUME_NAME)) { // If headphones are unplugged and master volume changed, adjust LFE volume set_lfe_volume(hwdep_fd, get_master_volume()); } } return 0; }
/** * \brief get identifier of HCTL handle * \param hctl HCTL handle * \return ascii identifier of HCTL handle * * Returns the ASCII identifier of given HCTL handle. It's the same * identifier specified in snd_hctl_open(). */ const char *snd_hctl_name(snd_hctl_t *hctl) { assert(hctl); return snd_ctl_name(hctl->ctl); }
/*---------------------------------------------------------------------------- ** ALSA_ComputeCaps ** ** Given an ALSA PCM, figure out our HW CAPS structure info. ** ctl can be null, pcm is required, as is all output parms. ** */ static int ALSA_ComputeCaps(snd_ctl_t *ctl, snd_pcm_t *pcm, WORD *channels, DWORD *flags, DWORD *formats, DWORD *supports) { snd_pcm_hw_params_t *hw_params; snd_pcm_format_mask_t *fmask; snd_pcm_access_mask_t *acmask; unsigned int ratemin = 0; unsigned int ratemax = 0; unsigned int chmin = 0; unsigned int chmax = 0; int rc, dir = 0; hw_params = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, snd_pcm_hw_params_sizeof() ); fmask = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, snd_pcm_format_mask_sizeof() ); acmask = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, snd_pcm_access_mask_sizeof() ); if ((rc = snd_pcm_hw_params_any(pcm, hw_params)) < 0) goto done; snd_pcm_hw_params_get_format_mask(hw_params, fmask); if ((rc = snd_pcm_hw_params_get_access_mask(hw_params, acmask)) < 0) goto done; if ((rc = snd_pcm_hw_params_get_rate_min(hw_params, &ratemin, &dir)) < 0) goto done; if ((rc = snd_pcm_hw_params_get_rate_max(hw_params, &ratemax, &dir)) < 0) goto done; if ((rc = snd_pcm_hw_params_get_channels_min(hw_params, &chmin)) < 0) goto done; if ((rc = snd_pcm_hw_params_get_channels_max(hw_params, &chmax)) < 0) goto done; #define X(r,v) \ if ( (r) >= ratemin && ( (r) <= ratemax || ratemax == -1) ) \ { \ if (snd_pcm_format_mask_test( fmask, SND_PCM_FORMAT_U8)) \ { \ if (chmin <= 1 && 1 <= chmax) \ *formats |= WAVE_FORMAT_##v##M08; \ if (chmin <= 2 && 2 <= chmax) \ *formats |= WAVE_FORMAT_##v##S08; \ } \ if (snd_pcm_format_mask_test( fmask, SND_PCM_FORMAT_S16_LE)) \ { \ if (chmin <= 1 && 1 <= chmax) \ *formats |= WAVE_FORMAT_##v##M16; \ if (chmin <= 2 && 2 <= chmax) \ *formats |= WAVE_FORMAT_##v##S16; \ } \ } X(11025,1); X(22050,2); X(44100,4); X(48000,48); X(96000,96); #undef X if (chmin > 1) FIXME("Device has a minimum of %d channels\n", chmin); *channels = chmax; /* FIXME: is sample accurate always true ? ** Can we do WAVECAPS_PITCH, WAVECAPS_SYNC, or WAVECAPS_PLAYBACKRATE? */ *supports |= WAVECAPS_SAMPLEACCURATE; *supports |= WAVECAPS_DIRECTSOUND; /* check for volume control support */ if (ctl) { if (snd_ctl_name(ctl)) { snd_hctl_t *hctl; if (snd_hctl_open(&hctl, snd_ctl_name(ctl), 0) >= 0) { snd_hctl_load(hctl); if (!ALSA_CheckSetVolume( hctl, NULL, NULL, NULL, NULL, NULL, NULL, NULL )) { *supports |= WAVECAPS_VOLUME; if (chmin <= 2 && 2 <= chmax) *supports |= WAVECAPS_LRVOLUME; } snd_hctl_free(hctl); snd_hctl_close(hctl); } } } *flags = DSCAPS_CERTIFIED | DSCAPS_CONTINUOUSRATE; *flags |= DSCAPS_SECONDARYMONO | DSCAPS_SECONDARYSTEREO; *flags |= DSCAPS_SECONDARY8BIT | DSCAPS_SECONDARY16BIT; if (*formats & (WAVE_FORMAT_1M08 | WAVE_FORMAT_2M08 | WAVE_FORMAT_4M08 | WAVE_FORMAT_48M08 | WAVE_FORMAT_96M08 | WAVE_FORMAT_1M16 | WAVE_FORMAT_2M16 | WAVE_FORMAT_4M16 | WAVE_FORMAT_48M16 | WAVE_FORMAT_96M16) ) *flags |= DSCAPS_PRIMARYMONO; if (*formats & (WAVE_FORMAT_1S08 | WAVE_FORMAT_2S08 | WAVE_FORMAT_4S08 | WAVE_FORMAT_48S08 | WAVE_FORMAT_96S08 | WAVE_FORMAT_1S16 | WAVE_FORMAT_2S16 | WAVE_FORMAT_4S16 | WAVE_FORMAT_48S16 | WAVE_FORMAT_96S16) ) *flags |= DSCAPS_PRIMARYSTEREO; if (*formats & (WAVE_FORMAT_1M08 | WAVE_FORMAT_2M08 | WAVE_FORMAT_4M08 | WAVE_FORMAT_48M08 | WAVE_FORMAT_96M08 | WAVE_FORMAT_1S08 | WAVE_FORMAT_2S08 | WAVE_FORMAT_4S08 | WAVE_FORMAT_48S08 | WAVE_FORMAT_96S08) ) *flags |= DSCAPS_PRIMARY8BIT; if (*formats & (WAVE_FORMAT_1M16 | WAVE_FORMAT_2M16 | WAVE_FORMAT_4M16 | WAVE_FORMAT_48M16 | WAVE_FORMAT_96M16 | WAVE_FORMAT_1S16 | WAVE_FORMAT_2S16 | WAVE_FORMAT_4S16 | WAVE_FORMAT_48S16 | WAVE_FORMAT_96S16) ) *flags |= DSCAPS_PRIMARY16BIT; rc = 0; done: if (rc < 0) ERR("failed: %s(%d)\n", snd_strerror(rc), rc); HeapFree( GetProcessHeap(), 0, hw_params ); HeapFree( GetProcessHeap(), 0, fmask ); HeapFree( GetProcessHeap(), 0, acmask ); return rc; }