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