Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
738669a7
Commit
738669a7
authored
Jan 12, 2002
by
Eric Pouech
Committed by
Alexandre Julliard
Jan 12, 2002
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixed the wodReset implementation, internal messages priority, full
duplex code, wait algorithm for feeding the OSS buffer.
parent
d0f260eb
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
93 additions
and
58 deletions
+93
-58
audio.c
dlls/winmm/wineoss/audio.c
+93
-58
No files found.
dlls/winmm/wineoss/audio.c
View file @
738669a7
...
...
@@ -9,7 +9,7 @@
/*
* FIXME:
* pause in waveOut does not work correctly in loop mode
* experimental full duple
s
mode
* experimental full duple
x
mode
* only one sound card is currently supported
*/
...
...
@@ -42,8 +42,6 @@ DEFAULT_DEBUG_CHANNEL(wave);
/* Allow 1% deviation for sample rates (some ES137x cards) */
#define NEAR_MATCH(rate1,rate2) (((100*((int)(rate1)-(int)(rate2)))/(rate1))==0)
#define REFILL_BUFFER_WHEN 3/4
/* fill the buffer when it's 3/4 empty */
#ifdef HAVE_OSS
#define SOUND_DEV "/dev/dsp"
...
...
@@ -92,6 +90,7 @@ typedef struct {
* this ring will be used by the input (resp output) record (resp playback) routine
*/
typedef
struct
{
/* FIXME: this could be made a dynamically growing array (if needed) */
#define OSS_RING_BUFFER_SIZE 30
OSS_MSG
messages
[
OSS_RING_BUFFER_SIZE
];
int
msg_tosave
;
...
...
@@ -111,9 +110,6 @@ typedef struct {
/* OSS information */
DWORD
dwFragmentSize
;
/* size of OSS buffer fragment */
DWORD
dwBufferSize
;
/* size of whole OSS buffer in bytes */
WORD
uWaitForFragments
;
/* The number of OSS buffer fragments we would like to be free
* before trying to write to the DSP
*/
LPWAVEHDR
lpQueuePtr
;
/* start of queued WAVEHDRs (waiting to be notified) */
LPWAVEHDR
lpPlayPtr
;
/* start of not yet fully played buffers */
DWORD
dwPartialOffset
;
/* Offset of not yet written bytes in lpPlayPtr */
...
...
@@ -166,8 +162,8 @@ static const char *wodPlayerCmdString[] = {
"WINE_WM_RESETTING"
,
"WINE_WM_HEADER"
,
"WINE_WM_UPDATE"
,
"WINE_WM_CLOSING"
,
"WINE_WM_BREAKLOOP"
,
"WINE_WM_CLOSING"
,
};
/*======================================================================*
...
...
@@ -178,8 +174,9 @@ static const char *wodPlayerCmdString[] = {
static
unsigned
OSS_OpenCount
/* = 0 */
;
/* number of times fd has been opened */
static
unsigned
OSS_OpenAccess
/* = 0 */
;
/* access used for opening... used to handle compat */
static
int
OSS_OpenFD
;
static
BOOL
OSS_FullDuplex
;
/* set to non-zero if the device supports full duplex */
static
DWORD
OSS_OwnerThreadID
/* = 0 */
;
#endif
static
BOOL
OSS_FullDuplex
;
/* set to non-zero if the device supports full duplex */
/******************************************************************
* OSS_OpenDevice
...
...
@@ -191,6 +188,7 @@ static BOOL OSS_FullDuplex; /* set to non-zero if the device suppo
static
int
OSS_OpenDevice
(
unsigned
req_access
)
{
#ifdef USE_FULLDUPLEX
/* FIXME: race */
if
(
OSS_OpenCount
==
0
)
{
if
(
access
(
SOUND_DEV
,
0
)
!=
0
||
...
...
@@ -203,12 +201,22 @@ static int OSS_OpenDevice(unsigned req_access)
if
(
req_access
==
O_RDWR
&&
OSS_FullDuplex
)
ioctl
(
OSS_OpenFD
,
SNDCTL_DSP_SETDUPLEX
,
0
);
OSS_OpenAccess
=
req_access
;
OSS_OwnerThreadID
=
GetCurrentThreadId
();
}
else
if
(
OSS_OpenAccess
!=
req_access
)
else
{
WARN
(
"Mismatch in access...
\n
"
);
return
-
1
;
if
(
OSS_OpenAccess
!=
req_access
)
{
WARN
(
"Mismatch in access...
\n
"
);
return
-
1
;
}
if
(
GetCurrentThreadId
()
==
OSS_OwnerThreadID
)
{
WARN
(
"Another thread is trying to access audio...
\n
"
);
return
-
1
;
}
}
OSS_OpenCount
++
;
return
OSS_OpenFD
;
#else
...
...
@@ -477,31 +485,47 @@ static int OSS_DestroyRingMessage(OSS_MSG_RING* omr)
*/
static
int
OSS_AddRingMessage
(
OSS_MSG_RING
*
omr
,
enum
win_wm_message
msg
,
DWORD
param
,
BOOL
wait
)
{
HANDLE
hEvent
;
HANDLE
hEvent
=
INVALID_HANDLE_VALUE
;
EnterCriticalSection
(
&
omr
->
msg_crst
);
if
((
omr
->
msg_tosave
==
omr
->
msg_toget
)
/* buffer overflow ? */
&&
(
omr
->
messages
[
omr
->
msg_toget
].
msg
))
if
((
omr
->
msg_toget
==
((
omr
->
msg_tosave
+
1
)
%
OSS_RING_BUFFER_SIZE
)))
/* buffer overflow ? */
{
ERR
(
"buffer overflow !?
\n
"
);
LeaveCriticalSection
(
&
omr
->
msg_crst
);
return
0
;
}
if
(
wait
)
{
hEvent
=
CreateEventA
(
NULL
,
FALSE
,
FALSE
,
NULL
);
if
(
hEvent
==
INVALID_HANDLE_VALUE
)
{
ERR
(
"can't create event !?
\n
"
);
LeaveCriticalSection
(
&
omr
->
msg_crst
);
return
0
;
}
if
(
omr
->
msg_toget
!=
omr
->
msg_tosave
&&
omr
->
messages
[
omr
->
msg_toget
].
msg
!=
WINE_WM_HEADER
)
FIXME
(
"two fast messages in the queue!!!!
\n
"
);
hEvent
=
wait
?
CreateEventA
(
NULL
,
FALSE
,
FALSE
,
NULL
)
:
INVALID_HANDLE_VALUE
;
omr
->
messages
[
omr
->
msg_tosave
].
msg
=
msg
;
omr
->
messages
[
omr
->
msg_tosave
].
param
=
param
;
omr
->
messages
[
omr
->
msg_tosave
].
hEvent
=
hEvent
;
/* fast messages have to be added at the start of the queue */
omr
->
msg_toget
=
(
omr
->
msg_toget
+
OSS_RING_BUFFER_SIZE
-
1
)
%
OSS_RING_BUFFER_SIZE
;
omr
->
msg_tosave
++
;
if
(
omr
->
msg_tosave
>
OSS_RING_BUFFER_SIZE
-
1
)
omr
->
msg_tosave
=
0
;
omr
->
messages
[
omr
->
msg_toget
].
msg
=
msg
;
omr
->
messages
[
omr
->
msg_toget
].
param
=
param
;
omr
->
messages
[
omr
->
msg_toget
].
hEvent
=
hEvent
;
}
else
{
omr
->
messages
[
omr
->
msg_tosave
].
msg
=
msg
;
omr
->
messages
[
omr
->
msg_tosave
].
param
=
param
;
omr
->
messages
[
omr
->
msg_tosave
].
hEvent
=
INVALID_HANDLE_VALUE
;
omr
->
msg_tosave
=
(
omr
->
msg_tosave
+
1
)
%
OSS_RING_BUFFER_SIZE
;
}
LeaveCriticalSection
(
&
omr
->
msg_crst
);
/* signal a new message */
SetEvent
(
omr
->
msg_event
);
if
(
wait
)
{
/* wait for playback/record thread to have processed the message */
WaitForSingleObject
(
hEvent
,
INFINITE
);
CloseHandle
(
hEvent
);
}
...
...
@@ -528,9 +552,7 @@ static int OSS_RetrieveRingMessage(OSS_MSG_RING* omr,
omr
->
messages
[
omr
->
msg_toget
].
msg
=
0
;
*
param
=
omr
->
messages
[
omr
->
msg_toget
].
param
;
*
hEvent
=
omr
->
messages
[
omr
->
msg_toget
].
hEvent
;
omr
->
msg_toget
++
;
if
(
omr
->
msg_toget
>
OSS_RING_BUFFER_SIZE
-
1
)
omr
->
msg_toget
=
0
;
omr
->
msg_toget
=
(
omr
->
msg_toget
+
1
)
%
OSS_RING_BUFFER_SIZE
;
LeaveCriticalSection
(
&
omr
->
msg_crst
);
return
1
;
}
...
...
@@ -646,17 +668,13 @@ static LPWAVEHDR wodPlayer_PlayPtrNext(WINE_WAVEOUT* wwo)
/**************************************************************************
* wodPlayer_DSPWait [internal]
* Returns the number of milliseconds to wait for the DSP buffer to clear.
* This is based on the number of fragments we want to be clear before
* writing and the number of free fragments we already have.
* Returns the number of milliseconds to wait for the DSP buffer to write
* one fragment.
*/
static
DWORD
wodPlayer_DSPWait
(
const
WINE_WAVEOUT
*
wwo
,
DWORD
availInQ
)
static
DWORD
wodPlayer_DSPWait
(
const
WINE_WAVEOUT
*
wwo
)
{
DWORD
uFreeFragments
=
availInQ
/
wwo
->
dwFragmentSize
;
return
(
uFreeFragments
>=
wwo
->
uWaitForFragments
)
?
1
:
(
wwo
->
dwFragmentSize
*
1000
/
wwo
->
format
.
wf
.
nAvgBytesPerSec
)
*
(
wwo
->
uWaitForFragments
-
uFreeFragments
);
/* time for one fragment to be played */
return
wwo
->
dwFragmentSize
*
1000
/
wwo
->
format
.
wf
.
nAvgBytesPerSec
;
}
/**************************************************************************
...
...
@@ -754,7 +772,6 @@ static DWORD wodPlayer_NotifyCompletions(WINE_WAVEOUT* wwo, BOOL force)
static
void
wodPlayer_Reset
(
WINE_WAVEOUT
*
wwo
,
BOOL
reset
)
{
wodUpdatePlayedTotal
(
wwo
,
NULL
);
/* updates current notify list */
wodPlayer_NotifyCompletions
(
wwo
,
FALSE
);
...
...
@@ -767,7 +784,11 @@ static void wodPlayer_Reset(WINE_WAVEOUT* wwo, BOOL reset)
}
if
(
reset
)
{
/* empty notify list */
enum
win_wm_message
msg
;
DWORD
param
;
HANDLE
ev
;
/* remove any buffer */
wodPlayer_NotifyCompletions
(
wwo
,
TRUE
);
wwo
->
lpPlayPtr
=
wwo
->
lpQueuePtr
=
wwo
->
lpLoopPtr
=
NULL
;
...
...
@@ -775,6 +796,25 @@ static void wodPlayer_Reset(WINE_WAVEOUT* wwo, BOOL reset)
wwo
->
dwPlayedTotal
=
wwo
->
dwWrittenTotal
=
0
;
/* Clear partial wavehdr */
wwo
->
dwPartialOffset
=
0
;
/* remove any existing message in the ring */
EnterCriticalSection
(
&
wwo
->
msgRing
.
msg_crst
);
/* return all pending headers in queue */
while
(
OSS_RetrieveRingMessage
(
&
wwo
->
msgRing
,
&
msg
,
&
param
,
&
ev
))
{
if
(
msg
!=
WINE_WM_HEADER
)
{
FIXME
(
"shouldn't have headers left
\n
"
);
SetEvent
(
ev
);
continue
;
}
((
LPWAVEHDR
)
param
)
->
dwFlags
&=
~
WHDR_INQUEUE
;
((
LPWAVEHDR
)
param
)
->
dwFlags
|=
WHDR_DONE
;
wodNotifyClient
(
wwo
,
WOM_DONE
,
param
,
0
);
}
ResetEvent
(
wwo
->
msgRing
.
msg_event
);
LeaveCriticalSection
(
&
wwo
->
msgRing
.
msg_crst
);
}
else
{
if
(
wwo
->
lpLoopPtr
)
{
/* complicated case, not handled yet (could imply modifying the loop counter */
...
...
@@ -890,21 +930,23 @@ static DWORD wodPlayer_FeedDSP(WINE_WAVEOUT* wwo)
}
/* no more room... no need to try to feed */
if
(
dspspace
.
fragments
==
0
)
return
wodPlayer_DSPWait
(
wwo
,
0
);
/* Feed from partial wavehdr */
if
(
wwo
->
lpPlayPtr
&&
wwo
->
dwPartialOffset
!=
0
)
{
wodPlayer_WriteMaxFrags
(
wwo
,
&
availInQ
);
}
if
(
dspspace
.
fragments
!=
0
)
{
/* Feed from partial wavehdr */
if
(
wwo
->
lpPlayPtr
&&
wwo
->
dwPartialOffset
!=
0
)
{
wodPlayer_WriteMaxFrags
(
wwo
,
&
availInQ
);
}
/* Feed wavehdrs until we run out of wavehdrs or DSP space */
if
(
wwo
->
dwPartialOffset
==
0
)
while
(
wwo
->
lpPlayPtr
&&
availInQ
>
0
)
{
/* note the value that dwPlayedTotal will return when this wave finishes playing */
wwo
->
lpPlayPtr
->
reserved
=
wwo
->
dwWrittenTotal
+
wwo
->
lpPlayPtr
->
dwBufferLength
;
wodPlayer_WriteMaxFrags
(
wwo
,
&
availInQ
);
/* Feed wavehdrs until we run out of wavehdrs or DSP space */
if
(
wwo
->
dwPartialOffset
==
0
)
{
while
(
wwo
->
lpPlayPtr
&&
availInQ
>
0
)
{
/* note the value that dwPlayedTotal will return when this wave finishes playing */
wwo
->
lpPlayPtr
->
reserved
=
wwo
->
dwWrittenTotal
+
wwo
->
lpPlayPtr
->
dwBufferLength
;
wodPlayer_WriteMaxFrags
(
wwo
,
&
availInQ
);
}
}
}
return
wodPlayer_DSPWait
(
wwo
,
availInQ
);
return
wodPlayer_DSPWait
(
wwo
);
}
...
...
@@ -1080,10 +1122,8 @@ static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
/* Remember fragsize and total buffer size for future use */
wwo
->
dwFragmentSize
=
info
.
fragsize
;
wwo
->
dwBufferSize
=
info
.
fragstotal
*
info
.
fragsize
;
wwo
->
uWaitForFragments
=
info
.
fragstotal
*
REFILL_BUFFER_WHEN
;
wwo
->
dwPlayedTotal
=
0
;
wwo
->
dwWrittenTotal
=
0
;
TRACE
(
"wait for %d fragments
\n
"
,
wwo
->
uWaitForFragments
);
OSS_InitRingMessage
(
&
wwo
->
msgRing
);
...
...
@@ -1131,7 +1171,6 @@ static DWORD wodClose(WORD wDevID)
WARN
(
"buffers still playing !
\n
"
);
ret
=
WAVERR_STILLPLAYING
;
}
else
{
TRACE
(
"imhere[3-close]
\n
"
);
if
(
wwo
->
hThread
!=
INVALID_HANDLE_VALUE
)
{
OSS_AddRingMessage
(
&
wwo
->
msgRing
,
WINE_WM_CLOSING
,
0
,
TRUE
);
}
...
...
@@ -1174,7 +1213,6 @@ static DWORD wodWrite(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
lpWaveHdr
->
dwFlags
|=
WHDR_INQUEUE
;
lpWaveHdr
->
lpNext
=
0
;
TRACE
(
"imhere[3-HEADER]
\n
"
);
OSS_AddRingMessage
(
&
WOutDev
[
wDevID
].
msgRing
,
WINE_WM_HEADER
,
(
DWORD
)
lpWaveHdr
,
FALSE
);
return
MMSYSERR_NOERROR
;
...
...
@@ -1233,7 +1271,6 @@ static DWORD wodPause(WORD wDevID)
return
MMSYSERR_BADDEVICEID
;
}
TRACE
(
"imhere[3-PAUSING]
\n
"
);
OSS_AddRingMessage
(
&
WOutDev
[
wDevID
].
msgRing
,
WINE_WM_PAUSING
,
0
,
TRUE
);
return
MMSYSERR_NOERROR
;
...
...
@@ -1252,7 +1289,6 @@ static DWORD wodRestart(WORD wDevID)
}
if
(
WOutDev
[
wDevID
].
state
==
WINE_WS_PAUSED
)
{
TRACE
(
"imhere[3-RESTARTING]
\n
"
);
OSS_AddRingMessage
(
&
WOutDev
[
wDevID
].
msgRing
,
WINE_WM_RESTARTING
,
0
,
TRUE
);
}
...
...
@@ -1276,7 +1312,6 @@ static DWORD wodReset(WORD wDevID)
return
MMSYSERR_BADDEVICEID
;
}
TRACE
(
"imhere[3-RESET]
\n
"
);
OSS_AddRingMessage
(
&
WOutDev
[
wDevID
].
msgRing
,
WINE_WM_RESETTING
,
0
,
TRUE
);
return
MMSYSERR_NOERROR
;
...
...
@@ -1424,7 +1459,7 @@ static DWORD wodGetNumDevs(void)
{
DWORD
ret
=
1
;
/* FIXME: For now, only one sound device (SOUND_DEV) is allowed */
int
audio
=
OSS_OpenDevice
(
O_WRONLY
);
int
audio
=
OSS_OpenDevice
(
O
SS_FullDuplex
?
O_RDWR
:
O
_WRONLY
);
if
(
audio
==
-
1
)
{
if
(
errno
!=
EBUSY
)
...
...
@@ -2357,7 +2392,7 @@ static DWORD widPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
return
WAVERR_STILLPLAYING
;
lpWaveHdr
->
dwFlags
|=
WHDR_PREPARED
;
lpWaveHdr
->
dwFlags
&=
~
(
WHDR_INQUEUE
|
WHDR_DONE
)
;
lpWaveHdr
->
dwFlags
&=
~
WHDR_DONE
;
lpWaveHdr
->
dwBytesRecorded
=
0
;
TRACE
(
"header prepared !
\n
"
);
return
MMSYSERR_NOERROR
;
...
...
@@ -2374,7 +2409,7 @@ static DWORD widUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
if
(
lpWaveHdr
->
dwFlags
&
WHDR_INQUEUE
)
return
WAVERR_STILLPLAYING
;
lpWaveHdr
->
dwFlags
&=
~
(
WHDR_PREPARED
|
WHDR_INQUEUE
)
;
lpWaveHdr
->
dwFlags
&=
~
WHDR_PREPARED
;
lpWaveHdr
->
dwFlags
|=
WHDR_DONE
;
return
MMSYSERR_NOERROR
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment