mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-11-03 09:01:52 -05:00
Code enhancements, added support for FM801 (untested)
This commit is contained in:
parent
e0ef729f41
commit
7e1f41be73
1 changed files with 170 additions and 26 deletions
|
|
@ -453,46 +453,130 @@ static int snd_pcm_surround_free(snd_pcm_surround_t *surr)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_surround_one_stream(snd_pcm_surround_t *surr,
|
||||||
|
snd_pcm_surround_type_t type ATTRIBUTE_UNUSED,
|
||||||
|
int card,
|
||||||
|
int dev, int subdev,
|
||||||
|
snd_pcm_stream_t stream, int mode)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if ((err = snd_pcm_hw_open(&surr->pcm[0], "Surround", card, dev,
|
||||||
|
subdev, stream, mode)) < 0)
|
||||||
|
return err;
|
||||||
|
surr->pcms++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int snd_pcm_surround_three_streams(snd_pcm_surround_t *surr,
|
static int snd_pcm_surround_three_streams(snd_pcm_surround_t *surr,
|
||||||
snd_pcm_surround_type_t type,
|
snd_pcm_surround_type_t type,
|
||||||
int card,
|
int card,
|
||||||
int dev0, int subdev0,
|
int dev0, int subdev0,
|
||||||
int dev1, int subdev1,
|
int dev1, int subdev1,
|
||||||
int dev2, int subdev2,
|
int dev2, int subdev2,
|
||||||
int mode)
|
snd_pcm_stream_t stream, int mode)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if ((err = snd_pcm_hw_open(&surr->pcm[0], "Surround L/R", card, dev0,
|
if ((err = snd_pcm_hw_open(&surr->pcm[0], "Surround L/R", card, dev0,
|
||||||
subdev0, SND_PCM_STREAM_PLAYBACK, mode)) < 0)
|
subdev0, stream, mode)) < 0)
|
||||||
return err;
|
return err;
|
||||||
surr->pcms++;
|
surr->pcms++;
|
||||||
if ((err = snd_pcm_hw_open(&surr->pcm[1], "Surround Rear L/R", card, dev1,
|
if ((err = snd_pcm_hw_open(&surr->pcm[1], "Surround Rear L/R", card, dev1,
|
||||||
subdev1, SND_PCM_STREAM_PLAYBACK, mode)) < 0)
|
subdev1, stream, mode)) < 0)
|
||||||
return err;
|
return err;
|
||||||
surr->pcms++;
|
surr->pcms++;
|
||||||
if (type == SND_PCM_SURROUND_51) {
|
if (type == SND_PCM_SURROUND_51) {
|
||||||
if ((err = snd_pcm_hw_open(&surr->pcm[2], "Surround Center/LFE", card, dev2,
|
if ((err = snd_pcm_hw_open(&surr->pcm[2], "Surround Center/LFE", card, dev2,
|
||||||
subdev2, SND_PCM_STREAM_PLAYBACK, mode)) < 0)
|
subdev2, stream, mode)) < 0)
|
||||||
return err;
|
return err;
|
||||||
surr->pcms++;
|
surr->pcms++;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int count_generic(snd_ctl_t *ctl ATTRIBUTE_UNUSED,
|
||||||
|
snd_ctl_card_info_t *info ATTRIBUTE_UNUSED,
|
||||||
|
snd_pcm_surround_type_t type ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int count_si7018(snd_ctl_t *ctl ATTRIBUTE_UNUSED,
|
||||||
|
snd_ctl_card_info_t *info ATTRIBUTE_UNUSED,
|
||||||
|
snd_pcm_surround_type_t type ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
/* this card supports multiopen also for DVD !!! */
|
||||||
|
return 32 / 2 / 3; /* 32 stereo channels / 2 (one helper voice) / 3 (count of streams) */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int open_si7018(snd_pcm_surround_t *surr,
|
||||||
|
snd_ctl_t *ctl ATTRIBUTE_UNUSED,
|
||||||
|
snd_ctl_card_info_t *info,
|
||||||
|
snd_pcm_surround_type_t type,
|
||||||
|
snd_pcm_stream_t stream, int mode)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if ((err = snd_pcm_surround_three_streams(surr, type,
|
||||||
|
snd_ctl_card_info_get_card(info),
|
||||||
|
0, -1, 0, -1, 0, -1,
|
||||||
|
stream, mode)) < 0)
|
||||||
|
return err;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int open_fm801(snd_pcm_surround_t *surr,
|
||||||
|
snd_ctl_t *ctl ATTRIBUTE_UNUSED,
|
||||||
|
snd_ctl_card_info_t *info,
|
||||||
|
snd_pcm_surround_type_t type,
|
||||||
|
snd_pcm_stream_t stream, int mode)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if ((err = snd_pcm_surround_one_stream(surr, type,
|
||||||
|
snd_ctl_card_info_get_card(info),
|
||||||
|
0, 0, stream, mode)) < 0)
|
||||||
|
return err;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SND_CARD_TYPE_NONE SNDRV_CARD_TYPE_SB_10 /* this card definitely doesn't support surround */
|
||||||
|
|
||||||
|
#define SURR_FLG_CAPTURE (1<<0)
|
||||||
|
#define SURR_FLG_NO_4CH (1<<1)
|
||||||
|
#define SURR_FLG_NO_6CH (1<<2)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
snd_card_type_t type;
|
||||||
|
unsigned int flags;
|
||||||
|
int (*scount)(snd_ctl_t *ctl, snd_ctl_card_info_t *info, snd_pcm_surround_type_t type);
|
||||||
|
int (*sopen)(snd_pcm_surround_t *surr,
|
||||||
|
snd_ctl_t *ctl, snd_ctl_card_info_t *info,
|
||||||
|
snd_pcm_surround_type_t type,
|
||||||
|
snd_pcm_stream_t stream,
|
||||||
|
int mode);
|
||||||
|
} surround_open_t;
|
||||||
|
|
||||||
|
static surround_open_t open_table[] = {
|
||||||
|
{ type: SND_CARD_TYPE_SI_7018, flags: 0, scount: count_si7018, sopen: open_si7018 },
|
||||||
|
{ type: SND_CARD_TYPE_FM801, flags: 0, scount: count_generic, sopen: open_fm801 },
|
||||||
|
{ type: SND_CARD_TYPE_NONE, flags: 0, scount: NULL, sopen: NULL }
|
||||||
|
};
|
||||||
|
|
||||||
int snd_pcm_surround_open(snd_pcm_t **pcmp, const char *name, int card, int dev,
|
int snd_pcm_surround_open(snd_pcm_t **pcmp, const char *name, int card, int dev,
|
||||||
snd_pcm_surround_type_t type,
|
snd_pcm_surround_type_t type,
|
||||||
snd_pcm_stream_t stream, int mode)
|
snd_pcm_stream_t stream, int mode)
|
||||||
{
|
{
|
||||||
snd_pcm_t *pcm;
|
snd_pcm_t *pcm = NULL;
|
||||||
snd_pcm_surround_t *surr;
|
snd_pcm_surround_t *surr;
|
||||||
snd_ctl_t *ctl;
|
snd_ctl_t *ctl = NULL;
|
||||||
snd_ctl_card_info_t *info;
|
snd_ctl_card_info_t *info;
|
||||||
|
snd_card_type_t ctype;
|
||||||
|
surround_open_t *po;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
assert(pcmp);
|
assert(pcmp);
|
||||||
if (stream == SND_PCM_STREAM_CAPTURE)
|
|
||||||
return -EINVAL; /* not supported at the time */
|
|
||||||
if (dev != 0)
|
if (dev != 0)
|
||||||
return -EINVAL; /* not supported at the time */
|
return -EINVAL; /* not supported at the time */
|
||||||
surr = calloc(1, sizeof(snd_pcm_surround_t));
|
surr = calloc(1, sizeof(snd_pcm_surround_t));
|
||||||
|
|
@ -514,29 +598,44 @@ int snd_pcm_surround_open(snd_pcm_t **pcmp, const char *name, int card, int dev,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
snd_ctl_card_info_alloca(&info);
|
snd_ctl_card_info_alloca(&info);
|
||||||
if ((err = snd_ctl_card_info(ctl, info)) < 0) {
|
if ((err = snd_ctl_card_info(ctl, info)) < 0)
|
||||||
snd_ctl_close(ctl);
|
goto __error;
|
||||||
snd_pcm_surround_free(surr);
|
ctype = snd_ctl_card_info_get_type(info);
|
||||||
return err;
|
for (po = open_table; po->type != SND_CARD_TYPE_NONE; po++) {
|
||||||
}
|
if (po->type == ctype) {
|
||||||
switch (snd_ctl_card_info_get_type(info)) {
|
if (stream == SND_PCM_STREAM_CAPTURE && !(po->flags & SURR_FLG_CAPTURE)) {
|
||||||
case SND_CARD_TYPE_SI_7018:
|
err = -ENODEV;
|
||||||
if ((err = snd_pcm_surround_three_streams(surr, type, card,
|
goto __error;
|
||||||
0, -1, 0, -1, 0, -1, mode)) < 0) {
|
}
|
||||||
snd_pcm_surround_free(surr);
|
switch (type) {
|
||||||
return err;
|
case SND_PCM_SURROUND_40:
|
||||||
|
if (po->flags & SURR_FLG_NO_4CH) {
|
||||||
|
err = -ENODEV;
|
||||||
|
goto __error;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SND_PCM_SURROUND_51:
|
||||||
|
if (po->flags & SURR_FLG_NO_6CH) {
|
||||||
|
err = -ENODEV;
|
||||||
|
goto __error;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((err = po->sopen(surr, ctl, info, type, stream, mode)) < 0)
|
||||||
|
goto __error;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
default:
|
if (po->type == SND_CARD_TYPE_NONE) {
|
||||||
snd_ctl_close(ctl);
|
err = -ENODEV;
|
||||||
snd_pcm_surround_free(surr);
|
goto __error;
|
||||||
return -ENODEV;
|
|
||||||
}
|
}
|
||||||
snd_ctl_close(ctl);
|
snd_ctl_close(ctl);
|
||||||
|
ctl = NULL;
|
||||||
pcm = calloc(1, sizeof(snd_pcm_t));
|
pcm = calloc(1, sizeof(snd_pcm_t));
|
||||||
if (!pcm) {
|
if (!pcm) {
|
||||||
snd_pcm_surround_free(surr);
|
err = -ENOMEM;
|
||||||
return -ENOMEM;
|
goto __error;
|
||||||
}
|
}
|
||||||
if (name)
|
if (name)
|
||||||
pcm->name = strdup(name);
|
pcm->name = strdup(name);
|
||||||
|
|
@ -555,6 +654,12 @@ int snd_pcm_surround_open(snd_pcm_t **pcmp, const char *name, int card, int dev,
|
||||||
*pcmp = pcm;
|
*pcmp = pcm;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
__error:
|
||||||
|
if (ctl)
|
||||||
|
snd_ctl_close(ctl);
|
||||||
|
snd_pcm_surround_free(surr);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _snd_pcm_surround_open(snd_pcm_t **pcmp, const char *name, snd_config_t *conf,
|
int _snd_pcm_surround_open(snd_pcm_t **pcmp, const char *name, snd_config_t *conf,
|
||||||
|
|
@ -623,3 +728,42 @@ int _snd_pcm_surround_open(snd_pcm_t **pcmp, const char *name, snd_config_t *con
|
||||||
}
|
}
|
||||||
return snd_pcm_surround_open(pcmp, name, card, device, type, stream, mode);
|
return snd_pcm_surround_open(pcmp, name, card, device, type, stream, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int snd_pcm_surround_next_device(snd_ctl_t *ctl, snd_pcm_surround_type_t type, int *device)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
snd_ctl_card_info_t *info;
|
||||||
|
snd_card_type_t ctype;
|
||||||
|
surround_open_t *po;
|
||||||
|
|
||||||
|
assert(device);
|
||||||
|
snd_ctl_card_info_alloca(&info);
|
||||||
|
if ((err = snd_ctl_card_info(ctl, info)) < 0)
|
||||||
|
return err;
|
||||||
|
ctype = snd_ctl_card_info_get_type(info);
|
||||||
|
for (po = open_table; po->type != SND_CARD_TYPE_NONE; po++) {
|
||||||
|
if (po->type == ctype) {
|
||||||
|
switch (type) {
|
||||||
|
case SND_PCM_SURROUND_40:
|
||||||
|
if (po->flags & SURR_FLG_NO_4CH)
|
||||||
|
return -ENODEV;
|
||||||
|
break;
|
||||||
|
case SND_PCM_SURROUND_51:
|
||||||
|
if (po->flags & SURR_FLG_NO_6CH)
|
||||||
|
return -ENODEV;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((err = po->scount(ctl, info, type)) < 0)
|
||||||
|
return err;
|
||||||
|
if (err == 0)
|
||||||
|
return -ENODEV;
|
||||||
|
if (*device == 0)
|
||||||
|
*device = 0;
|
||||||
|
(*device)++;
|
||||||
|
if (*device >= err)
|
||||||
|
*device = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue