Asterisk - The Open Source Telephony Project  21.4.1
app_morsecode.c
Go to the documentation of this file.
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 
20 /*! \file
21  *
22  * \brief Morsecode application
23  *
24  * \author Tilghman Lesher <app_morsecode__v001@the-tilghman.com>
25  * \author Naveen Albert <asterisk@phreaknet.org>
26  *
27  * \ingroup applications
28  */
29 
30 /*** MODULEINFO
31  <support_level>extended</support_level>
32  ***/
33 
34 #include "asterisk.h"
35 
36 #include "asterisk/file.h"
37 #include "asterisk/channel.h"
38 #include "asterisk/pbx.h"
39 #include "asterisk/module.h"
40 #include "asterisk/indications.h"
41 
42 /*** DOCUMENTATION
43  <application name="Morsecode" language="en_US">
44  <synopsis>
45  Plays morse code.
46  </synopsis>
47  <syntax>
48  <parameter name="string" required="true">
49  <para>String to playback as morse code to channel</para>
50  </parameter>
51  </syntax>
52  <description>
53  <para>Plays the Morse code equivalent of the passed string.</para>
54  <para>This application does not automatically answer and should be preceeded by
55  an application such as Answer() or Progress().</para>
56  <para>This application uses the following variables:</para>
57  <variablelist>
58  <variable name="MORSEDITLEN">
59  <para>Use this value in (ms) for length of dit</para>
60  </variable>
61  <variable name="MORSETONE">
62  <para>The pitch of the tone in (Hz), default is 800</para>
63  </variable>
64  <variable name="MORSESPACETONE">
65  <para>The pitch of the spaces in (Hz), default is 0</para>
66  </variable>
67  <variable name="MORSETYPE">
68  <para>The code type to use (AMERICAN for standard American Morse
69  or INTERNATIONAL for international code.
70  Default is INTERNATIONAL).</para>
71  </variable>
72  </variablelist>
73  </description>
74  <see-also>
75  <ref type="application">SayAlpha</ref>
76  <ref type="application">SayPhonetic</ref>
77  </see-also>
78  </application>
79  ***/
80 static const char app_morsecode[] = "Morsecode";
81 
82 static const char * const internationalcode[] = {
83  "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /* 0-15 */
84  "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /* 16-31 */
85  " ", /* 32 - <space> */
86  ".-.-.-", /* 33 - ! */
87  ".-..-.", /* 34 - " */
88  "", /* 35 - # */
89  "", /* 36 - $ */
90  "", /* 37 - % */
91  "", /* 38 - & */
92  ".----.", /* 39 - ' */
93  "-.--.-", /* 40 - ( */
94  "-.--.-", /* 41 - ) */
95  "", /* 42 - * */
96  "", /* 43 - + */
97  "--..--", /* 44 - , */
98  "-....-", /* 45 - - */
99  ".-.-.-", /* 46 - . */
100  "-..-.", /* 47 - / */
101  "-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----.", /* 48-57 - 0-9 */
102  "---...", /* 58 - : */
103  "-.-.-.", /* 59 - ; */
104  "", /* 60 - < */
105  "-...-", /* 61 - = */
106  "", /* 62 - > */
107  "..--..", /* 63 - ? */
108  ".--.-.", /* 64 - @ */
109  ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", /* A-M */
110  "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", /* N-Z */
111  "-.--.-", /* 91 - [ (really '(') */
112  "-..-.", /* 92 - \ (really '/') */
113  "-.--.-", /* 93 - ] (really ')') */
114  "", /* 94 - ^ */
115  "..--.-", /* 95 - _ */
116  ".----.", /* 96 - ` */
117  ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", /* a-m */
118  "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", /* n-z */
119  "-.--.-", /* 123 - { (really '(') */
120  "", /* 124 - | */
121  "-.--.-", /* 125 - } (really ')') */
122  "-..-.", /* 126 - ~ (really bar) */
123  ". . .", /* 127 - <del> (error) */
124 };
125 
126 static const char * const americanmorsecode[] = {
127  "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /* 0-15 */
128  "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /* 16-31 */
129  " ", /* 32 - <space> */
130  "---.", /* 33 - ! */
131  "..-. -.",/* 34 - " (QN)*/
132  "", /* 35 - # */
133  "... .-..",/* 36 - $ (SX) */
134  "", /* 37 - % */
135  ". ...", /* 38 - & (ES) */
136  "..-. .-..",/* 39 - ' (QX) */
137  "..... -.", /* 40 - ( (PN) */
138  "..... .. ..", /* 41 - ) (PY) */
139  "", /* 42 - * */
140  "", /* 43 - + */
141  ".-.-", /* 44 - , */
142  ".... .-..",/* 45 - (HX) */
143  "..--..", /* 46 - . */
144  "..- -", /* 47 - / (UT) */
145  ".--.", "..-..", "...-.", "....-", "---", "......", "--..", "-....", "-..-", "0", /* 48-57 - 0-9 */
146  "-.- . .",/* 58 - : (KO) */
147  "... ..", /* 59 - ; */
148  "", /* 60 - < */
149  "-...-", /* 61 - = (paragraph mark) */
150  "", /* 62 - > */
151  "-..-.", /* 63 - ? */
152  ".--.-.", /* 64 - @ */
153  ".-", "-...", ".. .", "-..", ".", ".-.", "--.", "....", "..", ".-.-", "-.-", "L", "--", /* A-M */
154  "-.", ". .", ".....", "..-.", ". ..", "...", "-", "..-", "...-", ".--", ".-..", ".. ..", "... .", /* N-Z */
155  "..... -.", /* 91 - [ (really '(') */
156  "..- -", /* 92 - \ (really '/') */
157  "..... .. ..", /* 93 - ] (really ')') */
158  "", /* 94 - ^ */
159  "..--.-", /* 95 - _ */
160  ".----.", /* 96 - ` */
161  ".-", "-...", ".. .", "-..", ".", ".-.", "--.", "....", "..", ".-.-", "-.-", "L", "--", /* a-m */
162  "-.", ". .", ".....", "..-.", ". ..", "...", "-", "..-", "...-", ".--", ".-..", ".. ..", "... .", /* n-z */
163  "..... -.", /* 123 - { (really '(') */
164  "", /* 124 - | */
165  "..... .. ..", /* 125 - } (really ')') */
166  "..- -", /* 126 - ~ (really bar) */
167  ". . .", /* 127 - <del> (error) */
168 };
169 
170 static int playtone(struct ast_channel *chan, int tone, int len)
171 {
172  int res;
173  char dtmf[20];
174  snprintf(dtmf, sizeof(dtmf), "%d/%d", tone, len);
175  ast_playtones_start(chan, 0, dtmf, 0);
176  res = ast_safe_sleep(chan, len);
177  ast_playtones_stop(chan);
178  return res;
179 }
180 
181 static int morsecode_exec(struct ast_channel *chan, const char *data)
182 {
183  int res = 0, ditlen, tone, toneoff, digit2;
184  const char *digit;
185  const char *ditlenc, *tonec, *toneb, *codetype;
186 
187  if (ast_strlen_zero(data)) {
188  ast_log(LOG_WARNING, "Syntax: Morsecode(<string>) - no argument found\n");
189  return 0;
190  }
191 
192  ast_channel_lock(chan);
193  /* Use variable MORESEDITLEN, if set (else 80) */
194  ditlenc = pbx_builtin_getvar_helper(chan, "MORSEDITLEN");
195  if (ast_strlen_zero(ditlenc) || (sscanf(ditlenc, "%30d", &ditlen) != 1)) {
196  ditlen = 80;
197  }
198 
199  /* Use variable MORSETONE, if set (else 800) */
200  tonec = pbx_builtin_getvar_helper(chan, "MORSETONE");
201  if (ast_strlen_zero(tonec) || (sscanf(tonec, "%30d", &tone) != 1)) {
202  tone = 800;
203  }
204 
205  /* Use variable MORSESPACETONE, if set (else 0) */
206  toneb = pbx_builtin_getvar_helper(chan, "MORSESPACETONE");
207  if (ast_strlen_zero(toneb) || (sscanf(toneb, "%30d", &toneoff) != 1)) {
208  toneoff = 0;
209  }
210 
211  /* Use variable MORSETYPE, if set (else INTERNATIONAL) */
212  codetype = pbx_builtin_getvar_helper(chan, "MORSETYPE");
213  if (!codetype || strcmp(codetype, "AMERICAN")) {
214  codetype = "INTERNATIONAL";
215  }
216 
217  ast_channel_unlock(chan);
218  if (!strcmp(codetype, "AMERICAN")) {
219  for (digit = data; *digit; digit++) {
220  const char *dahdit;
221  digit2 = *digit;
222  if (digit2 < 0 || digit2 > 127) {
223  continue;
224  }
225  for (dahdit = americanmorsecode[digit2]; *dahdit; dahdit++) {
226  if (*dahdit == '-') {
227  res = playtone(chan, tone, 3 * ditlen);
228  } else if (*dahdit == '.') {
229  res = playtone(chan, tone, 1 * ditlen);
230  } else if (*dahdit == 'L' || *dahdit == 'l') {
231  res = playtone(chan, tone, 6 * ditlen); /* long dash */
232  } else if (*dahdit == '0') {
233  res = playtone(chan, tone, 9 * ditlen); /* extra long dash */
234  } else if (*dahdit == ' ') { /* space char (x20) = 6 dot lengths */
235  /* Intra-char pauses, specific to American Morse */
236  res = playtone(chan, toneoff, 3 * ditlen);
237  } else {
238  /* Account for ditlen of silence immediately following */
239  res = playtone(chan, toneoff, 2 * ditlen);
240  }
241 
242  /* Pause slightly between each dit and dah */
243  res = playtone(chan, toneoff, 1 * ditlen);
244  if (res)
245  break;
246  }
247  /* Pause between characters */
248  res = playtone(chan, toneoff, 3 * ditlen);
249  if (res)
250  break;
251  }
252  } else { /* International */
253  for (digit = data; *digit; digit++) {
254  const char *dahdit;
255  digit2 = *digit;
256  if (digit2 < 0 || digit2 > 127) {
257  continue;
258  }
259  for (dahdit = internationalcode[digit2]; *dahdit; dahdit++) {
260  if (*dahdit == '-') {
261  res = playtone(chan, tone, 3 * ditlen);
262  } else if (*dahdit == '.') {
263  res = playtone(chan, tone, 1 * ditlen);
264  } else {
265  /* Account for ditlen of silence immediately following */
266  res = playtone(chan, toneoff, 2 * ditlen);
267  }
268 
269  /* Pause slightly between each dit and dah */
270  res = playtone(chan, toneoff, 1 * ditlen);
271  if (res)
272  break;
273  }
274  /* Pause between characters */
275  res = playtone(chan, toneoff, 2 * ditlen);
276  if (res)
277  break;
278  }
279  }
280 
281  return res;
282 }
283 
284 static int unload_module(void)
285 {
286  return ast_unregister_application(app_morsecode);
287 }
288 
289 static int load_module(void)
290 {
291  return ast_register_application_xml(app_morsecode, morsecode_exec);
292 }
293 
294 AST_MODULE_INFO_STANDARD_EXTENDED(ASTERISK_GPL_KEY, "Morse code");
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1574
Tone Indication Support.
Main Channel structure associated with a channel.
Asterisk main include file. File version handling, generic pbx functions.
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
void ast_playtones_stop(struct ast_channel *chan)
Stop playing tones on a channel.
Definition: indications.c:393
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
General Asterisk PBX channel definitions.
Core PBX routines and definitions.
int ast_playtones_start(struct ast_channel *chan, int vol, const char *tonelist, int interruptible)
Start playing a list of tones on a channel.
Definition: indications.c:302
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
Asterisk module definitions.
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:640