Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Latest commit

 

History

History
260 lines (222 loc) · 7.62 KB

SDL_mmeaudio.c

File metadata and controls

260 lines (222 loc) · 7.62 KB
 
1
2
/*
SDL - Simple DirectMedia Layer
Feb 12, 2011
Feb 12, 2011
3
Copyright (C) 1997-2011 Sam Lantinga
4
5
This library is free software; you can redistribute it and/or
Jan 24, 2010
Jan 24, 2010
6
modify it under the terms of the GNU Lesser General Public
7
License as published by the Free Software Foundation; either
Jan 24, 2010
Jan 24, 2010
8
version 2.1 of the License, or (at your option) any later version.
9
10
11
12
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Jan 24, 2010
Jan 24, 2010
13
Lesser General Public License for more details.
Jan 24, 2010
Jan 24, 2010
15
16
17
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19
20
21
Sam Lantinga
slouken@libsdl.org
*/
Feb 21, 2006
Feb 21, 2006
22
#include "SDL_config.h"
23
24
/* Tru64 UNIX MME support */
Feb 7, 2006
Feb 7, 2006
25
26
27
#include <mme_api.h>
#include "SDL_timer.h"
Feb 10, 2006
Feb 10, 2006
28
#include "SDL_audio.h"
Feb 16, 2006
Feb 16, 2006
29
#include "../SDL_audio_c.h"
30
31
32
33
#include "SDL_mmeaudio.h"
static BOOL inUse[NUM_BUFFERS];
Jul 10, 2006
Jul 10, 2006
34
35
static void
SetMMerror(char *function, MMRESULT code)
36
37
38
39
{
int len;
char errbuf[MAXERRORLENGTH];
Feb 7, 2006
Feb 7, 2006
40
SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: ", function);
Feb 7, 2006
Feb 7, 2006
41
len = SDL_strlen(errbuf);
Jul 10, 2006
Jul 10, 2006
42
43
waveOutGetErrorText(code, errbuf + len, MAXERRORLENGTH - len);
SDL_SetError("%s", errbuf);
Jul 10, 2006
Jul 10, 2006
46
static void CALLBACK
Oct 17, 2006
Oct 17, 2006
47
MME_Callback(HWAVEOUT hwo,
Jul 10, 2006
Jul 10, 2006
48
UINT uMsg, DWORD dwInstance, LPARAM dwParam1, LPARAM dwParam2)
49
50
51
{
WAVEHDR *wp = (WAVEHDR *) dwParam1;
Jul 10, 2006
Jul 10, 2006
52
53
if (uMsg == WOM_DONE)
inUse[wp->dwUser] = FALSE;
Jul 10, 2006
Jul 10, 2006
56
static int
Oct 17, 2006
Oct 17, 2006
57
MME_OpenDevice(_THIS, const char *devname, int iscapture)
Oct 17, 2006
Oct 17, 2006
59
int valid_format = 0;
60
MMRESULT result;
Oct 17, 2006
Oct 17, 2006
61
Uint8 *mixbuf = NULL;
Oct 17, 2006
Oct 17, 2006
64
65
/* Initialize all variables that we clean on shutdown */
this->hidden = (struct SDL_PrivateAudioData *)
Oct 28, 2006
Oct 28, 2006
66
SDL_malloc((sizeof *this->hidden));
Oct 17, 2006
Oct 17, 2006
67
68
69
70
71
if (this->hidden == NULL) {
SDL_OutOfMemory();
return 0;
}
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
72
73
/* Set basic WAVE format parameters */
Oct 17, 2006
Oct 17, 2006
74
75
76
77
78
this->hidden->shm = mmeAllocMem(sizeof(*this->hidden->shm));
if (this->hidden->shm == NULL) {
MME_CloseDevice(this);
SDL_OutOfMemory();
return 0;
Oct 17, 2006
Oct 17, 2006
80
Oct 28, 2006
Oct 28, 2006
81
SDL_memset(this->hidden->shm, '\0', sizeof(*this->hidden->shm));
Oct 17, 2006
Oct 17, 2006
82
83
this->hidden->shm->sound = 0;
this->hidden->shm->wFmt.wf.wFormatTag = WAVE_FORMAT_PCM;
84
85
/* Determine the audio parameters from the AudioSpec */
Oct 17, 2006
Oct 17, 2006
86
87
88
89
90
/* Try for a closest match on audio format */
for (test_format = SDL_FirstAudioFormat(this->spec.format);
!valid_format && test_format;) {
valid_format = 1;
switch (test_format) {
Oct 28, 2006
Oct 28, 2006
91
92
93
94
95
96
97
case AUDIO_U8:
case AUDIO_S16:
case AUDIO_S32:
break;
default:
valid_format = 0;
test_format = SDL_NextAudioFormat();
Oct 17, 2006
Oct 17, 2006
98
99
100
101
102
}
}
if (!valid_format) {
MME_CloseDevice(this);
Jul 10, 2006
Jul 10, 2006
103
SDL_SetError("Unsupported audio format");
Oct 17, 2006
Oct 17, 2006
104
return 0;
Oct 17, 2006
Oct 17, 2006
107
108
109
this->spec.format = test_format;
this->hidden->shm->wFmt.wBitsPerSample = SDL_AUDIO_BITSIZE(test_format);
Sep 1, 2006
Sep 1, 2006
110
/* !!! FIXME: Can this handle more than stereo? */
Oct 17, 2006
Oct 17, 2006
111
112
113
this->hidden->shm->wFmt.wf.nChannels = this->spec.channels;
this->hidden->shm->wFmt.wf.nSamplesPerSec = this->spec.freq;
this->hidden->shm->wFmt.wf.nBlockAlign =
Oct 28, 2006
Oct 28, 2006
114
115
this->hidden->shm->wFmt.wf.nChannels *
this->hidden->shm->wFmt.wBitsPerSample / 8;
Oct 17, 2006
Oct 17, 2006
116
this->hidden->shm->wFmt.wf.nAvgBytesPerSec =
Oct 28, 2006
Oct 28, 2006
117
118
this->hidden->shm->wFmt.wf.nSamplesPerSec *
this->hidden->shm->wFmt.wf.nBlockAlign;
119
120
/* Check the buffer size -- minimum of 1/4 second (word aligned) */
Oct 17, 2006
Oct 17, 2006
121
122
if (this->spec.samples < (this->spec.freq / 4))
this->spec.samples = ((this->spec.freq / 4) + 3) & ~3;
123
124
/* Update the fragment size as size in bytes */
Oct 17, 2006
Oct 17, 2006
125
SDL_CalculateAudioSpec(&this->spec);
126
127
/* Open the audio device */
Oct 17, 2006
Oct 17, 2006
128
result = waveOutOpen(&(this->hidden->shm->sound),
Jul 10, 2006
Jul 10, 2006
129
WAVE_MAPPER,
Oct 17, 2006
Oct 17, 2006
130
131
&(this->hidden->shm->wFmt.wf),
MME_Callback,
Jul 10, 2006
Jul 10, 2006
132
133
NULL, (CALLBACK_FUNCTION | WAVE_OPEN_SHAREABLE));
if (result != MMSYSERR_NOERROR) {
Oct 17, 2006
Oct 17, 2006
134
MME_CloseDevice(this);
Jul 10, 2006
Jul 10, 2006
135
SetMMerror("waveOutOpen()", result);
Oct 17, 2006
Oct 17, 2006
136
return 0;
137
138
139
}
/* Create the sound buffers */
Oct 17, 2006
Oct 17, 2006
140
mixbuf = (Uint8 *) mmeAllocBuffer(NUM_BUFFERS * (this->spec.size));
Jul 10, 2006
Jul 10, 2006
141
if (mixbuf == NULL) {
Oct 17, 2006
Oct 17, 2006
142
143
144
MME_CloseDevice(this);
SDL_OutOfMemory();
return 0;
Oct 17, 2006
Oct 17, 2006
146
this->hidden->mixbuf = mixbuf;
147
148
for (i = 0; i < NUM_BUFFERS; i++) {
Oct 17, 2006
Oct 17, 2006
149
150
151
152
this->hidden->shm->wHdr[i].lpData = &mixbuf[i * (this->spec.size)];
this->hidden->shm->wHdr[i].dwBufferLength = this->spec.size;
this->hidden->shm->wHdr[i].dwFlags = 0;
this->hidden->shm->wHdr[i].dwUser = i;
Oct 28, 2006
Oct 28, 2006
153
154
this->hidden->shm->wHdr[i].dwLoops = 0; /* loop control counter */
this->hidden->shm->wHdr[i].lpNext = NULL; /* reserved for driver */
Oct 17, 2006
Oct 17, 2006
155
this->hidden->shm->wHdr[i].reserved = 0;
Jul 10, 2006
Jul 10, 2006
156
inUse[i] = FALSE;
Oct 17, 2006
Oct 17, 2006
158
159
160
this->hidden->next_buffer = 0;
return 1;
Jul 10, 2006
Jul 10, 2006
163
static void
Oct 17, 2006
Oct 17, 2006
164
MME_WaitDevice(_THIS)
Oct 17, 2006
Oct 17, 2006
166
while (inUse[this->hidden->next_buffer]) {
Jul 10, 2006
Jul 10, 2006
167
168
mmeWaitForCallbacks();
mmeProcessCallbacks();
Dec 14, 2003
Dec 14, 2003
169
}
Jul 10, 2006
Jul 10, 2006
172
static Uint8 *
Oct 17, 2006
Oct 17, 2006
173
MME_GetDeviceBuf(_THIS)
Oct 17, 2006
Oct 17, 2006
175
176
177
void *retval = this->hidden->shm->wHdr[this->hidden->next_buffer].lpData;
inUse[this->hidden->next_buffer] = TRUE;
return (Uint8 *) retval;
Jul 10, 2006
Jul 10, 2006
180
static void
Oct 17, 2006
Oct 17, 2006
181
MME_PlayDevice(_THIS)
182
183
{
/* Queue it up */
Oct 17, 2006
Oct 17, 2006
184
185
waveOutWrite(this->hidden->shm->sound,
&(this->hidden->shm->wHdr[this->hidden->next_buffer]),
Oct 28, 2006
Oct 28, 2006
186
sizeof(WAVEHDR));
Oct 17, 2006
Oct 17, 2006
187
this->hidden->next_buffer = (this->hidden->next_buffer + 1) % NUM_BUFFERS;
Jul 10, 2006
Jul 10, 2006
190
191
static void
MME_WaitDone(_THIS)
192
193
194
195
{
MMRESULT result;
int i;
Oct 17, 2006
Oct 17, 2006
196
if (this->hidden->shm->sound) {
Jul 10, 2006
Jul 10, 2006
197
198
199
200
201
for (i = 0; i < NUM_BUFFERS; i++)
while (inUse[i]) {
mmeWaitForCallbacks();
mmeProcessCallbacks();
}
Oct 17, 2006
Oct 17, 2006
202
result = waveOutReset(this->hidden->shm->sound);
Jul 10, 2006
Jul 10, 2006
203
204
205
if (result != MMSYSERR_NOERROR)
SetMMerror("waveOutReset()", result);
mmeProcessCallbacks();
Jul 10, 2006
Jul 10, 2006
209
static void
Oct 17, 2006
Oct 17, 2006
210
MME_CloseDevice(_THIS)
Oct 17, 2006
Oct 17, 2006
212
213
if (this->hidden != NULL) {
MMRESULT result;
Oct 17, 2006
Oct 17, 2006
215
216
217
218
219
220
if (this->hidden->mixbuf) {
result = mmeFreeBuffer(this->hidden->mixbuf);
if (result != MMSYSERR_NOERROR)
SetMMerror("mmeFreeBuffer", result);
this->hidden->mixbuf = NULL;
}
Oct 17, 2006
Oct 17, 2006
222
223
224
225
226
227
228
229
if (this->hidden->shm) {
if (this->hidden->shm->sound) {
result = waveOutClose(this->hidden->shm->sound);
if (result != MMSYSERR_NOERROR)
SetMMerror("waveOutClose()", result);
mmeProcessCallbacks();
}
result = mmeFreeMem(this->hidden->shm);
Jul 10, 2006
Jul 10, 2006
230
if (result != MMSYSERR_NOERROR)
Oct 17, 2006
Oct 17, 2006
231
232
SetMMerror("mmeFreeMem()", result);
this->hidden->shm = NULL;
Jul 10, 2006
Jul 10, 2006
233
}
Oct 17, 2006
Oct 17, 2006
234
235
236
SDL_free(this->hidden);
this->hidden = NULL;
Oct 17, 2006
Oct 17, 2006
240
static int
Oct 28, 2006
Oct 28, 2006
241
MME_Init(SDL_AudioDriverImpl * impl)
Oct 17, 2006
Oct 17, 2006
242
243
244
245
246
247
248
249
250
251
{
/* Set the function pointers */
impl->OpenDevice = MME_OpenDevice;
impl->WaitDevice = MME_WaitDevice;
impl->WaitDone = MME_WaitDone;
impl->PlayDevice = MME_PlayDevice;
impl->GetDeviceBuf = MME_GetDeviceBuf;
impl->CloseDevice = MME_CloseDevice;
impl->OnlyHasDefaultOutputDevice = 1;
Jan 26, 2010
Jan 26, 2010
252
return 1; /* this audio target is available. */
Oct 17, 2006
Oct 17, 2006
253
254
255
256
257
258
259
}
/* !!! FIXME: Windows "windib" driver is called waveout, too */
AudioBootStrap MMEAUDIO_bootstrap = {
"waveout", "Tru64 MME WaveOut", MME_Init, 0
};
Jul 10, 2006
Jul 10, 2006
260
/* vi: set ts=4 sw=4 expandtab: */