Ignore:
Timestamp:
Dec 28, 2016 3:40:07 AM (7 years ago)
Author:
nanang
Message:

Re #1900: More merged from trunk (r5512 mistakenly contains merged changes in third-party dir only).

Location:
pjproject/branches/projects/uwp
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/uwp

  • pjproject/branches/projects/uwp/pjmedia/src/pjmedia-audiodev/audiodev.c

    r5210 r5513  
    2020#include <pjmedia-audiodev/audiodev_imp.h> 
    2121#include <pj/assert.h> 
    22 #include <pj/errno.h> 
    23 #include <pj/log.h> 
    24 #include <pj/pool.h> 
    25 #include <pj/string.h> 
    2622 
    2723#define THIS_FILE   "audiodev.c" 
    28  
    29 #define DEFINE_CAP(name, info)  {name, info} 
    30  
    31 /* Capability names */ 
    32 static struct cap_info 
    33 { 
    34     const char *name; 
    35     const char *info; 
    36 } cap_infos[] =  
    37 { 
    38     DEFINE_CAP("ext-fmt",     "Extended/non-PCM format"), 
    39     DEFINE_CAP("latency-in",  "Input latency/buffer size setting"), 
    40     DEFINE_CAP("latency-out", "Output latency/buffer size setting"), 
    41     DEFINE_CAP("vol-in",      "Input volume setting"), 
    42     DEFINE_CAP("vol-out",     "Output volume setting"), 
    43     DEFINE_CAP("meter-in",    "Input meter"), 
    44     DEFINE_CAP("meter-out",   "Output meter"), 
    45     DEFINE_CAP("route-in",    "Input routing"), 
    46     DEFINE_CAP("route-out",   "Output routing"), 
    47     DEFINE_CAP("aec",         "Accoustic echo cancellation"), 
    48     DEFINE_CAP("aec-tail",    "Tail length setting for AEC"), 
    49     DEFINE_CAP("vad",         "Voice activity detection"), 
    50     DEFINE_CAP("cng",         "Comfort noise generation"), 
    51     DEFINE_CAP("plg",         "Packet loss concealment") 
    52 }; 
    53  
    54  
    55 /* 
    56  * The device index seen by application and driver is different.  
    57  * 
    58  * At application level, device index is index to global list of device. 
    59  * At driver level, device index is index to device list on that particular 
    60  * factory only. 
    61  */ 
    62 #define MAKE_DEV_ID(f_id, index)   (((f_id & 0xFFFF) << 16) | (index & 0xFFFF)) 
    63 #define GET_INDEX(dev_id)          ((dev_id) & 0xFFFF) 
    64 #define GET_FID(dev_id)            ((dev_id) >> 16) 
    65 #define DEFAULT_DEV_ID              0 
    6624 
    6725 
     
    11977#endif 
    12078 
    121 #define MAX_DRIVERS     16 
    122 #define MAX_DEVS        64 
    123  
    124  
    125 /* driver structure */ 
    126 struct driver 
    127 { 
    128     /* Creation function */ 
    129     pjmedia_aud_dev_factory_create_func_ptr create; 
    130     /* Factory instance */ 
    131     pjmedia_aud_dev_factory *f; 
    132     char                     name[32];  /* Driver name                      */ 
    133     unsigned                 dev_cnt;   /* Number of devices                */ 
    134     unsigned                 start_idx; /* Start index in global list       */ 
    135     int                      rec_dev_idx;/* Default capture device.         */ 
    136     int                      play_dev_idx;/* Default playback device        */ 
    137     int                      dev_idx;   /* Default device.                  */ 
    138 }; 
    139  
    140 /* The audio subsystem */ 
    141 static struct aud_subsys 
    142 { 
    143     unsigned         init_count;        /* How many times init() is called  */ 
    144     pj_pool_factory *pf;                /* The pool factory.                */ 
    145  
    146     unsigned         drv_cnt;           /* Number of drivers.               */ 
    147     struct driver    drv[MAX_DRIVERS];  /* Array of drivers.                */ 
    148  
    149     unsigned         dev_cnt;           /* Total number of devices.         */ 
    150     pj_uint32_t      dev_list[MAX_DEVS];/* Array of device IDs.             */ 
    151  
    152 } aud_subsys; 
    153  
    154 /* API: get capability name/info */ 
    155 PJ_DEF(const char*) pjmedia_aud_dev_cap_name(pjmedia_aud_dev_cap cap, 
    156                                              const char **p_desc) 
    157 { 
    158     const char *desc; 
    159     unsigned i; 
    160  
    161     if (p_desc==NULL) p_desc = &desc; 
    162  
    163     for (i=0; i<PJ_ARRAY_SIZE(cap_infos); ++i) { 
    164         if ((1 << i)==cap) 
    165             break; 
    166     } 
    167  
    168     if (i==PJ_ARRAY_SIZE(cap_infos)) { 
    169         *p_desc = "??"; 
    170         return "??"; 
    171     } 
    172  
    173     *p_desc = cap_infos[i].info; 
    174     return cap_infos[i].name; 
    175 } 
    176  
    177 static pj_status_t get_cap_pointer(const pjmedia_aud_param *param, 
    178                                    pjmedia_aud_dev_cap cap, 
    179                                    void **ptr, 
    180                                    unsigned *size) 
    181 { 
    182 #define FIELD_INFO(name)    *ptr = (void*)&param->name; \ 
    183                             *size = sizeof(param->name) 
    184  
    185     switch (cap) { 
    186     case PJMEDIA_AUD_DEV_CAP_EXT_FORMAT: 
    187         FIELD_INFO(ext_fmt); 
    188         break; 
    189     case PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY: 
    190         FIELD_INFO(input_latency_ms); 
    191         break; 
    192     case PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY: 
    193         FIELD_INFO(output_latency_ms); 
    194         break; 
    195     case PJMEDIA_AUD_DEV_CAP_INPUT_VOLUME_SETTING: 
    196         FIELD_INFO(input_vol); 
    197         break; 
    198     case PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING: 
    199         FIELD_INFO(output_vol); 
    200         break; 
    201     case PJMEDIA_AUD_DEV_CAP_INPUT_ROUTE: 
    202         FIELD_INFO(input_route); 
    203         break; 
    204     case PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE: 
    205         FIELD_INFO(output_route); 
    206         break; 
    207     case PJMEDIA_AUD_DEV_CAP_EC: 
    208         FIELD_INFO(ec_enabled); 
    209         break; 
    210     case PJMEDIA_AUD_DEV_CAP_EC_TAIL: 
    211         FIELD_INFO(ec_tail_ms); 
    212         break; 
    213     /* vad is no longer in "fmt" in 2.0. 
    214     case PJMEDIA_AUD_DEV_CAP_VAD: 
    215         FIELD_INFO(ext_fmt.vad); 
    216         break; 
    217     */ 
    218     case PJMEDIA_AUD_DEV_CAP_CNG: 
    219         FIELD_INFO(cng_enabled); 
    220         break; 
    221     case PJMEDIA_AUD_DEV_CAP_PLC: 
    222         FIELD_INFO(plc_enabled); 
    223         break; 
    224     default: 
    225         return PJMEDIA_EAUD_INVCAP; 
    226     } 
    227  
    228 #undef FIELD_INFO 
    229  
    230     return PJ_SUCCESS; 
    231 } 
    232  
    233 /* API: set cap value to param */ 
    234 PJ_DEF(pj_status_t) pjmedia_aud_param_set_cap( pjmedia_aud_param *param, 
    235                                                pjmedia_aud_dev_cap cap, 
    236                                                const void *pval) 
    237 { 
    238     void *cap_ptr; 
    239     unsigned cap_size; 
    240     pj_status_t status; 
    241  
    242     status = get_cap_pointer(param, cap, &cap_ptr, &cap_size); 
    243     if (status != PJ_SUCCESS) 
    244         return status; 
    245  
    246     pj_memcpy(cap_ptr, pval, cap_size); 
    247     param->flags |= cap; 
    248  
    249     return PJ_SUCCESS; 
    250 } 
    251  
    252 /* API: get cap value from param */ 
    253 PJ_DEF(pj_status_t) pjmedia_aud_param_get_cap( const pjmedia_aud_param *param, 
    254                                                pjmedia_aud_dev_cap cap, 
    255                                                void *pval) 
    256 { 
    257     void *cap_ptr; 
    258     unsigned cap_size; 
    259     pj_status_t status; 
    260  
    261     status = get_cap_pointer(param, cap, &cap_ptr, &cap_size); 
    262     if (status != PJ_SUCCESS) 
    263         return status; 
    264  
    265     if ((param->flags & cap) == 0) { 
    266         pj_bzero(cap_ptr, cap_size); 
    267         return PJMEDIA_EAUD_INVCAP; 
    268     } 
    269  
    270     pj_memcpy(pval, cap_ptr, cap_size); 
    271     return PJ_SUCCESS; 
    272 } 
    273  
    274 /* Internal: init driver */ 
    275 static pj_status_t init_driver(unsigned drv_idx, pj_bool_t refresh) 
    276 { 
    277     struct driver *drv = &aud_subsys.drv[drv_idx]; 
    278     pjmedia_aud_dev_factory *f; 
    279     unsigned i, dev_cnt; 
    280     pj_status_t status; 
    281  
    282     if (!refresh && drv->create) { 
    283         /* Create the factory */ 
    284         f = (*drv->create)(aud_subsys.pf); 
    285         if (!f) 
    286             return PJ_EUNKNOWN; 
    287  
    288         /* Call factory->init() */ 
    289         status = f->op->init(f); 
    290         if (status != PJ_SUCCESS) { 
    291             f->op->destroy(f); 
    292             return status; 
    293         } 
    294     } else { 
    295         f = drv->f; 
    296     } 
    297  
    298     if (!f) 
    299         return PJ_EUNKNOWN; 
    300  
    301     /* Get number of devices */ 
    302     dev_cnt = f->op->get_dev_count(f); 
    303     if (dev_cnt + aud_subsys.dev_cnt > MAX_DEVS) { 
    304         PJ_LOG(4,(THIS_FILE, "%d device(s) cannot be registered because" 
    305                               " there are too many devices", 
    306                               aud_subsys.dev_cnt + dev_cnt - MAX_DEVS)); 
    307         dev_cnt = MAX_DEVS - aud_subsys.dev_cnt; 
    308     } 
    309  
    310     /* enabling this will cause pjsua-lib initialization to fail when there 
    311      * is no sound device installed in the system, even when pjsua has been 
    312      * run with --null-audio 
    313      * 
    314     if (dev_cnt == 0) { 
    315         f->op->destroy(f); 
    316         return PJMEDIA_EAUD_NODEV; 
    317     } 
    318     */ 
    319  
    320     /* Fill in default devices */ 
    321     drv->play_dev_idx = drv->rec_dev_idx = 
    322                         drv->dev_idx = PJMEDIA_AUD_INVALID_DEV; 
    323     for (i=0; i<dev_cnt; ++i) { 
    324         pjmedia_aud_dev_info info; 
    325  
    326         status = f->op->get_dev_info(f, i, &info); 
    327         if (status != PJ_SUCCESS) { 
    328             f->op->destroy(f); 
    329             return status; 
    330         } 
    331  
    332         if (drv->name[0]=='\0') { 
    333             /* Set driver name */ 
    334             pj_ansi_strncpy(drv->name, info.driver, sizeof(drv->name)); 
    335             drv->name[sizeof(drv->name)-1] = '\0'; 
    336         } 
    337  
    338         if (drv->play_dev_idx < 0 && info.output_count) { 
    339             /* Set default playback device */ 
    340             drv->play_dev_idx = i; 
    341         } 
    342         if (drv->rec_dev_idx < 0 && info.input_count) { 
    343             /* Set default capture device */ 
    344             drv->rec_dev_idx = i; 
    345         } 
    346         if (drv->dev_idx < 0 && info.input_count && 
    347             info.output_count) 
    348         { 
    349             /* Set default capture and playback device */ 
    350             drv->dev_idx = i; 
    351         } 
    352  
    353         if (drv->play_dev_idx >= 0 && drv->rec_dev_idx >= 0 &&  
    354             drv->dev_idx >= 0)  
    355         { 
    356             /* Done. */ 
    357             break; 
    358         } 
    359     } 
    360  
    361     /* Register the factory */ 
    362     drv->f = f; 
    363     drv->f->sys.drv_idx = drv_idx; 
    364     drv->start_idx = aud_subsys.dev_cnt; 
    365     drv->dev_cnt = dev_cnt; 
    366  
    367     /* Register devices to global list */ 
    368     for (i=0; i<dev_cnt; ++i) { 
    369         aud_subsys.dev_list[aud_subsys.dev_cnt++] = MAKE_DEV_ID(drv_idx, i); 
    370     } 
    371  
    372     return PJ_SUCCESS; 
    373 } 
    374  
    375 /* Internal: deinit driver */ 
    376 static void deinit_driver(unsigned drv_idx) 
    377 { 
    378     struct driver *drv = &aud_subsys.drv[drv_idx]; 
    379  
    380     if (drv->f) { 
    381         drv->f->op->destroy(drv->f); 
    382         drv->f = NULL; 
    383     } 
    384  
    385     pj_bzero(drv, sizeof(*drv)); 
    386     drv->play_dev_idx = drv->rec_dev_idx =  
    387                         drv->dev_idx = PJMEDIA_AUD_INVALID_DEV; 
    388 } 
    38979 
    39080/* API: Initialize the audio subsystem. */ 
     
    39383    unsigned i; 
    39484    pj_status_t status; 
     85    pjmedia_aud_subsys *aud_subsys = pjmedia_get_aud_subsys(); 
    39586 
    39687    /* Allow init() to be called multiple times as long as there is matching 
    39788     * number of shutdown(). 
    39889     */ 
    399     if (aud_subsys.init_count++ != 0) { 
     90    if (aud_subsys->init_count++ != 0) { 
    40091        return PJ_SUCCESS; 
    40192    } 
     
    40899 
    409100    /* Init */ 
    410     aud_subsys.pf = pf; 
    411     aud_subsys.drv_cnt = 0; 
    412     aud_subsys.dev_cnt = 0; 
     101    aud_subsys->pf = pf; 
     102    aud_subsys->drv_cnt = 0; 
     103    aud_subsys->dev_cnt = 0; 
    413104 
    414105    /* Register creation functions */ 
    415106#if PJMEDIA_AUDIO_DEV_HAS_OPENSL 
    416     aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_opensl_factory; 
     107    aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_opensl_factory; 
    417108#endif 
    418109#if PJMEDIA_AUDIO_DEV_HAS_ANDROID_JNI 
    419     aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_android_factory; 
     110    aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_android_factory; 
    420111#endif 
    421112#if PJMEDIA_AUDIO_DEV_HAS_BB10 
    422     aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_bb10_factory; 
     113    aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_bb10_factory; 
    423114#endif 
    424115#if PJMEDIA_AUDIO_DEV_HAS_ALSA 
    425     aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_alsa_factory; 
     116    aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_alsa_factory; 
    426117#endif 
    427118#if PJMEDIA_AUDIO_DEV_HAS_COREAUDIO 
    428     aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_coreaudio_factory; 
     119    aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_coreaudio_factory; 
    429120#endif 
    430121#if PJMEDIA_AUDIO_DEV_HAS_PORTAUDIO 
    431     aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_pa_factory; 
     122    aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_pa_factory; 
    432123#endif 
    433124#if PJMEDIA_AUDIO_DEV_HAS_WMME 
    434     aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_wmme_factory; 
     125    aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_wmme_factory; 
    435126#endif 
    436127#if PJMEDIA_AUDIO_DEV_HAS_BDIMAD 
    437     aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_bdimad_factory; 
     128    aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_bdimad_factory; 
    438129#endif 
    439130#if PJMEDIA_AUDIO_DEV_HAS_SYMB_VAS 
    440     aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_symb_vas_factory; 
     131    aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_symb_vas_factory; 
    441132#endif 
    442133#if PJMEDIA_AUDIO_DEV_HAS_SYMB_APS 
    443     aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_aps_factory; 
     134    aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_aps_factory; 
    444135#endif 
    445136#if PJMEDIA_AUDIO_DEV_HAS_SYMB_MDA 
    446     aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_symb_mda_factory; 
     137    aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_symb_mda_factory; 
    447138#endif 
    448139#if PJMEDIA_AUDIO_DEV_HAS_WASAPI 
     
    450141#endif 
    451142#if PJMEDIA_AUDIO_DEV_HAS_NULL_AUDIO 
    452     aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_null_audio_factory; 
     143    aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_null_audio_factory; 
    453144#endif 
    454145 
    455146    /* Initialize each factory and build the device ID list */ 
    456     for (i=0; i<aud_subsys.drv_cnt; ++i) { 
    457         status = init_driver(i, PJ_FALSE); 
     147    for (i=0; i<aud_subsys->drv_cnt; ++i) { 
     148        status = pjmedia_aud_driver_init(i, PJ_FALSE); 
    458149        if (status != PJ_SUCCESS) { 
    459             deinit_driver(i); 
     150            pjmedia_aud_driver_deinit(i); 
    460151            continue; 
    461152        } 
    462153    } 
    463154 
    464     return aud_subsys.dev_cnt ? PJ_SUCCESS : status; 
     155    return aud_subsys->dev_cnt ? PJ_SUCCESS : status; 
    465156} 
    466157 
     
    470161{ 
    471162    pj_status_t status; 
    472  
    473     if (aud_subsys.init_count == 0) 
     163    pjmedia_aud_subsys *aud_subsys = pjmedia_get_aud_subsys(); 
     164 
     165    if (aud_subsys->init_count == 0) 
    474166        return PJMEDIA_EAUD_INIT; 
    475167 
    476     aud_subsys.drv[aud_subsys.drv_cnt].create = adf; 
    477     status = init_driver(aud_subsys.drv_cnt, PJ_FALSE); 
     168    aud_subsys->drv[aud_subsys->drv_cnt].create = adf; 
     169    status = pjmedia_aud_driver_init(aud_subsys->drv_cnt, PJ_FALSE); 
    478170    if (status == PJ_SUCCESS) { 
    479         aud_subsys.drv_cnt++; 
     171        aud_subsys->drv_cnt++; 
    480172    } else { 
    481         deinit_driver(aud_subsys.drv_cnt); 
     173        pjmedia_aud_driver_deinit(aud_subsys->drv_cnt); 
    482174    } 
    483175 
     
    490182{ 
    491183    unsigned i, j; 
    492  
    493     if (aud_subsys.init_count == 0) 
     184    pjmedia_aud_subsys *aud_subsys = pjmedia_get_aud_subsys(); 
     185 
     186    if (aud_subsys->init_count == 0) 
    494187        return PJMEDIA_EAUD_INIT; 
    495188 
    496     for (i=0; i<aud_subsys.drv_cnt; ++i) { 
    497         struct driver *drv = &aud_subsys.drv[i]; 
     189    for (i=0; i<aud_subsys->drv_cnt; ++i) { 
     190        pjmedia_aud_driver *drv = &aud_subsys->drv[i]; 
    498191 
    499192        if (drv->create == adf) { 
    500193            for (j = drv->start_idx; j < drv->start_idx + drv->dev_cnt; j++) 
    501194            { 
    502                 aud_subsys.dev_list[j] = (pj_uint32_t)PJMEDIA_AUD_INVALID_DEV; 
     195                aud_subsys->dev_list[j] = (pj_uint32_t)PJMEDIA_AUD_INVALID_DEV; 
    503196            } 
    504197 
    505             deinit_driver(i); 
     198            pjmedia_aud_driver_deinit(i); 
    506199            return PJ_SUCCESS; 
    507200        } 
     
    514207PJ_DEF(pj_pool_factory*) pjmedia_aud_subsys_get_pool_factory(void) 
    515208{ 
    516     return aud_subsys.pf; 
     209    pjmedia_aud_subsys *aud_subsys = pjmedia_get_aud_subsys(); 
     210    return aud_subsys->pf; 
    517211} 
    518212 
     
    521215{ 
    522216    unsigned i; 
     217    pjmedia_aud_subsys *aud_subsys = pjmedia_get_aud_subsys(); 
    523218 
    524219    /* Allow shutdown() to be called multiple times as long as there is matching 
    525220     * number of init(). 
    526221     */ 
    527     if (aud_subsys.init_count == 0) { 
     222    if (aud_subsys->init_count == 0) { 
    528223        return PJ_SUCCESS; 
    529224    } 
    530     --aud_subsys.init_count; 
    531  
    532     if (aud_subsys.init_count == 0) { 
    533         for (i=0; i<aud_subsys.drv_cnt; ++i) { 
    534             deinit_driver(i); 
     225    --aud_subsys->init_count; 
     226 
     227    if (aud_subsys->init_count == 0) { 
     228        for (i=0; i<aud_subsys->drv_cnt; ++i) { 
     229            pjmedia_aud_driver_deinit(i); 
    535230        } 
    536231 
    537         aud_subsys.pf = NULL; 
     232        aud_subsys->pf = NULL; 
    538233    } 
    539234    return PJ_SUCCESS; 
    540235} 
    541  
    542 /* API: Refresh the list of sound devices installed in the system. */ 
    543 PJ_DEF(pj_status_t) pjmedia_aud_dev_refresh(void) 
    544 { 
    545     unsigned i; 
    546      
    547     aud_subsys.dev_cnt = 0; 
    548     for (i=0; i<aud_subsys.drv_cnt; ++i) { 
    549         struct driver *drv = &aud_subsys.drv[i]; 
    550          
    551         if (drv->f && drv->f->op->refresh) { 
    552             pj_status_t status = drv->f->op->refresh(drv->f); 
    553             if (status != PJ_SUCCESS) { 
    554                 PJ_PERROR(4, (THIS_FILE, status, "Unable to refresh device " 
    555                                                  "list for %s", drv->name)); 
    556             } 
    557         } 
    558         init_driver(i, PJ_TRUE); 
    559     } 
    560     return PJ_SUCCESS; 
    561 } 
    562  
    563 /* API: Get the number of sound devices installed in the system. */ 
    564 PJ_DEF(unsigned) pjmedia_aud_dev_count(void) 
    565 { 
    566     return aud_subsys.dev_cnt; 
    567 } 
    568  
    569 /* Internal: convert local index to global device index */ 
    570 static pj_status_t make_global_index(unsigned drv_idx,  
    571                                      pjmedia_aud_dev_index *id) 
    572 { 
    573     if (*id < 0) { 
    574         return PJ_SUCCESS; 
    575     } 
    576  
    577     /* Check that factory still exists */ 
    578     PJ_ASSERT_RETURN(aud_subsys.drv[drv_idx].f, PJ_EBUG); 
    579  
    580     /* Check that device index is valid */ 
    581     PJ_ASSERT_RETURN(*id>=0 && *id<(int)aud_subsys.drv[drv_idx].dev_cnt,  
    582                      PJ_EBUG); 
    583  
    584     *id += aud_subsys.drv[drv_idx].start_idx; 
    585     return PJ_SUCCESS; 
    586 } 
    587  
    588 /* Internal: lookup device id */ 
    589 static pj_status_t lookup_dev(pjmedia_aud_dev_index id, 
    590                               pjmedia_aud_dev_factory **p_f, 
    591                               unsigned *p_local_index) 
    592 { 
    593     int f_id, index; 
    594  
    595     if (id < 0) { 
    596         unsigned i; 
    597  
    598         if (id == PJMEDIA_AUD_INVALID_DEV) 
    599             return PJMEDIA_EAUD_INVDEV; 
    600  
    601         for (i=0; i<aud_subsys.drv_cnt; ++i) { 
    602             struct driver *drv = &aud_subsys.drv[i]; 
    603             if (drv->dev_idx >= 0) { 
    604                 id = drv->dev_idx; 
    605                 make_global_index(i, &id); 
    606                 break; 
    607             } else if (id==PJMEDIA_AUD_DEFAULT_CAPTURE_DEV &&  
    608                 drv->rec_dev_idx >= 0)  
    609             { 
    610                 id = drv->rec_dev_idx; 
    611                 make_global_index(i, &id); 
    612                 break; 
    613             } else if (id==PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV &&  
    614                 drv->play_dev_idx >= 0)  
    615             { 
    616                 id = drv->play_dev_idx; 
    617                 make_global_index(i, &id); 
    618                 break; 
    619             } 
    620         } 
    621  
    622         if (id < 0) { 
    623             return PJMEDIA_EAUD_NODEFDEV; 
    624         } 
    625     } 
    626  
    627     f_id = GET_FID(aud_subsys.dev_list[id]); 
    628     index = GET_INDEX(aud_subsys.dev_list[id]); 
    629  
    630     if (f_id < 0 || f_id >= (int)aud_subsys.drv_cnt) 
    631         return PJMEDIA_EAUD_INVDEV; 
    632  
    633     if (index < 0 || index >= (int)aud_subsys.drv[f_id].dev_cnt) 
    634         return PJMEDIA_EAUD_INVDEV; 
    635  
    636     *p_f = aud_subsys.drv[f_id].f; 
    637     *p_local_index = (unsigned)index; 
    638  
    639     return PJ_SUCCESS; 
    640  
    641 } 
    642  
    643 /* API: Get device information. */ 
    644 PJ_DEF(pj_status_t) pjmedia_aud_dev_get_info(pjmedia_aud_dev_index id, 
    645                                              pjmedia_aud_dev_info *info) 
    646 { 
    647     pjmedia_aud_dev_factory *f; 
    648     unsigned index; 
    649     pj_status_t status; 
    650  
    651     PJ_ASSERT_RETURN(info && id!=PJMEDIA_AUD_INVALID_DEV, PJ_EINVAL); 
    652     PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT); 
    653  
    654     status = lookup_dev(id, &f, &index); 
    655     if (status != PJ_SUCCESS) 
    656         return status; 
    657  
    658     return f->op->get_dev_info(f, index, info); 
    659 } 
    660  
    661 /* API: find device */ 
    662 PJ_DEF(pj_status_t) pjmedia_aud_dev_lookup( const char *drv_name, 
    663                                             const char *dev_name, 
    664                                             pjmedia_aud_dev_index *id) 
    665 { 
    666     pjmedia_aud_dev_factory *f = NULL; 
    667     unsigned drv_idx, dev_idx; 
    668  
    669     PJ_ASSERT_RETURN(drv_name && dev_name && id, PJ_EINVAL); 
    670     PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT); 
    671  
    672     for (drv_idx=0; drv_idx<aud_subsys.drv_cnt; ++drv_idx) { 
    673         if (!pj_ansi_stricmp(drv_name, aud_subsys.drv[drv_idx].name)) { 
    674             f = aud_subsys.drv[drv_idx].f; 
    675             break; 
    676         } 
    677     } 
    678  
    679     if (!f) 
    680         return PJ_ENOTFOUND; 
    681  
    682     for (dev_idx=0; dev_idx<aud_subsys.drv[drv_idx].dev_cnt; ++dev_idx) { 
    683         pjmedia_aud_dev_info info; 
    684         pj_status_t status; 
    685  
    686         status = f->op->get_dev_info(f, dev_idx, &info); 
    687         if (status != PJ_SUCCESS) 
    688             return status; 
    689  
    690         if (!pj_ansi_stricmp(dev_name, info.name)) 
    691             break; 
    692     } 
    693  
    694     if (dev_idx==aud_subsys.drv[drv_idx].dev_cnt) 
    695         return PJ_ENOTFOUND; 
    696  
    697     *id = dev_idx; 
    698     make_global_index(drv_idx, id); 
    699  
    700     return PJ_SUCCESS; 
    701 } 
    702  
    703 /* API: Initialize the audio device parameters with default values for the 
    704  * specified device. 
    705  */ 
    706 PJ_DEF(pj_status_t) pjmedia_aud_dev_default_param(pjmedia_aud_dev_index id, 
    707                                                   pjmedia_aud_param *param) 
    708 { 
    709     pjmedia_aud_dev_factory *f; 
    710     unsigned index; 
    711     pj_status_t status; 
    712  
    713     PJ_ASSERT_RETURN(param && id!=PJMEDIA_AUD_INVALID_DEV, PJ_EINVAL); 
    714     PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT); 
    715  
    716     status = lookup_dev(id, &f, &index); 
    717     if (status != PJ_SUCCESS) 
    718         return status; 
    719  
    720     status = f->op->default_param(f, index, param); 
    721     if (status != PJ_SUCCESS) 
    722         return status; 
    723  
    724     /* Normalize device IDs */ 
    725     make_global_index(f->sys.drv_idx, &param->rec_id); 
    726     make_global_index(f->sys.drv_idx, &param->play_id); 
    727  
    728     return PJ_SUCCESS; 
    729 } 
    730  
    731 /* API: Open audio stream object using the specified parameters. */ 
    732 PJ_DEF(pj_status_t) pjmedia_aud_stream_create(const pjmedia_aud_param *prm, 
    733                                               pjmedia_aud_rec_cb rec_cb, 
    734                                               pjmedia_aud_play_cb play_cb, 
    735                                               void *user_data, 
    736                                               pjmedia_aud_stream **p_aud_strm) 
    737 { 
    738     pjmedia_aud_dev_factory *rec_f=NULL, *play_f=NULL, *f=NULL; 
    739     pjmedia_aud_param param; 
    740     pj_status_t status; 
    741  
    742     PJ_ASSERT_RETURN(prm && prm->dir && p_aud_strm, PJ_EINVAL); 
    743     PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT); 
    744     PJ_ASSERT_RETURN(prm->dir==PJMEDIA_DIR_CAPTURE || 
    745                      prm->dir==PJMEDIA_DIR_PLAYBACK || 
    746                      prm->dir==PJMEDIA_DIR_CAPTURE_PLAYBACK, 
    747                      PJ_EINVAL); 
    748  
    749     /* Must make copy of param because we're changing device ID */ 
    750     pj_memcpy(&param, prm, sizeof(param)); 
    751  
    752     /* Normalize rec_id */ 
    753     if (param.dir & PJMEDIA_DIR_CAPTURE) { 
    754         unsigned index; 
    755  
    756         if (param.rec_id < 0) 
    757             param.rec_id = PJMEDIA_AUD_DEFAULT_CAPTURE_DEV; 
    758  
    759         status = lookup_dev(param.rec_id, &rec_f, &index); 
    760         if (status != PJ_SUCCESS) 
    761             return status; 
    762  
    763         param.rec_id = index; 
    764         f = rec_f; 
    765     } 
    766  
    767     /* Normalize play_id */ 
    768     if (param.dir & PJMEDIA_DIR_PLAYBACK) { 
    769         unsigned index; 
    770  
    771         if (param.play_id < 0) 
    772             param.play_id = PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV; 
    773  
    774         status = lookup_dev(param.play_id, &play_f, &index); 
    775         if (status != PJ_SUCCESS) 
    776             return status; 
    777  
    778         param.play_id = index; 
    779         f = play_f; 
    780     } 
    781  
    782     PJ_ASSERT_RETURN(f != NULL, PJ_EBUG); 
    783  
    784     /* For now, rec_id and play_id must belong to the same factory */ 
    785     PJ_ASSERT_RETURN((param.dir != PJMEDIA_DIR_CAPTURE_PLAYBACK) ||  
    786                      (rec_f == play_f), 
    787                      PJMEDIA_EAUD_INVDEV); 
    788  
    789     /* Create the stream */ 
    790     status = f->op->create_stream(f, &param, rec_cb, play_cb, 
    791                                   user_data, p_aud_strm); 
    792     if (status != PJ_SUCCESS) 
    793         return status; 
    794  
    795     /* Assign factory id to the stream */ 
    796     (*p_aud_strm)->sys.drv_idx = f->sys.drv_idx; 
    797     return PJ_SUCCESS; 
    798 } 
    799  
    800 /* API: Get the running parameters for the specified audio stream. */ 
    801 PJ_DEF(pj_status_t) pjmedia_aud_stream_get_param(pjmedia_aud_stream *strm, 
    802                                                  pjmedia_aud_param *param) 
    803 { 
    804     pj_status_t status; 
    805  
    806     PJ_ASSERT_RETURN(strm && param, PJ_EINVAL); 
    807     PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT); 
    808  
    809     status = strm->op->get_param(strm, param); 
    810     if (status != PJ_SUCCESS) 
    811         return status; 
    812  
    813     /* Normalize device id's */ 
    814     make_global_index(strm->sys.drv_idx, &param->rec_id); 
    815     make_global_index(strm->sys.drv_idx, &param->play_id); 
    816  
    817     return PJ_SUCCESS; 
    818 } 
    819  
    820 /* API: Get the value of a specific capability of the audio stream. */ 
    821 PJ_DEF(pj_status_t) pjmedia_aud_stream_get_cap(pjmedia_aud_stream *strm, 
    822                                                pjmedia_aud_dev_cap cap, 
    823                                                void *value) 
    824 { 
    825     return strm->op->get_cap(strm, cap, value); 
    826 } 
    827  
    828 /* API: Set the value of a specific capability of the audio stream. */ 
    829 PJ_DEF(pj_status_t) pjmedia_aud_stream_set_cap(pjmedia_aud_stream *strm, 
    830                                                pjmedia_aud_dev_cap cap, 
    831                                                const void *value) 
    832 { 
    833     return strm->op->set_cap(strm, cap, value); 
    834 } 
    835  
    836 /* API: Start the stream. */ 
    837 PJ_DEF(pj_status_t) pjmedia_aud_stream_start(pjmedia_aud_stream *strm) 
    838 { 
    839     return strm->op->start(strm); 
    840 } 
    841  
    842 /* API: Stop the stream. */ 
    843 PJ_DEF(pj_status_t) pjmedia_aud_stream_stop(pjmedia_aud_stream *strm) 
    844 { 
    845     return strm->op->stop(strm); 
    846 } 
    847  
    848 /* API: Destroy the stream. */ 
    849 PJ_DEF(pj_status_t) pjmedia_aud_stream_destroy(pjmedia_aud_stream *strm) 
    850 { 
    851     return strm->op->destroy(strm); 
    852 } 
    853  
    854  
Note: See TracChangeset for help on using the changeset viewer.