Exemplo n.º 1
0
void ALSAAudioCaptureDevice::enumerateDevices(std::vector<AudioCaptureDevice::DeviceIdPtr>& devices)
	{
	/* Enumerate all ALSA cards and devices: */
	int cardIndex=-1; // Start with first card
	while(true)
		{
		/* Get the index of the next card: */
		if(snd_card_next(&cardIndex)!=0||cardIndex<0)
			{
			/* There was an error, or there are no more cards: */
			break;
			}
		
		/* Open the card's control interface: */
		char cardName[20];
		snprintf(cardName,sizeof(cardName),"hw:%d",cardIndex);
		snd_ctl_t* cardHandle;
		if(snd_ctl_open(&cardHandle,cardName,0)!=0)
			break;
		
		/* Enumerate all PCM devices on this card: */
		int numCardDevices=0;
		int pcmIndex=-1;
		while(true)
			{
			/* Get the index of the next PCM device: */
			if(snd_ctl_pcm_next_device(cardHandle,&pcmIndex)!=0||pcmIndex<0)
				{
				/* There was an error, or there are no more PCM devices: */
				break;
				}
			
			/* Create an info structure for the PCM device: */
			snd_pcm_info_t* pcmInfo;
			snd_pcm_info_alloca(&pcmInfo);
			snd_pcm_info_set_device(pcmInfo,pcmIndex);
			snd_pcm_info_set_stream(pcmInfo,SND_PCM_STREAM_CAPTURE);
			
			/* Get the number of capture subdevices for the device: */
			if(snd_ctl_pcm_info(cardHandle,pcmInfo)!=0)
				break;
			int numSubDevices=snd_pcm_info_get_subdevices_count(pcmInfo);
			for(int subDeviceIndex=0;subDeviceIndex<numSubDevices;++subDeviceIndex)
				{
				/* Query information about the subdevice: */
				snd_pcm_info_set_subdevice(pcmInfo,subDeviceIndex);
				if(snd_ctl_pcm_info(cardHandle,pcmInfo)==0)
					{
					/* Query the card's name: */
					char* cardName;
					if(snd_card_get_name(cardIndex,&cardName)==0)
						{
						/* Create a device ID: */
						std::string deviceName=cardName;
						free(cardName);
						if(numCardDevices>0)
							{
							char suffix[10];
							snprintf(suffix,sizeof(suffix),":%d",numCardDevices);
							deviceName.append(suffix);
							}
						DeviceId* newDeviceId=new DeviceId(deviceName);
						
						/* Set the PCM device name: */
						char pcmDeviceName[20];
						if(numSubDevices>1)
							snprintf(pcmDeviceName,sizeof(pcmDeviceName),"plughw:%d,%d,%d",snd_pcm_info_get_card(pcmInfo),snd_pcm_info_get_device(pcmInfo),snd_pcm_info_get_subdevice(pcmInfo));
						else
							snprintf(pcmDeviceName,sizeof(pcmDeviceName),"plughw:%d,%d",snd_pcm_info_get_card(pcmInfo),snd_pcm_info_get_device(pcmInfo));
						newDeviceId->pcmDeviceName=pcmDeviceName;
						
						/* Store the device ID: */
						devices.push_back(newDeviceId);
						
						++numCardDevices;
						}
					}
				}
			}
		
		/* Close the card's control interface: */
		snd_ctl_close(cardHandle);
		}
	}
Exemplo n.º 2
0
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;
}