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.
33 #include <sys/types.h>
38 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
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"
53 static const char dtext[] = "Indications Configuration";
54 static const char config[] = "indications.conf";
57 * Help for commands provided by this module ...
59 static char help_add_indication[] =
60 "Usage: indication add <country> <indication> \"<tonelist>\"\n"
61 " Add the given indication to the country.\n";
63 static char help_remove_indication[] =
64 "Usage: indication remove <country> <indication>\n"
65 " Remove the given indication from the country.\n";
67 static char help_show_indications[] =
68 "Usage: show indications [<country> ...]\n"
69 " Show either a condensed for of all country/indications, or the\n"
70 " indications for the specified countries.\n";
73 "PlayTones(arg): Plays a tone list. Execution will continue with the next step immediately,\n"
74 "while the tones continue to play.\n"
75 "Arg is either the tone name defined in the indications.conf configuration file, or a directly\n"
76 "specified list of frequencies and durations.\n"
77 "See the sample indications.conf for a description of the specification of a tonelist.\n\n"
78 "Use the StopPlayTones application to stop the tones playing. \n";
81 * Implementation of functions provided by this module
85 * ADD INDICATION command stuff
87 static int handle_add_indication(int fd, int argc, char *argv[])
90 int created_country = 0;
91 if (argc != 5) return RESULT_SHOWUSAGE;
93 tz = ast_get_indication_zone(argv[2]);
95 /* country does not exist, create it */
96 ast_log(LOG_NOTICE, "Country '%s' does not exist, creating it.\n",argv[2]);
98 tz = malloc(sizeof(struct tone_zone));
100 ast_log(LOG_WARNING, "Out of memory\n");
103 memset(tz,0,sizeof(struct tone_zone));
104 ast_copy_string(tz->country,argv[2],sizeof(tz->country));
105 if (ast_register_indication_country(tz)) {
106 ast_log(LOG_WARNING, "Unable to register new country\n");
112 if (ast_register_indication(tz,argv[3],argv[4])) {
113 ast_log(LOG_WARNING, "Unable to register indication %s/%s\n",argv[2],argv[3]);
115 ast_unregister_indication_country(argv[2]);
122 * REMOVE INDICATION command stuff
124 static int handle_remove_indication(int fd, int argc, char *argv[])
126 struct tone_zone *tz;
127 if (argc != 3 && argc != 4) return RESULT_SHOWUSAGE;
130 /* remove entiry country */
131 if (ast_unregister_indication_country(argv[2])) {
132 ast_log(LOG_WARNING, "Unable to unregister indication country %s\n",argv[2]);
138 tz = ast_get_indication_zone(argv[2]);
140 ast_log(LOG_WARNING, "Unable to unregister indication %s/%s, country does not exists\n",argv[2],argv[3]);
143 if (ast_unregister_indication(tz,argv[3])) {
144 ast_log(LOG_WARNING, "Unable to unregister indication %s/%s\n",argv[2],argv[3]);
151 * SHOW INDICATIONS command stuff
153 static int handle_show_indications(int fd, int argc, char *argv[])
155 struct tone_zone *tz;
157 int found_country = 0;
159 if (ast_mutex_lock(&tzlock)) {
160 ast_log(LOG_WARNING, "Unable to lock tone_zones list\n");
164 /* no arguments, show a list of countries */
165 ast_cli(fd,"Country Alias Description\n"
166 "===========================\n");
167 for (tz=tone_zones; tz; tz=tz->next) {
168 ast_cli(fd,"%-7.7s %-7.7s %s\n", tz->country, tz->alias, tz->description);
170 ast_mutex_unlock(&tzlock);
173 /* there was a request for specific country(ies), lets humor them */
174 for (tz=tone_zones; tz; tz=tz->next) {
176 for (i=2; i<argc; i++) {
177 if (strcasecmp(tz->country,argv[i])==0 &&
179 struct tone_zone_sound* ts;
180 if (!found_country) {
182 ast_cli(fd,"Country Indication PlayList\n"
183 "=====================================\n");
185 j = snprintf(buf,sizeof(buf),"%-7.7s %-15.15s ",tz->country,"<ringcadence>");
186 for (i=0; i<tz->nrringcadence; i++) {
187 j += snprintf(buf+j,sizeof(buf)-j,"%d,",tz->ringcadence[i]);
189 if (tz->nrringcadence) j--;
190 ast_copy_string(buf+j,"\n",sizeof(buf)-j);
192 for (ts=tz->tones; ts; ts=ts->next)
193 ast_cli(fd,"%-7.7s %-15.15s %s\n",tz->country,ts->name,ts->data);
199 ast_cli(fd,"No countries matched your criteria.\n");
200 ast_mutex_unlock(&tzlock);
205 * Playtones command stuff
207 static int handle_playtones(struct ast_channel *chan, void *data)
209 struct tone_zone_sound *ts;
212 if (!data || !((char*)data)[0]) {
213 ast_log(LOG_NOTICE,"Nothing to play\n");
216 ts = ast_get_indication_tone(chan->zone, (const char*)data);
217 if (ts && ts->data[0])
218 res = ast_playtones_start(chan, 0, ts->data, 0);
220 res = ast_playtones_start(chan, 0, (const char*)data, 0);
222 ast_log(LOG_NOTICE,"Unable to start playtones\n");
227 * StopPlaylist command stuff
229 static int handle_stopplaytones(struct ast_channel *chan, void *data)
231 ast_playtones_stop(chan);
238 static int ind_load_module(void)
240 struct ast_config *cfg;
241 struct ast_variable *v;
244 struct tone_zone *tones;
245 const char *country = NULL;
247 /* that the following cast is needed, is yuk! */
248 /* yup, checked it out. It is NOT written to. */
249 cfg = ast_config_load((char *)config);
253 /* Use existing config to populate the Indication table */
254 cxt = ast_category_browse(cfg, NULL);
256 /* All categories but "general" are considered countries */
257 if (!strcasecmp(cxt, "general")) {
258 cxt = ast_category_browse(cfg, cxt);
261 tones = malloc(sizeof(struct tone_zone));
263 ast_log(LOG_WARNING,"Out of memory\n");
264 ast_config_destroy(cfg);
267 memset(tones,0,sizeof(struct tone_zone));
268 ast_copy_string(tones->country,cxt,sizeof(tones->country));
270 v = ast_variable_browse(cfg, cxt);
272 if (!strcasecmp(v->name, "description")) {
273 ast_copy_string(tones->description, v->value, sizeof(tones->description));
274 } else if ((!strcasecmp(v->name,"ringcadence"))||(!strcasecmp(v->name,"ringcadance"))) {
275 char *ring,*rings = ast_strdupa(v->value);
277 ring = strsep(&c,",");
280 if (!isdigit(ring[0]) || (val=atoi(ring))==-1) {
281 ast_log(LOG_WARNING,"Invalid ringcadence given '%s' at line %d.\n",ring,v->lineno);
282 ring = strsep(&c,",");
285 tmp = realloc(tones->ringcadence,(tones->nrringcadence+1)*sizeof(int));
287 ast_log(LOG_WARNING, "Out of memory\n");
288 ast_config_destroy(cfg);
291 tones->ringcadence = tmp;
292 tmp[tones->nrringcadence] = val;
293 tones->nrringcadence++;
295 ring = strsep(&c,",");
297 } else if (!strcasecmp(v->name,"alias")) {
298 char *countries = ast_strdupa(v->value);
300 country = strsep(&c,",");
302 struct tone_zone* azone = malloc(sizeof(struct tone_zone));
304 ast_log(LOG_WARNING,"Out of memory\n");
305 ast_config_destroy(cfg);
308 memset(azone,0,sizeof(struct tone_zone));
309 ast_copy_string(azone->country, country, sizeof(azone->country));
310 ast_copy_string(azone->alias, cxt, sizeof(azone->alias));
311 if (ast_register_indication_country(azone)) {
312 ast_log(LOG_WARNING, "Unable to register indication alias at line %d.\n",v->lineno);
316 country = strsep(&c,",");
319 /* add tone to country */
320 struct tone_zone_sound *ps,*ts;
321 for (ps=NULL,ts=tones->tones; ts; ps=ts, ts=ts->next) {
322 if (strcasecmp(v->name,ts->name)==0) {
324 ast_log(LOG_NOTICE,"Duplicate entry '%s', skipped.\n",v->name);
328 /* not there, add it to the back */
329 ts = malloc(sizeof(struct tone_zone_sound));
331 ast_log(LOG_WARNING, "Out of memory\n");
332 ast_config_destroy(cfg);
336 ts->name = strdup(v->name);
337 ts->data = strdup(v->value);
345 if (tones->description[0] || tones->alias[0] || tones->tones) {
346 if (ast_register_indication_country(tones)) {
347 ast_log(LOG_WARNING, "Unable to register indication at line %d.\n",v->lineno);
352 cxt = ast_category_browse(cfg, cxt);
355 /* determine which country is the default */
356 country = ast_variable_retrieve(cfg,"general","country");
357 if (!country || !*country || ast_set_indication_country(country))
358 ast_log(LOG_WARNING,"Unable to set the default country (for indication tones)\n");
360 ast_config_destroy(cfg);
365 * CLI entries for commands provided by this module
367 static struct ast_cli_entry add_indication_cli =
368 { { "indication", "add", NULL }, handle_add_indication,
369 "Add the given indication to the country", help_add_indication,
372 static struct ast_cli_entry remove_indication_cli =
373 { { "indication", "remove", NULL }, handle_remove_indication,
374 "Remove the given indication from the country", help_remove_indication,
377 static struct ast_cli_entry show_indications_cli =
378 { { "show", "indications", NULL }, handle_show_indications,
379 "Show a list of all country/indications", help_show_indications,
383 * Standard module functions ...
385 int unload_module(void)
387 /* remove the registed indications... */
388 ast_unregister_indication_country(NULL);
390 /* and the functions */
391 ast_cli_unregister(&add_indication_cli);
392 ast_cli_unregister(&remove_indication_cli);
393 ast_cli_unregister(&show_indications_cli);
394 ast_unregister_application("PlayTones");
395 ast_unregister_application("StopPlayTones");
400 int load_module(void)
402 if (ind_load_module()) return -1;
404 ast_cli_register(&add_indication_cli);
405 ast_cli_register(&remove_indication_cli);
406 ast_cli_register(&show_indications_cli);
407 ast_register_application("PlayTones", handle_playtones, "Play a tone list", playtones_desc);
408 ast_register_application("StopPlayTones", handle_stopplaytones, "Stop playing a tone list","Stop playing a tone list");
415 /* remove the registed indications... */
416 ast_unregister_indication_country(NULL);
418 return ind_load_module();
421 char *description(void)
423 /* that the following cast is needed, is yuk! */
434 return ASTERISK_GPL_KEY;