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