/*---------------------------------------------------------------------- | main +---------------------------------------------------------------------*/ int main(int argc, char** argv) { bool no_pcm = false; if (argc >= 2 && !strcmp(argv[1], "--no-pcm")) no_pcm = true; printf("------- Win32 Soundcard Probe ------ built " __DATE__ "\n"); unsigned int num_devs = waveOutGetNumDevs(); printf("Found %d devices\n", num_devs); for (unsigned int i=0; i<num_devs; i++) { ProbeDevice(i, no_pcm); } }
AudioStream* AlsaBackend::OpenStream(StreamDirection dir, DeviceInfo* device, StreamSpec& spec, SOUNDCARD_CALLBACK callback, void* userdata) { if (!device->probed) if (!ProbeDevice(device, spec)) return NULL; if (!device->mixer) { Log("Device was probed but no mixer set, trying to enable now."); device->mixer = new AlsaVolumeControl; static_cast<AlsaVolumeControl*>(device->mixer)->ProbeMixer(device); } snd_pcm_stream_t stream; if (dir == INPUT) stream = SND_PCM_STREAM_CAPTURE; else if (dir >= OUTPUT) stream = SND_PCM_STREAM_PLAYBACK; else { return NULL; } AudioStream *audioStream = new AudioStream; MutexLock lock(audioStream->mutex); Log("AlsaBackend.open_stream_lock"); //int result; snd_pcm_t *phandle = 0; int openMode = SND_PCM_ASYNC; snd_output_t *out; _EE_CALL(snd_pcm_open(&phandle, device->guid, stream, openMode), false, phandle, "pcm device %s won't open for %s", device->displayName, dir==INPUT?"input":"output"); // Fill the parameter structure. AlsaHardwareParams alsa_hw_params(phandle); #define DUMP_PARAMS(out, title, func) \ if (!snd_output_buffer_open(&out)) \ { \ char* str; \ Log(title); \ func; \ snd_output_putc(out, '\0'); \ if (snd_output_buffer_string(out, &str) > 0) \ Log("%s",str); \ snd_output_close(out); \ } DUMP_PARAMS(out, "AlsaBackend: dump hardware params just after device open:", snd_pcm_hw_params_dump(alsa_hw_params, out)); // Set up interleaving audioStream->userInterleaved = true; audioStream->deviceInterleaved = true; bool use_mmap = false; alsa_hw_params.set_params(&spec, &use_mmap); audioStream->deviceFormat = audioStream->userFormat = spec.format; audioStream->deviceChannels = audioStream->userChannels = spec.channels; DUMP_PARAMS(out, "AlsaBackend: dump hardware params after installation:", snd_pcm_hw_params_dump(alsa_hw_params, out)); AlsaSoftwareParams sw_params(phandle); sw_params.set_params(spec.fragmentFrames, true); DUMP_PARAMS(out, "AlsaBackend: dump software params after installation:", snd_pcm_sw_params_dump(sw_params, out)); // Allocate the ApiHandle if necessary and then save. AlsaHandle *apiInfo = 0; if (audioStream->apiHandle == 0) { apiInfo = new AlsaHandle; if (!apiInfo) { Log("error allocating AlsaHandle memory"); delete audioStream; return NULL; } audioStream->apiHandle = (void *) apiInfo; apiInfo->handle = 0; } else { apiInfo = (AlsaHandle *) audioStream->apiHandle; } apiInfo->handle = phandle; apiInfo->xrun = false; apiInfo->type = device->type; audioStream->spec = spec; audioStream->running = 0; audioStream->dir = dir; audioStream->mixer = device->mixer; // Setup callback thread. audioStream->callback.object = this; audioStream->callback.stream = audioStream; audioStream->callback.callback = callback; audioStream->callback.userdata = userdata; audioStream->callback.apiInfo = apiInfo; audioStream->callback.isRunning = 1; // Allocate necessary internal buffer. audioStream->buffer = new PhantomRingbuffer(spec.FrameBytes(), spec.bufferFrames, spec.fragmentFrames); if (audioStream->buffer == NULL) { Log("error allocating ringbuffer memory"); if (apiInfo) { if (apiInfo->handle) snd_pcm_close(apiInfo->handle); delete apiInfo; apiInfo = NULL; audioStream->apiHandle = 0; } delete audioStream; return NULL; } p_alsathread[audioStream] = new AlsaThread(&audioStream->callback, dir == INPUT ? "alsa_capture_thread" : "alsa_playback_thread"); pthread_create(&thrd,NULL,&(AlsaThread::run),p_alsathread[audioStream]); pthread_detach(thrd); Log("Using %0.1f fragments of size %lu bytes (%0.2fms), buffer size is %lu bytes (%0.2fms)", (double) (spec.bufferFrames * spec.FrameBytes()) / (double) (spec.fragmentFrames * spec.FrameBytes()), (long unsigned) spec.fragmentFrames * spec.FrameBytes(), spec.FragmentMs(), (long unsigned) spec.bufferFrames * spec.FrameBytes(), spec.BufferMs()); return audioStream; }