File: coding-4.html

package info (click to toggle)
alsadriver 0.2.0-pre8-3
  • links: PTS
  • area: main
  • in suites: slink
  • size: 2,808 kB
  • ctags: 6,550
  • sloc: ansic: 43,490; sh: 916; makefile: 759; perl: 54
file content (339 lines) | stat: -rw-r--r-- 10,838 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
<HTML>
<HEAD>
<TITLE>Advanced Linux Sound Architecture - Driver: Mixer</TITLE>
</HEAD>
<BODY>
<A HREF="coding-3.html">Previous</A>
<A HREF="coding-5.html">Next</A>
<A HREF="coding.html#toc4">Table of Contents</A>
<HR>
<H2><A NAME="s4">4. Mixer</A></H2>

<P>Mixer related structures and function is in <I>include/mixer.h</I> header
file.</P>

<H2><A NAME="ss4.1">4.1 Variables and functions</A></H2>

<P>Variables from <I>snd_kmixer_t</I> structure which must be filled:</P>
<P>
<UL>
<LI><B>name</B> is name of mixer (for example 'AD1848').</LI>
<LI><B>hw</B> read-only variables dependend on hardware.</LI>
</UL>
</P>

<P>Variables from <I>snd_kmixer_t</I> structure which should be filled:</P>
<P>
<UL>
<LI><B>private_data</B> should contains private data for mixer.</LI>
<LI><B>private_free</B> should free private data.</LI>
</UL>
</P>

<P>Variables from <I>struct snd_stru_mixer_hw</I> structure which must be filled:</P>
<P>
<UL>
<LI><B>caps</B> mixer capabilities (see to <B>SND_SND_MIXER_INFO_CAP_*</B>).</LI>
</UL>
</P>

<P>Variables from <I>struct snd_stru_mixer_hw</I> structure which should be filled:</P>
<P>
<UL>
<LI><B>get_special</B></LI>
<LI><B>set_special</B></LI>
</UL>
</P>

<P>Variables from <I>snd_kmixer_channel_t</I> structure which must be filled:</P>
<P>
<UL>
<LI><B>hw</B> read-only variables dependend on hardware.</LI>
</UL>
</P>

<P>Variables from <I>snd_kmixer_channel_t</I> structure which should be filled:</P>
<P>
<UL>
<LI><B>private_value</B> is <I>unsigned int</I> variable which isn't used 
by middle-level code.</LI>
<LI><B>private_data</B> is pointer to some private data associated with
appropriate channel. These data aren't freed by middle-level code.</LI>
</UL>
</P>

<P>Variables from <I>struct snd_stru_mixer_channel_hw</I> structure which must
be filled:</P>
<P>
<UL>
<LI><B>priority</B> priority (identificator) - see to <B>SND_MIXER_PRI_*</B></LI>
<LI><B>parent_priority</B> parent mixer channel priority or <B>SND_MIXER_PRI_PARENT</B></LI>
<LI><B>name</B> name of this mixer channel - see to <B>SND_MIXER_ID_*</B></LI>
<LI><B>ossdev</B> OSS (Open Sound System) device - see to <B>SND_MIXER_OSS_*</B></LI>
<LI><B>mute</B> if hardware mute is supported</LI>
<LI><B>stereo</B> if stereo is supported</LI>
<LI><B>record</B> is recording is possible from this channel</LI>
<LI><B>digital</B> is this channel is digitaly (not analog) mixed</LI>
<LI><B>input</B> is channel is input channel</LI>
<LI><B>min, max</B> specifies exact linear range from <I>min</I> to <I>max</I></LI>
<LI><B>min_dB, max_dB, step_dB</B> range and step size for decibel * 100</LI>
<LI><B>void (*set_record_source)( snd_kmixer_t *mixer, snd_kmixer_channel_t *channel, int enable )</B>
<UL>
<LI><B>mixer</B> pointer to mixer structure</LI>
<LI><B>channel</B> pointer to channel structure</LI>
<LI><B>enable</B> if non-zero - record source must be enabled</LI>
<LI>must be set, if channel supports recording</LI>
</UL>
</LI>
<LI><B>void (*set_mute)( snd_kmixer_t *mixer, snd_kmixer_channel_t *channel, unsigned int mute )</B>
<UL>
<LI><B>mixer</B> pointer to mixer structure</LI>
<LI><B>channel</B> pointer to channel structure</LI>
<LI><B>mute</B> should be zero (no mute) or <B>SND_MIX_MUTE*</B></LI>
<LI>must be set, if channel supports hardware muting</LI>
</UL>
</LI>
<LI><B>void (*set_volume_level)( snd_kmixer_t *mixer, snd_kmixer_channel_t *channel, int left, int right )</B>
<UL>
<LI><B>mixer</B> pointer to mixer structure</LI>
<LI><B>channel</B> pointer to channel structure</LI>
<LI><B>left</B> volume level in exact range</LI>
<LI><B>right</B> volume level in exact range</LI>
<LI>handler which sets volume level for this channel</LI>
</UL>
</LI>
</UL>
</P>

<P>Variables from <I>struct snd_stru_mixer_channel_hw</I> structure which should
be filled:</P>
<P>
<UL>
<LI><B>int (*compute_linear)( snd_kmixer_t *mixer, snd_kmixer_channel_t *channel, int dB )</B>
<UL>
<LI>input = dB from application, output = min...max (linear volume)</LI>
</UL>
</LI>
<LI><B>int (*compute_dB)( snd_kmixer_t *mixer, snd_kmixer_channel_t *channel, int volume )</B>
<UL>
<LI>input = min...max (linear volume), output = dB to application</LI>
</UL>
</LI>
</UL>
</P>

<P>Functions list:</P>
<P>
<UL>
<LI><B>void snd_mixer_set_kernel_mute( snd_kmixer_t *mixer, unsigned int priority, unsigned short mute )</B>
<UL>
<LI><B>mixer</B> pointer to mixer structure</LI>
<LI><B>priority</B> specifies mixer channel</LI>
<LI><B>mute</B> zero or <B>SND_MIX_MUTE*</B></LI>
<LI>should be use as mute control from kernel</LI>
<LI>this settings is never overriden by application</LI>
</UL>
</LI>
<LI><B>snd_kmixer_t *snd_mixer_new( snd_card_t *card, char *id )</B>
<UL>
<LI><B>card</B> pointer to soundcard structure</LI>
<LI><B>id</B> is identification of code (for example 'AD1848').</LI>
</UL>
</LI>
<LI><B>int snd_mixer_free( snd_kmixer_t *mixer )</B>
<UL>
<LI><B>mixer</B> pointer to mixer structure</LI>
<LI>frees mixer structure and private data</LI>
</UL>
</LI>
<LI><B>snd_kmixer_channel_t *snd_mixer_new_channel( snd_kmixer_t *mixer, struct snd_stru_mixer_channel_hw *hw )</B>
<UL>
<LI><B>mixer</B> pointer to mixer structure</LI>
<LI><B>hw</B> pointer to mixer channel variables and operations</LI>
<LI>creates new mixer channel</LI>
</UL>
</LI>
<LI><B>void snd_mixer_reorder_channel( snd_kmixer_t *mixer, snd_kmixer_channel_t *channel )</B>
<UL>
<LI><B>mixer</B> pointer to mixer structure</LI>
<LI><B>channel</B> pointer to mixer channel</LI>
<LI>reorders mixer channels if channel -> priority was changed</LI>
</UL>
</LI>
<LI><B>int snd_mixer_register( snd_kmixer_t *mixer, int device )</B>
<UL>
<LI><B>mixer</B> pointer to mixer structure</LI>
<LI><B>device</B> device number (0-1)</LI>
<LI>registers specified mixer</LI>
</UL>
</LI>
<LI><B>int snd_mixer_unregister( snd_mixer_t *mixer )</B>
<UL>
<LI><B>mixer</B> pointer to mixer structure</LI>
<LI>unregisters and <B>frees</B> specified mixer</LI>
</UL>
</LI>
</UL>
</P>


<H2><A NAME="ss4.2">4.2 Exaples</A></H2>


<P>
<BLOCKQUOTE><CODE>
<HR>
<PRE>
#define CS4231_MIXS (sizeof(snd_cs4231_mixs)/sizeof(struct snd_stru_mixer_channel_hw))
#define CS4231_PRIVATE( left, right, shift, mute ) ((left &lt;&lt; 24)|(right &lt;&lt; 16)|(shift&lt;&lt;8)|mute)

static struct snd_stru_mixer_channel_hw snd_cs4231_mixs[] = {
  {
    SND_MIXER_PRI_GAIN,         /* priority */
    SND_MIXER_PRI_PARENT,       /* parent priority */
    SND_MIXER_ID_GAIN,          /* device name */
    SND_MIXER_OSS_IMIX,         /* OSS device # */
    0, 1, 0, 0, 1,              /* mute/stereo/record/digital/input */
    0, 15,                      /* min, max value */
    0, 2250, 150,               /* min, max, step - dB */
    CS4231_PRIVATE( CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0x00 ) | 0x2000,
    NULL,                       /* compute dB -&gt; linear */
    NULL,                       /* compute linear -&gt; dB */
    NULL,                       /* record source */
    NULL,                       /* set mute */
    snd_cs4231_volume_level,    /* set volume level */
  },
  ....
};

snd_kmixer_t *snd_cs4231_new_mixer( snd_pcm_t *pcm )
{
  int idx;
  cs4231_t *codec;
  snd_kmixer_t *mixer;
  snd_kmixer_channel_t *channel;

  if ( !pcm || !pcm -&gt; card ) return NULL;
  codec = (cs4231_t *)pcm -&gt; private_data;
  if ( !codec ) return NULL;
  mixer = snd_mixer_new( pcm -&gt; card, pcm -&gt; id );
  if ( !mixer ) return NULL;
  strcpy( mixer -&gt; name, pcm -&gt; name );
  for ( idx = 0; idx &lt; CS4231_MIXS; idx++ ) {
    channel = snd_mixer_new_channel( mixer, &amp;snd_cs4231_mixs[ idx ] );
    if ( !channel ) {
      snd_mixer_free( mixer );
      return NULL;
    }
  }
  mixer -&gt; hw.caps = SND_MIXER_INFO_CAP_EXCL_RECORD;
  mixer -&gt; private_data = codec;
  codec -&gt; mixer = mixer;
  return mixer;
}
</PRE>
<HR>
</CODE></BLOCKQUOTE>
</P>

<P>Do you need modify some default mixer channel assignment?</P>
<P>
<BLOCKQUOTE><CODE>
<HR>
<PRE>
  snd_kmixer_channel_t *channel;

  /* ok. InterWave have MIC different (stereo) */
  channel = snd_mixer_find_channel( mixer, SND_MIXER_PRI_MIC );
  channel -&gt; hw.stereo = 1;
  channel -&gt; hw.max = 31;
  channel -&gt; hw.private_value = CS4231_PRIVATE( CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 0, 0x80 );

  /* reassign AUXA to SYNTHESIZER */
  channel = snd_mixer_find_channel( mixer, SND_MIXER_PRI_AUXA );
  channel -&gt; hw.priority = SND_MIXER_PRI_SYNTHESIZER;
  channel -&gt; hw.ossdev = SND_MIXER_OSS_SYNTH;
  strcpy( channel -&gt; hw.name, SND_MIXER_ID_SYNTHESIZER );
  snd_mixer_reorder_channel( mixer, channel );
</PRE>
<HR>
</CODE></BLOCKQUOTE>
</P>

<P>Do you need add some mixer channel to generic mixer?</P>
<P>
<BLOCKQUOTE><CODE>
<HR>
<PRE>
  static struct snd_stru_mixer_channel_hw master = {
    SND_MIXER_PRI_MASTER,               /* priority */
    SND_MIXER_PRI_PARENT,               /* parent priority */
    SND_MIXER_ID_MASTER,                /* device name */
    SND_MIXER_OSS_VOLUME,               /* OSS device # */
    1, 1, 1, 0, 0,                      /* mute/stereo/record/digital */
    0, 31,                              /* max. value */
    -3450, 1200, 150,                   /* min, max, step - dB */
    CS4231_PRIVATE( CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 0, 0x80
    NULL,                               /* compute dB -&gt; linear */
    NULL,                               /* compute linear -&gt; dB */
    NULL,                               /* record source */
    NULL,                               /* set mute */
    NULL,                               /* set volume level */
  };
  int idx;

  /* make master as parent */
  for ( idx = 0; idx &lt; mixer -&gt; channels_count; idx++ ) {
    channel = mixer -&gt; channels[ idx ];
    if ( !channel -&gt; hw.input )
      channel -&gt; hw.parent_priority = SND_MIXER_PRI_MASTER;
  }
  /* add master volume control */
  master.set_record_source = channel -&gt; hw.set_record_source;
  master.set_mute = channel -&gt; hw.set_mute;
  master.set_volume_level = channel -&gt; hw.set_volume_level;
  channel = snd_mixer_new_channel( mixer, &amp;master );
  if ( !channel ) return -ENOMEM;
</PRE>
<HR>
</CODE></BLOCKQUOTE>
</P>
<P>Mixer device registering:</P>
<P>
<BLOCKQUOTE><CODE>
<HR>
<PRE>
  snd_card_t *card;
  snd_pcm_t *pcm.
  snd_kmixer_t *mixer;

  ...
  mixer = snd_es1688_new_mixer( pcm );
  if ( !mixer ) {
    snd_pcm_free( pcm );
    snd_card_free( card );
    return -NXIO;
  }
  ...
  if ( snd_mixer_register( mixer, 0 ) ) {
    ... unregister already registered devices ...
    snd_mixer_free( mixer );
    snd_pcm_free( pcm );
    snd_card_free( card );
    return -ENXIO;
  }
  ...
  snd_mixer_unregister( mixer );
</PRE>
<HR>
</CODE></BLOCKQUOTE>
</P>



<HR>
<A HREF="coding-3.html">Previous</A>
<A HREF="coding-5.html">Next</A>
<A HREF="coding.html#toc4">Table of Contents</A>
</BODY>
</HTML>