Sat Aug 6 00:39:31 2011

Asterisk developer's documentation


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: 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 /* 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 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 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 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 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  * Playtones command stuff
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  * 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 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 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 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_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  * Standard module functions ...
00369  */
00370 static int unload_module(void)
00371 {
00372    /* remove the registed indications... */
00373    ast_unregister_indication_country(NULL);
00374 
00375    /* and the functions */
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    /* remove the registed indications... */
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           );

Generated on Sat Aug 6 00:39:31 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7