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
24da756e
Commit
24da756e
authored
Nov 19, 2004
by
Robert Reif
Committed by
Alexandre Julliard
Nov 19, 2004
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
One step closer to getting hardware accelerated capture working.
parent
9e4a5813
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
463 additions
and
60 deletions
+463
-60
dscapture.c
dlls/winmm/wineoss/dscapture.c
+463
-60
No files found.
dlls/winmm/wineoss/dscapture.c
View file @
24da756e
...
...
@@ -54,7 +54,7 @@
#include "audio.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
wav
e
);
WINE_DEFAULT_DEBUG_CHANNEL
(
dscaptur
e
);
#ifdef HAVE_OSS
...
...
@@ -104,11 +104,16 @@ struct IDsCaptureDriverBufferImpl
/* IDsCaptureDriverBufferImpl fields */
IDsCaptureDriverImpl
*
drv
;
DWORD
buflen
;
LPBYTE
buffer
;
DWORD
writeptr
;
LPBYTE
mapping
;
DWORD
maplen
;
LPBYTE
buffer
;
/* user buffer */
DWORD
buflen
;
/* user buffer length */
LPBYTE
mapping
;
/* DMA buffer */
DWORD
maplen
;
/* DMA buffer length */
BOOL
is_direct_map
;
/* DMA == user ? */
DWORD
fragsize
;
DWORD
map_writepos
;
/* DMA write offset */
DWORD
map_readpos
;
/* DMA read offset */
DWORD
writeptr
;
/* user write offset */
DWORD
readptr
;
/* user read offset */
/* IDsDriverNotifyImpl fields */
IDsCaptureDriverNotifyImpl
*
notify
;
...
...
@@ -121,6 +126,13 @@ struct IDsCaptureDriverBufferImpl
BOOL
is_capturing
;
BOOL
is_looping
;
WAVEFORMATEX
wfx
;
HANDLE
hThread
;
DWORD
dwThreadID
;
HANDLE
hStartUpEvent
;
HANDLE
hExitEvent
;
int
pipe_fd
[
2
];
int
fd
;
};
static
HRESULT
WINAPI
IDsCaptureDriverPropertySetImpl_Create
(
...
...
@@ -297,7 +309,7 @@ static HRESULT WINAPI IDsCaptureDriverNotifyImpl_SetNotificationPositions(
return
DSERR_INVALIDPARAM
;
}
if
(
TRACE_ON
(
wav
e
))
{
if
(
TRACE_ON
(
dscaptur
e
))
{
int
i
;
for
(
i
=
0
;
i
<
howmuch
;
i
++
)
TRACE
(
"notify at %ld to 0x%08lx
\n
"
,
...
...
@@ -343,7 +355,8 @@ static HRESULT DSCDB_MapBuffer(IDsCaptureDriverBufferImpl *dscdb)
dscdb
,
strerror
(
errno
));
return
DSERR_GENERIC
;
}
TRACE
(
"(%p): sound device has been mapped for direct access at %p, size=%ld
\n
"
,
dscdb
,
dscdb
->
mapping
,
dscdb
->
maplen
);
TRACE
(
"(%p): sound device has been mapped for direct access at %p, "
"size=%ld
\n
"
,
dscdb
,
dscdb
->
mapping
,
dscdb
->
maplen
);
}
return
DS_OK
;
}
...
...
@@ -421,7 +434,31 @@ static ULONG WINAPI IDsCaptureDriverBufferImpl_Release(PIDSCDRIVERBUFFER iface)
ref
=
InterlockedDecrement
(
&
(
This
->
ref
));
if
(
ref
==
0
)
{
WINE_WAVEIN
*
wwi
;
wwi
=
&
WInDev
[
This
->
drv
->
wDevID
];
if
(
This
->
hThread
)
{
int
x
=
0
;
/* request thread termination */
write
(
This
->
pipe_fd
[
1
],
&
x
,
sizeof
(
x
));
/* wait for reply */
WaitForSingleObject
(
This
->
hExitEvent
,
INFINITE
);
CloseHandle
(
This
->
hExitEvent
);
}
close
(
This
->
pipe_fd
[
0
]);
close
(
This
->
pipe_fd
[
1
]);
DSCDB_UnmapBuffer
(
This
);
OSS_CloseDevice
(
wwi
->
ossdev
);
wwi
->
state
=
WINE_WS_CLOSED
;
wwi
->
dwFragmentSize
=
0
;
This
->
drv
->
capture_buffer
=
NULL
;
if
(
This
->
notifies
!=
NULL
)
HeapFree
(
GetProcessHeap
(),
0
,
This
->
notifies
);
HeapFree
(
GetProcessHeap
(),
0
,
This
);
...
...
@@ -441,8 +478,49 @@ static HRESULT WINAPI IDsCaptureDriverBufferImpl_Lock(
DWORD
dwFlags
)
{
IDsCaptureDriverBufferImpl
*
This
=
(
IDsCaptureDriverBufferImpl
*
)
iface
;
FIXME
(
"(%p,%p,%p,%p,%p,%ld,%ld,0x%08lx): stub!
\n
"
,
This
,
ppvAudio1
,
pdwLen1
,
TRACE
(
"(%p,%p,%p,%p,%p,%ld,%ld,0x%08lx)
\n
"
,
This
,
ppvAudio1
,
pdwLen1
,
ppvAudio2
,
pdwLen2
,
dwWritePosition
,
dwWriteLen
,
dwFlags
);
if
(
This
->
is_direct_map
)
{
if
(
ppvAudio1
)
*
ppvAudio1
=
This
->
mapping
+
dwWritePosition
;
if
(
dwWritePosition
+
dwWriteLen
<
This
->
maplen
)
{
if
(
pdwLen1
)
*
pdwLen1
=
dwWriteLen
;
if
(
ppvAudio2
)
*
ppvAudio2
=
0
;
if
(
pdwLen2
)
*
pdwLen2
=
0
;
}
else
{
if
(
pdwLen1
)
*
pdwLen1
=
This
->
maplen
-
dwWritePosition
;
if
(
ppvAudio2
)
*
ppvAudio2
=
0
;
if
(
pdwLen2
)
*
pdwLen2
=
dwWriteLen
-
(
This
->
maplen
-
dwWritePosition
);
}
}
else
{
if
(
ppvAudio1
)
*
ppvAudio1
=
This
->
buffer
+
dwWritePosition
;
if
(
dwWritePosition
+
dwWriteLen
<
This
->
buflen
)
{
if
(
pdwLen1
)
*
pdwLen1
=
dwWriteLen
;
if
(
ppvAudio2
)
*
ppvAudio2
=
0
;
if
(
pdwLen2
)
*
pdwLen2
=
0
;
}
else
{
if
(
pdwLen1
)
*
pdwLen1
=
This
->
buflen
-
dwWritePosition
;
if
(
ppvAudio2
)
*
ppvAudio2
=
0
;
if
(
pdwLen2
)
*
pdwLen2
=
dwWriteLen
-
(
This
->
buflen
-
dwWritePosition
);
}
}
return
DS_OK
;
}
...
...
@@ -454,7 +532,13 @@ static HRESULT WINAPI IDsCaptureDriverBufferImpl_Unlock(
DWORD
dwLen2
)
{
IDsCaptureDriverBufferImpl
*
This
=
(
IDsCaptureDriverBufferImpl
*
)
iface
;
FIXME
(
"(%p,%p,%ld,%p,%ld): stub!
\n
"
,
This
,
pvAudio1
,
dwLen1
,
pvAudio2
,
dwLen2
);
TRACE
(
"(%p,%p,%ld,%p,%ld)
\n
"
,
This
,
pvAudio1
,
dwLen1
,
pvAudio2
,
dwLen2
);
if
(
This
->
is_direct_map
)
This
->
map_readpos
=
(
This
->
map_readpos
+
dwLen1
+
dwLen2
)
%
This
->
maplen
;
else
This
->
readptr
=
(
This
->
readptr
+
dwLen1
+
dwLen2
)
%
This
->
buflen
;
return
DS_OK
;
}
...
...
@@ -464,8 +548,6 @@ static HRESULT WINAPI IDsCaptureDriverBufferImpl_GetPosition(
LPDWORD
lpdwRead
)
{
IDsCaptureDriverBufferImpl
*
This
=
(
IDsCaptureDriverBufferImpl
*
)
iface
;
count_info
info
;
DWORD
ptr
;
TRACE
(
"(%p,%p,%p)
\n
"
,
This
,
lpdwCapture
,
lpdwRead
);
if
(
WInDev
[
This
->
drv
->
wDevID
].
state
==
WINE_WS_CLOSED
)
{
...
...
@@ -480,23 +562,21 @@ static HRESULT WINAPI IDsCaptureDriverBufferImpl_GetPosition(
*
lpdwRead
=
0
;
}
if
(
ioctl
(
WInDev
[
This
->
drv
->
wDevID
].
ossdev
->
fd
,
SNDCTL_DSP_GETIPTR
,
&
info
)
<
0
)
{
ERR
(
"ioctl(%s, SNDCTL_DSP_GETIPTR) failed (%s)
\n
"
,
WInDev
[
This
->
drv
->
wDevID
].
ossdev
->
dev_name
,
strerror
(
errno
));
return
DSERR_GENERIC
;
}
ptr
=
info
.
ptr
&
~
3
;
/* align the pointer, just in case */
if
(
lpdwCapture
)
*
lpdwCapture
=
ptr
;
if
(
This
->
is_direct_map
)
{
if
(
lpdwCapture
)
*
lpdwCapture
=
This
->
map_writepos
;
if
(
lpdwRead
)
{
/* add some safety margin (not strictly necessary, but...) */
if
(
WInDev
[
This
->
drv
->
wDevID
].
ossdev
->
in_caps_support
&
WAVECAPS_SAMPLEACCURATE
)
*
lpdwRead
=
ptr
+
32
;
else
*
lpdwRead
=
ptr
+
WInDev
[
This
->
drv
->
wDevID
].
dwFragmentSize
;
while
(
*
lpdwRead
>
This
->
buflen
)
*
lpdwRead
-=
This
->
buflen
;
*
lpdwRead
=
This
->
map_readpos
;
}
TRACE
(
"capturepos=%ld, readpos=%ld
\n
"
,
lpdwCapture
?*
lpdwCapture
:
0
,
lpdwRead
?*
lpdwRead
:
0
);
}
else
{
if
(
lpdwCapture
)
*
lpdwCapture
=
This
->
writeptr
;
if
(
lpdwRead
)
*
lpdwRead
=
This
->
readptr
;
}
TRACE
(
"capturepos=%ld, readpos=%ld
\n
"
,
lpdwCapture
?*
lpdwCapture
:
0
,
lpdwRead
?*
lpdwRead
:
0
);
return
DS_OK
;
}
...
...
@@ -588,11 +668,16 @@ static HRESULT WINAPI IDsCaptureDriverBufferImpl_Stop(PIDSCDRIVERBUFFER iface)
This
->
is_capturing
=
FALSE
;
This
->
is_looping
=
FALSE
;
/* Most OSS drivers just can't stop capturing without closing the device...
* so we need to somehow signal to our DirectSound implementation
* that it should completely recreate this HW buffer...
* this unexpected error code should do the trick... */
return
DSERR_BUFFERLOST
;
if
(
This
->
hThread
)
{
int
x
=
0
;
write
(
This
->
pipe_fd
[
1
],
&
x
,
sizeof
(
x
));
WaitForSingleObject
(
This
->
hExitEvent
,
INFINITE
);
CloseHandle
(
This
->
hExitEvent
);
This
->
hExitEvent
=
INVALID_HANDLE_VALUE
;
This
->
hThread
=
0
;
}
return
DS_OK
;
}
static
HRESULT
WINAPI
IDsCaptureDriverBufferImpl_SetFormat
(
...
...
@@ -677,7 +762,6 @@ static HRESULT WINAPI IDsCaptureDriverImpl_GetDriverDesc(
/* copy version from driver */
memcpy
(
pDesc
,
&
(
WInDev
[
This
->
wDevID
].
ossdev
->
ds_desc
),
sizeof
(
DSDRIVERDESC
));
pDesc
->
dwFlags
|=
DSDDESC_USESYSTEMMEMORY
;
pDesc
->
dnDevNode
=
WInDev
[
This
->
wDevID
].
waveDesc
.
dnDevNode
;
pDesc
->
wVxdId
=
0
;
pDesc
->
wReserved
=
0
;
...
...
@@ -720,6 +804,167 @@ static HRESULT WINAPI IDsCaptureDriverImpl_GetCaps(
return
DS_OK
;
}
static
void
DSCDB_CheckEvent
(
IDsCaptureDriverBufferImpl
*
dscb
,
DWORD
writepos
,
DWORD
len
,
DWORD
buflen
)
{
LPDSBPOSITIONNOTIFY
event
=
dscb
->
notifies
+
dscb
->
notify_index
;
DWORD
offset
=
event
->
dwOffset
;
TRACE
(
"(%p,%ld,%ld,%ld)
\n
"
,
dscb
,
writepos
,
len
,
buflen
);
TRACE
(
"(%p) buflen = %ld, writeptr = %ld
\n
"
,
dscb
,
dscb
->
buflen
,
dscb
->
writeptr
);
TRACE
(
"checking %d, position %ld, event = %p
\n
"
,
dscb
->
notify_index
,
offset
,
event
->
hEventNotify
);
if
((
writepos
+
len
)
>
offset
)
{
TRACE
(
"signalled event %p (%d) %ld
\n
"
,
event
->
hEventNotify
,
dscb
->
notify_index
,
offset
);
SetEvent
(
event
->
hEventNotify
);
dscb
->
notify_index
=
(
dscb
->
notify_index
+
1
)
%
dscb
->
nrofnotifies
;
return
;
}
else
if
((
writepos
+
len
)
>
buflen
)
{
writepos
=
writepos
+
len
-
buflen
;
if
((
writepos
+
len
)
>
offset
)
{
TRACE
(
"signalled event %p (%d) %ld
\n
"
,
event
->
hEventNotify
,
dscb
->
notify_index
,
offset
);
SetEvent
(
event
->
hEventNotify
);
dscb
->
notify_index
=
(
dscb
->
notify_index
+
1
)
%
dscb
->
nrofnotifies
;
return
;
}
}
return
;
}
/* FIXME: using memcpy can cause strange crashes so use this fake one */
static
void
*
my_memcpy
(
void
*
dst
,
const
void
*
src
,
int
length
)
{
int
i
;
for
(
i
=
0
;
i
<
length
;
i
++
)
((
char
*
)
dst
)[
i
]
=
((
char
*
)
src
)[
i
];
return
dst
;
}
static
DWORD
CALLBACK
DSCDB_Thread
(
LPVOID
lpParameter
)
{
IDsCaptureDriverBufferImpl
*
This
=
(
IDsCaptureDriverBufferImpl
*
)
lpParameter
;
struct
pollfd
poll_list
[
2
];
int
retval
;
DWORD
offset
=
0
;
DWORD
map_offset
=
0
;
TRACE
(
"(%p)
\n
"
,
lpParameter
);
poll_list
[
0
].
fd
=
This
->
fd
;
/* data available */
poll_list
[
1
].
fd
=
This
->
pipe_fd
[
0
];
/* message from parent process */
poll_list
[
0
].
events
=
POLLIN
;
poll_list
[
1
].
events
=
POLLIN
;
/* let other process know we are running */
SetEvent
(
This
->
hStartUpEvent
);
while
(
1
)
{
/* wait for something to happen */
retval
=
poll
(
poll_list
,(
unsigned
long
)
2
,
-
1
);
/* Retval will always be greater than 0 or -1 in this case.
* Since we're doing it while blocking
*/
if
(
retval
<
0
)
{
ERR
(
"Error while polling: %s
\n
"
,
strerror
(
errno
));
continue
;
}
/* check for exit command */
if
((
poll_list
[
1
].
revents
&
POLLIN
)
==
POLLIN
)
{
TRACE
(
"(%p) done
\n
"
,
lpParameter
);
/* acknowledge command and exit */
SetEvent
(
This
->
hExitEvent
);
ExitThread
(
0
);
return
0
;
}
/* check for data */
if
((
poll_list
[
0
].
revents
&
POLLIN
)
==
POLLIN
)
{
count_info
info
;
int
fragsize
,
first
,
second
;
/* get the current DMA position */
if
(
ioctl
(
This
->
fd
,
SNDCTL_DSP_GETIPTR
,
&
info
)
<
0
)
{
ERR
(
"ioctl(%s, SNDCTL_DSP_GETIPTR) failed (%s)
\n
"
,
WInDev
[
This
->
drv
->
wDevID
].
ossdev
->
dev_name
,
strerror
(
errno
));
return
DSERR_GENERIC
;
}
if
(
This
->
is_direct_map
)
{
offset
=
This
->
map_writepos
;
This
->
map_writepos
=
info
.
ptr
;
if
(
info
.
ptr
<
offset
)
fragsize
=
info
.
ptr
+
This
->
maplen
-
offset
;
else
fragsize
=
info
.
ptr
-
offset
;
DSCDB_CheckEvent
(
This
,
offset
,
fragsize
,
This
->
maplen
);
}
else
{
map_offset
=
This
->
map_writepos
;
offset
=
This
->
writeptr
;
/* test for mmap buffer wrap */
if
(
info
.
ptr
<
map_offset
)
{
/* mmap buffer wrapped */
fragsize
=
info
.
ptr
+
This
->
maplen
-
map_offset
;
/* check for user buffer wrap */
if
((
offset
+
fragsize
)
>
This
->
buflen
)
{
/* both buffers wrapped
* figure out which wrapped first
*/
if
((
This
->
maplen
-
map_offset
)
>
(
This
->
buflen
-
offset
))
{
/* user buffer wrapped first */
first
=
This
->
buflen
-
offset
;
second
=
(
This
->
maplen
-
map_offset
)
-
first
;
my_memcpy
(
This
->
buffer
+
offset
,
This
->
mapping
+
map_offset
,
first
);
my_memcpy
(
This
->
buffer
,
This
->
mapping
+
map_offset
+
first
,
second
);
my_memcpy
(
This
->
buffer
+
second
,
This
->
mapping
,
fragsize
-
(
first
+
second
));
}
else
{
/* mmap buffer wrapped first */
first
=
This
->
maplen
-
map_offset
;
second
=
(
This
->
buflen
-
offset
)
-
first
;
my_memcpy
(
This
->
buffer
+
offset
,
This
->
mapping
+
map_offset
,
first
);
my_memcpy
(
This
->
buffer
+
offset
+
first
,
This
->
mapping
,
second
);
my_memcpy
(
This
->
buffer
,
This
->
mapping
+
second
,
fragsize
-
(
first
+
second
));
}
}
else
{
/* only mmap buffer wrapped */
first
=
This
->
maplen
-
map_offset
;
my_memcpy
(
This
->
buffer
+
offset
,
This
->
mapping
+
map_offset
,
first
);
my_memcpy
(
This
->
buffer
+
offset
+
first
,
This
->
mapping
,
fragsize
-
first
);
}
}
else
{
/* mmap buffer didn't wrap */
fragsize
=
info
.
ptr
-
map_offset
;
/* check for user buffer wrap */
if
((
offset
+
fragsize
)
>
This
->
buflen
)
{
first
=
This
->
buflen
-
offset
;
my_memcpy
(
This
->
buffer
+
offset
,
This
->
mapping
+
map_offset
,
first
);
my_memcpy
(
This
->
buffer
,
This
->
mapping
+
map_offset
+
first
,
fragsize
-
first
);
}
else
my_memcpy
(
This
->
buffer
+
offset
,
This
->
mapping
+
map_offset
,
fragsize
);
}
This
->
map_writepos
=
info
.
ptr
;
This
->
writeptr
=
(
This
->
writeptr
+
fragsize
)
%
This
->
buflen
;
DSCDB_CheckEvent
(
This
,
offset
,
fragsize
,
This
->
buflen
);
}
}
}
return
TRUE
;
}
static
HRESULT
WINAPI
IDsCaptureDriverImpl_CreateCaptureBuffer
(
PIDSCDRIVER
iface
,
LPWAVEFORMATEX
pwfx
,
...
...
@@ -733,7 +978,9 @@ static HRESULT WINAPI IDsCaptureDriverImpl_CreateCaptureBuffer(
IDsCaptureDriverBufferImpl
**
ippdscdb
=
(
IDsCaptureDriverBufferImpl
**
)
ppvObj
;
HRESULT
err
;
audio_buf_info
info
;
int
enable
;
int
audio_fragment
,
fsize
,
shift
,
ret
;
BOOL
bNewBuffer
=
FALSE
;
WINE_WAVEIN
*
wwi
;
TRACE
(
"(%p,%p,%lx,%lx,%p,%p,%p)
\n
"
,
This
,
pwfx
,
dwFlags
,
dwCardAddress
,
pdwcbBufferSize
,
ppbBuffer
,
ppvObj
);
...
...
@@ -742,7 +989,26 @@ static HRESULT WINAPI IDsCaptureDriverImpl_CreateCaptureBuffer(
return
DSERR_ALLOCATED
;
}
*
ippdscdb
=
(
IDsCaptureDriverBufferImpl
*
)
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
IDsCaptureDriverBufferImpl
));
/* must be given a buffer size */
if
(
pdwcbBufferSize
==
NULL
||
*
pdwcbBufferSize
==
0
)
{
TRACE
(
"invalid parameter: pdwcbBufferSize
\n
"
);
return
DSERR_INVALIDPARAM
;
}
/* must be given a buffer pointer */
if
(
ppbBuffer
==
NULL
)
{
TRACE
(
"invalid parameter: ppbBuffer
\n
"
);
return
DSERR_INVALIDPARAM
;
}
/* may or may not be given a buffer */
if
(
*
ppbBuffer
==
NULL
)
{
TRACE
(
"creating buffer
\n
"
);
bNewBuffer
=
TRUE
;
/* not given a buffer so create one */
}
else
TRACE
(
"using supplied buffer
\n
"
);
*
ippdscdb
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
IDsCaptureDriverBufferImpl
));
if
(
*
ippdscdb
==
NULL
)
{
TRACE
(
"out of memory
\n
"
);
return
DSERR_OUTOFMEMORY
;
...
...
@@ -758,55 +1024,192 @@ static HRESULT WINAPI IDsCaptureDriverImpl_CreateCaptureBuffer(
(
*
ippdscdb
)
->
property_set
=
NULL
;
(
*
ippdscdb
)
->
is_capturing
=
FALSE
;
(
*
ippdscdb
)
->
is_looping
=
FALSE
;
(
*
ippdscdb
)
->
wfx
=
*
pwfx
;
(
*
ippdscdb
)
->
buflen
=
*
pdwcbBufferSize
;
if
(
WInDev
[
This
->
wDevID
].
state
==
WINE_WS_CLOSED
)
{
WAVEOPENDESC
desc
;
desc
.
hWave
=
0
;
desc
.
lpFormat
=
pwfx
;
desc
.
dwCallback
=
0
;
desc
.
dwInstance
=
0
;
desc
.
uMappedDeviceID
=
0
;
desc
.
dnDevNode
=
0
;
err
=
widOpen
(
This
->
wDevID
,
&
desc
,
dwFlags
|
WAVE_DIRECTSOUND
);
if
(
err
!=
MMSYSERR_NOERROR
)
{
TRACE
(
"widOpen failed
\n
"
);
return
err
;
if
(
bNewBuffer
)
(
*
ippdscdb
)
->
buffer
=
NULL
;
else
(
*
ippdscdb
)
->
buffer
=
*
ppbBuffer
;
wwi
=
&
WInDev
[
This
->
wDevID
];
if
(
wwi
->
state
==
WINE_WS_CLOSED
)
{
unsigned
int
frag_size
;
if
(
wwi
->
ossdev
->
open_count
>
0
)
{
/* opened already so use existing fragment size */
audio_fragment
=
wwi
->
ossdev
->
audio_fragment
;
}
else
{
/* calculate a fragment size */
unsigned
int
mask
=
0xffffffff
;
/* calculate largest fragment size less than 10 ms. */
fsize
=
pwfx
->
nAvgBytesPerSec
/
100
;
/* 10 ms chunk */
shift
=
0
;
while
((
1
<<
shift
)
<=
fsize
)
shift
++
;
shift
--
;
fsize
=
1
<<
shift
;
TRACE
(
"shift = %d, fragment size = %d
\n
"
,
shift
,
fsize
);
TRACE
(
"BufferSize=%ld(%08lx)
\n
"
,
*
pdwcbBufferSize
,
*
pdwcbBufferSize
);
/* See if we can directly map the buffer first.
* (buffer length is multiple of a power of 2)
*/
mask
=
(
mask
>>
(
32
-
shift
));
TRACE
(
"mask=%08x
\n
"
,
mask
);
if
(
*
pdwcbBufferSize
&
mask
)
{
/* no so try a smaller fragment size greater than 1 ms */
int
new_shift
=
shift
-
1
;
int
min_shift
=
0
;
int
min_fsize
=
pwfx
->
nAvgBytesPerSec
/
1000
;
BOOL
found_one
=
FALSE
;
while
((
1
<<
min_shift
)
<=
min_fsize
)
min_shift
++
;
min_shift
--
;
while
(
new_shift
>
min_shift
)
{
if
(
*
pdwcbBufferSize
&
(
-
1
>>
(
32
-
new_shift
)))
{
new_shift
--
;
continue
;
}
else
{
found_one
=
TRUE
;
break
;
}
}
if
(
found_one
)
{
/* found a smaller one that will work */
audio_fragment
=
((
*
pdwcbBufferSize
>>
new_shift
)
<<
16
)
|
new_shift
;
(
*
ippdscdb
)
->
is_direct_map
=
TRUE
;
TRACE
(
"new shift = %d, fragment size = %d
\n
"
,
new_shift
,
1
<<
(
audio_fragment
&
0xffff
));
}
else
{
/* buffer can't be direct mapped */
audio_fragment
=
0x00100000
+
shift
;
/* 16 fragments of 2^shift */
(
*
ippdscdb
)
->
is_direct_map
=
FALSE
;
}
}
else
{
/* good fragment size */
audio_fragment
=
((
*
pdwcbBufferSize
>>
shift
)
<<
16
)
|
shift
;
(
*
ippdscdb
)
->
is_direct_map
=
TRUE
;
}
}
frag_size
=
1
<<
(
audio_fragment
&
0xffff
);
TRACE
(
"is_direct_map = %s
\n
"
,
(
*
ippdscdb
)
->
is_direct_map
?
"TRUE"
:
"FALSE"
);
TRACE
(
"requesting %d %d byte fragments (%d bytes) (%ld ms/fragment)
\n
"
,
audio_fragment
>>
16
,
frag_size
,
frag_size
*
(
audio_fragment
>>
16
),
(
frag_size
*
1000
)
/
pwfx
->
nAvgBytesPerSec
);
ret
=
OSS_OpenDevice
(
wwi
->
ossdev
,
O_RDWR
,
&
audio_fragment
,
1
,
pwfx
->
nSamplesPerSec
,
(
pwfx
->
nChannels
>
1
)
?
1
:
0
,
(
pwfx
->
wBitsPerSample
==
16
)
?
AFMT_S16_LE
:
AFMT_U8
);
if
(
ret
!=
0
)
{
WARN
(
"OSS_OpenDevice failed
\n
"
);
HeapFree
(
GetProcessHeap
(),
0
,
*
ippdscdb
);
*
ippdscdb
=
NULL
;
return
DSERR_GENERIC
;
}
wwi
->
state
=
WINE_WS_STOPPED
;
/* find out what fragment and buffer sizes OSS gave us */
if
(
ioctl
(
wwi
->
ossdev
->
fd
,
SNDCTL_DSP_GETISPACE
,
&
info
)
<
0
)
{
ERR
(
"ioctl(%s, SNDCTL_DSP_GETISPACE) failed (%s)
\n
"
,
wwi
->
ossdev
->
dev_name
,
strerror
(
errno
));
OSS_CloseDevice
(
wwi
->
ossdev
);
wwi
->
state
=
WINE_WS_CLOSED
;
HeapFree
(
GetProcessHeap
(),
0
,
*
ippdscdb
);
*
ippdscdb
=
NULL
;
return
DSERR_GENERIC
;
}
TRACE
(
"got %d %d byte fragments (%d bytes) (%ld ms/fragment)
\n
"
,
info
.
fragstotal
,
info
.
fragsize
,
info
.
fragstotal
*
info
.
fragsize
,
info
.
fragsize
*
1000
/
pwfx
->
nAvgBytesPerSec
);
wwi
->
dwTotalRecorded
=
0
;
memcpy
(
&
wwi
->
waveFormat
,
pwfx
,
sizeof
(
PCMWAVEFORMAT
));
wwi
->
dwFragmentSize
=
info
.
fragsize
;
/* make sure we got what we asked for */
if
((
*
ippdscdb
)
->
buflen
!=
info
.
fragstotal
*
info
.
fragsize
)
{
TRACE
(
"Couldn't create requested buffer
\n
"
);
if
((
*
ippdscdb
)
->
is_direct_map
)
{
(
*
ippdscdb
)
->
is_direct_map
=
FALSE
;
TRACE
(
"is_direct_map = FALSE
\n
"
);
}
}
else
if
(
info
.
fragsize
!=
frag_size
)
{
TRACE
(
"same buffer length but different fragment size
\n
"
);
}
}
(
*
ippdscdb
)
->
fd
=
WInDev
[
This
->
wDevID
].
ossdev
->
fd
;
if
(
pipe
((
*
ippdscdb
)
->
pipe_fd
)
<
0
)
{
TRACE
(
"pipe() failed (%s)
\n
"
,
strerror
(
errno
));
OSS_CloseDevice
(
wwi
->
ossdev
);
wwi
->
state
=
WINE_WS_CLOSED
;
HeapFree
(
GetProcessHeap
(),
0
,
*
ippdscdb
);
*
ippdscdb
=
NULL
;
return
DSERR_GENERIC
;
}
/* check how big the DMA buffer is now */
if
(
ioctl
(
WInDev
[
This
->
wDevID
].
ossdev
->
fd
,
SNDCTL_DSP_GETISPACE
,
&
info
)
<
0
)
{
if
(
ioctl
(
wwi
->
ossdev
->
fd
,
SNDCTL_DSP_GETISPACE
,
&
info
)
<
0
)
{
ERR
(
"ioctl(%s, SNDCTL_DSP_GETISPACE) failed (%s)
\n
"
,
WInDev
[
This
->
wDevID
].
ossdev
->
dev_name
,
strerror
(
errno
));
wwi
->
ossdev
->
dev_name
,
strerror
(
errno
));
OSS_CloseDevice
(
wwi
->
ossdev
);
wwi
->
state
=
WINE_WS_CLOSED
;
close
((
*
ippdscdb
)
->
pipe_fd
[
0
]);
close
((
*
ippdscdb
)
->
pipe_fd
[
1
]);
HeapFree
(
GetProcessHeap
(),
0
,
*
ippdscdb
);
*
ippdscdb
=
NULL
;
return
DSERR_GENERIC
;
}
(
*
ippdscdb
)
->
maplen
=
(
*
ippdscdb
)
->
buflen
=
info
.
fragstotal
*
info
.
fragsize
;
(
*
ippdscdb
)
->
maplen
=
info
.
fragstotal
*
info
.
fragsize
;
(
*
ippdscdb
)
->
fragsize
=
info
.
fragsize
;
(
*
ippdscdb
)
->
map_writepos
=
0
;
(
*
ippdscdb
)
->
map_readpos
=
0
;
/* map the DMA buffer */
err
=
DSCDB_MapBuffer
(
*
ippdscdb
);
if
(
err
!=
DS_OK
)
{
OSS_CloseDevice
(
wwi
->
ossdev
);
wwi
->
state
=
WINE_WS_CLOSED
;
close
((
*
ippdscdb
)
->
pipe_fd
[
0
]);
close
((
*
ippdscdb
)
->
pipe_fd
[
1
]);
HeapFree
(
GetProcessHeap
(),
0
,
*
ippdscdb
);
*
ippdscdb
=
NULL
;
return
err
;
}
/* c
apture buffer is ready to go
*/
*
pdwcbBufferSize
=
(
*
ippdscdb
)
->
maplen
;
*
ppbBuffer
=
(
*
ippdscdb
)
->
mapping
;
/* c
reate the buffer if necessary
*/
if
(
!
(
*
ippdscdb
)
->
buffer
)
(
*
ippdscdb
)
->
buffer
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,(
*
ippdscdb
)
->
buflen
)
;
/* some drivers need some extra nudging after mapping */
WInDev
[
This
->
wDevID
].
ossdev
->
bInputEnabled
=
FALSE
;
enable
=
getEnables
(
WInDev
[
This
->
wDevID
].
ossdev
);
if
(
ioctl
(
WInDev
[
This
->
wDevID
].
ossdev
->
fd
,
SNDCTL_DSP_SETTRIGGER
,
&
enable
)
<
0
)
{
ERR
(
"ioctl(%s, SNDCTL_DSP_SETTRIGGER) failed (%s)
\n
"
,
WInDev
[
This
->
wDevID
].
ossdev
->
dev_name
,
strerror
(
errno
));
return
DSERR_GENERIC
;
if
((
*
ippdscdb
)
->
buffer
==
NULL
)
{
OSS_CloseDevice
(
wwi
->
ossdev
);
wwi
->
state
=
WINE_WS_CLOSED
;
close
((
*
ippdscdb
)
->
pipe_fd
[
0
]);
close
((
*
ippdscdb
)
->
pipe_fd
[
1
]);
HeapFree
(
GetProcessHeap
(),
0
,
*
ippdscdb
);
*
ippdscdb
=
NULL
;
return
DSERR_OUTOFMEMORY
;
}
This
->
capture_buffer
=
*
ippdscdb
;
(
*
ippdscdb
)
->
hStartUpEvent
=
CreateEventA
(
NULL
,
FALSE
,
FALSE
,
NULL
);
(
*
ippdscdb
)
->
hExitEvent
=
CreateEventA
(
NULL
,
FALSE
,
FALSE
,
NULL
);
(
*
ippdscdb
)
->
hThread
=
CreateThread
(
NULL
,
0
,
DSCDB_Thread
,
(
LPVOID
)(
*
ippdscdb
),
0
,
&
((
*
ippdscdb
)
->
dwThreadID
));
WaitForSingleObject
((
*
ippdscdb
)
->
hStartUpEvent
,
INFINITE
);
CloseHandle
((
*
ippdscdb
)
->
hStartUpEvent
);
(
*
ippdscdb
)
->
hStartUpEvent
=
INVALID_HANDLE_VALUE
;
return
DS_OK
;
}
...
...
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