#if defined(MPT_BUILD_WINESUPPORT_WRAPPER) #include "NativeConfig.h" #include #include #include "Native.h" #include "NativeUtils.h" #include "NativeSoundDevice.h" #ifdef _MSC_VER #pragma warning(disable:4098) /* 'void' function returning a value */ #endif #define WINE_THREAD #ifdef __cplusplus extern "C" { #endif OPENMPT_WINESUPPORT_WRAPPER_API uintptr_t OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_Init(void) { return OpenMPT_Init(); } OPENMPT_WINESUPPORT_WRAPPER_API uintptr_t OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_Fini(void) { return OpenMPT_Fini(); } OPENMPT_WINESUPPORT_WRAPPER_API void * OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_Alloc( size_t size ) { return OpenMPT_Alloc( size ); } OPENMPT_WINESUPPORT_WRAPPER_API void OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_Free( void * mem ) { return OpenMPT_Free( mem ); } OPENMPT_WINESUPPORT_WRAPPER_API size_t OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_String_Length( const char * str ) { return OpenMPT_String_Length( str ); } OPENMPT_WINESUPPORT_WRAPPER_API char * OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_String_Duplicate( const char * src ) { return OpenMPT_String_Duplicate( src ); } OPENMPT_WINESUPPORT_WRAPPER_API void OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_String_Free( char * str ) { return OpenMPT_String_Free( str ); } OPENMPT_WINESUPPORT_WRAPPER_API char * OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_EnumerateDevices() { return OpenMPT_SoundDevice_EnumerateDevices(); } typedef struct OpenMPT_Wine_Wrapper_SoundDevice_IMessageReceiver { void * inst; void (OPENMPT_WINESUPPORT_WRAPPER_CALL * SoundDeviceMessageFunc)( void * inst, uintptr_t level, const char * message ); } OpenMPT_Wine_Wrapper_SoundDevice_IMessageReceiver; typedef struct OpenMPT_Wine_Wrapper_SoundDevice_ICallback { void * inst; // main thread void (OPENMPT_WINESUPPORT_WRAPPER_CALL * SoundCallbackGetReferenceClockNowNanosecondsFunc)( void * inst, uint64_t * result ); void (OPENMPT_WINESUPPORT_WRAPPER_CALL * SoundCallbackPreStartFunc)( void * inst ); void (OPENMPT_WINESUPPORT_WRAPPER_CALL * SoundCallbackPostStopFunc)( void * inst ); void (OPENMPT_WINESUPPORT_WRAPPER_CALL * SoundCallbackIsLockedByCurrentThreadFunc)( void * inst, uintptr_t * result ); // audio thread void (OPENMPT_WINESUPPORT_WRAPPER_CALL * SoundCallbackLockFunc)( void * inst ); void (OPENMPT_WINESUPPORT_WRAPPER_CALL * SoundCallbackLockedGetReferenceClockNowNanosecondsFunc)( void * inst, uint64_t * result ); void (OPENMPT_WINESUPPORT_WRAPPER_CALL * SoundCallbackLockedProcessPrepareFunc)( void * inst, const OpenMPT_SoundDevice_TimeInfo * timeInfo ); void (OPENMPT_WINESUPPORT_WRAPPER_CALL * SoundCallbackLockedProcessUint8Func)( void * inst, const OpenMPT_SoundDevice_BufferFormat * bufferFormat, uintptr_t numFrames, uint8_t * buffer, const uint8_t * inputBuffer ); void (OPENMPT_WINESUPPORT_WRAPPER_CALL * SoundCallbackLockedProcessInt8Func)( void * inst, const OpenMPT_SoundDevice_BufferFormat * bufferFormat, uintptr_t numFrames, int8_t * buffer, const int8_t * inputBuffer ); void (OPENMPT_WINESUPPORT_WRAPPER_CALL * SoundCallbackLockedProcessInt16Func)( void * inst, const OpenMPT_SoundDevice_BufferFormat * bufferFormat, uintptr_t numFrames, int16_t * buffer, const int16_t * inputBuffer ); void (OPENMPT_WINESUPPORT_WRAPPER_CALL * SoundCallbackLockedProcessInt24Func)( void * inst, const OpenMPT_SoundDevice_BufferFormat * bufferFormat, uintptr_t numFrames, OpenMPT_int24 * buffer, const OpenMPT_int24 * inputBuffer ); void (OPENMPT_WINESUPPORT_WRAPPER_CALL * SoundCallbackLockedProcessInt32Func)( void * inst, const OpenMPT_SoundDevice_BufferFormat * bufferFormat, uintptr_t numFrames, int32_t * buffer, const int32_t * inputBuffer ); void (OPENMPT_WINESUPPORT_WRAPPER_CALL * SoundCallbackLockedProcessFloatFunc)( void * inst, const OpenMPT_SoundDevice_BufferFormat * bufferFormat, uintptr_t numFrames, float * buffer, const float * inputBuffer ); void (OPENMPT_WINESUPPORT_WRAPPER_CALL * SoundCallbackLockedProcessDoubleFunc)( void * inst, const OpenMPT_SoundDevice_BufferFormat * bufferFormat, uintptr_t numFrames, double * buffer, const double * inputBuffer ); void (OPENMPT_WINESUPPORT_WRAPPER_CALL * SoundCallbackLockedProcessDoneFunc)( void * inst, const OpenMPT_SoundDevice_TimeInfo * timeInfo ); void (OPENMPT_WINESUPPORT_WRAPPER_CALL * SoundCallbackUnlockFunc)( void * inst ); } OpenMPT_Wine_Wrapper_SoundDevice_ICallback; #ifdef WINE_THREAD typedef enum OpenMPT_Wine_Wrapper_AudioThreadCommand { AudioThreadCommandInvalid = -1 , AudioThreadCommandExit = 0 , AudioThreadCommandLock = 1 , AudioThreadCommandClock = 2 , AudioThreadCommandReadPrepare = 3 , AudioThreadCommandReadUint8 = 4 , AudioThreadCommandReadInt8 = 5 , AudioThreadCommandReadInt16 = 6 , AudioThreadCommandReadInt24 = 7 , AudioThreadCommandReadInt32 = 8 , AudioThreadCommandReadFloat = 9 , AudioThreadCommandReadDouble = 10 , AudioThreadCommandReadDone = 11 , AudioThreadCommandUnlock = 12 } OpenMPT_Wine_Wrapper_AudioThreadCommand; #endif typedef struct OpenMPT_Wine_Wrapper_SoundDevice { OpenMPT_SoundDevice * impl; OpenMPT_SoundDevice_IMessageReceiver native_receiver; OpenMPT_SoundDevice_ICallback native_callback; OpenMPT_Wine_Wrapper_SoundDevice_IMessageReceiver wine_receiver; OpenMPT_Wine_Wrapper_SoundDevice_ICallback wine_callback; #ifdef WINE_THREAD HANDLE audiothread_startup_done; OpenMPT_Semaphore * audiothread_sem_request; OpenMPT_Semaphore * audiothread_sem_done; OpenMPT_Wine_Wrapper_AudioThreadCommand audiothread_command; const OpenMPT_SoundDevice_TimeInfo * audiothread_command_timeInfo; const OpenMPT_SoundDevice_BufferFormat * audiothread_command_bufferFormat; const OpenMPT_SoundDevice_BufferAttributes * audiothread_command_bufferAttributes; uintptr_t audiothread_command_numFrames; union { uint8_t * buf_uint8; int8_t * buf_int8; int16_t * buf_int16; OpenMPT_int24 * buf_int24; int32_t * buf_int32; float * buf_float; double * buf_double; } audiothread_command_buffer; union { const uint8_t * buf_uint8; const int8_t * buf_int8; const int16_t * buf_int16; const OpenMPT_int24 * buf_int24; const int32_t * buf_int32; const float * buf_float; const double * buf_double; } audiothread_command_inputBuffer; uint64_t * audiothread_command_result; HANDLE audiothread; OpenMPT_PriorityBooster * priority_booster; #endif } OpenMPT_Wine_Wrapper_SoundDevice; static void OPENMPT_WINESUPPORT_CALL SoundDeviceMessageFunc( void * inst, uintptr_t level, const char * message ) { OpenMPT_Wine_Wrapper_SoundDevice * sd = (OpenMPT_Wine_Wrapper_SoundDevice*)inst; if ( !sd ) { return; } return sd->wine_receiver.SoundDeviceMessageFunc( sd->wine_receiver.inst, level, message ); } static void OPENMPT_WINESUPPORT_CALL SoundCallbackGetReferenceClockNowNanosecondsFunc( void * inst, uint64_t * result ) { OpenMPT_Wine_Wrapper_SoundDevice * sd = (OpenMPT_Wine_Wrapper_SoundDevice*)inst; if ( !sd ) { return; } return sd->wine_callback.SoundCallbackGetReferenceClockNowNanosecondsFunc( sd->wine_callback.inst, result ); } static void OPENMPT_WINESUPPORT_CALL SoundCallbackPreStartFunc( void * inst ) { OpenMPT_Wine_Wrapper_SoundDevice * sd = (OpenMPT_Wine_Wrapper_SoundDevice*)inst; if ( !sd ) { return; } return sd->wine_callback.SoundCallbackPreStartFunc( sd->wine_callback.inst ); } static void OPENMPT_WINESUPPORT_CALL SoundCallbackPostStopFunc( void * inst ) { OpenMPT_Wine_Wrapper_SoundDevice * sd = (OpenMPT_Wine_Wrapper_SoundDevice*)inst; if ( !sd ) { return; } return sd->wine_callback.SoundCallbackPostStopFunc( sd->wine_callback.inst ); } static void OPENMPT_WINESUPPORT_CALL SoundCallbackIsLockedByCurrentThreadFunc( void * inst, uintptr_t * result ) { OpenMPT_Wine_Wrapper_SoundDevice * sd = (OpenMPT_Wine_Wrapper_SoundDevice*)inst; if ( !sd ) { return; } return sd->wine_callback.SoundCallbackIsLockedByCurrentThreadFunc( sd->wine_callback.inst, result ); } static void OPENMPT_WINESUPPORT_CALL SoundCallbackLockFunc( void * inst ) { OpenMPT_Wine_Wrapper_SoundDevice * sd = (OpenMPT_Wine_Wrapper_SoundDevice*)inst; if ( !sd ) { return; } #ifdef WINE_THREAD sd->audiothread_command = AudioThreadCommandLock; OpenMPT_Semaphore_Post( sd->audiothread_sem_request ); OpenMPT_Semaphore_Wait( sd->audiothread_sem_done ); #else return sd->wine_callback.SoundCallbackLockFunc( sd->wine_callback.inst ); #endif } static void OPENMPT_WINESUPPORT_CALL SoundCallbackLockedGetReferenceClockNowNanosecondsFunc( void * inst, uint64_t * result ) { OpenMPT_Wine_Wrapper_SoundDevice * sd = (OpenMPT_Wine_Wrapper_SoundDevice*)inst; if ( !sd ) { return; } #ifdef WINE_THREAD sd->audiothread_command = AudioThreadCommandClock; sd->audiothread_command_result = result; OpenMPT_Semaphore_Post( sd->audiothread_sem_request ); OpenMPT_Semaphore_Wait( sd->audiothread_sem_done ); #else return sd->wine_callback.SoundCallbackLockedGetReferenceClockNowNanosecondsFunc( sd->wine_callback.inst, result ); #endif } static void OPENMPT_WINESUPPORT_CALL SoundCallbackLockedProcessPrepareFunc( void * inst, const OpenMPT_SoundDevice_TimeInfo * timeInfo ) { OpenMPT_Wine_Wrapper_SoundDevice * sd = (OpenMPT_Wine_Wrapper_SoundDevice*)inst; if ( !sd ) { return; } #ifdef WINE_THREAD sd->audiothread_command = AudioThreadCommandReadPrepare; sd->audiothread_command_timeInfo = timeInfo; OpenMPT_Semaphore_Post( sd->audiothread_sem_request ); OpenMPT_Semaphore_Wait( sd->audiothread_sem_done ); #else return sd->wine_callback.SoundCallbackLockedProcessPrepareFunc( sd->wine_callback.inst, timeInfo ); #endif } static void OPENMPT_WINESUPPORT_CALL SoundCallbackLockedProcessUint8Func( void * inst, const OpenMPT_SoundDevice_BufferFormat * bufferFormat, uintptr_t numFrames, uint8_t * buffer, const uint8_t * inputBuffer ) { OpenMPT_Wine_Wrapper_SoundDevice * sd = (OpenMPT_Wine_Wrapper_SoundDevice*)inst; if ( !sd ) { return; } #ifdef WINE_THREAD sd->audiothread_command = AudioThreadCommandReadUint8; sd->audiothread_command_bufferFormat = bufferFormat; sd->audiothread_command_numFrames = numFrames; sd->audiothread_command_buffer.buf_uint8 = buffer; sd->audiothread_command_inputBuffer.buf_uint8 = inputBuffer; OpenMPT_Semaphore_Post( sd->audiothread_sem_request ); OpenMPT_Semaphore_Wait( sd->audiothread_sem_done ); #else return sd->wine_callback.SoundCallbackLockedProcessUint8Func( sd->wine_callback.inst, bufferFormat, bufferAttributes, numFrames, buffer, inputBuffer ); #endif } static void OPENMPT_WINESUPPORT_CALL SoundCallbackLockedProcessInt8Func( void * inst, const OpenMPT_SoundDevice_BufferFormat * bufferFormat, uintptr_t numFrames, int8_t * buffer, const int8_t * inputBuffer ) { OpenMPT_Wine_Wrapper_SoundDevice * sd = (OpenMPT_Wine_Wrapper_SoundDevice*)inst; if ( !sd ) { return; } #ifdef WINE_THREAD sd->audiothread_command = AudioThreadCommandReadInt8; sd->audiothread_command_bufferFormat = bufferFormat; sd->audiothread_command_numFrames = numFrames; sd->audiothread_command_buffer.buf_int8 = buffer; sd->audiothread_command_inputBuffer.buf_int8 = inputBuffer; OpenMPT_Semaphore_Post( sd->audiothread_sem_request ); OpenMPT_Semaphore_Wait( sd->audiothread_sem_done ); #else return sd->wine_callback.SoundCallbackLockedProcessInt8Func( sd->wine_callback.inst, bufferFormat, bufferAttributes, numFrames, buffer, inputBuffer ); #endif } static void OPENMPT_WINESUPPORT_CALL SoundCallbackLockedProcessInt16Func( void * inst, const OpenMPT_SoundDevice_BufferFormat * bufferFormat, uintptr_t numFrames, int16_t * buffer, const int16_t * inputBuffer ) { OpenMPT_Wine_Wrapper_SoundDevice * sd = (OpenMPT_Wine_Wrapper_SoundDevice*)inst; if ( !sd ) { return; } #ifdef WINE_THREAD sd->audiothread_command = AudioThreadCommandReadInt16; sd->audiothread_command_bufferFormat = bufferFormat; sd->audiothread_command_numFrames = numFrames; sd->audiothread_command_buffer.buf_int16 = buffer; sd->audiothread_command_inputBuffer.buf_int16 = inputBuffer; OpenMPT_Semaphore_Post( sd->audiothread_sem_request ); OpenMPT_Semaphore_Wait( sd->audiothread_sem_done ); #else return sd->wine_callback.SoundCallbackLockedProcessInt16Func( sd->wine_callback.inst, bufferFormat, bufferAttributes, numFrames, buffer, inputBuffer ); #endif } static void OPENMPT_WINESUPPORT_CALL SoundCallbackLockedProcessInt24Func( void * inst, const OpenMPT_SoundDevice_BufferFormat * bufferFormat, uintptr_t numFrames, OpenMPT_int24 * buffer, const OpenMPT_int24 * inputBuffer ) { OpenMPT_Wine_Wrapper_SoundDevice * sd = (OpenMPT_Wine_Wrapper_SoundDevice*)inst; if ( !sd ) { return; } #ifdef WINE_THREAD sd->audiothread_command = AudioThreadCommandReadInt24; sd->audiothread_command_bufferFormat = bufferFormat; sd->audiothread_command_numFrames = numFrames; sd->audiothread_command_buffer.buf_int24 = buffer; sd->audiothread_command_inputBuffer.buf_int24 = inputBuffer; OpenMPT_Semaphore_Post( sd->audiothread_sem_request ); OpenMPT_Semaphore_Wait( sd->audiothread_sem_done ); #else return sd->wine_callback.SoundCallbackLockedProcessInt24Func( sd->wine_callback.inst, bufferFormat, bufferAttributes, numFrames, buffer, inputBuffer ); #endif } static void OPENMPT_WINESUPPORT_CALL SoundCallbackLockedProcessInt32Func( void * inst, const OpenMPT_SoundDevice_BufferFormat * bufferFormat, uintptr_t numFrames, int32_t * buffer, const int32_t * inputBuffer ) { OpenMPT_Wine_Wrapper_SoundDevice * sd = (OpenMPT_Wine_Wrapper_SoundDevice*)inst; if ( !sd ) { return; } #ifdef WINE_THREAD sd->audiothread_command = AudioThreadCommandReadInt32; sd->audiothread_command_bufferFormat = bufferFormat; sd->audiothread_command_numFrames = numFrames; sd->audiothread_command_buffer.buf_int32 = buffer; sd->audiothread_command_inputBuffer.buf_int32 = inputBuffer; OpenMPT_Semaphore_Post( sd->audiothread_sem_request ); OpenMPT_Semaphore_Wait( sd->audiothread_sem_done ); #else return sd->wine_callback.SoundCallbackLockedProcessInt32Func( sd->wine_callback.inst, bufferFormat, bufferAttributes, numFrames, buffer, inputBuffer ); #endif } static void OPENMPT_WINESUPPORT_CALL SoundCallbackLockedProcessFloatFunc( void * inst, const OpenMPT_SoundDevice_BufferFormat * bufferFormat, uintptr_t numFrames, float * buffer, const float * inputBuffer ) { OpenMPT_Wine_Wrapper_SoundDevice * sd = (OpenMPT_Wine_Wrapper_SoundDevice*)inst; if ( !sd ) { return; } #ifdef WINE_THREAD sd->audiothread_command = AudioThreadCommandReadFloat; sd->audiothread_command_bufferFormat = bufferFormat; sd->audiothread_command_numFrames = numFrames; sd->audiothread_command_buffer.buf_float = buffer; sd->audiothread_command_inputBuffer.buf_float = inputBuffer; OpenMPT_Semaphore_Post( sd->audiothread_sem_request ); OpenMPT_Semaphore_Wait( sd->audiothread_sem_done ); #else return sd->wine_callback.SoundCallbackLockedProcessFloatFunc( sd->wine_callback.inst, bufferFormat, bufferAttributes, numFrames, buffer, inputBuffer ); #endif } static void OPENMPT_WINESUPPORT_CALL SoundCallbackLockedProcessDoubleFunc( void * inst, const OpenMPT_SoundDevice_BufferFormat * bufferFormat, uintptr_t numFrames, double * buffer, const double * inputBuffer ) { OpenMPT_Wine_Wrapper_SoundDevice * sd = (OpenMPT_Wine_Wrapper_SoundDevice*)inst; if ( !sd ) { return; } #ifdef WINE_THREAD sd->audiothread_command = AudioThreadCommandReadDouble; sd->audiothread_command_bufferFormat = bufferFormat; sd->audiothread_command_numFrames = numFrames; sd->audiothread_command_buffer.buf_double = buffer; sd->audiothread_command_inputBuffer.buf_double = inputBuffer; OpenMPT_Semaphore_Post( sd->audiothread_sem_request ); OpenMPT_Semaphore_Wait( sd->audiothread_sem_done ); #else return sd->wine_callback.SoundCallbackLockedProcessDoubleFunc( sd->wine_callback.inst, bufferFormat, bufferAttributes, numFrames, buffer, inputBuffer ); #endif } static void OPENMPT_WINESUPPORT_CALL SoundCallbackLockedProcessDoneFunc( void * inst, const OpenMPT_SoundDevice_TimeInfo * timeInfo ) { OpenMPT_Wine_Wrapper_SoundDevice * sd = (OpenMPT_Wine_Wrapper_SoundDevice*)inst; if ( !sd ) { return; } #ifdef WINE_THREAD sd->audiothread_command = AudioThreadCommandReadDone; sd->audiothread_command_timeInfo = timeInfo; OpenMPT_Semaphore_Post( sd->audiothread_sem_request ); OpenMPT_Semaphore_Wait( sd->audiothread_sem_done ); #else return sd->wine_callback.SoundCallbackLockedProcessDoneFunc( sd->wine_callback.inst, timeInfo ); #endif } static void OPENMPT_WINESUPPORT_CALL SoundCallbackUnlockFunc( void * inst ) { OpenMPT_Wine_Wrapper_SoundDevice * sd = (OpenMPT_Wine_Wrapper_SoundDevice*)inst; if ( !sd ) { return; } #ifdef WINE_THREAD sd->audiothread_command = AudioThreadCommandUnlock; OpenMPT_Semaphore_Post( sd->audiothread_sem_request ); OpenMPT_Semaphore_Wait( sd->audiothread_sem_done ); #else return sd->wine_callback.SoundCallbackUnlockFunc( sd->wine_callback.inst ); #endif } #ifdef WINE_THREAD static DWORD WINAPI AudioThread( LPVOID userdata ) { OpenMPT_Wine_Wrapper_SoundDevice * sd = (OpenMPT_Wine_Wrapper_SoundDevice*)userdata; sd->priority_booster = OpenMPT_PriorityBooster_Construct_From_SoundDevice( sd->impl ); SetEvent( sd->audiothread_startup_done ); { int exit = 0; while(!exit) { OpenMPT_Semaphore_Wait( sd->audiothread_sem_request ); switch ( sd->audiothread_command ) { case AudioThreadCommandExit: exit = 1; break; case AudioThreadCommandLock: if(sd->wine_callback.SoundCallbackLockFunc) sd->wine_callback.SoundCallbackLockFunc( sd->wine_callback.inst ); break; case AudioThreadCommandClock: if(sd->wine_callback.SoundCallbackLockedGetReferenceClockNowNanosecondsFunc) sd->wine_callback.SoundCallbackLockedGetReferenceClockNowNanosecondsFunc( sd->wine_callback.inst, sd->audiothread_command_result ); break; case AudioThreadCommandReadPrepare: if(sd->wine_callback.SoundCallbackLockedProcessPrepareFunc) sd->wine_callback.SoundCallbackLockedProcessPrepareFunc ( sd->wine_callback.inst , sd->audiothread_command_timeInfo ); break; case AudioThreadCommandReadUint8: if(sd->wine_callback.SoundCallbackLockedProcessUint8Func) sd->wine_callback.SoundCallbackLockedProcessUint8Func ( sd->wine_callback.inst , sd->audiothread_command_bufferFormat , sd->audiothread_command_numFrames , sd->audiothread_command_buffer.buf_uint8 , sd->audiothread_command_inputBuffer.buf_uint8 ); break; case AudioThreadCommandReadInt8: if(sd->wine_callback.SoundCallbackLockedProcessInt8Func) sd->wine_callback.SoundCallbackLockedProcessInt8Func ( sd->wine_callback.inst , sd->audiothread_command_bufferFormat , sd->audiothread_command_numFrames , sd->audiothread_command_buffer.buf_int8 , sd->audiothread_command_inputBuffer.buf_int8 ); break; case AudioThreadCommandReadInt16: if(sd->wine_callback.SoundCallbackLockedProcessInt16Func) sd->wine_callback.SoundCallbackLockedProcessInt16Func ( sd->wine_callback.inst , sd->audiothread_command_bufferFormat , sd->audiothread_command_numFrames , sd->audiothread_command_buffer.buf_int16 , sd->audiothread_command_inputBuffer.buf_int16 ); break; case AudioThreadCommandReadInt24: if(sd->wine_callback.SoundCallbackLockedProcessInt24Func) sd->wine_callback.SoundCallbackLockedProcessInt24Func ( sd->wine_callback.inst , sd->audiothread_command_bufferFormat , sd->audiothread_command_numFrames , sd->audiothread_command_buffer.buf_int24 , sd->audiothread_command_inputBuffer.buf_int24 ); break; case AudioThreadCommandReadInt32: if(sd->wine_callback.SoundCallbackLockedProcessInt32Func) sd->wine_callback.SoundCallbackLockedProcessInt32Func ( sd->wine_callback.inst , sd->audiothread_command_bufferFormat , sd->audiothread_command_numFrames , sd->audiothread_command_buffer.buf_int32 , sd->audiothread_command_inputBuffer.buf_int32 ); break; case AudioThreadCommandReadFloat: if(sd->wine_callback.SoundCallbackLockedProcessFloatFunc) sd->wine_callback.SoundCallbackLockedProcessFloatFunc ( sd->wine_callback.inst , sd->audiothread_command_bufferFormat , sd->audiothread_command_numFrames , sd->audiothread_command_buffer.buf_float , sd->audiothread_command_inputBuffer.buf_float ); break; case AudioThreadCommandReadDouble: if(sd->wine_callback.SoundCallbackLockedProcessDoubleFunc) sd->wine_callback.SoundCallbackLockedProcessDoubleFunc ( sd->wine_callback.inst , sd->audiothread_command_bufferFormat , sd->audiothread_command_numFrames , sd->audiothread_command_buffer.buf_double , sd->audiothread_command_inputBuffer.buf_double ); break; case AudioThreadCommandReadDone: if(sd->wine_callback.SoundCallbackLockedProcessDoneFunc) sd->wine_callback.SoundCallbackLockedProcessDoneFunc ( sd->wine_callback.inst , sd->audiothread_command_timeInfo ); break; case AudioThreadCommandUnlock: if(sd->wine_callback.SoundCallbackUnlockFunc) sd->wine_callback.SoundCallbackUnlockFunc( sd->wine_callback.inst ); break; default: break; } OpenMPT_Semaphore_Post( sd->audiothread_sem_done ); } } OpenMPT_PriorityBooster_Destruct(sd->priority_booster); sd->priority_booster = NULL; return 0; } #endif OPENMPT_WINESUPPORT_WRAPPER_API OpenMPT_Wine_Wrapper_SoundDevice * OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_Construct( const char * info ) { OpenMPT_Wine_Wrapper_SoundDevice * sd = (OpenMPT_Wine_Wrapper_SoundDevice*)OpenMPT_Wine_Wrapper_Alloc( sizeof( OpenMPT_Wine_Wrapper_SoundDevice ) ); sd->impl = OpenMPT_SoundDevice_Construct( info ); return sd; } OPENMPT_WINESUPPORT_WRAPPER_API void OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_Destruct( OpenMPT_Wine_Wrapper_SoundDevice * sd ) { OpenMPT_SoundDevice_Destruct( sd->impl ); sd->impl = NULL; OpenMPT_Wine_Wrapper_Free( sd ); } OPENMPT_WINESUPPORT_WRAPPER_API void OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_SetMessageReceiver( OpenMPT_Wine_Wrapper_SoundDevice * sd, const OpenMPT_Wine_Wrapper_SoundDevice_IMessageReceiver * receiver ) { OpenMPT_SoundDevice_SetMessageReceiver( sd->impl, NULL ); ZeroMemory( &( sd->wine_receiver ), sizeof( sd->wine_receiver ) ); if(receiver) { sd->wine_receiver = *receiver; } sd->native_receiver.inst = sd; sd->native_receiver.SoundDeviceMessageFunc = &SoundDeviceMessageFunc; OpenMPT_SoundDevice_SetMessageReceiver( sd->impl, &sd->native_receiver ); } OPENMPT_WINESUPPORT_WRAPPER_API void OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_SetCallback( OpenMPT_Wine_Wrapper_SoundDevice * sd, const OpenMPT_Wine_Wrapper_SoundDevice_ICallback * callback ) { OpenMPT_SoundDevice_SetCallback( sd->impl, NULL ); ZeroMemory( &( sd->wine_callback ), sizeof( sd->wine_callback) ); if(callback) { sd->wine_callback = *callback; } sd->native_callback.inst = sd; sd->native_callback.SoundCallbackGetReferenceClockNowNanosecondsFunc = &SoundCallbackGetReferenceClockNowNanosecondsFunc; sd->native_callback.SoundCallbackPreStartFunc = &SoundCallbackPreStartFunc; sd->native_callback.SoundCallbackPostStopFunc = &SoundCallbackPostStopFunc; sd->native_callback.SoundCallbackIsLockedByCurrentThreadFunc = &SoundCallbackIsLockedByCurrentThreadFunc; sd->native_callback.SoundCallbackLockFunc = &SoundCallbackLockFunc; sd->native_callback.SoundCallbackLockedGetReferenceClockNowNanosecondsFunc = &SoundCallbackLockedGetReferenceClockNowNanosecondsFunc; sd->native_callback.SoundCallbackLockedProcessPrepareFunc = &SoundCallbackLockedProcessPrepareFunc; sd->native_callback.SoundCallbackLockedProcessUint8Func = &SoundCallbackLockedProcessUint8Func; sd->native_callback.SoundCallbackLockedProcessInt8Func = &SoundCallbackLockedProcessInt8Func; sd->native_callback.SoundCallbackLockedProcessInt16Func = &SoundCallbackLockedProcessInt16Func; sd->native_callback.SoundCallbackLockedProcessInt24Func = &SoundCallbackLockedProcessInt24Func; sd->native_callback.SoundCallbackLockedProcessInt32Func = &SoundCallbackLockedProcessInt32Func; sd->native_callback.SoundCallbackLockedProcessFloatFunc = &SoundCallbackLockedProcessFloatFunc; sd->native_callback.SoundCallbackLockedProcessDoubleFunc = &SoundCallbackLockedProcessDoubleFunc; sd->native_callback.SoundCallbackLockedProcessDoneFunc = &SoundCallbackLockedProcessDoneFunc; sd->native_callback.SoundCallbackUnlockFunc = &SoundCallbackUnlockFunc; OpenMPT_SoundDevice_SetCallback( sd->impl, &sd->native_callback ); } OPENMPT_WINESUPPORT_WRAPPER_API char * OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_GetDeviceInfo( const OpenMPT_Wine_Wrapper_SoundDevice * sd ) { return OpenMPT_SoundDevice_GetDeviceInfo( sd->impl ); } OPENMPT_WINESUPPORT_WRAPPER_API char * OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_GetDeviceCaps( const OpenMPT_Wine_Wrapper_SoundDevice * sd ) { return OpenMPT_SoundDevice_GetDeviceCaps( sd->impl ); } OPENMPT_WINESUPPORT_WRAPPER_API char * OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_GetDeviceDynamicCaps( OpenMPT_Wine_Wrapper_SoundDevice * sd, const char * baseSampleRates ) { return OpenMPT_SoundDevice_GetDeviceDynamicCaps( sd->impl, baseSampleRates ); } OPENMPT_WINESUPPORT_WRAPPER_API uintptr_t OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_Init( OpenMPT_Wine_Wrapper_SoundDevice * sd, const char * appInfo ) { return OpenMPT_SoundDevice_Init( sd->impl, appInfo ); } OPENMPT_WINESUPPORT_WRAPPER_API uintptr_t OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_Open( OpenMPT_Wine_Wrapper_SoundDevice * sd, const char * settings ) { uintptr_t result = 0; result = OpenMPT_SoundDevice_Open( sd->impl, settings ); #ifdef WINE_THREAD if ( result ) { DWORD threadId = 0; sd->audiothread_startup_done = CreateEvent( NULL, FALSE, FALSE, NULL ); sd->audiothread_sem_request = OpenMPT_Semaphore_Construct(); sd->audiothread_sem_done = OpenMPT_Semaphore_Construct(); sd->audiothread_command = AudioThreadCommandInvalid; sd->audiothread = CreateThread( NULL, 0, &AudioThread, sd, 0, &threadId ); WaitForSingleObject( sd->audiothread_startup_done, INFINITE ); } #endif return result; } OPENMPT_WINESUPPORT_WRAPPER_API uintptr_t OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_Close( OpenMPT_Wine_Wrapper_SoundDevice * sd ) { uintptr_t result = 0; #ifdef WINE_THREAD if ( OpenMPT_SoundDevice_IsOpen( sd->impl ) ) { sd->audiothread_command = AudioThreadCommandExit; OpenMPT_Semaphore_Post( sd->audiothread_sem_request ); OpenMPT_Semaphore_Wait( sd->audiothread_sem_done ); sd->audiothread_command = AudioThreadCommandInvalid; WaitForSingleObject( sd->audiothread, INFINITE ); CloseHandle( sd->audiothread ); sd->audiothread = NULL; OpenMPT_Semaphore_Destruct( sd->audiothread_sem_done ); sd->audiothread_sem_done = NULL; OpenMPT_Semaphore_Destruct( sd->audiothread_sem_request ); sd->audiothread_sem_request = NULL; CloseHandle( sd->audiothread_startup_done ); sd->audiothread_startup_done = NULL; } #endif result = OpenMPT_SoundDevice_Close( sd->impl ); return result; } OPENMPT_WINESUPPORT_WRAPPER_API uintptr_t OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_Start( OpenMPT_Wine_Wrapper_SoundDevice * sd ) { return OpenMPT_SoundDevice_Start( sd->impl ); } OPENMPT_WINESUPPORT_WRAPPER_API void OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_Stop( OpenMPT_Wine_Wrapper_SoundDevice * sd ) { return OpenMPT_SoundDevice_Stop( sd->impl ); } OPENMPT_WINESUPPORT_WRAPPER_API void OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_GetRequestFlags( const OpenMPT_Wine_Wrapper_SoundDevice * sd, uint32_t * result) { return OpenMPT_SoundDevice_GetRequestFlags( sd->impl, result ); } OPENMPT_WINESUPPORT_WRAPPER_API uintptr_t OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_IsInited( const OpenMPT_Wine_Wrapper_SoundDevice * sd ) { return OpenMPT_SoundDevice_IsInited( sd->impl ); } OPENMPT_WINESUPPORT_WRAPPER_API uintptr_t OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_IsOpen( const OpenMPT_Wine_Wrapper_SoundDevice * sd ) { return OpenMPT_SoundDevice_IsOpen( sd->impl ); } OPENMPT_WINESUPPORT_WRAPPER_API uintptr_t OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_IsAvailable( const OpenMPT_Wine_Wrapper_SoundDevice * sd ) { return OpenMPT_SoundDevice_IsAvailable( sd->impl ); } OPENMPT_WINESUPPORT_WRAPPER_API uintptr_t OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_IsPlaying( const OpenMPT_Wine_Wrapper_SoundDevice * sd ) { return OpenMPT_SoundDevice_IsPlaying( sd->impl ); } OPENMPT_WINESUPPORT_WRAPPER_API uintptr_t OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_IsPlayingSilence( const OpenMPT_Wine_Wrapper_SoundDevice * sd ) { return OpenMPT_SoundDevice_IsPlayingSilence( sd->impl ); } OPENMPT_WINESUPPORT_WRAPPER_API void OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_StopAndAvoidPlayingSilence( OpenMPT_Wine_Wrapper_SoundDevice * sd ) { return OpenMPT_SoundDevice_StopAndAvoidPlayingSilence( sd->impl ); } OPENMPT_WINESUPPORT_WRAPPER_API void OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_EndPlayingSilence( OpenMPT_Wine_Wrapper_SoundDevice * sd ) { return OpenMPT_SoundDevice_EndPlayingSilence( sd->impl ); } OPENMPT_WINESUPPORT_WRAPPER_API uintptr_t OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_OnIdle( OpenMPT_Wine_Wrapper_SoundDevice * sd ) { return OpenMPT_SoundDevice_OnIdle( sd->impl ); } OPENMPT_WINESUPPORT_WRAPPER_API char * OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_GetSettings( const OpenMPT_Wine_Wrapper_SoundDevice * sd ) { return OpenMPT_SoundDevice_GetSettings( sd->impl ); } OPENMPT_WINESUPPORT_WRAPPER_API void OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_GetActualSampleFormat( const OpenMPT_Wine_Wrapper_SoundDevice * sd, int32_t * result ) { return OpenMPT_SoundDevice_GetActualSampleFormat( sd->impl, result ); } OPENMPT_WINESUPPORT_WRAPPER_API void OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_GetEffectiveBufferAttributes( const OpenMPT_Wine_Wrapper_SoundDevice * sd, OpenMPT_SoundDevice_BufferAttributes * result ) { return OpenMPT_SoundDevice_GetEffectiveBufferAttributes( sd->impl, result ); } OPENMPT_WINESUPPORT_WRAPPER_API void OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_GetTimeInfo( const OpenMPT_Wine_Wrapper_SoundDevice * sd, OpenMPT_SoundDevice_TimeInfo * result ) { return OpenMPT_SoundDevice_GetTimeInfo( sd->impl, result ); } OPENMPT_WINESUPPORT_WRAPPER_API void OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_GetStreamPosition( const OpenMPT_Wine_Wrapper_SoundDevice * sd, OpenMPT_SoundDevice_StreamPosition * result ) { return OpenMPT_SoundDevice_GetStreamPosition( sd->impl, result ); } OPENMPT_WINESUPPORT_WRAPPER_API uintptr_t OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_DebugIsFragileDevice( const OpenMPT_Wine_Wrapper_SoundDevice * sd ) { return OpenMPT_SoundDevice_DebugIsFragileDevice( sd->impl ); } OPENMPT_WINESUPPORT_WRAPPER_API uintptr_t OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_DebugInRealtimeCallback( const OpenMPT_Wine_Wrapper_SoundDevice * sd ) { return OpenMPT_SoundDevice_DebugInRealtimeCallback( sd->impl ); } OPENMPT_WINESUPPORT_WRAPPER_API char * OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_GetStatistics( const OpenMPT_Wine_Wrapper_SoundDevice * sd ) { return OpenMPT_SoundDevice_GetStatistics( sd->impl ); } OPENMPT_WINESUPPORT_WRAPPER_API uintptr_t OPENMPT_WINESUPPORT_WRAPPER_CALL OpenMPT_Wine_Wrapper_SoundDevice_OpenDriverSettings( OpenMPT_Wine_Wrapper_SoundDevice * sd ) { return OpenMPT_SoundDevice_OpenDriverSettings( sd->impl ); } #ifdef __cplusplus } // extern "C" #endif #endif // MPT_BUILD_WINESUPPORT_WRAPPER