Changeset 2468


Ignore:
Timestamp:
Feb 21, 2009 2:21:59 PM (15 years ago)
Author:
bennylp
Message:

Updated libraries and applications to use the new Audio Device API

Location:
pjproject/branches/projects/aps-direct
Files:
2 deleted
33 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/aps-direct/pjmedia/build/pjmedia.dsp

    r2458 r2468  
    122122# Begin Source File 
    123123 
    124 SOURCE=..\src\pjmedia\dsound.c 
    125 # End Source File 
    126 # Begin Source File 
    127  
    128124SOURCE=..\src\pjmedia\echo_common.c 
    129125# End Source File 
     
    178174# Begin Source File 
    179175 
    180 SOURCE=..\src\pjmedia\nullsound.c 
    181 # End Source File 
    182 # Begin Source File 
    183  
    184 SOURCE=..\src\pjmedia\pasound.c 
    185 # End Source File 
    186 # Begin Source File 
    187  
    188176SOURCE=..\src\pjmedia\plc_common.c 
    189177# End Source File 
     
    295283 
    296284SOURCE=..\src\pjmedia\wave.c 
    297 # End Source File 
    298 # Begin Source File 
    299  
    300 SOURCE=..\src\pjmedia\wmme_sound.c 
    301285# End Source File 
    302286# Begin Source File 
  • pjproject/branches/projects/aps-direct/pjmedia/build/pjmedia_audiodev.dsp

    r2463 r2468  
    102102# Begin Source File 
    103103 
     104SOURCE="..\src\pjmedia-audiodev\symb_aps_dev.cpp" 
     105# PROP Exclude_From_Build 1 
     106# End Source File 
     107# Begin Source File 
     108 
     109SOURCE="..\src\pjmedia-audiodev\symb_mda_dev.cpp" 
     110# PROP Exclude_From_Build 1 
     111# End Source File 
     112# Begin Source File 
     113 
    104114SOURCE="..\src\pjmedia-audiodev\wmme_dev.c" 
    105115# End Source File 
  • pjproject/branches/projects/aps-direct/pjmedia/include/pjmedia-audiodev/audiodev.h

    r2466 r2468  
    1818 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  
    1919 */ 
    20 #ifndef __AUDIODEV_H__ 
    21 #define __AUDIODEV_H__ 
     20#ifndef __PJMEDIA_AUDIODEV_AUDIODEV_H__ 
     21#define __PJMEDIA_AUDIODEV_AUDIODEV_H__ 
    2222 
    2323/** 
     
    5252 */ 
    5353 
    54 /** Device identifier */ 
    55 typedef pj_int32_t pjmedia_aud_dev_id; 
    56  
    57 /** Constant to denote default ID */ 
    58 #define PJMEDIA_AUD_DEV_DEFAULT_ID  (-1) 
     54/**  
     55 * Type for device index. 
     56 */ 
     57typedef pj_int32_t pjmedia_aud_dev_index; 
     58 
     59/**  
     60 * Constant to denote default device  
     61 */ 
     62#define PJMEDIA_AUD_DEV_DEFAULT  (-1) 
     63 
     64/**  
     65 * Type for device unique identifier. The unique device ID can be used to save 
     66 * a reference to a particular device across software reboots. 
     67 */ 
     68typedef pj_uint32_t pjmedia_aud_dev_uid; 
    5969 
    6070 
     
    6777 * 
    6878 * Application can also set the specific features/capabilities when opening 
    69  * the audio stream by setting the \a flags member of #pjmedia_aud_dev_param 
     79 * the audio stream by setting the \a flags member of #pjmedia_aud_param 
    7080 * structure. 
    7181 * 
     
    118128     * the audio volume in percent. 
    119129     */ 
    120     PJMEDIA_AUD_DEV_CAP_INPUT_SIGNAL_VOLUME = 32, 
     130    PJMEDIA_AUD_DEV_CAP_INPUT_SIGNAL_METER = 32, 
    121131 
    122132    /**  
     
    125135     * the audio volume in percent. 
    126136     */ 
    127     PJMEDIA_AUD_DEV_CAP_OUTPUT_SIGNAL_VOLUME = 64, 
     137    PJMEDIA_AUD_DEV_CAP_OUTPUT_SIGNAL_METER = 64, 
    128138 
    129139    /**  
     
    142152    /**  
    143153     * The audio device has echo cancellation feature. The value of this 
    144      * capability is an integer containing boolean PJ_TRUE or PJ_FALSE. 
     154     * capability is a pj_bool_t containing boolean PJ_TRUE or PJ_FALSE. 
    145155     */ 
    146156    PJMEDIA_AUD_DEV_CAP_EC = 512, 
     
    155165    /**  
    156166     * The audio device has voice activity detection feature. The value 
    157      * of this capability is an integer containing boolean PJ_TRUE or  
     167     * of this capability is a pj_bool_t containing boolean PJ_TRUE or  
    158168     * PJ_FALSE. 
    159169     */ 
     
    162172    /**  
    163173     * The audio device has comfort noise generation feature. The value 
    164      * of this capability is an integer containing boolean PJ_TRUE or  
     174     * of this capability is a pj_bool_t containing boolean PJ_TRUE or  
    165175     * PJ_FALSE. 
    166176     */ 
     
    169179    /**  
    170180     * The audio device has packet loss concealment feature. The value 
    171      * of this capability is an integer containing boolean PJ_TRUE or  
     181     * of this capability is a pj_bool_t containing boolean PJ_TRUE or  
    172182     * PJ_FALSE. 
    173183     */ 
     
    226236     * The underlying driver name  
    227237     */ 
    228     char driver[128]; 
     238    char driver[32]; 
    229239 
    230240    /**  
     
    290300 
    291301/** 
    292  * This structure specifies the parameters to open the audio device stream. 
    293  */ 
    294 typedef struct pjmedia_aud_dev_param 
     302 * This structure specifies the parameters to open the audio stream. 
     303 */ 
     304typedef struct pjmedia_aud_param 
    295305{ 
    296306    /** 
     
    303313     * direction includes input/capture direction. 
    304314     */ 
    305     pjmedia_aud_dev_id rec_id; 
     315    pjmedia_aud_dev_index rec_id; 
    306316 
    307317    /** 
     
    309319     * direction includes output/playback direction. 
    310320     */ 
    311     pjmedia_aud_dev_id play_id; 
     321    pjmedia_aud_dev_index play_id; 
    312322 
    313323    /**  
     
    387397    pj_bool_t cng_enabled; 
    388398 
    389 } pjmedia_aud_dev_param; 
     399} pjmedia_aud_param; 
    390400 
    391401 
     
    432442 
    433443/** 
     444 * Get string info for the specified capability. 
     445 * 
     446 * @param cap           The capability ID. 
     447 * @param p_desc        Optional pointer which will be filled with longer  
     448 *                      description about the capability. 
     449 * 
     450 * @return              Capability name. 
     451 */ 
     452PJ_DECL(const char*) pjmedia_aud_dev_cap_name(pjmedia_aud_dev_cap cap, 
     453                                              const char **p_desc); 
     454 
     455 
     456/** 
    434457 * Get the number of sound devices installed in the system. 
    435458 * 
     
    438461PJ_DECL(unsigned) pjmedia_aud_dev_count(void); 
    439462 
    440  
    441 /** 
    442  * Enumerate device ID's. 
    443  * 
    444  * @param max_count     Maximum number of device id's to retrieve. 
    445  * @param ids           Array to receive the device id's. 
    446  * 
    447  * @return              The actual number of device id's filled in. 
    448  */ 
    449 PJ_DECL(unsigned) pjmedia_aud_dev_enum(unsigned max_count, 
    450                                        pjmedia_aud_dev_id ids[]); 
    451463 
    452464/** 
     
    460472 *                      error code. 
    461473 */ 
    462 PJ_DECL(pj_status_t) pjmedia_aud_dev_get_info(pjmedia_aud_dev_id id, 
     474PJ_DECL(pj_status_t) pjmedia_aud_dev_get_info(pjmedia_aud_dev_index id, 
    463475                                              pjmedia_aud_dev_info *info); 
     476 
     477 
     478/** 
     479 * Lookup device index based on the driver and device name. 
     480 * 
     481 * @param drv_name      The driver name. 
     482 * @param dev_name      The device name. 
     483 * 
     484 * @return              PJ_SUCCESS if the device can be found. 
     485 */ 
     486PJ_DECL(pj_status_t) pjmedia_aud_dev_lookup(const char *drv_name, 
     487                                            const char *dev_name, 
     488                                            pjmedia_aud_dev_index *id); 
    464489 
    465490 
     
    475500 *                      error code. 
    476501 */ 
    477 PJ_DECL(pj_status_t) pjmedia_aud_dev_default_param(pjmedia_aud_dev_id id, 
    478                                                    pjmedia_aud_dev_param *param); 
     502PJ_DECL(pj_status_t) pjmedia_aud_dev_default_param(pjmedia_aud_dev_index id, 
     503                                                   pjmedia_aud_param *param); 
    479504 
    480505 
     
    493518 *                      error code. 
    494519 */ 
    495 PJ_DECL(pj_status_t) pjmedia_aud_stream_create(const pjmedia_aud_dev_param *param, 
     520PJ_DECL(pj_status_t) pjmedia_aud_stream_create(const pjmedia_aud_param *param, 
    496521                                               pjmedia_aud_rec_cb rec_cb, 
    497522                                               pjmedia_aud_play_cb play_cb, 
    498523                                               void *user_data, 
    499                                                pjmedia_aud_stream **p_aud_strm); 
     524                                               pjmedia_aud_stream **p_strm); 
    500525 
    501526/** 
     
    510535 */ 
    511536PJ_DECL(pj_status_t) pjmedia_aud_stream_get_param(pjmedia_aud_stream *strm, 
    512                                                   pjmedia_aud_dev_param *param); 
     537                                                  pjmedia_aud_param *param); 
    513538 
    514539/** 
     
    581606#define PJMEDIA_EAUD_NOTREADY   -1 
    582607 
     608/* Invalid audio capability or audio capability not supported */ 
     609#define PJMEDIA_EAUD_INVCAP     -1 
     610 
    583611/* Unknown system error */ 
    584612#define PJMEDIA_EAUD_SYSERR     -1 
     
    592620 
    593621 
    594 #endif  /* __AUDIODEV_H__ */ 
    595  
     622#endif  /* __PJMEDIA_AUDIODEV_AUDIODEV_H__ */ 
     623 
  • pjproject/branches/projects/aps-direct/pjmedia/include/pjmedia-audiodev/audiodev_imp.h

    r2459 r2468  
    8080    pj_status_t (*default_param)(pjmedia_aud_dev_factory *f, 
    8181                                 unsigned index, 
    82                                  pjmedia_aud_dev_param *param); 
     82                                 pjmedia_aud_param *param); 
    8383 
    8484    /** 
     
    8787     */ 
    8888    pj_status_t (*create_stream)(pjmedia_aud_dev_factory *f, 
    89                                  const pjmedia_aud_dev_param *param, 
     89                                 const pjmedia_aud_param *param, 
    9090                                 pjmedia_aud_rec_cb rec_cb, 
    9191                                 pjmedia_aud_play_cb play_cb, 
     
    120120     */ 
    121121    pj_status_t (*get_param)(pjmedia_aud_stream *strm, 
    122                              pjmedia_aud_dev_param *param); 
     122                             pjmedia_aud_param *param); 
    123123 
    124124    /** 
     
    159159struct pjmedia_aud_stream 
    160160{ 
    161     /** Factory */ 
    162     pjmedia_aud_dev_factory *factory; 
     161    /** Factory id (internal) */ 
     162    unsigned factory_id; 
    163163 
    164164    /** Operations */ 
  • pjproject/branches/projects/aps-direct/pjmedia/include/pjmedia-audiodev/audiotest.h

    r2463 r2468  
    1818 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  
    1919 */ 
    20 #ifndef __AUDIOTEST_H__ 
    21 #define __AUDIOTEST_H__ 
     20#ifndef __PJMEDIA_AUDIODEV_AUDIOTEST_H__ 
     21#define __PJMEDIA_AUDIODEV_AUDIOTEST_H__ 
    2222 
    2323/** 
     
    9292 * Perform audio device testing. 
    9393 */ 
    94 PJ_DECL(pj_status_t) pjmedia_aud_test(const pjmedia_aud_dev_param *param, 
     94PJ_DECL(pj_status_t) pjmedia_aud_test(const pjmedia_aud_param *param, 
    9595                                      pjmedia_aud_test_results *result); 
    9696 
     
    102102 
    103103 
    104 #endif  /* __AUDIOTEST_H__ */ 
     104#endif  /* __PJMEDIA_AUDIODEV_AUDIOTEST_H__ */ 
    105105 
    106106 
  • pjproject/branches/projects/aps-direct/pjmedia/include/pjmedia.h

    r2394 r2468  
    5353#include <pjmedia/session.h> 
    5454#include <pjmedia/silencedet.h> 
     55/* This sound API is deprecated. Please see: 
     56http://trac.pjsip.org/repos/wiki/Audio_Dev_API 
    5557#include <pjmedia/sound.h> 
     58*/ 
    5659#include <pjmedia/sound_port.h> 
    5760#include <pjmedia/splitcomb.h> 
  • pjproject/branches/projects/aps-direct/pjmedia/include/pjmedia/config.h

    r2452 r2468  
    6565 */ 
    6666 
    67 /** Constant for NULL sound backend. */ 
    68 #define PJMEDIA_SOUND_NULL_SOUND            0 
    69  
    70 /** Constant for PortAudio sound backend. */ 
    71 #define PJMEDIA_SOUND_PORTAUDIO_SOUND       1 
    72  
    73 /** Constant for Win32 DirectSound sound backend. */ 
    74 #define PJMEDIA_SOUND_WIN32_DIRECT_SOUND    2 
    75  
    76 /** Constant for Win32 MME sound backend. */ 
    77 #define PJMEDIA_SOUND_WIN32_MME_SOUND       3 
    78  
    79 /** Constant for Symbian Multimedia Audio Stream backend. */ 
    80 #define PJMEDIA_SOUND_SYMB_MDA_SOUND        4 
    81  
    82 /** Constant for Symbian APS backend. */ 
    83 #define PJMEDIA_SOUND_SYMB_APS_SOUND        5 
    84  
    85 /** Constant for Symbian VAS backend. */ 
    86 #define PJMEDIA_SOUND_SYMB_VAS_SOUND        6 
    87  
    88  
    89 /** When this is set, pjmedia will not provide any sound device backend.  
    90  *  Application will have to provide its own sound device backend 
    91  *  and link the application with it. 
    92  */ 
    93 #define PJMEDIA_SOUND_EXTERNAL              255 
    94  
    95  
    96 /** 
    97  * Unless specified otherwise, sound device uses PortAudio implementation 
    98  * by default. 
    99  */ 
    100 #ifndef PJMEDIA_SOUND_IMPLEMENTATION 
    101 #  if defined(PJ_WIN32) && PJ_WIN32!=0 
    102 /*#   define PJMEDIA_SOUND_IMPLEMENTATION   PJMEDIA_SOUND_WIN32_DIRECT_SOUND*/ 
    103 /*#   define PJMEDIA_SOUND_IMPLEMENTATION   PJMEDIA_SOUND_WIN32_MME_SOUND*/ 
    104 #   define PJMEDIA_SOUND_IMPLEMENTATION     PJMEDIA_SOUND_PORTAUDIO_SOUND 
    105 #  else 
    106 #   define PJMEDIA_SOUND_IMPLEMENTATION     PJMEDIA_SOUND_PORTAUDIO_SOUND 
    107 #  endif 
    108 #endif 
    109  
    110 /** 
    111  * Specify if the sound device implementation supports handling encoded 
    112  * frames. Setting this to zero will activate some emulation in the 
    113  * sound port. 
    114  */ 
    115 #if PJMEDIA_SOUND_IMPLEMENTATION==PJMEDIA_SOUND_SYMB_APS_SOUND || \ 
    116     PJMEDIA_SOUND_IMPLEMENTATION==PJMEDIA_SOUND_SYMB_VAS_SOUND 
    117 #   define PJMEDIA_SND_SUPPORT_OPEN2    1 
    118 #else 
    119 #   define PJMEDIA_SND_SUPPORT_OPEN2    0 
    120 #endif 
    121  
    122 /** 
    123  * Specify whether we prefer to use DirectSound on Windows. 
    124  * 
    125  * Default: 0 
    126  */ 
    127 #ifndef PJMEDIA_PREFER_DIRECT_SOUND 
    128 #   define PJMEDIA_PREFER_DIRECT_SOUND      0 
    129 #endif 
    130  
    131  
    132 /** 
    133  * Specify sound device latency default, in milisecond. 
     67/** 
     68 * This macro has been deprecated in releasee 1.1. Please see 
     69 * http://trac.pjsip.org/repos/wiki/Audio_Dev_API for more information. 
     70 */ 
     71#if defined(PJMEDIA_SOUND_IMPLEMENTATION) 
     72#   error PJMEDIA_SOUND_IMPLEMENTATION has been deprecated 
     73#endif 
     74 
     75/** 
     76 * This macro has been deprecated in releasee 1.1. Please see 
     77 * http://trac.pjsip.org/repos/wiki/Audio_Dev_API for more information. 
     78 */ 
     79#if defined(PJMEDIA_PREFER_DIRECT_SOUND) 
     80#   error PJMEDIA_PREFER_DIRECT_SOUND has been deprecated 
     81#endif 
     82 
     83/** 
     84 * Setting PJMEDIA_AUDIO_API to this value will completely deprecate the use 
     85 * of old API, and inclusion of <pjmedia/sound.h> in the code will raise  
     86 * compilation error. 
     87 */ 
     88#define PJMEDIA_AUDIO_API_NEW_ONLY          1 
     89 
     90/** 
     91 * Setting PJMEDIA_AUDIO_API to this value enables application to use the old 
     92 * sound device API to access audio devices provided by the new audio device  
     93 * API.  
     94 */ 
     95#define PJMEDIA_AUDIO_API_HAS_OLD_API       2 
     96 
     97/** 
     98 * Setting PJMEDIA_AUDIO_API to this value enables old sound device  
     99 * implementation to be accessed via both old and new API's.  
     100 */ 
     101#define PJMEDIA_AUDIO_API_HAS_OLD_DEVICE    3 
     102 
     103/** 
     104 * Specify how the audio API should handle compatibility with old sound API. 
     105 * Valid values are: PJMEDIA_AUDIO_API_HAS_OLD_API (default,  
     106 * PJMEDIA_AUDIO_API_NEW_ONLY, or PJMEDIA_AUDIO_API_HAS_OLD_DEVICE. Please 
     107 * see http://trac.pjsip.org/repos/wiki/Audio_Dev_API for more info. 
     108 */ 
     109#ifndef PJMEDIA_AUDIO_API 
     110#   define PJMEDIA_AUDIO_API                PJMEDIA_AUDIO_API_NEW_ONLY 
     111#endif 
     112 
     113 
     114/** 
     115 * Specify default sound device latency, in milisecond. 
    134116 */ 
    135117#ifndef PJMEDIA_SND_DEFAULT_REC_LATENCY 
     
    137119#endif 
    138120 
     121/** 
     122 * Specify default sound device latency, in milisecond. 
     123 */ 
    139124#ifndef PJMEDIA_SND_DEFAULT_PLAY_LATENCY 
    140125#   define PJMEDIA_SND_DEFAULT_PLAY_LATENCY 100 
    141 #endif 
    142  
    143  
    144 /** 
    145  * Specify whether delay buffer is used for sound device. 
    146  * When delay buffer is enabled, the sound device callback  
    147  * will be called one after another evenly. 
    148  * The delay buffer also performs the best delay calculation 
    149  * for the sound device, and will try to limit the delay caused 
    150  * by uneven callback calls to this delay. 
    151  * 
    152  * When this setting is enabled, the PJMEDIA_SOUND_BUFFER_COUNT 
    153  * macro will specify the maximum size of the delay buffer. 
    154  */ 
    155 #ifndef PJMEDIA_SOUND_USE_DELAYBUF 
    156 #   define PJMEDIA_SOUND_USE_DELAYBUF       0 
    157126#endif 
    158127 
  • pjproject/branches/projects/aps-direct/pjmedia/include/pjmedia/endpoint.h

    r2394 r2468  
    3838 */ 
    3939 
    40 #include <pjmedia/sound.h> 
    4140#include <pjmedia/codec.h> 
    4241#include <pjmedia/sdp.h> 
  • pjproject/branches/projects/aps-direct/pjmedia/include/pjmedia/sound.h

    r2460 r2468  
    2020#ifndef __PJMEDIA_SOUND_H__ 
    2121#define __PJMEDIA_SOUND_H__ 
     22 
     23 
     24/* This is legacy sound device code, which has been superseded by the 
     25 * new pjmedia-audiodev framework. Please see the documentation on how 
     26 * to use this legacy API. 
     27 */ 
     28#if PJMEDIA_AUDIO_API==PJMEDIA_AUDIO_API_NEW_ONLY 
     29#   error "The sound device API is deprecated. Please see doc for details." 
     30#endif 
    2231 
    2332 
  • pjproject/branches/projects/aps-direct/pjmedia/include/pjmedia/sound_port.h

    r2438 r2468  
    2525 * @brief Media port connection abstraction to sound device. 
    2626 */ 
    27 #include <pjmedia/sound.h> 
     27#include <pjmedia-audiodev/audiodev.h> 
    2828#include <pjmedia/port.h> 
    2929 
     
    163163 
    164164/** 
    165  * Create unidirectional or bidirectional sound port. This also allows 
    166  * creating sound port with extended settings, e.g: audio format, see  
    167  * #pjmedia_snd_setting. 
    168  * 
    169  * @param pool              Pool to allocate sound port structure. 
    170  * @param dir               Sound device direction. 
    171  * @param rec_id            Device index for recorder/capture stream, or 
    172  *                          -1 to use the first capable device. 
    173  * @param play_id           Device index for playback stream, or -1 to use  
    174  *                          the first capable device. 
    175  * @param clock_rate        Sound device's clock rate to set. 
    176  * @param channel_count     Set number of channels, 1 for mono, or 2 for 
    177  *                          stereo. The channel count determines the format 
    178  *                          of the frame. 
    179  * @param samples_per_frame Number of samples per frame. 
    180  * @param bits_per_sample   Set the number of bits per sample. The normal  
    181  *                          value for this parameter is 16 bits per sample. 
    182  * @param setting           Sound device extended settings, see  
    183  *                          #pjmedia_snd_setting. 
     165 * Create sound device port according to the specified parameters. 
     166 * 
     167 * @param pool              Pool to allocate sound port structure. 
     168 * @param prm               Sound device settings. 
    184169 * @param p_port            Pointer to receive the sound device port instance. 
    185170 * 
     
    188173 */ 
    189174PJ_DECL(pj_status_t) pjmedia_snd_port_create2(pj_pool_t *pool, 
    190                                               pjmedia_dir dir, 
    191                                               int rec_id, 
    192                                               int play_id, 
    193                                               unsigned clock_rate, 
    194                                               unsigned channel_count, 
    195                                               unsigned samples_per_frame, 
    196                                               unsigned bits_per_sample, 
    197                                               const pjmedia_snd_setting *setting, 
     175                                              const pjmedia_aud_param *prm, 
    198176                                              pjmedia_snd_port **p_port); 
    199177 
     
    217195 * @return                  The sound stream instance. 
    218196 */ 
    219 PJ_DECL(pjmedia_snd_stream*) pjmedia_snd_port_get_snd_stream( 
     197PJ_DECL(pjmedia_aud_stream*) pjmedia_snd_port_get_snd_stream( 
    220198                                                pjmedia_snd_port *snd_port); 
    221199 
    222200 
    223201/** 
    224  * Configure the echo cancellation tail length. By default, echo canceller 
    225  * is enabled in the sound device with the default tail length. After the 
    226  * sound port is created, application can query the current echo canceller 
    227  * tail length by calling #pjmedia_snd_port_get_ec_tail. 
    228  * 
    229  * Note that you should only change the EC settings when the sound port 
    230  * is not connected to any downstream ports, otherwise race condition may 
    231  * occur. 
     202 * Change the echo cancellation settings. The echo cancellation settings  
     203 * should have been specified when this sound port was created, by setting 
     204 * the appropriate fields in the pjmedia_aud_param, because not all sound 
     205 * device implementation supports changing the EC setting once the device 
     206 * has been opened. 
     207 * 
     208 * The behavior of this function depends on whether device or software AEC 
     209 * is being used. If the device supports AEC, this function will forward 
     210 * the change request to the device and it will be up to the device whether 
     211 * to support the request. If software AEC is being used (the software EC 
     212 * will be used if the device does not support AEC), this function will 
     213 * change the software EC settings. 
    232214 * 
    233215 * @param snd_port          The sound device port. 
     
    237219 *                          be disabled. 
    238220 * @param options           The options to be passed to #pjmedia_echo_create(). 
     221 *                          This is only used if software EC is being used. 
    239222 * 
    240223 * @return                  PJ_SUCCESS on success. 
  • pjproject/branches/projects/aps-direct/pjmedia/include/pjmedia/stream.h

    r2394 r2468  
    2727 */ 
    2828 
    29 #include <pjmedia/sound.h> 
    3029#include <pjmedia/codec.h> 
    3130#include <pjmedia/endpoint.h> 
  • pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia-audiodev/audiodev.c

    r2464 r2468  
    2020#include <pjmedia-audiodev/audiodev_imp.h> 
    2121#include <pj/errno.h> 
     22#include <pj/log.h> 
     23#include <pj/string.h> 
     24 
     25#define THIS_FILE   "audiodev.c" 
     26 
     27/* Capability names */ 
     28static struct cap_info 
     29{ 
     30    const char *name; 
     31    const char *info; 
     32} cap_infos[] =  
     33{ 
     34    {"ext-fmt",     "Extended/non-PCM format"}, 
     35    {"latency-in",  "Input latency/buffer size setting"}, 
     36    {"latency-out", "Output latency/buffer size setting"}, 
     37    {"vol-in",      "Input volume setting"}, 
     38    {"vol-out",     "Output volume setting"}, 
     39    {"meter-in",    "Input meter"}, 
     40    {"meter-out",   "Output meter"}, 
     41    {"route-in",    "Input routing"}, 
     42    {"route-out",   "Output routing"}, 
     43    {"aec",         "Accoustic echo cancellation"}, 
     44    {"aec-tail",    "Tail length setting for AEC"}, 
     45    {"vad",         "Voice activity detection"}, 
     46    {"cng",         "Comfort noise generation"}, 
     47    {"plg",         "Packet loss concealment"} 
     48}; 
     49 
    2250 
    2351/* 
    24  * The Device ID seen by application and driver is different.  
     52 * The device index seen by application and driver is different.  
    2553 * 
    26  * At application level, device ID is a 32bit value. The high 16bit contains 
    27  * the factory ID, and the low 16bit contains the device index in the  
    28  * specified factory. The device ID may also be -1 to denote default device. 
    29  * 
    30  * At driver level, device ID is a 16bit unsigned integer index. 
     54 * At application level, device index is index to global list of device. 
     55 * At driver level, device index is index to device list on that particular 
     56 * factory only. 
    3157 */ 
    3258#define MAKE_DEV_ID(f_id, index)   (((f_id & 0xFFFF) << 16) | (index & 0xFFFF)) 
     
    4167 
    4268#define MAX_DRIVERS     16 
     69#define MAX_DEVS        64 
     70 
     71/* typedef for factory creation function */ 
     72typedef pjmedia_aud_dev_factory*  (*create_func_ptr)(pj_pool_factory*); 
     73 
     74/* driver structure */ 
     75struct driver 
     76{ 
     77    create_func_ptr          create;    /* Creation function.               */ 
     78    pjmedia_aud_dev_factory *f;         /* Factory instance.                */ 
     79    char                     name[32];  /* Driver name                      */ 
     80    unsigned                 dev_cnt;   /* Number of devices                */ 
     81    unsigned                 start_idx; /* Start index in global list       */ 
     82}; 
    4383 
    4484/* The audio subsystem */ 
    4585static struct aud_subsys 
    4686{ 
    47     unsigned         init_count; 
    48     pj_pool_factory *pf; 
    49     unsigned         factory_cnt; 
    50  
    51     struct factory 
    52     { 
    53         pjmedia_aud_dev_factory*   (*create)(pj_pool_factory*); 
    54         pjmedia_aud_dev_factory     *f; 
    55  
    56     } factories[MAX_DRIVERS]; 
     87    unsigned         init_count;        /* How many times init() is called  */ 
     88    pj_pool_factory *pf;                /* The pool factory.                */ 
     89 
     90    unsigned         drv_cnt;           /* Number of drivers.               */ 
     91    struct driver    drv[MAX_DRIVERS];  /* Array of drivers.                */ 
     92 
     93    unsigned         dev_cnt;           /* Total number of devices.         */ 
     94    pj_uint32_t      dev_list[MAX_DEVS];/* Array of device IDs.             */ 
    5795 
    5896} aud_subsys; 
     
    74112 
    75113    aud_subsys.pf = pf; 
    76     aud_subsys.factory_cnt = 0; 
    77  
    78     aud_subsys.factories[aud_subsys.factory_cnt++].create = &pjmedia_pa_factory; 
    79     aud_subsys.factories[aud_subsys.factory_cnt++].create = &pjmedia_wmme_factory; 
    80  
    81     for (i=0; i<aud_subsys.factory_cnt; ++i) { 
     114    aud_subsys.drv_cnt = 0; 
     115    aud_subsys.dev_cnt = 0; 
     116 
     117    /* Register creation functions */ 
     118    aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_pa_factory; 
     119    aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_wmme_factory; 
     120 
     121    /* Initialize each factory and build the device ID list */ 
     122    for (i=0; i<aud_subsys.drv_cnt; ++i) { 
    82123        pjmedia_aud_dev_factory *f; 
    83  
    84         f = (*aud_subsys.factories[i].create)(pf); 
     124        pjmedia_aud_dev_info info; 
     125        unsigned j, dev_cnt; 
     126 
     127        /* Create the factory */ 
     128        f = (*aud_subsys.drv[i].create)(pf); 
    85129        if (!f) 
    86130            continue; 
    87131 
     132        /* Call factory->init() */ 
    88133        status = f->op->init(f); 
    89134        if (status != PJ_SUCCESS) { 
     
    92137        } 
    93138 
    94         aud_subsys.factories[i].f = f; 
    95         aud_subsys.factories[i].f->internal.id = i; 
    96     } 
    97  
    98     return aud_subsys.factory_cnt ? PJ_SUCCESS : status; 
     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; 
    99175} 
    100176 
     
    118194    --aud_subsys.init_count; 
    119195 
    120     for (i=0; i<aud_subsys.factory_cnt; ++i) { 
    121         pjmedia_aud_dev_factory *f = aud_subsys.factories[i].f; 
     196    for (i=0; i<aud_subsys.drv_cnt; ++i) { 
     197        pjmedia_aud_dev_factory *f = aud_subsys.drv[i].f; 
    122198 
    123199        if (!f) 
     
    125201 
    126202        f->op->destroy(f); 
    127         aud_subsys.factories[i].f = NULL; 
    128     } 
    129  
    130     return PJ_SUCCESS; 
     203        aud_subsys.drv[i].f = NULL; 
     204    } 
     205 
     206    return PJ_SUCCESS; 
     207} 
     208 
     209/* API: get capability name/info */ 
     210PJ_DEF(const char*) pjmedia_aud_dev_cap_name(pjmedia_aud_dev_cap cap, 
     211                                             const char **p_desc) 
     212{ 
     213    char *desc; 
     214    unsigned i; 
     215 
     216    if (p_desc==NULL) p_desc = &desc; 
     217 
     218    for (i=0; i<PJ_ARRAY_SIZE(cap_infos); ++i) { 
     219        if ((1 << i)==cap) 
     220            break; 
     221    } 
     222 
     223    if (i==32) { 
     224        *p_desc = "??"; 
     225        return "??"; 
     226    } 
     227 
     228    *p_desc = cap_infos[i].info; 
     229    return cap_infos[i].name; 
    131230} 
    132231 
     
    134233PJ_DEF(unsigned) pjmedia_aud_dev_count(void) 
    135234{ 
    136     unsigned i, count = 0; 
    137  
    138     for (i=0; i<aud_subsys.factory_cnt; ++i) { 
    139         pjmedia_aud_dev_factory *f = aud_subsys.factories[i].f; 
    140  
    141         if (!f) 
    142             continue; 
    143  
    144         count += f->op->get_dev_count(f); 
    145     } 
    146  
    147     return count; 
    148 } 
    149  
    150 /* API: Enumerate device ID's. */ 
    151 PJ_DEF(unsigned) pjmedia_aud_dev_enum(unsigned max_count, 
    152                                       pjmedia_aud_dev_id ids[]) 
    153 { 
    154     unsigned i, count = 0; 
    155  
    156     for (i=0; i<aud_subsys.factory_cnt && count < max_count; ++i) { 
    157         pjmedia_aud_dev_factory *f = aud_subsys.factories[i].f; 
    158         unsigned j, fcount; 
    159  
    160         if (!f) 
    161             continue; 
    162  
    163         fcount = f->op->get_dev_count(f); 
    164         for (j=0; j<fcount && count<max_count; ++j) { 
    165             ids[count++] = MAKE_DEV_ID(i, j); 
    166         } 
    167     } 
    168  
    169     return count; 
    170 } 
    171  
     235    return aud_subsys.dev_cnt; 
     236} 
     237 
     238/* Internal: lookup device id */ 
     239static pj_status_t lookup_dev(pjmedia_aud_dev_index id, 
     240                              pjmedia_aud_dev_factory **p_f, 
     241                              unsigned *p_local_index) 
     242{ 
     243    int f_id, index; 
     244 
     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); 
     250 
     251    f_id = GET_FID(aud_subsys.dev_list[id]); 
     252    index = GET_INDEX(aud_subsys.dev_list[id]); 
     253 
     254    if (f_id < 0 || f_id >= (int)aud_subsys.drv_cnt) 
     255        return PJMEDIA_EAUD_INVDEV; 
     256 
     257    if (index < 0 || index >= (int)aud_subsys.drv[f_id].dev_cnt) 
     258        return PJMEDIA_EAUD_INVDEV; 
     259 
     260    *p_f = aud_subsys.drv[f_id].f; 
     261    *p_local_index = (unsigned)index; 
     262 
     263    return PJ_SUCCESS; 
     264 
     265} 
     266 
     267/* Internal: convert local index to global device index */ 
     268static 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; 
     284} 
    172285 
    173286/* API: Get device information. */ 
    174 PJ_DEF(pj_status_t) pjmedia_aud_dev_get_info(pjmedia_aud_dev_id id, 
     287PJ_DEF(pj_status_t) pjmedia_aud_dev_get_info(pjmedia_aud_dev_index id, 
    175288                                             pjmedia_aud_dev_info *info) 
    176289{ 
    177290    pjmedia_aud_dev_factory *f; 
    178     int f_id, index; 
    179  
    180     if (id == PJMEDIA_AUD_DEV_DEFAULT_ID) 
    181         id = DEFAULT_DEV_ID; 
    182  
    183     f_id = GET_FID(id); 
    184     index = GET_INDEX(id); 
    185  
    186     if (f_id < 0 || f_id >= (int)aud_subsys.factory_cnt) 
    187         return PJMEDIA_EAUD_INVDEV; 
    188  
    189     f = aud_subsys.factories[f_id].f; 
    190     if (f == NULL) 
    191         return PJMEDIA_EAUD_INVDEV; 
     291    unsigned index; 
     292    pj_status_t status; 
     293 
     294    PJ_ASSERT_RETURN(info, PJ_EINVAL); 
     295 
     296    status = lookup_dev(id, &f, &index); 
     297    if (status != PJ_SUCCESS) 
     298        return status; 
    192299 
    193300    return f->op->get_dev_info(f, index, info); 
     301} 
     302 
     303/* API: find device */ 
     304PJ_DEF(pj_status_t) pjmedia_aud_dev_lookup( const char *drv_name, 
     305                                            const char *dev_name, 
     306                                            pjmedia_aud_dev_index *id) 
     307{ 
     308    pjmedia_aud_dev_factory *f = NULL; 
     309    unsigned i, j; 
     310 
     311    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; 
     316            break; 
     317        } 
     318    } 
     319 
     320    if (!f) 
     321        return PJ_ENOTFOUND; 
     322 
     323    for (j=0; j<aud_subsys.drv[i].dev_cnt; ++j) { 
     324        pjmedia_aud_dev_info info; 
     325        pj_status_t status; 
     326 
     327        status = f->op->get_dev_info(f, j, &info); 
     328        if (status != PJ_SUCCESS) 
     329            return status; 
     330 
     331        if (!pj_ansi_stricmp(dev_name, info.name)) 
     332            break; 
     333    } 
     334 
     335    if (j==aud_subsys.drv[i].dev_cnt) 
     336        return PJ_ENOTFOUND; 
     337 
     338    *id = j; 
     339    make_global_index(f, id); 
     340 
     341    return PJ_SUCCESS; 
    194342} 
    195343 
     
    197345 * specified device. 
    198346 */ 
    199 PJ_DEF(pj_status_t) pjmedia_aud_dev_default_param(pjmedia_aud_dev_id id, 
    200                                                   pjmedia_aud_dev_param *param) 
     347PJ_DEF(pj_status_t) pjmedia_aud_dev_default_param(pjmedia_aud_dev_index id, 
     348                                                  pjmedia_aud_param *param) 
    201349{ 
    202350    pjmedia_aud_dev_factory *f; 
    203     int f_id, index; 
     351    unsigned index; 
    204352    pj_status_t status; 
    205353 
    206     if (id == PJMEDIA_AUD_DEV_DEFAULT_ID) 
    207         id = DEFAULT_DEV_ID; 
    208  
    209     f_id = GET_FID(id); 
    210     index = GET_INDEX(id); 
    211  
    212     if (f_id < 0 || f_id >= (int)aud_subsys.factory_cnt) 
    213         return PJMEDIA_EAUD_INVDEV; 
    214  
    215     f = aud_subsys.factories[f_id].f; 
    216     if (f == NULL) 
    217         return PJMEDIA_EAUD_INVDEV; 
     354    PJ_ASSERT_RETURN(param, PJ_EINVAL); 
     355 
     356    status = lookup_dev(id, &f, &index); 
     357    if (status != PJ_SUCCESS) 
     358        return status; 
    218359 
    219360    status = f->op->default_param(f, index, param); 
     
    222363 
    223364    /* Normalize device IDs */ 
    224     if (param->rec_id != PJMEDIA_AUD_DEV_DEFAULT_ID) 
    225         param->rec_id = MAKE_DEV_ID(f_id, param->rec_id); 
    226     if (param->play_id != PJMEDIA_AUD_DEV_DEFAULT_ID) 
    227         param->play_id = MAKE_DEV_ID(f_id, param->play_id); 
     365    make_global_index(f, &param->rec_id); 
     366    make_global_index(f, &param->play_id); 
    228367 
    229368    return PJ_SUCCESS; 
     
    231370 
    232371/* API: Open audio stream object using the specified parameters. */ 
    233 PJ_DEF(pj_status_t) pjmedia_aud_stream_create(const pjmedia_aud_dev_param *p, 
     372PJ_DEF(pj_status_t) pjmedia_aud_stream_create(const pjmedia_aud_param *prm, 
    234373                                              pjmedia_aud_rec_cb rec_cb, 
    235374                                              pjmedia_aud_play_cb play_cb, 
     
    237376                                              pjmedia_aud_stream **p_aud_strm) 
    238377{ 
    239     pjmedia_aud_dev_factory *f; 
    240     pjmedia_aud_dev_param param; 
    241     int f_id; 
     378    pjmedia_aud_dev_factory *rec_f=NULL, *play_f=NULL, *f=NULL; 
     379    pjmedia_aud_param param; 
    242380    pj_status_t status; 
    243381 
     382    PJ_ASSERT_RETURN(prm && prm->dir && p_aud_strm, PJ_EINVAL); 
     383 
    244384    /* Must make copy of param because we're changing device ID */ 
    245     pj_memcpy(&param, p, sizeof(param)); 
    246  
    247     /* Set default device */ 
    248     if (param.rec_id == PJMEDIA_AUD_DEV_DEFAULT_ID)  
    249         param.rec_id = DEFAULT_DEV_ID; 
    250     if (param.play_id == PJMEDIA_AUD_DEV_DEFAULT_ID)  
    251         param.play_id = DEFAULT_DEV_ID; 
     385    pj_memcpy(&param, prm, sizeof(param)); 
     386 
     387    /* Normalize rec_id */ 
     388    if (param.dir & PJMEDIA_DIR_CAPTURE) { 
     389        unsigned index; 
     390 
     391        status = lookup_dev(param.rec_id, &rec_f, &index); 
     392        if (status != PJ_SUCCESS) 
     393            return status; 
     394 
     395        param.rec_id = index; 
     396        f = rec_f; 
     397    } 
     398 
     399    /* Normalize play_id */ 
     400    if (param.dir & PJMEDIA_DIR_PLAYBACK) { 
     401        unsigned index; 
     402 
     403        status = lookup_dev(param.play_id, &play_f, &index); 
     404        if (status != PJ_SUCCESS) 
     405            return status; 
     406 
     407        param.play_id = index; 
     408        f = play_f; 
     409 
     410        /* For now, rec_id and play_id must belong to the same factory */ 
     411        PJ_ASSERT_RETURN(rec_f == play_f, PJ_EINVAL); 
     412    } 
     413 
    252414     
    253     if (param.dir & PJMEDIA_DIR_CAPTURE) 
    254         f_id = GET_FID(param.rec_id); 
    255     else 
    256         f_id = GET_FID(param.play_id); 
    257  
    258     if (f_id < 0 || f_id >= (int)aud_subsys.factory_cnt) 
    259         return PJMEDIA_EAUD_INVDEV; 
    260      
    261     /* Normalize device id's */ 
    262     param.rec_id = GET_INDEX(param.rec_id); 
    263     param.play_id = GET_INDEX(param.play_id); 
    264  
    265     f = aud_subsys.factories[f_id].f; 
    266     if (f == NULL) 
    267         return PJMEDIA_EAUD_INVDEV; 
    268  
     415    /* Create the stream */ 
    269416    status = f->op->create_stream(f, &param, rec_cb, play_cb, 
    270417                                  user_data, p_aud_strm); 
     
    272419        return status; 
    273420 
    274     (*p_aud_strm)->factory = f; 
     421    /* Assign factory id to the stream */ 
     422    (*p_aud_strm)->factory_id = f->internal.id; 
    275423    return PJ_SUCCESS; 
    276424} 
     
    278426/* API: Get the running parameters for the specified audio stream. */ 
    279427PJ_DEF(pj_status_t) pjmedia_aud_stream_get_param(pjmedia_aud_stream *strm, 
    280                                                  pjmedia_aud_dev_param *param) 
     428                                                 pjmedia_aud_param *param) 
    281429{ 
    282430    pj_status_t status; 
     
    287435 
    288436    /* Normalize device id's */ 
    289     if (param->rec_id != PJMEDIA_AUD_DEV_DEFAULT_ID) 
    290         param->rec_id = MAKE_DEV_ID(strm->factory->internal.id, param->rec_id); 
    291     if (param->play_id != PJMEDIA_AUD_DEV_DEFAULT_ID) 
    292         param->play_id = MAKE_DEV_ID(strm->factory->internal.id, param->play_id); 
     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); 
    293439 
    294440    return PJ_SUCCESS; 
  • pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia-audiodev/audiotest.c

    r2463 r2468  
    5252{ 
    5353    pj_pool_t                      *pool; 
    54     const pjmedia_aud_dev_param    *param; 
     54    const pjmedia_aud_param    *param; 
    5555    pjmedia_aud_test_results       *result; 
    5656    pj_bool_t                       running; 
     
    182182 
    183183 
    184 PJ_DEF(pj_status_t) pjmedia_aud_test( const pjmedia_aud_dev_param *param, 
     184PJ_DEF(pj_status_t) pjmedia_aud_test( const pjmedia_aud_param *param, 
    185185                                      pjmedia_aud_test_results *result) 
    186186{ 
  • pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia-audiodev/pa_dev.c

    r2464 r2468  
    106106static pj_status_t  pa_default_param(pjmedia_aud_dev_factory *f, 
    107107                                     unsigned index, 
    108                                      pjmedia_aud_dev_param *param); 
     108                                     pjmedia_aud_param *param); 
    109109static pj_status_t  pa_create_stream(pjmedia_aud_dev_factory *f, 
    110                                      const pjmedia_aud_dev_param *param, 
     110                                     const pjmedia_aud_param *param, 
    111111                                     pjmedia_aud_rec_cb rec_cb, 
    112112                                     pjmedia_aud_play_cb play_cb, 
     
    116116/* Stream prototypes */ 
    117117static pj_status_t strm_get_param(pjmedia_aud_stream *strm, 
    118                                   pjmedia_aud_dev_param *param); 
     118                                  pjmedia_aud_param *param); 
    119119static pj_status_t strm_get_cap(pjmedia_aud_stream *strm, 
    120120                                pjmedia_aud_dev_cap cap, 
     
    515515static pj_status_t  pa_default_param(pjmedia_aud_dev_factory *f, 
    516516                                     unsigned index, 
    517                                      pjmedia_aud_dev_param *param) 
     517                                     pjmedia_aud_param *param) 
    518518{ 
    519519    pjmedia_aud_dev_info adi; 
     
    534534        param->dir = PJMEDIA_DIR_CAPTURE; 
    535535        param->rec_id = index; 
    536         param->play_id = PJMEDIA_AUD_DEV_DEFAULT_ID; 
     536        param->play_id = PJMEDIA_AUD_DEV_DEFAULT; 
    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_ID; 
     540        param->rec_id = PJMEDIA_AUD_DEV_DEFAULT; 
    541541    } else { 
    542542        return PJMEDIA_EAUD_INVDEV; 
     
    670670/* Internal: create capture/recorder stream */ 
    671671static pj_status_t create_rec_stream( struct pa_aud_factory *pa, 
    672                                       const pjmedia_aud_dev_param *param, 
     672                                      const pjmedia_aud_param *param, 
    673673                                      pjmedia_aud_rec_cb rec_cb, 
    674674                                      void *user_data, 
     
    676676{ 
    677677    pj_pool_t *pool; 
    678     pjmedia_aud_dev_id rec_id; 
     678    pjmedia_aud_dev_index rec_id; 
    679679    struct pa_aud_stream *stream; 
    680680    PaStreamParameters inputParam; 
     
    775775/* Internal: create playback stream */ 
    776776static pj_status_t create_play_stream(struct pa_aud_factory *pa, 
    777                                       const pjmedia_aud_dev_param *param, 
     777                                      const pjmedia_aud_param *param, 
    778778                                      pjmedia_aud_play_cb play_cb, 
    779779                                      void *user_data, 
     
    781781{ 
    782782    pj_pool_t *pool; 
    783     pjmedia_aud_dev_id play_id; 
     783    pjmedia_aud_dev_index play_id; 
    784784    struct pa_aud_stream *stream; 
    785785    PaStreamParameters outputParam; 
     
    882882/* Internal: Create both player and recorder stream */ 
    883883static pj_status_t create_bidir_stream(struct pa_aud_factory *pa, 
    884                                        const pjmedia_aud_dev_param *param, 
     884                                       const pjmedia_aud_param *param, 
    885885                                       pjmedia_aud_rec_cb rec_cb, 
    886886                                       pjmedia_aud_play_cb play_cb, 
     
    889889{ 
    890890    pj_pool_t *pool; 
    891     pjmedia_aud_dev_id rec_id, play_id; 
     891    pjmedia_aud_dev_index rec_id, play_id; 
    892892    struct pa_aud_stream *stream; 
    893893    PaStream *paStream = NULL; 
     
    10611061/* API: create stream */ 
    10621062static pj_status_t  pa_create_stream(pjmedia_aud_dev_factory *f, 
    1063                                      const pjmedia_aud_dev_param *param, 
     1063                                     const pjmedia_aud_param *param, 
    10641064                                     pjmedia_aud_rec_cb rec_cb, 
    10651065                                     pjmedia_aud_play_cb play_cb, 
     
    10921092/* API: Get stream parameters */ 
    10931093static pj_status_t strm_get_param(pjmedia_aud_stream *s, 
    1094                                   pjmedia_aud_dev_param *pi) 
     1094                                  pjmedia_aud_param *pi) 
    10951095{ 
    10961096    struct pa_aud_stream *strm = (struct pa_aud_stream*)s; 
  • pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia-audiodev/symb_aps_dev.cpp

    r2466 r2468  
    7272 
    7373    // Common settings. 
    74     pjmedia_aud_dev_param param;                /**< Stream param.      */ 
     74    pjmedia_aud_param param;            /**< Stream param.      */ 
    7575    pjmedia_aud_rec_cb   rec_cb;                /**< Record callback.   */ 
    7676    pjmedia_aud_play_cb  play_cb;               /**< Playback callback. */ 
     
    101101static pj_status_t factory_default_param(pjmedia_aud_dev_factory *f, 
    102102                                         unsigned index, 
    103                                          pjmedia_aud_dev_param *param); 
     103                                         pjmedia_aud_param *param); 
    104104static pj_status_t factory_create_stream(pjmedia_aud_dev_factory *f, 
    105                                          const pjmedia_aud_dev_param *param, 
     105                                         const pjmedia_aud_param *param, 
    106106                                         pjmedia_aud_rec_cb rec_cb, 
    107107                                         pjmedia_aud_play_cb play_cb, 
     
    110110 
    111111static pj_status_t stream_get_param(pjmedia_aud_stream *strm, 
    112                                     pjmedia_aud_dev_param *param); 
     112                                    pjmedia_aud_param *param); 
    113113static pj_status_t stream_get_cap(pjmedia_aud_stream *strm, 
    114114                                  pjmedia_aud_dev_cap cap, 
     
    11761176static pj_status_t factory_default_param(pjmedia_aud_dev_factory *f, 
    11771177                                         unsigned index, 
    1178                                          pjmedia_aud_dev_param *param) 
     1178                                         pjmedia_aud_param *param) 
    11791179{ 
    11801180    struct aps_factory *af = (struct aps_factory*)f; 
     
    12001200/* API: create stream */ 
    12011201static pj_status_t factory_create_stream(pjmedia_aud_dev_factory *f, 
    1202                                          const pjmedia_aud_dev_param *param, 
     1202                                         const pjmedia_aud_param *param, 
    12031203                                         pjmedia_aud_rec_cb rec_cb, 
    12041204                                         pjmedia_aud_play_cb play_cb, 
     
    13331333/* API: Get stream info. */ 
    13341334static pj_status_t stream_get_param(pjmedia_aud_stream *s, 
    1335                                     pjmedia_aud_dev_param *pi) 
     1335                                    pjmedia_aud_param *pi) 
    13361336{ 
    13371337    struct aps_stream *strm = (struct aps_stream*)s; 
  • pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia-audiodev/symb_mda_dev.cpp

    r2467 r2468  
    7373 
    7474    // Common settings. 
    75     pjmedia_aud_dev_param param;                /**< Stream param.      */ 
     75    pjmedia_aud_param param;            /**< Stream param.      */ 
    7676 
    7777    // Audio engine 
     
    9090static pj_status_t factory_default_param(pjmedia_aud_dev_factory *f, 
    9191                                         unsigned index, 
    92                                          pjmedia_aud_dev_param *param); 
     92                                         pjmedia_aud_param *param); 
    9393static pj_status_t factory_create_stream(pjmedia_aud_dev_factory *f, 
    94                                          const pjmedia_aud_dev_param *param, 
     94                                         const pjmedia_aud_param *param, 
    9595                                         pjmedia_aud_rec_cb rec_cb, 
    9696                                         pjmedia_aud_play_cb play_cb, 
     
    9999 
    100100static pj_status_t stream_get_param(pjmedia_aud_stream *strm, 
    101                                     pjmedia_aud_dev_param *param); 
     101                                    pjmedia_aud_param *param); 
    102102static pj_status_t stream_get_cap(pjmedia_aud_stream *strm, 
    103103                                  pjmedia_aud_dev_cap cap, 
     
    845845static pj_status_t factory_default_param(pjmedia_aud_dev_factory *f, 
    846846                                         unsigned index, 
    847                                          pjmedia_aud_dev_param *param) 
     847                                         pjmedia_aud_param *param) 
    848848{ 
    849849    struct mda_factory *af = (struct mda_factory*)f; 
     
    867867/* API: create stream */ 
    868868static pj_status_t factory_create_stream(pjmedia_aud_dev_factory *f, 
    869                                          const pjmedia_aud_dev_param *param, 
     869                                         const pjmedia_aud_param *param, 
    870870                                         pjmedia_aud_rec_cb rec_cb, 
    871871                                         pjmedia_aud_play_cb play_cb, 
     
    922922/* API: Get stream info. */ 
    923923static pj_status_t stream_get_param(pjmedia_aud_stream *s, 
    924                                     pjmedia_aud_dev_param *pi) 
     924                                    pjmedia_aud_param *pi) 
    925925{ 
    926926    struct mda_stream *strm = (struct mda_stream*)s; 
  • pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia-audiodev/wmme_dev.c

    r2459 r2468  
    121121static pj_status_t factory_default_param(pjmedia_aud_dev_factory *f, 
    122122                                         unsigned index, 
    123                                          pjmedia_aud_dev_param *param); 
     123                                         pjmedia_aud_param *param); 
    124124static pj_status_t factory_create_stream(pjmedia_aud_dev_factory *f, 
    125                                          const pjmedia_aud_dev_param *param, 
     125                                         const pjmedia_aud_param *param, 
    126126                                         pjmedia_aud_rec_cb rec_cb, 
    127127                                         pjmedia_aud_play_cb play_cb, 
     
    130130 
    131131static pj_status_t stream_get_param(pjmedia_aud_stream *strm, 
    132                                     pjmedia_aud_dev_param *param); 
     132                                    pjmedia_aud_param *param); 
    133133static pj_status_t stream_get_cap(pjmedia_aud_stream *strm, 
    134134                                  pjmedia_aud_dev_cap cap, 
     
    399399static pj_status_t factory_default_param(pjmedia_aud_dev_factory *f, 
    400400                                         unsigned index, 
    401                                          pjmedia_aud_dev_param *param) 
     401                                         pjmedia_aud_param *param) 
    402402{ 
    403403    struct wmme_factory *wf = (struct wmme_factory*)f; 
     
    414414        param->dir = PJMEDIA_DIR_CAPTURE; 
    415415        param->rec_id = index; 
    416         param->play_id = PJMEDIA_AUD_DEV_DEFAULT_ID; 
     416        param->play_id = PJMEDIA_AUD_DEV_DEFAULT; 
    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_ID; 
     420        param->rec_id = PJMEDIA_AUD_DEV_DEFAULT; 
    421421    } else { 
    422422        return PJMEDIA_EAUD_INVDEV; 
     
    816816/* API: create stream */ 
    817817static pj_status_t factory_create_stream(pjmedia_aud_dev_factory *f, 
    818                                          const pjmedia_aud_dev_param *param, 
     818                                         const pjmedia_aud_param *param, 
    819819                                         pjmedia_aud_rec_cb rec_cb, 
    820820                                         pjmedia_aud_play_cb play_cb, 
     
    930930/* API: Get stream info. */ 
    931931static pj_status_t stream_get_param(pjmedia_aud_stream *s, 
    932                                     pjmedia_aud_dev_param *pi) 
     932                                    pjmedia_aud_param *pi) 
    933933{ 
    934934    struct wmme_stream *strm = (struct wmme_stream*)s; 
  • pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia/conf_switch.c

    r2460 r2468  
    114114    unsigned              port_cnt;     /**< Current number of ports.       */ 
    115115    unsigned              connect_cnt;  /**< Total number of connections    */ 
    116     pjmedia_snd_port     *snd_dev_port; /**< Sound device port.             */ 
    117116    pjmedia_port         *master_port;  /**< Port zero's port.              */ 
    118117    char                  master_name_buf[80]; /**< Port0 name buffer.      */ 
     
    188187    pj_status_t status; 
    189188 
    190  
    191189    status = create_conf_port(pool, conf, conf->master_port, &name, &conf_port); 
    192190    if (status != PJ_SUCCESS) 
    193191        return status; 
    194  
    195  
    196     /* Create sound device port: */ 
    197  
    198     if ((conf->options & PJMEDIA_CONF_NO_DEVICE) == 0) { 
    199         pjmedia_snd_stream *strm; 
    200         pjmedia_snd_stream_info si; 
    201         pjmedia_port_info *master_port_info = (pjmedia_port_info*) 
    202                                               &conf->master_port->info; 
    203  
    204         /* 
    205          * If capture is disabled then create player only port. 
    206          * Otherwise create bidirectional sound device port. 
    207          */ 
    208         if (conf->options & PJMEDIA_CONF_NO_MIC)  { 
    209             status = pjmedia_snd_port_create_player( 
    210                                         pool, -1,  
    211                                         master_port_info->clock_rate, 
    212                                         master_port_info->channel_count, 
    213                                         master_port_info->samples_per_frame, 
    214                                         master_port_info->bits_per_sample,  
    215                                         0,      /* options */ 
    216                                         &conf->snd_dev_port); 
    217  
    218         } else { 
    219             status = pjmedia_snd_port_create(  
    220                                         pool, -1, -1,  
    221                                         master_port_info->clock_rate,  
    222                                         master_port_info->channel_count,  
    223                                         master_port_info->samples_per_frame, 
    224                                         master_port_info->bits_per_sample, 
    225                                         0,    /* Options */ 
    226                                         &conf->snd_dev_port); 
    227         } 
    228  
    229         if (status != PJ_SUCCESS) 
    230             return status; 
    231  
    232         strm = pjmedia_snd_port_get_snd_stream(conf->snd_dev_port); 
    233         status = pjmedia_snd_stream_get_info(strm, &si); 
    234         if (status == PJ_SUCCESS) { 
    235             const pjmedia_snd_dev_info *snd_dev_info; 
    236             if (conf->options & PJMEDIA_CONF_NO_MIC) 
    237                 snd_dev_info = pjmedia_snd_get_dev_info(si.play_id); 
    238             else 
    239                 snd_dev_info = pjmedia_snd_get_dev_info(si.rec_id); 
    240             pj_strdup2_with_null(pool, &conf_port->name, snd_dev_info->name); 
    241         } 
    242     } 
    243  
    244192 
    245193     /* Add the port to the bridge */ 
     
    247195    conf->ports[0] = conf_port; 
    248196    conf->port_cnt++; 
    249  
    250197 
    251198    PJ_LOG(5,(THIS_FILE, "Sound device successfully created for port 0")); 
     
    312259        return status; 
    313260 
    314     /* If sound device was created, connect sound device to the 
    315      * master port. 
    316      */ 
    317     if (conf->snd_dev_port) { 
    318         status = pjmedia_snd_port_connect( conf->snd_dev_port,  
    319                                            conf->master_port ); 
    320         if (status != PJ_SUCCESS) { 
    321             pjmedia_conf_destroy(conf); 
    322             return status; 
    323         } 
    324     } 
    325  
    326261    /* Done */ 
    327262 
     
    359294{ 
    360295    PJ_ASSERT_RETURN(conf != NULL, PJ_EINVAL); 
    361  
    362     /* Destroy sound device port. */ 
    363     if (conf->snd_dev_port) { 
    364         pjmedia_snd_port_destroy(conf->snd_dev_port); 
    365         conf->snd_dev_port = NULL; 
    366     } 
    367296 
    368297    /* Destroy mutex */ 
  • pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia/conference.c

    r2460 r2468  
    466466 
    467467    if ((conf->options & PJMEDIA_CONF_NO_DEVICE) == 0) { 
    468         pjmedia_snd_stream *strm; 
    469         pjmedia_snd_stream_info si; 
     468        pjmedia_aud_stream *strm; 
     469        pjmedia_aud_param param; 
    470470 
    471471        /* 
     
    495495 
    496496        strm = pjmedia_snd_port_get_snd_stream(conf->snd_dev_port); 
    497         status = pjmedia_snd_stream_get_info(strm, &si); 
     497        status = pjmedia_aud_stream_get_param(strm, &param); 
    498498        if (status == PJ_SUCCESS) { 
    499             const pjmedia_snd_dev_info *snd_dev_info; 
     499            pjmedia_aud_dev_info snd_dev_info; 
    500500            if (conf->options & PJMEDIA_CONF_NO_MIC) 
    501                 snd_dev_info = pjmedia_snd_get_dev_info(si.play_id); 
     501                pjmedia_aud_dev_get_info(param.play_id, &snd_dev_info); 
    502502            else 
    503                 snd_dev_info = pjmedia_snd_get_dev_info(si.rec_id); 
    504             pj_strdup2_with_null(pool, &conf_port->name, snd_dev_info->name); 
     503                pjmedia_aud_dev_get_info(param.rec_id, &snd_dev_info); 
     504            pj_strdup2_with_null(pool, &conf_port->name, snd_dev_info.name); 
    505505        } 
    506506    } 
  • pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia/endpoint.c

    r2394 r2468  
    2121#include <pjmedia/errno.h> 
    2222#include <pjmedia/sdp.h> 
     23#include <pjmedia-audiodev/audiodev.h> 
    2324#include <pj/assert.h> 
    2425#include <pj/ioqueue.h> 
     
    122123 
    123124    /* Sound */ 
    124     status = pjmedia_snd_init(pf); 
     125    status = pjmedia_aud_subsys_init(pf); 
    125126    if (status != PJ_SUCCESS) 
    126127        goto on_error; 
     
    172173        pj_ioqueue_destroy(endpt->ioqueue); 
    173174 
    174     pjmedia_snd_deinit(); 
     175    pjmedia_aud_subsys_shutdown(); 
    175176    pj_pool_release(pool); 
    176177    return status; 
     
    213214    endpt->pf = NULL; 
    214215 
    215     pjmedia_snd_deinit(); 
     216    pjmedia_aud_subsys_shutdown(); 
    216217    pj_pool_release (endpt->pool); 
    217218 
  • pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia/sound_port.c

    r2460 r2468  
    2323#include <pjmedia/echo.h> 
    2424#include <pjmedia/errno.h> 
    25 #include <pjmedia/plc.h> 
    2625#include <pj/assert.h> 
    2726#include <pj/log.h> 
     
    2928#include <pj/string.h>      /* pj_memset() */ 
    3029 
    31 //#define SIMULATE_LOST_PCT   20 
    3230#define AEC_TAIL            128     /* default AEC length in ms */ 
    3331#define AEC_SUSPEND_LIMIT   5       /* seconds of no activity   */ 
     
    4139    int                  rec_id; 
    4240    int                  play_id; 
    43     pjmedia_snd_stream  *snd_stream; 
     41    pj_uint32_t          aud_caps; 
     42    pjmedia_aud_param    aud_param; 
     43    pjmedia_aud_stream  *aud_stream; 
    4444    pjmedia_dir          dir; 
    4545    pjmedia_port        *port; 
    46  
    47     pjmedia_echo_state  *ec_state; 
    48     unsigned             aec_tail_len; 
    49  
    50     pj_bool_t            ec_suspended; 
    51     unsigned             ec_suspend_count; 
    52     unsigned             ec_suspend_limit; 
    53  
    54     pjmedia_plc         *plc; 
    5546 
    5647    unsigned             clock_rate; 
     
    5849    unsigned             samples_per_frame; 
    5950    unsigned             bits_per_sample; 
    60     pjmedia_snd_setting  setting; 
    61  
    62 #if PJMEDIA_SOUND_USE_DELAYBUF 
    63     pjmedia_delay_buf   *delay_buf; 
    64 #endif 
    65  
    66     /* Encoded sound emulation */ 
    67 #if !defined(PJMEDIA_SND_SUPPORT_OPEN2) || !PJMEDIA_SND_SUPPORT_OPEN2 
    68     unsigned             frm_buf_size; 
    69     pj_uint8_t          *put_frm_buf; 
    70     pj_uint8_t          *get_frm_buf; 
    71 #endif 
     51 
     52    /* software ec */ 
     53    pjmedia_echo_state  *ec_state; 
     54    unsigned             ec_options; 
     55    unsigned             ec_tail_len; 
     56    pj_bool_t            ec_suspended; 
     57    unsigned             ec_suspend_count; 
     58    unsigned             ec_suspend_limit; 
    7259}; 
    7360 
     
    7663 * played. 
    7764 */ 
    78 static pj_status_t play_cb(/* in */   void *user_data, 
    79                            /* in */   pj_uint32_t timestamp, 
    80                            /* out */  void *output, 
    81                            /* out */  unsigned size) 
     65static pj_status_t play_cb(void *user_data, pjmedia_frame *frame) 
    8266{ 
    8367    pjmedia_snd_port *snd_port = (pjmedia_snd_port*) user_data; 
    8468    pjmedia_port *port; 
    85     pjmedia_frame frame; 
     69    unsigned required_size = frame->size; 
    8670    pj_status_t status; 
    8771 
     
    9074        goto no_frame; 
    9175 
    92     frame.buf = output; 
    93     frame.size = size; 
    94     frame.timestamp.u32.hi = 0; 
    95     frame.timestamp.u32.lo = timestamp; 
    96  
    97 #if PJMEDIA_SOUND_USE_DELAYBUF 
    98     if (snd_port->delay_buf) { 
    99         status = pjmedia_delay_buf_get(snd_port->delay_buf, (pj_int16_t*)output); 
    100         if (status != PJ_SUCCESS) 
    101             pj_bzero(output, size); 
    102  
    103         frame.type = PJMEDIA_FRAME_TYPE_AUDIO; 
    104         pjmedia_port_put_frame(port, &frame); 
    105  
    106 #ifdef TEST_OVERFLOW_UNDERFLOW 
    107         { 
    108             static int count = 1; 
    109             if (++count % 10 == 0) { 
    110                 status = pjmedia_delay_buf_get(snd_port->delay_buf,  
    111                                                (pj_int16_t*)output); 
    112                 if (status != PJ_SUCCESS) 
    113                     pj_bzero(output, size); 
    114  
    115                 frame.type = PJMEDIA_FRAME_TYPE_AUDIO; 
    116                 pjmedia_port_put_frame(port, &frame); 
    117             } 
    118         } 
    119 #endif 
    120  
    121     } 
    122 #endif 
    123  
    124     status = pjmedia_port_get_frame(port, &frame); 
     76    status = pjmedia_port_get_frame(port, frame); 
    12577    if (status != PJ_SUCCESS) 
    12678        goto no_frame; 
    12779 
    128     if (frame.type != PJMEDIA_FRAME_TYPE_AUDIO) 
     80    if (frame->type != PJMEDIA_FRAME_TYPE_AUDIO) 
    12981        goto no_frame; 
    13082 
    13183    /* Must supply the required samples */ 
    132     pj_assert(frame.size == size); 
    133  
    134 #ifdef SIMULATE_LOST_PCT 
    135     /* Simulate packet lost */ 
    136     if (pj_rand() % 100 < SIMULATE_LOST_PCT) { 
    137         PJ_LOG(4,(THIS_FILE, "Frame dropped")); 
    138         goto no_frame; 
    139     } 
    140 #endif 
    141  
    142     if (snd_port->plc) 
    143         pjmedia_plc_save(snd_port->plc, (pj_int16_t*) output); 
     84    PJ_UNUSED_ARG(required_size); 
     85    pj_assert(frame->size == required_size); 
    14486 
    14587    if (snd_port->ec_state) { 
     
    15092        } 
    15193        snd_port->ec_suspend_count = 0; 
    152         pjmedia_echo_playback(snd_port->ec_state, (pj_int16_t*)output); 
     94        pjmedia_echo_playback(snd_port->ec_state, (pj_int16_t*)frame->buf); 
    15395    } 
    15496 
     
    166108        if (snd_port->ec_state) { 
    167109            /* To maintain correct delay in EC */ 
    168             pjmedia_echo_playback(snd_port->ec_state, (pj_int16_t*)output); 
    169         } 
    170     } 
    171  
    172     /* Apply PLC */ 
    173     if (snd_port->plc) { 
    174  
    175         pjmedia_plc_generate(snd_port->plc, (pj_int16_t*) output); 
    176 #ifdef SIMULATE_LOST_PCT 
    177         PJ_LOG(4,(THIS_FILE, "Lost frame generated")); 
    178 #endif 
    179     } else { 
    180         pj_bzero(output, size); 
    181     } 
    182  
     110            pjmedia_echo_playback(snd_port->ec_state, (pj_int16_t*)frame->buf); 
     111        } 
     112    } 
    183113 
    184114    return PJ_SUCCESS; 
     
    190120 * frame. 
    191121 */ 
    192 static pj_status_t rec_cb(/* in */   void *user_data, 
    193                           /* in */   pj_uint32_t timestamp, 
    194                           /* in */   void *input, 
    195                           /* in*/    unsigned size) 
     122static pj_status_t rec_cb(void *user_data, pjmedia_frame *frame) 
    196123{ 
    197124    pjmedia_snd_port *snd_port = (pjmedia_snd_port*) user_data; 
    198125    pjmedia_port *port; 
    199     pjmedia_frame frame; 
    200126 
    201127    port = snd_port->port; 
     
    205131    /* Cancel echo */ 
    206132    if (snd_port->ec_state && !snd_port->ec_suspended) { 
    207         pjmedia_echo_capture(snd_port->ec_state, (pj_int16_t*) input, 0); 
    208     } 
    209  
    210 #if PJMEDIA_SOUND_USE_DELAYBUF 
    211     if (snd_port->delay_buf) { 
    212         pjmedia_delay_buf_put(snd_port->delay_buf, (pj_int16_t*)input); 
    213     } else { 
    214         frame.buf = (void*)input; 
    215         frame.size = size; 
    216         frame.type = PJMEDIA_FRAME_TYPE_AUDIO; 
    217         frame.timestamp.u32.lo = timestamp; 
    218  
    219         pjmedia_port_put_frame(port, &frame); 
    220     } 
    221 #else 
    222     frame.buf = (void*)input; 
    223     frame.size = size; 
    224     frame.type = PJMEDIA_FRAME_TYPE_AUDIO; 
    225     frame.timestamp.u32.lo = timestamp; 
    226  
    227     pjmedia_port_put_frame(port, &frame); 
    228 #endif 
     133        pjmedia_echo_capture(snd_port->ec_state, (pj_int16_t*) frame->buf, 0); 
     134    } 
     135 
     136    pjmedia_port_put_frame(port, frame); 
    229137 
    230138    return PJ_SUCCESS; 
     
    235143 * played. This version is for non-PCM data. 
    236144 */ 
    237 static pj_status_t play_cb_ext(/* in */   void *user_data, 
    238                                /* in */   pj_uint32_t timestamp, 
    239                                /* out */  void *output, 
    240                                /* out */  unsigned size) 
    241 { 
    242 #if defined(PJMEDIA_SND_SUPPORT_OPEN2) && PJMEDIA_SND_SUPPORT_OPEN2!=0 
    243     /* This is the version to use when the sound device supports 
    244      * open2(). 
    245      */ 
     145static pj_status_t play_cb_ext(void *user_data, pjmedia_frame *frame) 
     146{ 
    246147    pjmedia_snd_port *snd_port = (pjmedia_snd_port*) user_data; 
    247     pjmedia_port *port; 
    248     pjmedia_frame *frame = (pjmedia_frame*) output; 
    249     pj_status_t status; 
    250  
    251     PJ_UNUSED_ARG(size); 
    252     PJ_UNUSED_ARG(timestamp); 
    253  
    254     port = snd_port->port; 
     148    pjmedia_port *port = snd_port->port; 
     149 
    255150    if (port == NULL) { 
    256151        frame->type = PJMEDIA_FRAME_TYPE_NONE; 
     
    258153    } 
    259154 
    260     status = pjmedia_port_get_frame(port, frame); 
    261  
    262     return status; 
    263 #else 
    264     /* This is the emulation version */ 
    265     pjmedia_snd_port *snd_port = (pjmedia_snd_port*) user_data; 
    266     pjmedia_port *port = snd_port->port; 
    267     pjmedia_frame_ext *fx = (pjmedia_frame_ext*) snd_port->get_frm_buf; 
    268     pj_status_t status; 
    269  
    270     if (port==NULL) { 
    271         goto no_frame; 
    272     } 
    273  
    274     pj_bzero(fx, sizeof(*fx)); 
    275     fx->base.type = PJMEDIA_FRAME_TYPE_NONE; 
    276     fx->base.buf = ((pj_uint8_t*)fx) + sizeof(*fx); 
    277     fx->base.size = snd_port->frm_buf_size - sizeof(*fx); 
    278     fx->base.timestamp.u32.hi = 0; 
    279     fx->base.timestamp.u32.lo = timestamp; 
    280  
    281     status = pjmedia_port_get_frame(port, &fx->base); 
    282     if (status != PJ_SUCCESS) 
    283         goto no_frame; 
    284  
    285     if (fx->base.type == PJMEDIA_FRAME_TYPE_AUDIO) { 
    286         pj_assert(fx->base.size == size); 
    287         pj_memcpy(output, fx->base.buf, size); 
    288     } else if (fx->base.type == PJMEDIA_FRAME_TYPE_EXTENDED) { 
    289         void (*decoder)(pj_int16_t*, const pj_uint8_t*, pj_size_t) = NULL; 
    290         unsigned i, size_decoded; 
    291  
    292         switch (snd_port->setting.format.id) { 
    293         case PJMEDIA_FORMAT_PCMA: 
    294             decoder = &pjmedia_alaw_decode; 
    295             break; 
    296         case PJMEDIA_FORMAT_PCMU: 
    297             decoder = &pjmedia_ulaw_decode; 
    298             break; 
    299         default: 
    300             PJ_LOG(1,(THIS_FILE, "Unsupported format %d",  
    301                       snd_port->setting.format.id)); 
    302             goto no_frame; 
    303         } 
    304  
    305         if (fx->samples_cnt > size>>1) { 
    306             PJ_LOG(4,(THIS_FILE, "Frame too large by %d samples",  
    307                       fx->samples_cnt - (size>>1))); 
    308         } else if (fx->samples_cnt < size>>1) { 
    309             PJ_LOG(4,(THIS_FILE, "Not enough frame by %d samples",  
    310                       (size>>1) - fx->samples_cnt)); 
    311         } 
    312  
    313         for (i=0, size_decoded=0;  
    314              i<fx->subframe_cnt && size_decoded<size;  
    315              ++i)  
    316         { 
    317             pjmedia_frame_ext_subframe *subfrm; 
    318  
    319             subfrm = pjmedia_frame_ext_get_subframe(fx, i);          
    320  
    321             if (!subfrm || subfrm->bitlen==0) 
    322                 continue; 
    323  
    324             if ((subfrm->bitlen>>3) > (int)(size-size_decoded)) { 
    325                 subfrm->bitlen = (pj_uint16_t)((size-size_decoded) << 3); 
    326             } 
    327  
    328             (*decoder)((short*)((pj_uint8_t*)output + size_decoded), 
    329                        subfrm->data, subfrm->bitlen>>3); 
    330  
    331             size_decoded += (subfrm->bitlen>>3) << 1; 
    332         } 
    333  
    334         if (size_decoded < size) { 
    335             pj_bzero((pj_uint8_t*)output + size_decoded, size-size_decoded); 
    336         } 
    337  
    338     } else { 
    339         goto no_frame; 
    340     } 
    341  
    342     return PJ_SUCCESS; 
    343  
    344 no_frame: 
    345     pj_bzero(output, size); 
    346     return PJ_SUCCESS; 
    347  
    348 #endif  /* PJMEDIA_SND_SUPPORT_OPEN2 */ 
     155    pjmedia_port_get_frame(port, frame); 
     156 
     157    return PJ_SUCCESS; 
    349158} 
    350159 
     
    354163 * frame. This version is for non-PCM data. 
    355164 */ 
    356 static pj_status_t rec_cb_ext(/* in */   void *user_data, 
    357                               /* in */   pj_uint32_t timestamp, 
    358                               /* in */   void *input, 
    359                               /* in*/    unsigned size) 
    360 { 
    361 #if defined(PJMEDIA_SND_SUPPORT_OPEN2) && PJMEDIA_SND_SUPPORT_OPEN2!=0 
    362     /* This is the version to use when the sound device supports 
    363      * open2(). 
    364      */ 
     165static pj_status_t rec_cb_ext(void *user_data, pjmedia_frame *frame) 
     166{ 
    365167    pjmedia_snd_port *snd_port = (pjmedia_snd_port*) user_data; 
    366168    pjmedia_port *port; 
    367     pjmedia_frame *frame = (pjmedia_frame*)input; 
    368  
    369     PJ_UNUSED_ARG(size); 
    370     PJ_UNUSED_ARG(timestamp); 
    371169 
    372170    port = snd_port->port; 
     
    377175 
    378176    return PJ_SUCCESS; 
    379 #else 
    380     pjmedia_snd_port *snd_port = (pjmedia_snd_port*) user_data; 
    381     pjmedia_port *port = snd_port->port; 
    382     pjmedia_frame_ext *fx = (pjmedia_frame_ext*) snd_port->put_frm_buf; 
    383     void (*encoder)(pj_uint8_t*, const pj_int16_t*, pj_size_t) = NULL; 
    384  
    385     if (port==NULL) 
    386         return PJ_SUCCESS; 
    387  
    388     pj_bzero(fx, sizeof(*fx)); 
    389     fx->base.buf = NULL; 
    390     fx->base.size = snd_port->frm_buf_size - sizeof(*fx); 
    391     fx->base.type = PJMEDIA_FRAME_TYPE_EXTENDED; 
    392     fx->base.timestamp.u32.lo = timestamp; 
    393  
    394     switch (snd_port->setting.format.id) { 
    395     case PJMEDIA_FORMAT_PCMA: 
    396         encoder = &pjmedia_alaw_encode; 
    397         break; 
    398     case PJMEDIA_FORMAT_PCMU: 
    399         encoder = &pjmedia_ulaw_encode; 
    400         break; 
    401     default: 
    402         PJ_LOG(1,(THIS_FILE, "Unsupported format %d",  
    403                   snd_port->setting.format.id)); 
    404         return PJ_SUCCESS; 
    405     } 
    406  
    407     (*encoder)((pj_uint8_t*)input, (pj_int16_t*)input, size >> 1); 
    408  
    409     pjmedia_frame_ext_append_subframe(fx, input, (size >> 1) << 3,  
    410                                       size >> 1); 
    411     pjmedia_port_put_frame(port, &fx->base); 
    412  
    413     return PJ_SUCCESS; 
    414 #endif 
    415177} 
    416178 
     
    422184                                       pjmedia_snd_port *snd_port ) 
    423185{ 
    424     pjmedia_snd_rec_cb snd_rec_cb; 
    425     pjmedia_snd_play_cb snd_play_cb; 
     186    pjmedia_aud_rec_cb snd_rec_cb; 
     187    pjmedia_aud_play_cb snd_play_cb; 
     188    pjmedia_aud_param param_copy; 
    426189    pj_status_t status; 
    427190 
    428191    /* Check if sound has been started. */ 
    429     if (snd_port->snd_stream != NULL) 
     192    if (snd_port->aud_stream != NULL) 
    430193        return PJ_SUCCESS; 
    431194 
     
    435198                     PJ_EBUG); 
    436199 
    437     if (snd_port->setting.format.id == PJMEDIA_FORMAT_L16) { 
     200    /* Get device caps */ 
     201    if (snd_port->aud_param.dir & PJMEDIA_DIR_CAPTURE) { 
     202        pjmedia_aud_dev_info dev_info; 
     203 
     204        status = pjmedia_aud_dev_get_info(snd_port->aud_param.rec_id,  
     205                                          &dev_info); 
     206        if (status != PJ_SUCCESS) 
     207            return status; 
     208 
     209        snd_port->aud_caps = dev_info.caps; 
     210    } else { 
     211        snd_port->aud_caps = 0; 
     212    } 
     213 
     214    /* Process EC settings */ 
     215    pj_memcpy(&param_copy, &snd_port->aud_param, sizeof(param_copy)); 
     216    if (param_copy.flags & PJMEDIA_AUD_DEV_CAP_EC) { 
     217        /* EC is wanted */ 
     218        if (snd_port->aud_caps & PJMEDIA_AUD_DEV_CAP_EC) { 
     219            /* Device supports EC */ 
     220            /* Nothing to do */ 
     221        } else { 
     222            /* Device doesn't support EC, remove EC settings from 
     223             * device parameters 
     224             */ 
     225            param_copy.flags &= ~(PJMEDIA_AUD_DEV_CAP_EC | 
     226                                  PJMEDIA_AUD_DEV_CAP_EC_TAIL); 
     227        } 
     228    } 
     229 
     230    /* Use different callback if format is not PCM */ 
     231    if (snd_port->aud_param.ext_fmt.id == PJMEDIA_FORMAT_L16) { 
    438232        snd_rec_cb = &rec_cb; 
    439233        snd_play_cb = &play_cb; 
     
    443237    } 
    444238 
    445 #if defined(PJMEDIA_SND_SUPPORT_OPEN2) && PJMEDIA_SND_SUPPORT_OPEN2!=0 
    446     status = pjmedia_snd_open2( snd_port->dir, 
    447                                 snd_port->rec_id,  
    448                                 snd_port->play_id, 
    449                                 snd_port->clock_rate, 
    450                                 snd_port->channel_count, 
    451                                 snd_port->samples_per_frame, 
    452                                 snd_port->bits_per_sample, 
    453                                 snd_rec_cb, 
    454                                 snd_play_cb, 
    455                                 snd_port, 
    456                                 &snd_port->setting, 
    457                                 &snd_port->snd_stream); 
    458 #else 
    459     status = pjmedia_snd_open(  snd_port->rec_id,  
    460                                 snd_port->play_id, 
    461                                 snd_port->clock_rate, 
    462                                 snd_port->channel_count, 
    463                                 snd_port->samples_per_frame, 
    464                                 snd_port->bits_per_sample, 
    465                                 snd_rec_cb, 
    466                                 snd_play_cb, 
    467                                 snd_port, 
    468                                 &snd_port->snd_stream); 
    469 #endif 
     239    /* Open the device */ 
     240    status = pjmedia_aud_stream_create(&param_copy, 
     241                                       snd_rec_cb, 
     242                                       snd_play_cb, 
     243                                       snd_port, 
     244                                       &snd_port->aud_stream); 
    470245 
    471246    if (status != PJ_SUCCESS) 
    472247        return status; 
    473  
    474  
    475 #ifdef SIMULATE_LOST_PCT 
    476     snd_port->setting.plc = PJ_TRUE; 
    477 #endif 
    478  
    479     /* If we have player components, allocate buffer to save the last 
    480      * frame played to the speaker. The last frame is used for packet 
    481      * lost concealment (PLC) algorithm. 
    482      */ 
    483     if ((snd_port->dir & PJMEDIA_DIR_PLAYBACK) && 
    484         (snd_port->setting.plc))  
    485     { 
    486         status = pjmedia_plc_create(pool, snd_port->clock_rate,  
    487                                     snd_port->samples_per_frame *  
    488                                         snd_port->channel_count, 
    489                                     0, &snd_port->plc); 
    490         if (status != PJ_SUCCESS) { 
    491             PJ_LOG(4,(THIS_FILE, "Unable to create PLC")); 
    492             snd_port->plc = NULL; 
    493         } 
    494     } 
    495248 
    496249    /* Inactivity limit before EC is suspended. */ 
     
    499252                                  snd_port->samples_per_frame); 
    500253 
     254    /* Create software EC if parameter specifies EC but device  
     255     * doesn't support EC 
     256     */ 
     257    if ((snd_port->aud_param.flags & PJMEDIA_AUD_DEV_CAP_EC) && 
     258        (snd_port->aud_caps & PJMEDIA_AUD_DEV_CAP_EC)==0) 
     259    { 
     260        if ((snd_port->aud_param.flags & PJMEDIA_AUD_DEV_CAP_EC_TAIL)==0) { 
     261            snd_port->aud_param.flags |= PJMEDIA_AUD_DEV_CAP_EC_TAIL; 
     262            snd_port->aud_param.ec_tail_ms = AEC_TAIL; 
     263            PJ_LOG(4,(THIS_FILE, "AEC tail is set to default %u ms", 
     264                                 snd_port->aud_param.ec_tail_ms)); 
     265        } 
     266             
     267        status = pjmedia_snd_port_set_ec(snd_port, pool,  
     268                                         snd_port->aud_param.ec_tail_ms, 0); 
     269        if (status != PJ_SUCCESS) { 
     270            pjmedia_aud_stream_destroy(snd_port->aud_stream); 
     271            snd_port->aud_stream = NULL; 
     272            return status; 
     273        } 
     274    } 
     275 
    501276    /* Start sound stream. */ 
    502     status = pjmedia_snd_stream_start(snd_port->snd_stream); 
     277    status = pjmedia_aud_stream_start(snd_port->aud_stream); 
    503278    if (status != PJ_SUCCESS) { 
    504         pjmedia_snd_stream_close(snd_port->snd_stream); 
    505         snd_port->snd_stream = NULL; 
     279        pjmedia_aud_stream_destroy(snd_port->aud_stream); 
     280        snd_port->aud_stream = NULL; 
    506281        return status; 
    507282    } 
     
    518293{ 
    519294    /* Check if we have sound stream device. */ 
    520     if (snd_port->snd_stream) { 
    521         pjmedia_snd_stream_stop(snd_port->snd_stream); 
    522         pjmedia_snd_stream_close(snd_port->snd_stream); 
    523         snd_port->snd_stream = NULL; 
     295    if (snd_port->aud_stream) { 
     296        pjmedia_aud_stream_stop(snd_port->aud_stream); 
     297        pjmedia_aud_stream_destroy(snd_port->aud_stream); 
     298        snd_port->aud_stream = NULL; 
    524299    } 
    525300 
     
    547322                                             pjmedia_snd_port **p_port) 
    548323{ 
    549     pjmedia_snd_port *snd_port; 
     324    pjmedia_aud_param param; 
     325    pj_status_t status; 
    550326 
    551327    PJ_UNUSED_ARG(options); 
    552328 
    553     PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL); 
    554  
    555     snd_port = PJ_POOL_ZALLOC_T(pool, pjmedia_snd_port); 
    556     PJ_ASSERT_RETURN(snd_port, PJ_ENOMEM); 
    557  
    558     snd_port->rec_id = rec_id; 
    559     snd_port->play_id = play_id; 
    560     snd_port->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK; 
    561     snd_port->clock_rate = clock_rate; 
    562     snd_port->channel_count = channel_count; 
    563     snd_port->samples_per_frame = samples_per_frame; 
    564     snd_port->bits_per_sample = bits_per_sample; 
    565      
    566 #if PJMEDIA_SOUND_USE_DELAYBUF 
    567     do { 
    568         pj_status_t status; 
    569         unsigned ptime; 
    570      
    571         ptime = samples_per_frame * 1000 / (clock_rate * channel_count); 
    572      
    573         status = pjmedia_delay_buf_create(pool, "snd_buff",  
    574                                           clock_rate, samples_per_frame, 
    575                                           channel_count, 
    576                                           PJMEDIA_SOUND_BUFFER_COUNT * ptime, 
    577                                           0, &snd_port->delay_buf); 
    578         PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); 
    579     } while (0); 
    580 #endif 
    581  
    582     *p_port = snd_port; 
    583  
    584  
    585     /* Start sound device immediately. 
    586      * If there's no port connected, the sound callback will return 
    587      * empty signal. 
    588      */ 
    589     return start_sound_device( pool, snd_port ); 
    590  
     329    status = pjmedia_aud_dev_default_param(rec_id, &param); 
     330    if (status != PJ_SUCCESS) 
     331        return status; 
     332 
     333    param.dir = PJMEDIA_DIR_CAPTURE_PLAYBACK; 
     334    param.rec_id = rec_id; 
     335    param.play_id = play_id; 
     336    param.clock_rate = clock_rate; 
     337    param.channel_count = channel_count; 
     338    param.samples_per_frame = samples_per_frame; 
     339    param.bits_per_sample = bits_per_sample; 
     340 
     341    return pjmedia_snd_port_create2(pool, &param, p_port); 
    591342} 
    592343 
     
    603354                                                 pjmedia_snd_port **p_port) 
    604355{ 
    605     pjmedia_snd_port *snd_port; 
     356    pjmedia_aud_param param; 
     357    pj_status_t status; 
    606358 
    607359    PJ_UNUSED_ARG(options); 
    608360 
    609     PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL); 
    610  
    611     snd_port = PJ_POOL_ZALLOC_T(pool, pjmedia_snd_port); 
    612     PJ_ASSERT_RETURN(snd_port, PJ_ENOMEM); 
    613  
    614     snd_port->rec_id = dev_id; 
    615     snd_port->dir = PJMEDIA_DIR_CAPTURE; 
    616     snd_port->clock_rate = clock_rate; 
    617     snd_port->channel_count = channel_count; 
    618     snd_port->samples_per_frame = samples_per_frame; 
    619     snd_port->bits_per_sample = bits_per_sample; 
    620  
    621     *p_port = snd_port; 
    622  
    623     /* Start sound device immediately. 
    624      * If there's no port connected, the sound callback will return 
    625      * empty signal. 
    626      */ 
    627     return start_sound_device( pool, snd_port ); 
     361    status = pjmedia_aud_dev_default_param(dev_id, &param); 
     362    if (status != PJ_SUCCESS) 
     363        return status; 
     364 
     365    param.dir = PJMEDIA_DIR_CAPTURE; 
     366    param.rec_id = dev_id; 
     367    param.clock_rate = clock_rate; 
     368    param.channel_count = channel_count; 
     369    param.samples_per_frame = samples_per_frame; 
     370    param.bits_per_sample = bits_per_sample; 
     371 
     372    return pjmedia_snd_port_create2(pool, &param, p_port); 
    628373} 
    629374 
     
    641386                                                    pjmedia_snd_port **p_port) 
    642387{ 
     388    pjmedia_aud_param param; 
     389    pj_status_t status; 
     390 
     391    PJ_UNUSED_ARG(options); 
     392 
     393    status = pjmedia_aud_dev_default_param(dev_id, &param); 
     394    if (status != PJ_SUCCESS) 
     395        return status; 
     396 
     397    param.dir = PJMEDIA_DIR_PLAYBACK; 
     398    param.play_id = dev_id; 
     399    param.clock_rate = clock_rate; 
     400    param.channel_count = channel_count; 
     401    param.samples_per_frame = samples_per_frame; 
     402    param.bits_per_sample = bits_per_sample; 
     403 
     404    return pjmedia_snd_port_create2(pool, &param, p_port); 
     405} 
     406 
     407 
     408/* 
     409 * Create sound port. 
     410 */ 
     411PJ_DEF(pj_status_t) pjmedia_snd_port_create2(pj_pool_t *pool, 
     412                                             const pjmedia_aud_param *prm, 
     413                                             pjmedia_snd_port **p_port) 
     414{ 
    643415    pjmedia_snd_port *snd_port; 
    644416 
    645     PJ_UNUSED_ARG(options); 
    646  
    647     PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL); 
     417    PJ_ASSERT_RETURN(pool && prm && p_port, PJ_EINVAL); 
    648418 
    649419    snd_port = PJ_POOL_ZALLOC_T(pool, pjmedia_snd_port); 
    650420    PJ_ASSERT_RETURN(snd_port, PJ_ENOMEM); 
    651421 
    652     snd_port->play_id = dev_id; 
    653     snd_port->dir = PJMEDIA_DIR_PLAYBACK; 
    654     snd_port->clock_rate = clock_rate; 
    655     snd_port->channel_count = channel_count; 
    656     snd_port->samples_per_frame = samples_per_frame; 
    657     snd_port->bits_per_sample = bits_per_sample; 
    658  
     422    snd_port->dir = prm->dir; 
     423    snd_port->rec_id = prm->rec_id; 
     424    snd_port->play_id = prm->play_id; 
     425    snd_port->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK; 
     426    snd_port->clock_rate = prm->clock_rate; 
     427    snd_port->channel_count = prm->channel_count; 
     428    snd_port->samples_per_frame = prm->samples_per_frame; 
     429    snd_port->bits_per_sample = prm->bits_per_sample; 
     430    pj_memcpy(&snd_port->aud_param, prm, sizeof(*prm)); 
     431     
    659432    *p_port = snd_port; 
     433 
    660434 
    661435    /* Start sound device immediately. 
     
    664438     */ 
    665439    return start_sound_device( pool, snd_port ); 
    666 } 
    667  
    668  
    669 /* 
    670  * Create bidirectional port. 
    671  */ 
    672 PJ_DEF(pj_status_t) pjmedia_snd_port_create2(pj_pool_t *pool, 
    673                                              pjmedia_dir dir, 
    674                                              int rec_id, 
    675                                              int play_id, 
    676                                              unsigned clock_rate, 
    677                                              unsigned channel_count, 
    678                                              unsigned samples_per_frame, 
    679                                              unsigned bits_per_sample, 
    680                                              const pjmedia_snd_setting *setting, 
    681                                              pjmedia_snd_port **p_port) 
    682 { 
    683     pjmedia_snd_port *snd_port; 
    684  
    685     PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL); 
    686  
    687     snd_port = PJ_POOL_ZALLOC_T(pool, pjmedia_snd_port); 
    688     PJ_ASSERT_RETURN(snd_port, PJ_ENOMEM); 
    689  
    690     snd_port->dir = dir; 
    691     snd_port->rec_id = rec_id; 
    692     snd_port->play_id = play_id; 
    693     snd_port->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK; 
    694     snd_port->clock_rate = clock_rate; 
    695     snd_port->channel_count = channel_count; 
    696     snd_port->samples_per_frame = samples_per_frame; 
    697     snd_port->bits_per_sample = bits_per_sample; 
    698     pj_memcpy(&snd_port->setting, setting, sizeof(*setting)); 
    699      
    700 #if PJMEDIA_SOUND_USE_DELAYBUF 
    701     if (snd_port->setting.format.u32 == PJMEDIA_FORMAT_L16) { 
    702         pj_status_t status; 
    703         unsigned ptime; 
    704      
    705         ptime = samples_per_frame * 1000 / (clock_rate * channel_count); 
    706      
    707         status = pjmedia_delay_buf_create(pool, "snd_buff",  
    708                                           clock_rate, samples_per_frame, 
    709                                           channel_count, 
    710                                           PJMEDIA_SOUND_BUFFER_COUNT * ptime, 
    711                                           0, &snd_port->delay_buf); 
    712         PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); 
    713     } 
    714 #endif 
    715  
    716 #if !defined(PJMEDIA_SND_SUPPORT_OPEN2) || PJMEDIA_SND_SUPPORT_OPEN2==0 
    717     /* For devices that doesn't support open2(), enable simulation */ 
    718     if (snd_port->setting.format.id != PJMEDIA_FORMAT_L16) { 
    719         snd_port->frm_buf_size = sizeof(pjmedia_frame_ext) +  
    720                                  (samples_per_frame << 1) + 
    721                                  16 * sizeof(pjmedia_frame_ext_subframe); 
    722         snd_port->put_frm_buf = (pj_uint8_t*) 
    723                                 pj_pool_alloc(pool, snd_port->frm_buf_size); 
    724         snd_port->get_frm_buf = (pj_uint8_t*) 
    725                                 pj_pool_alloc(pool, snd_port->frm_buf_size); 
    726     } 
    727 #endif 
    728  
    729     *p_port = snd_port; 
    730  
    731  
    732     /* Start sound device immediately. 
    733      * If there's no port connected, the sound callback will return 
    734      * empty signal. 
    735      */ 
    736     return start_sound_device( pool, snd_port ); 
    737440 
    738441} 
     
    753456 * Retrieve the sound stream associated by this sound device port. 
    754457 */ 
    755 PJ_DEF(pjmedia_snd_stream*) pjmedia_snd_port_get_snd_stream( 
     458PJ_DEF(pjmedia_aud_stream*) pjmedia_snd_port_get_snd_stream( 
    756459                                                pjmedia_snd_port *snd_port) 
    757460{ 
    758461    PJ_ASSERT_RETURN(snd_port, NULL); 
    759     return snd_port->snd_stream; 
    760 } 
    761  
    762  
    763 /* 
    764  * Enable AEC 
     462    return snd_port->aud_stream; 
     463} 
     464 
     465 
     466/* 
     467 * Change EC settings. 
    765468 */ 
    766469PJ_DEF(pj_status_t) pjmedia_snd_port_set_ec( pjmedia_snd_port *snd_port, 
     
    769472                                             unsigned options) 
    770473{ 
    771     pjmedia_snd_stream_info si; 
     474    pjmedia_aud_param prm; 
    772475    pj_status_t status; 
    773476 
     
    777480                     PJ_EINVALIDOP); 
    778481 
    779     /* Sound port must have 16bits per sample */ 
    780     PJ_ASSERT_RETURN(snd_port->bits_per_sample == 16, 
    781                      PJ_EINVALIDOP); 
    782  
    783     /* Destroy AEC */ 
    784     if (snd_port->ec_state) { 
    785         pjmedia_echo_destroy(snd_port->ec_state); 
    786         snd_port->ec_state = NULL; 
    787     } 
    788  
    789     snd_port->aec_tail_len = tail_ms; 
    790  
    791     if (tail_ms != 0) { 
    792         unsigned delay_ms; 
    793  
    794         status = pjmedia_snd_stream_get_info(snd_port->snd_stream, &si); 
     482    /* Determine whether we use device or software EC */ 
     483    if (snd_port->aud_caps & PJMEDIA_AUD_DEV_CAP_EC) { 
     484        /* We use device EC */ 
     485        pj_bool_t ec_enabled; 
     486 
     487        /* Query EC status */ 
     488        status = pjmedia_aud_stream_get_cap(snd_port->aud_stream, 
     489                                            PJMEDIA_AUD_DEV_CAP_EC, 
     490                                            &ec_enabled); 
    795491        if (status != PJ_SUCCESS) 
    796             si.rec_latency = si.play_latency = 0; 
    797  
    798         //No need to add input latency in the latency calculation, 
    799         //since actual input latency should be zero. 
    800         //delay_ms = (si.rec_latency + si.play_latency) * 1000 / 
    801         //         snd_port->clock_rate; 
    802         delay_ms = si.play_latency * 1000 / snd_port->clock_rate; 
    803         status = pjmedia_echo_create2(pool, snd_port->clock_rate,  
    804                                       snd_port->channel_count, 
    805                                       snd_port->samples_per_frame,  
    806                                       tail_ms, delay_ms, 
    807                                       options, &snd_port->ec_state); 
    808         if (status != PJ_SUCCESS) 
     492            return status; 
     493 
     494        if (tail_ms != 0) { 
     495            /* Change EC setting */ 
     496 
     497            if (!ec_enabled) { 
     498                /* Enable EC first */ 
     499                pj_bool_t value = PJ_TRUE; 
     500                status = pjmedia_aud_stream_set_cap(snd_port->aud_stream,  
     501                                                    PJMEDIA_AUD_DEV_CAP_EC, 
     502                                                    &value); 
     503                if (status != PJ_SUCCESS) 
     504                    return status; 
     505            } 
     506 
     507            if ((snd_port->aud_caps & PJMEDIA_AUD_DEV_CAP_EC_TAIL)==0) { 
     508                /* Device does not support setting EC tail */ 
     509                return PJMEDIA_EAUD_INVCAP; 
     510            } 
     511 
     512            return pjmedia_aud_stream_set_cap(snd_port->aud_stream, 
     513                                              PJMEDIA_AUD_DEV_CAP_EC_TAIL, 
     514                                              &tail_ms); 
     515 
     516        } else if (ec_enabled) { 
     517            /* Disable EC */ 
     518            pj_bool_t value = PJ_FALSE; 
     519            return pjmedia_aud_stream_set_cap(snd_port->aud_stream,  
     520                                              PJMEDIA_AUD_DEV_CAP_EC, 
     521                                              &value); 
     522        } else { 
     523            /* Request to disable EC but EC has been disabled */ 
     524            /* Do nothing */ 
     525            return PJ_SUCCESS; 
     526        } 
     527 
     528    } else { 
     529        /* We use software EC */ 
     530        /* Sound port must have 16bits per sample */ 
     531        PJ_ASSERT_RETURN(snd_port->bits_per_sample == 16, 
     532                         PJ_EINVALIDOP); 
     533 
     534        /* Check if there is change in parameters */ 
     535        if (tail_ms==snd_port->ec_tail_len && options==snd_port->ec_options) { 
     536            PJ_LOG(5,(THIS_FILE, "pjmedia_snd_port_set_ec() ignored, no " 
     537                                 "change in settings")); 
     538            return PJ_SUCCESS; 
     539        } 
     540 
     541        /* Destroy AEC */ 
     542        if (snd_port->ec_state) { 
     543            pjmedia_echo_destroy(snd_port->ec_state); 
    809544            snd_port->ec_state = NULL; 
    810         else 
    811             snd_port->ec_suspended = PJ_FALSE; 
    812     } else { 
    813         PJ_LOG(4,(THIS_FILE, "Echo canceller is now disabled in the " 
    814                              "sound port")); 
    815         status = PJ_SUCCESS; 
     545        } 
     546 
     547        snd_port->ec_options = options; 
     548        snd_port->ec_tail_len = tail_ms; 
     549 
     550        if (tail_ms != 0) { 
     551            unsigned delay_ms; 
     552 
     553            status = pjmedia_aud_stream_get_param(snd_port->aud_stream, &prm); 
     554            if (status != PJ_SUCCESS) 
     555                prm.input_latency_ms = prm.output_latency_ms = 0; 
     556 
     557            //No need to add input latency in the latency calculation, 
     558            //since actual input latency should be zero. 
     559            //delay_ms = (si.rec_latency + si.play_latency) * 1000 / 
     560            //     snd_port->clock_rate; 
     561            delay_ms = prm.output_latency_ms; 
     562            status = pjmedia_echo_create2(pool, snd_port->clock_rate,  
     563                                          snd_port->channel_count, 
     564                                          snd_port->samples_per_frame,  
     565                                          tail_ms, delay_ms, 
     566                                          options, &snd_port->ec_state); 
     567            if (status != PJ_SUCCESS) 
     568                snd_port->ec_state = NULL; 
     569            else 
     570                snd_port->ec_suspended = PJ_FALSE; 
     571        } else { 
     572            PJ_LOG(4,(THIS_FILE, "Echo canceller is now disabled in the " 
     573                                 "sound port")); 
     574            status = PJ_SUCCESS; 
     575        } 
    816576    } 
    817577 
     
    825585{ 
    826586    PJ_ASSERT_RETURN(snd_port && p_length, PJ_EINVAL); 
    827     *p_length =  snd_port->ec_state ? snd_port->aec_tail_len : 0; 
    828     return PJ_SUCCESS; 
    829 } 
    830  
     587 
     588    /* Determine whether we use device or software EC */ 
     589    if (snd_port->aud_caps & PJMEDIA_AUD_DEV_CAP_EC) { 
     590        /* We use device EC */ 
     591        pj_bool_t ec_enabled; 
     592        pj_status_t status; 
     593 
     594        /* Query EC status */ 
     595        status = pjmedia_aud_stream_get_cap(snd_port->aud_stream, 
     596                                            PJMEDIA_AUD_DEV_CAP_EC, 
     597                                            &ec_enabled); 
     598        if (status != PJ_SUCCESS) 
     599            return status; 
     600 
     601        if (!ec_enabled) { 
     602            *p_length = 0; 
     603        } else if (snd_port->aud_caps & PJMEDIA_AUD_DEV_CAP_EC_TAIL) { 
     604            /* Get device EC tail */ 
     605            status = pjmedia_aud_stream_get_cap(snd_port->aud_stream, 
     606                                                PJMEDIA_AUD_DEV_CAP_EC_TAIL, 
     607                                                p_length); 
     608            if (status != PJ_SUCCESS) 
     609                return status; 
     610        } else { 
     611            /* Just use default */ 
     612            *p_length = AEC_TAIL; 
     613        } 
     614 
     615    } else { 
     616        /* We use software EC */ 
     617        *p_length =  snd_port->ec_state ? snd_port->ec_tail_len : 0; 
     618    } 
     619    return PJ_SUCCESS; 
     620} 
    831621 
    832622 
  • pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia/transport_ice.c

    r2394 r2468  
    2222#include <pj/assert.h> 
    2323#include <pj/log.h> 
     24#include <pj/pool.h> 
    2425#include <pj/rand.h> 
    2526 
  • pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia/transport_loop.c

    r2394 r2468  
    2323#include <pj/ioqueue.h> 
    2424#include <pj/log.h> 
     25#include <pj/pool.h> 
    2526#include <pj/rand.h> 
    2627#include <pj/string.h> 
  • pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia/transport_udp.c

    r2394 r2468  
    2424#include <pj/ioqueue.h> 
    2525#include <pj/log.h> 
     26#include <pj/pool.h> 
    2627#include <pj/rand.h> 
    2728#include <pj/string.h> 
  • pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia/wmme_sound.c

    r2366 r2468  
    1 #include <pjmedia/sound.h> 
    2 #include <pjmedia/errno.h> 
    3 #include <pj/assert.h> 
    4 #include <pj/log.h> 
    5 #include <pj/os.h> 
    6 #include <pj/string.h> 
    7  
    8 #if PJMEDIA_SOUND_IMPLEMENTATION == PJMEDIA_SOUND_WIN32_MME_SOUND 
    9  
    10 #ifdef _MSC_VER 
    11 #   pragma warning(push, 3) 
    12 #endif 
    13  
    14 #include <windows.h> 
    15 #include <mmsystem.h> 
    16  
    17 #ifdef _MSC_VER 
    18 #   pragma warning(pop) 
    19 #endif 
    20  
    21 #if defined(PJ_WIN32_WINCE) && PJ_WIN32_WINCE!=0 
    22 #   pragma comment(lib, "Coredll.lib") 
    23 #elif defined(_MSC_VER) 
    24 #   pragma comment(lib, "winmm.lib") 
    25 #endif 
    26  
    27  
    28 #define THIS_FILE                       "wmme_sound.c" 
    29 #define BITS_PER_SAMPLE                 16 
    30 #define BYTES_PER_SAMPLE                (BITS_PER_SAMPLE/8) 
    31  
    32 #define MAX_PACKET_BUFFER_COUNT         32 
    33 #define MAX_HARDWARE                    16 
    34  
    35 struct wmme_dev_info 
    36 { 
    37     pjmedia_snd_dev_info info; 
    38     unsigned             deviceId; 
    39 }; 
    40  
    41 static unsigned dev_count; 
    42 static struct wmme_dev_info dev_info[MAX_HARDWARE]; 
    43 static pj_bool_t snd_initialized = PJ_FALSE; 
    44  
    45 /* Latency settings */ 
    46 static unsigned snd_input_latency  = PJMEDIA_SND_DEFAULT_REC_LATENCY; 
    47 static unsigned snd_output_latency = PJMEDIA_SND_DEFAULT_PLAY_LATENCY; 
    48  
    49  
    50 /* Individual WMME capture/playback stream descriptor */ 
    51 struct wmme_stream 
    52 { 
    53     union 
    54     { 
    55         HWAVEIN   In; 
    56         HWAVEOUT  Out; 
    57     } hWave; 
    58  
    59     WAVEHDR      *WaveHdr; 
    60     HANDLE        hEvent; 
    61     DWORD         dwBufIdx; 
    62     DWORD         dwMaxBufIdx; 
    63     pj_timestamp  timestamp; 
    64 }; 
    65  
    66  
    67 /* Sound stream. */ 
    68 struct pjmedia_snd_stream 
    69 { 
    70     pjmedia_dir          dir;               /**< Sound direction.      */ 
    71     int                  play_id;           /**< Playback dev id.      */ 
    72     int                  rec_id;            /**< Recording dev id.     */ 
    73     pj_pool_t           *pool;              /**< Memory pool.          */ 
    74  
    75     pjmedia_snd_rec_cb   rec_cb;            /**< Capture callback.     */ 
    76     pjmedia_snd_play_cb  play_cb;           /**< Playback callback.    */ 
    77     void                *user_data;         /**< Application data.     */ 
    78  
    79     struct wmme_stream   play_strm;         /**< Playback stream.      */ 
    80     struct wmme_stream   rec_strm;          /**< Capture stream.       */ 
    81  
    82     void                *buffer;            /**< Temp. frame buffer.   */ 
    83     unsigned             clock_rate;        /**< Clock rate.           */ 
    84     unsigned             samples_per_frame; /**< Samples per frame.    */ 
    85     unsigned             bits_per_sample;   /**< Bits per sample.      */ 
    86     unsigned             channel_count;     /**< Channel count.        */ 
    87  
    88     pj_thread_t         *thread;            /**< Thread handle.        */ 
    89     HANDLE               thread_quit_event; /**< Quit signal to thread */ 
    90 }; 
    91  
    92  
    93 static pj_pool_factory *pool_factory; 
    94  
    95 static void init_waveformatex (LPWAVEFORMATEX pcmwf,  
    96                                unsigned clock_rate, 
    97                                unsigned channel_count) 
    98 { 
    99     pj_bzero(pcmwf, sizeof(PCMWAVEFORMAT));  
    100     pcmwf->wFormatTag = WAVE_FORMAT_PCM;  
    101     pcmwf->nChannels = (pj_uint16_t)channel_count; 
    102     pcmwf->nSamplesPerSec = clock_rate; 
    103     pcmwf->nBlockAlign = (pj_uint16_t)(channel_count * BYTES_PER_SAMPLE); 
    104     pcmwf->nAvgBytesPerSec = clock_rate * channel_count * BYTES_PER_SAMPLE; 
    105     pcmwf->wBitsPerSample = BITS_PER_SAMPLE; 
    106 } 
    107  
    108  
    109 /* 
    110  * Initialize WMME player device. 
    111  */ 
    112 static pj_status_t init_player_stream(  pj_pool_t *pool, 
    113                                         struct wmme_stream *wmme_strm, 
    114                                         int dev_id, 
    115                                         unsigned clock_rate, 
    116                                         unsigned channel_count, 
    117                                         unsigned samples_per_frame, 
    118                                         unsigned buffer_count) 
    119 { 
    120     MMRESULT mr; 
    121     WAVEFORMATEX pcmwf;  
    122     unsigned bytes_per_frame; 
    123     unsigned i; 
    124  
    125     PJ_ASSERT_RETURN(buffer_count <= MAX_PACKET_BUFFER_COUNT, PJ_EINVAL); 
    126  
    127     /* Check device ID */ 
    128     if (dev_id == -1) 
    129         dev_id = 0; 
    130  
    131     PJ_ASSERT_RETURN(dev_id >= 0 && dev_id < (int)dev_count, PJ_EINVAL); 
    132  
    133     /* 
    134      * Create a wait event. 
    135      */ 
    136     wmme_strm->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 
    137     if (NULL == wmme_strm->hEvent) 
    138         return pj_get_os_error(); 
    139  
    140     /* 
    141      * Set up wave format structure for opening the device. 
    142      */ 
    143     init_waveformatex(&pcmwf, clock_rate, channel_count); 
    144     bytes_per_frame = samples_per_frame * BYTES_PER_SAMPLE; 
    145  
    146     /* 
    147      * Open wave device. 
    148      */ 
    149     mr = waveOutOpen(&wmme_strm->hWave.Out, dev_info[dev_id].deviceId, &pcmwf,  
    150                      (DWORD)wmme_strm->hEvent, 0, CALLBACK_EVENT); 
    151     if (mr != MMSYSERR_NOERROR) 
    152         /* TODO: This is for HRESULT/GetLastError() */ 
    153         PJ_RETURN_OS_ERROR(mr); 
    154  
    155     /* Pause the wave out device */ 
    156     mr = waveOutPause(wmme_strm->hWave.Out); 
    157     if (mr != MMSYSERR_NOERROR) 
    158         /* TODO: This is for HRESULT/GetLastError() */ 
    159         PJ_RETURN_OS_ERROR(mr); 
    160  
    161     /* 
    162      * Create the buffers.  
    163      */ 
    164     wmme_strm->WaveHdr = pj_pool_zalloc(pool, sizeof(WAVEHDR) * buffer_count); 
    165     for (i = 0; i < buffer_count; ++i) 
    166     { 
    167         wmme_strm->WaveHdr[i].lpData = pj_pool_zalloc(pool, bytes_per_frame); 
    168         wmme_strm->WaveHdr[i].dwBufferLength = bytes_per_frame; 
    169         mr = waveOutPrepareHeader(wmme_strm->hWave.Out,  
    170                                   &(wmme_strm->WaveHdr[i]), 
    171                                   sizeof(WAVEHDR)); 
    172         if (mr != MMSYSERR_NOERROR) 
    173             /* TODO: This is for HRESULT/GetLastError() */ 
    174             PJ_RETURN_OS_ERROR(mr);  
    175         mr = waveOutWrite(wmme_strm->hWave.Out, &(wmme_strm->WaveHdr[i]),  
    176                           sizeof(WAVEHDR)); 
    177         if (mr != MMSYSERR_NOERROR) 
    178             /* TODO: This is for HRESULT/GetLastError() */ 
    179             PJ_RETURN_OS_ERROR(mr); 
    180     } 
    181  
    182     wmme_strm->dwBufIdx = 0; 
    183     wmme_strm->dwMaxBufIdx = buffer_count; 
    184     wmme_strm->timestamp.u64 = 0; 
    185  
    186     /* Done setting up play device. */ 
    187     PJ_LOG(5, (THIS_FILE,  
    188                " WaveAPI Sound player \"%s\" initialized (clock_rate=%d, " 
    189                "channel_count=%d, samples_per_frame=%d (%dms))", 
    190                dev_info[dev_id].info.name, 
    191                clock_rate, channel_count, samples_per_frame, 
    192                samples_per_frame * 1000 / clock_rate)); 
    193  
    194     return PJ_SUCCESS; 
    195 } 
    196  
    197  
    198 /* 
    199  * Initialize Windows Multimedia recorder device 
    200  */ 
    201 static pj_status_t init_capture_stream( pj_pool_t *pool, 
    202                                         struct wmme_stream *wmme_strm, 
    203                                         int dev_id, 
    204                                         unsigned clock_rate, 
    205                                         unsigned channel_count, 
    206                                         unsigned samples_per_frame, 
    207                                         unsigned buffer_count) 
    208 { 
    209     MMRESULT mr; 
    210     WAVEFORMATEX pcmwf;  
    211     unsigned bytes_per_frame; 
    212     unsigned i; 
    213  
    214     PJ_ASSERT_RETURN(buffer_count <= MAX_PACKET_BUFFER_COUNT, PJ_EINVAL); 
    215  
    216     /* Check device ID */ 
    217     if (dev_id == -1) 
    218         dev_id = 0; 
    219  
    220     PJ_ASSERT_RETURN(dev_id >= 0 && dev_id < (int)dev_count, PJ_EINVAL); 
    221  
    222     /* 
    223     * Create a wait event. 
    224     */ 
    225     wmme_strm->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 
    226     if (NULL == wmme_strm->hEvent) 
    227         return pj_get_os_error(); 
    228  
    229     /* 
    230      * Set up wave format structure for opening the device. 
    231      */ 
    232     init_waveformatex(&pcmwf, clock_rate, channel_count); 
    233     bytes_per_frame = samples_per_frame * BYTES_PER_SAMPLE; 
    234  
    235     /* 
    236      * Open wave device. 
    237      */ 
    238     mr = waveInOpen(&wmme_strm->hWave.In, dev_info[dev_id].deviceId, &pcmwf,  
    239                     (DWORD)wmme_strm->hEvent, 0, CALLBACK_EVENT); 
    240     if (mr != MMSYSERR_NOERROR) 
    241         /* TODO: This is for HRESULT/GetLastError() */ 
    242         PJ_RETURN_OS_ERROR(mr); 
    243  
    244     /* 
    245      * Create the buffers.  
    246      */ 
    247     wmme_strm->WaveHdr = pj_pool_zalloc(pool, sizeof(WAVEHDR) * buffer_count); 
    248     for (i = 0; i < buffer_count; ++i) 
    249     { 
    250         wmme_strm->WaveHdr[i].lpData = pj_pool_zalloc(pool, bytes_per_frame); 
    251         wmme_strm->WaveHdr[i].dwBufferLength = bytes_per_frame; 
    252         mr = waveInPrepareHeader(wmme_strm->hWave.In, &(wmme_strm->WaveHdr[i]), 
    253                                                         sizeof(WAVEHDR)); 
    254         if (mr != MMSYSERR_NOERROR) 
    255             /* TODO: This is for HRESULT/GetLastError() */ 
    256             PJ_RETURN_OS_ERROR(mr); 
    257         mr = waveInAddBuffer(wmme_strm->hWave.In, &(wmme_strm->WaveHdr[i]),  
    258                              sizeof(WAVEHDR)); 
    259         if (mr != MMSYSERR_NOERROR) 
    260             /* TODO: This is for HRESULT/GetLastError() */ 
    261             PJ_RETURN_OS_ERROR(mr); 
    262     } 
    263  
    264     wmme_strm->dwBufIdx = 0; 
    265     wmme_strm->dwMaxBufIdx = buffer_count; 
    266     wmme_strm->timestamp.u64 = 0; 
    267  
    268     /* Done setting up play device. */ 
    269     PJ_LOG(5,(THIS_FILE,  
    270         " WaveAPI Sound recorder \"%s\" initialized (clock_rate=%d, " 
    271         "channel_count=%d, samples_per_frame=%d (%dms))", 
    272         dev_info[dev_id].info.name, 
    273         clock_rate, channel_count, samples_per_frame, 
    274         samples_per_frame * 1000 / clock_rate)); 
    275  
    276     return PJ_SUCCESS; 
    277 } 
    278  
    279  
    280  
    281 /* 
    282 * WMME capture and playback thread. 
    283 */ 
    284 static int PJ_THREAD_FUNC wmme_dev_thread(void *arg) 
    285 { 
    286     pjmedia_snd_stream *strm = arg; 
    287     HANDLE events[3]; 
    288     unsigned eventCount; 
    289     unsigned bytes_per_frame; 
    290     pj_status_t status = PJ_SUCCESS; 
    291  
    292  
    293     eventCount = 0; 
    294     events[eventCount++] = strm->thread_quit_event; 
    295     if (strm->dir & PJMEDIA_DIR_PLAYBACK) 
    296         events[eventCount++] = strm->play_strm.hEvent; 
    297     if (strm->dir & PJMEDIA_DIR_CAPTURE) 
    298         events[eventCount++] = strm->rec_strm.hEvent; 
    299  
    300  
    301     /* Raise self priority. We don't want the audio to be distorted by 
    302      * system activity. 
    303      */ 
    304 #if defined(PJ_WIN32_WINCE) && PJ_WIN32_WINCE != 0 
    305     if (strm->dir & PJMEDIA_DIR_PLAYBACK) 
    306         CeSetThreadPriority(GetCurrentThread(), 153); 
    307     else 
    308         CeSetThreadPriority(GetCurrentThread(), 247); 
    309 #else 
    310     SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); 
    311 #endif 
    312  
    313     /* Calculate bytes per frame */ 
    314     bytes_per_frame = strm->samples_per_frame * BYTES_PER_SAMPLE; 
    315  
    316     /* 
    317      * Loop while not signalled to quit, wait for event objects to be  
    318      * signalled by WMME capture and play buffer. 
    319      */ 
    320     while (status == PJ_SUCCESS) 
    321     { 
    322  
    323         DWORD rc; 
    324         pjmedia_dir signalled_dir; 
    325  
    326         rc = WaitForMultipleObjects(eventCount, events, FALSE, INFINITE); 
    327         if (rc < WAIT_OBJECT_0 || rc >= WAIT_OBJECT_0 + eventCount) 
    328             continue; 
    329  
    330         if (rc == WAIT_OBJECT_0) 
    331             break; 
    332  
    333         if (rc == (WAIT_OBJECT_0 + 1)) 
    334         { 
    335             if (events[1] == strm->play_strm.hEvent) 
    336                 signalled_dir = PJMEDIA_DIR_PLAYBACK; 
    337             else 
    338                 signalled_dir = PJMEDIA_DIR_CAPTURE; 
    339         } 
    340         else 
    341         { 
    342             if (events[2] == strm->play_strm.hEvent) 
    343                 signalled_dir = PJMEDIA_DIR_PLAYBACK; 
    344             else 
    345                 signalled_dir = PJMEDIA_DIR_CAPTURE; 
    346         } 
    347  
    348  
    349         if (signalled_dir == PJMEDIA_DIR_PLAYBACK) 
    350         { 
    351             struct wmme_stream *wmme_strm = &strm->play_strm; 
    352             MMRESULT mr = MMSYSERR_NOERROR; 
    353             status = PJ_SUCCESS; 
    354  
    355             /* 
    356             * Windows Multimedia has requested us to feed some frames to 
    357             * playback buffer. 
    358             */ 
    359  
    360             while (wmme_strm->WaveHdr[wmme_strm->dwBufIdx].dwFlags & WHDR_DONE) 
    361             { 
    362                 void* buffer = wmme_strm->WaveHdr[wmme_strm->dwBufIdx].lpData; 
    363  
    364                 PJ_LOG(5,(THIS_FILE, "Finished writing buffer %d",  
    365                           wmme_strm->dwBufIdx)); 
    366  
    367                 /* Get frame from application. */ 
    368                 status = (*strm->play_cb)(strm->user_data,  
    369                                           wmme_strm->timestamp.u32.lo, 
    370                                           buffer, 
    371                                           bytes_per_frame); 
    372  
    373                 if (status != PJ_SUCCESS) 
    374                     break; 
    375  
    376                 /* Write to the device. */ 
    377                 mr = waveOutWrite(wmme_strm->hWave.Out,  
    378                                   &(wmme_strm->WaveHdr[wmme_strm->dwBufIdx]),  
    379                                   sizeof(WAVEHDR)); 
    380                 if (mr != MMSYSERR_NOERROR) 
    381                 { 
    382                     status = PJ_STATUS_FROM_OS(mr); 
    383                     break; 
    384                 } 
    385  
    386                 /* Increment position. */ 
    387                 if (++wmme_strm->dwBufIdx >= wmme_strm->dwMaxBufIdx) 
    388                     wmme_strm->dwBufIdx = 0; 
    389                 wmme_strm->timestamp.u64 += strm->samples_per_frame /  
    390                                             strm->channel_count; 
    391             } 
    392         } 
    393         else 
    394         { 
    395             struct wmme_stream *wmme_strm = &strm->rec_strm; 
    396             MMRESULT mr = MMSYSERR_NOERROR; 
    397             status = PJ_SUCCESS; 
    398  
    399             /* 
    400             * Windows Multimedia has indicated that it has some frames ready 
    401             * in the capture buffer. Get as much frames as possible to 
    402             * prevent overflows. 
    403             */ 
    404 #if 0 
    405             { 
    406                 static DWORD tc = 0; 
    407                 DWORD now = GetTickCount(); 
    408                 DWORD i = 0; 
    409                 DWORD bits = 0; 
    410  
    411                 if (tc == 0) tc = now; 
    412  
    413                 for (i = 0; i < wmme_strm->dwMaxBufIdx; ++i) 
    414                 { 
    415                     bits = bits << 4; 
    416                     bits |= wmme_strm->WaveHdr[i].dwFlags & WHDR_DONE; 
    417                 } 
    418                 PJ_LOG(5,(THIS_FILE, "Record Signal> Index: %d, Delta: %4.4d, " 
    419                           "Flags: %6.6x\n", 
    420                           wmme_strm->dwBufIdx, 
    421                           now - tc, 
    422                           bits)); 
    423                 tc = now; 
    424             } 
    425 #endif 
    426  
    427             while (wmme_strm->WaveHdr[wmme_strm->dwBufIdx].dwFlags & WHDR_DONE) 
    428             { 
    429                 char* buffer = (char*) 
    430                                wmme_strm->WaveHdr[wmme_strm->dwBufIdx].lpData; 
    431                 unsigned cap_len =  
    432                         wmme_strm->WaveHdr[wmme_strm->dwBufIdx].dwBytesRecorded; 
    433  
    434                 /* 
    435                 PJ_LOG(5,(THIS_FILE, "Read %d bytes from buffer %d", cap_len,  
    436                           wmme_strm->dwBufIdx)); 
    437                 */ 
    438  
    439                 if (cap_len < bytes_per_frame) 
    440                     pj_bzero(buffer + cap_len, bytes_per_frame - cap_len); 
    441  
    442                 /* Copy the audio data out of the wave buffer. */ 
    443                 pj_memcpy(strm->buffer, buffer, bytes_per_frame); 
    444  
    445                 /* Re-add the buffer to the device. */ 
    446                 mr = waveInAddBuffer(wmme_strm->hWave.In,  
    447                                      &(wmme_strm->WaveHdr[wmme_strm->dwBufIdx]),  
    448                                      sizeof(WAVEHDR)); 
    449                 if (mr != MMSYSERR_NOERROR) { 
    450                     status = PJ_STATUS_FROM_OS(mr); 
    451                     break; 
    452                 } 
    453  
    454                 /* Call callback */ 
    455                 status = (*strm->rec_cb)(strm->user_data,  
    456                                          wmme_strm->timestamp.u32.lo,  
    457                                          strm->buffer,  
    458                                          bytes_per_frame); 
    459  
    460                 if (status != PJ_SUCCESS) 
    461                     break; 
    462  
    463                 /* Increment position. */ 
    464                 if (++wmme_strm->dwBufIdx >= wmme_strm->dwMaxBufIdx) 
    465                     wmme_strm->dwBufIdx = 0; 
    466                 wmme_strm->timestamp.u64 += strm->samples_per_frame /  
    467                                             strm->channel_count; 
    468             } 
    469         } 
    470     } 
    471  
    472     PJ_LOG(5,(THIS_FILE, "WMME: thread stopping..")); 
    473     return 0; 
    474 } 
    475  
    476  
    477 /* 
    478 * Init sound library. 
    479 */ 
    480 PJ_DEF(pj_status_t) pjmedia_snd_init(pj_pool_factory *factory) 
    481 { 
    482     unsigned c; 
    483     int i; 
    484     int inputDeviceCount, outputDeviceCount, maximumPossibleDeviceCount; 
    485  
    486     if (snd_initialized) 
    487         return PJ_SUCCESS; 
    488  
    489     pj_bzero(&dev_info, sizeof(dev_info)); 
    490  
    491     dev_count = 0; 
    492     pool_factory = factory; 
    493  
    494     /* Enumerate sound playback devices */ 
    495     maximumPossibleDeviceCount = 0; 
    496  
    497     inputDeviceCount = waveInGetNumDevs(); 
    498     if (inputDeviceCount > 0) 
    499         /* assume there is a WAVE_MAPPER */ 
    500         maximumPossibleDeviceCount += inputDeviceCount + 1; 
    501  
    502     outputDeviceCount = waveOutGetNumDevs(); 
    503     if (outputDeviceCount > 0) 
    504         /* assume there is a WAVE_MAPPER */ 
    505         maximumPossibleDeviceCount += outputDeviceCount + 1; 
    506  
    507     if (maximumPossibleDeviceCount >= MAX_HARDWARE) 
    508     { 
    509         pj_assert(!"Too many hardware found"); 
    510         PJ_LOG(3,(THIS_FILE, "Too many hardware found, " 
    511                   "some devices will not be listed")); 
    512     } 
    513  
    514     if (inputDeviceCount > 0) 
    515     { 
    516         /* -1 is the WAVE_MAPPER */ 
    517         for (i = -1; i < inputDeviceCount && dev_count < MAX_HARDWARE; ++i) 
    518         { 
    519             UINT uDeviceID = (UINT)((i==-1) ? WAVE_MAPPER : i); 
    520             WAVEINCAPS wic; 
    521             MMRESULT mr; 
    522  
    523             pj_bzero(&wic, sizeof(WAVEINCAPS)); 
    524  
    525             mr = waveInGetDevCaps(uDeviceID, &wic, sizeof(WAVEINCAPS)); 
    526  
    527             if (mr == MMSYSERR_NOMEM) 
    528                 return PJ_ENOMEM; 
    529  
    530             if (mr != MMSYSERR_NOERROR) 
    531                 continue; 
    532  
    533 #ifdef UNICODE 
    534             WideCharToMultiByte(CP_ACP, 0, wic.szPname, wcslen(wic.szPname),  
    535                                 dev_info[dev_count].info.name, 64, NULL, NULL); 
    536 #else 
    537             strncpy(dev_info[dev_count].info.name, wic.szPname, MAXPNAMELEN); 
    538 #endif 
    539             if (uDeviceID == WAVE_MAPPER) 
    540                 strcat(dev_info[dev_count].info.name, " - Input"); 
    541  
    542             dev_info[dev_count].info.input_count = wic.wChannels; 
    543             dev_info[dev_count].info.output_count = 0; 
    544             dev_info[dev_count].info.default_samples_per_sec = 44100; 
    545             dev_info[dev_count].deviceId = uDeviceID; 
    546  
    547             /* Sometimes a device can return a rediculously large number of  
    548              * channels. This happened with an SBLive card on a Windows ME box. 
    549              * It also happens on Win XP! 
    550              */ 
    551             if ((dev_info[dev_count].info.input_count < 1) ||  
    552                 (dev_info[dev_count].info.input_count > 256)) 
    553                 dev_info[dev_count].info.input_count = 2; 
    554  
    555             ++dev_count; 
    556         } 
    557     } 
    558  
    559     if( outputDeviceCount > 0 ) 
    560     { 
    561         /* -1 is the WAVE_MAPPER */ 
    562         for (i = -1; i < outputDeviceCount && dev_count < MAX_HARDWARE; ++i) 
    563         { 
    564             UINT uDeviceID = (UINT)((i==-1) ? WAVE_MAPPER : i); 
    565             WAVEOUTCAPS woc; 
    566             MMRESULT mr; 
    567  
    568             pj_bzero(&woc, sizeof(WAVEOUTCAPS)); 
    569  
    570             mr = waveOutGetDevCaps(uDeviceID, &woc, sizeof(WAVEOUTCAPS)); 
    571  
    572             if (mr == MMSYSERR_NOMEM) 
    573                 return PJ_ENOMEM; 
    574  
    575             if (mr != MMSYSERR_NOERROR) 
    576                 continue; 
    577  
    578 #ifdef UNICODE 
    579             WideCharToMultiByte(CP_ACP, 0, woc.szPname, wcslen(woc.szPname), 
    580                                 dev_info[dev_count].info.name, 64, NULL, NULL); 
    581 #else 
    582             strncpy(dev_info[dev_count].info.name, woc.szPname, MAXPNAMELEN); 
    583 #endif 
    584             if (uDeviceID == WAVE_MAPPER) 
    585                 strcat(dev_info[dev_count].info.name, " - Output"); 
    586  
    587             dev_info[dev_count].info.output_count = woc.wChannels; 
    588             dev_info[dev_count].info.input_count = 0; 
    589             dev_info[dev_count].deviceId = uDeviceID; 
    590             /* TODO: Perform a search! */ 
    591             dev_info[dev_count].info.default_samples_per_sec = 44100; 
    592  
    593             /* Sometimes a device can return a rediculously large number of channels. 
    594              * This happened with an SBLive card on a Windows ME box. 
    595              * It also happens on Win XP! 
    596              */ 
    597             if ((dev_info[dev_count].info.output_count < 1) ||  
    598                 (dev_info[dev_count].info.output_count > 256)) 
    599                 dev_info[dev_count].info.output_count = 2; 
    600  
    601             ++dev_count; 
    602         } 
    603     } 
    604  
    605     PJ_LOG(4, (THIS_FILE, "WMME initialized, found %d devices:", dev_count)); 
    606     for (c = 0; c < dev_count; ++c) 
    607     { 
    608         PJ_LOG(4, (THIS_FILE, " dev_id %d: %s  (in=%d, out=%d)",  
    609             c, 
    610             dev_info[c].info.name, 
    611             dev_info[c].info.input_count, 
    612             dev_info[c].info.output_count)); 
    613     } 
    614     return PJ_SUCCESS; 
    615 } 
    616  
    617 /* 
    618  * Deinitialize sound library. 
    619  */ 
    620 PJ_DEF(pj_status_t) pjmedia_snd_deinit(void) 
    621 { 
    622     snd_initialized = PJ_FALSE; 
    623     return PJ_SUCCESS; 
    624 } 
    625  
    626 /* 
    627  * Get device count. 
    628  */ 
    629 PJ_DEF(int) pjmedia_snd_get_dev_count(void) 
    630 { 
    631     return dev_count; 
    632 } 
    633  
    634 /* 
    635  * Get device info. 
    636  */ 
    637 PJ_DEF(const pjmedia_snd_dev_info*) pjmedia_snd_get_dev_info(unsigned index) 
    638 { 
    639     if (index == (unsigned)-1)  
    640         index = 0; 
    641  
    642     PJ_ASSERT_RETURN(index < dev_count, NULL); 
    643  
    644     return &dev_info[index].info; 
    645 } 
    646  
    647  
    648 /* 
    649  * Open stream. 
    650  */ 
    651 static pj_status_t open_stream(pjmedia_dir dir, 
    652                                int rec_id, 
    653                                int play_id, 
    654                                unsigned clock_rate, 
    655                                unsigned channel_count, 
    656                                unsigned samples_per_frame, 
    657                                unsigned bits_per_sample, 
    658                                pjmedia_snd_rec_cb rec_cb, 
    659                                pjmedia_snd_play_cb play_cb, 
    660                                void *user_data, 
    661                                pjmedia_snd_stream **p_snd_strm) 
    662 { 
    663     pj_pool_t *pool; 
    664     pjmedia_snd_stream *strm; 
    665     pj_status_t status; 
    666  
    667  
    668     /* Make sure sound subsystem has been initialized with 
    669      * pjmedia_snd_init() 
    670      */ 
    671     PJ_ASSERT_RETURN(pool_factory != NULL, PJ_EINVALIDOP); 
    672  
    673  
    674     /* Can only support 16bits per sample */ 
    675     PJ_ASSERT_RETURN(bits_per_sample == BITS_PER_SAMPLE, PJ_EINVAL); 
    676  
    677     /* Create and Initialize stream descriptor */ 
    678     pool = pj_pool_create(pool_factory, "wmme-dev", 1000, 1000, NULL); 
    679     PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM); 
    680  
    681     strm = pj_pool_zalloc(pool, sizeof(pjmedia_snd_stream)); 
    682     strm->dir = dir; 
    683     strm->play_id = play_id; 
    684     strm->rec_id = rec_id; 
    685     strm->pool = pool; 
    686     strm->rec_cb = rec_cb; 
    687     strm->play_cb = play_cb; 
    688     strm->user_data = user_data; 
    689     strm->clock_rate = clock_rate; 
    690     strm->samples_per_frame = samples_per_frame; 
    691     strm->bits_per_sample = bits_per_sample; 
    692     strm->channel_count = channel_count; 
    693     strm->buffer = pj_pool_alloc(pool, samples_per_frame * BYTES_PER_SAMPLE); 
    694     if (!strm->buffer) 
    695     { 
    696         pj_pool_release(pool); 
    697         return PJ_ENOMEM; 
    698     } 
    699  
    700     /* Create player stream */ 
    701     if (dir & PJMEDIA_DIR_PLAYBACK) 
    702     { 
    703         unsigned buf_count; 
    704  
    705         buf_count = snd_output_latency * clock_rate * channel_count /  
    706                     samples_per_frame / 1000; 
    707  
    708         status = init_player_stream(strm->pool, 
    709                                     &strm->play_strm, 
    710                                     play_id, 
    711                                     clock_rate, 
    712                                     channel_count, 
    713                                     samples_per_frame, 
    714                                     buf_count); 
    715  
    716         if (status != PJ_SUCCESS) 
    717         { 
    718             pjmedia_snd_stream_close(strm); 
    719             return status; 
    720         } 
    721     } 
    722  
    723     /* Create capture stream */ 
    724     if (dir & PJMEDIA_DIR_CAPTURE) 
    725     { 
    726         unsigned buf_count; 
    727  
    728         buf_count = snd_input_latency * clock_rate * channel_count /  
    729                     samples_per_frame / 1000; 
    730  
    731         status = init_capture_stream(strm->pool, 
    732                                      &strm->rec_strm, 
    733                                      rec_id, 
    734                                      clock_rate, 
    735                                      channel_count, 
    736                                      samples_per_frame, 
    737                                      buf_count); 
    738  
    739         if (status != PJ_SUCCESS) 
    740         { 
    741             pjmedia_snd_stream_close(strm); 
    742             return status; 
    743         } 
    744     } 
    745  
    746     /* Create the stop event */ 
    747     strm->thread_quit_event = CreateEvent(NULL, FALSE, FALSE, NULL); 
    748     if (strm->thread_quit_event == NULL) 
    749         return pj_get_os_error(); 
    750  
    751     /* Create and start the thread */ 
    752     status = pj_thread_create(pool, "wmme", &wmme_dev_thread, strm, 0, 0,  
    753                               &strm->thread); 
    754     if (status != PJ_SUCCESS) 
    755     { 
    756         pjmedia_snd_stream_close(strm); 
    757         return status; 
    758     } 
    759  
    760     *p_snd_strm = strm; 
    761  
    762     return PJ_SUCCESS; 
    763 } 
    764  
    765 /* 
    766  * Open stream. 
    767  */ 
    768 PJ_DEF(pj_status_t) pjmedia_snd_open_rec(int index, 
    769                                          unsigned clock_rate, 
    770                                          unsigned channel_count, 
    771                                          unsigned samples_per_frame, 
    772                                          unsigned bits_per_sample, 
    773                                          pjmedia_snd_rec_cb rec_cb, 
    774                                          void *user_data, 
    775                                          pjmedia_snd_stream **p_snd_strm) 
    776 { 
    777     PJ_ASSERT_RETURN(rec_cb && p_snd_strm, PJ_EINVAL); 
    778  
    779     return open_stream( PJMEDIA_DIR_CAPTURE, 
    780                         index, 
    781                         -1, 
    782                         clock_rate, 
    783                         channel_count, 
    784                         samples_per_frame, 
    785                         bits_per_sample, 
    786                         rec_cb, 
    787                         NULL, 
    788                         user_data, 
    789                         p_snd_strm); 
    790 } 
    791  
    792 PJ_DEF(pj_status_t) pjmedia_snd_open_player(int index, 
    793                                             unsigned clock_rate, 
    794                                             unsigned channel_count, 
    795                                             unsigned samples_per_frame, 
    796                                             unsigned bits_per_sample, 
    797                                             pjmedia_snd_play_cb play_cb, 
    798                                             void *user_data, 
    799                                             pjmedia_snd_stream **p_snd_strm) 
    800 { 
    801     PJ_ASSERT_RETURN(play_cb && p_snd_strm, PJ_EINVAL); 
    802  
    803     return open_stream( PJMEDIA_DIR_PLAYBACK, 
    804                         -1, 
    805                         index, 
    806                         clock_rate, 
    807                         channel_count, 
    808                         samples_per_frame, 
    809                         bits_per_sample, 
    810                         NULL, 
    811                         play_cb, 
    812                         user_data, 
    813                         p_snd_strm); 
    814 } 
    815  
    816 /* 
    817  * Open both player and recorder. 
    818  */ 
    819 PJ_DEF(pj_status_t) pjmedia_snd_open(int rec_id, 
    820                                      int play_id, 
    821                                      unsigned clock_rate, 
    822                                      unsigned channel_count, 
    823                                      unsigned samples_per_frame, 
    824                                      unsigned bits_per_sample, 
    825                                      pjmedia_snd_rec_cb rec_cb, 
    826                                      pjmedia_snd_play_cb play_cb, 
    827                                      void *user_data, 
    828                                      pjmedia_snd_stream **p_snd_strm) 
    829 { 
    830     PJ_ASSERT_RETURN(rec_cb && play_cb && p_snd_strm, PJ_EINVAL); 
    831  
    832     return open_stream( PJMEDIA_DIR_CAPTURE_PLAYBACK, 
    833                         rec_id, 
    834                         play_id, 
    835                         clock_rate, 
    836                         channel_count, 
    837                         samples_per_frame, 
    838                         bits_per_sample, 
    839                         rec_cb, 
    840                         play_cb, 
    841                         user_data, 
    842                         p_snd_strm); 
    843 } 
    844  
    845 /* 
    846  * Get stream info. 
    847  */ 
    848 PJ_DEF(pj_status_t) pjmedia_snd_stream_get_info(pjmedia_snd_stream *strm,  
    849                                                 pjmedia_snd_stream_info *pi) 
    850 { 
    851     PJ_ASSERT_RETURN(strm && pi, PJ_EINVAL); 
    852  
    853     pj_bzero(pi, sizeof(*pi)); 
    854     pi->dir = strm->dir; 
    855     pi->play_id = strm->play_id; 
    856     pi->rec_id = strm->rec_id; 
    857     pi->clock_rate = strm->clock_rate; 
    858     pi->channel_count = strm->channel_count; 
    859     pi->samples_per_frame = strm->samples_per_frame; 
    860     pi->bits_per_sample = strm->bits_per_sample; 
    861     pi->rec_latency = snd_input_latency * strm->clock_rate *  
    862                       strm->channel_count / 1000; 
    863     pi->play_latency = snd_output_latency * strm->clock_rate *  
    864                        strm->channel_count / 1000; 
    865  
    866     return PJ_SUCCESS; 
    867 } 
    868  
    869  
    870 /* 
    871 * Start stream. 
    872 */ 
    873 PJ_DEF(pj_status_t) pjmedia_snd_stream_start(pjmedia_snd_stream *stream) 
    874 { 
    875     MMRESULT mr; 
    876  
    877     PJ_UNUSED_ARG(stream); 
    878  
    879     if (stream->play_strm.hWave.Out != NULL) 
    880     { 
    881         mr = waveOutRestart(stream->play_strm.hWave.Out); 
    882         if (mr != MMSYSERR_NOERROR) 
    883             /* TODO: This macro is supposed to be used for HRESULT, fix. */ 
    884             PJ_RETURN_OS_ERROR(mr); 
    885         PJ_LOG(5,(THIS_FILE, "WMME playback stream started")); 
    886     } 
    887  
    888     if (stream->rec_strm.hWave.In != NULL) 
    889     { 
    890         mr = waveInStart(stream->rec_strm.hWave.In); 
    891         if (mr != MMSYSERR_NOERROR) 
    892             /* TODO: This macro is supposed to be used for HRESULT, fix. */ 
    893             PJ_RETURN_OS_ERROR(mr); 
    894         PJ_LOG(5,(THIS_FILE, "WMME capture stream started")); 
    895     } 
    896  
    897     return PJ_SUCCESS; 
    898 } 
    899  
    900 /* 
    901  * Stop stream. 
    902  */ 
    903 PJ_DEF(pj_status_t) pjmedia_snd_stream_stop(pjmedia_snd_stream *stream) 
    904 { 
    905     MMRESULT mr; 
    906  
    907     PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL); 
    908  
    909     if (stream->play_strm.hWave.Out != NULL) 
    910     { 
    911         mr = waveOutPause(stream->play_strm.hWave.Out); 
    912         if (mr != MMSYSERR_NOERROR) 
    913             /* TODO: This macro is supposed to be used for HRESULT, fix. */ 
    914             PJ_RETURN_OS_ERROR(mr); 
    915         PJ_LOG(5,(THIS_FILE, "Stopped WMME playback stream")); 
    916     } 
    917  
    918     if (stream->rec_strm.hWave.In != NULL) 
    919     { 
    920         mr = waveInStop(stream->rec_strm.hWave.In); 
    921         if (mr != MMSYSERR_NOERROR) 
    922             /* TODO: This macro is supposed to be used for HRESULT, fix. */ 
    923             PJ_RETURN_OS_ERROR(mr); 
    924         PJ_LOG(5,(THIS_FILE, "Stopped WMME capture stream")); 
    925     } 
    926  
    927     return PJ_SUCCESS; 
    928 } 
    929  
    930  
    931 /* 
    932  * Destroy stream. 
    933  */ 
    934 PJ_DEF(pj_status_t) pjmedia_snd_stream_close(pjmedia_snd_stream *stream) 
    935 { 
    936     unsigned i; 
    937  
    938     PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL); 
    939  
    940     pjmedia_snd_stream_stop(stream); 
    941  
    942     if (stream->thread) 
    943     { 
    944         SetEvent(stream->thread_quit_event); 
    945         pj_thread_join(stream->thread); 
    946         pj_thread_destroy(stream->thread); 
    947         stream->thread = NULL; 
    948     } 
    949  
    950     /* Unprepare the headers and close the play device */ 
    951     if (stream->play_strm.hWave.Out) 
    952     { 
    953         waveOutReset(stream->play_strm.hWave.Out); 
    954         for (i = 0; i < stream->play_strm.dwMaxBufIdx; ++i) 
    955             waveOutUnprepareHeader(stream->play_strm.hWave.Out,  
    956                                    &(stream->play_strm.WaveHdr[i]), 
    957                                    sizeof(WAVEHDR)); 
    958         waveOutClose(stream->play_strm.hWave.Out); 
    959         stream->play_strm.hWave.Out = NULL; 
    960     } 
    961  
    962     /* Close the play event */ 
    963     if (stream->play_strm.hEvent) 
    964     { 
    965         CloseHandle(stream->play_strm.hEvent); 
    966         stream->play_strm.hEvent = NULL; 
    967     } 
    968  
    969     /* Unprepare the headers and close the record device */ 
    970     if (stream->rec_strm.hWave.In) 
    971     { 
    972         waveInReset(stream->rec_strm.hWave.In); 
    973         for (i = 0; i < stream->play_strm.dwMaxBufIdx; ++i) 
    974             waveInUnprepareHeader(stream->rec_strm.hWave.In,  
    975                                   &(stream->rec_strm.WaveHdr[i]), 
    976                                   sizeof(WAVEHDR)); 
    977         waveInClose(stream->rec_strm.hWave.In); 
    978         stream->rec_strm.hWave.In = NULL; 
    979     } 
    980  
    981     /* Close the record event */ 
    982     if (stream->rec_strm.hEvent) 
    983     { 
    984         CloseHandle(stream->rec_strm.hEvent); 
    985         stream->rec_strm.hEvent = NULL; 
    986     } 
    987  
    988     pj_pool_release(stream->pool); 
    989  
    990     return PJ_SUCCESS; 
    991 } 
    992  
    993 /* 
    994  * Set sound latency. 
    995  */ 
    996 PJ_DEF(pj_status_t) pjmedia_snd_set_latency(unsigned input_latency,  
    997                                             unsigned output_latency) 
    998 { 
    999     snd_input_latency  = (input_latency == 0)?  
    1000                           PJMEDIA_SND_DEFAULT_REC_LATENCY : input_latency; 
    1001     snd_output_latency = (output_latency == 0)?  
    1002                          PJMEDIA_SND_DEFAULT_PLAY_LATENCY : output_latency; 
    1003  
    1004     return PJ_SUCCESS; 
    1005 } 
    1006  
    1007 #endif  /* PJMEDIA_SOUND_IMPLEMENTATION */ 
    1008  
  • pjproject/branches/projects/aps-direct/pjproject.dsw

    r2463 r2468  
    234234    Project_Dep_Name pjnath 
    235235    End Project Dependency 
     236    Begin Project Dependency 
     237    Project_Dep_Name pjmedia_audiodev 
     238    End Project Dependency 
    236239}}} 
    237240 
     
    363366    Project_Dep_Name libsrtp 
    364367    End Project Dependency 
     368    Begin Project Dependency 
     369    Project_Dep_Name pjmedia_audiodev 
     370    End Project Dependency 
    365371}}} 
    366372 
     
    451457    End Project Dependency 
    452458    Begin Project Dependency 
     459    Project_Dep_Name libgsmcodec 
     460    End Project Dependency 
     461    Begin Project Dependency 
     462    Project_Dep_Name libilbccodec 
     463    End Project Dependency 
     464    Begin Project Dependency 
     465    Project_Dep_Name libportaudio 
     466    End Project Dependency 
     467    Begin Project Dependency 
     468    Project_Dep_Name libresample 
     469    End Project Dependency 
     470    Begin Project Dependency 
     471    Project_Dep_Name libspeex 
     472    End Project Dependency 
     473    Begin Project Dependency 
     474    Project_Dep_Name pjnath 
     475    End Project Dependency 
     476    Begin Project Dependency 
     477    Project_Dep_Name libsrtp 
     478    End Project Dependency 
     479    Begin Project Dependency 
     480    Project_Dep_Name pjmedia_audiodev 
     481    End Project Dependency 
     482}}} 
     483 
     484############################################################################### 
     485 
     486Project: "samples"=".\pjsip-apps\build\samples.dsp" - Package Owner=<4> 
     487 
     488Package=<5> 
     489{{{ 
     490}}} 
     491 
     492Package=<4> 
     493{{{ 
     494    Begin Project Dependency 
     495    Project_Dep_Name pjlib 
     496    End Project Dependency 
     497    Begin Project Dependency 
     498    Project_Dep_Name pjlib_util 
     499    End Project Dependency 
     500    Begin Project Dependency 
     501    Project_Dep_Name pjmedia 
     502    End Project Dependency 
     503    Begin Project Dependency 
     504    Project_Dep_Name pjmedia_codec 
     505    End Project Dependency 
     506    Begin Project Dependency 
     507    Project_Dep_Name pjsip_core 
     508    End Project Dependency 
     509    Begin Project Dependency 
     510    Project_Dep_Name pjsip_simple 
     511    End Project Dependency 
     512    Begin Project Dependency 
     513    Project_Dep_Name pjsip_ua 
     514    End Project Dependency 
     515    Begin Project Dependency 
    453516    Project_Dep_Name pjsua_lib 
    454517    End Project Dependency 
     
    481544############################################################################### 
    482545 
    483 Project: "samples"=".\pjsip-apps\build\samples.dsp" - Package Owner=<4> 
     546Project: "test_pjsip"=".\pjsip\build\test_pjsip.dsp" - Package Owner=<4> 
    484547 
    485548Package=<5> 
     
    513576    Project_Dep_Name pjsua_lib 
    514577    End Project Dependency 
    515     Begin Project Dependency 
    516     Project_Dep_Name libgsmcodec 
    517     End Project Dependency 
    518     Begin Project Dependency 
    519     Project_Dep_Name libilbccodec 
    520     End Project Dependency 
    521     Begin Project Dependency 
    522     Project_Dep_Name libportaudio 
    523     End Project Dependency 
    524     Begin Project Dependency 
    525     Project_Dep_Name libresample 
    526     End Project Dependency 
    527     Begin Project Dependency 
    528     Project_Dep_Name libspeex 
    529     End Project Dependency 
    530     Begin Project Dependency 
    531     Project_Dep_Name pjnath 
    532     End Project Dependency 
    533     Begin Project Dependency 
    534     Project_Dep_Name libsrtp 
    535     End Project Dependency 
    536 }}} 
    537  
    538 ############################################################################### 
    539  
    540 Project: "test_pjsip"=".\pjsip\build\test_pjsip.dsp" - Package Owner=<4> 
    541  
    542 Package=<5> 
    543 {{{ 
    544 }}} 
    545  
    546 Package=<4> 
    547 {{{ 
    548     Begin Project Dependency 
    549     Project_Dep_Name pjlib 
    550     End Project Dependency 
    551     Begin Project Dependency 
    552     Project_Dep_Name pjlib_util 
    553     End Project Dependency 
    554     Begin Project Dependency 
    555     Project_Dep_Name pjmedia 
    556     End Project Dependency 
    557     Begin Project Dependency 
    558     Project_Dep_Name pjmedia_codec 
    559     End Project Dependency 
    560     Begin Project Dependency 
    561     Project_Dep_Name pjsip_core 
    562     End Project Dependency 
    563     Begin Project Dependency 
    564     Project_Dep_Name pjsip_simple 
    565     End Project Dependency 
    566     Begin Project Dependency 
    567     Project_Dep_Name pjsip_ua 
    568     End Project Dependency 
    569     Begin Project Dependency 
    570     Project_Dep_Name pjsua_lib 
    571     End Project Dependency 
    572578}}} 
    573579 
  • pjproject/branches/projects/aps-direct/pjsip-apps/build/Samples-vc.mak

    r2178 r2468  
    1414PJMEDIA_LIB = ..\..\pjmedia\lib\pjmedia-$(TARGET)$(LIBEXT) 
    1515PJMEDIA_CODEC_LIB = ..\..\pjmedia\lib\pjmedia-codec-$(TARGET)$(LIBEXT) 
     16PJMEDIA_AUDIODEV_LIB = ..\..\pjmedia\lib\pjmedia-audiodev-$(TARGET)$(LIBEXT) 
    1617PJSIP_LIB = ..\..\pjsip\lib\pjsip-core-$(TARGET)$(LIBEXT) 
    1718PJSIP_UA_LIB = ..\..\pjsip\lib\pjsip-ua-$(TARGET)$(LIBEXT) 
     
    3031 
    3132LIBS = $(PJSUA_LIB_LIB) $(PJSIP_UA_LIB) $(PJSIP_SIMPLE_LIB) \ 
    32           $(PJSIP_LIB) $(PJMEDIA_CODEC_LIB) $(PJMEDIA_LIB) $(PJNATH_LIB) \ 
    33           $(PJLIB_UTIL_LIB) $(PJLIB_LIB) \ 
     33          $(PJSIP_LIB) $(PJMEDIA_CODEC_LIB) $(PJMEDIA_AUDIODEV_LIB) \ 
     34          $(PJMEDIA_LIB) $(PJNATH_LIB) $(PJLIB_UTIL_LIB) $(PJLIB_LIB) \ 
    3435          $(THIRD_PARTY_LIBS) 
    3536 
     
    5051 
    5152 
    52 SAMPLES = $(BINDIR)\confsample.exe \ 
     53SAMPLES = $(BINDIR)\auddemo.exe \ 
     54          $(BINDIR)\confsample.exe \ 
    5355          $(BINDIR)\confbench.exe \ 
    5456          $(BINDIR)\encdec.exe \ 
     
    6668          $(BINDIR)\siprtp.exe \ 
    6769          $(BINDIR)\sipstateless.exe \ 
    68           $(BINDIR)\sndinfo.exe \ 
    69           $(BINDIR)\sndtest.exe \ 
    7070          $(BINDIR)\stateful_proxy.exe \ 
    7171          $(BINDIR)\stateless_proxy.exe \ 
  • pjproject/branches/projects/aps-direct/pjsip-apps/build/Samples.mak

    r2183 r2468  
    1414BINDIR := ../bin/samples 
    1515 
    16 SAMPLES := confsample \ 
     16SAMPLES := auddemo \ 
     17           confsample \ 
    1718           encdec \ 
    1819           latency \ 
     
    2930           siprtp \ 
    3031           sipstateless \ 
    31            sndinfo \ 
    32            sndtest \ 
    3332           stateful_proxy \ 
    3433           stateless_proxy \ 
  • pjproject/branches/projects/aps-direct/pjsip-apps/src/pjsua/pjsua_app.c

    r2460 r2468  
    40604060    app_config.cfg.cb.on_nat_detect = &on_nat_detect; 
    40614061 
     4062    /* Set sound device latency */ 
     4063    if (app_config.capture_lat > 0) 
     4064        app_config.media_cfg.snd_rec_latency = app_config.capture_lat; 
     4065    if (app_config.playback_lat) 
     4066        app_config.media_cfg.snd_play_latency = app_config.playback_lat; 
     4067 
    40624068    /* Initialize pjsua */ 
    40634069    status = pjsua_init(&app_config.cfg, &app_config.log_cfg, 
     
    43184324    if (status != PJ_SUCCESS) 
    43194325        goto on_error; 
    4320  
    4321     /* Set sound device latency */ 
    4322     pjmedia_snd_set_latency(app_config.capture_lat, app_config.playback_lat); 
    43234326 
    43244327    /* Use null sound device? */ 
  • pjproject/branches/projects/aps-direct/pjsip-apps/src/samples/auddemo.c

    r2464 r2468  
    3030 
    3131static unsigned dev_count; 
    32 static pjmedia_aud_dev_id dev_id[MAX_DEVICES]; 
    3332 
    3433static void app_perror(const char *title, pj_status_t status) 
     
    5453    PJ_LOG(3,(THIS_FILE, "Found %d devices:", dev_count)); 
    5554 
    56     dev_count = pjmedia_aud_dev_enum(PJ_ARRAY_SIZE(dev_id), dev_id); 
    57  
    5855    for (i=0; i<dev_count; ++i) { 
    5956        pjmedia_aud_dev_info info; 
    6057 
    61         status = pjmedia_aud_dev_get_info(dev_id[i], &info); 
     58        status = pjmedia_aud_dev_get_info(i, &info); 
    6259        if (status != PJ_SUCCESS) 
    6360            continue; 
     
    7168{ 
    7269    static char text[200]; 
     70    unsigned i; 
    7371 
    7472    text[0] = '\0'; 
    7573 
    76     if (caps & PJMEDIA_AUD_DEV_CAP_EXT_FORMAT) { 
    77         strcat(text, "extfmt "); 
    78     } 
    79  
    80     if (caps & PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY) { 
    81         strcat(text, "inlatency "); 
    82     } 
    83  
    84     if (caps & PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY) { 
    85         strcat(text, "outlatency "); 
    86     } 
    87  
    88     if (caps & PJMEDIA_AUD_DEV_CAP_INPUT_VOLUME_SETTING) { 
    89         strcat(text, "invol "); 
    90     } 
    91  
    92     if (caps & PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING) { 
    93         strcat(text, "outvol "); 
    94     } 
    95  
    96     if (caps & PJMEDIA_AUD_DEV_CAP_INPUT_SIGNAL_VOLUME) { 
    97         strcat(text, "insignal "); 
    98     } 
    99  
    100     if (caps & PJMEDIA_AUD_DEV_CAP_OUTPUT_SIGNAL_VOLUME) { 
    101         strcat(text, "outsignal "); 
    102     } 
    103  
    104     if (caps & PJMEDIA_AUD_DEV_CAP_INPUT_ROUTE) { 
    105         strcat(text, "inroute "); 
    106     } 
    107  
    108     if (caps & PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE) { 
    109         strcat(text, "outroute "); 
    110     } 
    111  
    112     if (caps & PJMEDIA_AUD_DEV_CAP_EC) { 
    113         strcat(text, "ec "); 
    114     } 
    115  
    116     if (caps & PJMEDIA_AUD_DEV_CAP_EC_TAIL) { 
    117         strcat(text, "ectail "); 
    118     } 
    119  
    120     if (caps & PJMEDIA_AUD_DEV_CAP_VAD) { 
    121         strcat(text, "vad "); 
    122     } 
    123  
    124     if (caps & PJMEDIA_AUD_DEV_CAP_CNG) { 
    125         strcat(text, "cng "); 
    126     } 
    127  
    128     if (caps & PJMEDIA_AUD_DEV_CAP_PLC) { 
    129         strcat(text, "plc "); 
     74    for (i=0; i<31; ++i) { 
     75        if ((1 << i) & caps) { 
     76            const char *capname; 
     77            capname = pjmedia_aud_dev_cap_name((pjmedia_aud_dev_cap)(1 << i),  
     78                                               NULL); 
     79            strcat(text, capname); 
     80            strcat(text, " "); 
     81        } 
    13082    } 
    13183 
     
    14597    } 
    14698 
    147     status = pjmedia_aud_dev_get_info(dev_id[index], &info); 
     99    status = pjmedia_aud_dev_get_info(index, &info); 
    148100    if (status != PJ_SUCCESS) { 
    149101        app_perror("pjmedia_aud_dev_get_info() error", status); 
     
    154106    PJ_LOG(3, (THIS_FILE, "-------------------------")); 
    155107 
    156     PJ_LOG(3, (THIS_FILE, H": %u (0x%x)", "ID", dev_id[index], dev_id[index])); 
     108    PJ_LOG(3, (THIS_FILE, H": %u (0x%x)", "ID", index, index)); 
    157109    PJ_LOG(3, (THIS_FILE, H": %s", "Name", info.name)); 
    158110    PJ_LOG(3, (THIS_FILE, H": %s", "Driver", info.driver)); 
     
    205157                        unsigned chnum) 
    206158{ 
    207     pjmedia_aud_dev_param param; 
     159    pjmedia_aud_param param; 
    208160    pjmedia_aud_test_results result; 
    209161    pj_status_t status; 
    210162 
    211163    if (dir & PJMEDIA_DIR_CAPTURE) { 
    212         status = pjmedia_aud_dev_default_param(dev_id[rec_id], &param); 
     164        status = pjmedia_aud_dev_default_param(rec_id, &param); 
    213165    } else { 
    214         status = pjmedia_aud_dev_default_param(dev_id[play_id], &param); 
     166        status = pjmedia_aud_dev_default_param(play_id, &param); 
    215167    } 
    216168 
     
    221173 
    222174    param.dir = dir; 
    223     param.rec_id = dev_id[rec_id]; 
    224     param.play_id = dev_id[play_id]; 
     175    param.rec_id = rec_id; 
     176    param.play_id = play_id; 
    225177    param.clock_rate = clock_rate; 
    226178    param.channel_count = chnum; 
     
    286238    pj_pool_t *pool = NULL; 
    287239    pjmedia_port *wav = NULL; 
    288     pjmedia_aud_dev_param param; 
     240    pjmedia_aud_param param; 
    289241    pjmedia_aud_stream *strm = NULL; 
    290242    char line[10]; 
     
    304256    } 
    305257 
    306     status = pjmedia_aud_dev_default_param(dev_id[rec_index], &param); 
     258    status = pjmedia_aud_dev_default_param(rec_index, &param); 
    307259    if (status != PJ_SUCCESS) { 
    308260        app_perror("pjmedia_aud_dev_default_param()", status); 
     
    354306    pj_pool_t *pool = NULL; 
    355307    pjmedia_port *wav = NULL; 
    356     pjmedia_aud_dev_param param; 
     308    pjmedia_aud_param param; 
    357309    pjmedia_aud_stream *strm = NULL; 
    358310    char line[10]; 
     
    371323    } 
    372324 
    373     status = pjmedia_aud_dev_default_param(dev_id[play_index], &param); 
     325    status = pjmedia_aud_dev_default_param(play_index, &param); 
    374326    if (status != PJ_SUCCESS) { 
    375327        app_perror("pjmedia_aud_dev_default_param()", status); 
  • pjproject/branches/projects/aps-direct/pjsip/include/pjsua-lib/pjsua.h

    r2460 r2468  
    42014201    unsigned            ec_tail_len; 
    42024202 
     4203    /** 
     4204     * Audio capture buffer length, in milliseconds. 
     4205     * 
     4206     * Default: PJMEDIA_SND_DEFAULT_REC_LATENCY 
     4207     */ 
     4208    unsigned            snd_rec_latency; 
     4209 
     4210    /** 
     4211     * Audio playback buffer length, in milliseconds. 
     4212     * 
     4213     * Default: PJMEDIA_SND_DEFAULT_PLAY_LATENCY 
     4214     */ 
     4215    unsigned            snd_play_latency; 
     4216 
    42034217    /**  
    42044218     * Jitter buffer initial prefetch delay in msec. The value must be 
     
    48054819 * 
    48064820 */ 
     4821#if PJMEDIA_AUDIO_API==PJMEDIA_AUDIO_API_NEW_ONLY 
     4822PJ_DECL(pj_status_t) pjsua_enum_snd_devs(pjmedia_aud_dev_info info[], 
     4823                                         unsigned *count); 
     4824#else 
    48074825PJ_DECL(pj_status_t) pjsua_enum_snd_devs(pjmedia_snd_dev_info info[], 
    48084826                                         unsigned *count); 
    4809  
     4827#endif 
    48104828 
    48114829 
     
    48804898 
    48814899/** 
    4882  * Configure the echo canceller tail length of the sound port. 
     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.  
     4903 * 
     4904 * If the sound device is currently active, and if the device supports AEC, 
     4905 * this function will forward the change request to the device and it will 
     4906 * be up to the device on whether support the request. If software AEC is 
     4907 * being used (the software EC will be used if the device does not support 
     4908 * AEC), this function will change the software EC settings. In all cases, 
     4909 * the setting will be saved for future opening of the sound device. 
     4910 * 
     4911 * If the sound device is not currently active, this will only change the 
     4912 * default AEC settings and the setting will be applied next time the  
     4913 * sound device is opened. 
    48834914 * 
    48844915 * @param tail_ms       The tail length, in miliseconds. Set to zero to 
     
    49114942 */ 
    49124943PJ_DECL(pj_status_t) pjsua_get_ec_tail(unsigned *p_tail_ms); 
    4913  
    4914  
    4915 /** 
    4916  * Set sound device route. 
    4917  * 
    4918  * @param route         Sound device route to be set. 
    4919  * 
    4920  * @return              PJ_SUCCESS on success, or the appropriate error code. 
    4921  */ 
    4922 PJ_DECL(pj_status_t) pjsua_set_snd_route(pjmedia_snd_route route); 
    49234944 
    49244945 
  • pjproject/branches/projects/aps-direct/pjsip/src/pjsua-lib/pjsua_core.c

    r2394 r2468  
    178178    cfg->ilbc_mode = PJSUA_DEFAULT_ILBC_MODE; 
    179179    cfg->ec_tail_len = PJSUA_DEFAULT_EC_TAIL_LEN; 
     180    cfg->snd_rec_latency = PJMEDIA_SND_DEFAULT_REC_LATENCY; 
     181    cfg->snd_play_latency = PJMEDIA_SND_DEFAULT_PLAY_LATENCY; 
    180182    cfg->jb_init = cfg->jb_min_pre = cfg->jb_max_pre = cfg->jb_max = -1; 
    181183    cfg->snd_auto_close_time = -1; 
  • pjproject/branches/projects/aps-direct/pjsip/src/pjsua-lib/pjsua_media.c

    r2462 r2468  
    15151515 * Open sound device with extended setting. 
    15161516 */ 
    1517 static pj_status_t open_snd_dev_ext( int capture_dev, 
    1518                                      int playback_dev, 
    1519                                      unsigned clock_rate, 
    1520                                      unsigned channel_count, 
    1521                                      unsigned samples_per_frame, 
    1522                                      const pjmedia_snd_setting *setting) 
     1517static pj_status_t open_snd_dev_ext(pjmedia_aud_param *param) 
    15231518{ 
    15241519    pjmedia_port *conf_port; 
    15251520    pj_status_t status; 
    15261521 
    1527     PJ_ASSERT_RETURN(setting, PJ_EINVAL); 
     1522    PJ_ASSERT_RETURN(param, PJ_EINVAL); 
    15281523 
    15291524    /* Check if NULL sound device is used */ 
    1530     if (NULL_SND_DEV_ID == capture_dev || NULL_SND_DEV_ID == playback_dev) { 
     1525    if (NULL_SND_DEV_ID==param->rec_id || NULL_SND_DEV_ID==param->play_id) { 
    15311526        return pjsua_set_null_snd_dev(); 
    15321527    } 
     
    15451540 
    15461541    PJ_LOG(4,(THIS_FILE, "Opening sound device @%d/%d/%s", 
    1547               clock_rate, channel_count, 
    1548               (setting->format.id==PJMEDIA_FORMAT_L16?"raw":"encoded"))); 
     1542              param->clock_rate, param->channel_count, 
     1543              (param->ext_fmt.id==PJMEDIA_FORMAT_L16?"pcm":"encoded"))); 
    15491544 
    15501545    status = pjmedia_snd_port_create2( pjsua_var.snd_pool,  
    1551                                        PJMEDIA_DIR_CAPTURE_PLAYBACK, 
    1552                                        capture_dev, 
    1553                                        playback_dev,  
    1554                                        clock_rate,  
    1555                                        channel_count, 
    1556                                        samples_per_frame, 
    1557                                        16,  
    1558                                        setting,  
    1559                                        &pjsua_var.snd_port); 
     1546                                       param,  &pjsua_var.snd_port); 
    15601547 
    15611548    /* Update port 0 info when sound dev opened successfully. */ 
    15621549    if (status == PJ_SUCCESS) { 
    1563         conf_port->info.format = setting->format; 
    1564         conf_port->info.clock_rate = clock_rate; 
    1565         conf_port->info.samples_per_frame = samples_per_frame; 
    1566         conf_port->info.channel_count = channel_count; 
     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; 
    15671555        conf_port->info.bits_per_sample = 16; 
    15681556    } else { 
     
    15831571 
    15841572    /* Save the device IDs */ 
    1585     pjsua_var.cap_dev = capture_dev; 
    1586     pjsua_var.play_dev = playback_dev; 
     1573    pjsua_var.cap_dev = param->rec_id; 
     1574    pjsua_var.play_dev = param->play_id; 
    15871575 
    15881576    /* Update sound device name. */ 
    1589     do { 
    1590         const pjmedia_snd_dev_info *play_info; 
    1591         pjmedia_snd_stream *strm; 
    1592         pjmedia_snd_stream_info si; 
     1577    { 
     1578        pjmedia_aud_dev_info play_info; 
     1579        pjmedia_aud_stream *strm; 
     1580        pjmedia_aud_param si; 
    15931581        pj_str_t tmp; 
    15941582 
    15951583        strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port); 
    1596         pjmedia_snd_stream_get_info(strm, &si); 
    1597         play_info = pjmedia_snd_get_dev_info(si.rec_id); 
    1598  
    1599         pjmedia_conf_set_port0_name(pjsua_var.mconf,  
    1600                                     pj_cstr(&tmp, play_info->name)); 
    1601     } while(0); 
     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    }; 
    16021590 
    16031591    return PJ_SUCCESS; 
     
    16121600    /* Close sound device */ 
    16131601    if (pjsua_var.snd_port) { 
    1614         pjmedia_snd_dev_info cap_info, play_info; 
    1615         pjmedia_snd_stream *strm; 
    1616         pjmedia_snd_stream_info si; 
     1602        pjmedia_aud_dev_info cap_info, play_info; 
     1603        pjmedia_aud_stream *strm; 
     1604        pjmedia_aud_param param; 
    16171605 
    16181606        strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port); 
    1619         pjmedia_snd_stream_get_info(strm, &si); 
    1620         cap_info = *(pjmedia_snd_get_dev_info(si.rec_id)); 
    1621         play_info = *(pjmedia_snd_get_dev_info(si.play_id)); 
     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'; 
    16221613 
    16231614        PJ_LOG(4,(THIS_FILE, "Closing %s sound playback device and " 
     
    17971788 
    17981789        if (need_reopen) { 
    1799             pjmedia_snd_setting setting; 
    1800  
    1801             pj_bzero(&setting, sizeof(setting)); 
    1802             setting.format = peer_info.format; 
    1803             setting.plc = PJ_FALSE; 
    1804             setting.route = PJMEDIA_SND_ROUTE_DEFAULT; 
     1790            pjmedia_aud_param param; 
     1791 
     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; 
     1797            } 
     1798 
     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; 
    18051825             
    1806             status = open_snd_dev_ext(pjsua_var.cap_dev, pjsua_var.play_dev, 
    1807                                       peer_info.clock_rate, 
    1808                                       peer_info.channel_count, 
    1809                                       peer_info.samples_per_frame, 
    1810                                       &setting); 
     1826            status = open_snd_dev_ext(&param); 
    18111827            if (status != PJ_SUCCESS) { 
    18121828                pjsua_perror(THIS_FILE, "Error opening sound device", status); 
     
    23072323 * Enum sound devices. 
    23082324 */ 
     2325#if PJMEDIA_AUDIO_API==PJMEDIA_AUDIO_API_NEW_ONLY 
     2326PJ_DEF(pj_status_t) pjsua_enum_snd_devs( pjmedia_aud_dev_info info[], 
     2327                                         unsigned *count) 
     2328{ 
     2329    unsigned i, dev_count; 
     2330 
     2331    dev_count = pjmedia_aud_dev_count(); 
     2332     
     2333    if (dev_count > *count) dev_count = *count; 
     2334 
     2335    for (i=0; i<dev_count; ++i) { 
     2336        pj_status_t status; 
     2337 
     2338        status = pjmedia_aud_dev_get_info(i, &info[i]); 
     2339        if (status != PJ_SUCCESS) 
     2340            return status; 
     2341    } 
     2342 
     2343    *count = dev_count; 
     2344 
     2345    return PJ_SUCCESS; 
     2346} 
     2347#else   /* PJMEDIA_AUDIO_API */ 
    23092348PJ_DEF(pj_status_t) pjsua_enum_snd_devs( pjmedia_snd_dev_info info[], 
    23102349                                         unsigned *count) 
     
    23122351    unsigned i, dev_count; 
    23132352 
    2314     dev_count = pjmedia_snd_get_dev_count(); 
     2353    dev_count = pjmedia_aud_dev_count(); 
    23152354     
    23162355    if (dev_count > *count) dev_count = *count; 
     2356    pj_bzero(info, dev_count * sizeof(pjmedia_snd_dev_info)); 
    23172357 
    23182358    for (i=0; i<dev_count; ++i) { 
    2319         const pjmedia_snd_dev_info *ci; 
    2320  
    2321         ci = pjmedia_snd_get_dev_info(i); 
    2322         pj_memcpy(&info[i], ci, sizeof(*ci)); 
     2359        pjmedia_aud_dev_info ai; 
     2360        pj_status_t status; 
     2361 
     2362        status = pjmedia_aud_dev_get_info(i, &ai); 
     2363        if (status != PJ_SUCCESS) 
     2364            return status; 
     2365 
     2366        strncpy(info[i].name, ai.name, sizeof(info[i].name)); 
     2367        info[i].name[sizeof(info[i].name)-1] = '\0'; 
     2368        info[i].input_count = ai.input_count; 
     2369        info[i].output_count = ai.output_count; 
     2370        info[i].default_samples_per_sec = ai.default_samples_per_sec; 
    23232371    } 
    23242372 
     
    23272375    return PJ_SUCCESS; 
    23282376} 
     2377#endif 
     2378 
     2379 
    23292380/* 
    23302381 * Select or change sound device. Application may call this function at 
     
    23352386{ 
    23362387    pjmedia_port *conf_port; 
    2337     const pjmedia_snd_dev_info *play_info; 
     2388    pjmedia_aud_dev_info play_info; 
     2389    pjmedia_aud_param param; 
    23382390    unsigned clock_rates[] = {0, 44100, 48000, 32000, 16000, 8000}; 
    23392391    unsigned selected_clock_rate = 0; 
    23402392    unsigned i; 
    2341     pjmedia_snd_stream *strm; 
    2342     pjmedia_snd_stream_info si; 
     2393    pjmedia_aud_stream *strm; 
    23432394    pj_str_t tmp; 
    23442395    pj_status_t status = -1; 
     
    23532404 
    23542405    /* Create memory pool for sound device. */ 
    2355     pjsua_var.snd_pool = pjsua_pool_create("pjsua_snd", 4000, 4000); 
     2406    pjsua_var.snd_pool = pjsua_pool_create("pjsua_snd", 1000, 1000); 
    23562407    PJ_ASSERT_RETURN(pjsua_var.snd_pool, PJ_ENOMEM); 
    23572408 
     
    23652416    pj_assert(conf_port != NULL); 
    23662417 
     2418    /* Create default parameters for the device */ 
     2419    status = pjmedia_aud_dev_default_param(capture_dev, &param); 
     2420    if (status != PJ_SUCCESS) { 
     2421        return status; 
     2422    } 
     2423    param.dir = PJMEDIA_DIR_CAPTURE_PLAYBACK; 
     2424    param.rec_id = capture_dev; 
     2425    param.play_id = playback_dev; 
     2426    param.channel_count = pjsua_var.media_cfg.channel_count; 
     2427    /* Latency settings */ 
     2428    param.flags |= (PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY |  
     2429                    PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY); 
     2430    param.input_latency_ms = pjsua_var.media_cfg.snd_rec_latency; 
     2431    param.output_latency_ms = pjsua_var.media_cfg.snd_play_latency; 
     2432    /* EC settings */ 
     2433    if (pjsua_var.media_cfg.ec_tail_len) { 
     2434        param.flags |= (PJMEDIA_AUD_DEV_CAP_EC | PJMEDIA_AUD_DEV_CAP_EC_TAIL); 
     2435        param.ec_enabled = PJ_TRUE; 
     2436        param.ec_tail_ms = pjsua_var.media_cfg.ec_tail_len; 
     2437    } else { 
     2438        param.flags &= ~(PJMEDIA_AUD_DEV_CAP_EC | PJMEDIA_AUD_DEV_CAP_EC_TAIL); 
     2439    } 
     2440 
    23672441    /* Attempts to open the sound device with different clock rates */ 
    23682442    for (i=0; i<PJ_ARRAY_SIZE(clock_rates); ++i) { 
    23692443        char errmsg[PJ_ERR_MSG_SIZE]; 
    2370         unsigned samples_per_frame; 
    23712444 
    23722445        PJ_LOG(4,(THIS_FILE,  
     
    23742447                  "@%d Hz", clock_rates[i])); 
    23752448 
    2376         samples_per_frame = clock_rates[i] * 
    2377                             pjsua_var.media_cfg.audio_frame_ptime * 
    2378                             pjsua_var.media_cfg.channel_count / 1000; 
     2449        param.clock_rate = clock_rates[i]; 
     2450        param.samples_per_frame = clock_rates[i] * 
     2451                                  pjsua_var.media_cfg.audio_frame_ptime * 
     2452                                  pjsua_var.media_cfg.channel_count / 1000; 
    23792453 
    23802454        /* Create the sound device. Sound port will start immediately. */ 
    2381         status = pjmedia_snd_port_create(pjsua_var.snd_pool, capture_dev, 
    2382                                          playback_dev,  
    2383                                          clock_rates[i],  
    2384                                          pjsua_var.media_cfg.channel_count, 
    2385                                          samples_per_frame, 
    2386                                          16, 0, &pjsua_var.snd_port); 
     2455        status = pjmedia_snd_port_create2(pjsua_var.snd_pool, &param, 
     2456                                          &pjsua_var.snd_port); 
    23872457 
    23882458        if (status == PJ_SUCCESS) { 
     
    24382508    } 
    24392509 
    2440     /* Set AEC */ 
    2441     pjmedia_snd_port_set_ec( pjsua_var.snd_port, pjsua_var.snd_pool,  
    2442                              pjsua_var.media_cfg.ec_tail_len,  
    2443                              pjsua_var.media_cfg.ec_options); 
    2444  
    24452510    /* Connect sound port to the bridge */        
    24462511    status = pjmedia_snd_port_connect(pjsua_var.snd_port,         
     
    24602525    /* Update sound device name. */ 
    24612526    strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port); 
    2462     pjmedia_snd_stream_get_info(strm, &si); 
    2463     play_info = pjmedia_snd_get_dev_info(si.rec_id); 
    2464  
    2465     if (si.clock_rate != pjsua_var.media_cfg.clock_rate) { 
     2527    pjmedia_aud_stream_get_param(strm, &param); 
     2528    pjmedia_aud_dev_get_info(param.play_id, &play_info); 
     2529 
     2530    if (param.clock_rate != pjsua_var.media_cfg.clock_rate) { 
    24662531        char tmp_buf[128]; 
    24672532        int tmp_buf_len = sizeof(tmp_buf); 
    24682533 
    24692534        tmp_buf_len = pj_ansi_snprintf(tmp_buf, sizeof(tmp_buf)-1, "%s (%dKHz)", 
    2470                                        play_info->name, si.clock_rate/1000); 
     2535                                       play_info.name, param.clock_rate/1000); 
    24712536        pj_strset(&tmp, tmp_buf, tmp_buf_len); 
    24722537        pjmedia_conf_set_port0_name(pjsua_var.mconf, &tmp);  
    24732538    } else { 
    24742539        pjmedia_conf_set_port0_name(pjsua_var.mconf,  
    2475                                     pj_cstr(&tmp, play_info->name)); 
     2540                                    pj_cstr(&tmp, play_info.name)); 
    24762541    } 
    24772542 
     
    25802645} 
    25812646 
    2582 /*  
    2583  * Header for specific Symbian APS audio routing. 
    2584  */ 
    2585 #include <pjmedia/symbian_sound_aps.h> 
    2586  
    2587 /* 
    2588  * Set sound device route. 
    2589  */ 
    2590 PJ_DEF(pj_status_t) pjsua_set_snd_route(pjmedia_snd_route route) 
    2591 { 
    2592 #if PJMEDIA_SOUND_IMPLEMENTATION == PJMEDIA_SOUND_SYMB_APS_SOUND 
    2593     pjmedia_snd_stream *strm; 
    2594  
    2595     if (!pjsua_var.snd_port) 
    2596         return PJ_ENOTFOUND; 
    2597  
    2598     strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port); 
    2599     return pjmedia_snd_aps_set_route(strm, route); 
    2600 #else 
    2601     PJ_UNUSED_ARG(route); 
    2602     return PJ_ENOTSUP; 
    2603 #endif 
    2604 } 
    26052647 
    26062648/***************************************************************************** 
Note: See TracChangeset for help on using the changeset viewer.