00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "asterisk.h"
00028
00029 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 182808 $")
00030
00031 #include <unistd.h>
00032 #include <string.h>
00033 #include <ctype.h>
00034 #include <stdlib.h>
00035 #include <stdio.h>
00036 #include <errno.h>
00037 #include <sys/types.h>
00038 #include <sys/stat.h>
00039
00040 #include "asterisk/lock.h"
00041 #include "asterisk/file.h"
00042 #include "asterisk/cli.h"
00043 #include "asterisk/logger.h"
00044 #include "asterisk/config.h"
00045 #include "asterisk/channel.h"
00046 #include "asterisk/pbx.h"
00047 #include "asterisk/module.h"
00048 #include "asterisk/translate.h"
00049 #include "asterisk/indications.h"
00050 #include "asterisk/utils.h"
00051
00052
00053 static const char config[] = "indications.conf";
00054
00055
00056
00057
00058 static char help_add_indication[] =
00059 "Usage: indication add <country> <indication> \"<tonelist>\"\n"
00060 " Add the given indication to the country.\n";
00061
00062 static char help_remove_indication[] =
00063 "Usage: indication remove <country> <indication>\n"
00064 " Remove the given indication from the country.\n";
00065
00066 static char help_show_indications[] =
00067 "Usage: indication show [<country> ...]\n"
00068 " Display either a condensed for of all country/indications, or the\n"
00069 " indications for the specified countries.\n";
00070
00071 char *playtones_desc=
00072 "PlayTones(arg): Plays a tone list. Execution will continue with the next step immediately,\n"
00073 "while the tones continue to play.\n"
00074 "Arg is either the tone name defined in the indications.conf configuration file, or a directly\n"
00075 "specified list of frequencies and durations.\n"
00076 "See the sample indications.conf for a description of the specification of a tonelist.\n\n"
00077 "Use the StopPlayTones application to stop the tones playing. \n";
00078
00079
00080
00081
00082
00083
00084
00085
00086 static int handle_add_indication(int fd, int argc, char *argv[])
00087 {
00088 struct tone_zone *tz;
00089 int created_country = 0;
00090 if (argc != 5) return RESULT_SHOWUSAGE;
00091
00092 tz = ast_get_indication_zone(argv[2]);
00093 if (!tz) {
00094
00095 ast_log(LOG_NOTICE, "Country '%s' does not exist, creating it.\n",argv[2]);
00096
00097 if (!(tz = ast_calloc(1, sizeof(*tz)))) {
00098 return -1;
00099 }
00100 ast_copy_string(tz->country,argv[2],sizeof(tz->country));
00101 if (ast_register_indication_country(tz)) {
00102 ast_log(LOG_WARNING, "Unable to register new country\n");
00103 free(tz);
00104 return -1;
00105 }
00106 created_country = 1;
00107 }
00108 if (ast_register_indication(tz,argv[3],argv[4])) {
00109 ast_log(LOG_WARNING, "Unable to register indication %s/%s\n",argv[2],argv[3]);
00110 if (created_country)
00111 ast_unregister_indication_country(argv[2]);
00112 return -1;
00113 }
00114 return 0;
00115 }
00116
00117
00118
00119
00120 static int handle_remove_indication(int fd, int argc, char *argv[])
00121 {
00122 struct tone_zone *tz;
00123 if (argc != 3 && argc != 4) return RESULT_SHOWUSAGE;
00124
00125 if (argc == 3) {
00126
00127 if (ast_unregister_indication_country(argv[2])) {
00128 ast_log(LOG_WARNING, "Unable to unregister indication country %s\n",argv[2]);
00129 return -1;
00130 }
00131 return 0;
00132 }
00133
00134 tz = ast_get_indication_zone(argv[2]);
00135 if (!tz) {
00136 ast_log(LOG_WARNING, "Unable to unregister indication %s/%s, country does not exists\n",argv[2],argv[3]);
00137 return -1;
00138 }
00139 if (ast_unregister_indication(tz,argv[3])) {
00140 ast_log(LOG_WARNING, "Unable to unregister indication %s/%s\n",argv[2],argv[3]);
00141 return -1;
00142 }
00143 return 0;
00144 }
00145
00146
00147
00148
00149 static int handle_show_indications(int fd, int argc, char *argv[])
00150 {
00151 struct tone_zone *tz = NULL;
00152 char buf[256];
00153 int found_country = 0;
00154
00155 if (argc == 2) {
00156
00157 ast_cli(fd,"Country Alias Description\n"
00158 "===========================\n");
00159 while ( (tz = ast_walk_indications(tz) ) )
00160 ast_cli(fd,"%-7.7s %-7.7s %s\n", tz->country, tz->alias, tz->description);
00161 return 0;
00162 }
00163
00164 while ( (tz = ast_walk_indications(tz) ) ) {
00165 int i,j;
00166 for (i=2; i<argc; i++) {
00167 if (strcasecmp(tz->country,argv[i])==0 &&
00168 !tz->alias[0]) {
00169 struct tone_zone_sound* ts;
00170 if (!found_country) {
00171 found_country = 1;
00172 ast_cli(fd,"Country Indication PlayList\n"
00173 "=====================================\n");
00174 }
00175 j = snprintf(buf,sizeof(buf),"%-7.7s %-15.15s ",tz->country,"<ringcadence>");
00176 for (i=0; i<tz->nrringcadence; i++) {
00177 j += snprintf(buf+j,sizeof(buf)-j,"%d,",tz->ringcadence[i]);
00178 }
00179 if (tz->nrringcadence)
00180 j--;
00181 ast_copy_string(buf+j,"\n",sizeof(buf)-j);
00182 ast_cli(fd, "%s", buf);
00183 for (ts=tz->tones; ts; ts=ts->next)
00184 ast_cli(fd,"%-7.7s %-15.15s %s\n",tz->country,ts->name,ts->data);
00185 break;
00186 }
00187 }
00188 }
00189 if (!found_country)
00190 ast_cli(fd,"No countries matched your criteria.\n");
00191 return -1;
00192 }
00193
00194
00195
00196
00197 static int handle_playtones(struct ast_channel *chan, void *data)
00198 {
00199 struct tone_zone_sound *ts;
00200 int res;
00201
00202 if (!data || !((char*)data)[0]) {
00203 ast_log(LOG_NOTICE,"Nothing to play\n");
00204 return -1;
00205 }
00206 ts = ast_get_indication_tone(chan->zone, (const char*)data);
00207 if (ts && ts->data[0])
00208 res = ast_playtones_start(chan, 0, ts->data, 0);
00209 else
00210 res = ast_playtones_start(chan, 0, (const char*)data, 0);
00211 if (res)
00212 ast_log(LOG_NOTICE,"Unable to start playtones\n");
00213 return res;
00214 }
00215
00216
00217
00218
00219 static int handle_stopplaytones(struct ast_channel *chan, void *data)
00220 {
00221 ast_playtones_stop(chan);
00222 return 0;
00223 }
00224
00225
00226
00227
00228 static int ind_load_module(void)
00229 {
00230 struct ast_config *cfg;
00231 struct ast_variable *v;
00232 char *cxt;
00233 char *c;
00234 struct tone_zone *tones;
00235 const char *country = NULL;
00236
00237
00238
00239 cfg = ast_config_load((char *)config);
00240 if (!cfg)
00241 return -1;
00242
00243
00244 cxt = ast_category_browse(cfg, NULL);
00245 while(cxt) {
00246
00247 if (!strcasecmp(cxt, "general")) {
00248 cxt = ast_category_browse(cfg, cxt);
00249 continue;
00250 }
00251 if (!(tones = ast_calloc(1, sizeof(*tones)))) {
00252 ast_config_destroy(cfg);
00253 return -1;
00254 }
00255 ast_copy_string(tones->country,cxt,sizeof(tones->country));
00256
00257 v = ast_variable_browse(cfg, cxt);
00258 while(v) {
00259 if (!strcasecmp(v->name, "description")) {
00260 ast_copy_string(tones->description, v->value, sizeof(tones->description));
00261 } else if ((!strcasecmp(v->name,"ringcadence"))||(!strcasecmp(v->name,"ringcadance"))) {
00262 char *ring,*rings = ast_strdupa(v->value);
00263 c = rings;
00264 ring = strsep(&c,",");
00265 while (ring) {
00266 int *tmp, val;
00267 if (!isdigit(ring[0]) || (val=atoi(ring))==-1) {
00268 ast_log(LOG_WARNING,"Invalid ringcadence given '%s' at line %d.\n",ring,v->lineno);
00269 ring = strsep(&c,",");
00270 continue;
00271 }
00272 if (!(tmp = ast_realloc(tones->ringcadence, (tones->nrringcadence + 1) * sizeof(int)))) {
00273 ast_config_destroy(cfg);
00274 return -1;
00275 }
00276 tones->ringcadence = tmp;
00277 tmp[tones->nrringcadence] = val;
00278 tones->nrringcadence++;
00279
00280 ring = strsep(&c,",");
00281 }
00282 } else if (!strcasecmp(v->name,"alias")) {
00283 char *countries = ast_strdupa(v->value);
00284 c = countries;
00285 country = strsep(&c,",");
00286 while (country) {
00287 struct tone_zone* azone;
00288 if (!(azone = ast_calloc(1, sizeof(*azone)))) {
00289 ast_config_destroy(cfg);
00290 return -1;
00291 }
00292 ast_copy_string(azone->country, country, sizeof(azone->country));
00293 ast_copy_string(azone->alias, cxt, sizeof(azone->alias));
00294 if (ast_register_indication_country(azone)) {
00295 ast_log(LOG_WARNING, "Unable to register indication alias at line %d.\n",v->lineno);
00296 free(tones);
00297 }
00298
00299 country = strsep(&c,",");
00300 }
00301 } else {
00302
00303 struct tone_zone_sound *ps,*ts;
00304 for (ps=NULL,ts=tones->tones; ts; ps=ts, ts=ts->next) {
00305 if (strcasecmp(v->name,ts->name)==0) {
00306
00307 ast_log(LOG_NOTICE,"Duplicate entry '%s', skipped.\n",v->name);
00308 goto out;
00309 }
00310 }
00311
00312 if (!(ts = ast_malloc(sizeof(*ts)))) {
00313 ast_config_destroy(cfg);
00314 return -1;
00315 }
00316 ts->next = NULL;
00317 ts->name = strdup(v->name);
00318 ts->data = strdup(v->value);
00319 if (ps)
00320 ps->next = ts;
00321 else
00322 tones->tones = ts;
00323 }
00324 out: v = v->next;
00325 }
00326 if (tones->description[0] || tones->alias[0] || tones->tones) {
00327 if (ast_register_indication_country(tones)) {
00328 ast_log(LOG_WARNING, "Unable to register indication at line %d.\n",v->lineno);
00329 free(tones);
00330 }
00331 } else free(tones);
00332
00333 cxt = ast_category_browse(cfg, cxt);
00334 }
00335
00336
00337 country = ast_variable_retrieve(cfg,"general","country");
00338 if (!country || !*country || ast_set_indication_country(country))
00339 ast_log(LOG_WARNING,"Unable to set the default country (for indication tones)\n");
00340
00341 ast_config_destroy(cfg);
00342 return 0;
00343 }
00344
00345
00346
00347
00348 static struct ast_cli_entry cli_show_indications_deprecated = {
00349 { "show", "indications", NULL },
00350 handle_show_indications, NULL,
00351 NULL };
00352
00353 static struct ast_cli_entry cli_indications[] = {
00354 { { "indication", "add", NULL },
00355 handle_add_indication, "Add the given indication to the country",
00356 help_add_indication, NULL },
00357
00358 { { "indication", "remove", NULL },
00359 handle_remove_indication, "Remove the given indication from the country",
00360 help_remove_indication, NULL },
00361
00362 { { "indication", "show", NULL },
00363 handle_show_indications, "Display a list of all countries/indications",
00364 help_show_indications, NULL, &cli_show_indications_deprecated },
00365 };
00366
00367
00368
00369
00370 static int unload_module(void)
00371 {
00372
00373 ast_unregister_indication_country(NULL);
00374
00375
00376 ast_cli_unregister_multiple(cli_indications, sizeof(cli_indications) / sizeof(struct ast_cli_entry));
00377 ast_unregister_application("PlayTones");
00378 ast_unregister_application("StopPlayTones");
00379 return 0;
00380 }
00381
00382
00383 static int load_module(void)
00384 {
00385 if (ind_load_module())
00386 return AST_MODULE_LOAD_DECLINE;
00387 ast_cli_register_multiple(cli_indications, sizeof(cli_indications) / sizeof(struct ast_cli_entry));
00388 ast_register_application("PlayTones", handle_playtones, "Play a tone list", playtones_desc);
00389 ast_register_application("StopPlayTones", handle_stopplaytones, "Stop playing a tone list","Stop playing a tone list");
00390
00391 return 0;
00392 }
00393
00394 static int reload(void)
00395 {
00396
00397 ast_unregister_indication_country(NULL);
00398
00399 return ind_load_module();
00400 }
00401
00402 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Indications Resource",
00403 .load = load_module,
00404 .unload = unload_module,
00405 .reload = reload,
00406 );