00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef DSBTYPE_IN
00025 #define NAME "capture buffer"
00026 #define NAME2 "DirectSoundCapture"
00027 #define TYPE in
00028 #define IFACE IDirectSoundCaptureBuffer
00029 #define BUFPTR LPDIRECTSOUNDCAPTUREBUFFER
00030 #define FIELD dsound_capture_buffer
00031 #define FIELD2 dsound_capture
00032 #else
00033 #define NAME "playback buffer"
00034 #define NAME2 "DirectSound"
00035 #define TYPE out
00036 #define IFACE IDirectSoundBuffer
00037 #define BUFPTR LPDIRECTSOUNDBUFFER
00038 #define FIELD dsound_buffer
00039 #define FIELD2 dsound
00040 #endif
00041
00042 static int glue (dsound_unlock_, TYPE) (
00043 BUFPTR buf,
00044 LPVOID p1,
00045 LPVOID p2,
00046 DWORD blen1,
00047 DWORD blen2
00048 )
00049 {
00050 HRESULT hr;
00051
00052 hr = glue (IFACE, _Unlock) (buf, p1, blen1, p2, blen2);
00053 if (FAILED (hr)) {
00054 dsound_logerr (hr, "Could not unlock " NAME "\n");
00055 return -1;
00056 }
00057
00058 return 0;
00059 }
00060
00061 static int glue (dsound_lock_, TYPE) (
00062 BUFPTR buf,
00063 struct audio_pcm_info *info,
00064 DWORD pos,
00065 DWORD len,
00066 LPVOID *p1p,
00067 LPVOID *p2p,
00068 DWORD *blen1p,
00069 DWORD *blen2p,
00070 int entire
00071 )
00072 {
00073 HRESULT hr;
00074 int i;
00075 LPVOID p1 = NULL, p2 = NULL;
00076 DWORD blen1 = 0, blen2 = 0;
00077 DWORD flag;
00078
00079 #ifdef DSBTYPE_IN
00080 flag = entire ? DSCBLOCK_ENTIREBUFFER : 0;
00081 #else
00082 flag = entire ? DSBLOCK_ENTIREBUFFER : 0;
00083 #endif
00084 for (i = 0; i < conf.lock_retries; ++i) {
00085 hr = glue (IFACE, _Lock) (
00086 buf,
00087 pos,
00088 len,
00089 &p1,
00090 &blen1,
00091 &p2,
00092 &blen2,
00093 flag
00094 );
00095
00096 if (FAILED (hr)) {
00097 #ifndef DSBTYPE_IN
00098 if (hr == DSERR_BUFFERLOST) {
00099 if (glue (dsound_restore_, TYPE) (buf)) {
00100 dsound_logerr (hr, "Could not lock " NAME "\n");
00101 goto fail;
00102 }
00103 continue;
00104 }
00105 #endif
00106 dsound_logerr (hr, "Could not lock " NAME "\n");
00107 goto fail;
00108 }
00109
00110 break;
00111 }
00112
00113 if (i == conf.lock_retries) {
00114 dolog ("%d attempts to lock " NAME " failed\n", i);
00115 goto fail;
00116 }
00117
00118 if ((p1 && (blen1 & info->align)) || (p2 && (blen2 & info->align))) {
00119 dolog ("DirectSound returned misaligned buffer %ld %ld\n",
00120 blen1, blen2);
00121 glue (dsound_unlock_, TYPE) (buf, p1, p2, blen1, blen2);
00122 goto fail;
00123 }
00124
00125 if (!p1 && blen1) {
00126 dolog ("warning: !p1 && blen1=%ld\n", blen1);
00127 blen1 = 0;
00128 }
00129
00130 if (!p2 && blen2) {
00131 dolog ("warning: !p2 && blen2=%ld\n", blen2);
00132 blen2 = 0;
00133 }
00134
00135 *p1p = p1;
00136 *p2p = p2;
00137 *blen1p = blen1;
00138 *blen2p = blen2;
00139 return 0;
00140
00141 fail:
00142 *p1p = NULL - 1;
00143 *p2p = NULL - 1;
00144 *blen1p = -1;
00145 *blen2p = -1;
00146 return -1;
00147 }
00148
00149 #ifdef DSBTYPE_IN
00150 static void dsound_fini_in (HWVoiceIn *hw)
00151 #else
00152 static void dsound_fini_out (HWVoiceOut *hw)
00153 #endif
00154 {
00155 HRESULT hr;
00156 #ifdef DSBTYPE_IN
00157 DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
00158 #else
00159 DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
00160 #endif
00161
00162 if (ds->FIELD) {
00163 hr = glue (IFACE, _Stop) (ds->FIELD);
00164 if (FAILED (hr)) {
00165 dsound_logerr (hr, "Could not stop " NAME "\n");
00166 }
00167
00168 hr = glue (IFACE, _Release) (ds->FIELD);
00169 if (FAILED (hr)) {
00170 dsound_logerr (hr, "Could not release " NAME "\n");
00171 }
00172 ds->FIELD = NULL;
00173 }
00174 }
00175
00176 #ifdef DSBTYPE_IN
00177 static int dsound_init_in (HWVoiceIn *hw, struct audsettings *as)
00178 #else
00179 static int dsound_init_out (HWVoiceOut *hw, struct audsettings *as)
00180 #endif
00181 {
00182 int err;
00183 HRESULT hr;
00184 dsound *s = &glob_dsound;
00185 WAVEFORMATEX wfx;
00186 struct audsettings obt_as;
00187 #ifdef DSBTYPE_IN
00188 const char *typ = "ADC";
00189 DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
00190 DSCBUFFERDESC bd;
00191 DSCBCAPS bc;
00192 #else
00193 const char *typ = "DAC";
00194 DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
00195 DSBUFFERDESC bd;
00196 DSBCAPS bc;
00197 #endif
00198
00199 if (!s->FIELD2) {
00200 dolog ("Attempt to initialize voice without " NAME2 " object\n");
00201 return -1;
00202 }
00203
00204 err = waveformat_from_audio_settings (&wfx, as);
00205 if (err) {
00206 return -1;
00207 }
00208
00209 memset (&bd, 0, sizeof (bd));
00210 bd.dwSize = sizeof (bd);
00211 bd.lpwfxFormat = &wfx;
00212 #ifdef DSBTYPE_IN
00213 bd.dwBufferBytes = conf.bufsize_in;
00214 hr = IDirectSoundCapture_CreateCaptureBuffer (
00215 s->dsound_capture,
00216 &bd,
00217 &ds->dsound_capture_buffer,
00218 NULL
00219 );
00220 #else
00221 bd.dwFlags = DSBCAPS_STICKYFOCUS | DSBCAPS_GETCURRENTPOSITION2;
00222 bd.dwBufferBytes = conf.bufsize_out;
00223 hr = IDirectSound_CreateSoundBuffer (
00224 s->dsound,
00225 &bd,
00226 &ds->dsound_buffer,
00227 NULL
00228 );
00229 #endif
00230
00231 if (FAILED (hr)) {
00232 dsound_logerr2 (hr, typ, "Could not create " NAME "\n");
00233 return -1;
00234 }
00235
00236 hr = glue (IFACE, _GetFormat) (ds->FIELD, &wfx, sizeof (wfx), NULL);
00237 if (FAILED (hr)) {
00238 dsound_logerr2 (hr, typ, "Could not get " NAME " format\n");
00239 goto fail0;
00240 }
00241
00242 #ifdef DEBUG_DSOUND
00243 dolog (NAME "\n");
00244 print_wave_format (&wfx);
00245 #endif
00246
00247 memset (&bc, 0, sizeof (bc));
00248 bc.dwSize = sizeof (bc);
00249
00250 hr = glue (IFACE, _GetCaps) (ds->FIELD, &bc);
00251 if (FAILED (hr)) {
00252 dsound_logerr2 (hr, typ, "Could not get " NAME " format\n");
00253 goto fail0;
00254 }
00255
00256 err = waveformat_to_audio_settings (&wfx, &obt_as);
00257 if (err) {
00258 goto fail0;
00259 }
00260
00261 ds->first_time = 1;
00262 obt_as.endianness = 0;
00263 audio_pcm_init_info (&hw->info, &obt_as);
00264
00265 if (bc.dwBufferBytes & hw->info.align) {
00266 dolog (
00267 "GetCaps returned misaligned buffer size %ld, alignment %d\n",
00268 bc.dwBufferBytes, hw->info.align + 1
00269 );
00270 }
00271 hw->samples = bc.dwBufferBytes >> hw->info.shift;
00272
00273 #ifdef DEBUG_DSOUND
00274 dolog ("caps %ld, desc %ld\n",
00275 bc.dwBufferBytes, bd.dwBufferBytes);
00276
00277 dolog ("bufsize %d, freq %d, chan %d, fmt %d\n",
00278 hw->bufsize, settings.freq, settings.nchannels, settings.fmt);
00279 #endif
00280 return 0;
00281
00282 fail0:
00283 glue (dsound_fini_, TYPE) (hw);
00284 return -1;
00285 }
00286
00287 #undef NAME
00288 #undef NAME2
00289 #undef TYPE
00290 #undef IFACE
00291 #undef BUFPTR
00292 #undef FIELD
00293 #undef FIELD2