Mon Aug 31 12:30:37 2015

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"

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
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)
static int ast_set_indication_country (const char *country)
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)
static int ast_unregister_indication_country (const char *country)
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)
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)

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 473 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, and ast_tone_zone_sound::name.

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(), and skinny_transfer().

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

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

locate ast_tone_zone

Parameters:
country country to find. If NULL is provided, get the default.
Returns:
a reference to the specified country if found or NULL if not found

Definition at line 451 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(), func_channel_write_real(), handle_cli_indication_add(), and handle_cli_indication_remove().

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

int ast_indications_init ( void   ) 

Load indications module.

Provided by indications.c

Definition at line 1169 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().

01170 {
01171    if (!(ast_tone_zones = ao2_container_alloc(NUM_TONE_ZONE_BUCKETS,
01172          ast_tone_zone_hash, ast_tone_zone_cmp))) {
01173       return -1;
01174    }
01175 
01176    if (load_indications(0)) {
01177       indications_shutdown();
01178       return -1;
01179    }
01180 
01181    ast_cli_register_multiple(cli_indications, ARRAY_LEN(cli_indications));
01182 
01183    ast_register_atexit(indications_shutdown);
01184    return 0;
01185 }

int ast_indications_reload ( void   ) 

Reload indications module.

Provided by indications.c

Definition at line 1188 of file indications.c.

References load_indications().

01189 {
01190    return load_indications(1);
01191 }

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, 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(), 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 playtones_item *new_items;
00345       struct ast_tone_zone_part tone_data = {
00346          .time = 0,
00347       };
00348 
00349       s = ast_strip(s);
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       new_items = ast_realloc(d.items, (d.nitems + 1) * sizeof(*d.items));
00378       if (!new_items) {
00379          ast_free(d.items);
00380          return -1;
00381       }
00382       d.items = new_items;
00383 
00384       d.items[d.nitems].fac1 = 2.0 * cos(2.0 * M_PI * (tone_data.freq1 / sample_rate)) * max_sample_val;
00385       d.items[d.nitems].init_v2_1 = sin(-4.0 * M_PI * (tone_data.freq1 / sample_rate)) * d.vol;
00386       d.items[d.nitems].init_v3_1 = sin(-2.0 * M_PI * (tone_data.freq1 / sample_rate)) * d.vol;
00387 
00388       d.items[d.nitems].fac2 = 2.0 * cos(2.0 * M_PI * (tone_data.freq2 / sample_rate)) * max_sample_val;
00389       d.items[d.nitems].init_v2_2 = sin(-4.0 * M_PI * (tone_data.freq2 / sample_rate)) * d.vol;
00390       d.items[d.nitems].init_v3_2 = sin(-2.0 * M_PI * (tone_data.freq2 / sample_rate)) * d.vol;
00391 
00392       d.items[d.nitems].duration = tone_data.time;
00393       d.items[d.nitems].modulate = tone_data.modulate;
00394 
00395       d.nitems++;
00396    }
00397 
00398    if (!d.nitems) {
00399       ast_log(LOG_ERROR, "No valid tone parts\n");
00400       return -1;
00401    }
00402 
00403    if (ast_activate_generator(chan, &playtones, &d)) {
00404       ast_free(d.items);
00405       return -1;
00406    }
00407 
00408    return 0;
00409 }

void ast_playtones_stop ( struct ast_channel chan  ) 

Stop playing tones on a channel.

Parameters:
chan the channel to stop tones on

Definition at line 411 of file indications.c.

References ast_deactivate_generator().

Referenced by ast_app_dtget(), ast_indicate_data(), ast_senddigit_end(), disa_exec(), handle_stopplaytones(), pbx_builtin_waitexten(), playtone(), read_exec(), readexten_exec(), receivefax_t38_init(), sendfax_t38_init(), stop_indicate(), and unistim_indicate().

00412 {
00413    ast_deactivate_generator(chan);
00414 }

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 588 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, and ast_tone_zone_sound::name.

Referenced by handle_cli_indication_add(), and store_config_tone_zone().

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

static int ast_register_indication_country ( struct ast_tone_zone zone  )  [static]

Definition at line 541 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().

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

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

Definition at line 427 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().

00428 {
00429    struct ast_tone_zone *zone = NULL;
00430 
00431    /* If no country is specified or we are unable to find the zone, then return not found */
00432    if (ast_strlen_zero(country) || !(zone = ast_get_indication_zone(country))) {
00433       return -1;
00434    }
00435 
00436    ast_verb(3, "Setting default indication country to '%s'\n", country);
00437 
00438    ao2_lock(ast_tone_zones);
00439    if (default_tone_zone) {
00440       default_tone_zone = ast_tone_zone_unref(default_tone_zone);
00441    }
00442    default_tone_zone = ast_tone_zone_ref(zone);
00443    ao2_unlock(ast_tone_zones);
00444 
00445    zone = ast_tone_zone_unref(zone);
00446 
00447    return 0;
00448 }

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

Definition at line 643 of file indications.c.

References ao2_alloc, and ast_tone_zone_destructor().

Referenced by handle_cli_indication_add(), and parse_tone_zone().

00644 {
00645    return ao2_alloc(sizeof(struct ast_tone_zone), ast_tone_zone_destructor);
00646 }

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

Definition at line 1118 of file indications.c.

References CMP_MATCH, CMP_STOP, and ast_tone_zone::country.

Referenced by ast_indications_init().

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

int ast_tone_zone_count ( void   ) 

Get the number of registered tone zones.

Returns:
the total number of registered tone zones

Definition at line 416 of file indications.c.

References ao2_container_count().

00417 {
00418    return ao2_container_count(ast_tone_zones);
00419 }

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

References ast_data_add_node(), ast_data_add_structure, AST_LIST_EMPTY, AST_LIST_TRAVERSE, ast_tone_zone_lock, and ast_tone_zone_unlock.

Referenced by ast_channel_data_add_structure().

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

static void ast_tone_zone_destructor ( void *  obj  )  [static]

deallocate the passed tone zone

Definition at line 525 of file indications.c.

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

Referenced by ast_tone_zone_alloc().

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

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

Definition at line 1111 of file indications.c.

References ast_str_case_hash(), and ast_tone_zone::country.

Referenced by ast_indications_init().

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

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

References ao2_iterator_init().

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

00422 {
00423    return ao2_iterator_init(ast_tone_zones, 0);
00424 }

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().

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

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

Referenced by ast_register_indication().

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

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

Definition at line 621 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, and ast_tone_zone_sound::name.

Referenced by handle_cli_indication_remove().

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

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

Definition at line 557 of file indications.c.

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

Referenced by handle_cli_indication_add(), and handle_cli_indication_remove().

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

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

Definition at line 648 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().

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

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

Definition at line 734 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, tz, and ast_cli_args::word.

Referenced by handle_cli_indication_remove().

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

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

Definition at line 673 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.

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

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

Definition at line 766 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.

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

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

Definition at line 815 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_buffer(), 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_cli_args::fd, ast_tone_zone_sound::name, ast_tone_zone::nrringcadence, OBJ_POINTER, ast_tone_zone::ringcadence, tz, and ast_cli_entry::usage.

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

static void indications_shutdown ( void   )  [static]

Definition at line 1155 of file indications.c.

References ao2_ref, ARRAY_LEN, ast_cli_unregister_multiple(), and ast_tone_zone_unref().

Referenced by ast_indications_init().

01156 {
01157    ast_cli_unregister_multiple(cli_indications, ARRAY_LEN(cli_indications));
01158    if (default_tone_zone) {
01159       ast_tone_zone_unref(default_tone_zone);
01160       default_tone_zone = NULL;
01161    }
01162    if (ast_tone_zones) {
01163       ao2_ref(ast_tone_zones, -1);
01164       ast_tone_zones = NULL;
01165    }
01166 }

static int is_valid_tone_zone ( struct ast_tone_zone zone  )  [static]

Definition at line 896 of file indications.c.

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

Referenced by parse_tone_zone().

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

static int load_indications ( int  reload  )  [static]

load indications module

Definition at line 1052 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().

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

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

Definition at line 965 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().

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

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

Definition at line 145 of file indications.c.

References ast_calloc, ast_clear_flag, AST_FLAG_WRITE_INT, AST_FORMAT_SLINEAR, ast_log(), ast_set_flag, ast_set_write_format(), 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, playtones_state::vol, and ast_channel::writeformat.

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    ps->origwfmt = chan->writeformat;
00155 
00156    if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
00157       ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format (write)\n", chan->name);
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(chan, AST_FLAG_WRITE_INT);
00171    } else {
00172       ast_clear_flag(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_SLINEAR, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_write(), ast_frame_subclass::codec, ast_frame::data, playtones_state::data, ast_frame::datalen, playtones_item::duration, playtones_state::f, playtones_item::fac1, playtones_item::fac2, 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    ps->f.subclass.codec = AST_FORMAT_SLINEAR;
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 1031 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::killme, and ast_tone_zone_sound::killme.

Referenced by load_indications().

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

static void reset_tone_zone ( struct ast_tone_zone zone  )  [static]

Definition at line 950 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().

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

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

Definition at line 937 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().

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

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

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

Referenced by store_config_tone_zone().

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

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

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

Referenced by load_indications().

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


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 1105 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 31 Aug 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1