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