Bug 6213 - Morse code app
[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: 7221 $")
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\n";
53
54 STANDARD_LOCAL_USER;
55
56 LOCAL_USER_DECL;
57
58 #define TONE    440
59 #define DITLEN  100
60 #define DAHLEN  250
61 #define DITDAHSEPLEN    50
62 #define CHARSEPLEN      200
63 /* Pause between words will be twice CHARSEPLEN plus DITDAHSEPLEN - 450 */
64
65 static char *morsecode[] = {
66         "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /*  0-15 */
67         "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /* 16-31 */
68         " ",      /* 32 - <space> */
69         ".-.-.-", /* 33 - ! */
70         ".-..-.", /* 34 - " */
71         "",       /* 35 - # */
72         "",       /* 36 - $ */
73         "",       /* 37 - % */
74         "",       /* 38 - & */
75         ".----.", /* 39 - ' */
76         "-.--.-", /* 40 - ( */
77         "-.--.-", /* 41 - ) */
78         "",       /* 42 - * */
79         "",       /* 43 - + */
80         "--..--", /* 44 - , */
81         "-....-", /* 45 - - */
82         ".-.-.-", /* 46 - . */
83         "-··-·",  /* 47 - / */
84         "-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----.", /* 48-57 - 0-9 */
85         "---...", /* 58 - : */
86         "-·-·-·", /* 59 - ; */
87         "",       /* 60 - < */
88         "-...-",  /* 61 - = */
89         "",       /* 62 - > */
90         "..--..", /* 63 - ? */
91         ".--.-.", /* 64 - @ */
92         ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--",
93         "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..",
94         "-.--.-", /* 91 - [ (really '(') */
95         "-··-·",  /* 92 - \ (really '/') */
96         "-.--.-", /* 93 - ] (really ')') */
97         "",       /* 94 - ^ */
98         "··--·-", /* 95 - _ */
99         ".----.", /* 96 - ` */
100         ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--",
101         "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..",
102         "-.--.-", /* 123 - { (really '(') */
103         "",       /* 124 - | */
104         "-.--.-", /* 125 - } (really ')') */
105         "-··-·",  /* 126 - ~ (really bar) */
106         "· · ·",  /* 127 - <del> (error) */
107 };
108
109 static void playtone(struct ast_channel *chan, int tone, int len)
110 {
111         char dtmf[20];
112         snprintf(dtmf, sizeof(dtmf), "%d/%d", tone, len);
113         ast_playtones_start(chan, 0, dtmf, 0);
114         ast_safe_sleep(chan, len);
115         ast_playtones_stop(chan);
116 }
117
118 static int morsecode_exec(struct ast_channel *chan, void *data)
119 {
120         int res=0;
121         char *digit;
122         struct localuser *u;
123
124         LOCAL_USER_ADD(u);
125
126         if (ast_strlen_zero(data)) {
127                 ast_log(LOG_WARNING, "Syntax: Morsecode(<string>) - no argument found\n");
128                 LOCAL_USER_REMOVE(u);
129                 return 0;
130         }
131
132         for (digit = data; *digit; digit++) {
133                 char *dahdit;
134                 if (*digit < 0) {
135                         continue;
136                 }
137                 for (dahdit = morsecode[(int)*digit]; *dahdit; dahdit++) {
138                         if (*dahdit == '-') {
139                                 playtone(chan, TONE, DAHLEN);
140                         } else if (*dahdit == '.') {
141                                 playtone(chan, TONE, DITLEN);
142                         } else {
143                                 playtone(chan, TONE, CHARSEPLEN);
144                         }
145
146                         /* Pause slightly between each dit and dah */
147                         playtone(chan, 0, DITDAHSEPLEN);
148                 }
149                 /* Pause between characters */
150                 playtone(chan, 0, CHARSEPLEN);
151         }
152
153         LOCAL_USER_REMOVE(u);
154         return res;
155 }
156
157 int unload_module(void)
158 {
159         int res;
160
161         res = ast_unregister_application(app_morsecode);
162
163         STANDARD_HANGUP_LOCALUSERS;
164
165         return res;
166 }
167
168 int load_module(void)
169 {
170         return ast_register_application(app_morsecode, morsecode_exec, morsecode_synopsis, morsecode_descrip);
171 }
172
173 char *description(void)
174 {
175         return tdesc;
176 }
177
178 int usecount(void)
179 {
180         int res;
181         STANDARD_USECOUNT(res);
182         return res;
183 }
184
185 char *key()
186 {
187         return ASTERISK_GPL_KEY;
188 }