sim.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /* $Id: simple_pjsua.c 3553 2011-05-05 06:14:19Z nanang $ */
  2. /*
  3. * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
  4. * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19. */
  20. #include <pjsua-lib/pjsua.h>
  21. #include <pjsip.h>
  22. #include <pjmedia.h>
  23. #include <pjlib.h>
  24. #include <stdlib.h> /* atoi() */
  25. #include <stdio.h>
  26. #include <math.h> /* sin() */
  27. #define THIS_FILE "APP"
  28. #define SIP_DOMAIN "sip.antisip.com"
  29. #define SIP_USER "melangtone"
  30. #define SIP_PASSWD "b8DU9AZXbd9tVCWg"
  31. /* Struct attached to sine generator */
  32. typedef struct {
  33. } port_data;
  34. pjmedia_port *sine_port;
  35. int slot;
  36. /* This callback is called to feed more samples */
  37. static pj_status_t sine_get_frame(pjmedia_port *port,
  38. pjmedia_frame *frame) {
  39. port_data *sine = port->port_data.pdata;
  40. pj_int16_t *samples = frame->buf;
  41. pj_size_t count;
  42. if (PJMEDIA_PIA_CCNT(&port->info) != 1) {
  43. //todo throw exception
  44. }
  45. /* Get number of samples */
  46. count = frame->size / 2 / PJMEDIA_PIA_CCNT(&port->info);
  47. for (int i = 0; i < count; ++i) {
  48. samples[i] = 10000.8 * (i % 10);
  49. }
  50. /* Must set frame->type correctly, otherwise the sound device
  51. * will refuse to play.
  52. */
  53. frame->type = PJMEDIA_FRAME_TYPE_AUDIO;
  54. return PJ_SUCCESS;
  55. }
  56. static pj_status_t sine_put_frame(pjmedia_port *port,
  57. pjmedia_frame *frame) {
  58. int sum = 0;
  59. pj_int16_t *samples = frame->buf;
  60. for (int i = 0; i < frame->size / 2; i++) {
  61. sum += samples[i];
  62. }
  63. printf("%d\n", sum);
  64. return PJ_SUCCESS;
  65. }
  66. /*
  67. * Create a media port to generate sine wave samples.
  68. */
  69. static pj_status_t create_sine_port(pj_pool_t *pool,
  70. unsigned sampling_rate,
  71. unsigned channel_count,
  72. pjmedia_port **p_port) {
  73. pjmedia_port *port;
  74. unsigned i;
  75. unsigned count;
  76. pj_str_t name;
  77. port_data *sine;
  78. PJ_ASSERT_RETURN(pool && channel_count > 0 && channel_count <= 2, PJ_EINVAL);
  79. port = pj_pool_zalloc(pool, sizeof(pjmedia_port));
  80. PJ_ASSERT_RETURN(port != NULL, PJ_ENOMEM);
  81. /* Fill in port info. */
  82. name = pj_str("sine generator");
  83. pjmedia_port_info_init(&port->info, &name,
  84. PJMEDIA_SIG_CLASS_PORT_AUD('s', 'i'),
  85. sampling_rate,
  86. 1,
  87. 16, sampling_rate * 20 / 1000 * 1);
  88. /* Set the function to feed frame */
  89. port->get_frame = &sine_get_frame;
  90. port->put_frame = &sine_put_frame;
  91. /* Create sine port data */
  92. port->port_data.pdata = sine = pj_pool_zalloc(pool, sizeof(port_data));
  93. *p_port = port;
  94. return PJ_SUCCESS;
  95. }
  96. /* Callback called by the library upon receiving incoming call */
  97. static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
  98. pjsip_rx_data *rdata) {
  99. pjsua_call_info ci;
  100. PJ_UNUSED_ARG(acc_id);
  101. PJ_UNUSED_ARG(rdata);
  102. pjsua_call_get_info(call_id, &ci);
  103. PJ_LOG(3, (THIS_FILE, "Incoming call from %.*s!!",
  104. (int) ci.remote_info.slen,
  105. ci.remote_info.ptr));
  106. /* Automatically answer incoming calls with 200/OK */
  107. pjsua_call_answer(call_id, 200, NULL, NULL);
  108. }
  109. /* Callback called by the library when call's state has changed */
  110. static void on_call_state(pjsua_call_id call_id, pjsip_event *e) {
  111. pjsua_call_info ci;
  112. PJ_UNUSED_ARG(e);
  113. pjsua_call_get_info(call_id, &ci);
  114. PJ_LOG(3, (THIS_FILE, "Call %d state=%.*s", call_id,
  115. (int) ci.state_text.slen,
  116. ci.state_text.ptr));
  117. }
  118. /* Callback called by the library when call's media state has changed */
  119. static void on_call_media_state(pjsua_call_id call_id) {
  120. pjsua_call_info ci;
  121. pjsua_call_get_info(call_id, &ci);
  122. if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
  123. // When media is active, connect call to sound device.
  124. pjsua_conf_connect(ci.conf_slot, slot);
  125. pjsua_conf_connect(slot, ci.conf_slot);
  126. }
  127. }
  128. /* Display error and exit application */
  129. static void error_exit(const char *title, pj_status_t status) {
  130. pjsua_perror(THIS_FILE, title, status);
  131. pjsua_destroy();
  132. exit(1);
  133. }
  134. /*
  135. * main()
  136. *
  137. * argv[1] may contain URL to call.
  138. */
  139. int main(int argc, char *argv[]) {
  140. pjsua_acc_id acc_id;
  141. pj_status_t status;
  142. pj_pool_t *pool;
  143. int channel_count = 1;
  144. /* Create pjsua first! */
  145. status = pjsua_create();
  146. if (status != PJ_SUCCESS) error_exit("Error in pjsua_create()", status);
  147. /* If argument is specified, it's got to be a valid SIP URL */
  148. if (argc > 1) {
  149. status = pjsua_verify_url(argv[1]);
  150. if (status != PJ_SUCCESS) error_exit("Invalid URL in argv", status);
  151. }
  152. /* Init pjsua */
  153. {
  154. pjsua_config cfg;
  155. pjsua_logging_config log_cfg;
  156. pjsua_config_default(&cfg);
  157. cfg.cb.on_incoming_call = &on_incoming_call;
  158. cfg.cb.on_call_media_state = &on_call_media_state;
  159. cfg.cb.on_call_state = &on_call_state;
  160. pjsua_logging_config_default(&log_cfg);
  161. log_cfg.console_level = 4;
  162. status = pjsua_init(&cfg, &log_cfg, NULL);
  163. if (status != PJ_SUCCESS) error_exit("Error in pjsua_init()", status);
  164. }
  165. /* Add UDP transport. */
  166. {
  167. pjsua_transport_config cfg;
  168. pjsua_transport_config_default(&cfg);
  169. cfg.port = 5060;
  170. status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &cfg, NULL);
  171. if (status != PJ_SUCCESS) error_exit("Error creating transport", status);
  172. }
  173. pj_caching_pool cp;
  174. pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
  175. pool = pj_pool_create(&cp.factory, /* pool factory */
  176. "wav", /* pool name. */
  177. 4000, /* init size */
  178. 4000, /* increment size */
  179. NULL /* callback on error */
  180. );
  181. status = create_sine_port(pool, /* memory pool */
  182. 8000, /* sampling rate */
  183. channel_count,/* # of channels */
  184. &sine_port /* returned port */
  185. );
  186. if (status != PJ_SUCCESS) {
  187. error_exit("Unable to create sine port", status);
  188. return 1;
  189. }
  190. pjsua_set_null_snd_dev();
  191. pjsua_conf_add_port(pool, sine_port, &slot);
  192. /* Initialization is done, now start pjsua */
  193. status = pjsua_start();
  194. if (status != PJ_SUCCESS) error_exit("Error starting pjsua", status);
  195. /* Register to SIP server by creating SIP account. */
  196. {
  197. pjsua_acc_config cfg;
  198. pjsua_acc_config_default(&cfg);
  199. cfg.id = pj_str("sip:" SIP_USER "@" SIP_DOMAIN);
  200. cfg.reg_uri = pj_str("sip:" SIP_DOMAIN);
  201. cfg.cred_count = 1;
  202. cfg.cred_info[0].realm = pj_str(SIP_DOMAIN);
  203. cfg.cred_info[0].scheme = pj_str("digest");
  204. cfg.cred_info[0].username = pj_str(SIP_USER);
  205. cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
  206. cfg.cred_info[0].data = pj_str(SIP_PASSWD);
  207. status = pjsua_acc_add(&cfg, PJ_TRUE, &acc_id);
  208. if (status != PJ_SUCCESS) error_exit("Error adding account", status);
  209. }
  210. /* Wait until user press "q" to quit. */
  211. for (; ;) {
  212. char option[10];
  213. puts("Press 'h' to hangup all calls, 'q' to quit");
  214. if (fgets(option, sizeof(option), stdin) == NULL) {
  215. puts("EOF while reading stdin, will quit now..");
  216. break;
  217. }
  218. if (option[0] == 'q')
  219. break;
  220. if (option[0] == 'h')
  221. pjsua_call_hangup_all();
  222. }
  223. /* Destroy pjsua */
  224. pjsua_destroy();
  225. return 0;
  226. }