• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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