예제 #1
0
/*----------------------------------------------------------------------
|    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);
    }

}
예제 #2
0
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;
}