static int WINMM_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) { SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format); int valid_datatype = 0; MMRESULT result; WAVEFORMATEX waveformat; UINT devId = WAVE_MAPPER; /* WAVE_MAPPER == choose system's default */ UINT i; if (handle != NULL) { /* specific device requested? */ /* -1 because we increment the original value to avoid NULL. */ const size_t val = ((size_t) handle) - 1; devId = (UINT) val; } /* Initialize all variables that we clean on shutdown */ this->hidden = (struct SDL_PrivateAudioData *) SDL_malloc((sizeof *this->hidden)); if (this->hidden == NULL) { return SDL_OutOfMemory(); } SDL_memset(this->hidden, 0, (sizeof *this->hidden)); /* Initialize the wavebuf structures for closing */ for (i = 0; i < NUM_BUFFERS; ++i) this->hidden->wavebuf[i].dwUser = 0xFFFF; if (this->spec.channels > 2) this->spec.channels = 2; /* !!! FIXME: is this right? */ while ((!valid_datatype) && (test_format)) { switch (test_format) { case AUDIO_U8: case AUDIO_S16: case AUDIO_S32: case AUDIO_F32: this->spec.format = test_format; if (PrepWaveFormat(this, devId, &waveformat, iscapture)) { valid_datatype = 1; } else { test_format = SDL_NextAudioFormat(); } break; default: test_format = SDL_NextAudioFormat(); break; } } if (!valid_datatype) { WINMM_CloseDevice(this); return SDL_SetError("Unsupported audio format"); } /* Update the fragment size as size in bytes */ SDL_CalculateAudioSpec(&this->spec); /* Open the audio device */ if (iscapture) { result = waveInOpen(&this->hidden->hin, devId, &waveformat, (DWORD_PTR) CaptureSound, (DWORD_PTR) this, CALLBACK_FUNCTION); } else { result = waveOutOpen(&this->hidden->hout, devId, &waveformat, (DWORD_PTR) FillSound, (DWORD_PTR) this, CALLBACK_FUNCTION); } if (result != MMSYSERR_NOERROR) { WINMM_CloseDevice(this); return SetMMerror("waveOutOpen()", result); } #ifdef SOUND_DEBUG /* Check the sound device we retrieved */ { WAVEOUTCAPS caps; result = waveOutGetDevCaps((UINT) this->hidden->hout, &caps, sizeof(caps)); if (result != MMSYSERR_NOERROR) { WINMM_CloseDevice(this); return SetMMerror("waveOutGetDevCaps()", result); } printf("Audio device: %s\n", caps.szPname); } #endif /* Create the audio buffer semaphore */ this->hidden->audio_sem = CreateSemaphore(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL); if (this->hidden->audio_sem == NULL) { WINMM_CloseDevice(this); return SDL_SetError("Couldn't create semaphore"); } /* Create the sound buffers */ this->hidden->mixbuf = (Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size); if (this->hidden->mixbuf == NULL) { WINMM_CloseDevice(this); return SDL_OutOfMemory(); } for (i = 0; i < NUM_BUFFERS; ++i) { SDL_memset(&this->hidden->wavebuf[i], 0, sizeof(this->hidden->wavebuf[i])); this->hidden->wavebuf[i].dwBufferLength = this->spec.size; this->hidden->wavebuf[i].dwFlags = WHDR_DONE; this->hidden->wavebuf[i].lpData = (LPSTR) & this->hidden->mixbuf[i * this->spec.size]; result = waveOutPrepareHeader(this->hidden->hout, &this->hidden->wavebuf[i], sizeof(this->hidden->wavebuf[i])); if (result != MMSYSERR_NOERROR) { WINMM_CloseDevice(this); return SetMMerror("waveOutPrepareHeader()", result); } } return 0; /* Ready to go! */ }
static int WINMM_OpenDevice(_THIS, const char *devname, int iscapture) { SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format); int valid_datatype = 0; MMRESULT result; WAVEFORMATEX waveformat; UINT_PTR devId = WAVE_MAPPER; /* WAVE_MAPPER == choose system's default */ char *utf8 = NULL; int i; if (devname != NULL) { /* specific device requested? */ if (iscapture) { const int devcount = (int) waveInGetNumDevs(); WAVEINCAPS caps; for (i = 0; (i < devcount) && (devId == WAVE_MAPPER); i++) { result = waveInGetDevCaps(i, &caps, sizeof (caps)); if (result != MMSYSERR_NOERROR) continue; else if ((utf8 = WIN_StringToUTF8(caps.szPname)) == NULL) continue; else if (SDL_strcmp(devname, utf8) == 0) devId = (UINT_PTR) i; SDL_free(utf8); } } else { const int devcount = (int) waveOutGetNumDevs(); WAVEOUTCAPS caps; for (i = 0; (i < devcount) && (devId == WAVE_MAPPER); i++) { result = waveOutGetDevCaps(i, &caps, sizeof (caps)); if (result != MMSYSERR_NOERROR) continue; else if ((utf8 = WIN_StringToUTF8(caps.szPname)) == NULL) continue; else if (SDL_strcmp(devname, utf8) == 0) devId = (UINT_PTR) i; SDL_free(utf8); } } if (devId == WAVE_MAPPER) { SDL_SetError("Requested device not found"); return 0; } } /* Initialize all variables that we clean on shutdown */ this->hidden = (struct SDL_PrivateAudioData *) SDL_malloc((sizeof *this->hidden)); if (this->hidden == NULL) { SDL_OutOfMemory(); return 0; } SDL_memset(this->hidden, 0, (sizeof *this->hidden)); /* Initialize the wavebuf structures for closing */ for (i = 0; i < NUM_BUFFERS; ++i) this->hidden->wavebuf[i].dwUser = 0xFFFF; while ((!valid_datatype) && (test_format)) { valid_datatype = 1; this->spec.format = test_format; switch (test_format) { case AUDIO_U8: case AUDIO_S16: case AUDIO_S32: break; /* valid. */ default: valid_datatype = 0; test_format = SDL_NextAudioFormat(); break; } } if (!valid_datatype) { WINMM_CloseDevice(this); SDL_SetError("Unsupported audio format"); return 0; } /* Set basic WAVE format parameters */ SDL_memset(&waveformat, '\0', sizeof(waveformat)); waveformat.wFormatTag = WAVE_FORMAT_PCM; waveformat.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format); if (this->spec.channels > 2) this->spec.channels = 2; /* !!! FIXME: is this right? */ waveformat.nChannels = this->spec.channels; waveformat.nSamplesPerSec = this->spec.freq; waveformat.nBlockAlign = waveformat.nChannels * (waveformat.wBitsPerSample / 8); waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec * waveformat.nBlockAlign; /* Check the buffer size -- minimum of 1/4 second (word aligned) */ if (this->spec.samples < (this->spec.freq / 4)) this->spec.samples = ((this->spec.freq / 4) + 3) & ~3; /* Update the fragment size as size in bytes */ SDL_CalculateAudioSpec(&this->spec); /* Open the audio device */ if (iscapture) { result = waveInOpen(&this->hidden->hin, devId, &waveformat, (DWORD_PTR) CaptureSound, (DWORD_PTR) this, CALLBACK_FUNCTION); } else { result = waveOutOpen(&this->hidden->hout, devId, &waveformat, (DWORD_PTR) FillSound, (DWORD_PTR) this, CALLBACK_FUNCTION); } if (result != MMSYSERR_NOERROR) { WINMM_CloseDevice(this); SetMMerror("waveOutOpen()", result); return 0; } #ifdef SOUND_DEBUG /* Check the sound device we retrieved */ { WAVEOUTCAPS caps; result = waveOutGetDevCaps((UINT) this->hidden->hout, &caps, sizeof(caps)); if (result != MMSYSERR_NOERROR) { WINMM_CloseDevice(this); SetMMerror("waveOutGetDevCaps()", result); return 0; } printf("Audio device: %s\n", caps.szPname); } #endif /* Create the audio buffer semaphore */ this->hidden->audio_sem = CreateSemaphore(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL); if (this->hidden->audio_sem == NULL) { WINMM_CloseDevice(this); SDL_SetError("Couldn't create semaphore"); return 0; } /* Create the sound buffers */ this->hidden->mixbuf = (Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size); if (this->hidden->mixbuf == NULL) { WINMM_CloseDevice(this); SDL_OutOfMemory(); return 0; } for (i = 0; i < NUM_BUFFERS; ++i) { SDL_memset(&this->hidden->wavebuf[i], 0, sizeof(this->hidden->wavebuf[i])); this->hidden->wavebuf[i].dwBufferLength = this->spec.size; this->hidden->wavebuf[i].dwFlags = WHDR_DONE; this->hidden->wavebuf[i].lpData = (LPSTR) & this->hidden->mixbuf[i * this->spec.size]; result = waveOutPrepareHeader(this->hidden->hout, &this->hidden->wavebuf[i], sizeof(this->hidden->wavebuf[i])); if (result != MMSYSERR_NOERROR) { WINMM_CloseDevice(this); SetMMerror("waveOutPrepareHeader()", result); return 0; } } return 1; /* Ready to go! */ }