mirror of
https://github.com/mpv-player/mpv
synced 2025-04-01 23:00:41 +00:00
ao_dsound: uncrustify
This commit is contained in:
parent
92ae48db0f
commit
cee56e8623
@ -47,10 +47,10 @@
|
|||||||
|
|
||||||
static const ao_info_t info =
|
static const ao_info_t info =
|
||||||
{
|
{
|
||||||
"Windows DirectSound audio output",
|
"Windows DirectSound audio output",
|
||||||
"dsound",
|
"dsound",
|
||||||
"Gabor Szecsi <deje@miki.hu>",
|
"Gabor Szecsi <deje@miki.hu>",
|
||||||
""
|
""
|
||||||
};
|
};
|
||||||
|
|
||||||
LIBAO_EXTERN(dsound)
|
LIBAO_EXTERN(dsound)
|
||||||
@ -62,7 +62,9 @@ LIBAO_EXTERN(dsound)
|
|||||||
#define WAVE_FORMAT_DOLBY_AC3_SPDIF 0x0092
|
#define WAVE_FORMAT_DOLBY_AC3_SPDIF 0x0092
|
||||||
#define WAVE_FORMAT_EXTENSIBLE 0xFFFE
|
#define WAVE_FORMAT_EXTENSIBLE 0xFFFE
|
||||||
|
|
||||||
static const GUID KSDATAFORMAT_SUBTYPE_PCM = {0x1,0x0000,0x0010, {0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71}};
|
static const GUID KSDATAFORMAT_SUBTYPE_PCM = {
|
||||||
|
0x1, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
|
||||||
|
};
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
#define DSSPEAKER_HEADPHONE 0x00000001
|
#define DSSPEAKER_HEADPHONE 0x00000001
|
||||||
@ -75,15 +77,15 @@ static const GUID KSDATAFORMAT_SUBTYPE_PCM = {0x1,0x0000,0x0010, {0x80,0x00,0x00
|
|||||||
|
|
||||||
#ifndef _WAVEFORMATEXTENSIBLE_
|
#ifndef _WAVEFORMATEXTENSIBLE_
|
||||||
typedef struct {
|
typedef struct {
|
||||||
WAVEFORMATEX Format;
|
WAVEFORMATEX Format;
|
||||||
union {
|
union {
|
||||||
WORD wValidBitsPerSample; /* bits of precision */
|
WORD wValidBitsPerSample; /* bits of precision */
|
||||||
WORD wSamplesPerBlock; /* valid if wBitsPerSample==0 */
|
WORD wSamplesPerBlock; /* valid if wBitsPerSample==0 */
|
||||||
WORD wReserved; /* If neither applies, set to zero. */
|
WORD wReserved; /* If neither applies, set to zero. */
|
||||||
} Samples;
|
} Samples;
|
||||||
DWORD dwChannelMask; /* which channels are */
|
DWORD dwChannelMask; /* which channels are */
|
||||||
/* present in stream */
|
/* present in stream */
|
||||||
GUID SubFormat;
|
GUID SubFormat;
|
||||||
} WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE;
|
} WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -111,28 +113,28 @@ static int audio_volume;
|
|||||||
*/
|
*/
|
||||||
static char * dserr2str(int err)
|
static char * dserr2str(int err)
|
||||||
{
|
{
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case DS_OK: return "DS_OK";
|
case DS_OK: return "DS_OK";
|
||||||
case DS_NO_VIRTUALIZATION: return "DS_NO_VIRTUALIZATION";
|
case DS_NO_VIRTUALIZATION: return "DS_NO_VIRTUALIZATION";
|
||||||
case DSERR_ALLOCATED: return "DS_NO_VIRTUALIZATION";
|
case DSERR_ALLOCATED: return "DS_NO_VIRTUALIZATION";
|
||||||
case DSERR_CONTROLUNAVAIL: return "DSERR_CONTROLUNAVAIL";
|
case DSERR_CONTROLUNAVAIL: return "DSERR_CONTROLUNAVAIL";
|
||||||
case DSERR_INVALIDPARAM: return "DSERR_INVALIDPARAM";
|
case DSERR_INVALIDPARAM: return "DSERR_INVALIDPARAM";
|
||||||
case DSERR_INVALIDCALL: return "DSERR_INVALIDCALL";
|
case DSERR_INVALIDCALL: return "DSERR_INVALIDCALL";
|
||||||
case DSERR_GENERIC: return "DSERR_GENERIC";
|
case DSERR_GENERIC: return "DSERR_GENERIC";
|
||||||
case DSERR_PRIOLEVELNEEDED: return "DSERR_PRIOLEVELNEEDED";
|
case DSERR_PRIOLEVELNEEDED: return "DSERR_PRIOLEVELNEEDED";
|
||||||
case DSERR_OUTOFMEMORY: return "DSERR_OUTOFMEMORY";
|
case DSERR_OUTOFMEMORY: return "DSERR_OUTOFMEMORY";
|
||||||
case DSERR_BADFORMAT: return "DSERR_BADFORMAT";
|
case DSERR_BADFORMAT: return "DSERR_BADFORMAT";
|
||||||
case DSERR_UNSUPPORTED: return "DSERR_UNSUPPORTED";
|
case DSERR_UNSUPPORTED: return "DSERR_UNSUPPORTED";
|
||||||
case DSERR_NODRIVER: return "DSERR_NODRIVER";
|
case DSERR_NODRIVER: return "DSERR_NODRIVER";
|
||||||
case DSERR_ALREADYINITIALIZED: return "DSERR_ALREADYINITIALIZED";
|
case DSERR_ALREADYINITIALIZED: return "DSERR_ALREADYINITIALIZED";
|
||||||
case DSERR_NOAGGREGATION: return "DSERR_NOAGGREGATION";
|
case DSERR_NOAGGREGATION: return "DSERR_NOAGGREGATION";
|
||||||
case DSERR_BUFFERLOST: return "DSERR_BUFFERLOST";
|
case DSERR_BUFFERLOST: return "DSERR_BUFFERLOST";
|
||||||
case DSERR_OTHERAPPHASPRIO: return "DSERR_OTHERAPPHASPRIO";
|
case DSERR_OTHERAPPHASPRIO: return "DSERR_OTHERAPPHASPRIO";
|
||||||
case DSERR_UNINITIALIZED: return "DSERR_UNINITIALIZED";
|
case DSERR_UNINITIALIZED: return "DSERR_UNINITIALIZED";
|
||||||
case DSERR_NOINTERFACE: return "DSERR_NOINTERFACE";
|
case DSERR_NOINTERFACE: return "DSERR_NOINTERFACE";
|
||||||
case DSERR_ACCESSDENIED: return "DSERR_ACCESSDENIED";
|
case DSERR_ACCESSDENIED: return "DSERR_ACCESSDENIED";
|
||||||
default: return "unknown";
|
}
|
||||||
}
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -142,15 +144,15 @@ static void UninitDirectSound(void)
|
|||||||
{
|
{
|
||||||
// finally release the DirectSound object
|
// finally release the DirectSound object
|
||||||
if (hds) {
|
if (hds) {
|
||||||
IDirectSound_Release(hds);
|
IDirectSound_Release(hds);
|
||||||
hds = NULL;
|
hds = NULL;
|
||||||
}
|
}
|
||||||
// free DSOUND.DLL
|
// free DSOUND.DLL
|
||||||
if (hdsound_dll) {
|
if (hdsound_dll) {
|
||||||
FreeLibrary(hdsound_dll);
|
FreeLibrary(hdsound_dll);
|
||||||
hdsound_dll = NULL;
|
hdsound_dll = NULL;
|
||||||
}
|
}
|
||||||
mp_msg(MSGT_AO, MSGL_V, "ao_dsound: DirectSound uninitialized\n");
|
mp_msg(MSGT_AO, MSGL_V, "ao_dsound: DirectSound uninitialized\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -158,7 +160,7 @@ static void UninitDirectSound(void)
|
|||||||
*/
|
*/
|
||||||
static void print_help(void)
|
static void print_help(void)
|
||||||
{
|
{
|
||||||
mp_msg(MSGT_AO, MSGL_FATAL,
|
mp_msg(MSGT_AO, MSGL_FATAL,
|
||||||
"\n-ao dsound commandline help:\n"
|
"\n-ao dsound commandline help:\n"
|
||||||
"Example: mpv -ao dsound:device=1\n"
|
"Example: mpv -ao dsound:device=1\n"
|
||||||
" sets 1st device\n"
|
" sets 1st device\n"
|
||||||
@ -172,17 +174,17 @@ static void print_help(void)
|
|||||||
\brief enumerate direct sound devices
|
\brief enumerate direct sound devices
|
||||||
\return TRUE to continue with the enumeration
|
\return TRUE to continue with the enumeration
|
||||||
*/
|
*/
|
||||||
static BOOL CALLBACK DirectSoundEnum(LPGUID guid,LPCSTR desc,LPCSTR module,LPVOID context)
|
static BOOL CALLBACK DirectSoundEnum(LPGUID guid, LPCSTR desc, LPCSTR module,
|
||||||
|
LPVOID context)
|
||||||
{
|
{
|
||||||
int* device_index=context;
|
int *device_index = context;
|
||||||
mp_msg(MSGT_AO, MSGL_V,"%i %s ",*device_index,desc);
|
mp_msg(MSGT_AO, MSGL_V, "%i %s ", *device_index, desc);
|
||||||
if(device_num==*device_index){
|
if (device_num == *device_index) {
|
||||||
mp_msg(MSGT_AO, MSGL_V,"<--");
|
mp_msg(MSGT_AO, MSGL_V, "<--");
|
||||||
if(guid){
|
if (guid)
|
||||||
memcpy(&device,guid,sizeof(GUID));
|
memcpy(&device, guid, sizeof(GUID));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
mp_msg(MSGT_AO, MSGL_V,"\n");
|
mp_msg(MSGT_AO, MSGL_V, "\n");
|
||||||
(*device_index)++;
|
(*device_index)++;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -194,73 +196,83 @@ static BOOL CALLBACK DirectSoundEnum(LPGUID guid,LPCSTR desc,LPCSTR module,LPVOI
|
|||||||
*/
|
*/
|
||||||
static int InitDirectSound(void)
|
static int InitDirectSound(void)
|
||||||
{
|
{
|
||||||
DSCAPS dscaps;
|
DSCAPS dscaps;
|
||||||
|
|
||||||
// initialize directsound
|
// initialize directsound
|
||||||
HRESULT (WINAPI *OurDirectSoundCreate)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN);
|
HRESULT (WINAPI *OurDirectSoundCreate)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN);
|
||||||
HRESULT (WINAPI *OurDirectSoundEnumerate)(LPDSENUMCALLBACKA, LPVOID);
|
HRESULT (WINAPI *OurDirectSoundEnumerate)(LPDSENUMCALLBACKA, LPVOID);
|
||||||
int device_index=0;
|
int device_index = 0;
|
||||||
const opt_t subopts[] = {
|
const opt_t subopts[] = {
|
||||||
{"device", OPT_ARG_INT, &device_num,NULL},
|
{"device", OPT_ARG_INT, &device_num, NULL},
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
if (subopt_parse(ao_subdevice, subopts) != 0) {
|
if (subopt_parse(ao_subdevice, subopts) != 0) {
|
||||||
print_help();
|
print_help();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
hdsound_dll = LoadLibrary("DSOUND.DLL");
|
hdsound_dll = LoadLibrary("DSOUND.DLL");
|
||||||
if (hdsound_dll == NULL) {
|
if (hdsound_dll == NULL) {
|
||||||
mp_msg(MSGT_AO, MSGL_ERR, "ao_dsound: cannot load DSOUND.DLL\n");
|
mp_msg(MSGT_AO, MSGL_ERR, "ao_dsound: cannot load DSOUND.DLL\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
OurDirectSoundCreate = (void*)GetProcAddress(hdsound_dll, "DirectSoundCreate");
|
OurDirectSoundCreate = (void *)GetProcAddress(hdsound_dll,
|
||||||
OurDirectSoundEnumerate = (void*)GetProcAddress(hdsound_dll, "DirectSoundEnumerateA");
|
"DirectSoundCreate");
|
||||||
|
OurDirectSoundEnumerate = (void *)GetProcAddress(hdsound_dll,
|
||||||
|
"DirectSoundEnumerateA");
|
||||||
|
|
||||||
if (OurDirectSoundCreate == NULL || OurDirectSoundEnumerate == NULL) {
|
if (OurDirectSoundCreate == NULL || OurDirectSoundEnumerate == NULL) {
|
||||||
mp_msg(MSGT_AO, MSGL_ERR, "ao_dsound: GetProcAddress FAILED\n");
|
mp_msg(MSGT_AO, MSGL_ERR, "ao_dsound: GetProcAddress FAILED\n");
|
||||||
FreeLibrary(hdsound_dll);
|
FreeLibrary(hdsound_dll);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enumerate all directsound devices
|
// Enumerate all directsound devices
|
||||||
mp_msg(MSGT_AO, MSGL_V,"ao_dsound: Output Devices:\n");
|
mp_msg(MSGT_AO, MSGL_V, "ao_dsound: Output Devices:\n");
|
||||||
OurDirectSoundEnumerate(DirectSoundEnum,&device_index);
|
OurDirectSoundEnumerate(DirectSoundEnum, &device_index);
|
||||||
|
|
||||||
// Create the direct sound object
|
// Create the direct sound object
|
||||||
if FAILED(OurDirectSoundCreate((device_num)?&device:NULL, &hds, NULL )) {
|
if (FAILED(OurDirectSoundCreate((device_num) ? &device : NULL, &hds,
|
||||||
mp_msg(MSGT_AO, MSGL_ERR, "ao_dsound: cannot create a DirectSound device\n");
|
NULL)))
|
||||||
FreeLibrary(hdsound_dll);
|
{
|
||||||
return 0;
|
mp_msg(MSGT_AO, MSGL_ERR,
|
||||||
}
|
"ao_dsound: cannot create a DirectSound device\n");
|
||||||
|
FreeLibrary(hdsound_dll);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Set DirectSound Cooperative level, ie what control we want over Windows
|
/* Set DirectSound Cooperative level, ie what control we want over Windows
|
||||||
* sound device. In our case, DSSCL_EXCLUSIVE means that we can modify the
|
* sound device. In our case, DSSCL_EXCLUSIVE means that we can modify the
|
||||||
* settings of the primary buffer, but also that only the sound of our
|
* settings of the primary buffer, but also that only the sound of our
|
||||||
* application will be hearable when it will have the focus.
|
* application will be hearable when it will have the focus.
|
||||||
* !!! (this is not really working as intended yet because to set the
|
* !!! (this is not really working as intended yet because to set the
|
||||||
* cooperative level you need the window handle of your application, and
|
* cooperative level you need the window handle of your application, and
|
||||||
* I don't know of any easy way to get it. Especially since we might play
|
* I don't know of any easy way to get it. Especially since we might play
|
||||||
* sound without any video, and so what window handle should we use ???
|
* sound without any video, and so what window handle should we use ???
|
||||||
* The hack for now is to use the Desktop window handle - it seems to be
|
* The hack for now is to use the Desktop window handle - it seems to be
|
||||||
* working */
|
* working */
|
||||||
if (IDirectSound_SetCooperativeLevel(hds, GetDesktopWindow(), DSSCL_EXCLUSIVE)) {
|
if (IDirectSound_SetCooperativeLevel(hds, GetDesktopWindow(),
|
||||||
mp_msg(MSGT_AO, MSGL_ERR, "ao_dsound: cannot set direct sound cooperative level\n");
|
DSSCL_EXCLUSIVE))
|
||||||
IDirectSound_Release(hds);
|
{
|
||||||
FreeLibrary(hdsound_dll);
|
mp_msg(MSGT_AO, MSGL_ERR,
|
||||||
return 0;
|
"ao_dsound: cannot set direct sound cooperative level\n");
|
||||||
}
|
IDirectSound_Release(hds);
|
||||||
mp_msg(MSGT_AO, MSGL_V, "ao_dsound: DirectSound initialized\n");
|
FreeLibrary(hdsound_dll);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
mp_msg(MSGT_AO, MSGL_V, "ao_dsound: DirectSound initialized\n");
|
||||||
|
|
||||||
memset(&dscaps, 0, sizeof(DSCAPS));
|
memset(&dscaps, 0, sizeof(DSCAPS));
|
||||||
dscaps.dwSize = sizeof(DSCAPS);
|
dscaps.dwSize = sizeof(DSCAPS);
|
||||||
if (DS_OK == IDirectSound_GetCaps(hds, &dscaps)) {
|
if (DS_OK == IDirectSound_GetCaps(hds, &dscaps)) {
|
||||||
if (dscaps.dwFlags & DSCAPS_EMULDRIVER) mp_msg(MSGT_AO, MSGL_V, "ao_dsound: DirectSound is emulated, waveOut may give better performance\n");
|
if (dscaps.dwFlags & DSCAPS_EMULDRIVER)
|
||||||
} else {
|
mp_msg(MSGT_AO, MSGL_V,
|
||||||
mp_msg(MSGT_AO, MSGL_V, "ao_dsound: cannot get device capabilities\n");
|
"ao_dsound: DirectSound is emulated, waveOut may give better performance\n");
|
||||||
}
|
} else {
|
||||||
|
mp_msg(MSGT_AO, MSGL_V, "ao_dsound: cannot get device capabilities\n");
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -268,14 +280,14 @@ static int InitDirectSound(void)
|
|||||||
*/
|
*/
|
||||||
static void DestroyBuffer(void)
|
static void DestroyBuffer(void)
|
||||||
{
|
{
|
||||||
if (hdsbuf) {
|
if (hdsbuf) {
|
||||||
IDirectSoundBuffer_Release(hdsbuf);
|
IDirectSoundBuffer_Release(hdsbuf);
|
||||||
hdsbuf = NULL;
|
hdsbuf = NULL;
|
||||||
}
|
}
|
||||||
if (hdspribuf) {
|
if (hdspribuf) {
|
||||||
IDirectSoundBuffer_Release(hdspribuf);
|
IDirectSoundBuffer_Release(hdspribuf);
|
||||||
hdspribuf = NULL;
|
hdspribuf = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -286,57 +298,58 @@ static void DestroyBuffer(void)
|
|||||||
*/
|
*/
|
||||||
static int write_buffer(unsigned char *data, int len)
|
static int write_buffer(unsigned char *data, int len)
|
||||||
{
|
{
|
||||||
HRESULT res;
|
HRESULT res;
|
||||||
LPVOID lpvPtr1;
|
LPVOID lpvPtr1;
|
||||||
DWORD dwBytes1;
|
DWORD dwBytes1;
|
||||||
LPVOID lpvPtr2;
|
LPVOID lpvPtr2;
|
||||||
DWORD dwBytes2;
|
DWORD dwBytes2;
|
||||||
|
|
||||||
underrun_check = 0;
|
underrun_check = 0;
|
||||||
|
|
||||||
// Lock the buffer
|
// Lock the buffer
|
||||||
res = IDirectSoundBuffer_Lock(hdsbuf,write_offset, len, &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0);
|
res = IDirectSoundBuffer_Lock(hdsbuf, write_offset, len, &lpvPtr1, &dwBytes1,
|
||||||
// If the buffer was lost, restore and retry lock.
|
&lpvPtr2, &dwBytes2, 0);
|
||||||
if (DSERR_BUFFERLOST == res)
|
// If the buffer was lost, restore and retry lock.
|
||||||
{
|
if (DSERR_BUFFERLOST == res) {
|
||||||
IDirectSoundBuffer_Restore(hdsbuf);
|
IDirectSoundBuffer_Restore(hdsbuf);
|
||||||
res = IDirectSoundBuffer_Lock(hdsbuf,write_offset, len, &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0);
|
res = IDirectSoundBuffer_Lock(hdsbuf, write_offset, len, &lpvPtr1,
|
||||||
}
|
&dwBytes1, &lpvPtr2, &dwBytes2, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (SUCCEEDED(res))
|
if (SUCCEEDED(res)) {
|
||||||
{
|
if (!AF_FORMAT_IS_AC3(ao_data.format)) {
|
||||||
if (!AF_FORMAT_IS_AC3(ao_data.format)) {
|
|
||||||
memcpy(lpvPtr1, data, dwBytes1);
|
memcpy(lpvPtr1, data, dwBytes1);
|
||||||
if (lpvPtr2 != NULL)
|
if (lpvPtr2 != NULL)
|
||||||
memcpy(lpvPtr2, (char *)data + dwBytes1, dwBytes2);
|
memcpy(lpvPtr2, (char *)data + dwBytes1, dwBytes2);
|
||||||
|
|
||||||
write_offset+=dwBytes1+dwBytes2;
|
write_offset += dwBytes1 + dwBytes2;
|
||||||
if(write_offset>=buffer_size)
|
if (write_offset >= buffer_size)
|
||||||
write_offset=dwBytes2;
|
write_offset = dwBytes2;
|
||||||
} else {
|
} else {
|
||||||
// Write to pointers without reordering.
|
// Write to pointers without reordering.
|
||||||
memcpy(lpvPtr1,data,dwBytes1);
|
memcpy(lpvPtr1, data, dwBytes1);
|
||||||
if (NULL != lpvPtr2 )memcpy(lpvPtr2,data+dwBytes1,dwBytes2);
|
if (NULL != lpvPtr2)
|
||||||
write_offset+=dwBytes1+dwBytes2;
|
memcpy(lpvPtr2, data + dwBytes1, dwBytes2);
|
||||||
if(write_offset>=buffer_size)write_offset=dwBytes2;
|
write_offset += dwBytes1 + dwBytes2;
|
||||||
}
|
if (write_offset >= buffer_size)
|
||||||
|
write_offset = dwBytes2;
|
||||||
|
}
|
||||||
|
|
||||||
// Release the data back to DirectSound.
|
// Release the data back to DirectSound.
|
||||||
res = IDirectSoundBuffer_Unlock(hdsbuf,lpvPtr1,dwBytes1,lpvPtr2,dwBytes2);
|
res = IDirectSoundBuffer_Unlock(hdsbuf, lpvPtr1, dwBytes1, lpvPtr2,
|
||||||
if (SUCCEEDED(res))
|
dwBytes2);
|
||||||
{
|
if (SUCCEEDED(res)) {
|
||||||
// Success.
|
// Success.
|
||||||
DWORD status;
|
DWORD status;
|
||||||
IDirectSoundBuffer_GetStatus(hdsbuf, &status);
|
IDirectSoundBuffer_GetStatus(hdsbuf, &status);
|
||||||
if (!(status & DSBSTATUS_PLAYING)){
|
if (!(status & DSBSTATUS_PLAYING))
|
||||||
res = IDirectSoundBuffer_Play(hdsbuf, 0, 0, DSBPLAY_LOOPING);
|
res = IDirectSoundBuffer_Play(hdsbuf, 0, 0, DSBPLAY_LOOPING);
|
||||||
}
|
return dwBytes1 + dwBytes2;
|
||||||
return dwBytes1+dwBytes2;
|
}
|
||||||
}
|
}
|
||||||
}
|
// Lock, Unlock, or Restore failed.
|
||||||
// Lock, Unlock, or Restore failed.
|
return 0;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************************/
|
/***************************************************************************************/
|
||||||
@ -349,24 +362,24 @@ static int write_buffer(unsigned char *data, int len)
|
|||||||
*/
|
*/
|
||||||
static int control(int cmd, void *arg)
|
static int control(int cmd, void *arg)
|
||||||
{
|
{
|
||||||
DWORD volume;
|
DWORD volume;
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case AOCONTROL_GET_VOLUME: {
|
case AOCONTROL_GET_VOLUME: {
|
||||||
ao_control_vol_t* vol = (ao_control_vol_t*)arg;
|
ao_control_vol_t *vol = (ao_control_vol_t *)arg;
|
||||||
vol->left = vol->right = audio_volume;
|
vol->left = vol->right = audio_volume;
|
||||||
return CONTROL_OK;
|
return CONTROL_OK;
|
||||||
}
|
}
|
||||||
case AOCONTROL_SET_VOLUME: {
|
case AOCONTROL_SET_VOLUME: {
|
||||||
ao_control_vol_t* vol = (ao_control_vol_t*)arg;
|
ao_control_vol_t *vol = (ao_control_vol_t *)arg;
|
||||||
volume = audio_volume = vol->right;
|
volume = audio_volume = vol->right;
|
||||||
if (volume < 1)
|
if (volume < 1)
|
||||||
volume = 1;
|
volume = 1;
|
||||||
volume = (DWORD)(log10(volume) * 5000.0) - 10000;
|
volume = (DWORD)(log10(volume) * 5000.0) - 10000;
|
||||||
IDirectSoundBuffer_SetVolume(hdsbuf, volume);
|
IDirectSoundBuffer_SetVolume(hdsbuf, volume);
|
||||||
return CONTROL_OK;
|
return CONTROL_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -380,118 +393,138 @@ static int control(int cmd, void *arg)
|
|||||||
static int init(int rate, const struct mp_chmap *channels, int format, int flags)
|
static int init(int rate, const struct mp_chmap *channels, int format, int flags)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
if (!InitDirectSound()) return 0;
|
if (!InitDirectSound())
|
||||||
|
return 0;
|
||||||
|
|
||||||
global_ao->no_persistent_volume = true;
|
global_ao->no_persistent_volume = true;
|
||||||
audio_volume = 100;
|
audio_volume = 100;
|
||||||
|
|
||||||
// ok, now create the buffers
|
// ok, now create the buffers
|
||||||
WAVEFORMATEXTENSIBLE wformat;
|
WAVEFORMATEXTENSIBLE wformat;
|
||||||
DSBUFFERDESC dsbpridesc;
|
DSBUFFERDESC dsbpridesc;
|
||||||
DSBUFFERDESC dsbdesc;
|
DSBUFFERDESC dsbdesc;
|
||||||
|
|
||||||
if (AF_FORMAT_IS_AC3(format)) {
|
if (AF_FORMAT_IS_AC3(format))
|
||||||
format = AF_FORMAT_AC3_NE;
|
format = AF_FORMAT_AC3_NE;
|
||||||
} else {
|
else {
|
||||||
struct mp_chmap_sel sel = {0};
|
struct mp_chmap_sel sel = {
|
||||||
mp_chmap_sel_add_waveext(&sel);
|
0
|
||||||
if (!ao_chmap_sel_adjust(&ao_data, &sel, &ao_data.channels))
|
};
|
||||||
return 0;
|
mp_chmap_sel_add_waveext(&sel);
|
||||||
|
if (!ao_chmap_sel_adjust(&ao_data, &sel, &ao_data.channels))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
switch (format) {
|
||||||
|
case AF_FORMAT_AC3_NE:
|
||||||
|
case AF_FORMAT_S24_LE:
|
||||||
|
case AF_FORMAT_S16_LE:
|
||||||
|
case AF_FORMAT_U8:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mp_msg(MSGT_AO, MSGL_V,
|
||||||
|
"ao_dsound: format %s not supported defaulting to Signed 16-bit Little-Endian\n",
|
||||||
|
af_fmt2str_short(format));
|
||||||
|
format = AF_FORMAT_S16_LE;
|
||||||
|
}
|
||||||
|
//fill global ao_data
|
||||||
|
ao_data.samplerate = rate;
|
||||||
|
ao_data.format = format;
|
||||||
|
ao_data.bps = ao_data.channels.num * rate * (af_fmt2bits(format) >> 3);
|
||||||
|
if (ao_data.buffersize == -1)
|
||||||
|
ao_data.buffersize = ao_data.bps; // space for 1 sec
|
||||||
|
mp_msg(MSGT_AO, MSGL_V,
|
||||||
|
"ao_dsound: Samplerate:%iHz Channels:%i Format:%s\n", rate,
|
||||||
|
ao_data.channels.num, af_fmt2str_short(format));
|
||||||
|
mp_msg(MSGT_AO, MSGL_V, "ao_dsound: Buffersize:%d bytes (%d msec)\n",
|
||||||
|
ao_data.buffersize, ao_data.buffersize / ao_data.bps * 1000);
|
||||||
|
|
||||||
|
//fill waveformatex
|
||||||
|
ZeroMemory(&wformat, sizeof(WAVEFORMATEXTENSIBLE));
|
||||||
|
wformat.Format.cbSize = (ao_data.channels.num > 2)
|
||||||
|
? sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) : 0;
|
||||||
|
wformat.Format.nChannels = ao_data.channels.num;
|
||||||
|
wformat.Format.nSamplesPerSec = rate;
|
||||||
|
if (AF_FORMAT_IS_AC3(format)) {
|
||||||
|
wformat.Format.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF;
|
||||||
|
wformat.Format.wBitsPerSample = 16;
|
||||||
|
wformat.Format.nBlockAlign = 4;
|
||||||
|
} else {
|
||||||
|
wformat.Format.wFormatTag = (ao_data.channels.num > 2)
|
||||||
|
? WAVE_FORMAT_EXTENSIBLE : WAVE_FORMAT_PCM;
|
||||||
|
wformat.Format.wBitsPerSample = af_fmt2bits(format);
|
||||||
|
wformat.Format.nBlockAlign = wformat.Format.nChannels *
|
||||||
|
(wformat.Format.wBitsPerSample >> 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fill in primary sound buffer descriptor
|
||||||
|
memset(&dsbpridesc, 0, sizeof(DSBUFFERDESC));
|
||||||
|
dsbpridesc.dwSize = sizeof(DSBUFFERDESC);
|
||||||
|
dsbpridesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
|
||||||
|
dsbpridesc.dwBufferBytes = 0;
|
||||||
|
dsbpridesc.lpwfxFormat = NULL;
|
||||||
|
|
||||||
|
// fill in the secondary sound buffer (=stream buffer) descriptor
|
||||||
|
memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
|
||||||
|
dsbdesc.dwSize = sizeof(DSBUFFERDESC);
|
||||||
|
dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 /** Better position accuracy */
|
||||||
|
| DSBCAPS_GLOBALFOCUS /** Allows background playing */
|
||||||
|
| DSBCAPS_CTRLVOLUME; /** volume control enabled */
|
||||||
|
|
||||||
|
if (ao_data.channels.num > 2) {
|
||||||
|
wformat.dwChannelMask = mp_chmap_to_waveext(&ao_data.channels);
|
||||||
|
wformat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
|
||||||
|
wformat.Samples.wValidBitsPerSample = wformat.Format.wBitsPerSample;
|
||||||
|
// Needed for 5.1 on emu101k - shit soundblaster
|
||||||
|
dsbdesc.dwFlags |= DSBCAPS_LOCHARDWARE;
|
||||||
|
}
|
||||||
|
wformat.Format.nAvgBytesPerSec = wformat.Format.nSamplesPerSec *
|
||||||
|
wformat.Format.nBlockAlign;
|
||||||
|
|
||||||
|
dsbdesc.dwBufferBytes = ao_data.buffersize;
|
||||||
|
dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&wformat;
|
||||||
|
buffer_size = dsbdesc.dwBufferBytes;
|
||||||
|
write_offset = 0;
|
||||||
|
min_free_space = wformat.Format.nBlockAlign;
|
||||||
|
ao_data.outburst = wformat.Format.nBlockAlign * 512;
|
||||||
|
|
||||||
|
// create primary buffer and set its format
|
||||||
|
|
||||||
|
res = IDirectSound_CreateSoundBuffer(hds, &dsbpridesc, &hdspribuf, NULL);
|
||||||
|
if (res != DS_OK) {
|
||||||
|
UninitDirectSound();
|
||||||
|
mp_msg(MSGT_AO, MSGL_ERR,
|
||||||
|
"ao_dsound: cannot create primary buffer (%s)\n",
|
||||||
|
dserr2str(res));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
res = IDirectSoundBuffer_SetFormat(hdspribuf, (WAVEFORMATEX *)&wformat);
|
||||||
|
if (res != DS_OK) {
|
||||||
|
mp_msg(MSGT_AO, MSGL_WARN,
|
||||||
|
"ao_dsound: cannot set primary buffer format (%s), using "
|
||||||
|
"standard setting (bad quality)", dserr2str(res));
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_msg(MSGT_AO, MSGL_V, "ao_dsound: primary buffer created\n");
|
||||||
|
|
||||||
|
// now create the stream buffer
|
||||||
|
|
||||||
|
res = IDirectSound_CreateSoundBuffer(hds, &dsbdesc, &hdsbuf, NULL);
|
||||||
|
if (res != DS_OK) {
|
||||||
|
if (dsbdesc.dwFlags & DSBCAPS_LOCHARDWARE) {
|
||||||
|
// Try without DSBCAPS_LOCHARDWARE
|
||||||
|
dsbdesc.dwFlags &= ~DSBCAPS_LOCHARDWARE;
|
||||||
|
res = IDirectSound_CreateSoundBuffer(hds, &dsbdesc, &hdsbuf, NULL);
|
||||||
}
|
}
|
||||||
switch(format){
|
if (res != DS_OK) {
|
||||||
case AF_FORMAT_AC3_NE:
|
UninitDirectSound();
|
||||||
case AF_FORMAT_S24_LE:
|
mp_msg(MSGT_AO, MSGL_ERR,
|
||||||
case AF_FORMAT_S16_LE:
|
"ao_dsound: cannot create secondary (stream)buffer (%s)\n",
|
||||||
case AF_FORMAT_U8:
|
dserr2str(res));
|
||||||
break;
|
return 0;
|
||||||
default:
|
}
|
||||||
mp_msg(MSGT_AO, MSGL_V,"ao_dsound: format %s not supported defaulting to Signed 16-bit Little-Endian\n",af_fmt2str_short(format));
|
}
|
||||||
format=AF_FORMAT_S16_LE;
|
mp_msg(MSGT_AO, MSGL_V, "ao_dsound: secondary (stream)buffer created\n");
|
||||||
}
|
return 1;
|
||||||
//fill global ao_data
|
|
||||||
ao_data.samplerate = rate;
|
|
||||||
ao_data.format = format;
|
|
||||||
ao_data.bps = ao_data.channels.num * rate * (af_fmt2bits(format)>>3);
|
|
||||||
if(ao_data.buffersize==-1) ao_data.buffersize = ao_data.bps; // space for 1 sec
|
|
||||||
mp_msg(MSGT_AO, MSGL_V,"ao_dsound: Samplerate:%iHz Channels:%i Format:%s\n", rate, ao_data.channels.num, af_fmt2str_short(format));
|
|
||||||
mp_msg(MSGT_AO, MSGL_V,"ao_dsound: Buffersize:%d bytes (%d msec)\n", ao_data.buffersize, ao_data.buffersize / ao_data.bps * 1000);
|
|
||||||
|
|
||||||
//fill waveformatex
|
|
||||||
ZeroMemory(&wformat, sizeof(WAVEFORMATEXTENSIBLE));
|
|
||||||
wformat.Format.cbSize = (ao_data.channels.num > 2) ? sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX) : 0;
|
|
||||||
wformat.Format.nChannels = ao_data.channels.num;
|
|
||||||
wformat.Format.nSamplesPerSec = rate;
|
|
||||||
if (AF_FORMAT_IS_AC3(format)) {
|
|
||||||
wformat.Format.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF;
|
|
||||||
wformat.Format.wBitsPerSample = 16;
|
|
||||||
wformat.Format.nBlockAlign = 4;
|
|
||||||
} else {
|
|
||||||
wformat.Format.wFormatTag = (ao_data.channels.num > 2) ? WAVE_FORMAT_EXTENSIBLE : WAVE_FORMAT_PCM;
|
|
||||||
wformat.Format.wBitsPerSample = af_fmt2bits(format);
|
|
||||||
wformat.Format.nBlockAlign = wformat.Format.nChannels * (wformat.Format.wBitsPerSample >> 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
// fill in primary sound buffer descriptor
|
|
||||||
memset(&dsbpridesc, 0, sizeof(DSBUFFERDESC));
|
|
||||||
dsbpridesc.dwSize = sizeof(DSBUFFERDESC);
|
|
||||||
dsbpridesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
|
|
||||||
dsbpridesc.dwBufferBytes = 0;
|
|
||||||
dsbpridesc.lpwfxFormat = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
// fill in the secondary sound buffer (=stream buffer) descriptor
|
|
||||||
memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
|
|
||||||
dsbdesc.dwSize = sizeof(DSBUFFERDESC);
|
|
||||||
dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 /** Better position accuracy */
|
|
||||||
| DSBCAPS_GLOBALFOCUS /** Allows background playing */
|
|
||||||
| DSBCAPS_CTRLVOLUME; /** volume control enabled */
|
|
||||||
|
|
||||||
if (ao_data.channels.num > 2) {
|
|
||||||
wformat.dwChannelMask = mp_chmap_to_waveext(&ao_data.channels);
|
|
||||||
wformat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
|
|
||||||
wformat.Samples.wValidBitsPerSample = wformat.Format.wBitsPerSample;
|
|
||||||
// Needed for 5.1 on emu101k - shit soundblaster
|
|
||||||
dsbdesc.dwFlags |= DSBCAPS_LOCHARDWARE;
|
|
||||||
}
|
|
||||||
wformat.Format.nAvgBytesPerSec = wformat.Format.nSamplesPerSec * wformat.Format.nBlockAlign;
|
|
||||||
|
|
||||||
dsbdesc.dwBufferBytes = ao_data.buffersize;
|
|
||||||
dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&wformat;
|
|
||||||
buffer_size = dsbdesc.dwBufferBytes;
|
|
||||||
write_offset = 0;
|
|
||||||
min_free_space = wformat.Format.nBlockAlign;
|
|
||||||
ao_data.outburst = wformat.Format.nBlockAlign * 512;
|
|
||||||
|
|
||||||
// create primary buffer and set its format
|
|
||||||
|
|
||||||
res = IDirectSound_CreateSoundBuffer( hds, &dsbpridesc, &hdspribuf, NULL );
|
|
||||||
if ( res != DS_OK ) {
|
|
||||||
UninitDirectSound();
|
|
||||||
mp_msg(MSGT_AO, MSGL_ERR,"ao_dsound: cannot create primary buffer (%s)\n", dserr2str(res));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
res = IDirectSoundBuffer_SetFormat( hdspribuf, (WAVEFORMATEX *)&wformat );
|
|
||||||
if ( res != DS_OK ) mp_msg(MSGT_AO, MSGL_WARN,"ao_dsound: cannot set primary buffer format (%s), using standard setting (bad quality)", dserr2str(res));
|
|
||||||
|
|
||||||
mp_msg(MSGT_AO, MSGL_V, "ao_dsound: primary buffer created\n");
|
|
||||||
|
|
||||||
// now create the stream buffer
|
|
||||||
|
|
||||||
res = IDirectSound_CreateSoundBuffer(hds, &dsbdesc, &hdsbuf, NULL);
|
|
||||||
if (res != DS_OK) {
|
|
||||||
if (dsbdesc.dwFlags & DSBCAPS_LOCHARDWARE) {
|
|
||||||
// Try without DSBCAPS_LOCHARDWARE
|
|
||||||
dsbdesc.dwFlags &= ~DSBCAPS_LOCHARDWARE;
|
|
||||||
res = IDirectSound_CreateSoundBuffer(hds, &dsbdesc, &hdsbuf, NULL);
|
|
||||||
}
|
|
||||||
if (res != DS_OK) {
|
|
||||||
UninitDirectSound();
|
|
||||||
mp_msg(MSGT_AO, MSGL_ERR, "ao_dsound: cannot create secondary (stream)buffer (%s)\n", dserr2str(res));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mp_msg(MSGT_AO, MSGL_V, "ao_dsound: secondary (stream)buffer created\n");
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -501,11 +534,11 @@ static int init(int rate, const struct mp_chmap *channels, int format, int flags
|
|||||||
*/
|
*/
|
||||||
static void reset(void)
|
static void reset(void)
|
||||||
{
|
{
|
||||||
IDirectSoundBuffer_Stop(hdsbuf);
|
IDirectSoundBuffer_Stop(hdsbuf);
|
||||||
// reset directsound buffer
|
// reset directsound buffer
|
||||||
IDirectSoundBuffer_SetCurrentPosition(hdsbuf, 0);
|
IDirectSoundBuffer_SetCurrentPosition(hdsbuf, 0);
|
||||||
write_offset=0;
|
write_offset = 0;
|
||||||
underrun_check=0;
|
underrun_check = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -513,7 +546,7 @@ static void reset(void)
|
|||||||
*/
|
*/
|
||||||
static void audio_pause(void)
|
static void audio_pause(void)
|
||||||
{
|
{
|
||||||
IDirectSoundBuffer_Stop(hdsbuf);
|
IDirectSoundBuffer_Stop(hdsbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -521,7 +554,7 @@ static void audio_pause(void)
|
|||||||
*/
|
*/
|
||||||
static void audio_resume(void)
|
static void audio_resume(void)
|
||||||
{
|
{
|
||||||
IDirectSoundBuffer_Play(hdsbuf, 0, 0, DSBPLAY_LOOPING);
|
IDirectSoundBuffer_Play(hdsbuf, 0, 0, DSBPLAY_LOOPING);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -530,51 +563,53 @@ static void audio_resume(void)
|
|||||||
*/
|
*/
|
||||||
static void uninit(int immed)
|
static void uninit(int immed)
|
||||||
{
|
{
|
||||||
if (!immed)
|
if (!immed)
|
||||||
mp_sleep_us(get_delay() * 1000000);
|
mp_sleep_us(get_delay() * 1000000);
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
DestroyBuffer();
|
DestroyBuffer();
|
||||||
UninitDirectSound();
|
UninitDirectSound();
|
||||||
}
|
}
|
||||||
|
|
||||||
// return exact number of free (safe to write) bytes
|
// return exact number of free (safe to write) bytes
|
||||||
static int check_free_buffer_size(void)
|
static int check_free_buffer_size(void)
|
||||||
{
|
{
|
||||||
int space;
|
int space;
|
||||||
DWORD play_offset;
|
DWORD play_offset;
|
||||||
IDirectSoundBuffer_GetCurrentPosition(hdsbuf,&play_offset,NULL);
|
IDirectSoundBuffer_GetCurrentPosition(hdsbuf, &play_offset, NULL);
|
||||||
space=buffer_size-(write_offset-play_offset);
|
space = buffer_size - (write_offset - play_offset);
|
||||||
// | | <-- const --> | | |
|
// | | <-- const --> | | |
|
||||||
// buffer start play_cursor write_cursor write_offset buffer end
|
// buffer start play_cursor write_cursor write_offset buffer end
|
||||||
// play_cursor is the actual postion of the play cursor
|
// play_cursor is the actual postion of the play cursor
|
||||||
// write_cursor is the position after which it is assumed to be save to write data
|
// write_cursor is the position after which it is assumed to be save to write data
|
||||||
// write_offset is the postion where we actually write the data to
|
// write_offset is the postion where we actually write the data to
|
||||||
if(space > buffer_size)space -= buffer_size; // write_offset < play_offset
|
if (space > buffer_size)
|
||||||
// Check for buffer underruns. An underrun happens if DirectSound
|
space -= buffer_size; // write_offset < play_offset
|
||||||
// started to play old data beyond the current write_offset. Detect this
|
// Check for buffer underruns. An underrun happens if DirectSound
|
||||||
// by checking whether the free space shrinks, even though no data was
|
// started to play old data beyond the current write_offset. Detect this
|
||||||
// written (i.e. no write_buffer). Doesn't always work, but the only
|
// by checking whether the free space shrinks, even though no data was
|
||||||
// reason we need this is to deal with the situation when playback ends,
|
// written (i.e. no write_buffer). Doesn't always work, but the only
|
||||||
// and the buffer is only half-filled.
|
// reason we need this is to deal with the situation when playback ends,
|
||||||
if (space < underrun_check) {
|
// and the buffer is only half-filled.
|
||||||
// there's no useful data in the buffers
|
if (space < underrun_check) {
|
||||||
space = buffer_size;
|
// there's no useful data in the buffers
|
||||||
reset();
|
space = buffer_size;
|
||||||
}
|
reset();
|
||||||
underrun_check = space;
|
}
|
||||||
return space;
|
underrun_check = space;
|
||||||
|
return space;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief find out how many bytes can be written into the audio buffer without
|
\brief find out how many bytes can be written into the audio buffer without
|
||||||
\return free space in bytes, has to return 0 if the buffer is almost full
|
\return free space in bytes, has to return 0 if the buffer is almost full
|
||||||
*/
|
*/
|
||||||
static int get_space(void)
|
static int get_space(void)
|
||||||
{
|
{
|
||||||
int space = check_free_buffer_size();
|
int space = check_free_buffer_size();
|
||||||
if(space < min_free_space)return 0;
|
if (space < min_free_space)
|
||||||
return space-min_free_space;
|
return 0;
|
||||||
|
return space - min_free_space;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -584,14 +619,15 @@ static int get_space(void)
|
|||||||
\param flags currently unused
|
\param flags currently unused
|
||||||
\return number of played bytes
|
\return number of played bytes
|
||||||
*/
|
*/
|
||||||
static int play(void* data, int len, int flags)
|
static int play(void *data, int len, int flags)
|
||||||
{
|
{
|
||||||
int space = check_free_buffer_size();
|
int space = check_free_buffer_size();
|
||||||
if(space < len) len = space;
|
if (space < len)
|
||||||
|
len = space;
|
||||||
|
|
||||||
if (!(flags & AOPLAY_FINAL_CHUNK))
|
if (!(flags & AOPLAY_FINAL_CHUNK))
|
||||||
len = (len / ao_data.outburst) * ao_data.outburst;
|
len = (len / ao_data.outburst) * ao_data.outburst;
|
||||||
return write_buffer(data, len);
|
return write_buffer(data, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -600,6 +636,6 @@ static int play(void* data, int len, int flags)
|
|||||||
*/
|
*/
|
||||||
static float get_delay(void)
|
static float get_delay(void)
|
||||||
{
|
{
|
||||||
int space = check_free_buffer_size();
|
int space = check_free_buffer_size();
|
||||||
return (float)(buffer_size - space) / (float)ao_data.bps;
|
return (float)(buffer_size - space) / (float)ao_data.bps;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user