![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
res_indications.c
Go to the documentation of this file.
00001 /* 00002 * Asterisk -- An open source telephony toolkit. 00003 * 00004 * Copyright (C) 2002, Pauline Middelink 00005 * 00006 * 00007 * See http://www.asterisk.org for more information about 00008 * the Asterisk project. Please do not directly contact 00009 * any of the maintainers of this project for assistance; 00010 * the project provides a web site, mailing lists and IRC 00011 * channels for your use. 00012 * 00013 * This program is free software, distributed under the terms of 00014 * the GNU General Public License Version 2. See the LICENSE file 00015 * at the top of the source tree. 00016 */ 00017 00018 /*! \file res_indications.c 00019 * 00020 * \brief Load the indications 00021 * 00022 * \author Pauline Middelink <middelink@polyware.nl> 00023 * 00024 * Load the country specific dialtones into the asterisk PBX. 00025 */ 00026 00027 #include "asterisk.h" 00028 00029 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 49116 $") 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 /* Globals */ 00053 static const char config[] = "indications.conf"; 00054 00055 /* 00056 * Help for commands provided by this module ... 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 * Implementation of functions provided by this module 00081 */ 00082 00083 /* 00084 * ADD INDICATION command stuff 00085 */ 00086 static int handle_add_indication(int fd, int argc, char *argv[]) 00087 { 00088 struct ind_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 /* country does not exist, create it */ 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 * REMOVE INDICATION command stuff 00119 */ 00120 static int handle_remove_indication(int fd, int argc, char *argv[]) 00121 { 00122 struct ind_tone_zone *tz; 00123 if (argc != 3 && argc != 4) return RESULT_SHOWUSAGE; 00124 00125 if (argc == 3) { 00126 /* remove entiry country */ 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 * SHOW INDICATIONS command stuff 00148 */ 00149 static int handle_show_indications(int fd, int argc, char *argv[]) 00150 { 00151 struct ind_tone_zone *tz = NULL; 00152 char buf[256]; 00153 int found_country = 0; 00154 00155 if (argc == 2) { 00156 /* no arguments, show a list of countries */ 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 /* there was a request for specific country(ies), lets humor them */ 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 ind_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,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 * Playtones command stuff 00196 */ 00197 static int handle_playtones(struct ast_channel *chan, void *data) 00198 { 00199 struct ind_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 * StopPlaylist command stuff 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 * Load module stuff 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 ind_tone_zone *tones; 00235 const char *country = NULL; 00236 00237 /* that the following cast is needed, is yuk! */ 00238 /* yup, checked it out. It is NOT written to. */ 00239 cfg = ast_config_load((char *)config); 00240 if (!cfg) 00241 return -1; 00242 00243 /* Use existing config to populate the Indication table */ 00244 cxt = ast_category_browse(cfg, NULL); 00245 while(cxt) { 00246 /* All categories but "general" are considered countries */ 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 /* next item */ 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 ind_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 /* next item */ 00299 country = strsep(&c,","); 00300 } 00301 } else { 00302 /* add tone to country */ 00303 struct ind_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 /* already there */ 00307 ast_log(LOG_NOTICE,"Duplicate entry '%s', skipped.\n",v->name); 00308 goto out; 00309 } 00310 } 00311 /* not there, add it to the back */ 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 /* determine which country is the default */ 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 * CLI entries for commands provided by this module 00347 */ 00348 static struct ast_cli_entry cli_indications[] = { 00349 { { "indication", "add", NULL }, 00350 handle_add_indication, "Add the given indication to the country", 00351 help_add_indication, NULL }, 00352 00353 { { "indication", "remove", NULL }, 00354 handle_remove_indication, "Remove the given indication from the country", 00355 help_remove_indication, NULL }, 00356 00357 { { "indication", "show", NULL }, 00358 handle_show_indications, "Display a list of all countries/indications", 00359 help_show_indications }, 00360 }; 00361 00362 /* 00363 * Standard module functions ... 00364 */ 00365 static int unload_module(void) 00366 { 00367 /* remove the registed indications... */ 00368 ast_unregister_indication_country(NULL); 00369 00370 /* and the functions */ 00371 ast_cli_unregister_multiple(cli_indications, sizeof(cli_indications) / sizeof(struct ast_cli_entry)); 00372 ast_unregister_application("PlayTones"); 00373 ast_unregister_application("StopPlayTones"); 00374 return 0; 00375 } 00376 00377 00378 static int load_module(void) 00379 { 00380 if (ind_load_module()) 00381 return AST_MODULE_LOAD_DECLINE; 00382 ast_cli_register_multiple(cli_indications, sizeof(cli_indications) / sizeof(struct ast_cli_entry)); 00383 ast_register_application("PlayTones", handle_playtones, "Play a tone list", playtones_desc); 00384 ast_register_application("StopPlayTones", handle_stopplaytones, "Stop playing a tone list","Stop playing a tone list"); 00385 00386 return 0; 00387 } 00388 00389 static int reload(void) 00390 { 00391 /* remove the registed indications... */ 00392 ast_unregister_indication_country(NULL); 00393 00394 return ind_load_module(); 00395 } 00396 00397 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Indications Resource", 00398 .load = load_module, 00399 .unload = unload_module, 00400 .reload = reload, 00401 );