Ignore:
Timestamp:
Mar 10, 2016 5:02:07 AM (9 years ago)
Author:
ming
Message:

Fixed #1907: Remove pjmedia* circular dependency

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/src/pjmedia-audiodev/audiodev.c

    r4879 r5255  
    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 
     
    11573#endif 
    11674 
    117 #define MAX_DRIVERS     16 
    118 #define MAX_DEVS        64 
    119  
    120  
    121 /* driver structure */ 
    122 struct driver 
    123 { 
    124     /* Creation function */ 
    125     pjmedia_aud_dev_factory_create_func_ptr create; 
    126     /* Factory instance */ 
    127     pjmedia_aud_dev_factory *f; 
    128     char                     name[32];  /* Driver name                      */ 
    129     unsigned                 dev_cnt;   /* Number of devices                */ 
    130     unsigned                 start_idx; /* Start index in global list       */ 
    131     int                      rec_dev_idx;/* Default capture device.         */ 
    132     int                      play_dev_idx;/* Default playback device        */ 
    133     int                      dev_idx;   /* Default device.                  */ 
    134 }; 
    135  
    136 /* The audio subsystem */ 
    137 static struct aud_subsys 
    138 { 
    139     unsigned         init_count;        /* How many times init() is called  */ 
    140     pj_pool_factory *pf;                /* The pool factory.                */ 
    141  
    142     unsigned         drv_cnt;           /* Number of drivers.               */ 
    143     struct driver    drv[MAX_DRIVERS];  /* Array of drivers.                */ 
    144  
    145     unsigned         dev_cnt;           /* Total number of devices.         */ 
    146     pj_uint32_t      dev_list[MAX_DEVS];/* Array of device IDs.             */ 
    147  
    148 } aud_subsys; 
    149  
    150 /* API: get capability name/info */ 
    151 PJ_DEF(const char*) pjmedia_aud_dev_cap_name(pjmedia_aud_dev_cap cap, 
    152                                              const char **p_desc) 
    153 { 
    154     const char *desc; 
    155     unsigned i; 
    156  
    157     if (p_desc==NULL) p_desc = &desc; 
    158  
    159     for (i=0; i<PJ_ARRAY_SIZE(cap_infos); ++i) { 
    160         if ((1 << i)==cap) 
    161             break; 
    162     } 
    163  
    164     if (i==PJ_ARRAY_SIZE(cap_infos)) { 
    165         *p_desc = "??"; 
    166         return "??"; 
    167     } 
    168  
    169     *p_desc = cap_infos[i].info; 
    170     return cap_infos[i].name; 
    171 } 
    172  
    173 static pj_status_t get_cap_pointer(const pjmedia_aud_param *param, 
    174                                    pjmedia_aud_dev_cap cap, 
    175                                    void **ptr, 
    176                                    unsigned *size) 
    177 { 
    178 #define FIELD_INFO(name)    *ptr = (void*)&param->name; \ 
    179                             *size = sizeof(param->name) 
    180  
    181     switch (cap) { 
    182     case PJMEDIA_AUD_DEV_CAP_EXT_FORMAT: 
    183         FIELD_INFO(ext_fmt); 
    184         break; 
    185     case PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY: 
    186         FIELD_INFO(input_latency_ms); 
    187         break; 
    188     case PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY: 
    189         FIELD_INFO(output_latency_ms); 
    190         break; 
    191     case PJMEDIA_AUD_DEV_CAP_INPUT_VOLUME_SETTING: 
    192         FIELD_INFO(input_vol); 
    193         break; 
    194     case PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING: 
    195         FIELD_INFO(output_vol); 
    196         break; 
    197     case PJMEDIA_AUD_DEV_CAP_INPUT_ROUTE: 
    198         FIELD_INFO(input_route); 
    199         break; 
    200     case PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE: 
    201         FIELD_INFO(output_route); 
    202         break; 
    203     case PJMEDIA_AUD_DEV_CAP_EC: 
    204         FIELD_INFO(ec_enabled); 
    205         break; 
    206     case PJMEDIA_AUD_DEV_CAP_EC_TAIL: 
    207         FIELD_INFO(ec_tail_ms); 
    208         break; 
    209     /* vad is no longer in "fmt" in 2.0. 
    210     case PJMEDIA_AUD_DEV_CAP_VAD: 
    211         FIELD_INFO(ext_fmt.vad); 
    212         break; 
    213     */ 
    214     case PJMEDIA_AUD_DEV_CAP_CNG: 
    215         FIELD_INFO(cng_enabled); 
    216         break; 
    217     case PJMEDIA_AUD_DEV_CAP_PLC: 
    218         FIELD_INFO(plc_enabled); 
    219         break; 
    220     default: 
    221         return PJMEDIA_EAUD_INVCAP; 
    222     } 
    223  
    224 #undef FIELD_INFO 
    225  
    226     return PJ_SUCCESS; 
    227 } 
    228  
    229 /* API: set cap value to param */ 
    230 PJ_DEF(pj_status_t) pjmedia_aud_param_set_cap( pjmedia_aud_param *param, 
    231                                                pjmedia_aud_dev_cap cap, 
    232                                                const void *pval) 
    233 { 
    234     void *cap_ptr; 
    235     unsigned cap_size; 
    236     pj_status_t status; 
    237  
    238     status = get_cap_pointer(param, cap, &cap_ptr, &cap_size); 
    239     if (status != PJ_SUCCESS) 
    240         return status; 
    241  
    242     pj_memcpy(cap_ptr, pval, cap_size); 
    243     param->flags |= cap; 
    244  
    245     return PJ_SUCCESS; 
    246 } 
    247  
    248 /* API: get cap value from param */ 
    249 PJ_DEF(pj_status_t) pjmedia_aud_param_get_cap( const pjmedia_aud_param *param, 
    250                                                pjmedia_aud_dev_cap cap, 
    251                                                void *pval) 
    252 { 
    253     void *cap_ptr; 
    254     unsigned cap_size; 
    255     pj_status_t status; 
    256  
    257     status = get_cap_pointer(param, cap, &cap_ptr, &cap_size); 
    258     if (status != PJ_SUCCESS) 
    259         return status; 
    260  
    261     if ((param->flags & cap) == 0) { 
    262         pj_bzero(cap_ptr, cap_size); 
    263         return PJMEDIA_EAUD_INVCAP; 
    264     } 
    265  
    266     pj_memcpy(pval, cap_ptr, cap_size); 
    267     return PJ_SUCCESS; 
    268 } 
    269  
    270 /* Internal: init driver */ 
    271 static pj_status_t init_driver(unsigned drv_idx, pj_bool_t refresh) 
    272 { 
    273     struct driver *drv = &aud_subsys.drv[drv_idx]; 
    274     pjmedia_aud_dev_factory *f; 
    275     unsigned i, dev_cnt; 
    276     pj_status_t status; 
    277  
    278     if (!refresh && drv->create) { 
    279         /* Create the factory */ 
    280         f = (*drv->create)(aud_subsys.pf); 
    281         if (!f) 
    282             return PJ_EUNKNOWN; 
    283  
    284         /* Call factory->init() */ 
    285         status = f->op->init(f); 
    286         if (status != PJ_SUCCESS) { 
    287             f->op->destroy(f); 
    288             return status; 
    289         } 
    290     } else { 
    291         f = drv->f; 
    292     } 
    293  
    294     if (!f) 
    295         return PJ_EUNKNOWN; 
    296  
    297     /* Get number of devices */ 
    298     dev_cnt = f->op->get_dev_count(f); 
    299     if (dev_cnt + aud_subsys.dev_cnt > MAX_DEVS) { 
    300         PJ_LOG(4,(THIS_FILE, "%d device(s) cannot be registered because" 
    301                               " there are too many devices", 
    302                               aud_subsys.dev_cnt + dev_cnt - MAX_DEVS)); 
    303         dev_cnt = MAX_DEVS - aud_subsys.dev_cnt; 
    304     } 
    305  
    306     /* enabling this will cause pjsua-lib initialization to fail when there 
    307      * is no sound device installed in the system, even when pjsua has been 
    308      * run with --null-audio 
    309      * 
    310     if (dev_cnt == 0) { 
    311         f->op->destroy(f); 
    312         return PJMEDIA_EAUD_NODEV; 
    313     } 
    314     */ 
    315  
    316     /* Fill in default devices */ 
    317     drv->play_dev_idx = drv->rec_dev_idx = 
    318                         drv->dev_idx = PJMEDIA_AUD_INVALID_DEV; 
    319     for (i=0; i<dev_cnt; ++i) { 
    320         pjmedia_aud_dev_info info; 
    321  
    322         status = f->op->get_dev_info(f, i, &info); 
    323         if (status != PJ_SUCCESS) { 
    324             f->op->destroy(f); 
    325             return status; 
    326         } 
    327  
    328         if (drv->name[0]=='\0') { 
    329             /* Set driver name */ 
    330             pj_ansi_strncpy(drv->name, info.driver, sizeof(drv->name)); 
    331             drv->name[sizeof(drv->name)-1] = '\0'; 
    332         } 
    333  
    334         if (drv->play_dev_idx < 0 && info.output_count) { 
    335             /* Set default playback device */ 
    336             drv->play_dev_idx = i; 
    337         } 
    338         if (drv->rec_dev_idx < 0 && info.input_count) { 
    339             /* Set default capture device */ 
    340             drv->rec_dev_idx = i; 
    341         } 
    342         if (drv->dev_idx < 0 && info.input_count && 
    343             info.output_count) 
    344         { 
    345             /* Set default capture and playback device */ 
    346             drv->dev_idx = i; 
    347         } 
    348  
    349         if (drv->play_dev_idx >= 0 && drv->rec_dev_idx >= 0 &&  
    350             drv->dev_idx >= 0)  
    351         { 
    352             /* Done. */ 
    353             break; 
    354         } 
    355     } 
    356  
    357     /* Register the factory */ 
    358     drv->f = f; 
    359     drv->f->sys.drv_idx = drv_idx; 
    360     drv->start_idx = aud_subsys.dev_cnt; 
    361     drv->dev_cnt = dev_cnt; 
    362  
    363     /* Register devices to global list */ 
    364     for (i=0; i<dev_cnt; ++i) { 
    365         aud_subsys.dev_list[aud_subsys.dev_cnt++] = MAKE_DEV_ID(drv_idx, i); 
    366     } 
    367  
    368     return PJ_SUCCESS; 
    369 } 
    370  
    371 /* Internal: deinit driver */ 
    372 static void deinit_driver(unsigned drv_idx) 
    373 { 
    374     struct driver *drv = &aud_subsys.drv[drv_idx]; 
    375  
    376     if (drv->f) { 
    377         drv->f->op->destroy(drv->f); 
    378         drv->f = NULL; 
    379     } 
    380  
    381     pj_bzero(drv, sizeof(*drv)); 
    382     drv->play_dev_idx = drv->rec_dev_idx =  
    383                         drv->dev_idx = PJMEDIA_AUD_INVALID_DEV; 
    384 } 
    38575 
    38676/* API: Initialize the audio subsystem. */ 
     
    38979    unsigned i; 
    39080    pj_status_t status; 
     81    pjmedia_aud_subsys *aud_subsys = pjmedia_get_aud_subsys(); 
    39182 
    39283    /* Allow init() to be called multiple times as long as there is matching 
    39384     * number of shutdown(). 
    39485     */ 
    395     if (aud_subsys.init_count++ != 0) { 
     86    if (aud_subsys->init_count++ != 0) { 
    39687        return PJ_SUCCESS; 
    39788    } 
     
    40495 
    40596    /* Init */ 
    406     aud_subsys.pf = pf; 
    407     aud_subsys.drv_cnt = 0; 
    408     aud_subsys.dev_cnt = 0; 
     97    aud_subsys->pf = pf; 
     98    aud_subsys->drv_cnt = 0; 
     99    aud_subsys->dev_cnt = 0; 
    409100 
    410101    /* Register creation functions */ 
    411102#if PJMEDIA_AUDIO_DEV_HAS_OPENSL 
    412     aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_opensl_factory; 
     103    aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_opensl_factory; 
    413104#endif 
    414105#if PJMEDIA_AUDIO_DEV_HAS_ANDROID_JNI 
    415     aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_android_factory; 
     106    aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_android_factory; 
    416107#endif 
    417108#if PJMEDIA_AUDIO_DEV_HAS_BB10 
    418     aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_bb10_factory; 
     109    aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_bb10_factory; 
    419110#endif 
    420111#if PJMEDIA_AUDIO_DEV_HAS_ALSA 
    421     aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_alsa_factory; 
     112    aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_alsa_factory; 
    422113#endif 
    423114#if PJMEDIA_AUDIO_DEV_HAS_COREAUDIO 
    424     aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_coreaudio_factory; 
     115    aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_coreaudio_factory; 
    425116#endif 
    426117#if PJMEDIA_AUDIO_DEV_HAS_PORTAUDIO 
    427     aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_pa_factory; 
     118    aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_pa_factory; 
    428119#endif 
    429120#if PJMEDIA_AUDIO_DEV_HAS_WMME 
    430     aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_wmme_factory; 
     121    aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_wmme_factory; 
    431122#endif 
    432123#if PJMEDIA_AUDIO_DEV_HAS_BDIMAD 
    433     aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_bdimad_factory; 
     124    aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_bdimad_factory; 
    434125#endif 
    435126#if PJMEDIA_AUDIO_DEV_HAS_SYMB_VAS 
    436     aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_symb_vas_factory; 
     127    aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_symb_vas_factory; 
    437128#endif 
    438129#if PJMEDIA_AUDIO_DEV_HAS_SYMB_APS 
    439     aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_aps_factory; 
     130    aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_aps_factory; 
    440131#endif 
    441132#if PJMEDIA_AUDIO_DEV_HAS_SYMB_MDA 
    442     aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_symb_mda_factory; 
     133    aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_symb_mda_factory; 
    443134#endif 
    444135#if PJMEDIA_AUDIO_DEV_HAS_NULL_AUDIO 
    445     aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_null_audio_factory; 
     136    aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_null_audio_factory; 
    446137#endif 
    447138 
    448139    /* Initialize each factory and build the device ID list */ 
    449     for (i=0; i<aud_subsys.drv_cnt; ++i) { 
    450         status = init_driver(i, PJ_FALSE); 
     140    for (i=0; i<aud_subsys->drv_cnt; ++i) { 
     141        status = pjmedia_aud_driver_init(i, PJ_FALSE); 
    451142        if (status != PJ_SUCCESS) { 
    452             deinit_driver(i); 
     143            pjmedia_aud_driver_deinit(i); 
    453144            continue; 
    454145        } 
    455146    } 
    456147 
    457     return aud_subsys.dev_cnt ? PJ_SUCCESS : status; 
     148    return aud_subsys->dev_cnt ? PJ_SUCCESS : status; 
    458149} 
    459150 
     
    463154{ 
    464155    pj_status_t status; 
    465  
    466     if (aud_subsys.init_count == 0) 
     156    pjmedia_aud_subsys *aud_subsys = pjmedia_get_aud_subsys(); 
     157 
     158    if (aud_subsys->init_count == 0) 
    467159        return PJMEDIA_EAUD_INIT; 
    468160 
    469     aud_subsys.drv[aud_subsys.drv_cnt].create = adf; 
    470     status = init_driver(aud_subsys.drv_cnt, PJ_FALSE); 
     161    aud_subsys->drv[aud_subsys->drv_cnt].create = adf; 
     162    status = pjmedia_aud_driver_init(aud_subsys->drv_cnt, PJ_FALSE); 
    471163    if (status == PJ_SUCCESS) { 
    472         aud_subsys.drv_cnt++; 
     164        aud_subsys->drv_cnt++; 
    473165    } else { 
    474         deinit_driver(aud_subsys.drv_cnt); 
     166        pjmedia_aud_driver_deinit(aud_subsys->drv_cnt); 
    475167    } 
    476168 
     
    483175{ 
    484176    unsigned i, j; 
    485  
    486     if (aud_subsys.init_count == 0) 
     177    pjmedia_aud_subsys *aud_subsys = pjmedia_get_aud_subsys(); 
     178 
     179    if (aud_subsys->init_count == 0) 
    487180        return PJMEDIA_EAUD_INIT; 
    488181 
    489     for (i=0; i<aud_subsys.drv_cnt; ++i) { 
    490         struct driver *drv = &aud_subsys.drv[i]; 
     182    for (i=0; i<aud_subsys->drv_cnt; ++i) { 
     183        pjmedia_aud_driver *drv = &aud_subsys->drv[i]; 
    491184 
    492185        if (drv->create == adf) { 
    493186            for (j = drv->start_idx; j < drv->start_idx + drv->dev_cnt; j++) 
    494187            { 
    495                 aud_subsys.dev_list[j] = (pj_uint32_t)PJMEDIA_AUD_INVALID_DEV; 
     188                aud_subsys->dev_list[j] = (pj_uint32_t)PJMEDIA_AUD_INVALID_DEV; 
    496189            } 
    497190 
    498             deinit_driver(i); 
     191            pjmedia_aud_driver_deinit(i); 
    499192            return PJ_SUCCESS; 
    500193        } 
     
    507200PJ_DEF(pj_pool_factory*) pjmedia_aud_subsys_get_pool_factory(void) 
    508201{ 
    509     return aud_subsys.pf; 
     202    pjmedia_aud_subsys *aud_subsys = pjmedia_get_aud_subsys(); 
     203    return aud_subsys->pf; 
    510204} 
    511205 
     
    514208{ 
    515209    unsigned i; 
     210    pjmedia_aud_subsys *aud_subsys = pjmedia_get_aud_subsys(); 
    516211 
    517212    /* Allow shutdown() to be called multiple times as long as there is matching 
    518213     * number of init(). 
    519214     */ 
    520     if (aud_subsys.init_count == 0) { 
     215    if (aud_subsys->init_count == 0) { 
    521216        return PJ_SUCCESS; 
    522217    } 
    523     --aud_subsys.init_count; 
    524  
    525     if (aud_subsys.init_count == 0) { 
    526         for (i=0; i<aud_subsys.drv_cnt; ++i) { 
    527             deinit_driver(i); 
     218    --aud_subsys->init_count; 
     219 
     220    if (aud_subsys->init_count == 0) { 
     221        for (i=0; i<aud_subsys->drv_cnt; ++i) { 
     222            pjmedia_aud_driver_deinit(i); 
    528223        } 
    529224 
    530         aud_subsys.pf = NULL; 
     225        aud_subsys->pf = NULL; 
    531226    } 
    532227    return PJ_SUCCESS; 
    533228} 
    534  
    535 /* API: Refresh the list of sound devices installed in the system. */ 
    536 PJ_DEF(pj_status_t) pjmedia_aud_dev_refresh(void) 
    537 { 
    538     unsigned i; 
    539      
    540     aud_subsys.dev_cnt = 0; 
    541     for (i=0; i<aud_subsys.drv_cnt; ++i) { 
    542         struct driver *drv = &aud_subsys.drv[i]; 
    543          
    544         if (drv->f && drv->f->op->refresh) { 
    545             pj_status_t status = drv->f->op->refresh(drv->f); 
    546             if (status != PJ_SUCCESS) { 
    547                 PJ_PERROR(4, (THIS_FILE, status, "Unable to refresh device " 
    548                                                  "list for %s", drv->name)); 
    549             } 
    550         } 
    551         init_driver(i, PJ_TRUE); 
    552     } 
    553     return PJ_SUCCESS; 
    554 } 
    555  
    556 /* API: Get the number of sound devices installed in the system. */ 
    557 PJ_DEF(unsigned) pjmedia_aud_dev_count(void) 
    558 { 
    559     return aud_subsys.dev_cnt; 
    560 } 
    561  
    562 /* Internal: convert local index to global device index */ 
    563 static pj_status_t make_global_index(unsigned drv_idx,  
    564                                      pjmedia_aud_dev_index *id) 
    565 { 
    566     if (*id < 0) { 
    567         return PJ_SUCCESS; 
    568     } 
    569  
    570     /* Check that factory still exists */ 
    571     PJ_ASSERT_RETURN(aud_subsys.drv[drv_idx].f, PJ_EBUG); 
    572  
    573     /* Check that device index is valid */ 
    574     PJ_ASSERT_RETURN(*id>=0 && *id<(int)aud_subsys.drv[drv_idx].dev_cnt,  
    575                      PJ_EBUG); 
    576  
    577     *id += aud_subsys.drv[drv_idx].start_idx; 
    578     return PJ_SUCCESS; 
    579 } 
    580  
    581 /* Internal: lookup device id */ 
    582 static pj_status_t lookup_dev(pjmedia_aud_dev_index id, 
    583                               pjmedia_aud_dev_factory **p_f, 
    584                               unsigned *p_local_index) 
    585 { 
    586     int f_id, index; 
    587  
    588     if (id < 0) { 
    589         unsigned i; 
    590  
    591         if (id == PJMEDIA_AUD_INVALID_DEV) 
    592             return PJMEDIA_EAUD_INVDEV; 
    593  
    594         for (i=0; i<aud_subsys.drv_cnt; ++i) { 
    595             struct driver *drv = &aud_subsys.drv[i]; 
    596             if (drv->dev_idx >= 0) { 
    597                 id = drv->dev_idx; 
    598                 make_global_index(i, &id); 
    599                 break; 
    600             } else if (id==PJMEDIA_AUD_DEFAULT_CAPTURE_DEV &&  
    601                 drv->rec_dev_idx >= 0)  
    602             { 
    603                 id = drv->rec_dev_idx; 
    604                 make_global_index(i, &id); 
    605                 break; 
    606             } else if (id==PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV &&  
    607                 drv->play_dev_idx >= 0)  
    608             { 
    609                 id = drv->play_dev_idx; 
    610                 make_global_index(i, &id); 
    611                 break; 
    612             } 
    613         } 
    614  
    615         if (id < 0) { 
    616             return PJMEDIA_EAUD_NODEFDEV; 
    617         } 
    618     } 
    619  
    620     f_id = GET_FID(aud_subsys.dev_list[id]); 
    621     index = GET_INDEX(aud_subsys.dev_list[id]); 
    622  
    623     if (f_id < 0 || f_id >= (int)aud_subsys.drv_cnt) 
    624         return PJMEDIA_EAUD_INVDEV; 
    625  
    626     if (index < 0 || index >= (int)aud_subsys.drv[f_id].dev_cnt) 
    627         return PJMEDIA_EAUD_INVDEV; 
    628  
    629     *p_f = aud_subsys.drv[f_id].f; 
    630     *p_local_index = (unsigned)index; 
    631  
    632     return PJ_SUCCESS; 
    633  
    634 } 
    635  
    636 /* API: Get device information. */ 
    637 PJ_DEF(pj_status_t) pjmedia_aud_dev_get_info(pjmedia_aud_dev_index id, 
    638                                              pjmedia_aud_dev_info *info) 
    639 { 
    640     pjmedia_aud_dev_factory *f; 
    641     unsigned index; 
    642     pj_status_t status; 
    643  
    644     PJ_ASSERT_RETURN(info && id!=PJMEDIA_AUD_INVALID_DEV, PJ_EINVAL); 
    645     PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT); 
    646  
    647     status = lookup_dev(id, &f, &index); 
    648     if (status != PJ_SUCCESS) 
    649         return status; 
    650  
    651     return f->op->get_dev_info(f, index, info); 
    652 } 
    653  
    654 /* API: find device */ 
    655 PJ_DEF(pj_status_t) pjmedia_aud_dev_lookup( const char *drv_name, 
    656                                             const char *dev_name, 
    657                                             pjmedia_aud_dev_index *id) 
    658 { 
    659     pjmedia_aud_dev_factory *f = NULL; 
    660     unsigned drv_idx, dev_idx; 
    661  
    662     PJ_ASSERT_RETURN(drv_name && dev_name && id, PJ_EINVAL); 
    663     PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT); 
    664  
    665     for (drv_idx=0; drv_idx<aud_subsys.drv_cnt; ++drv_idx) { 
    666         if (!pj_ansi_stricmp(drv_name, aud_subsys.drv[drv_idx].name)) { 
    667             f = aud_subsys.drv[drv_idx].f; 
    668             break; 
    669         } 
    670     } 
    671  
    672     if (!f) 
    673         return PJ_ENOTFOUND; 
    674  
    675     for (dev_idx=0; dev_idx<aud_subsys.drv[drv_idx].dev_cnt; ++dev_idx) { 
    676         pjmedia_aud_dev_info info; 
    677         pj_status_t status; 
    678  
    679         status = f->op->get_dev_info(f, dev_idx, &info); 
    680         if (status != PJ_SUCCESS) 
    681             return status; 
    682  
    683         if (!pj_ansi_stricmp(dev_name, info.name)) 
    684             break; 
    685     } 
    686  
    687     if (dev_idx==aud_subsys.drv[drv_idx].dev_cnt) 
    688         return PJ_ENOTFOUND; 
    689  
    690     *id = dev_idx; 
    691     make_global_index(drv_idx, id); 
    692  
    693     return PJ_SUCCESS; 
    694 } 
    695  
    696 /* API: Initialize the audio device parameters with default values for the 
    697  * specified device. 
    698  */ 
    699 PJ_DEF(pj_status_t) pjmedia_aud_dev_default_param(pjmedia_aud_dev_index id, 
    700                                                   pjmedia_aud_param *param) 
    701 { 
    702     pjmedia_aud_dev_factory *f; 
    703     unsigned index; 
    704     pj_status_t status; 
    705  
    706     PJ_ASSERT_RETURN(param && id!=PJMEDIA_AUD_INVALID_DEV, PJ_EINVAL); 
    707     PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT); 
    708  
    709     status = lookup_dev(id, &f, &index); 
    710     if (status != PJ_SUCCESS) 
    711         return status; 
    712  
    713     status = f->op->default_param(f, index, param); 
    714     if (status != PJ_SUCCESS) 
    715         return status; 
    716  
    717     /* Normalize device IDs */ 
    718     make_global_index(f->sys.drv_idx, &param->rec_id); 
    719     make_global_index(f->sys.drv_idx, &param->play_id); 
    720  
    721     return PJ_SUCCESS; 
    722 } 
    723  
    724 /* API: Open audio stream object using the specified parameters. */ 
    725 PJ_DEF(pj_status_t) pjmedia_aud_stream_create(const pjmedia_aud_param *prm, 
    726                                               pjmedia_aud_rec_cb rec_cb, 
    727                                               pjmedia_aud_play_cb play_cb, 
    728                                               void *user_data, 
    729                                               pjmedia_aud_stream **p_aud_strm) 
    730 { 
    731     pjmedia_aud_dev_factory *rec_f=NULL, *play_f=NULL, *f=NULL; 
    732     pjmedia_aud_param param; 
    733     pj_status_t status; 
    734  
    735     PJ_ASSERT_RETURN(prm && prm->dir && p_aud_strm, PJ_EINVAL); 
    736     PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT); 
    737     PJ_ASSERT_RETURN(prm->dir==PJMEDIA_DIR_CAPTURE || 
    738                      prm->dir==PJMEDIA_DIR_PLAYBACK || 
    739                      prm->dir==PJMEDIA_DIR_CAPTURE_PLAYBACK, 
    740                      PJ_EINVAL); 
    741  
    742     /* Must make copy of param because we're changing device ID */ 
    743     pj_memcpy(&param, prm, sizeof(param)); 
    744  
    745     /* Normalize rec_id */ 
    746     if (param.dir & PJMEDIA_DIR_CAPTURE) { 
    747         unsigned index; 
    748  
    749         if (param.rec_id < 0) 
    750             param.rec_id = PJMEDIA_AUD_DEFAULT_CAPTURE_DEV; 
    751  
    752         status = lookup_dev(param.rec_id, &rec_f, &index); 
    753         if (status != PJ_SUCCESS) 
    754             return status; 
    755  
    756         param.rec_id = index; 
    757         f = rec_f; 
    758     } 
    759  
    760     /* Normalize play_id */ 
    761     if (param.dir & PJMEDIA_DIR_PLAYBACK) { 
    762         unsigned index; 
    763  
    764         if (param.play_id < 0) 
    765             param.play_id = PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV; 
    766  
    767         status = lookup_dev(param.play_id, &play_f, &index); 
    768         if (status != PJ_SUCCESS) 
    769             return status; 
    770  
    771         param.play_id = index; 
    772         f = play_f; 
    773     } 
    774  
    775     PJ_ASSERT_RETURN(f != NULL, PJ_EBUG); 
    776  
    777     /* For now, rec_id and play_id must belong to the same factory */ 
    778     PJ_ASSERT_RETURN((param.dir != PJMEDIA_DIR_CAPTURE_PLAYBACK) ||  
    779                      (rec_f == play_f), 
    780                      PJMEDIA_EAUD_INVDEV); 
    781  
    782     /* Create the stream */ 
    783     status = f->op->create_stream(f, &param, rec_cb, play_cb, 
    784                                   user_data, p_aud_strm); 
    785     if (status != PJ_SUCCESS) 
    786         return status; 
    787  
    788     /* Assign factory id to the stream */ 
    789     (*p_aud_strm)->sys.drv_idx = f->sys.drv_idx; 
    790     return PJ_SUCCESS; 
    791 } 
    792  
    793 /* API: Get the running parameters for the specified audio stream. */ 
    794 PJ_DEF(pj_status_t) pjmedia_aud_stream_get_param(pjmedia_aud_stream *strm, 
    795                                                  pjmedia_aud_param *param) 
    796 { 
    797     pj_status_t status; 
    798  
    799     PJ_ASSERT_RETURN(strm && param, PJ_EINVAL); 
    800     PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT); 
    801  
    802     status = strm->op->get_param(strm, param); 
    803     if (status != PJ_SUCCESS) 
    804         return status; 
    805  
    806     /* Normalize device id's */ 
    807     make_global_index(strm->sys.drv_idx, &param->rec_id); 
    808     make_global_index(strm->sys.drv_idx, &param->play_id); 
    809  
    810     return PJ_SUCCESS; 
    811 } 
    812  
    813 /* API: Get the value of a specific capability of the audio stream. */ 
    814 PJ_DEF(pj_status_t) pjmedia_aud_stream_get_cap(pjmedia_aud_stream *strm, 
    815                                                pjmedia_aud_dev_cap cap, 
    816                                                void *value) 
    817 { 
    818     return strm->op->get_cap(strm, cap, value); 
    819 } 
    820  
    821 /* API: Set the value of a specific capability of the audio stream. */ 
    822 PJ_DEF(pj_status_t) pjmedia_aud_stream_set_cap(pjmedia_aud_stream *strm, 
    823                                                pjmedia_aud_dev_cap cap, 
    824                                                const void *value) 
    825 { 
    826     return strm->op->set_cap(strm, cap, value); 
    827 } 
    828  
    829 /* API: Start the stream. */ 
    830 PJ_DEF(pj_status_t) pjmedia_aud_stream_start(pjmedia_aud_stream *strm) 
    831 { 
    832     return strm->op->start(strm); 
    833 } 
    834  
    835 /* API: Stop the stream. */ 
    836 PJ_DEF(pj_status_t) pjmedia_aud_stream_stop(pjmedia_aud_stream *strm) 
    837 { 
    838     return strm->op->stop(strm); 
    839 } 
    840  
    841 /* API: Destroy the stream. */ 
    842 PJ_DEF(pj_status_t) pjmedia_aud_stream_destroy(pjmedia_aud_stream *strm) 
    843 { 
    844     return strm->op->destroy(strm); 
    845 } 
    846  
    847  
Note: See TracChangeset for help on using the changeset viewer.