00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034 #include <math.h>
00035
00036 #include "asterisk.h"
00037
00038 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 7221 $")
00039
00040 #include "asterisk/indications.h"
00041 #include "asterisk/frame.h"
00042 #include "asterisk/options.h"
00043 #include "asterisk/channel.h"
00044 #include "asterisk/logger.h"
00045 #include "asterisk/lock.h"
00046 #include "asterisk/utils.h"
00047
00048 static int midi_tohz[128] = {
00049 8,8,9,9,10,10,11,12,12,13,14,
00050 15,16,17,18,19,20,21,23,24,25,
00051 27,29,30,32,34,36,38,41,43,46,
00052 48,51,55,58,61,65,69,73,77,82,
00053 87,92,97,103,110,116,123,130,138,146,
00054 155,164,174,184,195,207,220,233,246,261,
00055 277,293,311,329,349,369,391,415,440,466,
00056 493,523,554,587,622,659,698,739,783,830,
00057 880,932,987,1046,1108,1174,1244,1318,1396,1479,
00058 1567,1661,1760,1864,1975,2093,2217,2349,2489,2637,
00059 2793,2959,3135,3322,3520,3729,3951,4186,4434,4698,
00060 4978,5274,5587,5919,6271,6644,7040,7458,7902,8372,
00061 8869,9397,9956,10548,11175,11839,12543
00062 };
00063
00064 struct playtones_item {
00065 int fac1;
00066 int init_v2_1;
00067 int init_v3_1;
00068 int fac2;
00069 int init_v2_2;
00070 int init_v3_2;
00071 int modulate;
00072 int duration;
00073 };
00074
00075 struct playtones_def {
00076 int vol;
00077 int reppos;
00078 int nitems;
00079 int interruptible;
00080 struct playtones_item *items;
00081 };
00082
00083 struct playtones_state {
00084 int vol;
00085 int v1_1;
00086 int v2_1;
00087 int v3_1;
00088 int v1_2;
00089 int v2_2;
00090 int v3_2;
00091 int reppos;
00092 int nitems;
00093 struct playtones_item *items;
00094 int npos;
00095 int oldnpos;
00096 int pos;
00097 int origwfmt;
00098 struct ast_frame f;
00099 unsigned char offset[AST_FRIENDLY_OFFSET];
00100 short data[4000];
00101 };
00102
00103 static void playtones_release(struct ast_channel *chan, void *params)
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 }
00112
00113 static void * playtones_alloc(struct ast_channel *chan, void *params)
00114 {
00115 struct playtones_def *pd = params;
00116 struct playtones_state *ps = malloc(sizeof(struct playtones_state));
00117 if (!ps)
00118 return NULL;
00119 memset(ps, 0, sizeof(struct playtones_state));
00120 ps->origwfmt = chan->writeformat;
00121 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
00122 ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format (write)\n", chan->name);
00123 playtones_release(NULL, ps);
00124 ps = NULL;
00125 } else {
00126 ps->vol = pd->vol;
00127 ps->reppos = pd->reppos;
00128 ps->nitems = pd->nitems;
00129 ps->items = pd->items;
00130 ps->oldnpos = -1;
00131 }
00132
00133 if (pd->interruptible)
00134 ast_set_flag(chan, AST_FLAG_WRITE_INT);
00135 else
00136 ast_clear_flag(chan, AST_FLAG_WRITE_INT);
00137 return ps;
00138 }
00139
00140 static int playtones_generator(struct ast_channel *chan, void *data, int len, int samples)
00141 {
00142 struct playtones_state *ps = data;
00143 struct playtones_item *pi;
00144 int x;
00145
00146
00147
00148 len = samples * 2;
00149 if (len > sizeof(ps->data) / 2 - 1) {
00150 ast_log(LOG_WARNING, "Can't generate that much data!\n");
00151 return -1;
00152 }
00153 memset(&ps->f, 0, sizeof(ps->f));
00154
00155 pi = &ps->items[ps->npos];
00156 if (ps->oldnpos != ps->npos) {
00157
00158 ps->v1_1 = 0;
00159 ps->v2_1 = pi->init_v2_1;
00160 ps->v3_1 = pi->init_v3_1;
00161 ps->v1_2 = 0;
00162 ps->v2_2 = pi->init_v2_2;
00163 ps->v3_2 = pi->init_v3_2;
00164 ps->oldnpos = ps->npos;
00165 }
00166 for (x=0;x<len/2;x++) {
00167 ps->v1_1 = ps->v2_1;
00168 ps->v2_1 = ps->v3_1;
00169 ps->v3_1 = (pi->fac1 * ps->v2_1 >> 15) - ps->v1_1;
00170
00171 ps->v1_2 = ps->v2_2;
00172 ps->v2_2 = ps->v3_2;
00173 ps->v3_2 = (pi->fac2 * ps->v2_2 >> 15) - ps->v1_2;
00174 if (pi->modulate) {
00175 int p;
00176 p = ps->v3_2 - 32768;
00177 if (p < 0) p = -p;
00178 p = ((p * 9) / 10) + 1;
00179 ps->data[x] = (ps->v3_1 * p) >> 15;
00180 } else
00181 ps->data[x] = ps->v3_1 + ps->v3_2;
00182 }
00183
00184 ps->f.frametype = AST_FRAME_VOICE;
00185 ps->f.subclass = AST_FORMAT_SLINEAR;
00186 ps->f.datalen = len;
00187 ps->f.samples = samples;
00188 ps->f.offset = AST_FRIENDLY_OFFSET;
00189 ps->f.data = ps->data;
00190 ps->f.delivery.tv_sec = 0;
00191 ps->f.delivery.tv_usec = 0;
00192 ast_write(chan, &ps->f);
00193
00194 ps->pos += x;
00195 if (pi->duration && ps->pos >= pi->duration * 8) {
00196 ps->pos = 0;
00197 ps->npos++;
00198 if (ps->npos >= ps->nitems) {
00199 if (ps->reppos == -1)
00200 return -1;
00201 ps->npos = ps->reppos;
00202 }
00203 }
00204 return 0;
00205 }
00206
00207 static struct ast_generator playtones = {
00208 alloc: playtones_alloc,
00209 release: playtones_release,
00210 generate: playtones_generator,
00211 };
00212
00213 int ast_playtones_start(struct ast_channel *chan, int vol, const char *playlst, int interruptible)
00214 {
00215 char *s, *data = ast_strdupa(playlst);
00216 struct playtones_def d = { vol, -1, 0, 1, NULL};
00217 char *stringp=NULL;
00218 char *separator;
00219 if (!data)
00220 return -1;
00221 if (vol < 1)
00222 d.vol = 7219;
00223
00224 d.interruptible = interruptible;
00225
00226 stringp=data;
00227
00228
00229 if (strchr(stringp,'|'))
00230 separator = "|";
00231 else
00232 separator = ",";
00233 s = strsep(&stringp,separator);
00234 while (s && *s) {
00235 int freq1, freq2, time, modulate=0, midinote=0;
00236
00237 if (s[0]=='!')
00238 s++;
00239 else if (d.reppos == -1)
00240 d.reppos = d.nitems;
00241 if (sscanf(s, "%d+%d/%d", &freq1, &freq2, &time) == 3) {
00242
00243 } else if (sscanf(s, "%d+%d", &freq1, &freq2) == 2) {
00244
00245 time = 0;
00246 } else if (sscanf(s, "%d*%d/%d", &freq1, &freq2, &time) == 3) {
00247
00248 modulate = 1;
00249 } else if (sscanf(s, "%d*%d", &freq1, &freq2) == 2) {
00250
00251 time = 0;
00252 modulate = 1;
00253 } else if (sscanf(s, "%d/%d", &freq1, &time) == 2) {
00254
00255 freq2 = 0;
00256 } else if (sscanf(s, "%d", &freq1) == 1) {
00257
00258 freq2 = 0;
00259 time = 0;
00260 } else if (sscanf(s, "M%d+M%d/%d", &freq1, &freq2, &time) == 3) {
00261
00262 midinote = 1;
00263 } else if (sscanf(s, "M%d+M%d", &freq1, &freq2) == 2) {
00264
00265 time = 0;
00266 midinote = 1;
00267 } else if (sscanf(s, "M%d*M%d/%d", &freq1, &freq2, &time) == 3) {
00268
00269 modulate = 1;
00270 midinote = 1;
00271 } else if (sscanf(s, "M%d*M%d", &freq1, &freq2) == 2) {
00272
00273 time = 0;
00274 modulate = 1;
00275 midinote = 1;
00276 } else if (sscanf(s, "M%d/%d", &freq1, &time) == 2) {
00277
00278 freq2 = -1;
00279 midinote = 1;
00280 } else if (sscanf(s, "M%d", &freq1) == 1) {
00281
00282 freq2 = -1;
00283 time = 0;
00284 midinote = 1;
00285 } else {
00286 ast_log(LOG_WARNING,"%s: tone component '%s' of '%s' is no good\n",chan->name,s,playlst);
00287 return -1;
00288 }
00289
00290 if (midinote) {
00291
00292 if ((freq1 >= 0) && (freq1 <= 127))
00293 freq1 = midi_tohz[freq1];
00294 else
00295 freq1 = 0;
00296
00297 if ((freq2 >= 0) && (freq2 <= 127))
00298 freq2 = midi_tohz[freq2];
00299 else
00300 freq2 = 0;
00301 }
00302
00303 d.items = realloc(d.items,(d.nitems+1)*sizeof(struct playtones_item));
00304 if (d.items == NULL) {
00305 ast_log(LOG_WARNING, "Realloc failed!\n");
00306 return -1;
00307 }
00308 d.items[d.nitems].fac1 = 2.0 * cos(2.0 * M_PI * (freq1 / 8000.0)) * 32768.0;
00309 d.items[d.nitems].init_v2_1 = sin(-4.0 * M_PI * (freq1 / 8000.0)) * d.vol;
00310 d.items[d.nitems].init_v3_1 = sin(-2.0 * M_PI * (freq1 / 8000.0)) * d.vol;
00311
00312 d.items[d.nitems].fac2 = 2.0 * cos(2.0 * M_PI * (freq2 / 8000.0)) * 32768.0;
00313 d.items[d.nitems].init_v2_2 = sin(-4.0 * M_PI * (freq2 / 8000.0)) * d.vol;
00314 d.items[d.nitems].init_v3_2 = sin(-2.0 * M_PI * (freq2 / 8000.0)) * d.vol;
00315 d.items[d.nitems].duration = time;
00316 d.items[d.nitems].modulate = modulate;
00317 d.nitems++;
00318
00319 s = strsep(&stringp,separator);
00320 }
00321
00322 if (ast_activate_generator(chan, &playtones, &d)) {
00323 free(d.items);
00324 return -1;
00325 }
00326 return 0;
00327 }
00328
00329 void ast_playtones_stop(struct ast_channel *chan)
00330 {
00331 ast_deactivate_generator(chan);
00332 }
00333
00334
00335
00336 struct tone_zone *tone_zones;
00337 static struct tone_zone *current_tonezone;
00338
00339
00340
00341 AST_MUTEX_DEFINE_EXPORTED(tzlock);
00342
00343
00344 int ast_set_indication_country(const char *country)
00345 {
00346 if (country) {
00347 struct tone_zone *z = ast_get_indication_zone(country);
00348 if (z) {
00349 if (option_verbose > 2)
00350 ast_verbose(VERBOSE_PREFIX_3 "Setting default indication country to '%s'\n",country);
00351 current_tonezone = z;
00352 return 0;
00353 }
00354 }
00355 return 1;
00356 }
00357
00358
00359 struct tone_zone *ast_get_indication_zone(const char *country)
00360 {
00361 struct tone_zone *tz;
00362 int alias_loop = 0;
00363
00364
00365 if (country == NULL && current_tonezone)
00366 return current_tonezone;
00367 if (country == NULL && tone_zones)
00368 return tone_zones;
00369 if (country == NULL)
00370 return 0;
00371
00372 if (ast_mutex_lock(&tzlock)) {
00373 ast_log(LOG_WARNING, "Unable to lock tone_zones list\n");
00374 return 0;
00375 }
00376 do {
00377 for (tz=tone_zones; tz; tz=tz->next) {
00378 if (strcasecmp(country,tz->country)==0) {
00379
00380 if (tz->alias && tz->alias[0]) {
00381 country = tz->alias;
00382 break;
00383 }
00384 ast_mutex_unlock(&tzlock);
00385 return tz;
00386 }
00387 }
00388 } while (++alias_loop<20 && tz);
00389 ast_mutex_unlock(&tzlock);
00390 if (alias_loop==20)
00391 ast_log(LOG_NOTICE,"Alias loop for '%s' forcefull broken\n",country);
00392
00393 return 0;
00394 }
00395
00396
00397 struct tone_zone_sound *ast_get_indication_tone(const struct tone_zone *zone, const char *indication)
00398 {
00399 struct tone_zone_sound *ts;
00400
00401
00402 if (zone == NULL && current_tonezone)
00403 zone = current_tonezone;
00404 if (zone == NULL && tone_zones)
00405 zone = tone_zones;
00406 if (zone == NULL)
00407 return 0;
00408
00409 if (ast_mutex_lock(&tzlock)) {
00410 ast_log(LOG_WARNING, "Unable to lock tone_zones list\n");
00411 return 0;
00412 }
00413 for (ts=zone->tones; ts; ts=ts->next) {
00414 if (strcasecmp(indication,ts->name)==0) {
00415
00416 ast_mutex_unlock(&tzlock);
00417 return ts;
00418 }
00419 }
00420
00421 ast_mutex_unlock(&tzlock);
00422 return 0;
00423 }
00424
00425
00426 static inline void free_zone(struct tone_zone* zone)
00427 {
00428 while (zone->tones) {
00429 struct tone_zone_sound *tmp = zone->tones->next;
00430 free((void*)zone->tones->name);
00431 free((void*)zone->tones->data);
00432 free(zone->tones);
00433 zone->tones = tmp;
00434 }
00435 if (zone->ringcadence)
00436 free((void*)zone->ringcadence);
00437 free(zone);
00438 }
00439
00440
00441
00442
00443 int ast_register_indication_country(struct tone_zone *zone)
00444 {
00445 struct tone_zone *tz,*pz;
00446
00447 if (ast_mutex_lock(&tzlock)) {
00448 ast_log(LOG_WARNING, "Unable to lock tone_zones list\n");
00449 return -1;
00450 }
00451 for (pz=NULL,tz=tone_zones; tz; pz=tz,tz=tz->next) {
00452 if (strcasecmp(zone->country,tz->country)==0) {
00453
00454 zone->next = tz->next;
00455 if (pz)
00456 pz->next = zone;
00457 else
00458 tone_zones = zone;
00459
00460 if (tz == current_tonezone)
00461 current_tonezone = zone;
00462
00463 free_zone(tz);
00464 ast_mutex_unlock(&tzlock);
00465 return 0;
00466 }
00467 }
00468
00469 zone->next = NULL;
00470 if (pz)
00471 pz->next = zone;
00472 else
00473 tone_zones = zone;
00474 ast_mutex_unlock(&tzlock);
00475
00476 if (option_verbose > 2)
00477 ast_verbose(VERBOSE_PREFIX_3 "Registered indication country '%s'\n",zone->country);
00478 return 0;
00479 }
00480
00481
00482
00483 int ast_unregister_indication_country(const char *country)
00484 {
00485 struct tone_zone *tz, *pz = NULL, *tmp;
00486 int res = -1;
00487
00488 if (ast_mutex_lock(&tzlock)) {
00489 ast_log(LOG_WARNING, "Unable to lock tone_zones list\n");
00490 return -1;
00491 }
00492 tz = tone_zones;
00493 while (tz) {
00494 if (country==NULL ||
00495 (strcasecmp(country, tz->country)==0 ||
00496 strcasecmp(country, tz->alias)==0)) {
00497
00498 tmp = tz->next;
00499 if (pz)
00500 pz->next = tmp;
00501 else
00502 tone_zones = tmp;
00503
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
00518 pz = tz;
00519 tz = tz->next;
00520 }
00521 }
00522 ast_mutex_unlock(&tzlock);
00523 return res;
00524 }
00525
00526
00527
00528 int ast_register_indication(struct tone_zone *zone, const char *indication, const char *tonelist)
00529 {
00530 struct tone_zone_sound *ts,*ps;
00531
00532
00533 if (zone->alias[0])
00534 return -1;
00535
00536 if (ast_mutex_lock(&tzlock)) {
00537 ast_log(LOG_WARNING, "Unable to lock tone_zones list\n");
00538 return -2;
00539 }
00540 for (ps=NULL,ts=zone->tones; ts; ps=ts,ts=ts->next) {
00541 if (strcasecmp(indication,ts->name)==0) {
00542
00543 free((void*)ts->name);
00544 free((void*)ts->data);
00545 break;
00546 }
00547 }
00548 if (!ts) {
00549
00550 ts = malloc(sizeof(struct tone_zone_sound));
00551 if (!ts) {
00552 ast_log(LOG_WARNING, "Out of memory\n");
00553 ast_mutex_unlock(&tzlock);
00554 return -2;
00555 }
00556 ts->next = NULL;
00557 }
00558 ts->name = strdup(indication);
00559 ts->data = strdup(tonelist);
00560 if (ts->name==NULL || ts->data==NULL) {
00561 ast_log(LOG_WARNING, "Out of memory\n");
00562 ast_mutex_unlock(&tzlock);
00563 return -2;
00564 }
00565 if (ps)
00566 ps->next = ts;
00567 else
00568 zone->tones = ts;
00569 ast_mutex_unlock(&tzlock);
00570 return 0;
00571 }
00572
00573
00574 int ast_unregister_indication(struct tone_zone *zone, const char *indication)
00575 {
00576 struct tone_zone_sound *ts,*ps = NULL, *tmp;
00577 int res = -1;
00578
00579
00580 if (zone->alias[0])
00581 return -1;
00582
00583 if (ast_mutex_lock(&tzlock)) {
00584 ast_log(LOG_WARNING, "Unable to lock tone_zones list\n");
00585 return -1;
00586 }
00587 ts = zone->tones;
00588 while (ts) {
00589 if (strcasecmp(indication,ts->name)==0) {
00590
00591 tmp = ts->next;
00592 if (ps)
00593 ps->next = tmp;
00594 else
00595 zone->tones = tmp;
00596 free((void*)ts->name);
00597 free((void*)ts->data);
00598 free(ts);
00599 ts = tmp;
00600 res = 0;
00601 }
00602 else {
00603
00604 ps = ts;
00605 ts = ts->next;
00606 }
00607 }
00608
00609 ast_mutex_unlock(&tzlock);
00610 return res;
00611 }