1 /** 2 * \file pcm/pcm_asym.c 3 * \ingroup PCM_Plugins 4 * \brief PCM Asymmetrical Plugin Interface 5 * \author Takashi Iwai <tiwai (at) 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 */ 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