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 "asterisk.h"
00032
00033 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 211528 $")
00034
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <string.h>
00038 #include <math.h>
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;
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
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 }
00138
00139 static int playtones_generator(struct ast_channel *chan, void *data, int len, int samples)
00140 {
00141 struct playtones_state *ps = data;
00142 struct playtones_item *pi;
00143 int x;
00144
00145
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
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) {
00195 ps->pos = 0;
00196 ps->npos++;
00197 if (ps->npos >= ps->nitems) {
00198 if (ps->reppos == -1)
00199 return -1;
00200 ps->npos = ps->reppos;
00201 }
00202 }
00203 return 0;
00204 }
00205
00206 static struct ast_generator playtones = {
00207 alloc: playtones_alloc,
00208 release: playtones_release,
00209 generate: playtones_generator,
00210 };
00211
00212 int ast_playtones_start(struct ast_channel *chan, int vol, const char *playlst, int interruptible)
00213 {
00214 char *s, *data = ast_strdupa(playlst);
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;
00221
00222 d.interruptible = interruptible;
00223
00224 stringp=data;
00225
00226
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, "%30d+%30d/%30d", &freq1, &freq2, &time) == 3) {
00240
00241 } else if (sscanf(s, "%30d+%30d", &freq1, &freq2) == 2) {
00242
00243 time = 0;
00244 } else if (sscanf(s, "%30d*%30d/%30d", &freq1, &freq2, &time) == 3) {
00245
00246 modulate = 1;
00247 } else if (sscanf(s, "%30d*%30d", &freq1, &freq2) == 2) {
00248
00249 time = 0;
00250 modulate = 1;
00251 } else if (sscanf(s, "%30d/%30d", &freq1, &time) == 2) {
00252
00253 freq2 = 0;
00254 } else if (sscanf(s, "%30d", &freq1) == 1) {
00255
00256 freq2 = 0;
00257 time = 0;
00258 } else if (sscanf(s, "M%30d+M%30d/%30d", &freq1, &freq2, &time) == 3) {
00259
00260 midinote = 1;
00261 } else if (sscanf(s, "M%30d+M%30d", &freq1, &freq2) == 2) {
00262
00263 time = 0;
00264 midinote = 1;
00265 } else if (sscanf(s, "M%30d*M%30d/%30d", &freq1, &freq2, &time) == 3) {
00266
00267 modulate = 1;
00268 midinote = 1;
00269 } else if (sscanf(s, "M%30d*M%30d", &freq1, &freq2) == 2) {
00270
00271 time = 0;
00272 modulate = 1;
00273 midinote = 1;
00274 } else if (sscanf(s, "M%30d/%30d", &freq1, &time) == 2) {
00275
00276 freq2 = -1;
00277 midinote = 1;
00278 } else if (sscanf(s, "M%30d", &freq1) == 1) {
00279
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
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 }
00324
00325 void ast_playtones_stop(struct ast_channel *chan)
00326 {
00327 ast_deactivate_generator(chan);
00328 }
00329
00330
00331
00332 static struct tone_zone *tone_zones;
00333 static struct tone_zone *current_tonezone;
00334
00335
00336
00337 AST_MUTEX_DEFINE_STATIC(tzlock);
00338
00339 struct tone_zone *ast_walk_indications(const struct tone_zone *cur)
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 }
00354
00355
00356 int ast_set_indication_country(const char *country)
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;
00368 }
00369
00370
00371 struct tone_zone *ast_get_indication_zone(const char *country)
00372 {
00373 struct tone_zone *tz;
00374 int alias_loop = 0;
00375
00376 if (ast_strlen_zero(country)) {
00377
00378 return current_tonezone ? current_tonezone : tone_zones;
00379 }
00380
00381 ast_mutex_lock(&tzlock);
00382 do {
00383 for (tz=tone_zones; tz; tz=tz->next) {
00384 if (strcasecmp(country,tz->country)==0) {
00385
00386 if (tz->alias && tz->alias[0]) {
00387 country = tz->alias;
00388 break;
00389 }
00390 ast_mutex_unlock(&tzlock);
00391 return tz;
00392 }
00393 }
00394 } while (++alias_loop<20 && tz);
00395 ast_mutex_unlock(&tzlock);
00396 if (alias_loop==20)
00397 ast_log(LOG_NOTICE,"Alias loop for '%s' forcefull broken\n",country);
00398
00399 return 0;
00400 }
00401
00402
00403 struct tone_zone_sound *ast_get_indication_tone(const struct tone_zone *zone, const char *indication)
00404 {
00405 struct tone_zone_sound *ts;
00406
00407
00408 if (zone == NULL && current_tonezone)
00409 zone = current_tonezone;
00410 if (zone == NULL && tone_zones)
00411 zone = tone_zones;
00412 if (zone == NULL)
00413 return 0;
00414
00415 ast_mutex_lock(&tzlock);
00416 for (ts=zone->tones; ts; ts=ts->next) {
00417 if (strcasecmp(indication,ts->name)==0) {
00418
00419 ast_mutex_unlock(&tzlock);
00420 return ts;
00421 }
00422 }
00423
00424 ast_mutex_unlock(&tzlock);
00425 return 0;
00426 }
00427
00428
00429 static inline void free_zone(struct tone_zone* zone)
00430 {
00431 while (zone->tones) {
00432 struct tone_zone_sound *tmp = zone->tones->next;
00433 free((void*)zone->tones->name);
00434 free((void*)zone->tones->data);
00435 free(zone->tones);
00436 zone->tones = tmp;
00437 }
00438 if (zone->ringcadence)
00439 free(zone->ringcadence);
00440 free(zone);
00441 }
00442
00443
00444
00445
00446 int ast_register_indication_country(struct tone_zone *zone)
00447 {
00448 struct tone_zone *tz,*pz;
00449
00450 ast_mutex_lock(&tzlock);
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 ast_mutex_lock(&tzlock);
00489 tz = tone_zones;
00490 while (tz) {
00491 if (country==NULL ||
00492 (strcasecmp(country, tz->country)==0 ||
00493 strcasecmp(country, tz->alias)==0)) {
00494
00495 tmp = tz->next;
00496 if (pz)
00497 pz->next = tmp;
00498 else
00499 tone_zones = tmp;
00500
00501 if (tz == current_tonezone) {
00502 ast_log(LOG_NOTICE,"Removed default indication country '%s'\n",tz->country);
00503 current_tonezone = NULL;
00504 }
00505 if (option_verbose > 2)
00506 ast_verbose(VERBOSE_PREFIX_3 "Unregistered indication country '%s'\n",tz->country);
00507 free_zone(tz);
00508 if (tone_zones == tz)
00509 tone_zones = tmp;
00510 tz = tmp;
00511 res = 0;
00512 }
00513 else {
00514
00515 pz = tz;
00516 tz = tz->next;
00517 }
00518 }
00519 ast_mutex_unlock(&tzlock);
00520 return res;
00521 }
00522
00523
00524
00525 int ast_register_indication(struct tone_zone *zone, const char *indication, const char *tonelist)
00526 {
00527 struct tone_zone_sound *ts,*ps;
00528
00529
00530 if (zone->alias[0])
00531 return -1;
00532
00533 ast_mutex_lock(&tzlock);
00534 for (ps=NULL,ts=zone->tones; ts; ps=ts,ts=ts->next) {
00535 if (strcasecmp(indication,ts->name)==0) {
00536
00537 free((void*)ts->name);
00538 free((void*)ts->data);
00539 break;
00540 }
00541 }
00542 if (!ts) {
00543
00544 if (!(ts = ast_malloc(sizeof(*ts)))) {
00545 ast_mutex_unlock(&tzlock);
00546 return -2;
00547 }
00548 ts->next = NULL;
00549 }
00550 if (!(ts->name = ast_strdup(indication)) || !(ts->data = ast_strdup(tonelist))) {
00551 ast_mutex_unlock(&tzlock);
00552 return -2;
00553 }
00554 if (ps)
00555 ps->next = ts;
00556 else
00557 zone->tones = ts;
00558 ast_mutex_unlock(&tzlock);
00559 return 0;
00560 }
00561
00562
00563 int ast_unregister_indication(struct tone_zone *zone, const char *indication)
00564 {
00565 struct tone_zone_sound *ts,*ps = NULL, *tmp;
00566 int res = -1;
00567
00568
00569 if (zone->alias[0])
00570 return -1;
00571
00572 ast_mutex_lock(&tzlock);
00573 ts = zone->tones;
00574 while (ts) {
00575 if (strcasecmp(indication,ts->name)==0) {
00576
00577 tmp = ts->next;
00578 if (ps)
00579 ps->next = tmp;
00580 else
00581 zone->tones = tmp;
00582 free((void*)ts->name);
00583 free((void*)ts->data);
00584 free(ts);
00585 ts = tmp;
00586 res = 0;
00587 }
00588 else {
00589
00590 ps = ts;
00591 ts = ts->next;
00592 }
00593 }
00594
00595 ast_mutex_unlock(&tzlock);
00596 return res;
00597 }