mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-12-16 08:56:42 -05:00
Add detailed documentation for external control plugin SDK
Added the detailed documentation for external control plugin SDK.
This commit is contained in:
parent
555b870760
commit
3656a66397
4 changed files with 300 additions and 10 deletions
|
|
@ -26,6 +26,7 @@ INPUT = index.doxygen \
|
||||||
../include/pcm_external.h \
|
../include/pcm_external.h \
|
||||||
../include/pcm_extplug.h \
|
../include/pcm_extplug.h \
|
||||||
../include/pcm_ioplug.h \
|
../include/pcm_ioplug.h \
|
||||||
|
../include/control_external.h \
|
||||||
../include/conv.h \
|
../include/conv.h \
|
||||||
../include/instr.h \
|
../include/instr.h \
|
||||||
../src/error.c \
|
../src/error.c \
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ may be placed in the library code instead of the kernel driver.</P>
|
||||||
<LI>Page \ref pcm explains the design of the PCM (digital audio) API.
|
<LI>Page \ref pcm explains the design of the PCM (digital audio) API.
|
||||||
<LI>Page \ref pcm_plugins explains the design of PCM (digital audio) plugins.
|
<LI>Page \ref pcm_plugins explains the design of PCM (digital audio) plugins.
|
||||||
<LI>Page \ref pcm_external_plugins explains the external PCM plugin SDK.
|
<LI>Page \ref pcm_external_plugins explains the external PCM plugin SDK.
|
||||||
|
<LI>Page \ref ctl_external_plugins explains the external control plugin SDK.
|
||||||
<LI>Page \ref rawmidi explains the design of the RawMidi API.
|
<LI>Page \ref rawmidi explains the design of the RawMidi API.
|
||||||
<LI>Page \ref timer explains the design of the Timer API.
|
<LI>Page \ref timer explains the design of the Timer API.
|
||||||
<LI>Page \ref seq explains the design of the Sequencer API.
|
<LI>Page \ref seq explains the design of the Sequencer API.
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \defgroup CtlPlugin_SDK External control plugin SDK
|
* \defgroup CtlPlugin_SDK External Control Plugin SDK
|
||||||
* \{
|
* \{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
@ -129,47 +129,128 @@ struct snd_ctl_ext {
|
||||||
|
|
||||||
/** Callback table of ext */
|
/** Callback table of ext */
|
||||||
struct snd_ctl_ext_callback {
|
struct snd_ctl_ext_callback {
|
||||||
void (*close)(snd_ctl_ext_t *ext); /* opt */
|
/**
|
||||||
void (*subscribe_events)(snd_ctl_ext_t *ext, int subscribe); /* opt */
|
* close the control handle; optional
|
||||||
int (*elem_count)(snd_ctl_ext_t *ext); /* req */
|
*/
|
||||||
int (*elem_list)(snd_ctl_ext_t *ext, unsigned int offset, snd_ctl_elem_id_t *id); /* req */
|
void (*close)(snd_ctl_ext_t *ext);
|
||||||
snd_ctl_ext_key_t (*find_elem)(snd_ctl_ext_t *ext, const snd_ctl_elem_id_t *id); /* req */
|
/**
|
||||||
void (*free_key)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key); /* opt */
|
* return the total number of elements; required
|
||||||
|
*/
|
||||||
|
int (*elem_count)(snd_ctl_ext_t *ext);
|
||||||
|
/**
|
||||||
|
* return the element id of the given offset (array index); required
|
||||||
|
*/
|
||||||
|
int (*elem_list)(snd_ctl_ext_t *ext, unsigned int offset, snd_ctl_elem_id_t *id);
|
||||||
|
/**
|
||||||
|
* convert the element id to a search key; required
|
||||||
|
*/
|
||||||
|
snd_ctl_ext_key_t (*find_elem)(snd_ctl_ext_t *ext, const snd_ctl_elem_id_t *id);
|
||||||
|
/**
|
||||||
|
* the destructor of the key; optional
|
||||||
|
*/
|
||||||
|
void (*free_key)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key);
|
||||||
|
/**
|
||||||
|
* get the attribute of the element; required
|
||||||
|
*/
|
||||||
int (*get_attribute)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key,
|
int (*get_attribute)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key,
|
||||||
int *type, unsigned int *acc, unsigned int *count); /* req */
|
int *type, unsigned int *acc, unsigned int *count);
|
||||||
|
/**
|
||||||
|
* get the element information of integer type
|
||||||
|
*/
|
||||||
int (*get_integer_info)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key,
|
int (*get_integer_info)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key,
|
||||||
long *imin, long *imax, long *istep);
|
long *imin, long *imax, long *istep);
|
||||||
|
/**
|
||||||
|
* get the element information of integer64 type
|
||||||
|
*/
|
||||||
int (*get_integer64_info)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key,
|
int (*get_integer64_info)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key,
|
||||||
int64_t *imin, int64_t *imax, int64_t *istep);
|
int64_t *imin, int64_t *imax, int64_t *istep);
|
||||||
|
/**
|
||||||
|
* get the element information of enumerated type
|
||||||
|
*/
|
||||||
int (*get_enumerated_info)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, unsigned int *items);
|
int (*get_enumerated_info)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, unsigned int *items);
|
||||||
|
/**
|
||||||
|
* get the name of the enumerated item
|
||||||
|
*/
|
||||||
int (*get_enumerated_name)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, unsigned int item,
|
int (*get_enumerated_name)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, unsigned int item,
|
||||||
char *name, size_t name_max_len);
|
char *name, size_t name_max_len);
|
||||||
|
/**
|
||||||
|
* read the current values of integer type
|
||||||
|
*/
|
||||||
int (*read_integer)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, long *value);
|
int (*read_integer)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, long *value);
|
||||||
|
/**
|
||||||
|
* read the current values of integer64 type
|
||||||
|
*/
|
||||||
int (*read_integer64)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, int64_t *value);
|
int (*read_integer64)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, int64_t *value);
|
||||||
|
/**
|
||||||
|
* read the current values of enumerated type
|
||||||
|
*/
|
||||||
int (*read_enumerated)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, unsigned int *items);
|
int (*read_enumerated)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, unsigned int *items);
|
||||||
|
/**
|
||||||
|
* read the current values of bytes type
|
||||||
|
*/
|
||||||
int (*read_bytes)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, unsigned char *data,
|
int (*read_bytes)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, unsigned char *data,
|
||||||
size_t max_bytes);
|
size_t max_bytes);
|
||||||
|
/**
|
||||||
|
* read the current values of iec958 type
|
||||||
|
*/
|
||||||
int (*read_iec958)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, snd_aes_iec958_t *iec958);
|
int (*read_iec958)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, snd_aes_iec958_t *iec958);
|
||||||
|
/**
|
||||||
|
* update the current values of integer type with the given values
|
||||||
|
*/
|
||||||
int (*write_integer)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, long *value);
|
int (*write_integer)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, long *value);
|
||||||
|
/**
|
||||||
|
* update the current values of integer64 type with the given values
|
||||||
|
*/
|
||||||
int (*write_integer64)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, int64_t *value);
|
int (*write_integer64)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, int64_t *value);
|
||||||
|
/**
|
||||||
|
* update the current values of enumerated type with the given values
|
||||||
|
*/
|
||||||
int (*write_enumerated)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, unsigned int *items);
|
int (*write_enumerated)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, unsigned int *items);
|
||||||
|
/**
|
||||||
|
* update the current values of bytes type with the given values
|
||||||
|
*/
|
||||||
int (*write_bytes)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, unsigned char *data,
|
int (*write_bytes)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, unsigned char *data,
|
||||||
size_t max_bytes);
|
size_t max_bytes);
|
||||||
|
/**
|
||||||
|
* update the current values of iec958 type with the given values
|
||||||
|
*/
|
||||||
int (*write_iec958)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, snd_aes_iec958_t *iec958);
|
int (*write_iec958)(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, snd_aes_iec958_t *iec958);
|
||||||
|
/**
|
||||||
|
* subscribe/unsubscribe the event notification; optional
|
||||||
|
*/
|
||||||
|
void (*subscribe_events)(snd_ctl_ext_t *ext, int subscribe);
|
||||||
|
/**
|
||||||
|
* read a pending notification event; optional
|
||||||
|
*/
|
||||||
int (*read_event)(snd_ctl_ext_t *ext, snd_ctl_elem_id_t *id, unsigned int *event_mask);
|
int (*read_event)(snd_ctl_ext_t *ext, snd_ctl_elem_id_t *id, unsigned int *event_mask);
|
||||||
|
/**
|
||||||
|
* return the number of poll descriptors; optional
|
||||||
|
*/
|
||||||
int (*poll_descriptors_count)(snd_ctl_ext_t *ext);
|
int (*poll_descriptors_count)(snd_ctl_ext_t *ext);
|
||||||
|
/**
|
||||||
|
* fill the poll descriptors; optional
|
||||||
|
*/
|
||||||
int (*poll_descriptors)(snd_ctl_ext_t *ext, struct pollfd *pfds, unsigned int space);
|
int (*poll_descriptors)(snd_ctl_ext_t *ext, struct pollfd *pfds, unsigned int space);
|
||||||
|
/**
|
||||||
|
* mangle the revents of poll descriptors
|
||||||
|
*/
|
||||||
int (*poll_revents)(snd_ctl_ext_t *ext, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);
|
int (*poll_revents)(snd_ctl_ext_t *ext, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);
|
||||||
};
|
};
|
||||||
|
|
||||||
enum snd_ctl_ext_access_t {
|
/**
|
||||||
|
* The access type bits stored in get_attribute callback
|
||||||
|
*/
|
||||||
|
typedef enum snd_ctl_ext_access {
|
||||||
SND_CTL_EXT_ACCESS_READ = (1<<0),
|
SND_CTL_EXT_ACCESS_READ = (1<<0),
|
||||||
SND_CTL_EXT_ACCESS_WRITE = (1<<1),
|
SND_CTL_EXT_ACCESS_WRITE = (1<<1),
|
||||||
SND_CTL_EXT_ACCESS_READWRITE = (3<<0),
|
SND_CTL_EXT_ACCESS_READWRITE = (3<<0),
|
||||||
SND_CTL_EXT_ACCESS_VOLATILE = (1<<2),
|
SND_CTL_EXT_ACCESS_VOLATILE = (1<<2),
|
||||||
SND_CTL_EXT_ACCESS_INACTIVE = (1<<8),
|
SND_CTL_EXT_ACCESS_INACTIVE = (1<<8),
|
||||||
};
|
} snd_ctl_ext_access_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* find_elem callback returns this if no matching control element is found
|
||||||
|
*/
|
||||||
#define SND_CTL_EXT_KEY_NOT_FOUND (snd_ctl_ext_key_t)(-1)
|
#define SND_CTL_EXT_KEY_NOT_FOUND (snd_ctl_ext_key_t)(-1)
|
||||||
|
|
||||||
int snd_ctl_ext_create(snd_ctl_ext_t *ext, const char *name, int mode);
|
int snd_ctl_ext_create(snd_ctl_ext_t *ext, const char *name, int mode);
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,10 @@
|
||||||
|
/**
|
||||||
|
* \file control/control_ext.c
|
||||||
|
* \ingroup CtlPlugin_SDK
|
||||||
|
* \brief External Control Plugin SDK
|
||||||
|
* \author Takashi Iwai <tiwai@suse.de>
|
||||||
|
* \date 2005
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* Control Interface - External Control Plugin SDK
|
* Control Interface - External Control Plugin SDK
|
||||||
*
|
*
|
||||||
|
|
@ -413,6 +420,206 @@ static snd_ctl_ops_t snd_ctl_ext_ops = {
|
||||||
.poll_revents = snd_ctl_ext_poll_revents,
|
.poll_revents = snd_ctl_ext_poll_revents,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Exported functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \page ctl_external_plugins External Control Plugin SDK
|
||||||
|
|
||||||
|
\section ctl_externals External Control Plugins
|
||||||
|
|
||||||
|
The external plugins are implemented in a shared object file located
|
||||||
|
at /usr/lib/alsa-lib (the exact location depends on the build option
|
||||||
|
and asoundrc configuration). It has to be the file like
|
||||||
|
libasound_module_ctl_MYPLUGIN.so, where MYPLUGIN corresponds to your
|
||||||
|
own plugin name.
|
||||||
|
|
||||||
|
The entry point of the plugin is defined via
|
||||||
|
#SND_CTL_PLUGIN_DEFINE_FUNC() macro. This macro defines the function
|
||||||
|
with a proper name to be referred from alsa-lib. The function takes
|
||||||
|
the following 5 arguments:
|
||||||
|
\code
|
||||||
|
int (snd_ctl_t **phandle, const char *name, snd_config_t *root,
|
||||||
|
snd_config_t *conf, int mode)
|
||||||
|
\endcode
|
||||||
|
The first argument, phandle, is the pointer to store the resultant control
|
||||||
|
handle. The arguments name, root and mode are the parameters
|
||||||
|
to be passed to the plugin constructor. The conf is the configuration
|
||||||
|
tree for the plugin. The arguments above are defined in the macro
|
||||||
|
itself, so don't use variables with the same names to shadow
|
||||||
|
parameters.
|
||||||
|
|
||||||
|
After parsing the configuration parameters in the given conf tree,
|
||||||
|
usually you will call the external plugin API function
|
||||||
|
#snd_ctl_ext_create().
|
||||||
|
The control handle must be filled *phandle in return.
|
||||||
|
Then this function must return either a value 0 when succeeded, or a
|
||||||
|
negative value as the error code.
|
||||||
|
|
||||||
|
Finally, add #SND_CTL_PLUGIN_SYMBOL() with the name of your
|
||||||
|
plugin as the argument at the end. This defines the proper versioned
|
||||||
|
symbol as the reference.
|
||||||
|
|
||||||
|
The typical code would look like below:
|
||||||
|
\code
|
||||||
|
struct myctl_info {
|
||||||
|
snd_ctl_ext_t ext;
|
||||||
|
int my_own_data;
|
||||||
|
...
|
||||||
|
};
|
||||||
|
|
||||||
|
SND_CTL_PLUGIN_DEFINE_FUNC(myctl)
|
||||||
|
{
|
||||||
|
snd_config_iterator_t i, next;
|
||||||
|
struct myctl_info *myctl;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
snd_config_for_each(i, next, conf) {
|
||||||
|
snd_config_t *n = snd_config_iterator_entry(i);
|
||||||
|
const char *id;
|
||||||
|
if (snd_config_get_id(n, &id) < 0)
|
||||||
|
continue;
|
||||||
|
if (strcmp(id, "comment") == 0 || strcmp(id, "type") == 0)
|
||||||
|
continue;
|
||||||
|
if (strcmp(id, "my_own_parameter") == 0) {
|
||||||
|
....
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
SNDERR("Unknown field %s", id);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
myctl = calloc(1, sizeof(*myctl));
|
||||||
|
if (myctl == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
myctl->ext.version = SND_CTL_EXT_VERSION;
|
||||||
|
myctl->ext.card_idx = 0;
|
||||||
|
strcpy(myctl->ext.id, "Myctl");
|
||||||
|
strcpy(myctl->ext.name, "My Control");
|
||||||
|
strcpy(myctl->ext.longname, "My External Control for Foobar");
|
||||||
|
strcpy(myctl->ext.mixername, "My Control");
|
||||||
|
myctl->ext.callback = &my_own_callback;
|
||||||
|
myctl->ext.private_data = myctl;
|
||||||
|
....
|
||||||
|
|
||||||
|
err = snd_pcm_extplug_create(&myctl->ext, name, mode);
|
||||||
|
if (err < 0) {
|
||||||
|
myctl_free(myctl);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
*phandle = myctl->ext.handle;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SND_CTL_PLUGIN_SYMBOL(myctl);
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
Read the codes in alsa-plugins package for the real examples.
|
||||||
|
|
||||||
|
|
||||||
|
\section ctl_ext_impl Implementation of External Control Plugins
|
||||||
|
|
||||||
|
The following fields have to be filled in external control record before calling
|
||||||
|
#snd_ctl_ext_create() : version, card_idx, id, name, longname, mixername, poll_fd and callback.
|
||||||
|
Otherfields are optional and should be initialized with zero.
|
||||||
|
|
||||||
|
The constant #SND_CTL_EXT_VERSION must be passed to the version
|
||||||
|
field for the version check in alsa-lib. The card_idx field specifies the card
|
||||||
|
index of this control. [FIXME: solve confliction of card index in alsa-lib?]
|
||||||
|
|
||||||
|
The id, name, longname and mixername fields are the strings shown in the card_info
|
||||||
|
inqurirys. They are the char arrays, so you have to <i>copy</i> strings to these
|
||||||
|
fields.
|
||||||
|
|
||||||
|
The callback field contains the table of callback functions for this plugin (defined as
|
||||||
|
#snd_ctl_ext_callback_t).
|
||||||
|
The poll_fd can be used to specify the poll file descriptor for this control.
|
||||||
|
Set -1 if not available. Alternatively, you can define poll_descriptors_count and
|
||||||
|
poll_descriptors callbacks in the callback table for handling the poll descriptor(s)
|
||||||
|
dynamically after the creation of plugin instance.
|
||||||
|
|
||||||
|
The driver can set an arbitrary value (pointer) to private_data
|
||||||
|
field to refer its own data in the callbacks.
|
||||||
|
|
||||||
|
The rest fields are filled by #snd_ctl_ext_create(). The handle field
|
||||||
|
is the resultant PCM handle. The others are the current status of the
|
||||||
|
PCM.
|
||||||
|
|
||||||
|
\section ctl_ext_impl Callback Functions of External Control Plugins
|
||||||
|
|
||||||
|
The callback functions in #snd_ctl_ext_callback_t define the real
|
||||||
|
behavior of the driver. There are many callbacks but many of them are optional.
|
||||||
|
|
||||||
|
The close callback is called when the PCM is closed. If the plugin
|
||||||
|
allocates private resources, this is the place to release them
|
||||||
|
again. This callback is optional.
|
||||||
|
|
||||||
|
The elem_count and elem_list callbacks are mandatory. The elem_count returns the
|
||||||
|
total number of control elements. The elem_list returns the control element ID
|
||||||
|
of the corresponding element offset (the offset is from 0 to elem_count - 1).
|
||||||
|
The id field is initialized to all zero in prior to elem_list callback. The callback
|
||||||
|
has to fill the necessary field (typically iface, name and index) in return via the
|
||||||
|
standard control API functions like #snd_ctl_elem_id_set_ifarce,
|
||||||
|
#snd_ctl_elem_id_set_name and #snd_ctl_elem_id_set_index, etc. The callbacks should
|
||||||
|
return 0 if successful, or a negative error code.
|
||||||
|
|
||||||
|
The find_elem callback is used to convert the given control element ID to the
|
||||||
|
certain key value for the faster access to get, read and write callbacks.
|
||||||
|
The key type is alias of unsigned long, so you can assign some static number
|
||||||
|
(e.g. index of the array) to this value of the corresponding element, or
|
||||||
|
assign the pointer (cast to #snd_ctl_ext_key_t). When no key is defined or found,
|
||||||
|
return #SND_CTL_EXT_KEY_NOT_FOUND. This callback is (very likely) required
|
||||||
|
if you use get, read and write callbacks as follows.
|
||||||
|
If you need to create a record dynamically (e.g. via malloc) at each find_elem call,
|
||||||
|
the allocated record can be released with the optional free_key callback.
|
||||||
|
|
||||||
|
The get_attribute is a mandatory callback, which returns the attribute of the
|
||||||
|
control element given via a key value (converted with find_elem callback).
|
||||||
|
It must fill the control element type (#snd_ctl_elem_type_t), the access type
|
||||||
|
(#snd_ctl_ext_access_t), and the count (element array size). The callback returns
|
||||||
|
0 if successful, or a negative error code, as usual.
|
||||||
|
|
||||||
|
The get_integer_info, get_integetr64_info and get_enumerated_info callbacks are called
|
||||||
|
to return the information of the given control element for each element type.
|
||||||
|
For integer and integer64 types, the callbacks need to fill the minimal (imin),
|
||||||
|
maximal (imax) and the step (istep) values of the control. For the enumerated type,
|
||||||
|
the number of enum items must be filled. Additionally, the enum control has to define
|
||||||
|
get_enumerated_name callback to store the name of the enumerated item of the given control
|
||||||
|
element. All functions return 0 if successful, or a negative error code.
|
||||||
|
|
||||||
|
For reading the current values of a control element, read_integer, read_integer64,
|
||||||
|
read_enumerated, read_bytes and read_iec958 callbacks are called depending on the
|
||||||
|
element type. These callbacks have to fill the current values of the element in return.
|
||||||
|
Note that a control element can be an array. If it contains more than one values
|
||||||
|
(i.e. the count value in get_attribute callback is more than 1), <i>all</i> values
|
||||||
|
must be filled on the given value pointer as an array. Also, note that the boolean type
|
||||||
|
is handled as integer here (although boolean type doesn't need to define the corresponding
|
||||||
|
info callback since it's obvious). These callbacks return 0 if successful, or
|
||||||
|
a negative error code.
|
||||||
|
|
||||||
|
For writing the current values, write_integer, write_integer64, write_bytes, and
|
||||||
|
write_iec958 callbacks are called as well as for read. The callbacks should check the
|
||||||
|
current values and compare with the given values. If they are identical, the callbacks
|
||||||
|
should do nothing and return 0. If they differ, update the current values and return 1,
|
||||||
|
instead. For any errors, return a negative error code.
|
||||||
|
|
||||||
|
The subscribe_events callback is called when the application subscribes or cancels
|
||||||
|
the event notifications (e.g. through mixer API). The current value of event
|
||||||
|
subscription is kept in the subscribed field.
|
||||||
|
The read_event callback is called for reading a pending notification event.
|
||||||
|
The callback needs to fill the event_mask value, a bit-field defined as SND_CTL_EVENT_MASK_XXX.
|
||||||
|
If no event is pending, return -EAGAIN. These two callbacks are optional.
|
||||||
|
|
||||||
|
The poll_descriptors_count and poll_descriptors callbacks are used to return
|
||||||
|
the poll descriptor(s) via callbacks. As already mentioned, if the callback cannot
|
||||||
|
set the static poll_fd, you can define these callbacks to return dynamically.
|
||||||
|
Also, when multiple poll descriptors are required, use these callbacks.
|
||||||
|
The poll_revents callback is used for handle poll revents.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Create an external control plugin instance
|
* \brief Create an external control plugin instance
|
||||||
* \param ext the plugin handle
|
* \param ext the plugin handle
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue