blob: 3749f78623ef72f0ba71051a21e0d88cedec697f [file] [log] [blame]
Benny Prijono2cd64f82009-02-17 19:57:48 +00001/* $Id$ */
2/*
3 * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#include <pjmedia-audiodev/audiodev_imp.h>
21#include <pj/errno.h>
22
23
24#define MAKE_DEV_ID(f_id, index) (((f_id & 0xFFFF) << 16) & (index & 0xFFFF))
25#define GET_INDEX(dev_id) ((dev_id) & 0xFFFF)
26#define GET_FID(dev_id) ((dev_id) >> 16)
27
28
29/* extern */
30pjmedia_aud_dev_factory* pjmedia_pa_factory(pj_pool_factory *pf);
31
32/* Array of factories */
33static struct factory
34{
35 pjmedia_aud_dev_factory* (*create)(pj_pool_factory*);
36 pjmedia_aud_dev_factory *f;
37
38} factories[] =
39{
40 {
41 &pjmedia_pa_factory
42 }
43};
44static unsigned factory_cnt;
45
46
47/* API: Initialize the audio subsystem. */
48PJ_DEF(pj_status_t) pjmedia_aud_subsys_init(pj_pool_factory *pf)
49{
50 unsigned i;
51 pj_status_t status = PJ_ENOMEM;
52
53 factory_cnt = 0;
54
55 for (i=0; i<PJ_ARRAY_SIZE(factories); ++i) {
56 factories[i].f = (*factories[i].create)(pf);
57 if (!factories[i].f)
58 continue;
59
60 status = factories[i].f->op->init(factories[i].f);
61 if (status != PJ_SUCCESS) {
62 factories[i].f->op->destroy(factories[i].f);
63 factories[i].f = NULL;
64 }
65
66 factories[i].f->internal.id = i;
67 ++factory_cnt;
68 }
69
70 return factory_cnt ? PJ_SUCCESS : status;
71}
72
73/* API: Shutdown the audio subsystem. */
74PJ_DEF(pj_status_t) pjmedia_aud_subsys_shutdown(void)
75{
76 unsigned i;
77
78 for (i=0; i<PJ_ARRAY_SIZE(factories); ++i) {
79 if (!factories[i].f)
80 continue;
81
82 factories[i].f->op->destroy(factories[i].f);
83 factories[i].f = NULL;
84 }
85
86 return PJ_SUCCESS;
87}
88
89/* API: Get the number of sound devices installed in the system. */
90PJ_DEF(unsigned) pjmedia_aud_dev_count(void)
91{
92 unsigned i, count = 0;
93
94 for (i=0; i<PJ_ARRAY_SIZE(factories); ++i) {
95 if (!factories[i].f)
96 continue;
97
98 count += factories[i].f->op->get_dev_count(factories[i].f);
99 }
100
101 return count;
102}
103
104/* API: Enumerate device ID's. */
105PJ_DEF(unsigned) pjmedia_aud_dev_enum(unsigned max_count,
106 pjmedia_aud_dev_id ids[])
107{
108 unsigned i, count = 0;
109
110 for (i=0; i<PJ_ARRAY_SIZE(factories) && count < max_count; ++i) {
111 unsigned j, fcount;
112
113 if (!factories[i].f)
114 continue;
115
116 fcount = factories[i].f->op->get_dev_count(factories[i].f);
117 for (j=0; j<fcount && count<max_count; ++j) {
118 ids[count++] = MAKE_DEV_ID(i, j);
119 }
120 }
121
122 return count;
123}
124
125
126/* API: Get device information. */
127PJ_DEF(pj_status_t) pjmedia_aud_dev_get_info(pjmedia_aud_dev_id id,
128 pjmedia_aud_dev_info *info)
129{
130 int f_id, index;
131
132 f_id = GET_FID(id);
133 index = GET_INDEX(id);
134
135 if (f_id < 0 || f_id >= PJ_ARRAY_SIZE(factories))
136 return PJMEDIA_EAUD_INVDEV;
137
138 if (factories[f_id].f == NULL)
139 return PJMEDIA_EAUD_INVDEV;
140
141 return factories[f_id].f->op->get_dev_info(factories[f_id].f,
142 index, info);
143}
144
145/* API: Initialize the audio device parameters with default values for the
146 * specified device.
147 */
148PJ_DEF(pj_status_t) pjmedia_aud_dev_default_param(pjmedia_aud_dev_id id,
149 pjmedia_aud_dev_param *param)
150{
151 int f_id, index;
152 pj_status_t status;
153
154 f_id = GET_FID(id);
155 index = GET_INDEX(id);
156
157 if (f_id < 0 || f_id >= PJ_ARRAY_SIZE(factories))
158 return PJMEDIA_EAUD_INVDEV;
159
160 if (factories[f_id].f == NULL)
161 return PJMEDIA_EAUD_INVDEV;
162
163 status = factories[f_id].f->op->default_param(factories[f_id].f,
164 index, param);
165 if (status != PJ_SUCCESS)
166 return status;
167
168 /* Normalize device IDs */
169 if (param->rec_id != PJMEDIA_AUD_DEV_DEFAULT_ID)
170 param->rec_id = MAKE_DEV_ID(f_id, param->rec_id);
171 if (param->play_id != PJMEDIA_AUD_DEV_DEFAULT_ID)
172 param->play_id = MAKE_DEV_ID(f_id, param->play_id);
173
174 return PJ_SUCCESS;
175}
176
177/* API: Open audio stream object using the specified parameters. */
178PJ_DEF(pj_status_t) pjmedia_aud_stream_create(const pjmedia_aud_dev_param *p,
179 pjmedia_aud_rec_cb rec_cb,
180 pjmedia_aud_play_cb play_cb,
181 void *user_data,
182 pjmedia_aud_stream **p_aud_strm)
183{
184 pjmedia_aud_dev_param param;
185 int f_id;
186 pj_status_t status;
187
188 /* Must make copy of param because we're changing device ID */
189 pj_memcpy(&param, p, sizeof(param));
190
191 /* Set default device */
192 if (param.rec_id == PJMEDIA_AUD_DEV_DEFAULT_ID) param.rec_id = 0;
193 if (param.play_id == PJMEDIA_AUD_DEV_DEFAULT_ID) param.play_id = 0;
194
195 if (param.dir & PJMEDIA_DIR_CAPTURE)
196 f_id = GET_FID(param.rec_id);
197 else
198 f_id = GET_FID(param.play_id);
199
200 if (f_id < 0 || f_id >= PJ_ARRAY_SIZE(factories))
201 return PJMEDIA_EAUD_INVDEV;
202
203 /* Normalize device id's */
204 param.rec_id = GET_INDEX(param.rec_id);
205 param.play_id = GET_INDEX(param.play_id);
206
207 if (factories[f_id].f == NULL)
208 return PJMEDIA_EAUD_INVDEV;
209
210 status = factories[f_id].f->op->create_stream(factories[f_id].f,
211 &param, rec_cb, play_cb,
212 user_data, p_aud_strm);
213 if (status != PJ_SUCCESS)
214 return status;
215
216 (*p_aud_strm)->factory = factories[f_id].f;
217 return PJ_SUCCESS;
218}
219
220/* API: Get the running parameters for the specified audio stream. */
221PJ_DEF(pj_status_t) pjmedia_aud_stream_get_param(pjmedia_aud_stream *strm,
222 pjmedia_aud_dev_param *param)
223{
224 pj_status_t status;
225
226 status = strm->op->get_param(strm, param);
227 if (status != PJ_SUCCESS)
228 return status;
229
230 /* Normalize device id's */
231 if (param->rec_id != PJMEDIA_AUD_DEV_DEFAULT_ID)
232 param->rec_id = MAKE_DEV_ID(strm->factory->internal.id, param->rec_id);
233 if (param->play_id != PJMEDIA_AUD_DEV_DEFAULT_ID)
234 param->play_id = MAKE_DEV_ID(strm->factory->internal.id, param->play_id);
235
236 return PJ_SUCCESS;
237}
238
239/* API: Get the value of a specific capability of the audio stream. */
240PJ_DEF(pj_status_t) pjmedia_aud_stream_get_cap(pjmedia_aud_stream *strm,
241 pjmedia_aud_dev_cap cap,
242 void *value)
243{
244 return strm->op->get_cap(strm, cap, value);
245}
246
247/* API: Set the value of a specific capability of the audio stream. */
248PJ_DEF(pj_status_t) pjmedia_aud_stream_set_cap(pjmedia_aud_stream *strm,
249 pjmedia_aud_dev_cap cap,
250 const void *value)
251{
252 return strm->op->set_cap(strm, cap, value);
253}
254
255/* API: Start the stream. */
256PJ_DEF(pj_status_t) pjmedia_aud_stream_start(pjmedia_aud_stream *strm)
257{
258 return strm->op->start(strm);
259}
260
261/* API: Stop the stream. */
262PJ_DEF(pj_status_t) pjmedia_aud_stream_stop(pjmedia_aud_stream *strm)
263{
264 return strm->op->stop(strm);
265}
266
267/* API: Destroy the stream. */
268PJ_DEF(pj_status_t) pjmedia_aud_stream_destroy(pjmedia_aud_stream *strm)
269{
270 return strm->op->destroy(strm);
271}
272
273