typedef struct {
HWVoiceOut hw;
LPDIRECTSOUNDBUFFER dsound_buffer;
+ bool first_time;
dsound *s;
} DSoundVoiceOut;
typedef struct {
HWVoiceIn hw;
LPDIRECTSOUNDCAPTUREBUFFER dsound_capture_buffer;
+ bool first_time;
dsound *s;
} DSoundVoiceIn;
#endif
#ifdef DSERR_ALLOCATED
case DSERR_ALLOCATED:
- str = "The request failed because resources, such as a priority level, were already in use by another caller";
+ str = "The request failed because resources, "
+ "such as a priority level, were already in use "
+ "by another caller";
break;
#endif
#ifdef DSERR_ALREADYINITIALIZED
#endif
#ifdef DSERR_BADSENDBUFFERGUID
case DSERR_BADSENDBUFFERGUID:
- str = "The GUID specified in an audiopath file does not match a valid mix-in buffer";
+ str = "The GUID specified in an audiopath file "
+ "does not match a valid mix-in buffer";
break;
#endif
#ifdef DSERR_BUFFERLOST
#endif
#ifdef DSERR_BUFFERTOOSMALL
case DSERR_BUFFERTOOSMALL:
- str = "The buffer size is not great enough to enable effects processing";
+ str = "The buffer size is not great enough to "
+ "enable effects processing";
break;
#endif
#ifdef DSERR_CONTROLUNAVAIL
case DSERR_CONTROLUNAVAIL:
- str = "The buffer control (volume, pan, and so on) requested by the caller is not available. Controls must be specified when the buffer is created, using the dwFlags member of DSBUFFERDESC";
+ str = "The buffer control (volume, pan, and so on) "
+ "requested by the caller is not available. "
+ "Controls must be specified when the buffer is created, "
+ "using the dwFlags member of DSBUFFERDESC";
break;
#endif
#ifdef DSERR_DS8_REQUIRED
case DSERR_DS8_REQUIRED:
- str = "A DirectSound object of class CLSID_DirectSound8 or later is required for the requested functionality. For more information, see IDirectSound8 Interface";
+ str = "A DirectSound object of class CLSID_DirectSound8 or later "
+ "is required for the requested functionality. "
+ "For more information, see IDirectSound8 Interface";
break;
#endif
#ifdef DSERR_FXUNAVAILABLE
case DSERR_FXUNAVAILABLE:
- str = "The effects requested could not be found on the system, or they are in the wrong order or in the wrong location; for example, an effect expected in hardware was found in software";
+ str = "The effects requested could not be found on the system, "
+ "or they are in the wrong order or in the wrong location; "
+ "for example, an effect expected in hardware "
+ "was found in software";
break;
#endif
#ifdef DSERR_GENERIC
- case DSERR_GENERIC :
+ case DSERR_GENERIC:
str = "An undetermined error occurred inside the DirectSound subsystem";
break;
#endif
#endif
#ifdef DSERR_NODRIVER
case DSERR_NODRIVER:
- str = "No sound driver is available for use, or the given GUID is not a valid DirectSound device ID";
+ str = "No sound driver is available for use, "
+ "or the given GUID is not a valid DirectSound device ID";
break;
#endif
#ifdef DSERR_NOINTERFACE
#endif
#ifdef DSERR_OTHERAPPHASPRIO
case DSERR_OTHERAPPHASPRIO:
- str = "Another application has a higher priority level, preventing this call from succeeding";
+ str = "Another application has a higher priority level, "
+ "preventing this call from succeeding";
break;
#endif
#ifdef DSERR_OUTOFMEMORY
case DSERR_OUTOFMEMORY:
- str = "The DirectSound subsystem could not allocate sufficient memory to complete the caller's request";
+ str = "The DirectSound subsystem could not allocate "
+ "sufficient memory to complete the caller's request";
break;
#endif
#ifdef DSERR_PRIOLEVELNEEDED
#endif
#ifdef DSERR_UNINITIALIZED
case DSERR_UNINITIALIZED:
- str = "The Initialize method has not been called or has not been called successfully before other methods were called";
+ str = "The Initialize method has not been called "
+ "or has not been called successfully "
+ "before other methods were called";
break;
#endif
#ifdef DSERR_UNSUPPORTED
break;
#endif
default:
- AUD_log (AUDIO_CAP, "Reason: Unknown (HRESULT %#lx)\n", hr);
+ AUD_log (AUDIO_CAP, "Reason: Unknown (HRESULT 0x%lx)\n", hr);
return;
}
AUD_log (AUDIO_CAP, "Reason: %s\n", str);
}
-static void GCC_FMT_ATTR (2, 3) dsound_logerr (
+static void G_GNUC_PRINTF (2, 3) dsound_logerr (
HRESULT hr,
const char *fmt,
...
dsound_log_hresult (hr);
}
-static void GCC_FMT_ATTR (3, 4) dsound_logerr2 (
+static void G_GNUC_PRINTF (3, 4) dsound_logerr2 (
HRESULT hr,
const char *typ,
const char *fmt,
return -1;
}
- if (*statusp & DSERR_BUFFERLOST) {
+ if (*statusp & DSBSTATUS_BUFFERLOST) {
dsound_restore_out(dsb, s);
return -1;
}
return;
}
- len1 = blen1 >> hw->info.shift;
- len2 = blen2 >> hw->info.shift;
+ len1 = blen1 / hw->info.bytes_per_frame;
+ len2 = blen2 / hw->info.bytes_per_frame;
#ifdef DEBUG_DSOUND
dolog ("clear %p,%ld,%ld %p,%ld,%ld\n",
dsound_unlock_out (dsb, p1, p2, blen1, blen2);
}
-static int dsound_open (dsound *s)
+static int dsound_set_cooperative_level(dsound *s)
{
HRESULT hr;
HWND hwnd;
- hwnd = GetForegroundWindow ();
+ hwnd = GetDesktopWindow();
hr = IDirectSound_SetCooperativeLevel (
s->dsound,
hwnd,
dsound_logerr (hr, "Could not stop playing buffer\n");
return;
}
- }
- else {
+ } else {
dolog ("warning: Voice is not playing\n");
}
}
}
-static void *dsound_get_buffer_out(HWVoiceOut *hw, size_t *size)
+static size_t dsound_buffer_get_free(HWVoiceOut *hw)
{
DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer;
HRESULT hr;
- DWORD ppos, act_size;
- size_t req_size;
- int err;
- void *ret;
+ DWORD ppos, wpos;
- hr = IDirectSoundBuffer_GetCurrentPosition(dsb, &ppos, NULL);
+ hr = IDirectSoundBuffer_GetCurrentPosition(
+ dsb, &ppos, ds->first_time ? &wpos : NULL);
if (FAILED(hr)) {
dsound_logerr(hr, "Could not get playback buffer position\n");
- *size = 0;
- return NULL;
+ return 0;
+ }
+
+ if (ds->first_time) {
+ hw->pos_emul = wpos;
+ ds->first_time = false;
}
- req_size = audio_ring_dist(ppos, hw->pos_emul, hw->size_emul);
- req_size = MIN(req_size, hw->size_emul - hw->pos_emul);
+ return audio_ring_dist(ppos, hw->pos_emul, hw->size_emul);
+}
+
+static void *dsound_get_buffer_out(HWVoiceOut *hw, size_t *size)
+{
+ DSoundVoiceOut *ds = (DSoundVoiceOut *)hw;
+ LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer;
+ DWORD act_size;
+ size_t req_size;
+ int err;
+ void *ret;
+
+ req_size = MIN(*size, hw->size_emul - hw->pos_emul);
+ assert(req_size > 0);
err = dsound_lock_out(dsb, &hw->info, hw->pos_emul, req_size, &ret, NULL,
&act_size, NULL, false, ds->s);
dsound_logerr (hr, "Could not stop capturing\n");
return;
}
- }
- else {
+ } else {
dolog ("warning: Voice is not capturing\n");
}
}
DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
LPDIRECTSOUNDCAPTUREBUFFER dscb = ds->dsound_capture_buffer;
HRESULT hr;
- DWORD cpos, act_size;
+ DWORD rpos, act_size;
size_t req_size;
int err;
void *ret;
- hr = IDirectSoundCaptureBuffer_GetCurrentPosition(dscb, &cpos, NULL);
+ hr = IDirectSoundCaptureBuffer_GetCurrentPosition(dscb, NULL, &rpos);
if (FAILED(hr)) {
dsound_logerr(hr, "Could not get capture buffer position\n");
*size = 0;
return NULL;
}
- req_size = audio_ring_dist(cpos, hw->pos_emul, hw->size_emul);
- req_size = MIN(req_size, hw->size_emul - hw->pos_emul);
+ if (ds->first_time) {
+ hw->pos_emul = rpos;
+ ds->first_time = false;
+ }
+
+ req_size = audio_ring_dist(rpos, hw->pos_emul, hw->size_emul);
+ req_size = MIN(*size, MIN(req_size, hw->size_emul - hw->pos_emul));
+
+ if (req_size == 0) {
+ *size = 0;
+ return NULL;
+ }
err = dsound_lock_in(dscb, &hw->info, hw->pos_emul, req_size, &ret, NULL,
&act_size, NULL, false, ds->s);
g_free(s);
}
-static void *dsound_audio_init(Audiodev *dev)
+static void *dsound_audio_init(Audiodev *dev, Error **errp)
{
int err;
HRESULT hr;
- dsound *s = g_malloc0(sizeof(dsound));
+ dsound *s = g_new0(dsound, 1);
AudiodevDsoundOptions *dso;
assert(dev->driver == AUDIODEV_DRIVER_DSOUND);
);
if (FAILED (hr)) {
dsound_logerr (hr, "Could not create DirectSoundCapture instance\n");
- }
- else {
+ } else {
hr = IDirectSoundCapture_Initialize (s->dsound_capture, NULL);
if (FAILED (hr)) {
dsound_logerr (hr, "Could not initialize DirectSoundCapture\n");
}
}
- err = dsound_open (s);
+ err = dsound_set_cooperative_level(s);
if (err) {
dsound_audio_fini (s);
return NULL;
.init_out = dsound_init_out,
.fini_out = dsound_fini_out,
.write = audio_generic_write,
+ .buffer_get_free = dsound_buffer_get_free,
.get_buffer_out = dsound_get_buffer_out,
.put_buffer_out = dsound_put_buffer_out,
.enable_out = dsound_enable_out,
.init = dsound_audio_init,
.fini = dsound_audio_fini,
.pcm_ops = &dsound_pcm_ops,
- .can_be_default = 1,
.max_voices_out = INT_MAX,
.max_voices_in = 1,
.voice_size_out = sizeof (DSoundVoiceOut),