Changeset 3438


Ignore:
Timestamp:
Mar 11, 2011 6:57:24 AM (14 years ago)
Author:
ming
Message:

Fixed #1204: Support for refreshing audio device list.

Location:
pjproject/trunk
Files:
15 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/include/pjmedia-audiodev/audiodev.h

    r3327 r3438  
    544544PJ_DECL(pj_status_t) 
    545545pjmedia_aud_unregister_factory(pjmedia_aud_dev_factory_create_func_ptr adf); 
     546 
     547 
     548/** 
     549 * Refresh the list of sound devices installed in the system. This function 
     550 * will only refresh the list of audio device so all active audio streams will 
     551 * be unaffected. After refreshing the device list, application MUST make sure 
     552 * to update all index references to audio devices (i.e. all variables of type 
     553 * pjmedia_aud_dev_index) before calling any function that accepts audio device 
     554 * index as its parameter. 
     555 * 
     556 * @return              PJ_SUCCESS on successful operation or the appropriate 
     557 *                      error code. 
     558 */ 
     559PJ_DECL(pj_status_t) pjmedia_aud_dev_refresh(void); 
    546560 
    547561 
  • pjproject/trunk/pjmedia/include/pjmedia-audiodev/audiodev_imp.h

    r2506 r3438  
    9393                                 pjmedia_aud_stream **p_aud_strm); 
    9494 
     95    /** 
     96     * Refresh the list of audio devices installed in the system. 
     97     * 
     98     * @param f         The audio device factory. 
     99     */ 
     100    pj_status_t (*refresh)(pjmedia_aud_dev_factory *f); 
     101 
    95102} pjmedia_aud_dev_factory_op; 
    96103 
  • pjproject/trunk/pjmedia/include/pjmedia/sound_port.h

    r2506 r3438  
    6262  
    6363 */ 
     64 
     65/** 
     66 * Sound port options. 
     67 */ 
     68enum pjmedia_snd_port_option 
     69{ 
     70    /**  
     71     * Don't start the audio device when creating a sound port. 
     72     */     
     73    PJMEDIA_SND_PORT_NO_AUTO_START = 1 
     74}; 
     75 
     76/** 
     77 * This structure specifies the parameters to create the sound port. 
     78 */ 
     79typedef struct pjmedia_snd_port_param 
     80{ 
     81    /** 
     82     * Base structure. 
     83     */ 
     84    pjmedia_aud_param base; 
     85     
     86    /** 
     87     * Sound port creation options. 
     88     */ 
     89    unsigned options; 
     90} pjmedia_snd_port_param; 
    6491 
    6592/** 
     
    87114 * @param bits_per_sample   Set the number of bits per sample. The normal  
    88115 *                          value for this parameter is 16 bits per sample. 
    89  * @param options           Options flag, currently must be zero. 
     116 * @param options           Options flag. 
    90117 * @param p_port            Pointer to receive the sound device port instance. 
    91118 * 
     
    117144 * @param bits_per_sample   Set the number of bits per sample. The normal  
    118145 *                          value for this parameter is 16 bits per sample. 
    119  * @param options           Options flag, currently must be zero. 
     146 * @param options           Options flag. 
    120147 * @param p_port            Pointer to receive the sound device port instance. 
    121148 * 
     
    146173 * @param bits_per_sample   Set the number of bits per sample. The normal  
    147174 *                          value for this parameter is 16 bits per sample. 
    148  * @param options           Options flag, currently must be zero. 
     175 * @param options           Options flag. 
    149176 * @param p_port            Pointer to receive the sound device port instance. 
    150177 * 
     
    166193 * 
    167194 * @param pool              Pool to allocate sound port structure. 
    168  * @param prm               Sound device settings. 
     195 * @param prm               Sound port parameter. 
    169196 * @param p_port            Pointer to receive the sound device port instance. 
    170197 * 
     
    173200 */ 
    174201PJ_DECL(pj_status_t) pjmedia_snd_port_create2(pj_pool_t *pool, 
    175                                               const pjmedia_aud_param *prm, 
     202                                              const pjmedia_snd_port_param *prm, 
    176203                                              pjmedia_snd_port **p_port); 
    177204 
  • pjproject/trunk/pjmedia/src/pjmedia-audiodev/alsa_dev.c

    r3079 r3438  
    5858static pj_status_t alsa_factory_init(pjmedia_aud_dev_factory *f); 
    5959static pj_status_t alsa_factory_destroy(pjmedia_aud_dev_factory *f); 
     60static pj_status_t alsa_factory_refresh(pjmedia_aud_dev_factory *f); 
    6061static unsigned    alsa_factory_get_dev_count(pjmedia_aud_dev_factory *f); 
    6162static pj_status_t alsa_factory_get_dev_info(pjmedia_aud_dev_factory *f, 
     
    9394    pj_pool_factory             *pf; 
    9495    pj_pool_t                   *pool; 
     96    pj_pool_t                   *base_pool; 
    9597 
    9698    unsigned                     dev_cnt; 
     
    134136    &alsa_factory_get_dev_info, 
    135137    &alsa_factory_default_param, 
    136     &alsa_factory_create_stream 
     138    &alsa_factory_create_stream, 
     139    &alsa_factory_refresh 
    137140}; 
    138141 
     
    146149    &alsa_stream_destroy 
    147150}; 
     151 
     152static void null_alsa_error_handler (const char *file, 
     153                                int line, 
     154                                const char *function, 
     155                                int err, 
     156                                const char *fmt, 
     157                                ...) 
     158{ 
     159    PJ_UNUSED_ARG(file); 
     160    PJ_UNUSED_ARG(line); 
     161    PJ_UNUSED_ARG(function); 
     162    PJ_UNUSED_ARG(err); 
     163    PJ_UNUSED_ARG(fmt); 
     164} 
    148165 
    149166static void alsa_error_handler (const char *file, 
     
    175192 
    176193 
    177 static pj_status_t add_dev (struct alsa_factory *af, int card, int device) 
     194static pj_status_t add_dev (struct alsa_factory *af, const char *dev_name) 
    178195{ 
    179196    pjmedia_aud_dev_info *adi; 
    180     char dev_name[32]; 
    181197    snd_pcm_t* pcm; 
    182198    int pb_result, ca_result; 
     
    187203    adi = &af->devs[af->dev_cnt]; 
    188204 
    189     TRACE_((THIS_FILE, "add_dev (%d, %d): Enter", card, device)); 
    190     sprintf (dev_name, ALSA_DEVICE_NAME, card, device); 
     205    TRACE_((THIS_FILE, "add_dev (%s): Enter", dev_name)); 
    191206 
    192207    /* Try to open the device in playback mode */ 
     
    246261    pj_pool_t *pool; 
    247262 
    248     pool = pj_pool_create(pf, "alsa_aud", 256, 256, NULL); 
     263    pool = pj_pool_create(pf, "alsa_aud_base", 256, 256, NULL); 
    249264    af = PJ_POOL_ZALLOC_T(pool, struct alsa_factory); 
    250265    af->pf = pf; 
    251     af->pool = pool; 
     266    af->base_pool = pool; 
    252267    af->base.op = &alsa_factory_op; 
    253268 
     
    259274static pj_status_t alsa_factory_init(pjmedia_aud_dev_factory *f) 
    260275{ 
     276    pj_status_t status = alsa_factory_refresh(f); 
     277    if (PJ_SUCCESS != status) 
     278        return status; 
     279 
     280    PJ_LOG(4,(THIS_FILE, "ALSA initialized")); 
     281    return PJ_SUCCESS; 
     282} 
     283 
     284 
     285/* API: destroy factory */ 
     286static pj_status_t alsa_factory_destroy(pjmedia_aud_dev_factory *f) 
     287{ 
    261288    struct alsa_factory *af = (struct alsa_factory*)f; 
    262     int card, device; 
     289 
     290    if (af->pool) 
     291        pj_pool_release(af->pool); 
     292 
     293    if (af->base_pool) { 
     294        pj_pool_t *pool = af->base_pool; 
     295        af->base_pool = NULL; 
     296        pj_pool_release(pool); 
     297    } 
     298 
     299    /* Restore handler */ 
     300    snd_lib_error_set_handler(NULL); 
     301 
     302    return PJ_SUCCESS; 
     303} 
     304 
     305 
     306/* API: refresh the device list */ 
     307static pj_status_t alsa_factory_refresh(pjmedia_aud_dev_factory *f) 
     308{ 
     309    struct alsa_factory *af = (struct alsa_factory*)f; 
     310    char **hints, **n; 
     311    int err; 
    263312 
    264313    TRACE_((THIS_FILE, "pjmedia_snd_init: Enumerate sound devices")); 
     314 
     315    if (af->pool != NULL) { 
     316        pj_pool_release(af->pool); 
     317        af->pool = NULL; 
     318    } 
     319 
     320    af->pool = pj_pool_create(af->pf, "alsa_aud", 256, 256, NULL); 
     321    af->dev_cnt = 0; 
     322 
    265323    /* Enumerate sound devices */ 
    266     for (card=0; card<MAX_SOUND_CARDS; card++) { 
    267         for (device=0; device<MAX_SOUND_DEVICES_PER_CARD; device++) { 
    268             add_dev(af, card, device); 
     324    err = snd_device_name_hint(-1, "pcm", (void***)&hints); 
     325    if (err != 0) 
     326        return PJMEDIA_EAUD_SYSERR; 
     327 
     328    /* Set a null error handler prior to enumeration to suppress errors */ 
     329    snd_lib_error_set_handler(null_alsa_error_handler); 
     330 
     331    n = hints; 
     332    while (*n != NULL) { 
     333        char *name = snd_device_name_get_hint(*n, "NAME"); 
     334        if (name != NULL && 0 != strcmp("null", name)) { 
     335            add_dev(af, name); 
     336            free(name); 
    269337        } 
     338        n++; 
    270339    } 
    271340 
     
    273342     * error messages about invalid card/device ID. 
    274343     */ 
    275     snd_lib_error_set_handler (alsa_error_handler); 
     344    snd_lib_error_set_handler(alsa_error_handler); 
     345 
     346    err = snd_device_name_free_hint((void**)hints); 
    276347 
    277348    PJ_LOG(4,(THIS_FILE, "ALSA driver found %d devices", af->dev_cnt)); 
    278     return PJ_SUCCESS; 
    279 } 
    280  
    281  
    282 /* API: destroy factory */ 
    283 static pj_status_t alsa_factory_destroy(pjmedia_aud_dev_factory *f) 
    284 { 
    285     struct alsa_factory *af = (struct alsa_factory*)f; 
    286  
    287     if (af->pool) { 
    288         pj_pool_t *pool = af->pool; 
    289         af->pool = NULL; 
    290         pj_pool_release(pool); 
    291     } 
    292  
    293     /* Restore handler */ 
    294     snd_lib_error_set_handler(NULL); 
    295349 
    296350    return PJ_SUCCESS; 
  • pjproject/trunk/pjmedia/src/pjmedia-audiodev/audiodev.c

    r3262 r3438  
    492492} 
    493493 
     494/* API: Refresh the list of sound devices installed in the system. */ 
     495PJ_DEF(pj_status_t) pjmedia_aud_dev_refresh(void) 
     496{ 
     497    unsigned i; 
     498     
     499    for (i=0; i<aud_subsys.drv_cnt; ++i) { 
     500        struct driver *drv = &aud_subsys.drv[i]; 
     501         
     502        if (drv->f && drv->f->op->refresh) { 
     503            pj_status_t status = drv->f->op->refresh(drv->f); 
     504            if (status != PJ_SUCCESS) { 
     505                PJ_PERROR(4, (THIS_FILE, status, "Unable to refresh device " 
     506                                                 "list for %s", drv->name)); 
     507            } 
     508        } 
     509    } 
     510    return PJ_SUCCESS; 
     511} 
     512 
    494513/* API: Get the number of sound devices installed in the system. */ 
    495514PJ_DEF(unsigned) pjmedia_aud_dev_count(void) 
  • pjproject/trunk/pjmedia/src/pjmedia-audiodev/coreaudio_dev.c

    r3422 r3438  
    179179    &ca_factory_get_dev_info, 
    180180    &ca_factory_default_param, 
    181     &ca_factory_create_stream 
     181    &ca_factory_create_stream, 
     182    &ca_factory_refresh 
    182183}; 
    183184 
  • pjproject/trunk/pjmedia/src/pjmedia-audiodev/legacy_dev.c

    r2506 r3438  
    5252static pj_status_t factory_init(pjmedia_aud_dev_factory *f); 
    5353static pj_status_t factory_destroy(pjmedia_aud_dev_factory *f); 
     54static pj_status_t factory_refresh(pjmedia_aud_dev_factory *f); 
    5455static unsigned    factory_get_dev_count(pjmedia_aud_dev_factory *f); 
    5556static pj_status_t factory_get_dev_info(pjmedia_aud_dev_factory *f,  
     
    8788    &factory_get_dev_info, 
    8889    &factory_default_param, 
    89     &factory_create_stream 
     90    &factory_create_stream, 
     91    &factory_refresh 
    9092}; 
    9193 
     
    146148 
    147149    return status; 
     150} 
     151 
     152/* API: refresh the list of devices */ 
     153static pj_status_t factory_refresh(pjmedia_aud_dev_factory *f) 
     154{ 
     155    PJ_UNUSED_ARG(f); 
     156    return PJ_ENOTSUP; 
    148157} 
    149158 
  • pjproject/trunk/pjmedia/src/pjmedia-audiodev/null_dev.c

    r3103 r3438  
    6060static pj_status_t null_factory_init(pjmedia_aud_dev_factory *f); 
    6161static pj_status_t null_factory_destroy(pjmedia_aud_dev_factory *f); 
     62static pj_status_t null_factory_refresh(pjmedia_aud_dev_factory *f); 
    6263static unsigned    null_factory_get_dev_count(pjmedia_aud_dev_factory *f); 
    6364static pj_status_t null_factory_get_dev_info(pjmedia_aud_dev_factory *f, 
     
    9495    &null_factory_get_dev_info, 
    9596    &null_factory_default_param, 
    96     &null_factory_create_stream 
     97    &null_factory_create_stream, 
     98    &null_factory_refresh 
    9799}; 
    98100 
     
    164166    pj_pool_release(pool); 
    165167 
     168    return PJ_SUCCESS; 
     169} 
     170 
     171/* API: refresh the list of devices */ 
     172static pj_status_t null_factory_refresh(pjmedia_aud_dev_factory *f) 
     173{ 
     174    PJ_UNUSED_ARG(f); 
    166175    return PJ_SUCCESS; 
    167176} 
  • pjproject/trunk/pjmedia/src/pjmedia-audiodev/pa_dev.c

    r3404 r3438  
    107107static pj_status_t  pa_init(pjmedia_aud_dev_factory *f); 
    108108static pj_status_t  pa_destroy(pjmedia_aud_dev_factory *f); 
     109static pj_status_t  pa_refresh(pjmedia_aud_dev_factory *f); 
    109110static unsigned     pa_get_dev_count(pjmedia_aud_dev_factory *f); 
    110111static pj_status_t  pa_get_dev_info(pjmedia_aud_dev_factory *f,  
     
    142143    &pa_get_dev_info, 
    143144    &pa_default_param, 
    144     &pa_create_stream 
     145    &pa_create_stream, 
     146    &pa_refresh     
    145147}; 
    146148 
     
    485487     
    486488    return err ? PJMEDIA_AUDIODEV_ERRNO_FROM_PORTAUDIO(err) : PJ_SUCCESS; 
     489} 
     490 
     491 
     492/* API: Refresh the device list. */ 
     493static pj_status_t pa_refresh(pjmedia_aud_dev_factory *f) 
     494{ 
     495    PJ_UNUSED_ARG(f); 
     496    return PJ_ENOTSUP; 
    487497} 
    488498 
  • pjproject/trunk/pjmedia/src/pjmedia-audiodev/symb_aps_dev.cpp

    r3136 r3438  
    121121static pj_status_t factory_init(pjmedia_aud_dev_factory *f); 
    122122static pj_status_t factory_destroy(pjmedia_aud_dev_factory *f); 
     123static pj_status_t factory_refresh(pjmedia_aud_dev_factory *f); 
    123124static unsigned    factory_get_dev_count(pjmedia_aud_dev_factory *f); 
    124125static pj_status_t factory_get_dev_info(pjmedia_aud_dev_factory *f,  
     
    156157    &factory_get_dev_info, 
    157158    &factory_default_param, 
    158     &factory_create_stream 
     159    &factory_create_stream, 
     160    &factory_refresh 
    159161}; 
    160162 
     
    14451447} 
    14461448 
     1449/* API: refresh the device list */ 
     1450static pj_status_t factory_refresh(pjmedia_aud_dev_factory *f) 
     1451{ 
     1452    PJ_UNUSED_ARG(f); 
     1453    return PJ_ENOTSUP; 
     1454} 
     1455 
    14471456/* API: get number of devices */ 
    14481457static unsigned factory_get_dev_count(pjmedia_aud_dev_factory *f) 
  • pjproject/trunk/pjmedia/src/pjmedia-audiodev/symb_mda_dev.cpp

    r2777 r3438  
    8686static pj_status_t factory_init(pjmedia_aud_dev_factory *f); 
    8787static pj_status_t factory_destroy(pjmedia_aud_dev_factory *f); 
     88static pj_status_t factory_refresh(pjmedia_aud_dev_factory *f); 
    8889static unsigned    factory_get_dev_count(pjmedia_aud_dev_factory *f); 
    8990static pj_status_t factory_get_dev_info(pjmedia_aud_dev_factory *f,  
     
    121122    &factory_get_dev_info, 
    122123    &factory_default_param, 
    123     &factory_create_stream 
     124    &factory_create_stream, 
     125    &factory_refresh 
    124126}; 
    125127 
     
    833835     
    834836    return PJ_SUCCESS; 
     837} 
     838 
     839/* API: refresh the device list */ 
     840static pj_status_t factory_refresh(pjmedia_aud_dev_factory *f) 
     841{ 
     842    PJ_UNUSED_ARG(f); 
     843    return PJ_ENOTSUP; 
    835844} 
    836845 
  • pjproject/trunk/pjmedia/src/pjmedia-audiodev/symb_vas_dev.cpp

    r3201 r3438  
    131131static pj_status_t factory_init(pjmedia_aud_dev_factory *f); 
    132132static pj_status_t factory_destroy(pjmedia_aud_dev_factory *f); 
     133static pj_status_t factory_refresh(pjmedia_aud_dev_factory *f); 
    133134static unsigned    factory_get_dev_count(pjmedia_aud_dev_factory *f); 
    134135static pj_status_t factory_get_dev_info(pjmedia_aud_dev_factory *f,  
     
    166167    &factory_get_dev_info, 
    167168    &factory_default_param, 
    168     &factory_create_stream 
     169    &factory_create_stream, 
     170    &factory_refresh 
    169171}; 
    170172 
     
    14771479} 
    14781480 
     1481/* API: refresh the device list */ 
     1482static pj_status_t factory_refresh(pjmedia_aud_dev_factory *f) 
     1483{ 
     1484    PJ_UNUSED_ARG(f); 
     1485    return PJ_ENOTSUP; 
     1486} 
     1487 
    14791488/* API: get number of devices */ 
    14801489static unsigned factory_get_dev_count(pjmedia_aud_dev_factory *f) 
  • pjproject/trunk/pjmedia/src/pjmedia-audiodev/wmme_dev.c

    r2941 r3438  
    3939#endif 
    4040 
     41#ifndef PJMEDIA_WMME_DEV_USE_MMDEVICE_API 
     42#   define PJMEDIAWMME_DEV_USE_MMDEVICE_API \ 
     43           (defined(_WIN32_WINNT) && (_WIN32_WINNT>=0x0600)) 
     44#endif 
     45 
     46#if PJMEDIA_WMME_DEV_USE_MMDEVICE_API != 0 
     47#   define DRV_QUERYFUNCTIONINSTANCEID     (DRV_RESERVED + 17) 
     48#   define DRV_QUERYFUNCTIONINSTANCEIDSIZE (DRV_RESERVED + 18) 
     49#endif 
     50 
    4151/* mingw lacks WAVE_FORMAT_ALAW/MULAW */ 
    4252#ifndef WAVE_FORMAT_ALAW 
     
    6171    pjmedia_aud_dev_info         info; 
    6272    unsigned                     deviceId; 
     73    const wchar_t               *endpointId; 
    6374}; 
    6475 
     
    6778{ 
    6879    pjmedia_aud_dev_factory      base; 
     80    pj_pool_t                   *base_pool; 
    6981    pj_pool_t                   *pool; 
    7082    pj_pool_factory             *pf; 
     
    122134static pj_status_t factory_init(pjmedia_aud_dev_factory *f); 
    123135static pj_status_t factory_destroy(pjmedia_aud_dev_factory *f); 
     136static pj_status_t factory_refresh(pjmedia_aud_dev_factory *f); 
    124137static unsigned    factory_get_dev_count(pjmedia_aud_dev_factory *f); 
    125138static pj_status_t factory_get_dev_info(pjmedia_aud_dev_factory *f,  
     
    157170    &factory_get_dev_info, 
    158171    &factory_default_param, 
    159     &factory_create_stream 
     172    &factory_create_stream, 
     173    &factory_refresh 
    160174}; 
    161175 
     
    182196    pj_pool_t *pool; 
    183197 
    184     pool = pj_pool_create(pf, "WMME", 1000, 1000, NULL); 
     198    pool = pj_pool_create(pf, "WMME base", 1000, 1000, NULL); 
    185199    f = PJ_POOL_ZALLOC_T(pool, struct wmme_factory); 
    186200    f->pf = pf; 
    187     f->pool = pool; 
     201    f->base_pool = pool; 
    188202    f->base.op = &factory_op; 
    189203 
     
    191205} 
    192206 
     207/* Internal: Windows Vista and Windows 7 have their device 
     208 * names truncated when using the waveXXX api.  The names 
     209 * should be acquired from the MMDevice APIs 
     210 */ 
     211#if PJMEDIA_WMME_DEV_USE_MMDEVICE_API != 0 
     212 
     213#define COBJMACROS 
     214#include <mmdeviceapi.h> 
     215#define INITGUID 
     216#include <Guiddef.h> 
     217#include <FunctionDiscoveryKeys_devpkey.h> 
     218 
     219DEFINE_GUID(CLSID_MMDeviceEnumerator, 0xBCDE0395, 0xE52F, 0x467C, 
     220            0x8E, 0x3D, 0xC4, 0x57, 0x92, 0x91, 0x69, 0x2E); 
     221DEFINE_GUID(IID_IMMDeviceEnumerator, 0xA95664D2, 0x9614, 0x4F35, 
     222            0xA7, 0x46, 0xDE, 0x8D, 0xB6, 0x36, 0x17, 0xE6); 
     223 
     224static void get_dev_names(pjmedia_aud_dev_factory *f) 
     225{ 
     226    struct wmme_factory *wf = (struct wmme_factory*)f; 
     227    HRESULT              coinit = S_OK; 
     228    HRESULT              hr = S_OK; 
     229    IMMDeviceEnumerator *pEnumerator = NULL; 
     230    IMMDeviceCollection *pDevices = NULL; 
     231    UINT                 cDevices = 0; 
     232    UINT                 nDevice = 0; 
     233 
     234    coinit = CoInitializeEx(NULL, COINIT_MULTITHREADED); 
     235    if (coinit == RPC_E_CHANGED_MODE) 
     236        coinit = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 
     237    if (FAILED(coinit)) 
     238        goto on_error; 
     239 
     240    hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, 
     241                          CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, 
     242                          (void**)&pEnumerator); 
     243    if (FAILED(hr)) 
     244        goto on_error; 
     245    hr = IMMDeviceEnumerator_EnumAudioEndpoints(pEnumerator, eAll, 
     246                                                DEVICE_STATE_ACTIVE, 
     247                                                &pDevices); 
     248    if (FAILED(hr)) 
     249        goto on_error; 
     250    hr = IMMDeviceCollection_GetCount(pDevices, &cDevices); 
     251    if (FAILED(hr)) 
     252        goto on_error; 
     253 
     254    for (nDevice = 0; nDevice < cDevices; ++nDevice) { 
     255        IMMDevice      *pDevice = NULL; 
     256        IPropertyStore *pProps = NULL; 
     257        LPWSTR          pwszID = NULL; 
     258        PROPVARIANT     varName; 
     259        unsigned        i; 
     260 
     261        PropVariantInit(&varName); 
     262 
     263        hr = IMMDeviceCollection_Item(pDevices, nDevice, &pDevice); 
     264        if (FAILED(hr)) 
     265            goto cleanup; 
     266        hr = IMMDevice_GetId(pDevice, &pwszID); 
     267        if (FAILED(hr)) 
     268            goto cleanup; 
     269        hr = IMMDevice_OpenPropertyStore(pDevice, STGM_READ, &pProps); 
     270        if (FAILED(hr)) 
     271            goto cleanup; 
     272        hr = IPropertyStore_GetValue(pProps, &PKEY_Device_FriendlyName, 
     273                                     &varName); 
     274        if (FAILED(hr)) 
     275            goto cleanup; 
     276 
     277        for (i = 0; i < wf->dev_count; ++i) { 
     278            if (0 == wcscmp(wf->dev_info[i].endpointId, pwszID)) { 
     279                wcstombs(wf->dev_info[i].info.name, varName.pwszVal, 
     280                         sizeof(wf->dev_info[i].info.name)); 
     281                break; 
     282            } 
     283        } 
     284 
     285        PropVariantClear(&varName); 
     286 
     287    cleanup: 
     288        if (pProps) 
     289            IPropertyStore_Release(pProps); 
     290        if (pwszID) 
     291            CoTaskMemFree(pwszID); 
     292        if (pDevice) 
     293            hr = IMMDevice_Release(pDevice); 
     294    } 
     295 
     296on_error: 
     297    if (pDevices) 
     298        hr = IMMDeviceCollection_Release(pDevices); 
     299 
     300    if (pEnumerator) 
     301        hr = IMMDeviceEnumerator_Release(pEnumerator); 
     302 
     303    if (SUCCEEDED(coinit)) 
     304        CoUninitialize(); 
     305} 
     306 
     307#else 
     308 
     309static void get_dev_names(pjmedia_aud_dev_factory *f) 
     310{ 
     311    PJ_UNUSED_ARG(f); 
     312} 
     313 
     314#endif 
    193315 
    194316/* Internal: build device info from WAVEINCAPS/WAVEOUTCAPS */ 
     
    262384static pj_status_t factory_init(pjmedia_aud_dev_factory *f) 
    263385{ 
     386    pj_status_t ret = factory_refresh(f); 
     387    if (ret != PJ_SUCCESS) 
     388        return ret; 
     389 
     390    PJ_LOG(4, (THIS_FILE, "WMME initialized")); 
     391    return PJ_SUCCESS; 
     392} 
     393 
     394/* API: refresh the device list */ 
     395static pj_status_t factory_refresh(pjmedia_aud_dev_factory *f) 
     396{ 
    264397    struct wmme_factory *wf = (struct wmme_factory*)f; 
    265398    unsigned c; 
     
    268401    pj_bool_t waveMapperAdded = PJ_FALSE; 
    269402 
     403    if (wf->pool != NULL) { 
     404        pj_pool_release(wf->pool); 
     405        wf->pool = NULL; 
     406    } 
     407 
    270408    /* Enumerate sound devices */ 
    271409    wf->dev_count = 0; 
     410    wf->pool = pj_pool_create(wf->pf, "WMME", 1000, 1000, NULL); 
    272411 
    273412    inputDeviceCount = waveInGetNumDevs(); 
     
    315454                build_dev_info(WAVE_MAPPER, &wf->dev_info[wf->dev_count],  
    316455                               &wic, &woc); 
     456                wf->dev_info[wf->dev_count].endpointId = L""; 
    317457                ++wf->dev_count; 
    318458                waveMapperAdded = PJ_TRUE; 
     
    328468            WAVEINCAPS wic; 
    329469            MMRESULT mr; 
     470            DWORD cbEndpointId; 
    330471 
    331472            pj_bzero(&wic, sizeof(WAVEINCAPS)); 
     
    341482            build_dev_info(uDeviceID, &wf->dev_info[wf->dev_count],  
    342483                           &wic, NULL); 
     484 
     485#if PJMEDIA_WMME_DEV_USE_MMDEVICE_API != 0 
     486            /* Try to get the endpoint id of the audio device */ 
     487            wf->dev_info[wf->dev_count].endpointId = L""; 
     488 
     489            mr = waveInMessage((HWAVEIN)IntToPtr(uDeviceID), 
     490                               DRV_QUERYFUNCTIONINSTANCEIDSIZE, 
     491                               (DWORD_PTR)&cbEndpointId, (DWORD_PTR)NULL); 
     492            if (mr == MMSYSERR_NOERROR) { 
     493                const wchar_t **epid = &wf->dev_info[wf->dev_count].endpointId; 
     494                *epid = (const wchar_t*) pj_pool_calloc(wf->pool, 
     495                                                        cbEndpointId, 1); 
     496                mr = waveInMessage((HWAVEIN)IntToPtr(uDeviceID), 
     497                                   DRV_QUERYFUNCTIONINSTANCEID, 
     498                                   (DWORD_PTR)*epid, 
     499                                   cbEndpointId); 
     500            } 
     501#else 
     502            PJ_UNUSED_ARG(cbEndpointId); 
     503#endif 
     504 
    343505            ++wf->dev_count; 
    344506        } 
     
    352514            WAVEOUTCAPS woc; 
    353515            MMRESULT mr; 
     516            DWORD cbEndpointId; 
    354517 
    355518            pj_bzero(&woc, sizeof(WAVEOUTCAPS)); 
     
    365528            build_dev_info(uDeviceID, &wf->dev_info[wf->dev_count],  
    366529                           NULL, &woc); 
     530 
     531#if PJMEDIA_WMME_DEV_USE_MMDEVICE_API != 0 
     532            /* Try to get the endpoint id of the audio device */ 
     533            wf->dev_info[wf->dev_count].endpointId = L""; 
     534 
     535            mr = waveOutMessage((HWAVEOUT)IntToPtr(uDeviceID), 
     536                                DRV_QUERYFUNCTIONINSTANCEIDSIZE, 
     537                                (DWORD_PTR)&cbEndpointId, (DWORD_PTR)NULL); 
     538            if (mr == MMSYSERR_NOERROR) { 
     539                const wchar_t **epid = &wf->dev_info[wf->dev_count].endpointId; 
     540                *epid = (const wchar_t*)pj_pool_calloc(wf->pool, 
     541                                                       cbEndpointId, 1); 
     542                mr = waveOutMessage((HWAVEOUT)IntToPtr(uDeviceID), 
     543                                    DRV_QUERYFUNCTIONINSTANCEID, 
     544                                    (DWORD_PTR)*epid, cbEndpointId); 
     545            } 
     546#else 
     547            PJ_UNUSED_ARG(cbEndpointId); 
     548#endif 
     549 
    367550            ++wf->dev_count; 
    368551        } 
    369552    } 
    370553 
    371     PJ_LOG(4, (THIS_FILE, "WMME initialized, found %d devices:",  
     554    /* On Windows Vista and Windows 7 get the full device names */ 
     555    get_dev_names(f); 
     556 
     557    PJ_LOG(4, (THIS_FILE, "WMME found %d devices:", 
    372558               wf->dev_count)); 
    373559    for (c = 0; c < wf->dev_count; ++c) { 
     
    386572{ 
    387573    struct wmme_factory *wf = (struct wmme_factory*)f; 
    388     pj_pool_t *pool = wf->pool; 
    389  
    390     wf->pool = NULL; 
     574    pj_pool_t *pool = wf->base_pool; 
     575 
     576    pj_pool_release(wf->pool); 
     577    wf->base_pool = NULL; 
    391578    pj_pool_release(pool); 
    392579 
  • pjproject/trunk/pjmedia/src/pjmedia/sound_port.c

    r3115 r3438  
    4949    unsigned             samples_per_frame; 
    5050    unsigned             bits_per_sample; 
     51    unsigned             options; 
    5152 
    5253    /* software ec */ 
     
    278279 
    279280    /* Start sound stream. */ 
    280     status = pjmedia_aud_stream_start(snd_port->aud_stream); 
     281    if (!(snd_port->options & PJMEDIA_SND_PORT_NO_AUTO_START)) { 
     282        status = pjmedia_aud_stream_start(snd_port->aud_stream); 
     283    } 
    281284    if (status != PJ_SUCCESS) { 
    282285        pjmedia_aud_stream_destroy(snd_port->aud_stream); 
     
    325328                                             pjmedia_snd_port **p_port) 
    326329{ 
    327     pjmedia_aud_param param; 
     330    pjmedia_snd_port_param param; 
    328331    pj_status_t status; 
    329332 
    330333    PJ_UNUSED_ARG(options); 
    331334 
    332     status = pjmedia_aud_dev_default_param(rec_id, &param); 
     335    status = pjmedia_aud_dev_default_param(rec_id, &param.base); 
    333336    if (status != PJ_SUCCESS) 
    334337        return status; 
    335338 
    336     param.dir = PJMEDIA_DIR_CAPTURE_PLAYBACK; 
    337     param.rec_id = rec_id; 
    338     param.play_id = play_id; 
    339     param.clock_rate = clock_rate; 
    340     param.channel_count = channel_count; 
    341     param.samples_per_frame = samples_per_frame; 
    342     param.bits_per_sample = bits_per_sample; 
     339    param.base.dir = PJMEDIA_DIR_CAPTURE_PLAYBACK; 
     340    param.base.rec_id = rec_id; 
     341    param.base.play_id = play_id; 
     342    param.base.clock_rate = clock_rate; 
     343    param.base.channel_count = channel_count; 
     344    param.base.samples_per_frame = samples_per_frame; 
     345    param.base.bits_per_sample = bits_per_sample; 
     346    param.options = options; 
    343347 
    344348    return pjmedia_snd_port_create2(pool, &param, p_port); 
     
    357361                                                 pjmedia_snd_port **p_port) 
    358362{ 
    359     pjmedia_aud_param param; 
     363    pjmedia_snd_port_param param; 
    360364    pj_status_t status; 
    361365 
    362366    PJ_UNUSED_ARG(options); 
    363367 
    364     status = pjmedia_aud_dev_default_param(dev_id, &param); 
     368    status = pjmedia_aud_dev_default_param(dev_id, &param.base); 
    365369    if (status != PJ_SUCCESS) 
    366370        return status; 
    367371 
    368     param.dir = PJMEDIA_DIR_CAPTURE; 
    369     param.rec_id = dev_id; 
    370     param.clock_rate = clock_rate; 
    371     param.channel_count = channel_count; 
    372     param.samples_per_frame = samples_per_frame; 
    373     param.bits_per_sample = bits_per_sample; 
     372    param.base.dir = PJMEDIA_DIR_CAPTURE; 
     373    param.base.rec_id = dev_id; 
     374    param.base.clock_rate = clock_rate; 
     375    param.base.channel_count = channel_count; 
     376    param.base.samples_per_frame = samples_per_frame; 
     377    param.base.bits_per_sample = bits_per_sample; 
     378    param.options = options; 
    374379 
    375380    return pjmedia_snd_port_create2(pool, &param, p_port); 
     
    389394                                                    pjmedia_snd_port **p_port) 
    390395{ 
    391     pjmedia_aud_param param; 
     396    pjmedia_snd_port_param param; 
    392397    pj_status_t status; 
    393398 
    394399    PJ_UNUSED_ARG(options); 
    395400 
    396     status = pjmedia_aud_dev_default_param(dev_id, &param); 
     401    status = pjmedia_aud_dev_default_param(dev_id, &param.base); 
    397402    if (status != PJ_SUCCESS) 
    398403        return status; 
    399404 
    400     param.dir = PJMEDIA_DIR_PLAYBACK; 
    401     param.play_id = dev_id; 
    402     param.clock_rate = clock_rate; 
    403     param.channel_count = channel_count; 
    404     param.samples_per_frame = samples_per_frame; 
    405     param.bits_per_sample = bits_per_sample; 
     405    param.base.dir = PJMEDIA_DIR_PLAYBACK; 
     406    param.base.play_id = dev_id; 
     407    param.base.clock_rate = clock_rate; 
     408    param.base.channel_count = channel_count; 
     409    param.base.samples_per_frame = samples_per_frame; 
     410    param.base.bits_per_sample = bits_per_sample; 
     411    param.options = options; 
    406412 
    407413    return pjmedia_snd_port_create2(pool, &param, p_port); 
     
    413419 */ 
    414420PJ_DEF(pj_status_t) pjmedia_snd_port_create2(pj_pool_t *pool, 
    415                                              const pjmedia_aud_param *prm, 
     421                                             const pjmedia_snd_port_param *prm, 
    416422                                             pjmedia_snd_port **p_port) 
    417423{ 
     
    424430    PJ_ASSERT_RETURN(snd_port, PJ_ENOMEM); 
    425431 
    426     snd_port->dir = prm->dir; 
    427     snd_port->rec_id = prm->rec_id; 
    428     snd_port->play_id = prm->play_id; 
     432    snd_port->dir = prm->base.dir; 
     433    snd_port->rec_id = prm->base.rec_id; 
     434    snd_port->play_id = prm->base.play_id; 
    429435    snd_port->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK; 
    430     snd_port->clock_rate = prm->clock_rate; 
    431     snd_port->channel_count = prm->channel_count; 
    432     snd_port->samples_per_frame = prm->samples_per_frame; 
    433     snd_port->bits_per_sample = prm->bits_per_sample; 
    434     pj_memcpy(&snd_port->aud_param, prm, sizeof(*prm)); 
     436    snd_port->clock_rate = prm->base.clock_rate; 
     437    snd_port->channel_count = prm->base.channel_count; 
     438    snd_port->samples_per_frame = prm->base.samples_per_frame; 
     439    snd_port->bits_per_sample = prm->base.bits_per_sample; 
     440    pj_memcpy(&snd_port->aud_param, prm, sizeof(snd_port->aud_param)); 
     441    snd_port->options = prm->options; 
    435442     
    436443    /* Start sound device immediately. 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c

    r3383 r3438  
    3737 
    3838/* Open sound dev */ 
    39 static pj_status_t open_snd_dev(pjmedia_aud_param *param); 
     39static pj_status_t open_snd_dev(pjmedia_snd_port_param *param); 
    4040/* Close existing sound device */ 
    4141static void close_snd_dev(void); 
     
    19761976        if (need_reopen) { 
    19771977            if (pjsua_var.cap_dev != NULL_SND_DEV_ID) { 
    1978                 pjmedia_aud_param param; 
     1978                pjmedia_snd_port_param param; 
    19791979 
    19801980                /* Create parameter based on peer info */ 
    1981                 status = create_aud_param(&param, pjsua_var.cap_dev,  
     1981                status = create_aud_param(&param.base, pjsua_var.cap_dev,  
    19821982                                          pjsua_var.play_dev, 
    19831983                                          peer_info.clock_rate, 
     
    19921992                /* And peer format */ 
    19931993                if (peer_info.format.id != PJMEDIA_FORMAT_PCM) { 
    1994                     param.flags |= PJMEDIA_AUD_DEV_CAP_EXT_FORMAT; 
    1995                     param.ext_fmt = peer_info.format; 
     1994                    param.base.flags |= PJMEDIA_AUD_DEV_CAP_EXT_FORMAT; 
     1995                    param.base.ext_fmt = peer_info.format; 
    19961996                } 
    19971997 
     1998                param.options = 0; 
    19981999                status = open_snd_dev(&param); 
    19992000                if (status != PJ_SUCCESS) { 
     
    26662667 
    26672668/* Open sound device with the setting. */ 
    2668 static pj_status_t open_snd_dev(pjmedia_aud_param *param) 
     2669static pj_status_t open_snd_dev(pjmedia_snd_port_param *param) 
    26692670{ 
    26702671    pjmedia_port *conf_port; 
     
    26742675 
    26752676    /* Check if NULL sound device is used */ 
    2676     if (NULL_SND_DEV_ID==param->rec_id || NULL_SND_DEV_ID==param->play_id) { 
     2677    if (NULL_SND_DEV_ID==param->base.rec_id || 
     2678        NULL_SND_DEV_ID==param->base.play_id) 
     2679    { 
    26772680        return pjsua_set_null_snd_dev(); 
    26782681    } 
     
    26872690 
    26882691    PJ_LOG(4,(THIS_FILE, "Opening sound device %s@%d/%d/%dms", 
    2689               get_fmt_name(param->ext_fmt.id), 
    2690               param->clock_rate, param->channel_count, 
    2691               param->samples_per_frame / param->channel_count * 1000 / 
    2692               param->clock_rate)); 
     2692              get_fmt_name(param->base.ext_fmt.id), 
     2693              param->base.clock_rate, param->base.channel_count, 
     2694              param->base.samples_per_frame / param->base.channel_count * 
     2695              1000 / param->base.clock_rate)); 
    26932696 
    26942697    status = pjmedia_snd_port_create2( pjsua_var.snd_pool,  
    2695                                        param,  &pjsua_var.snd_port); 
     2698                                       param, &pjsua_var.snd_port); 
    26962699    if (status != PJ_SUCCESS) 
    26972700        return status; 
     
    27052708     */ 
    27062709    if (!pjsua_var.is_mswitch && 
    2707         param->ext_fmt.id == PJMEDIA_FORMAT_PCM && 
    2708         conf_port->info.clock_rate != param->clock_rate) 
     2710        param->base.ext_fmt.id == PJMEDIA_FORMAT_PCM && 
     2711        conf_port->info.clock_rate != param->base.clock_rate) 
    27092712    { 
    27102713        pjmedia_port *resample_port; 
     
    27222725        status = pjmedia_resample_port_create(pjsua_var.snd_pool,  
    27232726                                              conf_port, 
    2724                                               param->clock_rate, 
     2727                                              param->base.clock_rate, 
    27252728                                              resample_opt,  
    27262729                                              &resample_port); 
     
    27422745     */ 
    27432746    if (pjsua_var.is_mswitch) { 
    2744         pj_memcpy(&conf_port->info.format, &param->ext_fmt,  
     2747        pj_memcpy(&conf_port->info.format, &param->base.ext_fmt,  
    27452748                  sizeof(conf_port->info.format)); 
    2746         conf_port->info.clock_rate = param->clock_rate; 
    2747         conf_port->info.samples_per_frame = param->samples_per_frame; 
    2748         conf_port->info.channel_count = param->channel_count; 
     2749        conf_port->info.clock_rate = param->base.clock_rate; 
     2750        conf_port->info.samples_per_frame = param->base.samples_per_frame; 
     2751        conf_port->info.channel_count = param->base.channel_count; 
    27492752        conf_port->info.bits_per_sample = 16; 
    27502753    } 
     
    27622765 
    27632766    /* Save the device IDs */ 
    2764     pjsua_var.cap_dev = param->rec_id; 
    2765     pjsua_var.play_dev = param->play_id; 
     2767    pjsua_var.cap_dev = param->base.rec_id; 
     2768    pjsua_var.play_dev = param->base.play_id; 
    27662769 
    27672770    /* Update sound device name. */ 
     
    27782781 
    27792782        if (status==PJ_SUCCESS) { 
    2780             if (param->clock_rate != pjsua_var.media_cfg.clock_rate) { 
     2783            if (param->base.clock_rate != pjsua_var.media_cfg.clock_rate) { 
    27812784                char tmp_buf[128]; 
    27822785                int tmp_buf_len = sizeof(tmp_buf); 
     
    27852788                                               "%s (%dKHz)", 
    27862789                                               rec_info.name,  
    2787                                                param->clock_rate/1000); 
     2790                                               param->base.clock_rate/1000); 
    27882791                pj_strset(&tmp, tmp_buf, tmp_buf_len); 
    27892792                pjmedia_conf_set_port0_name(pjsua_var.mconf, &tmp);  
     
    28842887    /* Attempts to open the sound device with different clock rates */ 
    28852888    for (i=0; i<alt_cr_cnt; ++i) { 
    2886         pjmedia_aud_param param; 
     2889        pjmedia_snd_port_param param; 
    28872890        unsigned samples_per_frame; 
    28882891 
     
    28912894                            pjsua_var.media_cfg.audio_frame_ptime * 
    28922895                            pjsua_var.media_cfg.channel_count / 1000; 
    2893         status = create_aud_param(&param, capture_dev, playback_dev,  
     2896        status = create_aud_param(&param.base, capture_dev, playback_dev,  
    28942897                                  alt_cr[i], pjsua_var.media_cfg.channel_count, 
    28952898                                  samples_per_frame, 16); 
     
    28982901 
    28992902        /* Open! */ 
     2903        param.options = 0; 
    29002904        status = open_snd_dev(&param); 
    29012905        if (status == PJ_SUCCESS) 
Note: See TracChangeset for help on using the changeset viewer.