#include "asterisk.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "asterisk/indications.h"
#include "asterisk/frame.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/logger.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
Go to the source code of this file.
Data Structures | |
struct | playtones_def |
struct | playtones_item |
struct | playtones_state |
Functions | |
struct tone_zone_sound * | ast_get_indication_tone (const struct tone_zone *zone, const char *indication) |
struct tone_zone * | ast_get_indication_zone (const char *country) |
AST_MUTEX_DEFINE_STATIC (tzlock) | |
int | ast_playtones_start (struct ast_channel *chan, int vol, const char *playlst, int interruptible) |
void | ast_playtones_stop (struct ast_channel *chan) |
int | ast_register_indication (struct tone_zone *zone, const char *indication, const char *tonelist) |
int | ast_register_indication_country (struct tone_zone *zone) |
int | ast_set_indication_country (const char *country) |
int | ast_unregister_indication (struct tone_zone *zone, const char *indication) |
int | ast_unregister_indication_country (const char *country) |
struct tone_zone * | ast_walk_indications (const struct tone_zone *cur) |
static void | free_zone (struct tone_zone *zone) |
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) |
Variables | |
static struct tone_zone * | current_tonezone |
static int | midi_tohz [128] |
static struct ast_generator | playtones |
static struct tone_zone * | tone_zones |
This set of function allow us to play a list of tones on a channel. Each element has two frequencies, which are mixed together and a duration. For silence both frequencies can be set to 0. The playtones can be given as a comma separated string.
Definition in file indications.c.
struct tone_zone_sound* ast_get_indication_tone | ( | const struct tone_zone * | zone, | |
const char * | indication | |||
) | [read] |
Definition at line 406 of file indications.c.
Referenced by ast_app_dtget(), ast_indicate_data(), dialtone_indicate(), handle_playtones(), play_dialtone(), and read_exec().
00407 { 00408 struct tone_zone_sound *ts; 00409 00410 /* we need some tonezone, pick the first */ 00411 if (zone == NULL && current_tonezone) 00412 zone = current_tonezone; /* default country? */ 00413 if (zone == NULL && tone_zones) 00414 zone = tone_zones; /* any country? */ 00415 if (zone == NULL) 00416 return 0; /* not a single country insight */ 00417 00418 ast_mutex_lock(&tzlock); 00419 for (ts=zone->tones; ts; ts=ts->next) { 00420 if (strcasecmp(indication,ts->name)==0) { 00421 /* found indication! */ 00422 ast_mutex_unlock(&tzlock); 00423 return ts; 00424 } 00425 } 00426 /* nothing found, sorry */ 00427 ast_mutex_unlock(&tzlock); 00428 return 0; 00429 }
struct tone_zone* ast_get_indication_zone | ( | const char * | country | ) | [read] |
Definition at line 371 of file indications.c.
Referenced by ast_set_indication_country(), func_channel_write(), handle_add_indication(), and handle_remove_indication().
00372 { 00373 struct tone_zone *tz; 00374 int alias_loop = 0; 00375 00376 /* we need some tonezone, pick the first */ 00377 if (country == NULL && current_tonezone) 00378 return current_tonezone; /* default country? */ 00379 if (country == NULL && tone_zones) 00380 return tone_zones; /* any country? */ 00381 if (country == NULL) 00382 return 0; /* not a single country insight */ 00383 00384 ast_mutex_lock(&tzlock); 00385 do { 00386 for (tz=tone_zones; tz; tz=tz->next) { 00387 if (strcasecmp(country,tz->country)==0) { 00388 /* tone_zone found */ 00389 if (tz->alias && tz->alias[0]) { 00390 country = tz->alias; 00391 break; 00392 } 00393 ast_mutex_unlock(&tzlock); 00394 return tz; 00395 } 00396 } 00397 } while (++alias_loop<20 && tz); 00398 ast_mutex_unlock(&tzlock); 00399 if (alias_loop==20) 00400 ast_log(LOG_NOTICE,"Alias loop for '%s' forcefull broken\n",country); 00401 /* nothing found, sorry */ 00402 return 0; 00403 }
AST_MUTEX_DEFINE_STATIC | ( | tzlock | ) |
int ast_playtones_start | ( | struct ast_channel * | chan, | |
int | vol, | |||
const char * | playlst, | |||
int | interruptible | |||
) |
Definition at line 212 of file indications.c.
Referenced by ast_app_dtget(), ast_indicate_data(), ast_senddigit_begin(), dialtone_indicate(), do_dtmf_local(), handle_playtones(), play_dialtone(), playtone(), read_exec(), and send_digit_to_chan().
00213 { 00214 char *s, *data = ast_strdupa(playlst); /* cute */ 00215 struct playtones_def d = { vol, -1, 0, 1, NULL}; 00216 char *stringp; 00217 char *separator; 00218 00219 if (vol < 1) 00220 d.vol = 7219; /* Default to -8db */ 00221 00222 d.interruptible = interruptible; 00223 00224 stringp=data; 00225 /* the stringp/data is not null here */ 00226 /* check if the data is separated with '|' or with ',' by default */ 00227 if (strchr(stringp,'|')) 00228 separator = "|"; 00229 else 00230 separator = ","; 00231 s = strsep(&stringp,separator); 00232 while (s && *s) { 00233 int freq1, freq2, time, modulate=0, midinote=0; 00234 00235 if (s[0]=='!') 00236 s++; 00237 else if (d.reppos == -1) 00238 d.reppos = d.nitems; 00239 if (sscanf(s, "%d+%d/%d", &freq1, &freq2, &time) == 3) { 00240 /* f1+f2/time format */ 00241 } else if (sscanf(s, "%d+%d", &freq1, &freq2) == 2) { 00242 /* f1+f2 format */ 00243 time = 0; 00244 } else if (sscanf(s, "%d*%d/%d", &freq1, &freq2, &time) == 3) { 00245 /* f1*f2/time format */ 00246 modulate = 1; 00247 } else if (sscanf(s, "%d*%d", &freq1, &freq2) == 2) { 00248 /* f1*f2 format */ 00249 time = 0; 00250 modulate = 1; 00251 } else if (sscanf(s, "%d/%d", &freq1, &time) == 2) { 00252 /* f1/time format */ 00253 freq2 = 0; 00254 } else if (sscanf(s, "%d", &freq1) == 1) { 00255 /* f1 format */ 00256 freq2 = 0; 00257 time = 0; 00258 } else if (sscanf(s, "M%d+M%d/%d", &freq1, &freq2, &time) == 3) { 00259 /* Mf1+Mf2/time format */ 00260 midinote = 1; 00261 } else if (sscanf(s, "M%d+M%d", &freq1, &freq2) == 2) { 00262 /* Mf1+Mf2 format */ 00263 time = 0; 00264 midinote = 1; 00265 } else if (sscanf(s, "M%d*M%d/%d", &freq1, &freq2, &time) == 3) { 00266 /* Mf1*Mf2/time format */ 00267 modulate = 1; 00268 midinote = 1; 00269 } else if (sscanf(s, "M%d*M%d", &freq1, &freq2) == 2) { 00270 /* Mf1*Mf2 format */ 00271 time = 0; 00272 modulate = 1; 00273 midinote = 1; 00274 } else if (sscanf(s, "M%d/%d", &freq1, &time) == 2) { 00275 /* Mf1/time format */ 00276 freq2 = -1; 00277 midinote = 1; 00278 } else if (sscanf(s, "M%d", &freq1) == 1) { 00279 /* Mf1 format */ 00280 freq2 = -1; 00281 time = 0; 00282 midinote = 1; 00283 } else { 00284 ast_log(LOG_WARNING,"%s: tone component '%s' of '%s' is no good\n",chan->name,s,playlst); 00285 return -1; 00286 } 00287 00288 if (midinote) { 00289 /* midi notes must be between 0 and 127 */ 00290 if ((freq1 >= 0) && (freq1 <= 127)) 00291 freq1 = midi_tohz[freq1]; 00292 else 00293 freq1 = 0; 00294 00295 if ((freq2 >= 0) && (freq2 <= 127)) 00296 freq2 = midi_tohz[freq2]; 00297 else 00298 freq2 = 0; 00299 } 00300 00301 if (!(d.items = ast_realloc(d.items, (d.nitems + 1) * sizeof(*d.items)))) { 00302 return -1; 00303 } 00304 d.items[d.nitems].fac1 = 2.0 * cos(2.0 * M_PI * (freq1 / 8000.0)) * 32768.0; 00305 d.items[d.nitems].init_v2_1 = sin(-4.0 * M_PI * (freq1 / 8000.0)) * d.vol; 00306 d.items[d.nitems].init_v3_1 = sin(-2.0 * M_PI * (freq1 / 8000.0)) * d.vol; 00307 00308 d.items[d.nitems].fac2 = 2.0 * cos(2.0 * M_PI * (freq2 / 8000.0)) * 32768.0; 00309 d.items[d.nitems].init_v2_2 = sin(-4.0 * M_PI * (freq2 / 8000.0)) * d.vol; 00310 d.items[d.nitems].init_v3_2 = sin(-2.0 * M_PI * (freq2 / 8000.0)) * d.vol; 00311 d.items[d.nitems].duration = time; 00312 d.items[d.nitems].modulate = modulate; 00313 d.nitems++; 00314 00315 s = strsep(&stringp,separator); 00316 } 00317 00318 if (ast_activate_generator(chan, &playtones, &d)) { 00319 free(d.items); 00320 return -1; 00321 } 00322 return 0; 00323 }
void ast_playtones_stop | ( | struct ast_channel * | chan | ) |
Stop the tones from playing
Definition at line 325 of file indications.c.
Referenced by ast_app_dtget(), ast_indicate_data(), ast_senddigit_end(), disa_exec(), handle_stopplaytones(), playtone(), read_exec(), and stop_indicate().
00326 { 00327 ast_deactivate_generator(chan); 00328 }
int ast_register_indication | ( | struct tone_zone * | zone, | |
const char * | indication, | |||
const char * | tonelist | |||
) |
Definition at line 528 of file indications.c.
Referenced by handle_add_indication().
00529 { 00530 struct tone_zone_sound *ts,*ps; 00531 00532 /* is it an alias? stop */ 00533 if (zone->alias[0]) 00534 return -1; 00535 00536 ast_mutex_lock(&tzlock); 00537 for (ps=NULL,ts=zone->tones; ts; ps=ts,ts=ts->next) { 00538 if (strcasecmp(indication,ts->name)==0) { 00539 /* indication already there, replace */ 00540 free((void*)ts->name); 00541 free((void*)ts->data); 00542 break; 00543 } 00544 } 00545 if (!ts) { 00546 /* not there, we have to add */ 00547 if (!(ts = ast_malloc(sizeof(*ts)))) { 00548 ast_mutex_unlock(&tzlock); 00549 return -2; 00550 } 00551 ts->next = NULL; 00552 } 00553 if (!(ts->name = ast_strdup(indication)) || !(ts->data = ast_strdup(tonelist))) { 00554 ast_mutex_unlock(&tzlock); 00555 return -2; 00556 } 00557 if (ps) 00558 ps->next = ts; 00559 else 00560 zone->tones = ts; 00561 ast_mutex_unlock(&tzlock); 00562 return 0; 00563 }
int ast_register_indication_country | ( | struct tone_zone * | zone | ) |
Definition at line 449 of file indications.c.
Referenced by handle_add_indication(), and ind_load_module().
00450 { 00451 struct tone_zone *tz,*pz; 00452 00453 ast_mutex_lock(&tzlock); 00454 for (pz=NULL,tz=tone_zones; tz; pz=tz,tz=tz->next) { 00455 if (strcasecmp(zone->country,tz->country)==0) { 00456 /* tone_zone already there, replace */ 00457 zone->next = tz->next; 00458 if (pz) 00459 pz->next = zone; 00460 else 00461 tone_zones = zone; 00462 /* if we are replacing the default zone, re-point it */ 00463 if (tz == current_tonezone) 00464 current_tonezone = zone; 00465 /* now free the previous zone */ 00466 free_zone(tz); 00467 ast_mutex_unlock(&tzlock); 00468 return 0; 00469 } 00470 } 00471 /* country not there, add */ 00472 zone->next = NULL; 00473 if (pz) 00474 pz->next = zone; 00475 else 00476 tone_zones = zone; 00477 ast_mutex_unlock(&tzlock); 00478 00479 if (option_verbose > 2) 00480 ast_verbose(VERBOSE_PREFIX_3 "Registered indication country '%s'\n",zone->country); 00481 return 0; 00482 }
int ast_set_indication_country | ( | const char * | country | ) |
Definition at line 356 of file indications.c.
Referenced by ind_load_module().
00357 { 00358 if (country) { 00359 struct tone_zone *z = ast_get_indication_zone(country); 00360 if (z) { 00361 if (option_verbose > 2) 00362 ast_verbose(VERBOSE_PREFIX_3 "Setting default indication country to '%s'\n",country); 00363 current_tonezone = z; 00364 return 0; 00365 } 00366 } 00367 return 1; /* not found */ 00368 }
int ast_unregister_indication | ( | struct tone_zone * | zone, | |
const char * | indication | |||
) |
Definition at line 566 of file indications.c.
Referenced by handle_remove_indication().
00567 { 00568 struct tone_zone_sound *ts,*ps = NULL, *tmp; 00569 int res = -1; 00570 00571 /* is it an alias? stop */ 00572 if (zone->alias[0]) 00573 return -1; 00574 00575 ast_mutex_lock(&tzlock); 00576 ts = zone->tones; 00577 while (ts) { 00578 if (strcasecmp(indication,ts->name)==0) { 00579 /* indication found */ 00580 tmp = ts->next; 00581 if (ps) 00582 ps->next = tmp; 00583 else 00584 zone->tones = tmp; 00585 free((void*)ts->name); 00586 free((void*)ts->data); 00587 free(ts); 00588 ts = tmp; 00589 res = 0; 00590 } 00591 else { 00592 /* next zone please */ 00593 ps = ts; 00594 ts = ts->next; 00595 } 00596 } 00597 /* indication not found, goodbye */ 00598 ast_mutex_unlock(&tzlock); 00599 return res; 00600 }
int ast_unregister_indication_country | ( | const char * | country | ) |
Definition at line 486 of file indications.c.
Referenced by handle_add_indication(), handle_remove_indication(), reload(), and unload_module().
00487 { 00488 struct tone_zone *tz, *pz = NULL, *tmp; 00489 int res = -1; 00490 00491 ast_mutex_lock(&tzlock); 00492 tz = tone_zones; 00493 while (tz) { 00494 if (country==NULL || 00495 (strcasecmp(country, tz->country)==0 || 00496 strcasecmp(country, tz->alias)==0)) { 00497 /* tone_zone found, remove */ 00498 tmp = tz->next; 00499 if (pz) 00500 pz->next = tmp; 00501 else 00502 tone_zones = tmp; 00503 /* if we are unregistering the default country, w'll notice */ 00504 if (tz == current_tonezone) { 00505 ast_log(LOG_NOTICE,"Removed default indication country '%s'\n",tz->country); 00506 current_tonezone = NULL; 00507 } 00508 if (option_verbose > 2) 00509 ast_verbose(VERBOSE_PREFIX_3 "Unregistered indication country '%s'\n",tz->country); 00510 free_zone(tz); 00511 if (tone_zones == tz) 00512 tone_zones = tmp; 00513 tz = tmp; 00514 res = 0; 00515 } 00516 else { 00517 /* next zone please */ 00518 pz = tz; 00519 tz = tz->next; 00520 } 00521 } 00522 ast_mutex_unlock(&tzlock); 00523 return res; 00524 }
Definition at line 339 of file indications.c.
Referenced by handle_show_indications().
00340 { 00341 struct tone_zone *tz; 00342 00343 if (cur == NULL) 00344 return tone_zones; 00345 ast_mutex_lock(&tzlock); 00346 for (tz = tone_zones; tz; tz = tz->next) 00347 if (tz == cur) 00348 break; 00349 if (tz) 00350 tz = tz->next; 00351 ast_mutex_unlock(&tzlock); 00352 return tz; 00353 }
static void free_zone | ( | struct tone_zone * | zone | ) | [inline, static] |
Definition at line 432 of file indications.c.
References tone_zone_sound::data, free, tone_zone_sound::name, tone_zone_sound::next, tone_zone::ringcadence, and tone_zone::tones.
Referenced by ast_register_indication_country(), ast_unregister_indication_country(), and load_config().
00433 { 00434 while (zone->tones) { 00435 struct tone_zone_sound *tmp = zone->tones->next; 00436 free((void*)zone->tones->name); 00437 free((void*)zone->tones->data); 00438 free(zone->tones); 00439 zone->tones = tmp; 00440 } 00441 if (zone->ringcadence) 00442 free(zone->ringcadence); 00443 free(zone); 00444 }
static void* playtones_alloc | ( | struct ast_channel * | chan, | |
void * | params | |||
) | [static] |
Definition at line 113 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.
00114 { 00115 struct playtones_def *pd = params; 00116 struct playtones_state *ps; 00117 if (!(ps = ast_calloc(1, sizeof(*ps)))) 00118 return NULL; 00119 ps->origwfmt = chan->writeformat; 00120 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) { 00121 ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format (write)\n", chan->name); 00122 playtones_release(NULL, ps); 00123 ps = NULL; 00124 } else { 00125 ps->vol = pd->vol; 00126 ps->reppos = pd->reppos; 00127 ps->nitems = pd->nitems; 00128 ps->items = pd->items; 00129 ps->oldnpos = -1; 00130 } 00131 /* Let interrupts interrupt :) */ 00132 if (pd->interruptible) 00133 ast_set_flag(chan, AST_FLAG_WRITE_INT); 00134 else 00135 ast_clear_flag(chan, AST_FLAG_WRITE_INT); 00136 return ps; 00137 }
static int playtones_generator | ( | struct ast_channel * | chan, | |
void * | data, | |||
int | len, | |||
int | samples | |||
) | [static] |
Definition at line 139 of file indications.c.
References AST_FORMAT_SLINEAR, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_write(), ast_frame::data, playtones_state::data, ast_frame::datalen, ast_frame::delivery, 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, 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.
00140 { 00141 struct playtones_state *ps = data; 00142 struct playtones_item *pi; 00143 int x; 00144 /* we need to prepare a frame with 16 * timelen samples as we're 00145 * generating SLIN audio 00146 */ 00147 len = samples * 2; 00148 if (len > sizeof(ps->data) / 2 - 1) { 00149 ast_log(LOG_WARNING, "Can't generate that much data!\n"); 00150 return -1; 00151 } 00152 memset(&ps->f, 0, sizeof(ps->f)); 00153 00154 pi = &ps->items[ps->npos]; 00155 if (ps->oldnpos != ps->npos) { 00156 /* Load new parameters */ 00157 ps->v1_1 = 0; 00158 ps->v2_1 = pi->init_v2_1; 00159 ps->v3_1 = pi->init_v3_1; 00160 ps->v1_2 = 0; 00161 ps->v2_2 = pi->init_v2_2; 00162 ps->v3_2 = pi->init_v3_2; 00163 ps->oldnpos = ps->npos; 00164 } 00165 for (x=0;x<len/2;x++) { 00166 ps->v1_1 = ps->v2_1; 00167 ps->v2_1 = ps->v3_1; 00168 ps->v3_1 = (pi->fac1 * ps->v2_1 >> 15) - ps->v1_1; 00169 00170 ps->v1_2 = ps->v2_2; 00171 ps->v2_2 = ps->v3_2; 00172 ps->v3_2 = (pi->fac2 * ps->v2_2 >> 15) - ps->v1_2; 00173 if (pi->modulate) { 00174 int p; 00175 p = ps->v3_2 - 32768; 00176 if (p < 0) p = -p; 00177 p = ((p * 9) / 10) + 1; 00178 ps->data[x] = (ps->v3_1 * p) >> 15; 00179 } else 00180 ps->data[x] = ps->v3_1 + ps->v3_2; 00181 } 00182 00183 ps->f.frametype = AST_FRAME_VOICE; 00184 ps->f.subclass = AST_FORMAT_SLINEAR; 00185 ps->f.datalen = len; 00186 ps->f.samples = samples; 00187 ps->f.offset = AST_FRIENDLY_OFFSET; 00188 ps->f.data = ps->data; 00189 ps->f.delivery.tv_sec = 0; 00190 ps->f.delivery.tv_usec = 0; 00191 ast_write(chan, &ps->f); 00192 00193 ps->pos += x; 00194 if (pi->duration && ps->pos >= pi->duration * 8) { /* item finished? */ 00195 ps->pos = 0; /* start new item */ 00196 ps->npos++; 00197 if (ps->npos >= ps->nitems) { /* last item? */ 00198 if (ps->reppos == -1) /* repeat set? */ 00199 return -1; 00200 ps->npos = ps->reppos; /* redo from top */ 00201 } 00202 } 00203 return 0; 00204 }
static void playtones_release | ( | struct ast_channel * | chan, | |
void * | params | |||
) | [static] |
Definition at line 103 of file indications.c.
References ast_set_write_format(), free, playtones_state::items, and playtones_state::origwfmt.
Referenced by playtones_alloc().
00104 { 00105 struct playtones_state *ps = params; 00106 if (chan) { 00107 ast_set_write_format(chan, ps->origwfmt); 00108 } 00109 if (ps->items) free(ps->items); 00110 free(ps); 00111 }
struct tone_zone* current_tonezone [static] |
Definition at line 333 of file indications.c.
int midi_tohz[128] [static] |
Definition at line 48 of file indications.c.
struct ast_generator playtones [static] |
Initial value:
{ alloc: playtones_alloc, release: playtones_release, generate: playtones_generator, }
Definition at line 206 of file indications.c.
struct tone_zone* tone_zones [static] |
Definition at line 332 of file indications.c.