From 14e7d7f5b4780e25c5cc924096bc862e04278ef2 Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Mon, 19 May 2014 05:51:10 +0000 Subject: Fixed #1767: Tone generation API in pjsua2 and SWIG wrappers git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@4845 74dad513-b988-da41-8d7b-12977e46ad98 --- pjsip-apps/src/swig/pjsua2.i | 3 + pjsip-apps/src/swig/python/test.py | 59 +++++++++++++- pjsip-apps/src/swig/symbols.i | 34 +++++++- pjsip-apps/src/swig/symbols.lst | 1 + pjsip/include/pjsua2/media.hpp | 139 +++++++++++++++++++++++++++++++ pjsip/src/pjsua2/media.cpp | 163 +++++++++++++++++++++++++++++++++++++ 6 files changed, 396 insertions(+), 3 deletions(-) diff --git a/pjsip-apps/src/swig/pjsua2.i b/pjsip-apps/src/swig/pjsua2.i index 2cc41d4a..aff740b4 100644 --- a/pjsip-apps/src/swig/pjsua2.i +++ b/pjsip-apps/src/swig/pjsua2.i @@ -94,6 +94,9 @@ using namespace pj; %template(SipMultipartPartVector) std::vector; %template(BuddyVector) std::vector; %template(AudioMediaVector) std::vector; +%template(ToneDescVector) std::vector; +%template(ToneDigitVector) std::vector; +%template(ToneDigitMapVector) std::vector; %template(MediaFormatVector) std::vector; %template(AudioDevInfoVector) std::vector; %template(CodecInfoVector) std::vector; diff --git a/pjsip-apps/src/swig/python/test.py b/pjsip-apps/src/swig/python/test.py index dc805c77..24801ed6 100644 --- a/pjsip-apps/src/swig/python/test.py +++ b/pjsip-apps/src/swig/python/test.py @@ -1,5 +1,6 @@ import pjsua2 as pj import sys +import time # # Basic data structure test, to make sure basic struct @@ -99,6 +100,61 @@ def ua_run_ua_test(): print "************* Endpoint started ok, now shutting down... *************" ep.libDestroy() +# +# Tone generator +# +def ua_tonegen_test(): + print "UA tonegen test.." + ep_cfg = pj.EpConfig() + + ep = pj.Endpoint() + ep.libCreate() + ep.libInit(ep_cfg) + ep.libStart() + + tonegen = pj.ToneGenerator() + tonegen.createToneGenerator() + + tone = pj.ToneDesc() + tone.freq1 = 400 + tone.freq2 = 600 + tone.on_msec = 1000 + tone.off_msec = 1000 + tones = pj.ToneDescVector() + tones.append(tone) + + digit = pj.ToneDigit() + digit.digit = '0' + digit.on_msec = 1000 + digit.off_msec = 1000 + digits = pj.ToneDigitVector() + digits.append(digit) + + adm = ep.audDevManager() + spk = adm.getPlaybackDevMedia() + + tonegen.play(tones, True) + tonegen.startTransmit(spk) + time.sleep(5) + + tonegen.stop() + tonegen.playDigits(digits, True) + time.sleep(5) + + dm = tonegen.getDigitMap() + print dm[0].digit + dm[0].freq1 = 400 + dm[0].freq2 = 600 + tonegen.setDigitMap(dm) + + tonegen.stop() + tonegen.playDigits(digits, True) + time.sleep(5) + + tonegen = None + + ep.libDestroy() + # # main() # @@ -107,6 +163,7 @@ if __name__ == "__main__": ua_run_test_exception() ua_run_log_test() ua_run_ua_test() + ua_tonegen_test() sys.exit(0) - \ No newline at end of file + diff --git a/pjsip-apps/src/swig/symbols.i b/pjsip-apps/src/swig/symbols.i index 79146006..1e37d729 100644 --- a/pjsip-apps/src/swig/symbols.i +++ b/pjsip-apps/src/swig/symbols.i @@ -1,4 +1,5 @@ // This file is autogenerated by importsym script, do not modify! + typedef int pj_status_t; enum pj_constants_ {PJ_SUCCESS = 0, PJ_TRUE = 1, PJ_FALSE = 0}; @@ -29,7 +30,7 @@ typedef struct pj_qos_params pj_qos_wmm_prio wmm_prio; } pj_qos_params; -typedef enum pj_ssl_cipher {PJ_TLS_NULL_WITH_NULL_NULL = 0x00000000, PJ_TLS_RSA_WITH_NULL_MD5 = 0x00000001, PJ_TLS_RSA_WITH_NULL_SHA = 0x00000002, PJ_TLS_RSA_WITH_NULL_SHA256 = 0x0000003B, PJ_TLS_RSA_WITH_RC4_128_MD5 = 0x00000004, PJ_TLS_RSA_WITH_RC4_128_SHA = 0x00000005, PJ_TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x0000000A, PJ_TLS_RSA_WITH_AES_128_CBC_SHA = 0x0000002F, PJ_TLS_RSA_WITH_AES_256_CBC_SHA = 0x00000035, PJ_TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x0000003C, PJ_TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x0000003D, PJ_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 0x0000000D, PJ_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 0x00000010, PJ_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x00000013, PJ_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x00000016, PJ_TLS_DH_DSS_WITH_AES_128_CBC_SHA = 0x00000030, PJ_TLS_DH_RSA_WITH_AES_128_CBC_SHA = 0x00000031, PJ_TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0x00000032, PJ_TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x00000033, PJ_TLS_DH_DSS_WITH_AES_256_CBC_SHA = 0x00000036, PJ_TLS_DH_RSA_WITH_AES_256_CBC_SHA = 0x00000037, PJ_TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0x00000038, PJ_TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x00000039, PJ_TLS_DH_DSS_WITH_AES_128_CBC_SHA256 = 0x0000003E, PJ_TLS_DH_RSA_WITH_AES_128_CBC_SHA256 = 0x0000003F, PJ_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 0x00000040, PJ_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x00000067, PJ_TLS_DH_DSS_WITH_AES_256_CBC_SHA256 = 0x00000068, PJ_TLS_DH_RSA_WITH_AES_256_CBC_SHA256 = 0x00000069, PJ_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 0x0000006A, PJ_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x0000006B, PJ_TLS_DH_anon_WITH_RC4_128_MD5 = 0x00000018, PJ_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = 0x0000001B, PJ_TLS_DH_anon_WITH_AES_128_CBC_SHA = 0x00000034, PJ_TLS_DH_anon_WITH_AES_256_CBC_SHA = 0x0000003A, PJ_TLS_DH_anon_WITH_AES_128_CBC_SHA256 = 0x0000006C, PJ_TLS_DH_anon_WITH_AES_256_CBC_SHA256 = 0x0000006D, PJ_TLS_RSA_EXPORT_WITH_RC4_40_MD5 = 0x00000003, PJ_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = 0x00000006, PJ_TLS_RSA_WITH_IDEA_CBC_SHA = 0x00000007, PJ_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x00000008, PJ_TLS_RSA_WITH_DES_CBC_SHA = 0x00000009, PJ_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x0000000B, PJ_TLS_DH_DSS_WITH_DES_CBC_SHA = 0x0000000C, PJ_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0000000E, PJ_TLS_DH_RSA_WITH_DES_CBC_SHA = 0x0000000F, PJ_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x00000011, PJ_TLS_DHE_DSS_WITH_DES_CBC_SHA = 0x00000012, PJ_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x00000014, PJ_TLS_DHE_RSA_WITH_DES_CBC_SHA = 0x00000015, PJ_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 = 0x00000017, PJ_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA = 0x00000019, PJ_TLS_DH_anon_WITH_DES_CBC_SHA = 0x0000001A, PJ_SSL_FORTEZZA_KEA_WITH_NULL_SHA = 0x0000001C, PJ_SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA = 0x0000001D, PJ_SSL_FORTEZZA_KEA_WITH_RC4_128_SHA = 0x0000001E, PJ_SSL_CK_RC4_128_WITH_MD5 = 0x00010080, PJ_SSL_CK_RC4_128_EXPORT40_WITH_MD5 = 0x00020080, PJ_SSL_CK_RC2_128_CBC_WITH_MD5 = 0x00030080, PJ_SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5 = 0x00040080, PJ_SSL_CK_IDEA_128_CBC_WITH_MD5 = 0x00050080, PJ_SSL_CK_DES_64_CBC_WITH_MD5 = 0x00060040, PJ_SSL_CK_DES_192_EDE3_CBC_WITH_MD5 = 0x000700C0} pj_ssl_cipher; +typedef enum pj_ssl_cipher {PJ_TLS_UNKNOWN_CIPHER = -1, PJ_TLS_NULL_WITH_NULL_NULL = 0x00000000, PJ_TLS_RSA_WITH_NULL_MD5 = 0x00000001, PJ_TLS_RSA_WITH_NULL_SHA = 0x00000002, PJ_TLS_RSA_WITH_NULL_SHA256 = 0x0000003B, PJ_TLS_RSA_WITH_RC4_128_MD5 = 0x00000004, PJ_TLS_RSA_WITH_RC4_128_SHA = 0x00000005, PJ_TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x0000000A, PJ_TLS_RSA_WITH_AES_128_CBC_SHA = 0x0000002F, PJ_TLS_RSA_WITH_AES_256_CBC_SHA = 0x00000035, PJ_TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x0000003C, PJ_TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x0000003D, PJ_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 0x0000000D, PJ_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 0x00000010, PJ_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x00000013, PJ_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x00000016, PJ_TLS_DH_DSS_WITH_AES_128_CBC_SHA = 0x00000030, PJ_TLS_DH_RSA_WITH_AES_128_CBC_SHA = 0x00000031, PJ_TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0x00000032, PJ_TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x00000033, PJ_TLS_DH_DSS_WITH_AES_256_CBC_SHA = 0x00000036, PJ_TLS_DH_RSA_WITH_AES_256_CBC_SHA = 0x00000037, PJ_TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0x00000038, PJ_TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x00000039, PJ_TLS_DH_DSS_WITH_AES_128_CBC_SHA256 = 0x0000003E, PJ_TLS_DH_RSA_WITH_AES_128_CBC_SHA256 = 0x0000003F, PJ_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 0x00000040, PJ_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x00000067, PJ_TLS_DH_DSS_WITH_AES_256_CBC_SHA256 = 0x00000068, PJ_TLS_DH_RSA_WITH_AES_256_CBC_SHA256 = 0x00000069, PJ_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 0x0000006A, PJ_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x0000006B, PJ_TLS_DH_anon_WITH_RC4_128_MD5 = 0x00000018, PJ_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = 0x0000001B, PJ_TLS_DH_anon_WITH_AES_128_CBC_SHA = 0x00000034, PJ_TLS_DH_anon_WITH_AES_256_CBC_SHA = 0x0000003A, PJ_TLS_DH_anon_WITH_AES_128_CBC_SHA256 = 0x0000006C, PJ_TLS_DH_anon_WITH_AES_256_CBC_SHA256 = 0x0000006D, PJ_TLS_RSA_EXPORT_WITH_RC4_40_MD5 = 0x00000003, PJ_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = 0x00000006, PJ_TLS_RSA_WITH_IDEA_CBC_SHA = 0x00000007, PJ_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x00000008, PJ_TLS_RSA_WITH_DES_CBC_SHA = 0x00000009, PJ_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x0000000B, PJ_TLS_DH_DSS_WITH_DES_CBC_SHA = 0x0000000C, PJ_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0000000E, PJ_TLS_DH_RSA_WITH_DES_CBC_SHA = 0x0000000F, PJ_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x00000011, PJ_TLS_DHE_DSS_WITH_DES_CBC_SHA = 0x00000012, PJ_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x00000014, PJ_TLS_DHE_RSA_WITH_DES_CBC_SHA = 0x00000015, PJ_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 = 0x00000017, PJ_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA = 0x00000019, PJ_TLS_DH_anon_WITH_DES_CBC_SHA = 0x0000001A, PJ_SSL_FORTEZZA_KEA_WITH_NULL_SHA = 0x0000001C, PJ_SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA = 0x0000001D, PJ_SSL_FORTEZZA_KEA_WITH_RC4_128_SHA = 0x0000001E, PJ_SSL_CK_RC4_128_WITH_MD5 = 0x00010080, PJ_SSL_CK_RC4_128_EXPORT40_WITH_MD5 = 0x00020080, PJ_SSL_CK_RC2_128_CBC_WITH_MD5 = 0x00030080, PJ_SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5 = 0x00040080, PJ_SSL_CK_IDEA_128_CBC_WITH_MD5 = 0x00050080, PJ_SSL_CK_DES_64_CBC_WITH_MD5 = 0x00060040, PJ_SSL_CK_DES_192_EDE3_CBC_WITH_MD5 = 0x000700C0} pj_ssl_cipher; typedef enum pj_stun_nat_type {PJ_STUN_NAT_TYPE_UNKNOWN, PJ_STUN_NAT_TYPE_ERR_UNKNOWN, PJ_STUN_NAT_TYPE_OPEN, PJ_STUN_NAT_TYPE_BLOCKED, PJ_STUN_NAT_TYPE_SYMMETRIC_UDP, PJ_STUN_NAT_TYPE_FULL_CONE, PJ_STUN_NAT_TYPE_SYMMETRIC, PJ_STUN_NAT_TYPE_RESTRICTED, PJ_STUN_NAT_TYPE_PORT_RESTRICTED} pj_stun_nat_type; @@ -53,6 +54,35 @@ enum pjmedia_file_writer_option {PJMEDIA_FILE_WRITE_PCM = 0, PJMEDIA_FILE_WRITE_ enum pjmedia_file_player_option {PJMEDIA_FILE_NO_LOOP = 1}; +typedef struct pjmedia_tone_digit +{ + char digit; + short on_msec; + short off_msec; + short volume; +} pjmedia_tone_digit; + +typedef struct pjmedia_tone_digit_map +{ + unsigned count; + struct + { + char digit; + short freq1; + short freq2; + } digits[16]; +} pjmedia_tone_digit_map; + +typedef struct pjmedia_tone_desc +{ + short freq1; + short freq2; + short on_msec; + short off_msec; + short volume; + short flags; +} pjmedia_tone_desc; + typedef enum pjmedia_type {PJMEDIA_TYPE_NONE, PJMEDIA_TYPE_AUDIO, PJMEDIA_TYPE_VIDEO, PJMEDIA_TYPE_APPLICATION, PJMEDIA_TYPE_UNKNOWN} pjmedia_type; typedef enum pjmedia_dir {PJMEDIA_DIR_NONE = 0, PJMEDIA_DIR_ENCODING = 1, PJMEDIA_DIR_CAPTURE = PJMEDIA_DIR_ENCODING, PJMEDIA_DIR_DECODING = 2, PJMEDIA_DIR_PLAYBACK = PJMEDIA_DIR_DECODING, PJMEDIA_DIR_RENDER = PJMEDIA_DIR_DECODING, PJMEDIA_DIR_ENCODING_DECODING = 3, PJMEDIA_DIR_CAPTURE_PLAYBACK = PJMEDIA_DIR_ENCODING_DECODING, PJMEDIA_DIR_CAPTURE_RENDER = PJMEDIA_DIR_ENCODING_DECODING} pjmedia_dir; @@ -75,7 +105,7 @@ typedef enum pjsip_transport_type_e {PJSIP_TRANSPORT_UNSPECIFIED, PJSIP_TRANSPOR enum pjsip_transport_flags_e {PJSIP_TRANSPORT_RELIABLE = 1, PJSIP_TRANSPORT_SECURE = 2, PJSIP_TRANSPORT_DATAGRAM = 4}; -typedef enum pjsip_transport_state {PJSIP_TP_STATE_CONNECTED, PJSIP_TP_STATE_DISCONNECTED} pjsip_transport_state; +typedef enum pjsip_transport_state {PJSIP_TP_STATE_CONNECTED, PJSIP_TP_STATE_DISCONNECTED, PJSIP_TP_STATE_SHUTDOWN, PJSIP_TP_STATE_DESTROY} pjsip_transport_state; typedef enum pjsip_ssl_method {PJSIP_SSL_UNSPECIFIED_METHOD = 0, PJSIP_TLSV1_METHOD = 31, PJSIP_SSLV2_METHOD = 20, PJSIP_SSLV3_METHOD = 30, PJSIP_SSLV23_METHOD = 23} pjsip_ssl_method; diff --git a/pjsip-apps/src/swig/symbols.lst b/pjsip-apps/src/swig/symbols.lst index 685c3713..b5e7b6e2 100644 --- a/pjsip-apps/src/swig/symbols.lst +++ b/pjsip-apps/src/swig/symbols.lst @@ -13,6 +13,7 @@ pjmedia/vid_stream.h pjmedia_vid_stream_rc_method pjmedia-videodev/videodev.h pjmedia_vid_dev_index pjmedia_vid_dev_std_index pjmedia-audiodev/audiodev.h pjmedia_aud_dev_route pjmedia_aud_dev_cap pjmedia/wav_port.h pjmedia_file_writer_option pjmedia_file_player_option +pjmedia/tonegen.h pjmedia_tone_digit pjmedia_tone_digit_map pjmedia_tone_desc pjmedia/types.h pjmedia_type pjmedia_dir pjmedia_tp_proto pjmedia/format.h pjmedia_format_id diff --git a/pjsip/include/pjsua2/media.hpp b/pjsip/include/pjsua2/media.hpp index 2f3a6855..99dd532e 100644 --- a/pjsip/include/pjsua2/media.hpp +++ b/pjsip/include/pjsua2/media.hpp @@ -511,6 +511,145 @@ private: int recorderId; }; +/** + * Tone descriptor (abstraction for pjmedia_tone_desc) + */ +class ToneDesc : public pjmedia_tone_desc +{ +public: + ToneDesc() + { + pj_bzero(this, sizeof(*this)); + } + ~ToneDesc() {} +}; + +/** + * Array of tone descriptor. + */ +typedef std::vector ToneDescVector; + +/** + * Tone digit (abstraction for pjmedia_tone_digit) + */ +class ToneDigit : public pjmedia_tone_digit +{ +public: + ToneDigit() + { + pj_bzero(this, sizeof(*this)); + } + ~ToneDigit() {} +}; + +/** + * Array of tone digits. + */ +typedef std::vector ToneDigitVector; + +/** + * A digit in tone digit map + */ +struct ToneDigitMapDigit +{ +public: + string digit; + int freq1; + int freq2; +}; + +/** + * Tone digit map + */ +typedef std::vector ToneDigitMapVector; + +/** + * Tone generator. + */ +class ToneGenerator : public AudioMedia +{ +public: + /** + * Constructor. + */ + ToneGenerator(); + + /** + * Destructor. + */ + ~ToneGenerator(); + + /** + * Create tone generator. + */ + void createToneGenerator(unsigned clock_rate = 16000, + unsigned channel_count = 1) throw(Error); + + /** + * Check if the tone generator is still busy producing some tones. + * @return Non-zero if busy. + */ + bool isBusy() const; + + /** + * Instruct the tone generator to stop current processing. + */ + void stop() throw(Error); + + /** + * Rewind the playback. This will start the playback to the first + * tone in the playback list. + */ + void rewind() throw(Error); + + /** + * Instruct the tone generator to play single or dual frequency tones + * with the specified duration. The new tones will be appended to + * currently playing tones, unless stop() is called before calling this + * function. The playback will begin as soon as the tone generator is + * connected to other media. + * + * @param tones Array of tones to be played. + * @param loop Play the tone in a loop. + */ + void play(const ToneDescVector &tones, + bool loop=false) throw(Error); + + /** + * Instruct the tone generator to play multiple MF digits with each of + * the digits having individual ON/OFF duration. Each of the digit in the + * digit array must have the corresponding descriptor in the digit map. + * The new tones will be appended to currently playing tones, unless + * stop() is called before calling this function. The playback will begin + * as soon as the tone generator is connected to a sink media. + * + * @param digits Array of MF digits. + * @param loop Play the tone in a loop. + */ + void playDigits(const ToneDigitVector &digits, + bool loop=false) throw(Error); + + /** + * Get the digit-map currently used by this tone generator. + * + * @return The digitmap currently used by the tone generator + */ + ToneDigitMapVector getDigitMap() const throw(Error); + + /** + * Set digit map to be used by the tone generator. + * + * @param digit_map Digitmap to be used by the tone generator. + */ + void setDigitMap(const ToneDigitMapVector &digit_map) throw(Error); + +private: + pj_pool_t *pool; + pjmedia_port *tonegen; + pjmedia_tone_digit_map digitMap; +}; + + /************************************************************************* * Sound device management */ diff --git a/pjsip/src/pjsua2/media.cpp b/pjsip/src/pjsua2/media.cpp index a6255ec2..5b149312 100644 --- a/pjsip/src/pjsua2/media.cpp +++ b/pjsip/src/pjsua2/media.cpp @@ -422,6 +422,169 @@ AudioMediaRecorder* AudioMediaRecorder::typecastFromAudioMedia( return static_cast(media); } +/////////////////////////////////////////////////////////////////////////////// + +ToneGenerator::ToneGenerator() +: pool(NULL), tonegen(NULL) +{ +} + +ToneGenerator::~ToneGenerator() +{ + if (tonegen) { + unregisterMediaPort(); + pjmedia_port_destroy(tonegen); + tonegen = NULL; + } + if (pool) { + pj_pool_release(pool); + pool = NULL; + } +} + +void ToneGenerator::createToneGenerator(unsigned clock_rate, + unsigned channel_count) throw(Error) +{ + pj_status_t status; + + if (pool) { + PJSUA2_RAISE_ERROR(PJ_EEXISTS); + } + + pool = pjsua_pool_create( "tonegen%p", 512, 512); + if (!pool) { + PJSUA2_RAISE_ERROR(PJ_ENOMEM); + } + + status = pjmedia_tonegen_create( pool, clock_rate, channel_count, + clock_rate * 20 / 1000, 16, + 0, &tonegen); + if (status != PJ_SUCCESS) { + PJSUA2_RAISE_ERROR(status); + } + + registerMediaPort(tonegen); +} + +bool ToneGenerator::isBusy() const +{ + return tonegen && pjmedia_tonegen_is_busy(tonegen) != 0; +} + +void ToneGenerator::stop() throw(Error) +{ + pj_status_t status; + + if (!tonegen) { + PJSUA2_RAISE_ERROR(PJ_EINVALIDOP); + } + + status = pjmedia_tonegen_stop(tonegen); + PJSUA2_CHECK_RAISE_ERROR2(status, "ToneGenerator::stop()"); +} + +void ToneGenerator::rewind() throw(Error) +{ + pj_status_t status; + + if (!tonegen) { + PJSUA2_RAISE_ERROR(PJ_EINVALIDOP); + } + + status = pjmedia_tonegen_rewind(tonegen); + PJSUA2_CHECK_RAISE_ERROR2(status, "ToneGenerator::rewind()"); +} + +void ToneGenerator::play(const ToneDescVector &tones, + bool loop) throw(Error) +{ + pj_status_t status; + + if (!tonegen) { + PJSUA2_RAISE_ERROR(PJ_EINVALIDOP); + } + if (tones.size() == 0) { + PJSUA2_RAISE_ERROR(PJ_EINVAL); + } + + status = pjmedia_tonegen_play(tonegen, tones.size(), &tones[0], + loop? PJMEDIA_TONEGEN_LOOP : 0); + PJSUA2_CHECK_RAISE_ERROR2(status, "ToneGenerator::play()"); +} + +void ToneGenerator::playDigits(const ToneDigitVector &digits, + bool loop) throw(Error) +{ + pj_status_t status; + + if (!tonegen) { + PJSUA2_RAISE_ERROR(PJ_EINVALIDOP); + } + if (digits.size() == 0) { + PJSUA2_RAISE_ERROR(PJ_EINVAL); + } + + status = pjmedia_tonegen_play_digits(tonegen, digits.size(), &digits[0], + loop? PJMEDIA_TONEGEN_LOOP : 0); + PJSUA2_CHECK_RAISE_ERROR2(status, "ToneGenerator::playDigits()"); +} + +ToneDigitMapVector ToneGenerator::getDigitMap() const throw(Error) +{ + const pjmedia_tone_digit_map *pdm; + ToneDigitMapVector tdm; + unsigned i; + pj_status_t status; + + if (!tonegen) { + PJSUA2_RAISE_ERROR(PJ_EINVALIDOP); + } + + status = pjmedia_tonegen_get_digit_map(tonegen, &pdm); + PJSUA2_CHECK_RAISE_ERROR2(status, "ToneGenerator::getDigitMap()"); + + for (i=0; icount; ++i) { + ToneDigitMapDigit d; + char str_digit[2]; + + str_digit[0] = pdm->digits[i].digit; + str_digit[1] = '\0'; + + d.digit = str_digit; + d.freq1 = pdm->digits[i].freq1; + d.freq2 = pdm->digits[i].freq2; + + tdm.push_back(d); + } + + return tdm; +} + +void ToneGenerator::setDigitMap(const ToneDigitMapVector &digit_map) + throw(Error) +{ + unsigned i; + pj_status_t status; + + if (!tonegen) { + PJSUA2_RAISE_ERROR(PJ_EINVALIDOP); + } + + digitMap.count = digit_map.size(); + if (digitMap.count > PJ_ARRAY_SIZE(digitMap.digits)) + digitMap.count = PJ_ARRAY_SIZE(digitMap.digits); + + for (i=0; i