#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_sound * | ast_get_indication_tone (const struct ast_tone_zone *_zone, const char *indication) |
| Locate a tone zone sound. | |
| struct ast_tone_zone * | ast_get_indication_zone (const char *country) |
| locate ast_tone_zone, given the country. if country == NULL, use the default country | |
| 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_zone * | ast_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_container * | ast_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_zone * | default_tone_zone |
| static const int | midi_tohz [128] |
| static struct ast_generator | playtones |
Definition in file indications.c.
| #define DATA_EXPORT_TONE_ZONE | ( | MEMBER | ) |
Value:
MEMBER(ast_tone_zone, country, AST_DATA_STRING) \ MEMBER(ast_tone_zone, description, AST_DATA_STRING) \ MEMBER(ast_tone_zone, nrringcadence, AST_DATA_UNSIGNED_INTEGER)
Definition at line 49 of file indications.c.
| #define DATA_EXPORT_TONE_ZONE_SOUND | ( | MEMBER | ) |
Value:
MEMBER(ast_tone_zone_sound, name, AST_DATA_STRING) \ MEMBER(ast_tone_zone_sound, data, AST_DATA_STRING)
Definition at line 56 of file indications.c.
| #define NUM_TONE_ZONE_BUCKETS 53 |
| 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.
| zone | Zone to look in for a sound, if NULL, the default will be used | |
| indication | Sound to look for, such as "busy" |
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.
| 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 |
| 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 | ) |
Stop playing tones on a channel.
| chan | the channel to stop tones on |
Definition at line 408 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(), send_tone_burst(), sendfax_t38_init(), stop_indicate(), and unistim_indicate().
00409 { 00410 ast_deactivate_generator(chan); 00411 }
| static int ast_register_indication | ( | struct ast_tone_zone * | zone, | |
| const char * | indication, | |||
| const char * | tonelist | |||
| ) | [static] |
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.
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.
| <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.
Use ao2_iterator_destroy() to clean up.
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.
| 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. |
| 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] |
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 }
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")
}
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] |
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.
1.5.6