Make the ditlen and tone configurable at runtime
[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 #include <stdio.h>
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <string.h>
31
32 #include "asterisk.h"
33
34 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
35
36 #include "asterisk/file.h"
37 #include "asterisk/logger.h"
38 #include "asterisk/options.h"
39 #include "asterisk/channel.h"
40 #include "asterisk/pbx.h"
41 #include "asterisk/module.h"
42 #include "asterisk/indications.h"
43
44 static char *tdesc = "Morse code";
45
46 static char *app_morsecode = "Morsecode";
47
48 static char *morsecode_synopsis = "Plays morse code";
49
50 static char *morsecode_descrip =
51 "Usage: Morsecode(<string>)\n"
52 "Plays the Morse code equivalent of the passed string.  If the variable\n"
53 "MORSEDITLEN is set, it will use that value for the length (in ms) of the dit\n"
54 "(defaults to 80).  Additionally, if MORSETONE is set, it will use that tone\n"
55 "(in Hz).  The tone default is 800.\n";
56
57 STANDARD_LOCAL_USER;
58
59 LOCAL_USER_DECL;
60
61 static char *morsecode[] = {
62         "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /*  0-15 */
63         "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /* 16-31 */
64         " ",      /* 32 - <space> */
65         ".-.-.-", /* 33 - ! */
66         ".-..-.", /* 34 - " */
67         "",       /* 35 - # */
68         "",       /* 36 - $ */
69         "",       /* 37 - % */
70         "",       /* 38 - & */
71         ".----.", /* 39 - ' */
72         "-.--.-", /* 40 - ( */
73         "-.--.-", /* 41 - ) */
74         "",       /* 42 - * */
75         "",       /* 43 - + */
76         "--..--", /* 44 - , */
77         "-....-", /* 45 - - */
78         ".-.-.-", /* 46 - . */
79         "-··-·",  /* 47 - / */
80         "-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----.", /* 48-57 - 0-9 */
81         "---...", /* 58 - : */
82         "-·-·-·", /* 59 - ; */
83         "",       /* 60 - < */
84         "-...-",  /* 61 - = */
85         "",       /* 62 - > */
86         "..--..", /* 63 - ? */
87         ".--.-.", /* 64 - @ */
88         ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--",
89         "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..",
90         "-.--.-", /* 91 - [ (really '(') */
91         "-··-·",  /* 92 - \ (really '/') */
92         "-.--.-", /* 93 - ] (really ')') */
93         "",       /* 94 - ^ */
94         "··--·-", /* 95 - _ */
95         ".----.", /* 96 - ` */
96         ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--",
97         "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..",
98         "-.--.-", /* 123 - { (really '(') */
99         "",       /* 124 - | */
100         "-.--.-", /* 125 - } (really ')') */
101         "-··-·",  /* 126 - ~ (really bar) */
102         "· · ·",  /* 127 - <del> (error) */
103 };
104
105 static void playtone(struct ast_channel *chan, int tone, int len)
106 {
107         char dtmf[20];
108         snprintf(dtmf, sizeof(dtmf), "%d/%d", tone, len);
109         ast_playtones_start(chan, 0, dtmf, 0);
110         ast_safe_sleep(chan, len);
111         ast_playtones_stop(chan);
112 }
113
114 static int morsecode_exec(struct ast_channel *chan, void *data)
115 {
116         int res=0, ditlen, tone;
117         char *digit;
118         const char *ditlenc, *tonec;
119         struct localuser *u;
120
121         LOCAL_USER_ADD(u);
122
123         if (ast_strlen_zero(data)) {
124                 ast_log(LOG_WARNING, "Syntax: Morsecode(<string>) - no argument found\n");
125                 LOCAL_USER_REMOVE(u);
126                 return 0;
127         }
128
129         /* Use variable MORESEDITLEN, if set (else 80) */
130         ditlenc = pbx_builtin_getvar_helper(chan, "MORSEDITLEN");
131         if (ast_strlen_zero(ditlenc) || (sscanf(ditlenc, "%d", &ditlen) != 1)) {
132                 ditlen = 80;
133         }
134
135         /* Use variable MORSETONE, if set (else 800) */
136         tonec = pbx_builtin_getvar_helper(chan, "MORSETONE");
137         if (ast_strlen_zero(tonec) || (sscanf(tonec, "%d", &tone) != 1)) {
138                 tone = 800;
139         }
140
141         for (digit = data; *digit; digit++) {
142                 char *dahdit;
143                 if (*digit < 0) {
144                         continue;
145                 }
146                 for (dahdit = morsecode[(int)*digit]; *dahdit; dahdit++) {
147                         if (*dahdit == '-') {
148                                 playtone(chan, tone, 3 * ditlen);
149                         } else if (*dahdit == '.') {
150                                 playtone(chan, tone, 1 * ditlen);
151                         } else {
152                                 /* Account for ditlen of silence immediately following */
153                                 playtone(chan, 0, 2 * ditlen);
154                         }
155
156                         /* Pause slightly between each dit and dah */
157                         playtone(chan, 0, 1 * ditlen);
158                 }
159                 /* Pause between characters */
160                 playtone(chan, 0, 2 * ditlen);
161         }
162
163         LOCAL_USER_REMOVE(u);
164         return res;
165 }
166
167 int unload_module(void)
168 {
169         int res;
170
171         res = ast_unregister_application(app_morsecode);
172
173         STANDARD_HANGUP_LOCALUSERS;
174
175         return res;
176 }
177
178 int load_module(void)
179 {
180         return ast_register_application(app_morsecode, morsecode_exec, morsecode_synopsis, morsecode_descrip);
181 }
182
183 char *description(void)
184 {
185         return tdesc;
186 }
187
188 int usecount(void)
189 {
190         int res;
191         STANDARD_USECOUNT(res);
192         return res;
193 }
194
195 char *key()
196 {
197         return ASTERISK_GPL_KEY;
198 }