Mon Mar 20 08:25:44 2006

Asterisk developer's documentation


Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

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 <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 /* Globals */
00053 static const char dtext[] = "Indications Configuration";
00054 static const char config[] = "indications.conf";
00055 
00056 /*
00057  * Help for commands provided by this module ...
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  * Implementation of functions provided by this module
00082  */
00083 
00084 /*
00085  * ADD INDICATION command stuff
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       /* country does not exist, create it */
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  * REMOVE INDICATION command stuff
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       /* remove entiry country */
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  * SHOW INDICATIONS command stuff
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       /* no arguments, show a list of countries */
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    /* there was a request for specific country(ies), lets humor them */
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  * Playtones command stuff
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  * StopPlaylist command stuff
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  * Load module stuff
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    /* that the following cast is needed, is yuk! */
00248    /* yup, checked it out. It is NOT written to. */
00249    cfg = ast_config_load((char *)config);
00250    if (!cfg)
00251       return 0;
00252 
00253    /* Use existing config to populate the Indication table */
00254    cxt = ast_category_browse(cfg, NULL);
00255    while(cxt) {
00256       /* All categories but "general" are considered countries */
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                /* next item */
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                /* next item */
00316                country = strsep(&c,",");
00317             }
00318          } else {
00319             /* add tone to country */
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                   /* already there */
00324                   ast_log(LOG_NOTICE,"Duplicate entry '%s', skipped.\n",v->name);
00325                   goto out;
00326                }
00327             }
00328             /* not there, add it to the back */
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    /* determine which country is the default */
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  * CLI entries for commands provided by this module
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  * Standard module functions ...
00384  */
00385 int unload_module(void)
00386 {
00387    /* remove the registed indications... */
00388    ast_unregister_indication_country(NULL);
00389 
00390    /* and the functions */
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    /* remove the registed indications... */
00416    ast_unregister_indication_country(NULL);
00417 
00418    return ind_load_module();
00419 }
00420 
00421 char *description(void)
00422 {
00423    /* that the following cast is needed, is yuk! */
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 }

Generated on Mon Mar 20 08:25:44 2006 for Asterisk - the Open Source PBX by  doxygen 1.3.9.1