diff options
author | Liong Sauw Ming <ming@teluu.com> | 2011-03-11 06:57:24 +0000 |
---|---|---|
committer | Liong Sauw Ming <ming@teluu.com> | 2011-03-11 06:57:24 +0000 |
commit | c44da2d6d7f8a991cd8143f97acda117a4e0a422 (patch) | |
tree | e57adad451551e486fdbb8f4de0b2240978d091d /pjmedia/src/pjmedia-audiodev/alsa_dev.c | |
parent | a71c9ccfea1d7d9e7999037a8ee13820eb0e16e2 (diff) |
Fixed #1204: Support for refreshing audio device list.
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@3438 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjmedia/src/pjmedia-audiodev/alsa_dev.c')
-rw-r--r-- | pjmedia/src/pjmedia-audiodev/alsa_dev.c | 106 |
1 files changed, 80 insertions, 26 deletions
diff --git a/pjmedia/src/pjmedia-audiodev/alsa_dev.c b/pjmedia/src/pjmedia-audiodev/alsa_dev.c index 90eca542..c2cc4e5e 100644 --- a/pjmedia/src/pjmedia-audiodev/alsa_dev.c +++ b/pjmedia/src/pjmedia-audiodev/alsa_dev.c @@ -57,6 +57,7 @@ */ static pj_status_t alsa_factory_init(pjmedia_aud_dev_factory *f); static pj_status_t alsa_factory_destroy(pjmedia_aud_dev_factory *f); +static pj_status_t alsa_factory_refresh(pjmedia_aud_dev_factory *f); static unsigned alsa_factory_get_dev_count(pjmedia_aud_dev_factory *f); static pj_status_t alsa_factory_get_dev_info(pjmedia_aud_dev_factory *f, unsigned index, @@ -92,6 +93,7 @@ struct alsa_factory pjmedia_aud_dev_factory base; pj_pool_factory *pf; pj_pool_t *pool; + pj_pool_t *base_pool; unsigned dev_cnt; pjmedia_aud_dev_info devs[MAX_DEVICES]; @@ -133,7 +135,8 @@ static pjmedia_aud_dev_factory_op alsa_factory_op = &alsa_factory_get_dev_count, &alsa_factory_get_dev_info, &alsa_factory_default_param, - &alsa_factory_create_stream + &alsa_factory_create_stream, + &alsa_factory_refresh }; static pjmedia_aud_stream_op alsa_stream_op = @@ -146,6 +149,20 @@ static pjmedia_aud_stream_op alsa_stream_op = &alsa_stream_destroy }; +static void null_alsa_error_handler (const char *file, + int line, + const char *function, + int err, + const char *fmt, + ...) +{ + PJ_UNUSED_ARG(file); + PJ_UNUSED_ARG(line); + PJ_UNUSED_ARG(function); + PJ_UNUSED_ARG(err); + PJ_UNUSED_ARG(fmt); +} + static void alsa_error_handler (const char *file, int line, const char *function, @@ -174,10 +191,9 @@ static void alsa_error_handler (const char *file, } -static pj_status_t add_dev (struct alsa_factory *af, int card, int device) +static pj_status_t add_dev (struct alsa_factory *af, const char *dev_name) { pjmedia_aud_dev_info *adi; - char dev_name[32]; snd_pcm_t* pcm; int pb_result, ca_result; @@ -186,8 +202,7 @@ static pj_status_t add_dev (struct alsa_factory *af, int card, int device) adi = &af->devs[af->dev_cnt]; - TRACE_((THIS_FILE, "add_dev (%d, %d): Enter", card, device)); - sprintf (dev_name, ALSA_DEVICE_NAME, card, device); + TRACE_((THIS_FILE, "add_dev (%s): Enter", dev_name)); /* Try to open the device in playback mode */ pb_result = snd_pcm_open (&pcm, dev_name, SND_PCM_STREAM_PLAYBACK, 0); @@ -245,10 +260,10 @@ pjmedia_aud_dev_factory* pjmedia_alsa_factory(pj_pool_factory *pf) struct alsa_factory *af; pj_pool_t *pool; - pool = pj_pool_create(pf, "alsa_aud", 256, 256, NULL); + pool = pj_pool_create(pf, "alsa_aud_base", 256, 256, NULL); af = PJ_POOL_ZALLOC_T(pool, struct alsa_factory); af->pf = pf; - af->pool = pool; + af->base_pool = pool; af->base.op = &alsa_factory_op; return &af->base; @@ -258,23 +273,11 @@ pjmedia_aud_dev_factory* pjmedia_alsa_factory(pj_pool_factory *pf) /* API: init factory */ static pj_status_t alsa_factory_init(pjmedia_aud_dev_factory *f) { - struct alsa_factory *af = (struct alsa_factory*)f; - int card, device; - - TRACE_((THIS_FILE, "pjmedia_snd_init: Enumerate sound devices")); - /* Enumerate sound devices */ - for (card=0; card<MAX_SOUND_CARDS; card++) { - for (device=0; device<MAX_SOUND_DEVICES_PER_CARD; device++) { - add_dev(af, card, device); - } - } - - /* Install error handler after enumeration, otherwise we'll get many - * error messages about invalid card/device ID. - */ - snd_lib_error_set_handler (alsa_error_handler); + pj_status_t status = alsa_factory_refresh(f); + if (PJ_SUCCESS != status) + return status; - PJ_LOG(4,(THIS_FILE, "ALSA driver found %d devices", af->dev_cnt)); + PJ_LOG(4,(THIS_FILE, "ALSA initialized")); return PJ_SUCCESS; } @@ -284,9 +287,12 @@ static pj_status_t alsa_factory_destroy(pjmedia_aud_dev_factory *f) { struct alsa_factory *af = (struct alsa_factory*)f; - if (af->pool) { - pj_pool_t *pool = af->pool; - af->pool = NULL; + if (af->pool) + pj_pool_release(af->pool); + + if (af->base_pool) { + pj_pool_t *pool = af->base_pool; + af->base_pool = NULL; pj_pool_release(pool); } @@ -297,6 +303,54 @@ static pj_status_t alsa_factory_destroy(pjmedia_aud_dev_factory *f) } +/* API: refresh the device list */ +static pj_status_t alsa_factory_refresh(pjmedia_aud_dev_factory *f) +{ + struct alsa_factory *af = (struct alsa_factory*)f; + char **hints, **n; + int err; + + TRACE_((THIS_FILE, "pjmedia_snd_init: Enumerate sound devices")); + + if (af->pool != NULL) { + pj_pool_release(af->pool); + af->pool = NULL; + } + + af->pool = pj_pool_create(af->pf, "alsa_aud", 256, 256, NULL); + af->dev_cnt = 0; + + /* Enumerate sound devices */ + err = snd_device_name_hint(-1, "pcm", (void***)&hints); + if (err != 0) + return PJMEDIA_EAUD_SYSERR; + + /* Set a null error handler prior to enumeration to suppress errors */ + snd_lib_error_set_handler(null_alsa_error_handler); + + n = hints; + while (*n != NULL) { + char *name = snd_device_name_get_hint(*n, "NAME"); + if (name != NULL && 0 != strcmp("null", name)) { + add_dev(af, name); + free(name); + } + n++; + } + + /* Install error handler after enumeration, otherwise we'll get many + * error messages about invalid card/device ID. + */ + snd_lib_error_set_handler(alsa_error_handler); + + err = snd_device_name_free_hint((void**)hints); + + PJ_LOG(4,(THIS_FILE, "ALSA driver found %d devices", af->dev_cnt)); + + return PJ_SUCCESS; +} + + /* API: get device count */ static unsigned alsa_factory_get_dev_count(pjmedia_aud_dev_factory *f) { |