Ignore:
Timestamp:
Feb 22, 2009 12:00:12 PM (15 years ago)
Author:
bennylp
Message:
  • New convention about default audio device ID (now there is different ID for default capture/playback device. It should be backward compatible)
  • Fixed crash if sound port is unable to open sound device
  • Testing with the switchboard
Location:
pjproject/branches/projects/aps-direct
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/aps-direct/pjmedia/include/pjmedia-audiodev/audiodev.h

    r2468 r2469  
    5757typedef pj_int32_t pjmedia_aud_dev_index; 
    5858 
    59 /**  
    60  * Constant to denote default device  
    61  */ 
    62 #define PJMEDIA_AUD_DEV_DEFAULT  (-1) 
     59/** 
     60 * Device index constants. 
     61 */ 
     62enum 
     63{ 
     64    /**  
     65     * Constant to denote default capture device  
     66     */ 
     67    PJMEDIA_AUD_DEFAULT_CAPTURE_DEV = -1, 
     68 
     69    /**  
     70     * Constant to denote default playback device  
     71     */ 
     72    PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV = -2, 
     73 
     74    /** 
     75     * Constant to denote invalid device index. 
     76     */ 
     77    PJMEDIA_AUD_INVALID_DEV = -3 
     78}; 
     79 
    6380 
    6481/**  
     
    597614 
    598615 
     616/* Audio subsystem not initialized */ 
     617#define PJMEDIA_EAUD_INIT       -1 
     618 
    599619/* Invalid audio device */ 
    600620#define PJMEDIA_EAUD_INVDEV     -1 
     
    603623#define PJMEDIA_EAUD_NODEV      -1 
    604624 
     625/* Unable to find default device */ 
     626#define PJMEDIA_EAUD_NODEFDEV   -1 
     627 
    605628/* Device not ready */ 
    606629#define PJMEDIA_EAUD_NOTREADY   -1 
  • pjproject/branches/projects/aps-direct/pjmedia/include/pjmedia-audiodev/audiodev_imp.h

    r2468 r2469  
    101101struct pjmedia_aud_dev_factory 
    102102{ 
    103     /** Internal data to be initialized by the framework. */ 
     103    /** Internal data to be initialized by audio subsystem. */ 
    104104    struct { 
    105         unsigned    id; 
    106     } internal; 
     105        /** Driver index */ 
     106        unsigned drv_idx; 
     107    } sys; 
    107108 
    108109    /** Operations */ 
     
    159160struct pjmedia_aud_stream 
    160161{ 
    161     /** Factory id (internal) */ 
    162     unsigned factory_id; 
     162    /** Internal data to be initialized by audio subsystem */ 
     163    struct { 
     164        /** Driver index */ 
     165        unsigned drv_idx; 
     166    } sys; 
    163167 
    164168    /** Operations */ 
  • pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia-audiodev/audiodev.c

    r2468 r2469  
    8080    unsigned                 dev_cnt;   /* Number of devices                */ 
    8181    unsigned                 start_idx; /* Start index in global list       */ 
     82    int                      rec_dev_idx;/* Default capture device.         */ 
     83    int                      play_dev_idx;/* Default playback device        */ 
     84    int                      dev_idx;   /* Default device.                  */ 
    8285}; 
    8386 
     
    97100 
    98101 
     102/* Internal: init driver */ 
     103static pj_status_t init_driver(unsigned drv_idx) 
     104{ 
     105    struct driver *drv = &aud_subsys.drv[drv_idx]; 
     106    pjmedia_aud_dev_factory *f; 
     107    unsigned i, dev_cnt; 
     108    pj_status_t status; 
     109 
     110    /* Create the factory */ 
     111    f = (*drv->create)(aud_subsys.pf); 
     112    if (!f) 
     113        return PJ_EUNKNOWN; 
     114 
     115    /* Call factory->init() */ 
     116    status = f->op->init(f); 
     117    if (status != PJ_SUCCESS) { 
     118        f->op->destroy(f); 
     119        return status; 
     120    } 
     121 
     122    /* Get number of devices */ 
     123    dev_cnt = f->op->get_dev_count(f); 
     124    if (dev_cnt + aud_subsys.dev_cnt > MAX_DEVS) { 
     125        PJ_LOG(4,(THIS_FILE, "%d device(s) cannot be registered because" 
     126                              " there are too many devices", 
     127                              aud_subsys.dev_cnt + dev_cnt - MAX_DEVS)); 
     128        dev_cnt = MAX_DEVS - aud_subsys.dev_cnt; 
     129    } 
     130    if (dev_cnt == 0) { 
     131        f->op->destroy(f); 
     132        return PJMEDIA_EAUD_NODEV; 
     133    } 
     134 
     135    /* Fill in default devices */ 
     136    drv->play_dev_idx = drv->rec_dev_idx = drv->dev_idx = -1; 
     137    for (i=0; i<dev_cnt; ++i) { 
     138        pjmedia_aud_dev_info info; 
     139 
     140        status = f->op->get_dev_info(f, i, &info); 
     141        if (status != PJ_SUCCESS) { 
     142            f->op->destroy(f); 
     143            return status; 
     144        } 
     145 
     146        if (drv->name[0]=='\0') { 
     147            /* Set driver name */ 
     148            pj_ansi_strncpy(drv->name, info.driver, sizeof(drv->name)); 
     149            drv->name[sizeof(drv->name)-1] = '\0'; 
     150        } 
     151 
     152        if (drv->play_dev_idx < 0 && info.output_count) { 
     153            /* Set default playback device */ 
     154            drv->play_dev_idx = i; 
     155        } 
     156        if (drv->rec_dev_idx < 0 && info.input_count) { 
     157            /* Set default capture device */ 
     158            drv->rec_dev_idx = i; 
     159        } 
     160        if (drv->dev_idx < 0 && info.input_count && 
     161            info.output_count) 
     162        { 
     163            /* Set default capture and playback device */ 
     164            drv->dev_idx = i; 
     165        } 
     166 
     167        if (drv->play_dev_idx >= 0 && drv->rec_dev_idx >= 0 &&  
     168            drv->dev_idx >= 0)  
     169        { 
     170            /* Done. */ 
     171            break; 
     172        } 
     173    } 
     174 
     175    /* Register the factory */ 
     176    drv->f = f; 
     177    drv->f->sys.drv_idx = drv_idx; 
     178    drv->start_idx = aud_subsys.dev_cnt; 
     179    drv->dev_cnt = dev_cnt; 
     180 
     181    /* Register devices to global list */ 
     182    for (i=0; i<dev_cnt; ++i) { 
     183        aud_subsys.dev_list[aud_subsys.dev_cnt++] = MAKE_DEV_ID(drv_idx, i); 
     184    } 
     185 
     186    return PJ_SUCCESS; 
     187} 
     188 
     189/* Internal: deinit driver */ 
     190static void deinit_driver(unsigned drv_idx) 
     191{ 
     192    struct driver *drv = &aud_subsys.drv[drv_idx]; 
     193 
     194    if (drv->f) { 
     195        drv->f->op->destroy(drv->f); 
     196        drv->f = NULL; 
     197    } 
     198 
     199    drv->dev_cnt = 0; 
     200    drv->play_dev_idx = drv->rec_dev_idx = drv->dev_idx = -1; 
     201} 
    99202 
    100203/* API: Initialize the audio subsystem. */ 
     
    121224    /* Initialize each factory and build the device ID list */ 
    122225    for (i=0; i<aud_subsys.drv_cnt; ++i) { 
    123         pjmedia_aud_dev_factory *f; 
    124         pjmedia_aud_dev_info info; 
    125         unsigned j, dev_cnt; 
    126  
    127         /* Create the factory */ 
    128         f = (*aud_subsys.drv[i].create)(pf); 
    129         if (!f) 
     226        status = init_driver(i); 
     227        if (status != PJ_SUCCESS) { 
     228            deinit_driver(i); 
    130229            continue; 
    131  
    132         /* Call factory->init() */ 
    133         status = f->op->init(f); 
    134         if (status != PJ_SUCCESS) { 
    135             f->op->destroy(f); 
    136             continue; 
    137         } 
    138  
    139         /* Build device list */ 
    140         dev_cnt = f->op->get_dev_count(f); 
    141         if (dev_cnt == 0) { 
    142             f->op->destroy(f); 
    143             continue; 
    144         } 
    145  
    146         /* Get one device info */ 
    147         status = f->op->get_dev_info(f, 0, &info); 
    148         if (status != PJ_SUCCESS) { 
    149             f->op->destroy(f); 
    150             continue; 
    151         } 
    152  
    153         /* Register the factory */ 
    154         aud_subsys.drv[i].f = f; 
    155         aud_subsys.drv[i].f->internal.id = i; 
    156         aud_subsys.drv[i].start_idx = aud_subsys.dev_cnt; 
    157         pj_ansi_strncpy(aud_subsys.drv[i].name, info.driver, 
    158                         sizeof(aud_subsys.drv[i].name)); 
    159         aud_subsys.drv[i].name[sizeof(aud_subsys.drv[i].name)-1] = '\0'; 
    160  
    161         /* Register devices */ 
    162         if (aud_subsys.dev_cnt + dev_cnt > MAX_DEVS) { 
    163             PJ_LOG(4,(THIS_FILE, "%d device(s) cannot be registered because" 
    164                                   " there are too many sound devices", 
    165                                   aud_subsys.dev_cnt + dev_cnt - MAX_DEVS)); 
    166             dev_cnt = MAX_DEVS - aud_subsys.dev_cnt; 
    167         } 
    168         for (j=0; j<dev_cnt; ++j) { 
    169             aud_subsys.dev_list[aud_subsys.dev_cnt++] = MAKE_DEV_ID(i, j); 
    170         } 
    171  
    172     } 
    173  
    174     return aud_subsys.drv_cnt ? PJ_SUCCESS : status; 
     230        } 
     231    } 
     232 
     233    return aud_subsys.dev_cnt ? PJ_SUCCESS : status; 
    175234} 
    176235 
     
    195254 
    196255    for (i=0; i<aud_subsys.drv_cnt; ++i) { 
    197         pjmedia_aud_dev_factory *f = aud_subsys.drv[i].f; 
    198  
    199         if (!f) 
    200             continue; 
    201  
    202         f->op->destroy(f); 
    203         aud_subsys.drv[i].f = NULL; 
    204     } 
    205  
     256        deinit_driver(i); 
     257    } 
     258 
     259    aud_subsys.pf = NULL; 
    206260    return PJ_SUCCESS; 
    207261} 
     
    234288{ 
    235289    return aud_subsys.dev_cnt; 
     290} 
     291 
     292/* Internal: convert local index to global device index */ 
     293static pj_status_t make_global_index(unsigned drv_idx,  
     294                                     pjmedia_aud_dev_index *id) 
     295{ 
     296    if (*id < 0) { 
     297        return PJ_SUCCESS; 
     298    } 
     299 
     300    /* Check that factory still exists */ 
     301    PJ_ASSERT_RETURN(aud_subsys.drv[drv_idx].f, PJ_EBUG); 
     302 
     303    /* Check that device index is valid */ 
     304    PJ_ASSERT_RETURN(*id>=0 && *id<(int)aud_subsys.drv[drv_idx].dev_cnt,  
     305                     PJ_EBUG); 
     306 
     307    *id += aud_subsys.drv[drv_idx].start_idx; 
     308    return PJ_SUCCESS; 
    236309} 
    237310 
     
    243316    int f_id, index; 
    244317 
    245     if (id == PJMEDIA_AUD_DEV_DEFAULT) 
    246         id = DEFAULT_DEV_ID; 
    247  
    248     PJ_ASSERT_RETURN(id>=0 && id<(int)aud_subsys.dev_cnt,  
    249                      PJMEDIA_EAUD_INVDEV); 
     318    if (id < 0) { 
     319        unsigned i; 
     320 
     321        if (id == PJMEDIA_AUD_INVALID_DEV) 
     322            return PJMEDIA_EAUD_INVDEV; 
     323 
     324        for (i=0; i<aud_subsys.drv_cnt; ++i) { 
     325            struct driver *drv = &aud_subsys.drv[i]; 
     326            if (drv->dev_idx >= 0) { 
     327                id = drv->dev_idx; 
     328                make_global_index(i, &id); 
     329                break; 
     330            } else if (id==PJMEDIA_AUD_DEFAULT_CAPTURE_DEV &&  
     331                drv->rec_dev_idx >= 0)  
     332            { 
     333                id = drv->rec_dev_idx; 
     334                make_global_index(i, &id); 
     335                break; 
     336            } else if (id==PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV &&  
     337                drv->play_dev_idx >= 0)  
     338            { 
     339                id = drv->play_dev_idx; 
     340                make_global_index(i, &id); 
     341                break; 
     342            } 
     343        } 
     344 
     345        if (id < 0) { 
     346            return PJMEDIA_EAUD_NODEFDEV; 
     347        } 
     348    } 
    250349 
    251350    f_id = GET_FID(aud_subsys.dev_list[id]); 
     
    263362    return PJ_SUCCESS; 
    264363 
    265 } 
    266  
    267 /* Internal: convert local index to global device index */ 
    268 static pj_status_t make_global_index(pjmedia_aud_dev_factory *f, 
    269                                      pjmedia_aud_dev_index *id) 
    270 { 
    271     unsigned f_id = f->internal.id; 
    272  
    273     if (*id == PJMEDIA_AUD_DEV_DEFAULT) 
    274         return PJ_SUCCESS; 
    275  
    276     /* Check that factory still exists */ 
    277     PJ_ASSERT_RETURN(f, PJ_EBUG); 
    278  
    279     /* Check that device index is valid */ 
    280     PJ_ASSERT_RETURN(*id>=0 && *id<(int)aud_subsys.drv[f_id].dev_cnt, PJ_EBUG); 
    281  
    282     *id += aud_subsys.drv[f_id].start_idx; 
    283     return PJ_SUCCESS; 
    284364} 
    285365 
     
    292372    pj_status_t status; 
    293373 
    294     PJ_ASSERT_RETURN(info, PJ_EINVAL); 
     374    PJ_ASSERT_RETURN(info && id!=PJMEDIA_AUD_INVALID_DEV, PJ_EINVAL); 
     375    PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT); 
    295376 
    296377    status = lookup_dev(id, &f, &index); 
     
    307388{ 
    308389    pjmedia_aud_dev_factory *f = NULL; 
    309     unsigned i, j; 
     390    unsigned drv_idx, dev_idx; 
    310391 
    311392    PJ_ASSERT_RETURN(drv_name && dev_name && id, PJ_EINVAL); 
    312  
    313     for (i=0; i<aud_subsys.drv_cnt; ++i) { 
    314         if (!pj_ansi_stricmp(drv_name, aud_subsys.drv[i].name)) { 
    315             f = aud_subsys.drv[i].f; 
     393    PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT); 
     394 
     395    for (drv_idx=0; drv_idx<aud_subsys.drv_cnt; ++drv_idx) { 
     396        if (!pj_ansi_stricmp(drv_name, aud_subsys.drv[drv_idx].name)) { 
     397            f = aud_subsys.drv[drv_idx].f; 
    316398            break; 
    317399        } 
     
    321403        return PJ_ENOTFOUND; 
    322404 
    323     for (j=0; j<aud_subsys.drv[i].dev_cnt; ++j) { 
     405    for (dev_idx=0; dev_idx<aud_subsys.drv[drv_idx].dev_cnt; ++dev_idx) { 
    324406        pjmedia_aud_dev_info info; 
    325407        pj_status_t status; 
    326408 
    327         status = f->op->get_dev_info(f, j, &info); 
     409        status = f->op->get_dev_info(f, dev_idx, &info); 
    328410        if (status != PJ_SUCCESS) 
    329411            return status; 
     
    333415    } 
    334416 
    335     if (j==aud_subsys.drv[i].dev_cnt) 
     417    if (dev_idx==aud_subsys.drv[drv_idx].dev_cnt) 
    336418        return PJ_ENOTFOUND; 
    337419 
    338     *id = j; 
    339     make_global_index(f, id); 
     420    *id = dev_idx; 
     421    make_global_index(drv_idx, id); 
    340422 
    341423    return PJ_SUCCESS; 
     
    352434    pj_status_t status; 
    353435 
    354     PJ_ASSERT_RETURN(param, PJ_EINVAL); 
     436    PJ_ASSERT_RETURN(param && id!=PJMEDIA_AUD_INVALID_DEV, PJ_EINVAL); 
     437    PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT); 
    355438 
    356439    status = lookup_dev(id, &f, &index); 
     
    363446 
    364447    /* Normalize device IDs */ 
    365     make_global_index(f, &param->rec_id); 
    366     make_global_index(f, &param->play_id); 
     448    make_global_index(f->sys.drv_idx, &param->rec_id); 
     449    make_global_index(f->sys.drv_idx, &param->play_id); 
    367450 
    368451    return PJ_SUCCESS; 
     
    381464 
    382465    PJ_ASSERT_RETURN(prm && prm->dir && p_aud_strm, PJ_EINVAL); 
     466    PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT); 
    383467 
    384468    /* Must make copy of param because we're changing device ID */ 
     
    389473        unsigned index; 
    390474 
     475        if (param.rec_id < 0) 
     476            param.rec_id = PJMEDIA_AUD_DEFAULT_CAPTURE_DEV; 
     477 
    391478        status = lookup_dev(param.rec_id, &rec_f, &index); 
    392479        if (status != PJ_SUCCESS) 
     
    401488        unsigned index; 
    402489 
     490        if (param.play_id < 0) 
     491            param.play_id = PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV; 
     492 
    403493        status = lookup_dev(param.play_id, &play_f, &index); 
    404494        if (status != PJ_SUCCESS) 
     
    409499 
    410500        /* For now, rec_id and play_id must belong to the same factory */ 
    411         PJ_ASSERT_RETURN(rec_f == play_f, PJ_EINVAL); 
     501        PJ_ASSERT_RETURN(rec_f == play_f, PJMEDIA_EAUD_INVDEV); 
    412502    } 
    413503 
     
    420510 
    421511    /* Assign factory id to the stream */ 
    422     (*p_aud_strm)->factory_id = f->internal.id; 
     512    (*p_aud_strm)->sys.drv_idx = f->sys.drv_idx; 
    423513    return PJ_SUCCESS; 
    424514} 
     
    430520    pj_status_t status; 
    431521 
     522    PJ_ASSERT_RETURN(strm && param, PJ_EINVAL); 
     523    PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT); 
     524 
    432525    status = strm->op->get_param(strm, param); 
    433526    if (status != PJ_SUCCESS) 
     
    435528 
    436529    /* Normalize device id's */ 
    437     make_global_index(aud_subsys.drv[strm->factory_id].f, &param->rec_id); 
    438     make_global_index(aud_subsys.drv[strm->factory_id].f, &param->play_id); 
     530    make_global_index(strm->sys.drv_idx, &param->rec_id); 
     531    make_global_index(strm->sys.drv_idx, &param->play_id); 
    439532 
    440533    return PJ_SUCCESS; 
  • pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia-audiodev/pa_dev.c

    r2468 r2469  
    534534        param->dir = PJMEDIA_DIR_CAPTURE; 
    535535        param->rec_id = index; 
    536         param->play_id = PJMEDIA_AUD_DEV_DEFAULT; 
     536        param->play_id = PJMEDIA_AUD_INVALID_DEV; 
    537537    } else if (adi.output_count) { 
    538538        param->dir = PJMEDIA_DIR_PLAYBACK; 
    539539        param->play_id = index; 
    540         param->rec_id = PJMEDIA_AUD_DEV_DEFAULT; 
     540        param->rec_id = PJMEDIA_AUD_INVALID_DEV; 
    541541    } else { 
    542542        return PJMEDIA_EAUD_INVDEV; 
  • pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia-audiodev/wmme_dev.c

    r2468 r2469  
    414414        param->dir = PJMEDIA_DIR_CAPTURE; 
    415415        param->rec_id = index; 
    416         param->play_id = PJMEDIA_AUD_DEV_DEFAULT; 
     416        param->play_id = PJMEDIA_AUD_INVALID_DEV; 
    417417    } else if (di->info.output_count) { 
    418418        param->dir = PJMEDIA_DIR_PLAYBACK; 
    419419        param->play_id = index; 
    420         param->rec_id = PJMEDIA_AUD_DEV_DEFAULT; 
     420        param->rec_id = PJMEDIA_AUD_INVALID_DEV; 
    421421    } else { 
    422422        return PJMEDIA_EAUD_INVDEV; 
  • pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia/sound_port.c

    r2468 r2469  
    414414{ 
    415415    pjmedia_snd_port *snd_port; 
     416    pj_status_t status; 
    416417 
    417418    PJ_ASSERT_RETURN(pool && prm && p_port, PJ_EINVAL); 
     
    430431    pj_memcpy(&snd_port->aud_param, prm, sizeof(*prm)); 
    431432     
    432     *p_port = snd_port; 
    433  
    434  
    435433    /* Start sound device immediately. 
    436434     * If there's no port connected, the sound callback will return 
    437435     * empty signal. 
    438436     */ 
    439     return start_sound_device( pool, snd_port ); 
    440  
     437    status = start_sound_device( pool, snd_port ); 
     438    if (status != PJ_SUCCESS) { 
     439        pjmedia_snd_port_destroy(snd_port); 
     440        return status; 
     441    } 
     442 
     443    *p_port = snd_port; 
     444    return PJ_SUCCESS; 
    441445} 
    442446 
  • pjproject/branches/projects/aps-direct/pjsip/src/pjsua-lib/pjsua_core.c

    r2468 r2469  
    584584 
    585585    /* Set default sound device ID */ 
    586     pjsua_var.cap_dev = pjsua_var.play_dev = -1; 
     586    pjsua_var.cap_dev = PJMEDIA_AUD_DEFAULT_CAPTURE_DEV; 
     587    pjsua_var.play_dev = PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV; 
    587588 
    588589    /* Init caching pool. */ 
  • pjproject/branches/projects/aps-direct/pjsip/src/pjsua-lib/pjsua_media.c

    r2468 r2469  
    24002400    } 
    24012401 
     2402    /* Normalize device ID with new convention about default device ID */ 
     2403    if (playback_dev == PJMEDIA_AUD_DEFAULT_CAPTURE_DEV) 
     2404        playback_dev = PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV; 
     2405 
    24022406    /* Close existing sound port */ 
    24032407    close_snd_dev(); 
     
    24192423    status = pjmedia_aud_dev_default_param(capture_dev, &param); 
    24202424    if (status != PJ_SUCCESS) { 
     2425        pjsua_perror(THIS_FILE, "Error retrieving default audio " 
     2426                                "device parameters", status); 
    24212427        return status; 
    24222428    } 
Note: See TracChangeset for help on using the changeset viewer.