Skip to content

Commit a36069e

Browse files
committed
tinyalsa: Add sample pcm/mixer plugin and sample sndcardparser
1 parent 496e653 commit a36069e

File tree

6 files changed

+947
-0
lines changed

6 files changed

+947
-0
lines changed

Android.bp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@ cc_library {
6363
},
6464
}
6565

66+
cc_library_headers {
67+
name: "libtinyalsav2_headers",
68+
export_include_dirs: ["include"],
69+
vendor_available: true,
70+
}
71+
6672
cc_binary {
6773
name: "tinyplay2",
6874
host_supported: true,

examples/plugins/Android.bp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
cc_library {
2+
name: "libtinyalsav2_example_plugin_pcm",
3+
vendor: true,
4+
srcs: ["sample_pcm_plugin.c"],
5+
cflags: ["-Werror", "-Wno-unused-parameter"],
6+
header_libs: ["libtinyalsav2_headers"],
7+
}
8+
9+
cc_library {
10+
name: "libtinyalsav2_example_plugin_mixer",
11+
vendor: true,
12+
srcs: ["sample_mixer_plugin.c"],
13+
cflags: ["-Werror", "-Wno-unused-parameter"],
14+
header_libs: ["libtinyalsav2_headers"],
15+
}
Lines changed: 319 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,319 @@
1+
/*
2+
** Copyright (c) 2021, The Linux Foundation. All rights reserved.
3+
**
4+
** Redistribution and use in source and binary forms, with or without
5+
** modification, are permitted provided that the following conditions are
6+
** met:
7+
** * Redistributions of source code must retain the above copyright
8+
** notice, this list of conditions and the following disclaimer.
9+
** * Redistributions in binary form must reproduce the above
10+
** copyright notice, this list of conditions and the following
11+
** disclaimer in the documentation and/or other materials provided
12+
** with the distribution.
13+
** * Neither the name of The Linux Foundation nor the names of its
14+
** contributors may be used to endorse or promote products derived
15+
** from this software without specific prior written permission.
16+
**
17+
** THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18+
** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19+
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20+
** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21+
** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22+
** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23+
** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24+
** BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25+
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26+
** OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27+
** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28+
**/
29+
30+
#include <errno.h>
31+
#include <stdio.h>
32+
#include <stdint.h>
33+
#include <stdlib.h>
34+
#include <string.h>
35+
36+
#include <sound/asound.h>
37+
#include <tinyalsa/plugin.h>
38+
#include <tinyalsa/asoundlib.h>
39+
40+
#define SAMPLE_MIXER_PRIV_GET_CTL_PTR(p, idx) (p->ctls + idx)
41+
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
42+
43+
static const char *const sample_enum_text[] = {"One", "Two", "Three"};
44+
45+
struct sample_mixer_priv {
46+
struct snd_control *ctls;
47+
int ctl_count;
48+
49+
struct snd_value_enum sample_enum;
50+
51+
mixer_event_callback event_cb;
52+
};
53+
54+
static int sample_mixer_int_ctl_get(struct mixer_plugin *plugin,
55+
struct snd_control *ctl, struct snd_ctl_elem_value *ev)
56+
{
57+
return 0;
58+
}
59+
60+
static int sample_mixer_int_ctl_put(struct mixer_plugin *plugin,
61+
struct snd_control *ctl, struct snd_ctl_elem_value *ev)
62+
{
63+
/*
64+
* Integer values can be retrieved using:
65+
* uint32_t val1 = (uint32_t)ev->value.integer.value[0];
66+
* uint32_t val2 = (uint32_t)ev->value.integer.value[1];
67+
* uint32_t val3 = (uint32_t)ev->value.integer.value[2];
68+
*/
69+
return 0;
70+
}
71+
72+
static int sample_mixer_byte_array_ctl_get(struct mixer_plugin *plugin,
73+
struct snd_control *ctl, struct snd_ctl_elem_value *ev)
74+
{
75+
return 0;
76+
}
77+
78+
static int sample_mixer_byte_array_ctl_put(struct mixer_plugin *plugin,
79+
struct snd_control *ctl, struct snd_ctl_elem_value *ev)
80+
{
81+
/*
82+
* Byte array payload can be retrieved using:
83+
* void *payload = ev->value.bytes.data;
84+
*/
85+
86+
return 0;
87+
}
88+
89+
static int sample_mixer_tlv_ctl_get(struct mixer_plugin *plugin,
90+
struct snd_control *ctl, struct snd_ctl_tlv *ev)
91+
{
92+
return 0;
93+
}
94+
95+
static int sample_mixer_tlv_ctl_put(struct mixer_plugin *plugin,
96+
struct snd_control *ctl, struct snd_ctl_tlv *tlv)
97+
{
98+
/*
99+
* TLV payload and len can be retrieved using:
100+
* void *payload = &tlv->tlv[0];
101+
* size_t tlv_size = tlv->length;
102+
*/
103+
104+
return 0;
105+
}
106+
107+
static int sample_mixer_enum_ctl_get(struct mixer_plugin *plugin,
108+
struct snd_control *ctl, struct snd_ctl_elem_value *ev)
109+
{
110+
return 0;
111+
}
112+
113+
static int sample_mixer_enum_ctl_put(struct mixer_plugin *plugin,
114+
struct snd_control *ctl, struct snd_ctl_elem_value *ev)
115+
{
116+
/*
117+
* Enum value can be retrieved using:
118+
* unsigned int val = ev->value.enumerated.item[0];
119+
*/
120+
return 0;
121+
}
122+
123+
static struct snd_value_int sample_mixer_ctl_value_int =
124+
SND_VALUE_INTEGER(3, 0, 1000, 100);
125+
126+
/* 512 max bytes for non-tlv byte controls */
127+
static struct snd_value_bytes byte_array_ctl_bytes =
128+
SND_VALUE_BYTES(512);
129+
130+
static struct snd_value_tlv_bytes sample_mixer_tlv_ctl_bytes =
131+
SND_VALUE_TLV_BYTES(1024, sample_mixer_tlv_ctl_get, sample_mixer_tlv_ctl_put);
132+
133+
static void create_integer_ctl(struct sample_mixer_priv *priv,
134+
int ctl_idx, int pval, void *pdata)
135+
{
136+
struct snd_control *ctl = SAMPLE_MIXER_PRIV_GET_CTL_PTR(priv, ctl_idx);
137+
char *ctl_name = strdup("Sample integer control");
138+
139+
/* pval and pdata can be retrieved using snd_control during get()/put() */
140+
INIT_SND_CONTROL_INTEGER(ctl, ctl_name, sample_mixer_int_ctl_get,
141+
sample_mixer_int_ctl_put, sample_mixer_ctl_value_int, pval, pdata);
142+
}
143+
144+
static void create_byte_array_ctl(struct sample_mixer_priv *priv,
145+
int ctl_idx, int pval, void *pdata)
146+
{
147+
struct snd_control *ctl = SAMPLE_MIXER_PRIV_GET_CTL_PTR(priv, ctl_idx);
148+
char *ctl_name = strdup("Sample byte array control");
149+
150+
INIT_SND_CONTROL_BYTES(ctl, ctl_name, sample_mixer_byte_array_ctl_get,
151+
sample_mixer_byte_array_ctl_put, byte_array_ctl_bytes,
152+
pval, pdata);
153+
}
154+
155+
static void create_tlv_ctl(struct sample_mixer_priv *priv,
156+
int ctl_idx, int pval, void *pdata)
157+
{
158+
struct snd_control *ctl = SAMPLE_MIXER_PRIV_GET_CTL_PTR(priv, ctl_idx);
159+
char *ctl_name = strdup("Sample tlv control");
160+
161+
INIT_SND_CONTROL_TLV_BYTES(ctl, ctl_name, sample_mixer_tlv_ctl_bytes,
162+
pval, pdata);
163+
}
164+
165+
static void create_enum_ctl(struct sample_mixer_priv *priv,
166+
int ctl_idx, struct snd_value_enum *e,
167+
int pval, void *pdata)
168+
{
169+
struct snd_control *ctl = SAMPLE_MIXER_PRIV_GET_CTL_PTR(priv, ctl_idx);
170+
char *ctl_name = strdup("Sample enum control");
171+
172+
INIT_SND_CONTROL_ENUM(ctl, ctl_name, sample_mixer_enum_ctl_get,
173+
sample_mixer_enum_ctl_put, e, pval, pdata);
174+
}
175+
176+
static int sample_mixer_form_ctls(struct sample_mixer_priv *priv, int ctl_idx)
177+
{
178+
create_integer_ctl(priv, ctl_idx, 0, NULL);
179+
ctl_idx++;
180+
create_byte_array_ctl(priv, ctl_idx, 0, NULL);
181+
ctl_idx++;
182+
create_tlv_ctl(priv, ctl_idx, 0, NULL);
183+
ctl_idx++;
184+
create_enum_ctl(priv, ctl_idx, &priv->sample_enum, 0, NULL);
185+
ctl_idx++;
186+
187+
return 0;
188+
}
189+
190+
static ssize_t sample_mixer_read_event(struct mixer_plugin *plugin,
191+
struct snd_ctl_event *ev, size_t size)
192+
{
193+
/* Fill snd_ctl_event *ev before sending.
194+
* Return : sizeof(struct snd_ctl_event),
195+
* 0 in case no event present.
196+
*/
197+
198+
return 0;
199+
}
200+
201+
static int sample_mixer_subscribe_events(struct mixer_plugin *plugin,
202+
mixer_event_callback event_cb)
203+
{
204+
struct sample_mixer_priv *priv = plugin->priv;
205+
206+
priv->event_cb = event_cb;
207+
/* event_cb is the callback function which needs to be called
208+
* when an event occurs. This will unblock poll() on mixer fd
209+
* which is called from mixer_wait_event().
210+
* Once poll is unblocked, clients can call mixer_read_event()
211+
* During unsubscribe(), event_cb is NULL.
212+
*/
213+
return 0;
214+
}
215+
216+
static int sample_mixer_alloc_ctls(struct sample_mixer_priv *priv)
217+
{
218+
int ret = 0, i;
219+
220+
priv->ctls = calloc(priv->ctl_count, sizeof(*priv->ctls));
221+
if (!priv->ctls) {
222+
return -ENOMEM;
223+
}
224+
225+
priv->sample_enum.items = ARRAY_SIZE(sample_enum_text);
226+
priv->sample_enum.texts = calloc(priv->sample_enum.items, sizeof(*priv->sample_enum.texts));
227+
228+
for (i = 0; i < ARRAY_SIZE(sample_enum_text); i++)
229+
priv->sample_enum.texts[i] = strdup(sample_enum_text[i]);
230+
231+
return sample_mixer_form_ctls(priv, 0);
232+
}
233+
234+
static void sample_mixer_free_ctls(struct sample_mixer_priv *priv)
235+
{
236+
int num_enums, i;
237+
struct snd_control *ctl = NULL;
238+
239+
for (i = 0; i < priv->ctl_count; i++) {
240+
ctl = SAMPLE_MIXER_PRIV_GET_CTL_PTR(priv, i);
241+
if (ctl->name)
242+
free((void *)ctl->name);
243+
}
244+
245+
num_enums = priv->sample_enum.items;
246+
247+
for (i = 0; i < num_enums; i++)
248+
free(priv->sample_enum.texts[i]);
249+
250+
free(priv->sample_enum.texts);
251+
priv->ctl_count = 0;
252+
253+
if (priv->ctls) {
254+
free(priv->ctls);
255+
priv->ctls = NULL;
256+
}
257+
}
258+
259+
static void sample_mixer_close(struct mixer_plugin **plugin)
260+
{
261+
struct mixer_plugin *mp = *plugin;
262+
struct sample_mixer_priv *priv = mp->priv;
263+
264+
/* unblock mixer event during close */
265+
if (priv->event_cb)
266+
priv->event_cb(mp);
267+
sample_mixer_subscribe_events(mp, NULL);
268+
sample_mixer_free_ctls(priv);
269+
free(priv);
270+
free(*plugin);
271+
*plugin = NULL;
272+
}
273+
274+
int sample_mixer_open(struct mixer_plugin **plugin, unsigned int card)
275+
{
276+
struct mixer_plugin *mp;
277+
struct sample_mixer_priv *priv;
278+
int i, ret = 0;
279+
int ctl_cnt = 4;
280+
281+
mp = calloc(1, sizeof(*mp));
282+
if (!mp) {
283+
return -ENOMEM;
284+
}
285+
286+
priv = calloc(1, sizeof(*priv));
287+
if (!priv) {
288+
ret = -ENOMEM;
289+
goto err_priv_alloc;
290+
}
291+
292+
priv->ctl_count = ctl_cnt;
293+
ret = sample_mixer_alloc_ctls(priv);
294+
if (ret)
295+
goto err_ctls_alloc;
296+
297+
/* Register the controls */
298+
mp->controls = priv->ctls;
299+
mp->num_controls = priv->ctl_count;
300+
mp->priv = priv;
301+
*plugin = mp;
302+
303+
return 0;
304+
305+
err_ctls_alloc:
306+
sample_mixer_free_ctls(priv);
307+
free(priv);
308+
309+
err_priv_alloc:
310+
free(mp);
311+
return ret;
312+
}
313+
314+
struct mixer_plugin_ops mixer_plugin_ops = {
315+
.open = sample_mixer_open,
316+
.close = sample_mixer_close,
317+
.subscribe_events = sample_mixer_subscribe_events,
318+
.read_event = sample_mixer_read_event,
319+
};

0 commit comments

Comments
 (0)