1 /**
2 * \file pcm/pcm_asym.c
3 * \ingroup PCM_Plugins
4 * \brief PCM Asymmetrical Plugin Interface
5 * \author Takashi Iwai <tiwai@suse.de>
6 * \date 2003
7 */
8
9 #include "pcm_local.h"
10
11 #ifndef PIC
12 /* entry for static linking */
13 const char *_snd_module_pcm_asym = "";
14 #endif
15
16 /*! \page pcm_plugins
17
18 \section pcm_plugins_asym Plugin: asym
19
20 This plugin is a combination of playback and capture PCM streams.
21 Slave PCMs can be defined asymmetrically for both directions.
22
23 \code
24 pcm.name {
25 type asym # Asym PCM
26 playback STR # Playback slave name
27 # or
28 playback { # Playback slave definition
29 pcm STR # Slave PCM name
30 # or
31 pcm { } # Slave PCM definition
32 }
33 capture STR # Capture slave name
34 # or
35 capture { # Capture slave definition
36 pcm STR # Slave PCM name
37 # or
38 pcm { } # Slave PCM definition
39 }
40 }
41 \endcode
42
43 For example, you can combine a dmix plugin and a dsnoop plugin as
44 as a single PCM for playback and capture directions, respectively.
45 \code
46 pcm.duplex {
47 type asym
48 playback.pcm "dmix"
49 capture.pcm "dsnoop"
50 }
51 \endcode
52
53 By defining only a single direction, the resultant PCM becomes
54 half-duplex.
55
56 \subsection pcm_plugins_asym_funcref Function reference
57
58 <UL>
59 <LI>_snd_pcm_asym_open()
60 </UL>
61
62 */
63
64 /**
65 * \brief Creates a new asym stream PCM
66 * \param pcmp Returns created PCM handle
67 * \param name Name of PCM
68 * \param root Root configuration node
69 * \param conf Configuration node with copy PCM description
70 * \param stream Stream type
71 * \param mode Stream mode
72 * \retval zero on success otherwise a negative error code
73 * \warning Using of this function might be dangerous in the sense
74 * of compatibility reasons. The prototype might be freely
75 * changed in future.
76 */
_snd_pcm_asym_open(snd_pcm_t ** pcmp,const char * name ATTRIBUTE_UNUSED,snd_config_t * root,snd_config_t * conf,snd_pcm_stream_t stream,int mode)77 int _snd_pcm_asym_open(snd_pcm_t **pcmp, const char *name ATTRIBUTE_UNUSED,
78 snd_config_t *root, snd_config_t *conf,
79 snd_pcm_stream_t stream, int mode)
80 {
81 snd_config_iterator_t i, next;
82 int err;
83 snd_config_t *slave = NULL, *sconf;
84 snd_config_for_each(i, next, conf) {
85 snd_config_t *n = snd_config_iterator_entry(i);
86 const char *id;
87 if (snd_config_get_id(n, &id) < 0)
88 continue;
89 if (snd_pcm_conf_generic_id(id))
90 continue;
91 if (strcmp(id, "playback") == 0) {
92 if (stream == SND_PCM_STREAM_PLAYBACK)
93 slave = n;
94 continue;
95 }
96 if (strcmp(id, "capture") == 0) {
97 if (stream == SND_PCM_STREAM_CAPTURE)
98 slave = n;
99 continue;
100 }
101 SNDERR("Unknown field %s", id);
102 return -EINVAL;
103 }
104 if (! slave) {
105 SNDERR("%s slave is not defined",
106 stream == SND_PCM_STREAM_PLAYBACK ? "playback" : "capture");
107 return -EINVAL;
108 }
109 err = snd_pcm_slave_conf(root, slave, &sconf, 0);
110 if (err < 0)
111 return err;
112 err = snd_pcm_open_named_slave(pcmp, name, root, sconf, stream,
113 mode, conf);
114 snd_config_delete(sconf);
115 return err;
116 }
117 #ifndef DOC_HIDDEN
118 SND_DLSYM_BUILD_VERSION(_snd_pcm_asym_open, SND_PCM_DLSYM_VERSION);
119 #endif
120