Changeset 2493 for pjproject


Ignore:
Timestamp:
Mar 9, 2009 1:08:16 PM (16 years ago)
Author:
bennylp
Message:

BIG refactoring in pjsua_media.c:

  • switchboard/conf detection is done at run-time, removing #ifdefs
    • use one function, open_snd_dev() to open device
    • use one function, create_aud_param() to initialize audio parameters:
      • get the default from device
      • override with user settings previously done with pjsua_snd_set_setting() (new API)
  • added new API to set/get sound device settings. The settings are

semi permanent, it will be used for future opening of sound dev:

  • pjsua_snd_set_setting()
  • pjsua_snd_get_setting()
  • snd_auto_close_time default value changed to 1 (from -1)
  • both pjsua_enum_snd_devs() and pjsua_enum_aud_devs() API are now

supported (previously it was done with #ifdef).

  • make_call() will not open the sound device is switchboard is

used

Location:
pjproject/branches/projects/aps-direct/pjsip
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/aps-direct/pjsip/include/pjsua-lib/pjsua.h

    r2480 r2493  
    42874287    /** 
    42884288     * Specify idle time of sound device before it is automatically closed, 
    4289      * in seconds. 
    4290      * 
    4291      * Default : -1 (Disable the auto-close feature of sound device) 
     4289     * in seconds. Use value -1 to disable the auto-close feature of sound 
     4290     * device 
     4291     * 
     4292     * Default : 1 
    42924293     */ 
    42934294    int                 snd_auto_close_time; 
     
    48024803 
    48034804/** 
    4804  * Enum all sound devices installed in the system. 
     4805 * Enum all audio devices installed in the system. 
    48054806 * 
    48064807 * @param info          Array of info to be initialized. 
     
    48104811 * 
    48114812 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     4813 */ 
     4814PJ_DECL(pj_status_t) pjsua_enum_aud_devs(pjmedia_aud_dev_info info[], 
     4815                                         unsigned *count); 
     4816 
     4817/** 
     4818 * Enum all sound devices installed in the system (old API). 
     4819 * 
     4820 * @param info          Array of info to be initialized. 
     4821 * @param count         On input, specifies max elements in the array. 
     4822 *                      On return, it contains actual number of elements 
     4823 *                      that have been initialized. 
     4824 * 
     4825 * @return              PJ_SUCCESS on success, or the appropriate error code. 
    48124826 * 
    48134827 * 
     
    48194833 * 
    48204834 */ 
    4821 #if PJMEDIA_AUDIO_API==PJMEDIA_AUDIO_API_NEW_ONLY 
    4822 PJ_DECL(pj_status_t) pjsua_enum_snd_devs(pjmedia_aud_dev_info info[], 
    4823                                          unsigned *count); 
    4824 #else 
    48254835PJ_DECL(pj_status_t) pjsua_enum_snd_devs(pjmedia_snd_dev_info info[], 
    48264836                                         unsigned *count); 
    4827 #endif 
    4828  
    48294837 
    48304838/** 
     
    48984906 
    48994907/** 
    4900  * Change the echo cancellation settings. The behavior of this function  
    4901  * depends on whether the sound device is currently active, and if it is, 
    4902  * whether device or software AEC is being used.  
     4908 * Change the echo cancellation settings. Application may also use the 
     4909 * #pjsua_snd_set_setting() to retrieve the echo cancellation setting. 
     4910 * 
     4911 * The behavior of this function depends on whether the sound device is 
     4912 * currently active, and if it is, whether device or software AEC is  
     4913 * being used.  
    49034914 * 
    49044915 * If the sound device is currently active, and if the device supports AEC, 
     
    49294940 
    49304941/** 
    4931  * Get current echo canceller tail length. 
     4942 * Get current echo canceller tail length. Application may also use the 
     4943 * #pjsua_snd_set_setting() to retrieve the echo cancellation setting. 
    49324944 * 
    49334945 * @param p_tail_ms     Pointer to receive the tail length, in miliseconds.  
     
    49454957 
    49464958/** 
    4947  * Get active audio device stream instance. 
    4948  * 
    4949  * @return              Audio device stream instance if any, otherwise  
    4950  *                      NULL will be returned. 
    4951  */ 
    4952 PJ_DECL(pjmedia_aud_stream*) pjsua_get_aud_stream(); 
     4959 * Check whether the sound device is currently active. The sound device 
     4960 * may be inactive if the application has set the auto close feature to 
     4961 * non-zero (the snd_auto_close_time setting in #pjsua_media_config), or 
     4962 * if null sound device or no sound device has been configured via the 
     4963 * #pjsua_set_no_snd_dev() function. 
     4964 */ 
     4965PJ_DECL(pj_bool_t) pjsua_snd_is_active(void); 
     4966 
     4967     
     4968/** 
     4969 * Configure sound device setting to the sound device being used. If sound  
     4970 * device is currently active, the function will forward the setting to the 
     4971 * sound device instance to be applied immediately, if it supports it.  
     4972 * 
     4973 * The setting will be saved for future opening of the sound device, if the  
     4974 * "keep" argument is set to non-zero. If the sound device is currently 
     4975 * inactive, and the "keep" argument is false, this function will return 
     4976 * error. 
     4977 *  
     4978 * Note that in case the setting is kept for future use, it will be applied 
     4979 * to any devices, even when application has changed the sound device to be 
     4980 * used. 
     4981 * 
     4982 * See also #pjmedia_aud_stream_set_cap() for more information about setting 
     4983 * an audio device capability. 
     4984 * 
     4985 * @param cap           The sound device setting to change. 
     4986 * @param pval          Pointer to value. Please see #pjmedia_aud_dev_cap 
     4987 *                      documentation about the type of value to be  
     4988 *                      supplied for each setting. 
     4989 * @param keep          Specify whether the setting is to be kept for future 
     4990 *                      use. 
     4991 * 
     4992 * @return              PJ_SUCCESS on success or the appropriate error code. 
     4993 */ 
     4994PJ_DECL(pj_status_t) pjsua_snd_set_setting(pjmedia_aud_dev_cap cap, 
     4995                                           const void *pval, 
     4996                                           pj_bool_t keep); 
     4997 
     4998/** 
     4999 * Retrieve a sound device setting. If sound device is currently active, 
     5000 * the function will forward the request to the sound device. If sound device 
     5001 * is currently inactive, and if application had previously set the setting 
     5002 * and mark the setting as kept, then that setting will be returned. 
     5003 * Otherwise, this function will return error. 
     5004 * 
     5005 * @param cap           The sound device setting to retrieve. 
     5006 * @param pval          Pointer to receive the value.  
     5007 *                      Please see #pjmedia_aud_dev_cap documentation about 
     5008 *                      the type of value to be supplied for each setting. 
     5009 * 
     5010 * @return              PJ_SUCCESS on success or the appropriate error code. 
     5011 */ 
     5012PJ_DECL(pj_status_t) pjsua_snd_get_setting(pjmedia_aud_dev_cap cap, 
     5013                                           void *pval); 
    49535014 
    49545015 
  • pjproject/branches/projects/aps-direct/pjsip/include/pjsua-lib/pjsua_internal.h

    r2394 r2493  
    273273    pjsua_conf_setting   mconf_cfg; /**< Additionan conf. bridge. param */ 
    274274    pjmedia_conf        *mconf;     /**< Conference bridge.             */ 
    275     int                  cap_dev;   /**< Capture device ID.             */ 
    276     int                  play_dev;  /**< Playback device ID.            */ 
     275    pj_bool_t            is_mswitch;/**< Are we using audio switchboard 
     276                                         (a.k.a APS-Direct)             */ 
     277 
     278    /* Sound device */ 
     279    pjmedia_aud_dev_index cap_dev;  /**< Capture device ID.             */ 
     280    pjmedia_aud_dev_index play_dev; /**< Playback device ID.            */ 
     281    pj_uint32_t          aud_svmask;/**< Which settings to save         */ 
     282    pjmedia_aud_param    aud_param; /**< User settings to sound dev     */ 
     283    pj_bool_t            aud_open_cnt;/**< How many # device is opened  */ 
    277284    pj_bool_t            no_snd;    /**< No sound (app will manage it)  */ 
    278285    pj_pool_t           *snd_pool;  /**< Sound's private pool.          */ 
  • pjproject/branches/projects/aps-direct/pjsip/src/pjsua-lib/pjsua_call.c

    r2394 r2493  
    371371    PJSUA_LOCK(); 
    372372 
    373     /* Create sound port if none is instantiated */ 
    374     if (pjsua_var.snd_port==NULL && pjsua_var.null_snd==NULL &&  
    375         !pjsua_var.no_snd)  
     373    /* Create sound port if none is instantiated, to check if sound device 
     374     * can be used. But only do this with the conference bridge, as with  
     375     * audio switchboard (i.e. APS-Direct), we can only open the sound  
     376     * device once the correct format has been known 
     377     */ 
     378    if (!pjsua_var.is_mswitch && pjsua_var.snd_port==NULL &&  
     379        pjsua_var.null_snd==NULL && !pjsua_var.no_snd)  
    376380    { 
    377381        pj_status_t status; 
  • pjproject/branches/projects/aps-direct/pjsip/src/pjsua-lib/pjsua_core.c

    r2469 r2493  
    181181    cfg->snd_play_latency = PJMEDIA_SND_DEFAULT_PLAY_LATENCY; 
    182182    cfg->jb_init = cfg->jb_min_pre = cfg->jb_max_pre = cfg->jb_max = -1; 
    183     cfg->snd_auto_close_time = -1; 
     183    cfg->snd_auto_close_time = 1; 
    184184 
    185185    cfg->turn_conn_type = PJ_TURN_TP_UDP; 
  • pjproject/branches/projects/aps-direct/pjsip/src/pjsua-lib/pjsua_media.c

    r2486 r2493  
    3636static pj_uint16_t next_rtp_port; 
    3737 
     38/* Open sound dev */ 
     39static pj_status_t open_snd_dev(pjmedia_aud_param *param); 
    3840/* Close existing sound device */ 
    3941static void close_snd_dev(void); 
     42/* Create audio device param */ 
     43static pj_status_t create_aud_param(pjmedia_aud_param *param, 
     44                                    pjmedia_aud_dev_index capture_dev, 
     45                                    pjmedia_aud_dev_index playback_dev, 
     46                                    unsigned clock_rate, 
     47                                    unsigned channel_count, 
     48                                    unsigned samples_per_frame, 
     49                                    unsigned bits_per_sample); 
    4050 
    4151 
     
    6070    /* To suppress warning about unused var when all codecs are disabled */ 
    6171    PJ_UNUSED_ARG(codec_id); 
     72 
     73    /* Specify which audio device settings are save-able */ 
     74    pjsua_var.aud_svmask = 0xFFFFFFFF; 
     75    /* These are not-settable */ 
     76    pjsua_var.aud_svmask &= ~(PJMEDIA_AUD_DEV_CAP_EXT_FORMAT | 
     77                              PJMEDIA_AUD_DEV_CAP_INPUT_SIGNAL_METER | 
     78                              PJMEDIA_AUD_DEV_CAP_OUTPUT_SIGNAL_METER); 
    6279 
    6380    /* Copy configuration */ 
     
    236253        return status; 
    237254    } 
     255 
     256    /* Are we using the audio switchboard (a.k.a APS-Direct)? */ 
     257    pjsua_var.is_mswitch = pjmedia_conf_get_master_port(pjsua_var.mconf) 
     258                            ->info.signature == PJMEDIA_CONF_SWITCH_SIGNATURE; 
    238259 
    239260    /* Create null port just in case user wants to use null sound. */ 
     
    15101531} 
    15111532 
    1512 #if PJMEDIA_CONF_USE_SWITCH_BOARD 
    1513  
    1514 /* 
    1515  * Open sound device with extended setting. 
    1516  */ 
    1517 static pj_status_t open_snd_dev_ext(pjmedia_aud_param *param) 
    1518 { 
    1519     pjmedia_port *conf_port; 
    1520     pj_status_t status; 
    1521  
    1522     PJ_ASSERT_RETURN(param, PJ_EINVAL); 
    1523  
    1524     /* Check if NULL sound device is used */ 
    1525     if (NULL_SND_DEV_ID==param->rec_id || NULL_SND_DEV_ID==param->play_id) { 
    1526         return pjsua_set_null_snd_dev(); 
    1527     } 
    1528  
    1529     /* Close existing sound port */ 
    1530     close_snd_dev(); 
    1531  
    1532     /* Create memory pool for sound device. */ 
    1533     pjsua_var.snd_pool = pjsua_pool_create("pjsua_snd", 4000, 4000); 
    1534     PJ_ASSERT_RETURN(pjsua_var.snd_pool, PJ_ENOMEM); 
    1535  
    1536  
    1537     /* Get the port0 of the conference bridge. */ 
    1538     conf_port = pjmedia_conf_get_master_port(pjsua_var.mconf); 
    1539     pj_assert(conf_port != NULL); 
    1540  
    1541     PJ_LOG(4,(THIS_FILE, "Opening sound device @%d/%d/%s", 
    1542               param->clock_rate, param->channel_count, 
    1543               (param->ext_fmt.id==PJMEDIA_FORMAT_L16?"pcm":"encoded"))); 
    1544  
    1545     status = pjmedia_snd_port_create2( pjsua_var.snd_pool,  
    1546                                        param,  &pjsua_var.snd_port); 
    1547  
    1548     /* Update port 0 info when sound dev opened successfully. */ 
    1549     if (status == PJ_SUCCESS) { 
    1550         pj_memcpy(&conf_port->info.format, &param->ext_fmt,  
    1551                   sizeof(conf_port->info.format)); 
    1552         conf_port->info.clock_rate = param->clock_rate; 
    1553         conf_port->info.samples_per_frame = param->samples_per_frame; 
    1554         conf_port->info.channel_count = param->channel_count; 
    1555         conf_port->info.bits_per_sample = 16; 
    1556     } else { 
    1557         pjsua_perror(THIS_FILE, "Unable to open sound device", status); 
    1558         return status; 
    1559     } 
    1560  
    1561     /* Connect sound port to the bridge */ 
    1562     status = pjmedia_snd_port_connect(pjsua_var.snd_port,         
    1563                                       conf_port );        
    1564     if (status != PJ_SUCCESS) {           
    1565         pjsua_perror(THIS_FILE, "Unable to connect conference port to " 
    1566                                 "sound device", status);          
    1567         pjmedia_snd_port_destroy(pjsua_var.snd_port);     
    1568         pjsua_var.snd_port = NULL;        
    1569         return status;    
    1570     } 
    1571  
    1572     /* Save the device IDs */ 
    1573     pjsua_var.cap_dev = param->rec_id; 
    1574     pjsua_var.play_dev = param->play_id; 
    1575  
    1576     /* Update sound device name. */ 
    1577     { 
    1578         pjmedia_aud_dev_info play_info; 
    1579         pjmedia_aud_stream *strm; 
    1580         pjmedia_aud_param si; 
    1581         pj_str_t tmp; 
    1582  
    1583         strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port); 
    1584         pjmedia_aud_stream_get_param(strm, &si); 
    1585         if (pjmedia_aud_dev_get_info(si.play_id, &play_info)==PJ_SUCCESS) { 
    1586             pjmedia_conf_set_port0_name(pjsua_var.mconf,  
    1587                                         pj_cstr(&tmp, play_info.name)); 
    1588         } 
    1589     }; 
    1590  
    1591     return PJ_SUCCESS; 
    1592 } 
    1593  
    1594 #endif 
    1595  
    1596  
    1597 /* Close existing sound device */ 
    1598 static void close_snd_dev(void) 
    1599 { 
    1600     /* Close sound device */ 
    1601     if (pjsua_var.snd_port) { 
    1602         pjmedia_aud_dev_info cap_info, play_info; 
    1603         pjmedia_aud_stream *strm; 
    1604         pjmedia_aud_param param; 
    1605  
    1606         strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port); 
    1607         pjmedia_aud_stream_get_param(strm, &param); 
    1608  
    1609         if (pjmedia_aud_dev_get_info(param.rec_id, &cap_info) != PJ_SUCCESS) 
    1610             cap_info.name[0] = '\0'; 
    1611         if (pjmedia_aud_dev_get_info(param.play_id, &play_info) != PJ_SUCCESS) 
    1612             play_info.name[0] = '\0'; 
    1613  
    1614         PJ_LOG(4,(THIS_FILE, "Closing %s sound playback device and " 
    1615                              "%s sound capture device", 
    1616                              play_info.name, cap_info.name)); 
    1617  
    1618         pjmedia_snd_port_disconnect(pjsua_var.snd_port); 
    1619         pjmedia_snd_port_destroy(pjsua_var.snd_port); 
    1620         pjsua_var.snd_port = NULL; 
    1621     } 
    1622  
    1623     /* Close null sound device */ 
    1624     if (pjsua_var.null_snd) { 
    1625         PJ_LOG(4,(THIS_FILE, "Closing null sound device..")); 
    1626         pjmedia_master_port_destroy(pjsua_var.null_snd, PJ_FALSE); 
    1627         pjsua_var.null_snd = NULL; 
    1628     } 
    1629  
    1630     if (pjsua_var.snd_pool)  
    1631         pj_pool_release(pjsua_var.snd_pool); 
    1632     pjsua_var.snd_pool = NULL; 
    1633 } 
    1634  
    1635  
    16361533/* 
    16371534 * Get maxinum number of conference ports. 
     
    17481645    } 
    17491646 
    1750 #if PJMEDIA_CONF_USE_SWITCH_BOARD 
    1751  
    1752     /* Check if sound device need to be reopened, i.e: its attributes 
     1647 
     1648    /* For audio switchboard (i.e. APS-Direct): 
     1649     * Check if sound device need to be reopened, i.e: its attributes 
    17531650     * (format, clock rate, channel count) must match to peer's.  
    17541651     * Note that sound device can be reopened only if it doesn't have 
    17551652     * any connection. 
    17561653     */ 
    1757     do { 
     1654    if (pjsua_var.is_mswitch) { 
    17581655        pjmedia_conf_port_info port0_info; 
    17591656        pjmedia_conf_port_info peer_info; 
     
    17901687            pjmedia_aud_param param; 
    17911688 
    1792             status = pjmedia_aud_dev_default_param(pjsua_var.cap_dev, &param); 
    1793             if (status != PJ_SUCCESS) { 
    1794                 pjsua_perror(THIS_FILE, "Error retrieving default audio " 
    1795                                         "device parameters", status); 
    1796                 return status; 
     1689            /* Create parameter based on peer info */ 
     1690            status = create_aud_param(&param, pjsua_var.cap_dev,  
     1691                                      pjsua_var.play_dev, 
     1692                                      peer_info.clock_rate, 
     1693                                      peer_info.channel_count, 
     1694                                      peer_info.samples_per_frame, 
     1695                                      peer_info.bits_per_sample); 
     1696 
     1697            /* And peer format */ 
     1698            if (peer_info.format.id != PJMEDIA_FORMAT_PCM) { 
     1699                param.flags |= PJMEDIA_AUD_DEV_CAP_EXT_FORMAT; 
     1700                param.ext_fmt = peer_info.format; 
    17971701            } 
    17981702 
    1799             param.dir = PJMEDIA_DIR_CAPTURE_PLAYBACK; 
    1800             param.rec_id = pjsua_var.cap_dev; 
    1801             param.play_id = pjsua_var.play_dev; 
    1802             param.clock_rate = peer_info.clock_rate; 
    1803             param.samples_per_frame = peer_info.samples_per_frame; 
    1804             param.channel_count = peer_info.channel_count; 
    1805             param.bits_per_sample = peer_info.bits_per_sample; 
    1806             /* Latency setting */ 
    1807             param.flags |= (PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY |  
    1808                             PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY); 
    1809             param.input_latency_ms = pjsua_var.media_cfg.snd_rec_latency; 
    1810             param.output_latency_ms = pjsua_var.media_cfg.snd_play_latency; 
    1811             /* EC settings */ 
    1812             if (pjsua_var.media_cfg.ec_tail_len) { 
    1813                 param.flags |= (PJMEDIA_AUD_DEV_CAP_EC | PJMEDIA_AUD_DEV_CAP_EC_TAIL); 
    1814                 param.ec_enabled = PJ_TRUE; 
    1815                 param.ec_tail_ms = pjsua_var.media_cfg.ec_tail_len; 
    1816             } else { 
    1817                 param.flags &= ~(PJMEDIA_AUD_DEV_CAP_EC | PJMEDIA_AUD_DEV_CAP_EC_TAIL); 
    1818             } 
    1819             /* Format */ 
    1820             param.flags |= (PJMEDIA_AUD_DEV_CAP_EXT_FORMAT |  
    1821                             PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE); 
    1822             param.ext_fmt = peer_info.format; 
    1823             //param.plc = PJ_FALSE; 
    1824             param.out_route = PJMEDIA_AUD_DEV_ROUTE_DEFAULT; 
    1825              
    1826             status = open_snd_dev_ext(&param); 
     1703            status = open_snd_dev(&param); 
    18271704            if (status != PJ_SUCCESS) { 
    18281705                pjsua_perror(THIS_FILE, "Error opening sound device", status); 
     
    18301707            } 
    18311708        } 
    1832     } while(0); 
    1833  
    1834 #else 
    1835  
    1836     /* Create sound port if none is instantiated */ 
    1837     if (pjsua_var.snd_port==NULL && pjsua_var.null_snd==NULL &&  
    1838         !pjsua_var.no_snd)  
    1839     { 
    1840         pj_status_t status; 
    1841  
    1842         status = pjsua_set_snd_dev(pjsua_var.cap_dev, pjsua_var.play_dev); 
    1843         if (status != PJ_SUCCESS) { 
    1844             pjsua_perror(THIS_FILE, "Error opening sound device", status); 
    1845             return status; 
    1846         } 
    1847     } 
    1848  
    1849 #endif 
     1709 
     1710    } else { 
     1711        /* The bridge version */ 
     1712 
     1713        /* Create sound port if none is instantiated */ 
     1714        if (pjsua_var.snd_port==NULL && pjsua_var.null_snd==NULL &&  
     1715            !pjsua_var.no_snd)  
     1716        { 
     1717            pj_status_t status; 
     1718 
     1719            status = pjsua_set_snd_dev(pjsua_var.cap_dev, pjsua_var.play_dev); 
     1720            if (status != PJ_SUCCESS) { 
     1721                pjsua_perror(THIS_FILE, "Error opening sound device", status); 
     1722                return status; 
     1723            } 
     1724        } 
     1725 
     1726    } 
    18501727 
    18511728    return pjmedia_conf_connect_port(pjsua_var.mconf, source, sink, 0); 
     
    23232200 * Enum sound devices. 
    23242201 */ 
    2325 #if PJMEDIA_AUDIO_API==PJMEDIA_AUDIO_API_NEW_ONLY 
    2326 PJ_DEF(pj_status_t) pjsua_enum_snd_devs( pjmedia_aud_dev_info info[], 
     2202 
     2203PJ_DEF(pj_status_t) pjsua_enum_aud_devs( pjmedia_aud_dev_info info[], 
    23272204                                         unsigned *count) 
    23282205{ 
     
    23452222    return PJ_SUCCESS; 
    23462223} 
    2347 #else   /* PJMEDIA_AUDIO_API */ 
     2224 
     2225 
    23482226PJ_DEF(pj_status_t) pjsua_enum_snd_devs( pjmedia_snd_dev_info info[], 
    23492227                                         unsigned *count) 
     
    23752253    return PJ_SUCCESS; 
    23762254} 
    2377 #endif 
    2378  
    2379  
    2380 /* 
    2381  * Select or change sound device. Application may call this function at 
    2382  * any time to replace current sound device. 
    2383  */ 
    2384 PJ_DEF(pj_status_t) pjsua_set_snd_dev( int capture_dev, 
    2385                                        int playback_dev) 
    2386 { 
    2387 #if PJMEDIA_CONF_USE_SWITCH_BOARD 
    2388  
    2389     pjmedia_aud_param param; 
     2255 
     2256/* Create audio device parameter to open the device */ 
     2257static pj_status_t create_aud_param(pjmedia_aud_param *param, 
     2258                                    pjmedia_aud_dev_index capture_dev, 
     2259                                    pjmedia_aud_dev_index playback_dev, 
     2260                                    unsigned clock_rate, 
     2261                                    unsigned channel_count, 
     2262                                    unsigned samples_per_frame, 
     2263                                    unsigned bits_per_sample) 
     2264{ 
    23902265    pj_status_t status; 
    23912266 
     2267    /* Normalize device ID with new convention about default device ID */ 
     2268    if (playback_dev == PJMEDIA_AUD_DEFAULT_CAPTURE_DEV) 
     2269        playback_dev = PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV; 
     2270 
    23922271    /* Create default parameters for the device */ 
    2393     status = pjmedia_aud_dev_default_param(capture_dev, &param); 
     2272    status = pjmedia_aud_dev_default_param(capture_dev, param); 
    23942273    if (status != PJ_SUCCESS) { 
    23952274        pjsua_perror(THIS_FILE, "Error retrieving default audio " 
     
    23972276        return status; 
    23982277    } 
    2399     param.dir = PJMEDIA_DIR_CAPTURE_PLAYBACK; 
    2400     param.rec_id = capture_dev; 
    2401     param.play_id = playback_dev; 
    2402     param.channel_count = pjsua_var.media_cfg.channel_count; 
     2278    param->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK; 
     2279    param->rec_id = capture_dev; 
     2280    param->play_id = playback_dev; 
     2281    param->clock_rate = clock_rate; 
     2282    param->channel_count = channel_count; 
     2283    param->samples_per_frame = samples_per_frame; 
     2284    param->bits_per_sample = bits_per_sample; 
     2285 
     2286    /* Update the setting with user preference */ 
     2287#define update_param(cap, field)    \ 
     2288        if (pjsua_var.aud_param.flags & cap) { \ 
     2289            param->flags |= cap; \ 
     2290            param->field = pjsua_var.aud_param.field; \ 
     2291        } 
     2292    update_param( PJMEDIA_AUD_DEV_CAP_INPUT_VOLUME_SETTING, input_vol); 
     2293    update_param( PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING, output_vol); 
     2294    update_param( PJMEDIA_AUD_DEV_CAP_INPUT_ROUTE, input_route); 
     2295    update_param( PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE, output_route); 
     2296#undef update_param 
     2297 
    24032298    /* Latency settings */ 
    2404     param.flags |= (PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY |  
    2405                     PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY); 
    2406     param.input_latency_ms = pjsua_var.media_cfg.snd_rec_latency; 
    2407     param.output_latency_ms = pjsua_var.media_cfg.snd_play_latency; 
     2299    param->flags |= (PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY |  
     2300                     PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY); 
     2301    param->input_latency_ms = pjsua_var.media_cfg.snd_rec_latency; 
     2302    param->output_latency_ms = pjsua_var.media_cfg.snd_play_latency; 
     2303 
    24082304    /* EC settings */ 
    24092305    if (pjsua_var.media_cfg.ec_tail_len) { 
    2410         param.flags |= (PJMEDIA_AUD_DEV_CAP_EC | PJMEDIA_AUD_DEV_CAP_EC_TAIL); 
    2411         param.ec_enabled = PJ_TRUE; 
    2412         param.ec_tail_ms = pjsua_var.media_cfg.ec_tail_len; 
     2306        param->flags |= (PJMEDIA_AUD_DEV_CAP_EC | PJMEDIA_AUD_DEV_CAP_EC_TAIL); 
     2307        param->ec_enabled = PJ_TRUE; 
     2308        param->ec_tail_ms = pjsua_var.media_cfg.ec_tail_len; 
    24132309    } else { 
    2414         param.flags &= ~(PJMEDIA_AUD_DEV_CAP_EC | PJMEDIA_AUD_DEV_CAP_EC_TAIL); 
    2415     } 
    2416  
    2417     return open_snd_dev_ext(&param); 
    2418  
    2419 #else 
    2420  
     2310        param->flags &= ~(PJMEDIA_AUD_DEV_CAP_EC|PJMEDIA_AUD_DEV_CAP_EC_TAIL); 
     2311    } 
     2312 
     2313    return PJ_SUCCESS; 
     2314} 
     2315 
     2316/* Internal: the first time the audio device is opened (during app 
     2317 *   startup), retrieve the audio settings such as volume level 
     2318 *   so that aud_get_settings() will work. 
     2319 */ 
     2320static pj_status_t update_initial_aud_param() 
     2321{ 
     2322    pjmedia_aud_stream *strm; 
     2323    pjmedia_aud_param param; 
     2324    pj_status_t status; 
     2325 
     2326    PJ_ASSERT_RETURN(pjsua_var.snd_port != NULL, PJ_EBUG); 
     2327 
     2328    strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port); 
     2329 
     2330    status = pjmedia_aud_stream_get_param(strm, &param); 
     2331    if (status != PJ_SUCCESS) { 
     2332        pjsua_perror(THIS_FILE, "Error audio stream " 
     2333                                "device parameters", status); 
     2334        return status; 
     2335    } 
     2336 
     2337#define update_saved_param(cap, field)  \ 
     2338        if (param.flags & cap) { \ 
     2339            pjsua_var.aud_param.flags |= cap; \ 
     2340            pjsua_var.aud_param.field = param.field; \ 
     2341        } 
     2342 
     2343    update_saved_param(PJMEDIA_AUD_DEV_CAP_INPUT_VOLUME_SETTING, input_vol); 
     2344    update_saved_param(PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING, output_vol); 
     2345    update_saved_param(PJMEDIA_AUD_DEV_CAP_INPUT_ROUTE, input_route); 
     2346    update_saved_param(PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE, output_route); 
     2347#undef update_saved_param 
     2348 
     2349    return PJ_SUCCESS; 
     2350} 
     2351 
     2352/* Get format name */ 
     2353static const char *get_fmt_name(pj_uint32_t id) 
     2354{ 
     2355    static char name[8]; 
     2356 
     2357    if (id == PJMEDIA_FORMAT_L16) 
     2358        return "PCM"; 
     2359    pj_memcpy(name, &id, 4); 
     2360    name[4] = '\0'; 
     2361    return name; 
     2362} 
     2363 
     2364/* Open sound device with the setting. */ 
     2365static pj_status_t open_snd_dev(pjmedia_aud_param *param) 
     2366{ 
    24212367    pjmedia_port *conf_port; 
    2422     pjmedia_aud_dev_info play_info; 
    2423     pjmedia_aud_param param; 
    2424     unsigned clock_rates[] = {0, 44100, 48000, 32000, 16000, 8000}; 
    2425     unsigned selected_clock_rate = 0; 
    2426     unsigned i; 
    2427     pjmedia_aud_stream *strm; 
    2428     pj_str_t tmp; 
    2429     pj_status_t status = -1; 
     2368    pj_status_t status; 
     2369 
     2370    PJ_ASSERT_RETURN(param, PJ_EINVAL); 
    24302371 
    24312372    /* Check if NULL sound device is used */ 
    2432     if (NULL_SND_DEV_ID == capture_dev || NULL_SND_DEV_ID == playback_dev) { 
     2373    if (NULL_SND_DEV_ID==param->rec_id || NULL_SND_DEV_ID==param->play_id) { 
    24332374        return pjsua_set_null_snd_dev(); 
    24342375    } 
    2435  
    2436     /* Normalize device ID with new convention about default device ID */ 
    2437     if (playback_dev == PJMEDIA_AUD_DEFAULT_CAPTURE_DEV) 
    2438         playback_dev = PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV; 
    24392376 
    24402377    /* Close existing sound port */ 
     
    24422379 
    24432380    /* Create memory pool for sound device. */ 
    2444     pjsua_var.snd_pool = pjsua_pool_create("pjsua_snd", 1000, 1000); 
     2381    pjsua_var.snd_pool = pjsua_pool_create("pjsua_snd", 4000, 4000); 
    24452382    PJ_ASSERT_RETURN(pjsua_var.snd_pool, PJ_ENOMEM); 
    24462383 
    2447     /* Set default clock rate */ 
    2448     clock_rates[0] = pjsua_var.media_cfg.snd_clock_rate; 
    2449     if (clock_rates[0] == 0) 
    2450         clock_rates[0] = pjsua_var.media_cfg.clock_rate; 
     2384 
     2385    PJ_LOG(4,(THIS_FILE, "Opening sound device %s@%d/%d/%dms", 
     2386              get_fmt_name(param->ext_fmt.id), 
     2387              param->clock_rate, param->channel_count, 
     2388              param->samples_per_frame / param->channel_count * 1000 / 
     2389              param->clock_rate)); 
     2390 
     2391    status = pjmedia_snd_port_create2( pjsua_var.snd_pool,  
     2392                                       param,  &pjsua_var.snd_port); 
     2393    if (status != PJ_SUCCESS) 
     2394        return status; 
    24512395 
    24522396    /* Get the port0 of the conference bridge. */ 
     
    24542398    pj_assert(conf_port != NULL); 
    24552399 
    2456     /* Create default parameters for the device */ 
    2457     status = pjmedia_aud_dev_default_param(capture_dev, &param); 
    2458     if (status != PJ_SUCCESS) { 
    2459         pjsua_perror(THIS_FILE, "Error retrieving default audio " 
    2460                                 "device parameters", status); 
    2461         return status; 
    2462     } 
    2463     param.dir = PJMEDIA_DIR_CAPTURE_PLAYBACK; 
    2464     param.rec_id = capture_dev; 
    2465     param.play_id = playback_dev; 
    2466     param.channel_count = pjsua_var.media_cfg.channel_count; 
    2467     /* Latency settings */ 
    2468     param.flags |= (PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY |  
    2469                     PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY); 
    2470     param.input_latency_ms = pjsua_var.media_cfg.snd_rec_latency; 
    2471     param.output_latency_ms = pjsua_var.media_cfg.snd_play_latency; 
    2472     /* EC settings */ 
    2473     if (pjsua_var.media_cfg.ec_tail_len) { 
    2474         param.flags |= (PJMEDIA_AUD_DEV_CAP_EC | PJMEDIA_AUD_DEV_CAP_EC_TAIL); 
    2475         param.ec_enabled = PJ_TRUE; 
    2476         param.ec_tail_ms = pjsua_var.media_cfg.ec_tail_len; 
    2477     } else { 
    2478         param.flags &= ~(PJMEDIA_AUD_DEV_CAP_EC | PJMEDIA_AUD_DEV_CAP_EC_TAIL); 
    2479     } 
    2480  
    2481     /* Attempts to open the sound device with different clock rates */ 
    2482     for (i=0; i<PJ_ARRAY_SIZE(clock_rates); ++i) { 
    2483         char errmsg[PJ_ERR_MSG_SIZE]; 
    2484  
    2485         PJ_LOG(4,(THIS_FILE,  
    2486                   "pjsua_set_snd_dev(): attempting to open devices " 
    2487                   "@%d Hz", clock_rates[i])); 
    2488  
    2489         param.clock_rate = clock_rates[i]; 
    2490         param.samples_per_frame = clock_rates[i] * 
    2491                                   pjsua_var.media_cfg.audio_frame_ptime * 
    2492                                   pjsua_var.media_cfg.channel_count / 1000; 
    2493  
    2494         /* Create the sound device. Sound port will start immediately. */ 
    2495         status = pjmedia_snd_port_create2(pjsua_var.snd_pool, &param, 
    2496                                           &pjsua_var.snd_port); 
    2497  
    2498         if (status == PJ_SUCCESS) { 
    2499             selected_clock_rate = clock_rates[i]; 
    2500  
    2501             /* If there's mismatch between sound port and conference's port, 
    2502              * create a resample port to bridge them. 
    2503              */ 
    2504             if (selected_clock_rate != pjsua_var.media_cfg.clock_rate) { 
    2505                 pjmedia_port *resample_port; 
    2506                 unsigned resample_opt = 0; 
    2507  
    2508                 if (pjsua_var.media_cfg.quality >= 3 && 
    2509                     pjsua_var.media_cfg.quality <= 4) 
    2510                 { 
    2511                     resample_opt |= PJMEDIA_RESAMPLE_USE_SMALL_FILTER; 
    2512                 } 
    2513                 else if (pjsua_var.media_cfg.quality < 3) { 
    2514                     resample_opt |= PJMEDIA_RESAMPLE_USE_LINEAR; 
    2515                 } 
    2516                  
    2517                 status = pjmedia_resample_port_create(pjsua_var.snd_pool,  
    2518                                                       conf_port, 
    2519                                                       selected_clock_rate, 
    2520                                                       resample_opt,  
    2521                                                       &resample_port); 
    2522                 if (status != PJ_SUCCESS) { 
    2523                     pj_strerror(status, errmsg, sizeof(errmsg)); 
    2524                     PJ_LOG(4, (THIS_FILE,  
    2525                                "Error creating resample port, trying next " 
    2526                                "clock rate",  
    2527                                errmsg)); 
    2528                     pjmedia_snd_port_destroy(pjsua_var.snd_port); 
    2529                     pjsua_var.snd_port = NULL; 
    2530                     continue; 
    2531                 } else { 
    2532                     conf_port = resample_port; 
    2533                     break; 
    2534                 } 
    2535  
    2536             } else { 
    2537                 break; 
    2538             } 
    2539         } 
    2540  
    2541         pj_strerror(status, errmsg, sizeof(errmsg)); 
    2542         PJ_LOG(4, (THIS_FILE, "..failed: %s", errmsg)); 
    2543     } 
    2544  
    2545     if (status != PJ_SUCCESS) { 
    2546         pjsua_perror(THIS_FILE, "Unable to open sound device", status); 
    2547         return status; 
    2548     } 
    2549  
    2550     /* Connect sound port to the bridge */        
     2400    /* For conference bridge, resample if necessary if the bridge's 
     2401     * clock rate is different than the sound device's clock rate. 
     2402     */ 
     2403    if (!pjsua_var.is_mswitch && 
     2404        param->ext_fmt.id == PJMEDIA_FORMAT_PCM && 
     2405        conf_port->info.clock_rate != param->clock_rate) 
     2406    { 
     2407        pjmedia_port *resample_port; 
     2408        unsigned resample_opt = 0; 
     2409 
     2410        if (pjsua_var.media_cfg.quality >= 3 && 
     2411            pjsua_var.media_cfg.quality <= 4) 
     2412        { 
     2413            resample_opt |= PJMEDIA_RESAMPLE_USE_SMALL_FILTER; 
     2414        } 
     2415        else if (pjsua_var.media_cfg.quality < 3) { 
     2416            resample_opt |= PJMEDIA_RESAMPLE_USE_LINEAR; 
     2417        } 
     2418         
     2419        status = pjmedia_resample_port_create(pjsua_var.snd_pool,  
     2420                                              conf_port, 
     2421                                              param->clock_rate, 
     2422                                              resample_opt,  
     2423                                              &resample_port); 
     2424        if (status != PJ_SUCCESS) { 
     2425            char errmsg[PJ_ERR_MSG_SIZE]; 
     2426            pj_strerror(status, errmsg, sizeof(errmsg)); 
     2427            PJ_LOG(4, (THIS_FILE,  
     2428                       "Error creating resample port: %s",  
     2429                       errmsg)); 
     2430            close_snd_dev(); 
     2431            return status; 
     2432        }  
     2433             
     2434        conf_port = resample_port; 
     2435    } 
     2436 
     2437    /* Otherwise for audio switchboard, the switch's port0 setting is 
     2438     * derived from the sound device setting, so update the setting. 
     2439     */ 
     2440    if (pjsua_var.is_mswitch) { 
     2441        pj_memcpy(&conf_port->info.format, &param->ext_fmt,  
     2442                  sizeof(conf_port->info.format)); 
     2443        conf_port->info.clock_rate = param->clock_rate; 
     2444        conf_port->info.samples_per_frame = param->samples_per_frame; 
     2445        conf_port->info.channel_count = param->channel_count; 
     2446        conf_port->info.bits_per_sample = 16; 
     2447    } 
     2448 
     2449    /* Connect sound port to the bridge */ 
    25512450    status = pjmedia_snd_port_connect(pjsua_var.snd_port,         
    25522451                                      conf_port );        
     
    25602459 
    25612460    /* Save the device IDs */ 
    2562     pjsua_var.cap_dev = capture_dev; 
    2563     pjsua_var.play_dev = playback_dev; 
     2461    pjsua_var.cap_dev = param->rec_id; 
     2462    pjsua_var.play_dev = param->play_id; 
    25642463 
    25652464    /* Update sound device name. */ 
    2566     strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port); 
    2567     pjmedia_aud_stream_get_param(strm, &param); 
    2568     pjmedia_aud_dev_get_info(param.play_id, &play_info); 
    2569  
    2570     if (param.clock_rate != pjsua_var.media_cfg.clock_rate) { 
    2571         char tmp_buf[128]; 
    2572         int tmp_buf_len = sizeof(tmp_buf); 
    2573  
    2574         tmp_buf_len = pj_ansi_snprintf(tmp_buf, sizeof(tmp_buf)-1, "%s (%dKHz)", 
    2575                                        play_info.name, param.clock_rate/1000); 
    2576         pj_strset(&tmp, tmp_buf, tmp_buf_len); 
    2577         pjmedia_conf_set_port0_name(pjsua_var.mconf, &tmp);  
     2465    { 
     2466        pjmedia_aud_dev_info rec_info; 
     2467        pjmedia_aud_stream *strm; 
     2468        pjmedia_aud_param si; 
     2469        pj_str_t tmp; 
     2470 
     2471        strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port); 
     2472        status = pjmedia_aud_stream_get_param(strm, &si); 
     2473        if (status == PJ_SUCCESS) 
     2474            status = pjmedia_aud_dev_get_info(si.rec_id, &rec_info); 
     2475 
     2476        if (status==PJ_SUCCESS) { 
     2477            if (param->clock_rate != pjsua_var.media_cfg.clock_rate) { 
     2478                char tmp_buf[128]; 
     2479                int tmp_buf_len = sizeof(tmp_buf); 
     2480 
     2481                tmp_buf_len = pj_ansi_snprintf(tmp_buf, sizeof(tmp_buf)-1,  
     2482                                               "%s (%dKHz)", 
     2483                                               rec_info.name,  
     2484                                               param->clock_rate/1000); 
     2485                pj_strset(&tmp, tmp_buf, tmp_buf_len); 
     2486                pjmedia_conf_set_port0_name(pjsua_var.mconf, &tmp);  
     2487            } else { 
     2488                pjmedia_conf_set_port0_name(pjsua_var.mconf,  
     2489                                            pj_cstr(&tmp, rec_info.name)); 
     2490            } 
     2491        } 
     2492 
     2493        /* Any error is not major, let it through */ 
     2494        status = PJ_SUCCESS; 
     2495    }; 
     2496 
     2497    /* If this is the first time the audio device is open, retrieve some 
     2498     * settings from the device (such as volume settings) so that the 
     2499     * pjsua_snd_get_setting() work. 
     2500     */ 
     2501    if (pjsua_var.aud_open_cnt == 0) { 
     2502        update_initial_aud_param(); 
     2503        ++pjsua_var.aud_open_cnt; 
     2504    } 
     2505 
     2506    return PJ_SUCCESS; 
     2507} 
     2508 
     2509 
     2510/* Close existing sound device */ 
     2511static void close_snd_dev(void) 
     2512{ 
     2513    /* Close sound device */ 
     2514    if (pjsua_var.snd_port) { 
     2515        pjmedia_aud_dev_info cap_info, play_info; 
     2516        pjmedia_aud_stream *strm; 
     2517        pjmedia_aud_param param; 
     2518 
     2519        strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port); 
     2520        pjmedia_aud_stream_get_param(strm, &param); 
     2521 
     2522        if (pjmedia_aud_dev_get_info(param.rec_id, &cap_info) != PJ_SUCCESS) 
     2523            cap_info.name[0] = '\0'; 
     2524        if (pjmedia_aud_dev_get_info(param.play_id, &play_info) != PJ_SUCCESS) 
     2525            play_info.name[0] = '\0'; 
     2526 
     2527        PJ_LOG(4,(THIS_FILE, "Closing %s sound playback device and " 
     2528                             "%s sound capture device", 
     2529                             play_info.name, cap_info.name)); 
     2530 
     2531        pjmedia_snd_port_disconnect(pjsua_var.snd_port); 
     2532        pjmedia_snd_port_destroy(pjsua_var.snd_port); 
     2533        pjsua_var.snd_port = NULL; 
     2534    } 
     2535 
     2536    /* Close null sound device */ 
     2537    if (pjsua_var.null_snd) { 
     2538        PJ_LOG(4,(THIS_FILE, "Closing null sound device..")); 
     2539        pjmedia_master_port_destroy(pjsua_var.null_snd, PJ_FALSE); 
     2540        pjsua_var.null_snd = NULL; 
     2541    } 
     2542 
     2543    if (pjsua_var.snd_pool)  
     2544        pj_pool_release(pjsua_var.snd_pool); 
     2545    pjsua_var.snd_pool = NULL; 
     2546} 
     2547 
     2548 
     2549/* 
     2550 * Select or change sound device. Application may call this function at 
     2551 * any time to replace current sound device. 
     2552 */ 
     2553PJ_DEF(pj_status_t) pjsua_set_snd_dev( int capture_dev, 
     2554                                       int playback_dev) 
     2555{ 
     2556    unsigned alt_cr_cnt = 1; 
     2557    unsigned alt_cr[] = {0, 44100, 48000, 32000, 16000, 8000}; 
     2558    unsigned i; 
     2559    pj_status_t status = -1; 
     2560 
     2561    /* Set default clock rate */ 
     2562    alt_cr[0] = pjsua_var.media_cfg.snd_clock_rate; 
     2563    if (alt_cr[0] == 0) 
     2564        alt_cr[0] = pjsua_var.media_cfg.clock_rate; 
     2565 
     2566    /* Allow retrying of different clock rate if we're using conference  
     2567     * bridge (meaning audio format is always PCM), otherwise lock on 
     2568     * to one clock rate. 
     2569     */ 
     2570    if (pjsua_var.is_mswitch) { 
     2571        alt_cr_cnt = 1; 
    25782572    } else { 
    2579         pjmedia_conf_set_port0_name(pjsua_var.mconf,  
    2580                                     pj_cstr(&tmp, play_info.name)); 
    2581     } 
    2582  
    2583     return PJ_SUCCESS; 
    2584  
    2585 #endif /* PJMEDIA_CONF_USE_SWITCH_BOARD */ 
    2586  
     2573        alt_cr_cnt = PJ_ARRAY_SIZE(alt_cr); 
     2574    } 
     2575 
     2576    /* Attempts to open the sound device with different clock rates */ 
     2577    for (i=0; i<alt_cr_cnt; ++i) { 
     2578        pjmedia_aud_param param; 
     2579        unsigned samples_per_frame; 
     2580 
     2581        /* Create the default audio param */ 
     2582        samples_per_frame = alt_cr[i] * 
     2583                            pjsua_var.media_cfg.audio_frame_ptime * 
     2584                            pjsua_var.media_cfg.channel_count / 1000; 
     2585        status = create_aud_param(&param, capture_dev, playback_dev,  
     2586                                  alt_cr[i], pjsua_var.media_cfg.channel_count, 
     2587                                  samples_per_frame, 16); 
     2588        if (status != PJ_SUCCESS) 
     2589            return status; 
     2590 
     2591        /* Open! */ 
     2592        status = open_snd_dev(&param); 
     2593        if (status == PJ_SUCCESS) 
     2594            break; 
     2595    } 
     2596 
     2597    if (status != PJ_SUCCESS) { 
     2598        pjsua_perror(THIS_FILE, "Unable to open sound device", status); 
     2599        return status; 
     2600    } 
     2601 
     2602    return PJ_SUCCESS; 
    25872603} 
    25882604 
     
    26902706 
    26912707/* 
    2692  * Get active sound port instance. 
    2693  */ 
    2694 PJ_DEF(pjmedia_aud_stream*) pjsua_get_aud_stream() 
    2695 { 
    2696     pjmedia_aud_stream *aud_stream = NULL; 
    2697  
    2698     if (pjsua_var.snd_port) 
    2699         aud_stream = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port); 
    2700  
    2701     return aud_stream; 
     2708 * Check whether the sound device is currently active. 
     2709 */ 
     2710PJ_DEF(pj_bool_t) pjsua_snd_is_active(void) 
     2711{ 
     2712    return pjsua_var.snd_port != NULL; 
     2713} 
     2714 
     2715 
     2716/* 
     2717 * Configure sound device setting to the sound device being used.  
     2718 */ 
     2719PJ_DEF(pj_status_t) pjsua_snd_set_setting( pjmedia_aud_dev_cap cap, 
     2720                                           const void *pval, 
     2721                                           pj_bool_t keep) 
     2722{ 
     2723    /* Check if we are allowed to set the cap */ 
     2724    if (cap & pjsua_var.aud_svmask) { 
     2725        return PJMEDIA_EAUD_INVCAP; 
     2726    } 
     2727 
     2728    if (keep) { 
     2729        /* Save in internal param for later device open */ 
     2730        pj_status_t status; 
     2731 
     2732        status = pjmedia_aud_param_set_cap(&pjsua_var.aud_param, 
     2733                                           cap, pval); 
     2734        if (status != PJ_SUCCESS) 
     2735            return status; 
     2736    } 
     2737 
     2738    if (pjsua_snd_is_active()) { 
     2739        /* Sound is active, set it immediately */ 
     2740        pjmedia_aud_stream *strm; 
     2741         
     2742        strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port); 
     2743        return pjmedia_aud_stream_set_cap(strm, cap, pval); 
     2744    } else { 
     2745        return PJ_SUCCESS; 
     2746    } 
     2747} 
     2748 
     2749/* 
     2750 * Retrieve a sound device setting. 
     2751 */ 
     2752PJ_DEF(pj_status_t) pjsua_snd_get_setting( pjmedia_aud_dev_cap cap, 
     2753                                           void *pval) 
     2754{ 
     2755    /* If sound device has never been opened before, open it to  
     2756     * retrieve the initial setting from the device (e.g. audio 
     2757     * volume) 
     2758     */ 
     2759    if (pjsua_var.aud_open_cnt==0) 
     2760        pjsua_set_snd_dev(pjsua_var.cap_dev, pjsua_var.play_dev); 
     2761 
     2762    if (pjsua_snd_is_active()) { 
     2763        /* Sound is active, retrieve from device directly */ 
     2764        pjmedia_aud_stream *strm; 
     2765         
     2766        strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port); 
     2767        return pjmedia_aud_stream_get_cap(strm, cap, pval); 
     2768    } else { 
     2769        /* Otherwise retrieve from internal param */ 
     2770        return pjmedia_aud_param_get_cap(&pjsua_var.aud_param, 
     2771                                         cap, pval); 
     2772    } 
    27022773} 
    27032774 
Note: See TracChangeset for help on using the changeset viewer.