2003-06-22 18:09:03 +00:00
|
|
|
/**
|
2003-06-22 19:02:19 +00:00
|
|
|
* \file ordinary_mixer/ordinary_mixer.c
|
|
|
|
|
* \ingroup Mixer_ordinary
|
|
|
|
|
* \brief Ordinary mixer interface
|
2003-06-22 18:09:03 +00:00
|
|
|
* \author Jaroslav Kysela <perex@suse.cz>
|
|
|
|
|
* \date 2003
|
|
|
|
|
*
|
2003-06-22 19:02:19 +00:00
|
|
|
* Ordinary mixer interface is a high level abtraction for soundcard's
|
2003-06-22 18:09:03 +00:00
|
|
|
* mixing.
|
|
|
|
|
*
|
2003-06-22 19:02:19 +00:00
|
|
|
* See the \ref Mixer_ordinary page for more details.
|
2003-06-22 18:09:03 +00:00
|
|
|
*/
|
|
|
|
|
/*
|
2003-06-22 19:02:19 +00:00
|
|
|
* Ordinary Mixer Interface - main file
|
2003-06-22 18:09:03 +00:00
|
|
|
* Copyright (c) 2003 by Jaroslav Kysela <perex@suse.cz>
|
|
|
|
|
*
|
|
|
|
|
* This library is free software; you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU Lesser General Public License as
|
|
|
|
|
* published by the Free Software Foundation; either version 2.1 of
|
|
|
|
|
* the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU Lesser General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2003-06-22 19:02:19 +00:00
|
|
|
/*! \page Mixer_ordinary Ordinary mixer interface
|
2003-06-22 18:09:03 +00:00
|
|
|
|
|
|
|
|
<P>Write something here</P>
|
|
|
|
|
|
2003-06-22 19:02:19 +00:00
|
|
|
\section Mixer_ordinary_overview
|
2003-06-22 18:09:03 +00:00
|
|
|
|
|
|
|
|
Write something here
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
/**
|
2003-06-22 19:02:19 +00:00
|
|
|
* \example ../test/ordinary_mixer.c
|
|
|
|
|
* \anchor example_ordinary_mixer
|
2003-06-22 18:09:03 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <malloc.h>
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
#include <signal.h>
|
|
|
|
|
#include <dlfcn.h>
|
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
|
#include <sys/poll.h>
|
|
|
|
|
#include <sys/shm.h>
|
|
|
|
|
#include <sys/mman.h>
|
|
|
|
|
#include <limits.h>
|
|
|
|
|
#include "local.h"
|
2003-09-03 19:25:08 +00:00
|
|
|
#include "alisp.h"
|
2003-06-22 19:02:19 +00:00
|
|
|
#include "mixer_ordinary.h"
|
2003-06-22 18:09:03 +00:00
|
|
|
|
2003-06-22 19:02:19 +00:00
|
|
|
struct sndo_mixer {
|
2003-09-03 19:25:08 +00:00
|
|
|
struct alisp_cfg *cfg;
|
|
|
|
|
struct alisp_instance *alisp;
|
|
|
|
|
int hctl_count;
|
|
|
|
|
snd_hctl_t **hctl;
|
|
|
|
|
int _free_cfg;
|
2003-06-22 18:09:03 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
2003-06-22 19:02:19 +00:00
|
|
|
* \brief Opens a ordinary mixer instance
|
|
|
|
|
* \param pmixer Returned ordinary mixer handle
|
2003-09-09 19:24:35 +00:00
|
|
|
* \param playback_pcm handle of the playback PCM
|
|
|
|
|
* \param capture_pcm handle of the capture PCM
|
2003-06-22 18:09:03 +00:00
|
|
|
* \param lconf Local configuration (might be NULL - use global configuration)
|
|
|
|
|
* \return 0 on success otherwise a negative error code
|
|
|
|
|
*/
|
2003-06-22 19:02:19 +00:00
|
|
|
int sndo_mixer_open(sndo_mixer_t **pmixer,
|
2003-09-09 19:24:35 +00:00
|
|
|
snd_pcm_t *playback_pcm,
|
|
|
|
|
snd_pcm_t *capture_pcm,
|
2003-09-03 19:25:08 +00:00
|
|
|
struct alisp_cfg *lconf)
|
2003-06-22 18:09:03 +00:00
|
|
|
{
|
2003-09-03 19:25:08 +00:00
|
|
|
struct alisp_cfg *cfg = lconf;
|
|
|
|
|
struct alisp_instance *alisp;
|
|
|
|
|
struct alisp_seq_iterator *iterator;
|
|
|
|
|
sndo_mixer_t *mixer;
|
|
|
|
|
int err, count;
|
|
|
|
|
long val;
|
|
|
|
|
|
2003-06-22 18:09:03 +00:00
|
|
|
*pmixer = NULL;
|
2003-09-03 19:25:08 +00:00
|
|
|
if (cfg == NULL) {
|
|
|
|
|
char *file;
|
|
|
|
|
snd_input_t *input;
|
|
|
|
|
file = getenv("ALSA_ORDINARY_MIXER");
|
|
|
|
|
if (!file)
|
|
|
|
|
file = DATADIR "/alsa/sndo-mixer.alisp";
|
|
|
|
|
if ((err = snd_input_stdio_open(&input, file, "r")) < 0) {
|
|
|
|
|
SNDERR("unable to open alisp file '%s'", file);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
cfg = alsa_lisp_default_cfg(input);
|
|
|
|
|
if (cfg == NULL)
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
}
|
|
|
|
|
err = alsa_lisp(cfg, &alisp);
|
|
|
|
|
if (err < 0)
|
|
|
|
|
goto __error;
|
2003-09-09 19:24:35 +00:00
|
|
|
err = alsa_lisp_function(alisp, &iterator, "sndo_mixer_open", "%ppcm%ppcm", playback_pcm, capture_pcm);
|
2003-09-03 19:25:08 +00:00
|
|
|
if (err < 0) {
|
|
|
|
|
alsa_lisp_free(alisp);
|
|
|
|
|
goto __error;
|
|
|
|
|
}
|
|
|
|
|
err = alsa_lisp_seq_integer(iterator, &val);
|
|
|
|
|
if (err == 0 && val < 0)
|
|
|
|
|
err = val;
|
|
|
|
|
if (err < 0) {
|
|
|
|
|
alsa_lisp_free(alisp);
|
|
|
|
|
goto __error;
|
|
|
|
|
}
|
|
|
|
|
count = 0;
|
|
|
|
|
if (alsa_lisp_seq_first(alisp, "hctls", &iterator) == 0) {
|
|
|
|
|
count = alsa_lisp_seq_count(iterator);
|
|
|
|
|
if (count < 0)
|
|
|
|
|
count = 0;
|
|
|
|
|
}
|
|
|
|
|
mixer = malloc(sizeof(sndo_mixer_t) + count * sizeof(snd_hctl_t *));
|
|
|
|
|
if (mixer == NULL) {
|
|
|
|
|
alsa_lisp_free(alisp);
|
|
|
|
|
err = -ENOMEM;
|
|
|
|
|
goto __error;
|
|
|
|
|
}
|
|
|
|
|
memset(mixer, 0, sizeof(sndo_mixer_t));
|
|
|
|
|
if (count > 0) {
|
|
|
|
|
mixer->hctl = (snd_hctl_t **)(mixer + 1);
|
|
|
|
|
do {
|
|
|
|
|
if (alsa_lisp_seq_pointer(iterator, "hctl", (void **)&mixer->hctl[mixer->hctl_count++]))
|
|
|
|
|
break;
|
|
|
|
|
} while (mixer->hctl_count < count && alsa_lisp_seq_next(&iterator) == 0);
|
|
|
|
|
if (mixer->hctl_count < count) {
|
|
|
|
|
mixer->hctl = NULL;
|
|
|
|
|
mixer->hctl_count = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
mixer->alisp = alisp;
|
|
|
|
|
mixer->cfg = cfg;
|
|
|
|
|
mixer->_free_cfg = cfg != lconf;
|
|
|
|
|
*pmixer = mixer;
|
|
|
|
|
return 0;
|
|
|
|
|
__error:
|
|
|
|
|
if (cfg != lconf)
|
|
|
|
|
alsa_lisp_default_cfg_free(cfg);
|
|
|
|
|
return err;
|
2003-06-22 18:09:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2003-06-22 19:02:19 +00:00
|
|
|
* \brief Closes a ordinary mixer instance
|
|
|
|
|
* \param mixer Ordinary mixer handle to close
|
2003-06-22 18:09:03 +00:00
|
|
|
* \return 0 on success otherwise a negative error code
|
|
|
|
|
*/
|
2003-06-22 19:02:19 +00:00
|
|
|
int sndo_mixer_close(sndo_mixer_t *mixer)
|
2003-06-22 18:09:03 +00:00
|
|
|
{
|
2003-09-03 19:25:08 +00:00
|
|
|
int res;
|
|
|
|
|
|
2003-09-09 19:24:35 +00:00
|
|
|
res = alsa_lisp_function(mixer->alisp, NULL, "sndo_mixer_close", "n");
|
2003-09-03 19:25:08 +00:00
|
|
|
alsa_lisp_free(mixer->alisp);
|
|
|
|
|
if (mixer->_free_cfg)
|
|
|
|
|
alsa_lisp_default_cfg_free(mixer->cfg);
|
|
|
|
|
free(mixer);
|
|
|
|
|
return res;
|
2003-06-22 18:09:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2003-06-22 19:02:19 +00:00
|
|
|
* \brief get count of poll descriptors for ordinary mixer handle
|
|
|
|
|
* \param mixer ordinary mixer handle
|
2003-06-22 18:09:03 +00:00
|
|
|
* \return count of poll descriptors
|
|
|
|
|
*/
|
2003-06-22 19:02:19 +00:00
|
|
|
int sndo_mixer_poll_descriptors_count(sndo_mixer_t *mixer)
|
2003-06-22 18:09:03 +00:00
|
|
|
{
|
2003-09-03 19:25:08 +00:00
|
|
|
int idx, err, res = -EIO;
|
|
|
|
|
|
|
|
|
|
if (mixer->hctl_count > 0) {
|
|
|
|
|
for (idx = 0; idx < mixer->hctl_count; idx++) {
|
|
|
|
|
err = snd_hctl_poll_descriptors_count(mixer->hctl[idx]);
|
|
|
|
|
if (err < 0)
|
|
|
|
|
return err;
|
|
|
|
|
res += err;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
struct alisp_seq_iterator *result;
|
|
|
|
|
long val;
|
2003-09-09 19:24:35 +00:00
|
|
|
err = alsa_lisp_function(mixer->alisp, &result, "sndo_mixer_poll_descriptors_count", "n");
|
2003-09-03 19:25:08 +00:00
|
|
|
if (err < 0)
|
|
|
|
|
return err;
|
|
|
|
|
err = alsa_lisp_seq_integer(result, &val);
|
|
|
|
|
return err < 0 ? err : val;
|
|
|
|
|
}
|
|
|
|
|
return res;
|
2003-06-22 18:09:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief get poll descriptors
|
2003-06-22 19:02:19 +00:00
|
|
|
* \param mixer ordinary mixer handle
|
2003-06-22 18:09:03 +00:00
|
|
|
* \param pfds array of poll descriptors
|
|
|
|
|
* \param space space in the poll descriptor array
|
|
|
|
|
* \return count of filled descriptors
|
|
|
|
|
*/
|
2003-06-22 19:02:19 +00:00
|
|
|
int sndo_mixer_poll_descriptors(sndo_mixer_t *mixer, struct pollfd *pfds, unsigned int space)
|
2003-06-22 18:09:03 +00:00
|
|
|
{
|
2003-09-03 19:25:08 +00:00
|
|
|
//return snd_mixer_poll_descriptors(mixer->mixer, pfds, space);
|
|
|
|
|
return -ENODEV;
|
2003-06-22 18:09:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief get returned events from poll descriptors
|
2003-06-22 19:02:19 +00:00
|
|
|
* \param mixer ordinary mixer handle
|
2003-06-22 18:09:03 +00:00
|
|
|
* \param pfds array of poll descriptors
|
|
|
|
|
* \param nfds count of poll descriptors
|
|
|
|
|
* \param revents returned events
|
|
|
|
|
* \return zero if success, otherwise a negative error code
|
|
|
|
|
*/
|
2003-06-22 19:02:19 +00:00
|
|
|
int sndo_mixer_poll_descriptors_revents(sndo_mixer_t *mixer, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
|
2003-06-22 18:09:03 +00:00
|
|
|
{
|
2003-09-03 19:25:08 +00:00
|
|
|
//return snd_mixer_poll_descriptors_revents(mixer->mixer, pfds, nfds, revents);
|
|
|
|
|
return -ENODEV;
|
2003-06-22 18:09:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2003-06-22 19:02:19 +00:00
|
|
|
* \brief get ordinary mixer io control value
|
|
|
|
|
* \param mixer ordinary mixer handle
|
2003-06-22 18:09:03 +00:00
|
|
|
* \param type io type
|
|
|
|
|
* \param val returned value
|
|
|
|
|
* \return zero if success, otherwise a negative error code
|
|
|
|
|
*/
|
2003-06-22 19:02:19 +00:00
|
|
|
int sndo_mixer_io_get(sndo_mixer_t *mixer, enum sndo_mixer_io_type type, int *val)
|
2003-06-22 18:09:03 +00:00
|
|
|
{
|
|
|
|
|
return -ENODEV;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2003-06-22 19:02:19 +00:00
|
|
|
* \brief set ordinary mixer io control value
|
|
|
|
|
* \param mixer ordinary mixer handle
|
2003-06-22 18:09:03 +00:00
|
|
|
* \param type io type
|
|
|
|
|
* \param val desired value
|
|
|
|
|
* \return zero if success, otherwise a negative error code
|
|
|
|
|
*/
|
2003-06-22 19:02:19 +00:00
|
|
|
int sndo_mixer_io_set(sndo_mixer_t *mixer, enum sndo_mixer_io_type type, int val)
|
2003-06-22 18:09:03 +00:00
|
|
|
{
|
|
|
|
|
return -ENODEV;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2003-06-22 19:02:19 +00:00
|
|
|
* \brief get ordinary mixer io control change notification
|
|
|
|
|
* \param mixer ordinary mixer handle
|
2003-06-22 18:09:03 +00:00
|
|
|
* \param changed list of changed io types
|
|
|
|
|
* \param changed_array_size size of list of changed io types
|
|
|
|
|
* \return zero if success, otherwise a negative error code
|
|
|
|
|
*/
|
2003-06-22 19:02:19 +00:00
|
|
|
int sndo_mixer_io_change(sndo_mixer_t *mixer, enum sndo_mixer_io_type *changed, int changed_array_size)
|
2003-06-22 18:09:03 +00:00
|
|
|
{
|
|
|
|
|
return -ENODEV;
|
|
|
|
|
}
|