app_morsecode.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (c) 2006, Tilghman Lesher. All rights reserved.
  5. *
  6. * Updated by Naveen Albert <asterisk@phreaknet.org>
  7. *
  8. * Tilghman Lesher <app_morsecode__v001@the-tilghman.com>
  9. *
  10. * This code is released by the author with no restrictions on usage.
  11. *
  12. * See http://www.asterisk.org for more information about
  13. * the Asterisk project. Please do not directly contact
  14. * any of the maintainers of this project for assistance;
  15. * the project provides a web site, mailing lists and IRC
  16. * channels for your use.
  17. *
  18. */
  19. /*! \file
  20. *
  21. * \brief Morsecode application
  22. *
  23. * \author Tilghman Lesher <app_morsecode__v001@the-tilghman.com>
  24. * \author Naveen Albert <asterisk@phreaknet.org>
  25. *
  26. * \ingroup applications
  27. */
  28. /*** MODULEINFO
  29. <support_level>extended</support_level>
  30. ***/
  31. #include "asterisk.h"
  32. #include "asterisk/file.h"
  33. #include "asterisk/channel.h"
  34. #include "asterisk/pbx.h"
  35. #include "asterisk/module.h"
  36. #include "asterisk/indications.h"
  37. /*** DOCUMENTATION
  38. <application name="Morsecode" language="en_US">
  39. <synopsis>
  40. Plays morse code.
  41. </synopsis>
  42. <syntax>
  43. <parameter name="string" required="true">
  44. <para>String to playback as morse code to channel</para>
  45. </parameter>
  46. </syntax>
  47. <description>
  48. <para>Plays the Morse code equivalent of the passed string.</para>
  49. <para>This application does not automatically answer and should be preceeded by
  50. an application such as Answer() or Progress().</para>
  51. <para>This application uses the following variables:</para>
  52. <variablelist>
  53. <variable name="MORSEDITLEN">
  54. <para>Use this value in (ms) for length of dit</para>
  55. </variable>
  56. <variable name="MORSETONE">
  57. <para>The pitch of the tone in (Hz), default is 800</para>
  58. </variable>
  59. <variable name="MORSESPACETONE">
  60. <para>The pitch of the spaces in (Hz), default is 0</para>
  61. </variable>
  62. <variable name="MORSETYPE">
  63. <para>The code type to use (AMERICAN for standard American Morse
  64. or INTERNATIONAL for international code.
  65. Default is INTERNATIONAL).</para>
  66. </variable>
  67. </variablelist>
  68. </description>
  69. <see-also>
  70. <ref type="application">SayAlpha</ref>
  71. <ref type="application">SayPhonetic</ref>
  72. </see-also>
  73. </application>
  74. ***/
  75. static const char app_morsecode[] = "Morsecode";
  76. static const char * const internationalcode[] = {
  77. "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /* 0-15 */
  78. "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /* 16-31 */
  79. " ", /* 32 - <space> */
  80. ".-.-.-", /* 33 - ! */
  81. ".-..-.", /* 34 - " */
  82. "", /* 35 - # */
  83. "", /* 36 - $ */
  84. "", /* 37 - % */
  85. "", /* 38 - & */
  86. ".----.", /* 39 - ' */
  87. "-.--.-", /* 40 - ( */
  88. "-.--.-", /* 41 - ) */
  89. "", /* 42 - * */
  90. "", /* 43 - + */
  91. "--..--", /* 44 - , */
  92. "-....-", /* 45 - - */
  93. ".-.-.-", /* 46 - . */
  94. "-..-.", /* 47 - / */
  95. "-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----.", /* 48-57 - 0-9 */
  96. "---...", /* 58 - : */
  97. "-.-.-.", /* 59 - ; */
  98. "", /* 60 - < */
  99. "-...-", /* 61 - = */
  100. "", /* 62 - > */
  101. "..--..", /* 63 - ? */
  102. ".--.-.", /* 64 - @ */
  103. ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", /* A-M */
  104. "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", /* N-Z */
  105. "-.--.-", /* 91 - [ (really '(') */
  106. "-..-.", /* 92 - \ (really '/') */
  107. "-.--.-", /* 93 - ] (really ')') */
  108. "", /* 94 - ^ */
  109. "..--.-", /* 95 - _ */
  110. ".----.", /* 96 - ` */
  111. ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", /* a-m */
  112. "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", /* n-z */
  113. "-.--.-", /* 123 - { (really '(') */
  114. "", /* 124 - | */
  115. "-.--.-", /* 125 - } (really ')') */
  116. "-..-.", /* 126 - ~ (really bar) */
  117. ". . .", /* 127 - <del> (error) */
  118. };
  119. static const char * const americanmorsecode[] = {
  120. "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /* 0-15 */
  121. "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /* 16-31 */
  122. " ", /* 32 - <space> */
  123. "---.", /* 33 - ! */
  124. "..-. -.",/* 34 - " (QN)*/
  125. "", /* 35 - # */
  126. "... .-..",/* 36 - $ (SX) */
  127. "", /* 37 - % */
  128. ". ...", /* 38 - & (ES) */
  129. "..-. .-..",/* 39 - ' (QX) */
  130. "..... -.", /* 40 - ( (PN) */
  131. "..... .. ..", /* 41 - ) (PY) */
  132. "", /* 42 - * */
  133. "", /* 43 - + */
  134. ".-.-", /* 44 - , */
  135. ".... .-..",/* 45 - (HX) */
  136. "..--..", /* 46 - . */
  137. "..- -", /* 47 - / (UT) */
  138. ".--.", "..-..", "...-.", "....-", "---", "......", "--..", "-....", "-..-", "0", /* 48-57 - 0-9 */
  139. "-.- . .",/* 58 - : (KO) */
  140. "... ..", /* 59 - ; */
  141. "", /* 60 - < */
  142. "-...-", /* 61 - = (paragraph mark) */
  143. "", /* 62 - > */
  144. "-..-.", /* 63 - ? */
  145. ".--.-.", /* 64 - @ */
  146. ".-", "-...", ".. .", "-..", ".", ".-.", "--.", "....", "..", ".-.-", "-.-", "L", "--", /* A-M */
  147. "-.", ". .", ".....", "..-.", ". ..", "...", "-", "..-", "...-", ".--", ".-..", ".. ..", "... .", /* N-Z */
  148. "..... -.", /* 91 - [ (really '(') */
  149. "..- -", /* 92 - \ (really '/') */
  150. "..... .. ..", /* 93 - ] (really ')') */
  151. "", /* 94 - ^ */
  152. "..--.-", /* 95 - _ */
  153. ".----.", /* 96 - ` */
  154. ".-", "-...", ".. .", "-..", ".", ".-.", "--.", "....", "..", ".-.-", "-.-", "L", "--", /* a-m */
  155. "-.", ". .", ".....", "..-.", ". ..", "...", "-", "..-", "...-", ".--", ".-..", ".. ..", "... .", /* n-z */
  156. "..... -.", /* 123 - { (really '(') */
  157. "", /* 124 - | */
  158. "..... .. ..", /* 125 - } (really ')') */
  159. "..- -", /* 126 - ~ (really bar) */
  160. ". . .", /* 127 - <del> (error) */
  161. };
  162. static int playtone(struct ast_channel *chan, int tone, int len)
  163. {
  164. int res;
  165. char dtmf[20];
  166. snprintf(dtmf, sizeof(dtmf), "%d/%d", tone, len);
  167. ast_playtones_start(chan, 0, dtmf, 0);
  168. res = ast_safe_sleep(chan, len);
  169. ast_playtones_stop(chan);
  170. return res;
  171. }
  172. static int morsecode_exec(struct ast_channel *chan, const char *data)
  173. {
  174. int res = 0, ditlen, tone, toneoff, digit2;
  175. const char *digit;
  176. const char *ditlenc, *tonec, *toneb, *codetype;
  177. if (ast_strlen_zero(data)) {
  178. ast_log(LOG_WARNING, "Syntax: Morsecode(<string>) - no argument found\n");
  179. return 0;
  180. }
  181. ast_channel_lock(chan);
  182. /* Use variable MORESEDITLEN, if set (else 80) */
  183. ditlenc = pbx_builtin_getvar_helper(chan, "MORSEDITLEN");
  184. if (ast_strlen_zero(ditlenc) || (sscanf(ditlenc, "%30d", &ditlen) != 1)) {
  185. ditlen = 80;
  186. }
  187. /* Use variable MORSETONE, if set (else 800) */
  188. tonec = pbx_builtin_getvar_helper(chan, "MORSETONE");
  189. if (ast_strlen_zero(tonec) || (sscanf(tonec, "%30d", &tone) != 1)) {
  190. tone = 800;
  191. }
  192. /* Use variable MORSESPACETONE, if set (else 0) */
  193. toneb = pbx_builtin_getvar_helper(chan, "MORSESPACETONE");
  194. if (ast_strlen_zero(toneb) || (sscanf(toneb, "%30d", &toneoff) != 1)) {
  195. toneoff = 0;
  196. }
  197. /* Use variable MORSETYPE, if set (else INTERNATIONAL) */
  198. codetype = pbx_builtin_getvar_helper(chan, "MORSETYPE");
  199. if (!codetype || strcmp(codetype, "AMERICAN")) {
  200. codetype = "INTERNATIONAL";
  201. }
  202. ast_channel_unlock(chan);
  203. if (!strcmp(codetype, "AMERICAN")) {
  204. for (digit = data; *digit; digit++) {
  205. const char *dahdit;
  206. digit2 = *digit;
  207. if (digit2 < 0 || digit2 > 127) {
  208. continue;
  209. }
  210. for (dahdit = americanmorsecode[digit2]; *dahdit; dahdit++) {
  211. if (*dahdit == '-') {
  212. res = playtone(chan, tone, 3 * ditlen);
  213. } else if (*dahdit == '.') {
  214. res = playtone(chan, tone, 1 * ditlen);
  215. } else if (*dahdit == 'L' || *dahdit == 'l') {
  216. res = playtone(chan, tone, 6 * ditlen); /* long dash */
  217. } else if (*dahdit == '0') {
  218. res = playtone(chan, tone, 9 * ditlen); /* extra long dash */
  219. } else if (*dahdit == ' ') { /* space char (x20) = 6 dot lengths */
  220. /* Intra-char pauses, specific to American Morse */
  221. res = playtone(chan, toneoff, 3 * ditlen);
  222. } else {
  223. /* Account for ditlen of silence immediately following */
  224. res = playtone(chan, toneoff, 2 * ditlen);
  225. }
  226. /* Pause slightly between each dit and dah */
  227. res = playtone(chan, toneoff, 1 * ditlen);
  228. if (res)
  229. break;
  230. }
  231. /* Pause between characters */
  232. res = playtone(chan, toneoff, 3 * ditlen);
  233. if (res)
  234. break;
  235. }
  236. } else { /* International */
  237. for (digit = data; *digit; digit++) {
  238. const char *dahdit;
  239. digit2 = *digit;
  240. if (digit2 < 0 || digit2 > 127) {
  241. continue;
  242. }
  243. for (dahdit = internationalcode[digit2]; *dahdit; dahdit++) {
  244. if (*dahdit == '-') {
  245. res = playtone(chan, tone, 3 * ditlen);
  246. } else if (*dahdit == '.') {
  247. res = playtone(chan, tone, 1 * ditlen);
  248. } else {
  249. /* Account for ditlen of silence immediately following */
  250. res = playtone(chan, toneoff, 2 * ditlen);
  251. }
  252. /* Pause slightly between each dit and dah */
  253. res = playtone(chan, toneoff, 1 * ditlen);
  254. if (res)
  255. break;
  256. }
  257. /* Pause between characters */
  258. res = playtone(chan, toneoff, 2 * ditlen);
  259. if (res)
  260. break;
  261. }
  262. }
  263. return res;
  264. }
  265. static int unload_module(void)
  266. {
  267. return ast_unregister_application(app_morsecode);
  268. }
  269. static int load_module(void)
  270. {
  271. return ast_register_application_xml(app_morsecode, morsecode_exec);
  272. }
  273. AST_MODULE_INFO_STANDARD_EXTENDED(ASTERISK_GPL_KEY, "Morse code");