Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
qemu
提交
8b438ba3
Q
qemu
项目概览
openeuler
/
qemu
通知
10
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Q
qemu
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
8b438ba3
编写于
9月 12, 2009
作者:
M
malc
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
alsa: poll mode handling
Signed-off-by:
N
malc
<
av1474@comtv.ru
>
上级
dd8a5649
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
204 addition
and
21 deletion
+204
-21
audio/alsaaudio.c
audio/alsaaudio.c
+204
-21
未找到文件。
audio/alsaaudio.c
浏览文件 @
8b438ba3
...
...
@@ -23,6 +23,7 @@
*/
#include <alsa/asoundlib.h>
#include "qemu-common.h"
#include "qemu-char.h"
#include "audio.h"
#if QEMU_GNUC_PREREQ(4, 3)
...
...
@@ -32,16 +33,24 @@
#define AUDIO_CAP "alsa"
#include "audio_int.h"
struct
pollhlp
{
snd_pcm_t
*
handle
;
struct
pollfd
*
pfds
;
int
count
;
};
typedef
struct
ALSAVoiceOut
{
HWVoiceOut
hw
;
void
*
pcm_buf
;
snd_pcm_t
*
handle
;
struct
pollhlp
pollhlp
;
}
ALSAVoiceOut
;
typedef
struct
ALSAVoiceIn
{
HWVoiceIn
hw
;
snd_pcm_t
*
handle
;
void
*
pcm_buf
;
struct
pollhlp
pollhlp
;
}
ALSAVoiceIn
;
static
struct
{
...
...
@@ -123,6 +132,156 @@ static void alsa_anal_close (snd_pcm_t **handlep)
*
handlep
=
NULL
;
}
static
int
alsa_recover
(
snd_pcm_t
*
handle
)
{
int
err
=
snd_pcm_prepare
(
handle
);
if
(
err
<
0
)
{
alsa_logerr
(
err
,
"Failed to prepare handle %p
\n
"
,
handle
);
return
-
1
;
}
return
0
;
}
static
int
alsa_resume
(
snd_pcm_t
*
handle
)
{
int
err
=
snd_pcm_resume
(
handle
);
if
(
err
<
0
)
{
alsa_logerr
(
err
,
"Failed to resume handle %p
\n
"
,
handle
);
return
-
1
;
}
return
0
;
}
static
void
alsa_poll_handler
(
void
*
opaque
)
{
int
err
,
count
;
snd_pcm_state_t
state
;
struct
pollhlp
*
hlp
=
opaque
;
unsigned
short
revents
;
count
=
poll
(
hlp
->
pfds
,
hlp
->
count
,
0
);
if
(
count
<
0
)
{
dolog
(
"alsa_poll_handler: poll %s
\n
"
,
strerror
(
errno
));
return
;
}
if
(
!
count
)
{
return
;
}
/* XXX: ALSA example uses initial count, not the one returned by
poll, correct? */
err
=
snd_pcm_poll_descriptors_revents
(
hlp
->
handle
,
hlp
->
pfds
,
hlp
->
count
,
&
revents
);
if
(
err
<
0
)
{
alsa_logerr
(
err
,
"snd_pcm_poll_descriptors_revents"
);
return
;
}
if
(
!
(
revents
&
POLLOUT
))
{
if
(
conf
.
verbose
)
{
dolog
(
"revents = %d
\n
"
,
revents
);
}
return
;
}
state
=
snd_pcm_state
(
hlp
->
handle
);
switch
(
state
)
{
case
SND_PCM_STATE_XRUN
:
alsa_recover
(
hlp
->
handle
);
break
;
case
SND_PCM_STATE_SUSPENDED
:
alsa_resume
(
hlp
->
handle
);
break
;
case
SND_PCM_STATE_PREPARED
:
audio_run
(
"alsa run (prepared)"
);
break
;
case
SND_PCM_STATE_RUNNING
:
audio_run
(
"alsa run (running)"
);
break
;
default:
dolog
(
"Unexpected state %d
\n
"
,
state
);
}
}
static
int
alsa_poll_helper
(
snd_pcm_t
*
handle
,
struct
pollhlp
*
hlp
)
{
int
i
,
count
,
err
;
struct
pollfd
*
pfds
;
count
=
snd_pcm_poll_descriptors_count
(
handle
);
if
(
count
<=
0
)
{
dolog
(
"Could not initialize poll mode
\n
"
"Invalid number of poll descriptors %d
\n
"
,
count
);
return
-
1
;
}
pfds
=
audio_calloc
(
"alsa_poll_helper"
,
count
,
sizeof
(
*
pfds
));
if
(
!
pfds
)
{
dolog
(
"Could not initialize poll mode
\n
"
);
return
-
1
;
}
err
=
snd_pcm_poll_descriptors
(
handle
,
pfds
,
count
);
if
(
err
<
0
)
{
alsa_logerr
(
err
,
"Could not initialize poll mode
\n
"
"Could not obtain poll descriptors
\n
"
);
qemu_free
(
pfds
);
return
-
1
;
}
for
(
i
=
0
;
i
<
count
;
++
i
)
{
if
(
pfds
[
i
].
events
&
POLLIN
)
{
err
=
qemu_set_fd_handler
(
pfds
[
i
].
fd
,
alsa_poll_handler
,
NULL
,
hlp
);
}
if
(
pfds
[
i
].
events
&
POLLOUT
)
{
if
(
conf
.
verbose
)
{
dolog
(
"POLLOUT %d %d
\n
"
,
i
,
pfds
[
i
].
fd
);
}
err
=
qemu_set_fd_handler
(
pfds
[
i
].
fd
,
NULL
,
alsa_poll_handler
,
hlp
);
}
if
(
conf
.
verbose
)
{
dolog
(
"Set handler events=%#x index=%d fd=%d err=%d
\n
"
,
pfds
[
i
].
events
,
i
,
pfds
[
i
].
fd
,
err
);
}
if
(
err
)
{
dolog
(
"Failed to set handler events=%#x index=%d fd=%d err=%d
\n
"
,
pfds
[
i
].
events
,
i
,
pfds
[
i
].
fd
,
err
);
while
(
i
--
)
{
qemu_set_fd_handler
(
pfds
[
i
].
fd
,
NULL
,
NULL
,
NULL
);
}
qemu_free
(
pfds
);
return
-
1
;
}
}
hlp
->
pfds
=
pfds
;
hlp
->
count
=
count
;
hlp
->
handle
=
handle
;
return
0
;
}
static
int
alsa_poll_out
(
HWVoiceOut
*
hw
)
{
ALSAVoiceOut
*
alsa
=
(
ALSAVoiceOut
*
)
hw
;
return
alsa_poll_helper
(
alsa
->
handle
,
&
alsa
->
pollhlp
);
}
static
int
alsa_poll_in
(
HWVoiceIn
*
hw
)
{
ALSAVoiceIn
*
alsa
=
(
ALSAVoiceIn
*
)
hw
;
return
alsa_poll_helper
(
alsa
->
handle
,
&
alsa
->
pollhlp
);
}
static
int
alsa_write
(
SWVoiceOut
*
sw
,
void
*
buf
,
int
len
)
{
return
audio_pcm_sw_write
(
sw
,
buf
,
len
);
...
...
@@ -493,26 +652,6 @@ static int alsa_open (int in, struct alsa_params_req *req,
return
-
1
;
}
static
int
alsa_recover
(
snd_pcm_t
*
handle
)
{
int
err
=
snd_pcm_prepare
(
handle
);
if
(
err
<
0
)
{
alsa_logerr
(
err
,
"Failed to prepare handle %p
\n
"
,
handle
);
return
-
1
;
}
return
0
;
}
static
int
alsa_resume
(
snd_pcm_t
*
handle
)
{
int
err
=
snd_pcm_resume
(
handle
);
if
(
err
<
0
)
{
alsa_logerr
(
err
,
"Failed to resume handle %p
\n
"
,
handle
);
return
-
1
;
}
return
0
;
}
static
snd_pcm_sframes_t
alsa_get_avail
(
snd_pcm_t
*
handle
)
{
snd_pcm_sframes_t
avail
;
...
...
@@ -626,6 +765,22 @@ static int alsa_run_out (HWVoiceOut *hw)
return
decr
;
}
static
void
alsa_fini_poll
(
struct
pollhlp
*
hlp
)
{
int
i
;
struct
pollfd
*
pfds
=
hlp
->
pfds
;
if
(
pfds
)
{
for
(
i
=
0
;
i
<
hlp
->
count
;
++
i
)
{
qemu_set_fd_handler
(
pfds
[
i
].
fd
,
NULL
,
NULL
,
NULL
);
}
qemu_free
(
pfds
);
}
hlp
->
pfds
=
NULL
;
hlp
->
count
=
0
;
hlp
->
handle
=
NULL
;
}
static
void
alsa_fini_out
(
HWVoiceOut
*
hw
)
{
ALSAVoiceOut
*
alsa
=
(
ALSAVoiceOut
*
)
hw
;
...
...
@@ -637,6 +792,8 @@ static void alsa_fini_out (HWVoiceOut *hw)
qemu_free
(
alsa
->
pcm_buf
);
alsa
->
pcm_buf
=
NULL
;
}
alsa_fini_poll
(
&
alsa
->
pollhlp
);
}
static
int
alsa_init_out
(
HWVoiceOut
*
hw
,
struct
audsettings
*
as
)
...
...
@@ -705,11 +862,21 @@ static int alsa_voice_ctl (snd_pcm_t *handle, const char *typ, int pause)
static
int
alsa_ctl_out
(
HWVoiceOut
*
hw
,
int
cmd
,
...)
{
va_list
ap
;
int
poll_mode
;
ALSAVoiceOut
*
alsa
=
(
ALSAVoiceOut
*
)
hw
;
va_start
(
ap
,
cmd
);
poll_mode
=
va_arg
(
ap
,
int
);
va_end
(
ap
);
switch
(
cmd
)
{
case
VOICE_ENABLE
:
ldebug
(
"enabling voice
\n
"
);
if
(
poll_mode
&&
alsa_poll_out
(
hw
))
{
poll_mode
=
0
;
}
hw
->
poll_mode
=
poll_mode
;
return
alsa_voice_ctl
(
alsa
->
handle
,
"playback"
,
0
);
case
VOICE_DISABLE
:
...
...
@@ -772,6 +939,7 @@ static void alsa_fini_in (HWVoiceIn *hw)
qemu_free
(
alsa
->
pcm_buf
);
alsa
->
pcm_buf
=
NULL
;
}
alsa_fini_poll
(
&
alsa
->
pollhlp
);
}
static
int
alsa_run_in
(
HWVoiceIn
*
hw
)
...
...
@@ -909,15 +1077,30 @@ static int alsa_read (SWVoiceIn *sw, void *buf, int size)
static
int
alsa_ctl_in
(
HWVoiceIn
*
hw
,
int
cmd
,
...)
{
va_list
ap
;
int
poll_mode
;
ALSAVoiceIn
*
alsa
=
(
ALSAVoiceIn
*
)
hw
;
va_start
(
ap
,
cmd
);
poll_mode
=
va_arg
(
ap
,
int
);
va_end
(
ap
);
switch
(
cmd
)
{
case
VOICE_ENABLE
:
ldebug
(
"enabling voice
\n
"
);
if
(
poll_mode
&&
alsa_poll_in
(
hw
))
{
poll_mode
=
0
;
}
hw
->
poll_mode
=
poll_mode
;
return
alsa_voice_ctl
(
alsa
->
handle
,
"capture"
,
0
);
case
VOICE_DISABLE
:
ldebug
(
"disabling voice
\n
"
);
if
(
hw
->
poll_mode
)
{
hw
->
poll_mode
=
0
;
alsa_fini_poll
(
&
alsa
->
pollhlp
);
}
return
alsa_voice_ctl
(
alsa
->
handle
,
"capture"
,
1
);
}
...
...
@@ -1014,7 +1197,7 @@ static struct audio_pcm_ops alsa_pcm_ops = {
.
fini_in
=
alsa_fini_in
,
.
run_in
=
alsa_run_in
,
.
read
=
alsa_read
,
.
ctl_in
=
alsa_ctl_in
.
ctl_in
=
alsa_ctl_in
,
};
struct
audio_driver
alsa_audio_driver
=
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录