Add new AMI action for app_voicemail
[asterisk/asterisk.git] / apps / app_morsecode.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (c) 2006, Tilghman Lesher.  All rights reserved.
5  *
6  * Tilghman Lesher <app_morsecode__v001@the-tilghman.com>
7  *
8  * This code is released by the author with no restrictions on usage.
9  *
10  * See http://www.asterisk.org for more information about
11  * the Asterisk project. Please do not directly contact
12  * any of the maintainers of this project for assistance;
13  * the project provides a web site, mailing lists and IRC
14  * channels for your use.
15  *
16  */
17
18 /*! \file
19  *
20  * \brief Morsecode application
21  *
22  * \author Tilghman Lesher <app_morsecode__v001@the-tilghman.com>
23  *
24  * \ingroup applications
25  */
26
27 /*** MODULEINFO
28         <support_level>extended</support_level>
29  ***/
30
31 #include "asterisk.h"
32
33 #include "asterisk/file.h"
34 #include "asterisk/channel.h"
35 #include "asterisk/pbx.h"
36 #include "asterisk/module.h"
37 #include "asterisk/indications.h"
38
39 /*** DOCUMENTATION
40         <application name="Morsecode" language="en_US">
41                 <synopsis>
42                         Plays morse code.
43                 </synopsis>
44                 <syntax>
45                         <parameter name="string" required="true">
46                                 <para>String to playback as morse code to channel</para>
47                         </parameter>
48                 </syntax>
49                 <description>
50                         <para>Plays the Morse code equivalent of the passed string.</para>
51                         <para>This application does not automatically answer and should be preceeded by
52                         an application such as Answer() or Progress().</para>
53                         <para>This application uses the following variables:</para>
54                         <variablelist>
55                                 <variable name="MORSEDITLEN">
56                                         <para>Use this value in (ms) for length of dit</para>
57                                 </variable>
58                                 <variable name="MORSETONE">
59                                         <para>The pitch of the tone in (Hz), default is 800</para>
60                                 </variable>
61                         </variablelist>
62                 </description>
63                 <see-also>
64                         <ref type="application">SayAlpha</ref>
65                         <ref type="application">SayPhonetic</ref>
66                 </see-also>
67         </application>
68  ***/   
69 static const char app_morsecode[] = "Morsecode";
70
71 static const char * const morsecode[] = {
72         "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /*  0-15 */
73         "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /* 16-31 */
74         " ",      /* 32 - <space> */
75         ".-.-.-", /* 33 - ! */
76         ".-..-.", /* 34 - " */
77         "",       /* 35 - # */
78         "",       /* 36 - $ */
79         "",       /* 37 - % */
80         "",       /* 38 - & */
81         ".----.", /* 39 - ' */
82         "-.--.-", /* 40 - ( */
83         "-.--.-", /* 41 - ) */
84         "",       /* 42 - * */
85         "",       /* 43 - + */
86         "--..--", /* 44 - , */
87         "-....-", /* 45 - - */
88         ".-.-.-", /* 46 - . */
89         "-..-.",  /* 47 - / */
90         "-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----.", /* 48-57 - 0-9 */
91         "---...", /* 58 - : */
92         "-.-.-.", /* 59 - ; */
93         "",       /* 60 - < */
94         "-...-",  /* 61 - = */
95         "",       /* 62 - > */
96         "..--..", /* 63 - ? */
97         ".--.-.", /* 64 - @ */
98         ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--",
99         "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..",
100         "-.--.-", /* 91 - [ (really '(') */
101         "-..-.",  /* 92 - \ (really '/') */
102         "-.--.-", /* 93 - ] (really ')') */
103         "",       /* 94 - ^ */
104         "..--.-", /* 95 - _ */
105         ".----.", /* 96 - ` */
106         ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--",
107         "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..",
108         "-.--.-", /* 123 - { (really '(') */
109         "",       /* 124 - | */
110         "-.--.-", /* 125 - } (really ')') */
111         "-..-.",  /* 126 - ~ (really bar) */
112         ". . .",  /* 127 - <del> (error) */
113 };
114
115 static void playtone(struct ast_channel *chan, int tone, int len)
116 {
117         char dtmf[20];
118         snprintf(dtmf, sizeof(dtmf), "%d/%d", tone, len);
119         ast_playtones_start(chan, 0, dtmf, 0);
120         ast_safe_sleep(chan, len);
121         ast_playtones_stop(chan);
122 }
123
124 static int morsecode_exec(struct ast_channel *chan, const char *data)
125 {
126         int res=0, ditlen, tone;
127         const char *digit;
128         const char *ditlenc, *tonec;
129
130         if (ast_strlen_zero(data)) {
131                 ast_log(LOG_WARNING, "Syntax: Morsecode(<string>) - no argument found\n");
132                 return 0;
133         }
134
135         /* Use variable MORESEDITLEN, if set (else 80) */
136         ast_channel_lock(chan);
137         ditlenc = pbx_builtin_getvar_helper(chan, "MORSEDITLEN");
138         if (ast_strlen_zero(ditlenc) || (sscanf(ditlenc, "%30d", &ditlen) != 1)) {
139                 ditlen = 80;
140         }
141         ast_channel_unlock(chan);
142
143         /* Use variable MORSETONE, if set (else 800) */
144         ast_channel_lock(chan);
145         tonec = pbx_builtin_getvar_helper(chan, "MORSETONE");
146         if (ast_strlen_zero(tonec) || (sscanf(tonec, "%30d", &tone) != 1)) {
147                 tone = 800;
148         }
149         ast_channel_unlock(chan);
150
151         for (digit = data; *digit; digit++) {
152                 int digit2 = *digit;
153                 const char *dahdit;
154                 if (digit2 < 0) {
155                         continue;
156                 }
157                 for (dahdit = morsecode[digit2]; *dahdit; dahdit++) {
158                         if (*dahdit == '-') {
159                                 playtone(chan, tone, 3 * ditlen);
160                         } else if (*dahdit == '.') {
161                                 playtone(chan, tone, 1 * ditlen);
162                         } else {
163                                 /* Account for ditlen of silence immediately following */
164                                 playtone(chan, 0, 2 * ditlen);
165                         }
166
167                         /* Pause slightly between each dit and dah */
168                         playtone(chan, 0, 1 * ditlen);
169                 }
170                 /* Pause between characters */
171                 playtone(chan, 0, 2 * ditlen);
172         }
173
174         return res;
175 }
176
177 static int unload_module(void)
178 {
179         return ast_unregister_application(app_morsecode);
180 }
181
182 static int load_module(void)
183 {
184         return ast_register_application_xml(app_morsecode, morsecode_exec);
185 }
186
187 AST_MODULE_INFO_STANDARD_EXTENDED(ASTERISK_GPL_KEY, "Morse code");
188