1
/* $Id: null_dev.c 3553 2011-05-05 06:14:19Z nanang $ */
3
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
#include <pjmedia-audiodev/audiodev_imp.h>
20
#include <pj/assert.h>
24
#if PJMEDIA_AUDIO_DEV_HAS_NULL_AUDIO
26
#define THIS_FILE "null_dev.c"
28
/* null_audio device info */
29
struct null_audio_dev_info
31
pjmedia_aud_dev_info info;
35
/* null_audio factory */
36
struct null_audio_factory
38
pjmedia_aud_dev_factory base;
43
struct null_audio_dev_info *dev_info;
47
struct null_audio_stream
49
pjmedia_aud_stream base; /**< Base stream */
50
pjmedia_aud_param param; /**< Settings */
51
pj_pool_t *pool; /**< Memory pool. */
53
pjmedia_aud_rec_cb rec_cb; /**< Capture callback. */
54
pjmedia_aud_play_cb play_cb; /**< Playback callback. */
55
void *user_data; /**< Application data. */
60
static pj_status_t null_factory_init(pjmedia_aud_dev_factory *f);
61
static pj_status_t null_factory_destroy(pjmedia_aud_dev_factory *f);
62
static pj_status_t null_factory_refresh(pjmedia_aud_dev_factory *f);
63
static unsigned null_factory_get_dev_count(pjmedia_aud_dev_factory *f);
64
static pj_status_t null_factory_get_dev_info(pjmedia_aud_dev_factory *f,
66
pjmedia_aud_dev_info *info);
67
static pj_status_t null_factory_default_param(pjmedia_aud_dev_factory *f,
69
pjmedia_aud_param *param);
70
static pj_status_t null_factory_create_stream(pjmedia_aud_dev_factory *f,
71
const pjmedia_aud_param *param,
72
pjmedia_aud_rec_cb rec_cb,
73
pjmedia_aud_play_cb play_cb,
75
pjmedia_aud_stream **p_aud_strm);
77
static pj_status_t null_stream_get_param(pjmedia_aud_stream *strm,
78
pjmedia_aud_param *param);
79
static pj_status_t null_stream_get_cap(pjmedia_aud_stream *strm,
80
pjmedia_aud_dev_cap cap,
82
static pj_status_t null_stream_set_cap(pjmedia_aud_stream *strm,
83
pjmedia_aud_dev_cap cap,
85
static pj_status_t null_stream_start(pjmedia_aud_stream *strm);
86
static pj_status_t null_stream_stop(pjmedia_aud_stream *strm);
87
static pj_status_t null_stream_destroy(pjmedia_aud_stream *strm);
90
static pjmedia_aud_dev_factory_op factory_op =
93
&null_factory_destroy,
94
&null_factory_get_dev_count,
95
&null_factory_get_dev_info,
96
&null_factory_default_param,
97
&null_factory_create_stream,
101
static pjmedia_aud_stream_op stream_op =
103
&null_stream_get_param,
104
&null_stream_get_cap,
105
&null_stream_set_cap,
112
/****************************************************************************
116
* Init null_audio audio driver.
118
pjmedia_aud_dev_factory* pjmedia_null_audio_factory(pj_pool_factory *pf)
120
struct null_audio_factory *f;
123
pool = pj_pool_create(pf, "null audio", 1000, 1000, NULL);
124
f = PJ_POOL_ZALLOC_T(pool, struct null_audio_factory);
127
f->base.op = &factory_op;
133
/* API: init factory */
134
static pj_status_t null_factory_init(pjmedia_aud_dev_factory *f)
136
struct null_audio_factory *nf = (struct null_audio_factory*)f;
137
struct null_audio_dev_info *ndi;
139
/* Initialize input and output devices here */
141
nf->dev_info = (struct null_audio_dev_info*)
142
pj_pool_calloc(nf->pool, nf->dev_count,
143
sizeof(struct null_audio_dev_info));
144
ndi = &nf->dev_info[0];
145
pj_bzero(ndi, sizeof(*ndi));
146
strcpy(ndi->info.name, "null device");
147
strcpy(ndi->info.driver, "null");
148
ndi->info.input_count = 1;
149
ndi->info.output_count = 1;
150
ndi->info.default_samples_per_sec = 16000;
151
/* Set the device capabilities here */
154
PJ_LOG(4, (THIS_FILE, "null audio initialized"));
159
/* API: destroy factory */
160
static pj_status_t null_factory_destroy(pjmedia_aud_dev_factory *f)
162
struct null_audio_factory *nf = (struct null_audio_factory*)f;
163
pj_pool_t *pool = nf->pool;
166
pj_pool_release(pool);
171
/* API: refresh the list of devices */
172
static pj_status_t null_factory_refresh(pjmedia_aud_dev_factory *f)
178
/* API: get number of devices */
179
static unsigned null_factory_get_dev_count(pjmedia_aud_dev_factory *f)
181
struct null_audio_factory *nf = (struct null_audio_factory*)f;
182
return nf->dev_count;
185
/* API: get device info */
186
static pj_status_t null_factory_get_dev_info(pjmedia_aud_dev_factory *f,
188
pjmedia_aud_dev_info *info)
190
struct null_audio_factory *nf = (struct null_audio_factory*)f;
192
PJ_ASSERT_RETURN(index < nf->dev_count, PJMEDIA_EAUD_INVDEV);
194
pj_memcpy(info, &nf->dev_info[index].info, sizeof(*info));
199
/* API: create default device parameter */
200
static pj_status_t null_factory_default_param(pjmedia_aud_dev_factory *f,
202
pjmedia_aud_param *param)
204
struct null_audio_factory *nf = (struct null_audio_factory*)f;
205
struct null_audio_dev_info *di = &nf->dev_info[index];
207
PJ_ASSERT_RETURN(index < nf->dev_count, PJMEDIA_EAUD_INVDEV);
209
pj_bzero(param, sizeof(*param));
210
if (di->info.input_count && di->info.output_count) {
211
param->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK;
212
param->rec_id = index;
213
param->play_id = index;
214
} else if (di->info.input_count) {
215
param->dir = PJMEDIA_DIR_CAPTURE;
216
param->rec_id = index;
217
param->play_id = PJMEDIA_AUD_INVALID_DEV;
218
} else if (di->info.output_count) {
219
param->dir = PJMEDIA_DIR_PLAYBACK;
220
param->play_id = index;
221
param->rec_id = PJMEDIA_AUD_INVALID_DEV;
223
return PJMEDIA_EAUD_INVDEV;
226
/* Set the mandatory settings here */
227
/* The values here are just some examples */
228
param->clock_rate = di->info.default_samples_per_sec;
229
param->channel_count = 1;
230
param->samples_per_frame = di->info.default_samples_per_sec * 20 / 1000;
231
param->bits_per_sample = 16;
233
/* Set the device capabilities here */
239
/* API: create stream */
240
static pj_status_t null_factory_create_stream(pjmedia_aud_dev_factory *f,
241
const pjmedia_aud_param *param,
242
pjmedia_aud_rec_cb rec_cb,
243
pjmedia_aud_play_cb play_cb,
245
pjmedia_aud_stream **p_aud_strm)
247
struct null_audio_factory *nf = (struct null_audio_factory*)f;
249
struct null_audio_stream *strm;
251
/* Create and Initialize stream descriptor */
252
pool = pj_pool_create(nf->pf, "null_audio-dev", 1000, 1000, NULL);
253
PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM);
255
strm = PJ_POOL_ZALLOC_T(pool, struct null_audio_stream);
256
pj_memcpy(&strm->param, param, sizeof(*param));
258
strm->rec_cb = rec_cb;
259
strm->play_cb = play_cb;
260
strm->user_data = user_data;
262
/* Create player stream here */
263
if (param->dir & PJMEDIA_DIR_PLAYBACK) {
266
/* Create capture stream here */
267
if (param->dir & PJMEDIA_DIR_CAPTURE) {
270
/* Apply the remaining settings */
271
/* Below is an example if you want to set the output volume */
272
if (param->flags & PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING) {
273
null_stream_set_cap(&strm->base,
274
PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING,
279
strm->base.op = &stream_op;
280
*p_aud_strm = &strm->base;
285
/* API: Get stream info. */
286
static pj_status_t null_stream_get_param(pjmedia_aud_stream *s,
287
pjmedia_aud_param *pi)
289
struct null_audio_stream *strm = (struct null_audio_stream*)s;
291
PJ_ASSERT_RETURN(strm && pi, PJ_EINVAL);
293
pj_memcpy(pi, &strm->param, sizeof(*pi));
295
/* Example: Update the volume setting */
296
if (null_stream_get_cap(s, PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING,
297
&pi->output_vol) == PJ_SUCCESS)
299
pi->flags |= PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING;
305
/* API: get capability */
306
static pj_status_t null_stream_get_cap(pjmedia_aud_stream *s,
307
pjmedia_aud_dev_cap cap,
310
struct null_audio_stream *strm = (struct null_audio_stream*)s;
314
PJ_ASSERT_RETURN(s && pval, PJ_EINVAL);
316
/* Example: Get the output's volume setting */
317
if (cap==PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING)
319
/* Output volume setting */
320
*(unsigned*)pval = 0; // retrieve output device's volume here
323
return PJMEDIA_EAUD_INVCAP;
327
/* API: set capability */
328
static pj_status_t null_stream_set_cap(pjmedia_aud_stream *s,
329
pjmedia_aud_dev_cap cap,
332
struct null_audio_stream *strm = (struct null_audio_stream*)s;
336
PJ_ASSERT_RETURN(s && pval, PJ_EINVAL);
339
if (cap==PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING)
341
/* Output volume setting */
342
// set output's volume level here
346
return PJMEDIA_EAUD_INVCAP;
349
/* API: Start stream. */
350
static pj_status_t null_stream_start(pjmedia_aud_stream *strm)
352
struct null_audio_stream *stream = (struct null_audio_stream*)strm;
354
PJ_UNUSED_ARG(stream);
356
PJ_LOG(4, (THIS_FILE, "Starting null audio stream"));
361
/* API: Stop stream. */
362
static pj_status_t null_stream_stop(pjmedia_aud_stream *strm)
364
struct null_audio_stream *stream = (struct null_audio_stream*)strm;
366
PJ_UNUSED_ARG(stream);
368
PJ_LOG(4, (THIS_FILE, "Stopping null audio stream"));
374
/* API: Destroy stream. */
375
static pj_status_t null_stream_destroy(pjmedia_aud_stream *strm)
377
struct null_audio_stream *stream = (struct null_audio_stream*)strm;
379
PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL);
381
null_stream_stop(strm);
383
pj_pool_release(stream->pool);
388
#endif /* PJMEDIA_AUDIO_DEV_HAS_NULL_AUDIO */