2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2002, Pauline Middelink
7 * See http://www.asterisk.org for more information about
8 * the Asterisk project. Please do not directly contact
9 * any of the maintainers of this project for assistance;
10 * the project provides a web site, mailing lists and IRC
11 * channels for your use.
13 * This program is free software, distributed under the terms of
14 * the GNU General Public License Version 2. See the LICENSE file
15 * at the top of the source tree.
18 /*! \file res_indications.c
20 * \brief Load the indications
22 * \author Pauline Middelink <middelink@polyware.nl>
24 * Load the country specific dialtones into the asterisk PBX.
29 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
37 #include <sys/types.h>
40 #include "asterisk/lock.h"
41 #include "asterisk/file.h"
42 #include "asterisk/cli.h"
43 #include "asterisk/logger.h"
44 #include "asterisk/config.h"
45 #include "asterisk/channel.h"
46 #include "asterisk/pbx.h"
47 #include "asterisk/module.h"
48 #include "asterisk/translate.h"
49 #include "asterisk/indications.h"
50 #include "asterisk/utils.h"
53 static const char config
[] = "indications.conf";
56 * Help for commands provided by this module ...
58 static char help_add_indication
[] =
59 "Usage: indication add <country> <indication> \"<tonelist>\"\n"
60 " Add the given indication to the country.\n";
62 static char help_remove_indication
[] =
63 "Usage: indication remove <country> <indication>\n"
64 " Remove the given indication from the country.\n";
66 static char help_show_indications
[] =
67 "Usage: indication show [<country> ...]\n"
68 " Display either a condensed for of all country/indications, or the\n"
69 " indications for the specified countries.\n";
72 "PlayTones(arg): Plays a tone list. Execution will continue with the next step immediately,\n"
73 "while the tones continue to play.\n"
74 "Arg is either the tone name defined in the indications.conf configuration file, or a directly\n"
75 "specified list of frequencies and durations.\n"
76 "See the sample indications.conf for a description of the specification of a tonelist.\n\n"
77 "Use the StopPlayTones application to stop the tones playing. \n";
80 * Implementation of functions provided by this module
84 * ADD INDICATION command stuff
86 static int handle_add_indication(int fd
, int argc
, char *argv
[])
88 struct ind_tone_zone
*tz
;
89 int created_country
= 0;
90 if (argc
!= 5) return RESULT_SHOWUSAGE
;
92 tz
= ast_get_indication_zone(argv
[2]);
94 /* country does not exist, create it */
95 ast_log(LOG_NOTICE
, "Country '%s' does not exist, creating it.\n",argv
[2]);
97 if (!(tz
= ast_calloc(1, sizeof(*tz
)))) {
100 ast_copy_string(tz
->country
,argv
[2],sizeof(tz
->country
));
101 if (ast_register_indication_country(tz
)) {
102 ast_log(LOG_WARNING
, "Unable to register new country\n");
108 if (ast_register_indication(tz
,argv
[3],argv
[4])) {
109 ast_log(LOG_WARNING
, "Unable to register indication %s/%s\n",argv
[2],argv
[3]);
111 ast_unregister_indication_country(argv
[2]);
118 * REMOVE INDICATION command stuff
120 static int handle_remove_indication(int fd
, int argc
, char *argv
[])
122 struct ind_tone_zone
*tz
;
123 if (argc
!= 3 && argc
!= 4) return RESULT_SHOWUSAGE
;
126 /* remove entiry country */
127 if (ast_unregister_indication_country(argv
[2])) {
128 ast_log(LOG_WARNING
, "Unable to unregister indication country %s\n",argv
[2]);
134 tz
= ast_get_indication_zone(argv
[2]);
136 ast_log(LOG_WARNING
, "Unable to unregister indication %s/%s, country does not exists\n",argv
[2],argv
[3]);
139 if (ast_unregister_indication(tz
,argv
[3])) {
140 ast_log(LOG_WARNING
, "Unable to unregister indication %s/%s\n",argv
[2],argv
[3]);
147 * SHOW INDICATIONS command stuff
149 static int handle_show_indications(int fd
, int argc
, char *argv
[])
151 struct ind_tone_zone
*tz
= NULL
;
153 int found_country
= 0;
156 /* no arguments, show a list of countries */
157 ast_cli(fd
,"Country Alias Description\n"
158 "===========================\n");
159 while ( (tz
= ast_walk_indications(tz
) ) )
160 ast_cli(fd
,"%-7.7s %-7.7s %s\n", tz
->country
, tz
->alias
, tz
->description
);
163 /* there was a request for specific country(ies), lets humor them */
164 while ( (tz
= ast_walk_indications(tz
) ) ) {
166 for (i
=2; i
<argc
; i
++) {
167 if (strcasecmp(tz
->country
,argv
[i
])==0 &&
169 struct ind_tone_zone_sound
* ts
;
170 if (!found_country
) {
172 ast_cli(fd
,"Country Indication PlayList\n"
173 "=====================================\n");
175 j
= snprintf(buf
,sizeof(buf
),"%-7.7s %-15.15s ",tz
->country
,"<ringcadence>");
176 for (i
=0; i
<tz
->nrringcadence
; i
++) {
177 j
+= snprintf(buf
+j
,sizeof(buf
)-j
,"%d,",tz
->ringcadence
[i
]);
179 if (tz
->nrringcadence
)
181 ast_copy_string(buf
+j
,"\n",sizeof(buf
)-j
);
183 for (ts
=tz
->tones
; ts
; ts
=ts
->next
)
184 ast_cli(fd
,"%-7.7s %-15.15s %s\n",tz
->country
,ts
->name
,ts
->data
);
190 ast_cli(fd
,"No countries matched your criteria.\n");
195 * Playtones command stuff
197 static int handle_playtones(struct ast_channel
*chan
, void *data
)
199 struct ind_tone_zone_sound
*ts
;
202 if (!data
|| !((char*)data
)[0]) {
203 ast_log(LOG_NOTICE
,"Nothing to play\n");
206 ts
= ast_get_indication_tone(chan
->zone
, (const char*)data
);
207 if (ts
&& ts
->data
[0])
208 res
= ast_playtones_start(chan
, 0, ts
->data
, 0);
210 res
= ast_playtones_start(chan
, 0, (const char*)data
, 0);
212 ast_log(LOG_NOTICE
,"Unable to start playtones\n");
217 * StopPlaylist command stuff
219 static int handle_stopplaytones(struct ast_channel
*chan
, void *data
)
221 ast_playtones_stop(chan
);
228 static int ind_load_module(void)
230 struct ast_config
*cfg
;
231 struct ast_variable
*v
;
234 struct ind_tone_zone
*tones
;
235 const char *country
= NULL
;
237 /* that the following cast is needed, is yuk! */
238 /* yup, checked it out. It is NOT written to. */
239 cfg
= ast_config_load((char *)config
);
243 /* Use existing config to populate the Indication table */
244 cxt
= ast_category_browse(cfg
, NULL
);
246 /* All categories but "general" are considered countries */
247 if (!strcasecmp(cxt
, "general")) {
248 cxt
= ast_category_browse(cfg
, cxt
);
251 if (!(tones
= ast_calloc(1, sizeof(*tones
)))) {
252 ast_config_destroy(cfg
);
255 ast_copy_string(tones
->country
,cxt
,sizeof(tones
->country
));
257 v
= ast_variable_browse(cfg
, cxt
);
259 if (!strcasecmp(v
->name
, "description")) {
260 ast_copy_string(tones
->description
, v
->value
, sizeof(tones
->description
));
261 } else if ((!strcasecmp(v
->name
,"ringcadence"))||(!strcasecmp(v
->name
,"ringcadance"))) {
262 char *ring
,*rings
= ast_strdupa(v
->value
);
264 ring
= strsep(&c
,",");
267 if (!isdigit(ring
[0]) || (val
=atoi(ring
))==-1) {
268 ast_log(LOG_WARNING
,"Invalid ringcadence given '%s' at line %d.\n",ring
,v
->lineno
);
269 ring
= strsep(&c
,",");
272 if (!(tmp
= ast_realloc(tones
->ringcadence
, (tones
->nrringcadence
+ 1) * sizeof(int)))) {
273 ast_config_destroy(cfg
);
276 tones
->ringcadence
= tmp
;
277 tmp
[tones
->nrringcadence
] = val
;
278 tones
->nrringcadence
++;
280 ring
= strsep(&c
,",");
282 } else if (!strcasecmp(v
->name
,"alias")) {
283 char *countries
= ast_strdupa(v
->value
);
285 country
= strsep(&c
,",");
287 struct ind_tone_zone
* azone
;
288 if (!(azone
= ast_calloc(1, sizeof(*azone
)))) {
289 ast_config_destroy(cfg
);
292 ast_copy_string(azone
->country
, country
, sizeof(azone
->country
));
293 ast_copy_string(azone
->alias
, cxt
, sizeof(azone
->alias
));
294 if (ast_register_indication_country(azone
)) {
295 ast_log(LOG_WARNING
, "Unable to register indication alias at line %d.\n",v
->lineno
);
299 country
= strsep(&c
,",");
302 /* add tone to country */
303 struct ind_tone_zone_sound
*ps
,*ts
;
304 for (ps
=NULL
,ts
=tones
->tones
; ts
; ps
=ts
, ts
=ts
->next
) {
305 if (strcasecmp(v
->name
,ts
->name
)==0) {
307 ast_log(LOG_NOTICE
,"Duplicate entry '%s', skipped.\n",v
->name
);
311 /* not there, add it to the back */
312 if (!(ts
= ast_malloc(sizeof(*ts
)))) {
313 ast_config_destroy(cfg
);
317 ts
->name
= strdup(v
->name
);
318 ts
->data
= strdup(v
->value
);
326 if (tones
->description
[0] || tones
->alias
[0] || tones
->tones
) {
327 if (ast_register_indication_country(tones
)) {
328 ast_log(LOG_WARNING
, "Unable to register indication at line %d.\n",v
->lineno
);
333 cxt
= ast_category_browse(cfg
, cxt
);
336 /* determine which country is the default */
337 country
= ast_variable_retrieve(cfg
,"general","country");
338 if (!country
|| !*country
|| ast_set_indication_country(country
))
339 ast_log(LOG_WARNING
,"Unable to set the default country (for indication tones)\n");
341 ast_config_destroy(cfg
);
346 * CLI entries for commands provided by this module
348 static struct ast_cli_entry cli_show_indications_deprecated
= {
349 { "show", "indications", NULL
},
350 handle_show_indications
, NULL
,
353 static struct ast_cli_entry cli_indications
[] = {
354 { { "indication", "add", NULL
},
355 handle_add_indication
, "Add the given indication to the country",
356 help_add_indication
, NULL
},
358 { { "indication", "remove", NULL
},
359 handle_remove_indication
, "Remove the given indication from the country",
360 help_remove_indication
, NULL
},
362 { { "indication", "show", NULL
},
363 handle_show_indications
, "Display a list of all countries/indications",
364 help_show_indications
, NULL
, &cli_show_indications_deprecated
},
368 * Standard module functions ...
370 static int unload_module(void)
372 /* remove the registed indications... */
373 ast_unregister_indication_country(NULL
);
375 /* and the functions */
376 ast_cli_unregister_multiple(cli_indications
, sizeof(cli_indications
) / sizeof(struct ast_cli_entry
));
377 ast_unregister_application("PlayTones");
378 ast_unregister_application("StopPlayTones");
383 static int load_module(void)
385 if (ind_load_module())
386 return AST_MODULE_LOAD_DECLINE
;
387 ast_cli_register_multiple(cli_indications
, sizeof(cli_indications
) / sizeof(struct ast_cli_entry
));
388 ast_register_application("PlayTones", handle_playtones
, "Play a tone list", playtones_desc
);
389 ast_register_application("StopPlayTones", handle_stopplaytones
, "Stop playing a tone list","Stop playing a tone list");
394 static int reload(void)
396 /* remove the registed indications... */
397 ast_unregister_indication_country(NULL
);
399 return ind_load_module();
402 AST_MODULE_INFO(ASTERISK_GPL_KEY
, AST_MODFLAG_GLOBAL_SYMBOLS
, "Indications Resource",
404 .unload
= unload_module
,