Thu Oct 11 06:36:29 2012

Asterisk developer's documentation


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/channel.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
#include "asterisk/module.h"
#include "asterisk/astobj2.h"
#include "asterisk/data.h"
#include "asterisk/_private.h"

Include dependency graph for indications.c:

Go to the source code of this file.

Data Structures

struct  playtones_def
struct  playtones_item
struct  playtones_state

Defines

#define DATA_EXPORT_TONE_ZONE(MEMBER)
#define DATA_EXPORT_TONE_ZONE_SOUND(MEMBER)
#define NUM_TONE_ZONE_BUCKETS   53

Functions

 AST_DATA_STRUCTURE (ast_tone_zone_sound, DATA_EXPORT_TONE_ZONE_SOUND)
 AST_DATA_STRUCTURE (ast_tone_zone, DATA_EXPORT_TONE_ZONE)
struct ast_tone_zone_soundast_get_indication_tone (const struct ast_tone_zone *_zone, const char *indication)
 Locate a tone zone sound.
struct ast_tone_zoneast_get_indication_zone (const char *country)
 locate ast_tone_zone, given the country. if country == NULL, use the default country
int ast_indications_init (void)
 Load indications module.
int ast_indications_reload (void)
 Reload indications module.
int ast_playtones_start (struct ast_channel *chan, int vol, const char *playlst, int interruptible)
 Start playing a list of tones on a channel.
void ast_playtones_stop (struct ast_channel *chan)
 Stop playing tones on a channel.
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.
int ast_tone_zone_data_add_structure (struct ast_data *tree, struct ast_tone_zone *zone)
 Add a tone_zone structure to the data tree specified.
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.
int ast_tone_zone_part_parse (const char *s, struct ast_tone_zone_part *tone_data)
 Parse a tone part.
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 void indications_shutdown (void)
static int is_valid_tone_zone (struct ast_tone_zone *zone)
static int load_indications (int reload)
 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 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.

Variables

static struct ao2_containerast_tone_zones
static struct ast_cli_entry cli_indications []
 CLI entries for commands provided by this module.
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 <middelink@polyware.nl>

Russell Bryant <russell@digium.com>

Definition in file indications.c.


Define Documentation

#define DATA_EXPORT_TONE_ZONE ( MEMBER   ) 

Value:

Definition at line 49 of file indications.c.

#define DATA_EXPORT_TONE_ZONE_SOUND ( MEMBER   ) 

Value:

Definition at line 56 of file indications.c.

#define NUM_TONE_ZONE_BUCKETS   53

Definition at line 83 of file indications.c.

Referenced by ast_indications_init().


Function Documentation

AST_DATA_STRUCTURE ( ast_tone_zone_sound  ,
DATA_EXPORT_TONE_ZONE_SOUND   
)

AST_DATA_STRUCTURE ( ast_tone_zone  ,
DATA_EXPORT_TONE_ZONE   
)

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

Locate a tone zone sound.

Parameters:
zone Zone to look in for a sound, if NULL, the default will be used
indication Sound to look for, such as "busy"
Returns:
a reference to the specified sound if it exists, NULL if not

Definition at line 470 of file indications.c.

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

Referenced by ast_app_dtget(), ast_indicate_data(), dial_handle_playtones(), dialtone_indicate(), handle_playtones(), in_band_indication(), pbx_builtin_waitexten(), play_dialtone(), read_exec(), readexten_exec(), send_dial_tone(), and skinny_transfer().

00471 {
00472    struct ast_tone_zone_sound *ts = NULL;
00473    /* _zone is const to the users of the API */
00474    struct ast_tone_zone *zone = (struct ast_tone_zone *) _zone;
00475 
00476    /* If no zone is specified, use the default */
00477    if (!zone) {
00478       ao2_lock(ast_tone_zones);
00479       if (default_tone_zone) {
00480          zone = ast_tone_zone_ref(default_tone_zone);
00481       }
00482       ao2_unlock(ast_tone_zones);
00483 
00484       if (!zone) {
00485          return NULL;
00486       }
00487    }
00488 
00489    ast_tone_zone_lock(zone);
00490 
00491    /* Look through list of tones in the zone searching for the right one */
00492    AST_LIST_TRAVERSE(&zone->tones, ts, entry) {
00493       if (!strcasecmp(ts->name, indication)) {
00494          /* Increase ref count for the reference we will return */
00495          ts = ast_tone_zone_sound_ref(ts);
00496          break;
00497       }
00498    }
00499 
00500    ast_tone_zone_unlock(zone);
00501 
00502    return ts;
00503 }

struct ast_tone_zone* ast_get_indication_zone ( const char *  country  )  [read]

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

locate ast_tone_zone

Definition at line 448 of file indications.c.

References ao2_find, ao2_lock, ao2_unlock, ast_copy_string(), ast_strlen_zero(), ast_tone_zone_ref(), ast_tone_zone::country, ast_tone_zone::nrringcadence, OBJ_POINTER, and tz.

Referenced by ast_set_indication_country(), ast_var_indications(), build_device(), build_peer(), func_channel_write_real(), handle_cli_indication_add(), handle_cli_indication_remove(), reload_config(), and sip_new().

00449 {
00450    struct ast_tone_zone *tz = NULL;
00451    struct ast_tone_zone zone_arg = {
00452       .nrringcadence = 0,
00453    };
00454 
00455    if (ast_strlen_zero(country)) {
00456       ao2_lock(ast_tone_zones);
00457       if (default_tone_zone) {
00458          tz = ast_tone_zone_ref(default_tone_zone);
00459       }
00460       ao2_unlock(ast_tone_zones);
00461 
00462       return tz;
00463    }
00464 
00465    ast_copy_string(zone_arg.country, country, sizeof(zone_arg.country));
00466 
00467    return ao2_find(ast_tone_zones, &zone_arg, OBJ_POINTER);
00468 }

int ast_indications_init ( void   ) 

Load indications module.

Provided by indications.c

Definition at line 1163 of file indications.c.

References ao2_container_alloc, ARRAY_LEN, ast_cli_register_multiple(), ast_register_atexit(), ast_tone_zone_cmp(), ast_tone_zone_hash(), indications_shutdown(), load_indications(), and NUM_TONE_ZONE_BUCKETS.

Referenced by main().

01164 {
01165    if (!(ast_tone_zones = ao2_container_alloc(NUM_TONE_ZONE_BUCKETS,
01166          ast_tone_zone_hash, ast_tone_zone_cmp))) {
01167       return -1;
01168    }
01169 
01170    if (load_indications(0)) {
01171       return -1;
01172    }
01173 
01174    ast_cli_register_multiple(cli_indications, ARRAY_LEN(cli_indications));
01175 
01176    ast_register_atexit(indications_shutdown);
01177    return 0;
01178 }

int ast_indications_reload ( void   ) 

Reload indications module.

Provided by indications.c

Definition at line 1181 of file indications.c.

References load_indications().

01182 {
01183    return load_indications(1);
01184 }

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:
chan the channel to play tones on
vol volume
tonelist the list of tones to play, comma separated
interruptible whether or not this tone can be interrupted
Return values:
0 success
non-zero failure

Definition at line 319 of file indications.c.

References ast_activate_generator(), ast_free, ast_log(), ast_realloc, ast_strdupa, ast_strip(), ast_strlen_zero(), ast_tone_zone_part_parse(), cos, playtones_item::duration, playtones_item::fac1, playtones_item::fac2, ast_tone_zone_part::freq1, ast_tone_zone_part::freq2, playtones_item::init_v2_1, playtones_item::init_v2_2, playtones_item::init_v3_1, playtones_item::init_v3_2, playtones_def::interruptible, playtones_def::items, LOG_ERROR, M_PI, ast_tone_zone_part::midinote, ast_tone_zone_part::modulate, playtones_item::modulate, playtones_def::nitems, playtones_def::reppos, strsep(), ast_tone_zone_part::time, and playtones_def::vol.

Referenced by ast_app_dtget(), ast_indicate_data(), ast_senddigit_begin(), dial_handle_playtones(), dialtone_indicate(), handle_playtones(), in_band_indication(), milliwatt_exec(), pbx_builtin_waitexten(), play_dialtone(), playtone(), read_exec(), readexten_exec(), receivefax_t38_init(), send_digit_to_chan(), send_tone_burst(), sendfax_t38_init(), and skinny_transfer().

00320 {
00321    char *s, *data = ast_strdupa(playlst);
00322    struct playtones_def d = { vol, -1, 0, 1, NULL };
00323    char *stringp;
00324    char *separator;
00325    static const float sample_rate = 8000.0;
00326    static const float max_sample_val = 32768.0;
00327 
00328    if (vol < 1) {
00329       d.vol = 7219; /* Default to -8db */
00330    }
00331 
00332    d.interruptible = interruptible;
00333 
00334    stringp = data;
00335 
00336    /* check if the data is separated with '|' or with ',' by default */
00337    if (strchr(stringp,'|')) {
00338       separator = "|";
00339    } else {
00340       separator = ",";
00341    }
00342 
00343    while ((s = strsep(&stringp, separator)) && !ast_strlen_zero(s)) {
00344       struct ast_tone_zone_part tone_data = {
00345          .time = 0,
00346       };
00347 
00348       s = ast_strip(s);
00349 
00350       if (s[0]=='!') {
00351          s++;
00352       } else if (d.reppos == -1) {
00353          d.reppos = d.nitems;
00354       }
00355 
00356       if (ast_tone_zone_part_parse(s, &tone_data)) {
00357          ast_log(LOG_ERROR, "Failed to parse tone part '%s'\n", s);
00358          continue;
00359       }
00360 
00361       if (tone_data.midinote) {
00362          /* midi notes must be between 0 and 127 */
00363 
00364          if (tone_data.freq1 >= 0 && tone_data.freq1 <= 127) {
00365             tone_data.freq1 = midi_tohz[tone_data.freq1];
00366          } else {
00367             tone_data.freq1 = 0;
00368          }
00369 
00370          if (tone_data.freq2 >= 0 && tone_data.freq2 <= 127) {
00371             tone_data.freq2 = midi_tohz[tone_data.freq2];
00372          } else {
00373             tone_data.freq2 = 0;
00374          }
00375       }
00376 
00377       if (!(d.items = ast_realloc(d.items, (d.nitems + 1) * sizeof(*d.items)))) {
00378          return -1;
00379       }
00380 
00381       d.items[d.nitems].fac1 = 2.0 * cos(2.0 * M_PI * (tone_data.freq1 / sample_rate)) * max_sample_val;
00382       d.items[d.nitems].init_v2_1 = sin(-4.0 * M_PI * (tone_data.freq1 / sample_rate)) * d.vol;
00383       d.items[d.nitems].init_v3_1 = sin(-2.0 * M_PI * (tone_data.freq1 / sample_rate)) * d.vol;
00384 
00385       d.items[d.nitems].fac2 = 2.0 * cos(2.0 * M_PI * (tone_data.freq2 / sample_rate)) * max_sample_val;
00386       d.items[d.nitems].init_v2_2 = sin(-4.0 * M_PI * (tone_data.freq2 / sample_rate)) * d.vol;
00387       d.items[d.nitems].init_v3_2 = sin(-2.0 * M_PI * (tone_data.freq2 / sample_rate)) * d.vol;
00388 
00389       d.items[d.nitems].duration = tone_data.time;
00390       d.items[d.nitems].modulate = tone_data.modulate;
00391 
00392       d.nitems++;
00393    }
00394 
00395    if (!d.nitems) {
00396       ast_log(LOG_ERROR, "No valid tone parts\n");
00397       return -1;
00398    }
00399 
00400    if (ast_activate_generator(chan, &playtones, &d)) {
00401       ast_free(d.items);
00402       return -1;
00403    }
00404 
00405    return 0;
00406 }

void ast_playtones_stop ( struct ast_channel chan  ) 

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 585 of file indications.c.

References ao2_alloc, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_strdup, ast_strlen_zero(), ast_tone_zone_sound_destructor(), ast_tone_zone_sound_unref(), ast_tone_zone_sound::data, ast_tone_zone_sound::entry, ast_tone_zone_sound::name, and ast_tone_zone::tones.

Referenced by handle_cli_indication_add(), and store_config_tone_zone().

00587 {
00588    struct ast_tone_zone_sound *ts;
00589 
00590    if (ast_strlen_zero(indication) || ast_strlen_zero(tonelist)) {
00591       return -1;
00592    }
00593 
00594    AST_LIST_TRAVERSE_SAFE_BEGIN(&zone->tones, ts, entry) {
00595       if (!strcasecmp(indication, ts->name)) {
00596          AST_LIST_REMOVE_CURRENT(entry);
00597          ts = ast_tone_zone_sound_unref(ts);
00598          break;
00599       }
00600    }
00601    AST_LIST_TRAVERSE_SAFE_END;
00602 
00603    if (!(ts = ao2_alloc(sizeof(*ts), ast_tone_zone_sound_destructor))) {
00604       return -1;
00605    }
00606 
00607    if (!(ts->name = ast_strdup(indication)) || !(ts->data = ast_strdup(tonelist))) {
00608       ts = ast_tone_zone_sound_unref(ts);
00609       return -1;
00610    }
00611 
00612    AST_LIST_INSERT_TAIL(&zone->tones, ts, entry); /* Inherit reference */
00613 
00614    return 0;
00615 }

static int ast_register_indication_country ( struct ast_tone_zone zone  )  [static]

add a new country, if country exists, it will be replaced.

Definition at line 538 of file indications.c.

References ao2_link, ao2_lock, ao2_unlock, ast_tone_zone_ref(), ast_verb, and ast_tone_zone::country.

Referenced by handle_cli_indication_add(), and parse_tone_zone().

00539 {
00540    ao2_lock(ast_tone_zones);
00541    if (!default_tone_zone) {
00542       default_tone_zone = ast_tone_zone_ref(zone);
00543    }
00544    ao2_unlock(ast_tone_zones);
00545 
00546    ao2_link(ast_tone_zones, zone);
00547 
00548    ast_verb(3, "Registered indication country '%s'\n", zone->country);
00549 
00550    return 0;
00551 }

static int ast_set_indication_country ( const char *  country  )  [static]

Set global indication country If no country is specified or we are unable to find the zone, then return not found.

Definition at line 425 of file indications.c.

References ao2_lock, ao2_unlock, ast_get_indication_zone(), ast_strlen_zero(), ast_tone_zone_ref(), ast_tone_zone_unref(), and ast_verb.

Referenced by load_indications().

00426 {
00427    struct ast_tone_zone *zone = NULL;
00428 
00429    if (ast_strlen_zero(country) || !(zone = ast_get_indication_zone(country))) {
00430       return -1;
00431    }
00432 
00433    ast_verb(3, "Setting default indication country to '%s'\n", country);
00434 
00435    ao2_lock(ast_tone_zones);
00436    if (default_tone_zone) {
00437       default_tone_zone = ast_tone_zone_unref(default_tone_zone);
00438    }
00439    default_tone_zone = ast_tone_zone_ref(zone);
00440    ao2_unlock(ast_tone_zones);
00441 
00442    zone = ast_tone_zone_unref(zone);
00443 
00444    return 0;
00445 }

static struct ast_tone_zone* ast_tone_zone_alloc ( void   )  [static, read]

Definition at line 640 of file indications.c.

References ao2_alloc, and ast_tone_zone_destructor().

Referenced by handle_cli_indication_add(), and parse_tone_zone().

00641 {
00642    return ao2_alloc(sizeof(struct ast_tone_zone), ast_tone_zone_destructor);
00643 }

static int ast_tone_zone_cmp ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 1117 of file indications.c.

References CMP_MATCH, CMP_STOP, and ast_tone_zone::country.

Referenced by ast_indications_init().

01118 {
01119    struct ast_tone_zone *zone = obj;
01120    struct ast_tone_zone *zone_arg = arg;
01121 
01122    return (!strcasecmp(zone->country, zone_arg->country)) ?
01123          CMP_MATCH | CMP_STOP : 0;
01124 }

int ast_tone_zone_count ( void   ) 

Get the number of registered tone zones.

Returns:
the total number of registered tone zones

Definition at line 413 of file indications.c.

References ao2_container_count().

00414 {
00415    return ao2_container_count(ast_tone_zones);
00416 }

int ast_tone_zone_data_add_structure ( struct ast_data tree,
struct ast_tone_zone zone 
)

Add a tone_zone structure to the data tree specified.

Return values:
<0 on error.
0 on success.

Definition at line 1126 of file indications.c.

References ast_data_add_node(), ast_data_add_structure, AST_LIST_EMPTY, AST_LIST_TRAVERSE, ast_tone_zone_lock, ast_tone_zone_unlock, ast_tone_zone_sound::entry, and ast_tone_zone::tones.

Referenced by ast_channel_data_add_structure().

01127 {
01128    struct ast_data *data_zone_sound;
01129    struct ast_tone_zone_sound *s;
01130 
01131    ast_data_add_structure(ast_tone_zone, tree, zone);
01132 
01133    if (AST_LIST_EMPTY(&zone->tones)) {
01134       return 0;
01135    }
01136 
01137    data_zone_sound = ast_data_add_node(tree, "tones");
01138    if (!data_zone_sound) {
01139       return -1;
01140    }
01141 
01142    ast_tone_zone_lock(zone);
01143 
01144    AST_LIST_TRAVERSE(&zone->tones, s, entry) {
01145       ast_data_add_structure(ast_tone_zone_sound, data_zone_sound, s);
01146    }
01147 
01148    ast_tone_zone_unlock(zone);
01149 
01150    return 0;
01151 }

static void ast_tone_zone_destructor ( void *  obj  )  [static]

deallocate the passed tone zone

Definition at line 522 of file indications.c.

References ast_free, AST_LIST_REMOVE_HEAD, ast_tone_zone_sound_unref(), ast_tone_zone_sound::entry, ast_tone_zone::ringcadence, and ast_tone_zone::tones.

Referenced by ast_tone_zone_alloc().

00523 {
00524    struct ast_tone_zone *zone = obj;
00525    struct ast_tone_zone_sound *current;
00526 
00527    while ((current = AST_LIST_REMOVE_HEAD(&zone->tones, entry))) {
00528       current = ast_tone_zone_sound_unref(current);
00529    }
00530 
00531    if (zone->ringcadence) {
00532       ast_free(zone->ringcadence);
00533       zone->ringcadence = NULL;
00534    }
00535 }

static int ast_tone_zone_hash ( const void *  obj,
const int  flags 
) [static]

Definition at line 1110 of file indications.c.

References ast_str_case_hash(), and ast_tone_zone::country.

Referenced by ast_indications_init().

01111 {
01112    const struct ast_tone_zone *zone = obj;
01113 
01114    return ast_str_case_hash(zone->country);
01115 }

struct ao2_iterator ast_tone_zone_iterator_init ( void   )  [read]

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 418 of file indications.c.

References ao2_iterator_init().

Referenced by ast_var_indications(), ast_var_indications_table(), and handle_cli_indication_show().

00419 {
00420    return ao2_iterator_init(ast_tone_zones, 0);
00421 }

int ast_tone_zone_part_parse ( const char *  s,
struct ast_tone_zone_part tone_data 
)

Parse a tone part.

Parameters:
s The 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_data An output parameter that contains the result of the parsing.
Return values:
0 success
-1 failure, and the contents of tone_data are undefined

Definition at line 262 of file indications.c.

References ast_tone_zone_part::freq1, ast_tone_zone_part::freq2, ast_tone_zone_part::midinote, ast_tone_zone_part::modulate, and ast_tone_zone_part::time.

Referenced by ast_playtones_start(), and send_dial_tone().

00263 {
00264    if (sscanf(s, "%30u+%30u/%30u", &tone_data->freq1, &tone_data->freq2,
00265          &tone_data->time) == 3) {
00266       /* f1+f2/time format */
00267    } else if (sscanf(s, "%30u+%30u", &tone_data->freq1, &tone_data->freq2) == 2) {
00268       /* f1+f2 format */
00269       tone_data->time = 0;
00270    } else if (sscanf(s, "%30u*%30u/%30u", &tone_data->freq1, &tone_data->freq2,
00271          &tone_data->time) == 3) {
00272       /* f1*f2/time format */
00273       tone_data->modulate = 1;
00274    } else if (sscanf(s, "%30u*%30u", &tone_data->freq1, &tone_data->freq2) == 2) {
00275       /* f1*f2 format */
00276       tone_data->time = 0;
00277       tone_data->modulate = 1;
00278    } else if (sscanf(s, "%30u/%30u", &tone_data->freq1, &tone_data->time) == 2) {
00279       /* f1/time format */
00280       tone_data->freq2 = 0;
00281    } else if (sscanf(s, "%30u", &tone_data->freq1) == 1) {
00282       /* f1 format */
00283       tone_data->freq2 = 0;
00284       tone_data->time = 0;
00285    } else if (sscanf(s, "M%30u+M%30u/%30u", &tone_data->freq1, &tone_data->freq2,
00286          &tone_data->time) == 3) {
00287       /* Mf1+Mf2/time format */
00288       tone_data->midinote = 1;
00289    } else if (sscanf(s, "M%30u+M%30u", &tone_data->freq1, &tone_data->freq2) == 2) {
00290       /* Mf1+Mf2 format */
00291       tone_data->time = 0;
00292       tone_data->midinote = 1;
00293    } else if (sscanf(s, "M%30u*M%30u/%30u", &tone_data->freq1, &tone_data->freq2,
00294          &tone_data->time) == 3) {
00295       /* Mf1*Mf2/time format */
00296       tone_data->modulate = 1;
00297       tone_data->midinote = 1;
00298    } else if (sscanf(s, "M%30u*M%30u", &tone_data->freq1, &tone_data->freq2) == 2) {
00299       /* Mf1*Mf2 format */
00300       tone_data->time = 0;
00301       tone_data->modulate = 1;
00302       tone_data->midinote = 1;
00303    } else if (sscanf(s, "M%30u/%30u", &tone_data->freq1, &tone_data->time) == 2) {
00304       /* Mf1/time format */
00305       tone_data->freq2 = -1;
00306       tone_data->midinote = 1;
00307    } else if (sscanf(s, "M%30u", &tone_data->freq1) == 1) {
00308       /* Mf1 format */
00309       tone_data->freq2 = -1;
00310       tone_data->time = 0;
00311       tone_data->midinote = 1;
00312    } else {
00313       return -1;
00314    }
00315 
00316    return 0;
00317 }

static void ast_tone_zone_sound_destructor ( void *  obj  )  [static]

Definition at line 505 of file indications.c.

References ast_free, ast_tone_zone_sound::data, and ast_tone_zone_sound::name.

Referenced by ast_register_indication().

00506 {
00507    struct ast_tone_zone_sound *ts = obj;
00508 
00509    /* Deconstify the 'const char *'s so the compiler doesn't complain. (but it's safe) */
00510    if (ts->name) {
00511       ast_free((char *) ts->name);
00512       ts->name = NULL;
00513    }
00514 
00515    if (ts->data) {
00516       ast_free((char *) ts->data);
00517       ts->data = NULL;
00518    }
00519 }

static int ast_unregister_indication ( struct ast_tone_zone zone,
const char *  indication 
) [static]

remove an existing country's indication. Both country and indication must exist

Definition at line 618 of file indications.c.

References AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_tone_zone_lock, ast_tone_zone_sound_unref(), ast_tone_zone_unlock, ast_tone_zone_sound::entry, ast_tone_zone_sound::name, and ast_tone_zone::tones.

Referenced by handle_cli_indication_remove().

00619 {
00620    struct ast_tone_zone_sound *ts;
00621    int res = -1;
00622 
00623    ast_tone_zone_lock(zone);
00624 
00625    AST_LIST_TRAVERSE_SAFE_BEGIN(&zone->tones, ts, entry) {
00626       if (!strcasecmp(indication, ts->name)) {
00627          AST_LIST_REMOVE_CURRENT(entry);
00628          ts = ast_tone_zone_sound_unref(ts);
00629          res = 0;
00630          break;
00631       }
00632    }
00633    AST_LIST_TRAVERSE_SAFE_END;
00634 
00635    ast_tone_zone_unlock(zone);
00636 
00637    return res;
00638 }

static int ast_unregister_indication_country ( const char *  country  )  [static]

remove an existing country and all its indications, country must exist.

Definition at line 554 of file indications.c.

References ao2_callback, ao2_find, ao2_lock, ao2_unlink, ao2_unlock, ast_copy_string(), ast_tone_zone_unref(), ast_tone_zone::country, ast_tone_zone::nrringcadence, OBJ_POINTER, and tz.

Referenced by handle_cli_indication_add(), and handle_cli_indication_remove().

00555 {
00556    struct ast_tone_zone *tz = NULL;
00557    struct ast_tone_zone zone_arg = {
00558       .nrringcadence = 0,
00559    };
00560 
00561    ast_copy_string(zone_arg.country, country, sizeof(zone_arg.country));
00562 
00563    if (!(tz = ao2_find(ast_tone_zones, &zone_arg, OBJ_POINTER))) {
00564       return -1;
00565    }
00566 
00567    ao2_lock(ast_tone_zones);
00568    if (default_tone_zone == tz) {
00569       ast_tone_zone_unref(default_tone_zone);
00570       /* Get a new default, punt to the first one we find */
00571       default_tone_zone = ao2_callback(ast_tone_zones, 0, NULL, NULL);
00572    }
00573    ao2_unlock(ast_tone_zones);
00574 
00575    ao2_unlink(ast_tone_zones, tz);
00576 
00577    tz = ast_tone_zone_unref(tz);
00578 
00579    return 0;
00580 }

static char* complete_country ( struct ast_cli_args a  )  [static]

Definition at line 645 of file indications.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ast_strdup, ast_tone_zone_unref(), ast_tone_zone::country, ast_cli_args::n, tz, and ast_cli_args::word.

Referenced by handle_cli_indication_add(), handle_cli_indication_remove(), and handle_cli_indication_show().

00646 {
00647    char *res = NULL;
00648    struct ao2_iterator i;
00649    int which = 0;
00650    size_t wordlen;
00651    struct ast_tone_zone *tz;
00652 
00653    wordlen = strlen(a->word);
00654 
00655    i = ao2_iterator_init(ast_tone_zones, 0);
00656    while ((tz = ao2_iterator_next(&i))) {
00657       if (!strncasecmp(a->word, tz->country, wordlen) && ++which > a->n) {
00658          res = ast_strdup(tz->country);
00659       }
00660       tz = ast_tone_zone_unref(tz);
00661       if (res) {
00662          break;
00663       }
00664    }
00665    ao2_iterator_destroy(&i);
00666 
00667    return res;
00668 }

static char* complete_indications ( struct ast_cli_args a  )  [static]

Definition at line 731 of file indications.c.

References ao2_find, ast_cli_args::argv, ast_copy_string(), AST_LIST_TRAVERSE, ast_strdup, ast_tone_zone_lock, ast_tone_zone_unlock, ast_tone_zone_unref(), ast_tone_zone::country, ast_cli_args::n, ast_tone_zone_sound::name, OBJ_POINTER, ast_cli_args::pos, ast_tone_zone::tones, tz, and ast_cli_args::word.

Referenced by handle_cli_indication_remove().

00732 {
00733    char *res = NULL;
00734    int which = 0;
00735    size_t wordlen;
00736    struct ast_tone_zone_sound *ts;
00737    struct ast_tone_zone *tz, tmp_tz = {
00738       .nrringcadence = 0,
00739    };
00740 
00741    ast_copy_string(tmp_tz.country, a->argv[a->pos - 1], sizeof(tmp_tz.country));
00742 
00743    if (!(tz = ao2_find(ast_tone_zones, &tmp_tz, OBJ_POINTER))) {
00744       return NULL;
00745    }
00746 
00747    wordlen = strlen(a->word);
00748 
00749    ast_tone_zone_lock(tz);
00750    AST_LIST_TRAVERSE(&tz->tones, ts, entry) {
00751       if (!strncasecmp(a->word, ts->name, wordlen) && ++which > a->n) {
00752          res = ast_strdup(ts->name);
00753          break;
00754       }
00755    }
00756    ast_tone_zone_unlock(tz);
00757 
00758    tz = ast_tone_zone_unref(tz);
00759 
00760    return res;
00761 }

static char* handle_cli_indication_add ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 670 of file indications.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_copy_string(), ast_get_indication_zone(), ast_log(), ast_register_indication(), ast_register_indication_country(), ast_tone_zone_alloc(), ast_tone_zone_lock, ast_tone_zone_unlock, ast_tone_zone_unref(), ast_unregister_indication_country(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_country(), ast_tone_zone::country, LOG_NOTICE, LOG_WARNING, ast_cli_args::pos, tz, and ast_cli_entry::usage.

00671 {
00672    struct ast_tone_zone *tz;
00673    int created_country = 0;
00674    char *res = CLI_SUCCESS;
00675 
00676    switch (cmd) {
00677    case CLI_INIT:
00678       e->command = "indication add";
00679       e->usage =
00680          "Usage: indication add <country> <indication> \"<tonelist>\"\n"
00681          "       Add the given indication to the country.\n";
00682       return NULL;
00683    case CLI_GENERATE:
00684       if (a->pos == 2) {
00685          return complete_country(a);
00686       } else {
00687          return NULL;
00688       }
00689    }
00690 
00691    if (a->argc != 5) {
00692       return CLI_SHOWUSAGE;
00693    }
00694 
00695    if (!(tz = ast_get_indication_zone(a->argv[2]))) {
00696       /* country does not exist, create it */
00697       ast_log(LOG_NOTICE, "Country '%s' does not exist, creating it.\n", a->argv[2]);
00698 
00699       if (!(tz = ast_tone_zone_alloc())) {
00700          return CLI_FAILURE;
00701       }
00702 
00703       ast_copy_string(tz->country, a->argv[2], sizeof(tz->country));
00704 
00705       if (ast_register_indication_country(tz)) {
00706          ast_log(LOG_WARNING, "Unable to register new country\n");
00707          tz = ast_tone_zone_unref(tz);
00708          return CLI_FAILURE;
00709       }
00710 
00711       created_country = 1;
00712    }
00713 
00714    ast_tone_zone_lock(tz);
00715 
00716    if (ast_register_indication(tz, a->argv[3], a->argv[4])) {
00717       ast_log(LOG_WARNING, "Unable to register indication %s/%s\n", a->argv[2], a->argv[3]);
00718       if (created_country) {
00719          ast_unregister_indication_country(a->argv[2]);
00720       }
00721       res = CLI_FAILURE;
00722    }
00723 
00724    ast_tone_zone_unlock(tz);
00725 
00726    tz = ast_tone_zone_unref(tz);
00727 
00728    return res;
00729 }

static char* handle_cli_indication_remove ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 763 of file indications.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_get_indication_zone(), ast_log(), ast_tone_zone_unref(), ast_unregister_indication(), ast_unregister_indication_country(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_country(), complete_indications(), LOG_WARNING, ast_cli_args::pos, tz, and ast_cli_entry::usage.

00764 {
00765    struct ast_tone_zone *tz;
00766    char *res = CLI_SUCCESS;
00767 
00768    switch (cmd) {
00769    case CLI_INIT:
00770       e->command = "indication remove";
00771       e->usage =
00772          "Usage: indication remove <country> [indication]\n"
00773          "       Remove the given indication from the country.\n";
00774       return NULL;
00775    case CLI_GENERATE:
00776       if (a->pos == 2) {
00777          return complete_country(a);
00778       } else if (a->pos == 3) {
00779          return complete_indications(a);
00780       }
00781    }
00782 
00783    if (a->argc != 3 && a->argc != 4) {
00784       return CLI_SHOWUSAGE;
00785    }
00786 
00787    if (a->argc == 3) {
00788       /* remove entire country */
00789       if (ast_unregister_indication_country(a->argv[2])) {
00790          ast_log(LOG_WARNING, "Unable to unregister indication country %s\n", a->argv[2]);
00791          return CLI_FAILURE;
00792       }
00793 
00794       return CLI_SUCCESS;
00795    }
00796 
00797    if (!(tz = ast_get_indication_zone(a->argv[2]))) {
00798       ast_log(LOG_WARNING, "Unable to unregister indication %s/%s, country does not exists\n", a->argv[2], a->argv[3]);
00799       return CLI_FAILURE;
00800    }
00801 
00802    if (ast_unregister_indication(tz, a->argv[3])) {
00803       ast_log(LOG_WARNING, "Unable to unregister indication %s/%s\n", a->argv[2], a->argv[3]);
00804       res = CLI_FAILURE;
00805    }
00806 
00807    tz = ast_tone_zone_unref(tz);
00808 
00809    return res;
00810 }

static char* handle_cli_indication_show ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 812 of file indications.c.

References ao2_find, ao2_iterator_destroy(), ao2_iterator_next, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_copy_string(), AST_LIST_TRAVERSE, ast_str_alloca, ast_str_append(), ast_str_set(), ast_tone_zone_iterator_init(), ast_tone_zone_lock, ast_tone_zone_unlock, ast_tone_zone_unref(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, complete_country(), ast_tone_zone::country, ast_tone_zone_sound::data, ast_tone_zone::description, ast_tone_zone_sound::entry, ast_cli_args::fd, ast_tone_zone_sound::name, ast_tone_zone::nrringcadence, OBJ_POINTER, ast_tone_zone::ringcadence, ast_tone_zone::tones, tz, and ast_cli_entry::usage.

00813 {
00814    struct ast_tone_zone *tz = NULL;
00815    struct ast_str *buf;
00816    int found_country = 0;
00817    int i;
00818 
00819    switch (cmd) {
00820    case CLI_INIT:
00821       e->command = "indication show";
00822       e->usage =
00823          "Usage: indication show [<country> ...]\n"
00824          "       Display either a condensed summary of all countries and indications, or a\n"
00825          "       more verbose list of indications for the specified countries.\n";
00826       return NULL;
00827    case CLI_GENERATE:
00828       return complete_country(a);
00829    }
00830 
00831    if (a->argc == 2) {
00832       struct ao2_iterator iter;
00833       /* no arguments, show a list of countries */
00834       ast_cli(a->fd, "Country   Description\n");
00835       ast_cli(a->fd, "===========================\n");
00836       iter = ast_tone_zone_iterator_init();
00837       while ((tz = ao2_iterator_next(&iter))) {
00838          ast_tone_zone_lock(tz);
00839          ast_cli(a->fd, "%-7.7s  %s\n", tz->country, tz->description);
00840          ast_tone_zone_unlock(tz);
00841          tz = ast_tone_zone_unref(tz);
00842       }
00843       ao2_iterator_destroy(&iter);
00844       return CLI_SUCCESS;
00845    }
00846 
00847    buf = ast_str_alloca(256);
00848 
00849    for (i = 2; i < a->argc; i++) {
00850       struct ast_tone_zone zone_arg = {
00851          .nrringcadence = 0,
00852       };
00853       struct ast_tone_zone_sound *ts;
00854       int j;
00855 
00856       ast_copy_string(zone_arg.country, a->argv[i], sizeof(zone_arg.country));
00857 
00858       if (!(tz = ao2_find(ast_tone_zones, &zone_arg, OBJ_POINTER))) {
00859          continue;
00860       }
00861 
00862       if (!found_country) {
00863          found_country = 1;
00864          ast_cli(a->fd, "Country Indication      PlayList\n");
00865          ast_cli(a->fd, "=====================================\n");
00866       }
00867 
00868       ast_tone_zone_lock(tz);
00869 
00870       ast_str_set(&buf, 0, "%-7.7s %-15.15s ", tz->country, "<ringcadence>");
00871       for (j = 0; j < tz->nrringcadence; j++) {
00872          ast_str_append(&buf, 0, "%d%s", tz->ringcadence[j],
00873                (j == tz->nrringcadence - 1) ? "" : ",");
00874       }
00875       ast_str_append(&buf, 0, "\n");
00876       ast_cli(a->fd, "%s", buf->str);
00877 
00878       AST_LIST_TRAVERSE(&tz->tones, ts, entry) {
00879          ast_cli(a->fd, "%-7.7s %-15.15s %s\n", tz->country, ts->name, ts->data);
00880       }
00881 
00882       ast_tone_zone_unlock(tz);
00883       tz = ast_tone_zone_unref(tz);
00884    }
00885 
00886    if (!found_country) {
00887       ast_cli(a->fd, "No countries matched your criteria.\n");
00888    }
00889 
00890    return CLI_SUCCESS;
00891 }

static void indications_shutdown ( void   )  [static]

Definition at line 1154 of file indications.c.

References ao2_ref.

Referenced by ast_indications_init().

01155 {
01156    if (ast_tone_zones) {
01157       ao2_ref(ast_tone_zones, -1);
01158       ast_tone_zones = NULL;
01159    }
01160 }

static int is_valid_tone_zone ( struct ast_tone_zone zone  )  [static]

Definition at line 893 of file indications.c.

References AST_LIST_EMPTY, ast_strlen_zero(), ast_tone_zone_lock, ast_tone_zone_unlock, ast_tone_zone::description, and ast_tone_zone::tones.

Referenced by parse_tone_zone().

00894 {
00895    int res;
00896 
00897    ast_tone_zone_lock(zone);
00898    res = (!ast_strlen_zero(zone->description) && !AST_LIST_EMPTY(&zone->tones));
00899    ast_tone_zone_unlock(zone);
00900 
00901    return res;
00902 }

static int load_indications ( int  reload  )  [static]

load indications module

Definition at line 1051 of file indications.c.

References ao2_callback, ao2_lock, ao2_unlock, ast_category_browse(), ast_config_destroy(), ast_config_load2(), ast_log(), ast_set_indication_country(), ast_strlen_zero(), ast_variable_retrieve(), CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, country, LOG_WARNING, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, parse_tone_zone(), prune_tone_zone(), and tone_zone_mark().

Referenced by ast_indications_init(), and ast_indications_reload().

01052 {
01053    struct ast_config *cfg;
01054    const char *cxt = NULL;
01055    const char *country = NULL;
01056    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
01057    int res = -1;
01058 
01059    cfg = ast_config_load2(config, "indications", config_flags);
01060 
01061    if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
01062       ast_log(LOG_WARNING, "Can't find indications config file %s.\n", config);
01063       return 0;
01064    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
01065       return 0;
01066    }
01067 
01068    /* Lock the container to prevent multiple simultaneous reloads */
01069    ao2_lock(ast_tone_zones);
01070 
01071    ao2_callback(ast_tone_zones, OBJ_NODATA, tone_zone_mark, NULL);
01072 
01073    /* Use existing config to populate the Indication table */
01074    while ((cxt = ast_category_browse(cfg, cxt))) {
01075       /* All categories but "general" are considered countries */
01076       if (!strcasecmp(cxt, "general")) {
01077          continue;
01078       }
01079 
01080       if (parse_tone_zone(cfg, cxt)) {
01081          goto return_cleanup;
01082       }
01083    }
01084 
01085    ao2_callback(ast_tone_zones, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK,
01086          prune_tone_zone, NULL);
01087 
01088    /* determine which country is the default */
01089    country = ast_variable_retrieve(cfg, "general", "country");
01090    if (ast_strlen_zero(country) || ast_set_indication_country(country)) {
01091       ast_log(LOG_WARNING, "Unable to set the default country (for indication tones)\n");
01092    }
01093 
01094    res = 0;
01095 
01096 return_cleanup:
01097    ao2_unlock(ast_tone_zones);
01098    ast_config_destroy(cfg);
01099 
01100    return res;
01101 }

static int parse_tone_zone ( struct ast_config cfg,
const char *  country 
) [static]

Definition at line 964 of file indications.c.

References ao2_find, ast_copy_string(), ast_log(), ast_register_indication_country(), ast_tone_zone_alloc(), ast_tone_zone_lock, ast_tone_zone_unlock, ast_tone_zone_unref(), ast_variable_browse(), ast_tone_zone::country, is_valid_tone_zone(), LOG_WARNING, ast_variable::name, ast_variable::next, ast_tone_zone::nrringcadence, OBJ_POINTER, reset_tone_zone(), store_config_tone_zone(), and ast_variable::value.

Referenced by load_indications().

00965 {
00966    struct ast_variable *v;
00967    struct ast_tone_zone *zone;
00968    struct ast_tone_zone tmp_zone = {
00969       .nrringcadence = 0,
00970    };
00971    int allocd = 0;
00972 
00973    ast_copy_string(tmp_zone.country, country, sizeof(tmp_zone.country));
00974 
00975    if ((zone = ao2_find(ast_tone_zones, &tmp_zone, OBJ_POINTER))) {
00976       reset_tone_zone(zone);
00977    } else if ((zone = ast_tone_zone_alloc())) {
00978       allocd = 1;
00979       ast_copy_string(zone->country, country, sizeof(zone->country));
00980    } else {
00981       return -1;
00982    }
00983 
00984    ast_tone_zone_lock(zone);
00985    for (v = ast_variable_browse(cfg, country); v; v = v->next) {
00986       store_config_tone_zone(zone, v->name, v->value);
00987    }
00988    ast_tone_zone_unlock(zone);
00989 
00990    if (allocd) {
00991       if (!is_valid_tone_zone(zone)) {
00992          ast_log(LOG_WARNING, "Indication country '%s' is invalid\n", country);
00993       } else if (ast_register_indication_country(zone)) {
00994          ast_log(LOG_WARNING, "Unable to register indication country '%s'.\n",
00995                country);
00996       }
00997    }
00998 
00999    zone = ast_tone_zone_unref(zone);
01000 
01001    return 0;
01002 }

static void* playtones_alloc ( struct ast_channel chan,
void *  params 
) [static]

Definition at line 145 of file indications.c.

References ast_calloc, ast_channel_flags(), ast_channel_name(), ast_channel_writeformat(), ast_clear_flag, AST_FLAG_WRITE_INT, ast_format_copy(), AST_FORMAT_SLINEAR, ast_log(), ast_set_flag, ast_set_write_format_by_id(), playtones_def::interruptible, playtones_def::items, playtones_state::items, LOG_WARNING, playtones_def::nitems, playtones_state::nitems, playtones_state::oldnpos, playtones_state::origwfmt, playtones_release(), playtones_def::reppos, playtones_state::reppos, playtones_def::vol, and playtones_state::vol.

00146 {
00147    struct playtones_def *pd = params;
00148    struct playtones_state *ps = NULL;
00149 
00150    if (!(ps = ast_calloc(1, sizeof(*ps)))) {
00151       return NULL;
00152    }
00153 
00154    ast_format_copy(&ps->origwfmt, ast_channel_writeformat(chan));
00155 
00156    if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR)) {
00157       ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format (write)\n", ast_channel_name(chan));
00158       playtones_release(NULL, ps);
00159       ps = NULL;
00160    } else {
00161       ps->vol = pd->vol;
00162       ps->reppos = pd->reppos;
00163       ps->nitems = pd->nitems;
00164       ps->items = pd->items;
00165       ps->oldnpos = -1;
00166    }
00167 
00168    /* Let interrupts interrupt :) */
00169    if (pd->interruptible) {
00170       ast_set_flag(ast_channel_flags(chan), AST_FLAG_WRITE_INT);
00171    } else {
00172       ast_clear_flag(ast_channel_flags(chan), AST_FLAG_WRITE_INT);
00173    }
00174 
00175    return ps;
00176 }

static int playtones_generator ( struct ast_channel chan,
void *  data,
int  len,
int  samples 
) [static]

Definition at line 178 of file indications.c.

References ast_format_set(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_write(), ast_frame::data, playtones_state::data, ast_frame::datalen, playtones_item::duration, playtones_state::f, playtones_item::fac1, playtones_item::fac2, ast_frame_subclass::format, ast_frame::frametype, playtones_item::init_v2_1, playtones_item::init_v2_2, playtones_item::init_v3_1, playtones_item::init_v3_2, playtones_state::items, LOG_WARNING, playtones_item::modulate, playtones_state::nitems, playtones_state::npos, ast_frame::offset, playtones_state::oldnpos, playtones_state::pos, ast_frame::ptr, playtones_state::reppos, ast_frame::samples, ast_frame::subclass, playtones_state::v1_1, playtones_state::v1_2, playtones_state::v2_1, playtones_state::v2_2, playtones_state::v3_1, and playtones_state::v3_2.

00179 {
00180    struct playtones_state *ps = data;
00181    struct playtones_item *pi;
00182    int x;
00183 
00184    /* we need to prepare a frame with 16 * timelen samples as we're
00185     * generating SLIN audio */
00186 
00187    len = samples * 2;
00188    if (len > sizeof(ps->data) / 2 - 1) {
00189       ast_log(LOG_WARNING, "Can't generate that much data!\n");
00190       return -1;
00191    }
00192 
00193    memset(&ps->f, 0, sizeof(ps->f));
00194 
00195    pi = &ps->items[ps->npos];
00196 
00197    if (ps->oldnpos != ps->npos) {
00198       /* Load new parameters */
00199       ps->v1_1 = 0;
00200       ps->v2_1 = pi->init_v2_1;
00201       ps->v3_1 = pi->init_v3_1;
00202       ps->v1_2 = 0;
00203       ps->v2_2 = pi->init_v2_2;
00204       ps->v3_2 = pi->init_v3_2;
00205       ps->oldnpos = ps->npos;
00206    }
00207 
00208    for (x = 0; x < samples; x++) {
00209       ps->v1_1 = ps->v2_1;
00210       ps->v2_1 = ps->v3_1;
00211       ps->v3_1 = (pi->fac1 * ps->v2_1 >> 15) - ps->v1_1;
00212 
00213       ps->v1_2 = ps->v2_2;
00214       ps->v2_2 = ps->v3_2;
00215       ps->v3_2 = (pi->fac2 * ps->v2_2 >> 15) - ps->v1_2;
00216       if (pi->modulate) {
00217          int p;
00218          p = ps->v3_2 - 32768;
00219          if (p < 0) {
00220             p = -p;
00221          }
00222          p = ((p * 9) / 10) + 1;
00223          ps->data[x] = (ps->v3_1 * p) >> 15;
00224       } else {
00225          ps->data[x] = ps->v3_1 + ps->v3_2;
00226       }
00227    }
00228 
00229    ps->f.frametype = AST_FRAME_VOICE;
00230    ast_format_set(&ps->f.subclass.format, AST_FORMAT_SLINEAR, 0);
00231    ps->f.datalen = len;
00232    ps->f.samples = samples;
00233    ps->f.offset = AST_FRIENDLY_OFFSET;
00234    ps->f.data.ptr = ps->data;
00235 
00236    if (ast_write(chan, &ps->f)) {
00237       return -1;
00238    }
00239 
00240    ps->pos += x;
00241 
00242    if (pi->duration && ps->pos >= pi->duration * 8) { /* item finished? */
00243       ps->pos = 0;               /* start new item */
00244       ps->npos++;
00245       if (ps->npos >= ps->nitems) {       /* last item? */
00246          if (ps->reppos == -1) {       /* repeat set? */
00247             return -1;
00248          }
00249          ps->npos = ps->reppos;        /* redo from top */
00250       }
00251    }
00252 
00253    return 0;
00254 }

static void playtones_release ( struct ast_channel chan,
void *  params 
) [static]

Definition at line 129 of file indications.c.

References ast_free, ast_set_write_format(), playtones_state::items, and playtones_state::origwfmt.

Referenced by playtones_alloc().

00130 {
00131    struct playtones_state *ps = params;
00132 
00133    if (chan) {
00134       ast_set_write_format(chan, &ps->origwfmt);
00135    }
00136 
00137    if (ps->items) {
00138       ast_free(ps->items);
00139       ps->items = NULL;
00140    }
00141 
00142    ast_free(ps);
00143 }

static int prune_tone_zone ( void *  obj,
void *  arg,
int  flags 
) [static]

Prune tones no longer in the configuration, and have the tone zone unlinked if it is no longer in the configuration at all.

Definition at line 1030 of file indications.c.

References AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_tone_zone_lock, ast_tone_zone_sound_unref(), ast_tone_zone_unlock, CMP_MATCH, ast_tone_zone_sound::entry, ast_tone_zone::killme, ast_tone_zone_sound::killme, and ast_tone_zone::tones.

Referenced by load_indications().

01031 {
01032    struct ast_tone_zone *zone = obj;
01033    struct ast_tone_zone_sound *s;
01034 
01035    ast_tone_zone_lock(zone);
01036 
01037    AST_LIST_TRAVERSE_SAFE_BEGIN(&zone->tones, s, entry) {
01038       if (s->killme) {
01039          AST_LIST_REMOVE_CURRENT(entry);
01040          s = ast_tone_zone_sound_unref(s);
01041       }
01042    }
01043    AST_LIST_TRAVERSE_SAFE_END;
01044 
01045    ast_tone_zone_unlock(zone);
01046 
01047    return zone->killme ? CMP_MATCH : 0;
01048 }

static void reset_tone_zone ( struct ast_tone_zone zone  )  [static]

Definition at line 949 of file indications.c.

References ast_free, ast_tone_zone_lock, ast_tone_zone_unlock, ast_tone_zone::killme, ast_tone_zone::nrringcadence, and ast_tone_zone::ringcadence.

Referenced by parse_tone_zone().

00950 {
00951    ast_tone_zone_lock(zone);
00952 
00953    zone->killme = 0;
00954 
00955    if (zone->nrringcadence) {
00956       zone->nrringcadence = 0;
00957       ast_free(zone->ringcadence);
00958       zone->ringcadence = NULL;
00959    }
00960 
00961    ast_tone_zone_unlock(zone);
00962 }

static void store_config_tone_zone ( struct ast_tone_zone zone,
const char *  var,
const char *  value 
) [static]

Definition at line 935 of file indications.c.

References ast_register_indication(), CV_END, CV_F, CV_START, CV_STR, ast_tone_zone::description, and store_tone_zone_ring_cadence().

Referenced by parse_tone_zone().

00937 {
00938    CV_START(var, value);
00939 
00940    CV_STR("description", zone->description);
00941    CV_F("ringcadence", store_tone_zone_ring_cadence(zone, value));
00942    CV_F("ringcadance", store_tone_zone_ring_cadence(zone, value));
00943 
00944    ast_register_indication(zone, var, value);
00945 
00946    CV_END;
00947 }

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 908 of file indications.c.

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

Referenced by store_config_tone_zone().

00909 {
00910    char buf[1024];
00911    char *ring, *c = buf;
00912 
00913    ast_copy_string(buf, val, sizeof(buf));
00914 
00915    while ((ring = strsep(&c, ","))) {
00916       int *tmp, val;
00917 
00918       ring = ast_strip(ring);
00919 
00920       if (!isdigit(ring[0]) || (val = atoi(ring)) == -1) {
00921          ast_log(LOG_WARNING, "Invalid ringcadence given '%s'.\n", ring);
00922          continue;
00923       }
00924 
00925       if (!(tmp = ast_realloc(zone->ringcadence, (zone->nrringcadence + 1) * sizeof(int)))) {
00926          return;
00927       }
00928 
00929       zone->ringcadence = tmp;
00930       tmp[zone->nrringcadence] = val;
00931       zone->nrringcadence++;
00932    }
00933 }

static int tone_zone_mark ( void *  obj,
void *  arg,
int  flags 
) [static]

Mark the zone and its tones before parsing configuration. We will use this to know what to remove after configuration is parsed.

Definition at line 1008 of file indications.c.

References AST_LIST_TRAVERSE, ast_tone_zone_lock, ast_tone_zone_unlock, ast_tone_zone_sound::entry, ast_tone_zone_sound::killme, ast_tone_zone::killme, and ast_tone_zone::tones.

Referenced by load_indications().

01009 {
01010    struct ast_tone_zone *zone = obj;
01011    struct ast_tone_zone_sound *s;
01012 
01013    ast_tone_zone_lock(zone);
01014 
01015    zone->killme = 1;
01016 
01017    AST_LIST_TRAVERSE(&zone->tones, s, entry) {
01018       s->killme = 1;
01019    }
01020 
01021    ast_tone_zone_unlock(zone);
01022 
01023    return 0;
01024 }


Variable Documentation

struct ao2_container* ast_tone_zones [static]

Definition at line 81 of file indications.c.

struct ast_cli_entry cli_indications[] [static]

Initial value:

 {
   AST_CLI_DEFINE(handle_cli_indication_add,    "Add the given indication to the country"),
   AST_CLI_DEFINE(handle_cli_indication_remove, "Remove the given indication from the country"),
   AST_CLI_DEFINE(handle_cli_indication_show,   "Display a list of all countries/indications")
}
CLI entries for commands provided by this module.

Definition at line 1104 of file indications.c.

const char config[] = "indications.conf" [static]

Definition at line 63 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 88 of file indications.c.

const int midi_tohz[128] [static]

Definition at line 65 of file indications.c.

struct ast_generator playtones [static]

Initial value:

 {
   .alloc     = playtones_alloc,
   .release   = playtones_release,
   .generate  = playtones_generator,
}

Definition at line 256 of file indications.c.


Generated on Thu Oct 11 06:36:29 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6