aboutsummaryrefslogtreecommitdiffstats
path: root/1.4.23-rc4/res/res_indications.c
diff options
context:
space:
mode:
Diffstat (limited to '1.4.23-rc4/res/res_indications.c')
-rw-r--r--1.4.23-rc4/res/res_indications.c406
1 files changed, 406 insertions, 0 deletions
diff --git a/1.4.23-rc4/res/res_indications.c b/1.4.23-rc4/res/res_indications.c
new file mode 100644
index 000000000..9bff10b76
--- /dev/null
+++ b/1.4.23-rc4/res/res_indications.c
@@ -0,0 +1,406 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2002, Pauline Middelink
+ *
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file res_indications.c
+ *
+ * \brief Load the indications
+ *
+ * \author Pauline Middelink <middelink@polyware.nl>
+ *
+ * Load the country specific dialtones into the asterisk PBX.
+ */
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "asterisk/lock.h"
+#include "asterisk/file.h"
+#include "asterisk/cli.h"
+#include "asterisk/logger.h"
+#include "asterisk/config.h"
+#include "asterisk/channel.h"
+#include "asterisk/pbx.h"
+#include "asterisk/module.h"
+#include "asterisk/translate.h"
+#include "asterisk/indications.h"
+#include "asterisk/utils.h"
+
+/* Globals */
+static const char config[] = "indications.conf";
+
+/*
+ * Help for commands provided by this module ...
+ */
+static char help_add_indication[] =
+"Usage: indication add <country> <indication> \"<tonelist>\"\n"
+" Add the given indication to the country.\n";
+
+static char help_remove_indication[] =
+"Usage: indication remove <country> <indication>\n"
+" Remove the given indication from the country.\n";
+
+static char help_show_indications[] =
+"Usage: indication show [<country> ...]\n"
+" Display either a condensed for of all country/indications, or the\n"
+" indications for the specified countries.\n";
+
+char *playtones_desc=
+"PlayTones(arg): Plays a tone list. Execution will continue with the next step immediately,\n"
+"while the tones continue to play.\n"
+"Arg is either the tone name defined in the indications.conf configuration file, or a directly\n"
+"specified list of frequencies and durations.\n"
+"See the sample indications.conf for a description of the specification of a tonelist.\n\n"
+"Use the StopPlayTones application to stop the tones playing. \n";
+
+/*
+ * Implementation of functions provided by this module
+ */
+
+/*
+ * ADD INDICATION command stuff
+ */
+static int handle_add_indication(int fd, int argc, char *argv[])
+{
+ struct tone_zone *tz;
+ int created_country = 0;
+ if (argc != 5) return RESULT_SHOWUSAGE;
+
+ tz = ast_get_indication_zone(argv[2]);
+ if (!tz) {
+ /* country does not exist, create it */
+ ast_log(LOG_NOTICE, "Country '%s' does not exist, creating it.\n",argv[2]);
+
+ if (!(tz = ast_calloc(1, sizeof(*tz)))) {
+ return -1;
+ }
+ ast_copy_string(tz->country,argv[2],sizeof(tz->country));
+ if (ast_register_indication_country(tz)) {
+ ast_log(LOG_WARNING, "Unable to register new country\n");
+ free(tz);
+ return -1;
+ }
+ created_country = 1;
+ }
+ if (ast_register_indication(tz,argv[3],argv[4])) {
+ ast_log(LOG_WARNING, "Unable to register indication %s/%s\n",argv[2],argv[3]);
+ if (created_country)
+ ast_unregister_indication_country(argv[2]);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * REMOVE INDICATION command stuff
+ */
+static int handle_remove_indication(int fd, int argc, char *argv[])
+{
+ struct tone_zone *tz;
+ if (argc != 3 && argc != 4) return RESULT_SHOWUSAGE;
+
+ if (argc == 3) {
+ /* remove entiry country */
+ if (ast_unregister_indication_country(argv[2])) {
+ ast_log(LOG_WARNING, "Unable to unregister indication country %s\n",argv[2]);
+ return -1;
+ }
+ return 0;
+ }
+
+ tz = ast_get_indication_zone(argv[2]);
+ if (!tz) {
+ ast_log(LOG_WARNING, "Unable to unregister indication %s/%s, country does not exists\n",argv[2],argv[3]);
+ return -1;
+ }
+ if (ast_unregister_indication(tz,argv[3])) {
+ ast_log(LOG_WARNING, "Unable to unregister indication %s/%s\n",argv[2],argv[3]);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * SHOW INDICATIONS command stuff
+ */
+static int handle_show_indications(int fd, int argc, char *argv[])
+{
+ struct tone_zone *tz = NULL;
+ char buf[256];
+ int found_country = 0;
+
+ if (argc == 2) {
+ /* no arguments, show a list of countries */
+ ast_cli(fd,"Country Alias Description\n"
+ "===========================\n");
+ while ( (tz = ast_walk_indications(tz) ) )
+ ast_cli(fd,"%-7.7s %-7.7s %s\n", tz->country, tz->alias, tz->description);
+ return 0;
+ }
+ /* there was a request for specific country(ies), lets humor them */
+ while ( (tz = ast_walk_indications(tz) ) ) {
+ int i,j;
+ for (i=2; i<argc; i++) {
+ if (strcasecmp(tz->country,argv[i])==0 &&
+ !tz->alias[0]) {
+ struct tone_zone_sound* ts;
+ if (!found_country) {
+ found_country = 1;
+ ast_cli(fd,"Country Indication PlayList\n"
+ "=====================================\n");
+ }
+ j = snprintf(buf,sizeof(buf),"%-7.7s %-15.15s ",tz->country,"<ringcadence>");
+ for (i=0; i<tz->nrringcadence; i++) {
+ j += snprintf(buf+j,sizeof(buf)-j,"%d,",tz->ringcadence[i]);
+ }
+ if (tz->nrringcadence)
+ j--;
+ ast_copy_string(buf+j,"\n",sizeof(buf)-j);
+ ast_cli(fd, "%s", buf);
+ for (ts=tz->tones; ts; ts=ts->next)
+ ast_cli(fd,"%-7.7s %-15.15s %s\n",tz->country,ts->name,ts->data);
+ break;
+ }
+ }
+ }
+ if (!found_country)
+ ast_cli(fd,"No countries matched your criteria.\n");
+ return -1;
+}
+
+/*
+ * Playtones command stuff
+ */
+static int handle_playtones(struct ast_channel *chan, void *data)
+{
+ struct tone_zone_sound *ts;
+ int res;
+
+ if (!data || !((char*)data)[0]) {
+ ast_log(LOG_NOTICE,"Nothing to play\n");
+ return -1;
+ }
+ ts = ast_get_indication_tone(chan->zone, (const char*)data);
+ if (ts && ts->data[0])
+ res = ast_playtones_start(chan, 0, ts->data, 0);
+ else
+ res = ast_playtones_start(chan, 0, (const char*)data, 0);
+ if (res)
+ ast_log(LOG_NOTICE,"Unable to start playtones\n");
+ return res;
+}
+
+/*
+ * StopPlaylist command stuff
+ */
+static int handle_stopplaytones(struct ast_channel *chan, void *data)
+{
+ ast_playtones_stop(chan);
+ return 0;
+}
+
+/*
+ * Load module stuff
+ */
+static int ind_load_module(void)
+{
+ struct ast_config *cfg;
+ struct ast_variable *v;
+ char *cxt;
+ char *c;
+ struct tone_zone *tones;
+ const char *country = NULL;
+
+ /* that the following cast is needed, is yuk! */
+ /* yup, checked it out. It is NOT written to. */
+ cfg = ast_config_load((char *)config);
+ if (!cfg)
+ return -1;
+
+ /* Use existing config to populate the Indication table */
+ cxt = ast_category_browse(cfg, NULL);
+ while(cxt) {
+ /* All categories but "general" are considered countries */
+ if (!strcasecmp(cxt, "general")) {
+ cxt = ast_category_browse(cfg, cxt);
+ continue;
+ }
+ if (!(tones = ast_calloc(1, sizeof(*tones)))) {
+ ast_config_destroy(cfg);
+ return -1;
+ }
+ ast_copy_string(tones->country,cxt,sizeof(tones->country));
+
+ v = ast_variable_browse(cfg, cxt);
+ while(v) {
+ if (!strcasecmp(v->name, "description")) {
+ ast_copy_string(tones->description, v->value, sizeof(tones->description));
+ } else if ((!strcasecmp(v->name,"ringcadence"))||(!strcasecmp(v->name,"ringcadance"))) {
+ char *ring,*rings = ast_strdupa(v->value);
+ c = rings;
+ ring = strsep(&c,",");
+ while (ring) {
+ int *tmp, val;
+ if (!isdigit(ring[0]) || (val=atoi(ring))==-1) {
+ ast_log(LOG_WARNING,"Invalid ringcadence given '%s' at line %d.\n",ring,v->lineno);
+ ring = strsep(&c,",");
+ continue;
+ }
+ if (!(tmp = ast_realloc(tones->ringcadence, (tones->nrringcadence + 1) * sizeof(int)))) {
+ ast_config_destroy(cfg);
+ return -1;
+ }
+ tones->ringcadence = tmp;
+ tmp[tones->nrringcadence] = val;
+ tones->nrringcadence++;
+ /* next item */
+ ring = strsep(&c,",");
+ }
+ } else if (!strcasecmp(v->name,"alias")) {
+ char *countries = ast_strdupa(v->value);
+ c = countries;
+ country = strsep(&c,",");
+ while (country) {
+ struct tone_zone* azone;
+ if (!(azone = ast_calloc(1, sizeof(*azone)))) {
+ ast_config_destroy(cfg);
+ return -1;
+ }
+ ast_copy_string(azone->country, country, sizeof(azone->country));
+ ast_copy_string(azone->alias, cxt, sizeof(azone->alias));
+ if (ast_register_indication_country(azone)) {
+ ast_log(LOG_WARNING, "Unable to register indication alias at line %d.\n",v->lineno);
+ free(tones);
+ }
+ /* next item */
+ country = strsep(&c,",");
+ }
+ } else {
+ /* add tone to country */
+ struct tone_zone_sound *ps,*ts;
+ for (ps=NULL,ts=tones->tones; ts; ps=ts, ts=ts->next) {
+ if (strcasecmp(v->name,ts->name)==0) {
+ /* already there */
+ ast_log(LOG_NOTICE,"Duplicate entry '%s', skipped.\n",v->name);
+ goto out;
+ }
+ }
+ /* not there, add it to the back */
+ if (!(ts = ast_malloc(sizeof(*ts)))) {
+ ast_config_destroy(cfg);
+ return -1;
+ }
+ ts->next = NULL;
+ ts->name = strdup(v->name);
+ ts->data = strdup(v->value);
+ if (ps)
+ ps->next = ts;
+ else
+ tones->tones = ts;
+ }
+out: v = v->next;
+ }
+ if (tones->description[0] || tones->alias[0] || tones->tones) {
+ if (ast_register_indication_country(tones)) {
+ ast_log(LOG_WARNING, "Unable to register indication at line %d.\n",v->lineno);
+ free(tones);
+ }
+ } else free(tones);
+
+ cxt = ast_category_browse(cfg, cxt);
+ }
+
+ /* determine which country is the default */
+ country = ast_variable_retrieve(cfg,"general","country");
+ if (!country || !*country || ast_set_indication_country(country))
+ ast_log(LOG_WARNING,"Unable to set the default country (for indication tones)\n");
+
+ ast_config_destroy(cfg);
+ return 0;
+}
+
+/*
+ * CLI entries for commands provided by this module
+ */
+static struct ast_cli_entry cli_show_indications_deprecated = {
+ { "show", "indications", NULL },
+ handle_show_indications, NULL,
+ NULL };
+
+static struct ast_cli_entry cli_indications[] = {
+ { { "indication", "add", NULL },
+ handle_add_indication, "Add the given indication to the country",
+ help_add_indication, NULL },
+
+ { { "indication", "remove", NULL },
+ handle_remove_indication, "Remove the given indication from the country",
+ help_remove_indication, NULL },
+
+ { { "indication", "show", NULL },
+ handle_show_indications, "Display a list of all countries/indications",
+ help_show_indications, NULL, &cli_show_indications_deprecated },
+};
+
+/*
+ * Standard module functions ...
+ */
+static int unload_module(void)
+{
+ /* remove the registed indications... */
+ ast_unregister_indication_country(NULL);
+
+ /* and the functions */
+ ast_cli_unregister_multiple(cli_indications, sizeof(cli_indications) / sizeof(struct ast_cli_entry));
+ ast_unregister_application("PlayTones");
+ ast_unregister_application("StopPlayTones");
+ return 0;
+}
+
+
+static int load_module(void)
+{
+ if (ind_load_module())
+ return AST_MODULE_LOAD_DECLINE;
+ ast_cli_register_multiple(cli_indications, sizeof(cli_indications) / sizeof(struct ast_cli_entry));
+ ast_register_application("PlayTones", handle_playtones, "Play a tone list", playtones_desc);
+ ast_register_application("StopPlayTones", handle_stopplaytones, "Stop playing a tone list","Stop playing a tone list");
+
+ return 0;
+}
+
+static int reload(void)
+{
+ /* remove the registed indications... */
+ ast_unregister_indication_country(NULL);
+
+ return ind_load_module();
+}
+
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Indications Resource",
+ .load = load_module,
+ .unload = unload_module,
+ .reload = reload,
+ );