Asterisk - The Open Source Telephony Project  21.4.1
Data Structures | Macros | Functions | Variables
indications.c File Reference

Indication Tone Handling. More...

#include "asterisk.h"
#include <math.h>
#include "asterisk/lock.h"
#include "asterisk/linkedlists.h"
#include "asterisk/indications.h"
#include "asterisk/frame.h"
#include "asterisk/format_cache.h"
#include "asterisk/channel.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
#include "asterisk/module.h"
#include "asterisk/astobj2.h"
#include "asterisk/_private.h"

Go to the source code of this file.

Data Structures

struct  playtones_def
 
struct  playtones_item
 
struct  playtones_state
 

Macros

#define NUM_TONE_ZONE_BUCKETS   53
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_tone_zone_soundast_get_indication_tone (const struct ast_tone_zone *_zone, const char *indication)
 Locate a tone zone sound. More...
 
struct ast_tone_zoneast_get_indication_zone (const char *country)
 locate ast_tone_zone, given the country. if country == NULL, use the default country More...
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
int ast_playtones_start (struct ast_channel *chan, int vol, const char *playlst, int interruptible)
 Start playing a list of tones on a channel. More...
 
void ast_playtones_stop (struct ast_channel *chan)
 Stop playing tones on a channel. More...
 
static int ast_register_indication (struct ast_tone_zone *zone, const char *indication, const char *tonelist)
 
static int ast_register_indication_country (struct ast_tone_zone *zone)
 add a new country, if country exists, it will be replaced.
 
static int ast_set_indication_country (const char *country)
 Set global indication country If no country is specified or we are unable to find the zone, then return not found.
 
static struct ast_tone_zoneast_tone_zone_alloc (void)
 
static int ast_tone_zone_cmp (void *obj, void *arg, int flags)
 
int ast_tone_zone_count (void)
 Get the number of registered tone zones. More...
 
static void ast_tone_zone_destructor (void *obj)
 deallocate the passed tone zone
 
static int ast_tone_zone_hash (const void *obj, const int flags)
 
struct ao2_iterator ast_tone_zone_iterator_init (void)
 Get an iterator for the available tone zones. More...
 
int ast_tone_zone_part_parse (const char *s, struct ast_tone_zone_part *tone_data)
 Parse a tone part. More...
 
static void ast_tone_zone_sound_destructor (void *obj)
 
static int ast_unregister_indication (struct ast_tone_zone *zone, const char *indication)
 remove an existing country's indication. Both country and indication must exist
 
static int ast_unregister_indication_country (const char *country)
 remove an existing country and all its indications, country must exist.
 
static char * complete_country (struct ast_cli_args *a)
 
static char * complete_indications (struct ast_cli_args *a)
 
static char * handle_cli_indication_add (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_indication_remove (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_indication_show (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int is_valid_tone_zone (struct ast_tone_zone *zone)
 
static int load_indications (int reload)
 load indications module
 
static int load_module (void)
 Load indications module.
 
static int parse_tone_zone (struct ast_config *cfg, const char *country)
 
static void * playtones_alloc (struct ast_channel *chan, void *params)
 
static int playtones_generator (struct ast_channel *chan, void *data, int len, int samples)
 
static void playtones_release (struct ast_channel *chan, void *params)
 
static int prune_tone_zone (void *obj, void *arg, int flags)
 Prune tones no longer in the configuration, and have the tone zone unlinked if it is no longer in the configuration at all.
 
static int reload_module (void)
 Reload indications module.
 
static void reset_tone_zone (struct ast_tone_zone *zone)
 
static void store_config_tone_zone (struct ast_tone_zone *zone, const char *var, const char *value)
 
static void store_tone_zone_ring_cadence (struct ast_tone_zone *zone, const char *val)
 
static int tone_zone_mark (void *obj, void *arg, int flags)
 Mark the zone and its tones before parsing configuration. We will use this to know what to remove after configuration is parsed.
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Indication Tone Handling" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "da6642af068ee5e6490c5b1d2cc1d238" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CORE, .requires = "extconfig", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ao2_containerast_tone_zones
 
static struct ast_cli_entry cli_indications []
 CLI entries for commands provided by this module. More...
 
static const char config [] = "indications.conf"
 
static struct ast_tone_zonedefault_tone_zone
 
static const int midi_tohz [128]
 
static struct ast_generator playtones
 

Detailed Description

Indication Tone Handling.

Author
Pauline Middelink midde.nosp@m.link.nosp@m.@poly.nosp@m.ware.nosp@m..nl
Russell Bryant russe.nosp@m.ll@d.nosp@m.igium.nosp@m..com

Definition in file indications.c.

Function Documentation

struct ast_tone_zone_sound* ast_get_indication_tone ( const struct ast_tone_zone zone,
const char *  indication 
)

Locate a tone zone sound.

Parameters
zoneZone to look in for a sound, if NULL, the default will be used
indicationSound to look for, such as "busy"
Returns
a reference to the specified sound if it exists, NULL if not

Definition at line 461 of file indications.c.

References AST_LIST_TRAVERSE, ast_tone_zone_lock, ast_tone_zone_ref(), ast_tone_zone_sound_ref(), ast_tone_zone_unlock, ast_tone_zone_unref(), ast_tone_zone_sound::name, and ast_tone_zone::tones.

Referenced by ast_app_dtget(), ast_control_tone(), and indicate_data_internal().

462 {
463  struct ast_tone_zone_sound *ts = NULL;
464  /* _zone is const to the users of the API */
465  struct ast_tone_zone *zone = (struct ast_tone_zone *) _zone;
466 
467  /* If no zone is specified, use the default */
468  if (!zone) {
469  ao2_lock(ast_tone_zones);
470  if (default_tone_zone) {
472  }
473  ao2_unlock(ast_tone_zones);
474 
475  if (!zone) {
476  return NULL;
477  }
478  }
479 
480  ast_tone_zone_lock(zone);
481 
482  /* Look through list of tones in the zone searching for the right one */
483  AST_LIST_TRAVERSE(&zone->tones, ts, entry) {
484  if (!strcasecmp(ts->name, indication)) {
485  /* Increase ref count for the reference we will return */
486  ts = ast_tone_zone_sound_ref(ts);
487  break;
488  }
489  }
490 
491  ast_tone_zone_unlock(zone);
492 
493  if (!_zone)
494  zone = ast_tone_zone_unref(zone);
495 
496  return ts;
497 }
static struct ast_tone_zone * ast_tone_zone_unref(struct ast_tone_zone *tz)
Release a reference to an ast_tone_zone.
Definition: indications.h:205
static struct ast_tone_zone * default_tone_zone
Definition: indications.c:73
#define ast_tone_zone_unlock(tz)
Unlock an ast_tone_zone.
Definition: indications.h:193
A set of tones for a given locale.
Definition: indications.h:74
const char * name
Name of the tone. For example, "busy".
Definition: indications.h:37
static struct ast_tone_zone_sound * ast_tone_zone_sound_ref(struct ast_tone_zone_sound *ts)
Increase the reference count on an ast_tone_zone_sound.
Definition: indications.h:238
Description of a tone.
Definition: indications.h:35
static struct ast_tone_zone * ast_tone_zone_ref(struct ast_tone_zone *tz)
Increase the reference count on an ast_tone_zone.
Definition: indications.h:216
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
Definition: search.h:40
#define ast_tone_zone_lock(tz)
Lock an ast_tone_zone.
Definition: indications.h:188
struct ast_tone_zone::@232 tones
A list of tones for this locale.
struct ast_tone_zone* ast_get_indication_zone ( const char *  country)

locate ast_tone_zone, given the country. if country == NULL, use the default country

locate ast_tone_zone

Definition at line 439 of file indications.c.

References ast_copy_string(), ast_tone_zone_ref(), ast_tone_zone::country, ast_tone_zone::nrringcadence, and OBJ_POINTER.

Referenced by ast_control_tone(), ast_set_indication_country(), and chan_pjsip_new().

440 {
441  struct ast_tone_zone *tz = NULL;
442  struct ast_tone_zone zone_arg = {
443  .nrringcadence = 0,
444  };
445 
446  if (ast_strlen_zero(country)) {
447  ao2_lock(ast_tone_zones);
448  if (default_tone_zone) {
450  }
451  ao2_unlock(ast_tone_zones);
452 
453  return tz;
454  }
455 
456  ast_copy_string(zone_arg.country, country, sizeof(zone_arg.country));
457 
458  return ao2_find(ast_tone_zones, &zone_arg, OBJ_POINTER);
459 }
char country[MAX_TONEZONE_COUNTRY]
Country code that this set of tones is for.
Definition: indications.h:76
static struct ast_tone_zone * default_tone_zone
Definition: indications.c:73
#define OBJ_POINTER
Definition: astobj2.h:1150
A set of tones for a given locale.
Definition: indications.h:74
static struct ast_tone_zone * ast_tone_zone_ref(struct ast_tone_zone *tz)
Increase the reference count on an ast_tone_zone.
Definition: indications.h:216
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
unsigned int nrringcadence
Number of ring cadence elements in the ringcadence array.
Definition: indications.h:84
int ast_playtones_start ( struct ast_channel chan,
int  vol,
const char *  tonelist,
int  interruptible 
)

Start playing a list of tones on a channel.

Parameters
chanthe channel to play tones on
volvolume
tonelistthe list of tones to play, comma separated
interruptiblewhether or not this tone can be interrupted
Return values
0success
non-zerofailure

Definition at line 302 of file indications.c.

References ast_activate_generator(), ast_realloc, ast_strdupa, ast_strip(), and ast_tone_zone_part_parse().

Referenced by ast_app_dtget(), ast_control_tone(), ast_senddigit_begin(), ast_senddigit_mf_begin(), indicate_data_internal(), and send_tone_burst().

303 {
304  char *s, *data = ast_strdupa(playlst);
305  struct playtones_def d = { vol, -1, 0, 1, NULL };
306  char *stringp;
307  char *separator;
308  static const float sample_rate = 8000.0;
309  static const float max_sample_val = 32768.0;
310 
311  if (vol < 1) {
312  d.vol = 7219; /* Default to -8db */
313  }
314 
315  d.interruptible = interruptible;
316 
317  stringp = data;
318 
319  /* check if the data is separated with '|' or with ',' by default */
320  if (strchr(stringp,'|')) {
321  separator = "|";
322  } else {
323  separator = ",";
324  }
325 
326  while ((s = strsep(&stringp, separator)) && !ast_strlen_zero(s)) {
327  struct playtones_item *new_items;
328  struct ast_tone_zone_part tone_data = {
329  .time = 0,
330  };
331 
332  s = ast_strip(s);
333  if (s[0]=='!') {
334  s++;
335  } else if (d.reppos == -1) {
336  d.reppos = d.nitems;
337  }
338 
339  if (ast_tone_zone_part_parse(s, &tone_data)) {
340  ast_log(LOG_ERROR, "Failed to parse tone part '%s'\n", s);
341  continue;
342  }
343 
344  if (tone_data.midinote) {
345  /* midi notes must be between 0 and 127 */
346  if (tone_data.freq1 <= 127) {
347  tone_data.freq1 = midi_tohz[tone_data.freq1];
348  } else {
349  tone_data.freq1 = 0;
350  }
351 
352  if (tone_data.freq2 <= 127) {
353  tone_data.freq2 = midi_tohz[tone_data.freq2];
354  } else {
355  tone_data.freq2 = 0;
356  }
357  }
358 
359  new_items = ast_realloc(d.items, (d.nitems + 1) * sizeof(*d.items));
360  if (!new_items) {
361  ast_free(d.items);
362  return -1;
363  }
364  d.items = new_items;
365 
366  d.items[d.nitems].fac1 = 2.0 * cos(2.0 * M_PI * (tone_data.freq1 / sample_rate)) * max_sample_val;
367  d.items[d.nitems].init_v2_1 = sin(-4.0 * M_PI * (tone_data.freq1 / sample_rate)) * d.vol;
368  d.items[d.nitems].init_v3_1 = sin(-2.0 * M_PI * (tone_data.freq1 / sample_rate)) * d.vol;
369 
370  d.items[d.nitems].fac2 = 2.0 * cos(2.0 * M_PI * (tone_data.freq2 / sample_rate)) * max_sample_val;
371  d.items[d.nitems].init_v2_2 = sin(-4.0 * M_PI * (tone_data.freq2 / sample_rate)) * d.vol;
372  d.items[d.nitems].init_v3_2 = sin(-2.0 * M_PI * (tone_data.freq2 / sample_rate)) * d.vol;
373 
374  d.items[d.nitems].duration = tone_data.time;
375  d.items[d.nitems].modulate = tone_data.modulate;
376 
377  d.nitems++;
378  }
379 
380  if (!d.nitems) {
381  ast_log(LOG_ERROR, "No valid tone parts\n");
382  return -1;
383  }
384 
385  if (ast_activate_generator(chan, &playtones, &d)) {
386  ast_free(d.items);
387  return -1;
388  }
389 
390  return 0;
391 }
#define ast_realloc(p, len)
A wrapper for realloc()
Definition: astmm.h:226
int ast_activate_generator(struct ast_channel *chan, struct ast_generator *gen, void *params)
Definition: channel.c:2951
A description of a part of a tone.
Definition: indications.h:109
int ast_tone_zone_part_parse(const char *s, struct ast_tone_zone_part *tone_data)
Parse a tone part.
Definition: indications.c:245
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:223
void ast_playtones_stop ( struct ast_channel chan)

Stop playing tones on a channel.

Parameters
chanthe channel to stop tones on

Definition at line 393 of file indications.c.

References ast_deactivate_generator().

Referenced by ast_app_dtget(), ast_senddigit_end(), ast_senddigit_mf_end(), indicate_data_internal(), and send_tone_burst().

394 {
396 }
void ast_deactivate_generator(struct ast_channel *chan)
Definition: channel.c:2893
static int ast_register_indication ( struct ast_tone_zone zone,
const char *  indication,
const char *  tonelist 
)
static
Note
called with the tone zone locked

Definition at line 579 of file indications.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_strdup, ast_tone_zone_sound_unref(), ast_tone_zone_sound::data, ast_tone_zone_sound::name, and ast_tone_zone::tones.

581 {
582  struct ast_tone_zone_sound *ts;
583 
584  if (ast_strlen_zero(indication) || ast_strlen_zero(tonelist)) {
585  return -1;
586  }
587 
589  if (!strcasecmp(indication, ts->name)) {
591  ts = ast_tone_zone_sound_unref(ts);
592  break;
593  }
594  }
596 
597  ts = ao2_alloc_options(sizeof(*ts), ast_tone_zone_sound_destructor,
599  if (!ts) {
600  return -1;
601  }
602 
603  if (!(ts->name = ast_strdup(indication)) || !(ts->data = ast_strdup(tonelist))) {
604  ts = ast_tone_zone_sound_unref(ts);
605  return -1;
606  }
607 
608  AST_LIST_INSERT_TAIL(&zone->tones, ts, entry); /* Inherit reference */
609 
610  return 0;
611 }
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557
static struct ast_tone_zone_sound * ast_tone_zone_sound_unref(struct ast_tone_zone_sound *ts)
Release a reference to an ast_tone_zone_sound.
Definition: indications.h:227
const char * name
Name of the tone. For example, "busy".
Definition: indications.h:37
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
Description of a tone.
Definition: indications.h:35
Definition: search.h:40
const char * data
Description of a tone.
Definition: indications.h:52
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
struct ast_tone_zone::@232 tones
A list of tones for this locale.
int ast_tone_zone_count ( void  )

Get the number of registered tone zones.

Returns
the total number of registered tone zones

Definition at line 398 of file indications.c.

References ao2_container_count().

399 {
400  return ao2_container_count(ast_tone_zones);
401 }
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
struct ao2_iterator ast_tone_zone_iterator_init ( void  )

Get an iterator for the available tone zones.

Note
Use ao2_iterator_next() to iterate the tone zones.
Use ao2_iterator_destroy() to clean up.
Returns
an initialized iterator

Definition at line 403 of file indications.c.

References ao2_iterator_init().

404 {
405  return ao2_iterator_init(ast_tone_zones, 0);
406 }
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
int ast_tone_zone_part_parse ( const char *  s,
struct ast_tone_zone_part tone_data 
)

Parse a tone part.

Parameters
sThe part of a tone to parse. This should be in the form described for the data part of ast_tone_zone_sound. '!' should be removed if present.
tone_dataAn output parameter that contains the result of the parsing.
Return values
0success
-1failure, and the contents of tone_data are undefined

Definition at line 245 of file indications.c.

Referenced by ast_playtones_start().

246 {
247  if (sscanf(s, "%30u+%30u/%30u", &tone_data->freq1, &tone_data->freq2,
248  &tone_data->time) == 3) {
249  /* f1+f2/time format */
250  } else if (sscanf(s, "%30u+%30u", &tone_data->freq1, &tone_data->freq2) == 2) {
251  /* f1+f2 format */
252  tone_data->time = 0;
253  } else if (sscanf(s, "%30u*%30u/%30u", &tone_data->freq1, &tone_data->freq2,
254  &tone_data->time) == 3) {
255  /* f1*f2/time format */
256  tone_data->modulate = 1;
257  } else if (sscanf(s, "%30u*%30u", &tone_data->freq1, &tone_data->freq2) == 2) {
258  /* f1*f2 format */
259  tone_data->time = 0;
260  tone_data->modulate = 1;
261  } else if (sscanf(s, "%30u/%30u", &tone_data->freq1, &tone_data->time) == 2) {
262  /* f1/time format */
263  tone_data->freq2 = 0;
264  } else if (sscanf(s, "%30u", &tone_data->freq1) == 1) {
265  /* f1 format */
266  tone_data->freq2 = 0;
267  tone_data->time = 0;
268  } else if (sscanf(s, "M%30u+M%30u/%30u", &tone_data->freq1, &tone_data->freq2,
269  &tone_data->time) == 3) {
270  /* Mf1+Mf2/time format */
271  tone_data->midinote = 1;
272  } else if (sscanf(s, "M%30u+M%30u", &tone_data->freq1, &tone_data->freq2) == 2) {
273  /* Mf1+Mf2 format */
274  tone_data->time = 0;
275  tone_data->midinote = 1;
276  } else if (sscanf(s, "M%30u*M%30u/%30u", &tone_data->freq1, &tone_data->freq2,
277  &tone_data->time) == 3) {
278  /* Mf1*Mf2/time format */
279  tone_data->modulate = 1;
280  tone_data->midinote = 1;
281  } else if (sscanf(s, "M%30u*M%30u", &tone_data->freq1, &tone_data->freq2) == 2) {
282  /* Mf1*Mf2 format */
283  tone_data->time = 0;
284  tone_data->modulate = 1;
285  tone_data->midinote = 1;
286  } else if (sscanf(s, "M%30u/%30u", &tone_data->freq1, &tone_data->time) == 2) {
287  /* Mf1/time format */
288  tone_data->freq2 = -1;
289  tone_data->midinote = 1;
290  } else if (sscanf(s, "M%30u", &tone_data->freq1) == 1) {
291  /* Mf1 format */
292  tone_data->freq2 = -1;
293  tone_data->time = 0;
294  tone_data->midinote = 1;
295  } else {
296  return -1;
297  }
298 
299  return 0;
300 }
static void store_tone_zone_ring_cadence ( struct ast_tone_zone zone,
const char *  val 
)
static
Note
This is called with the tone zone locked.

Definition at line 918 of file indications.c.

References ast_copy_string(), ast_realloc, ast_strip(), ast_tone_zone::nrringcadence, and ast_tone_zone::ringcadence.

919 {
920  char buf[1024];
921  char *ring, *c = buf;
922 
923  ast_copy_string(buf, val, sizeof(buf));
924 
925  while ((ring = strsep(&c, ","))) {
926  int *tmp, value;
927 
928  ring = ast_strip(ring);
929 
930  if (!isdigit(ring[0]) || (value = atoi(ring)) == -1) {
931  ast_log(LOG_WARNING, "Invalid ringcadence given '%s'.\n", ring);
932  continue;
933  }
934 
935  if (!(tmp = ast_realloc(zone->ringcadence, (zone->nrringcadence + 1) * sizeof(int)))) {
936  return;
937  }
938 
939  zone->ringcadence = tmp;
940  tmp[zone->nrringcadence] = value;
941  zone->nrringcadence++;
942  }
943 }
#define ast_realloc(p, len)
A wrapper for realloc()
Definition: astmm.h:226
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:223
int * ringcadence
Array of ring cadence parts.
Definition: indications.h:91
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
unsigned int nrringcadence
Number of ring cadence elements in the ringcadence array.
Definition: indications.h:84

Variable Documentation

struct ast_cli_entry cli_indications[]
static
Initial value:
= {
{ .handler = handle_cli_indication_add , .summary = "Add the given indication to the country" ,},
{ .handler = handle_cli_indication_remove , .summary = "Remove the given indication from the country" ,},
{ .handler = handle_cli_indication_show , .summary = "Display a list of all countries/indications" ,}
}

CLI entries for commands provided by this module.

Definition at line 1118 of file indications.c.

struct ast_tone_zone* default_tone_zone
static
Note
Access to this is protected by locking the ast_tone_zones container

Definition at line 73 of file indications.c.

struct ast_generator playtones
static
Initial value:
= {
.alloc = playtones_alloc,
.release = playtones_release,
.generate = playtones_generator,
}

Definition at line 239 of file indications.c.