[svn-commits] russell: branch russell/indications r174365 - in /team/russell/indications: a...
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Mon Feb 9 17:56:13 CST 2009
Author: russell
Date: Mon Feb 9 17:56:13 2009
New Revision: 174365
URL: http://svn.digium.com/svn-view/asterisk?view=rev&rev=174365
Log:
Commit progress on re-work of indications API - abotu 85% done
I'll type up more of a description when I'm more awake, but it includes cool
things like not crashing if you do a reload with changes in the configuration
for indications currently in use.
Removed:
team/russell/indications/res/res_indications.c
Modified:
team/russell/indications/apps/app_disa.c
team/russell/indications/apps/app_read.c
team/russell/indications/apps/app_readexten.c
team/russell/indications/channels/chan_skinny.c
team/russell/indications/channels/chan_unistim.c
team/russell/indications/configs/indications.conf.sample
team/russell/indications/funcs/func_channel.c
team/russell/indications/include/asterisk/_private.h
team/russell/indications/include/asterisk/channel.h
team/russell/indications/include/asterisk/indications.h
team/russell/indications/main/app.c
team/russell/indications/main/asterisk.c
team/russell/indications/main/channel.c
team/russell/indications/main/indications.c
team/russell/indications/main/loader.c
team/russell/indications/main/pbx.c
team/russell/indications/res/snmp/agent.c
Modified: team/russell/indications/apps/app_disa.c
URL: http://svn.digium.com/svn-view/asterisk/team/russell/indications/apps/app_disa.c?view=diff&rev=174365&r1=174364&r2=174365
==============================================================================
--- team/russell/indications/apps/app_disa.c (original)
+++ team/russell/indications/apps/app_disa.c Mon Feb 9 17:56:13 2009
@@ -124,15 +124,19 @@
static void play_dialtone(struct ast_channel *chan, char *mailbox)
{
- const struct tone_zone_sound *ts = NULL;
- if(ast_app_has_voicemail(mailbox, NULL))
+ const struct ast_tone_zone_sound *ts = NULL;
+
+ if (ast_app_has_voicemail(mailbox, NULL)) {
ts = ast_get_indication_tone(chan->zone, "dialrecall");
- else
+ } else {
ts = ast_get_indication_tone(chan->zone, "dial");
- if (ts)
+ }
+
+ if (ts) {
ast_playtones_start(chan, 0, ts->data, 0);
- else
+ } else {
ast_tonepair_start(chan, 350, 440, 0, 0);
+ }
}
static int disa_exec(struct ast_channel *chan, void *data)
Modified: team/russell/indications/apps/app_read.c
URL: http://svn.digium.com/svn-view/asterisk/team/russell/indications/apps/app_read.c?view=diff&rev=174365&r1=174364&r2=174365
==============================================================================
--- team/russell/indications/apps/app_read.c (original)
+++ team/russell/indications/apps/app_read.c Mon Feb 9 17:56:13 2009
@@ -132,7 +132,7 @@
int tries = 1, to = 0, x = 0;
double tosec;
char *argcopy = NULL;
- struct tone_zone_sound *ts = NULL;
+ struct ast_tone_zone_sound *ts = NULL;
struct ast_flags flags = {0};
const char *status = "ERROR";
Modified: team/russell/indications/apps/app_readexten.c
URL: http://svn.digium.com/svn-view/asterisk/team/russell/indications/apps/app_readexten.c?view=diff&rev=174365&r1=174364&r2=174365
==============================================================================
--- team/russell/indications/apps/app_readexten.c (original)
+++ team/russell/indications/apps/app_readexten.c Mon Feb 9 17:56:13 2009
@@ -132,7 +132,7 @@
int maxdigits = sizeof(exten) - 1;
int timeout = 0, digit_timeout = 0, x = 0;
char *argcopy = NULL, *status = "";
- struct tone_zone_sound *ts = NULL;
+ struct ast_tone_zone_sound *ts = NULL;
struct ast_flags flags = {0};
AST_DECLARE_APP_ARGS(arglist,
@@ -179,8 +179,9 @@
if (digit_timeout <= 0)
digit_timeout = chan->pbx ? chan->pbx->dtimeoutms : 5000;
- if (ast_test_flag(&flags, OPT_INDICATION) && !ast_strlen_zero(arglist.filename))
+ if (ast_test_flag(&flags, OPT_INDICATION) && !ast_strlen_zero(arglist.filename)) {
ts = ast_get_indication_tone(chan->zone, arglist.filename);
+ }
do {
if (chan->_state != AST_STATE_UP) {
Modified: team/russell/indications/channels/chan_skinny.c
URL: http://svn.digium.com/svn-view/asterisk/team/russell/indications/channels/chan_skinny.c?view=diff&rev=174365&r1=174364&r2=174365
==============================================================================
--- team/russell/indications/channels/chan_skinny.c (original)
+++ team/russell/indications/channels/chan_skinny.c Mon Feb 9 17:56:13 2009
@@ -3751,7 +3751,7 @@
{
struct skinny_subchannel *xferor; /* the sub doing the transferring */
struct skinny_subchannel *xferee; /* the sub being transferred */
- const struct tone_zone_sound *ts = NULL;
+ const struct ast_tone_zone_sound *ts = NULL;
if (ast_bridged_channel(sub->owner) || ast_bridged_channel(sub->related->owner)) {
if (sub->xferor) {
Modified: team/russell/indications/channels/chan_unistim.c
URL: http://svn.digium.com/svn-view/asterisk/team/russell/indications/channels/chan_unistim.c?view=diff&rev=174365&r1=174364&r2=174365
==============================================================================
--- team/russell/indications/channels/chan_unistim.c (original)
+++ team/russell/indications/channels/chan_unistim.c Mon Feb 9 17:56:13 2009
@@ -439,7 +439,7 @@
char datetimeformat; /*!< format used for displaying time/date */
char contrast; /*!< contrast */
char country[3]; /*!< country used for dial tone frequency */
- struct tone_zone *tz; /*!< Tone zone for res_indications (ring, busy, congestion) */
+ struct ast_tone_zone *tz; /*!< Tone zone for res_indications (ring, busy, congestion) */
char ringvolume; /*!< Ring volume */
char ringstyle; /*!< Ring melody */
int rtp_port; /*!< RTP port used by the phone */
@@ -4057,17 +4057,16 @@
return "UNKNOWN";
}
-static void in_band_indication(struct ast_channel *ast, const struct tone_zone *tz,
+static void in_band_indication(struct ast_channel *ast, const struct ast_tone_zone *tz,
const char *indication)
{
- const struct tone_zone_sound *ts = NULL;
-
- ts = ast_get_indication_tone(tz, indication);
-
- if (ts && ts->data[0])
+ const struct ast_tone_zone_sound *ts = NULL;
+
+ if ((ts = ast_get_indication_tone(tz, indication))) {
ast_playtones_start(ast, 0, ts->data, 1);
- else
+ } else {
ast_log(LOG_WARNING, "Unable to get indication tone for %s\n", indication);
+ }
}
static int unistim_indicate(struct ast_channel *ast, int ind, const void *data,
Modified: team/russell/indications/configs/indications.conf.sample
URL: http://svn.digium.com/svn-view/asterisk/team/russell/indications/configs/indications.conf.sample?view=diff&rev=174365&r1=174364&r2=174365
==============================================================================
--- team/russell/indications/configs/indications.conf.sample (original)
+++ team/russell/indications/configs/indications.conf.sample Mon Feb 9 17:56:13 2009
@@ -17,9 +17,6 @@
; [example]
; description = string
; The full name of your country, in English.
-; alias = iso[,iso]*
-; List of other countries 2-letter iso codes, which have the same
-; tone indications.
; ringcadence = num[,num]*
; List of durations the physical bell rings.
; dial = tonelist
Modified: team/russell/indications/funcs/func_channel.c
URL: http://svn.digium.com/svn-view/asterisk/team/russell/indications/funcs/func_channel.c?view=diff&rev=174365&r1=174364&r2=174365
==============================================================================
--- team/russell/indications/funcs/func_channel.c (original)
+++ team/russell/indications/funcs/func_channel.c Mon Feb 9 17:56:13 2009
@@ -296,12 +296,19 @@
}
#endif
else if (!strcasecmp(data, "tonezone")) {
- struct tone_zone *new_zone;
+ struct ast_tone_zone *new_zone;
if (!(new_zone = ast_get_indication_zone(value))) {
ast_log(LOG_ERROR, "Unknown country code '%s' for tonezone. Check indications.conf for available country codes.\n", value);
ret = -1;
- } else
- chan->zone = new_zone;
+ } else {
+ ast_channel_lock(chan);
+ if (chan->zone) {
+ chan->zone = ast_tone_zone_unref(chan->zone);
+ }
+ chan->zone = ast_tone_zone_ref(new_zone);
+ ast_channel_unlock(chan);
+ new_zone = ast_tone_zone_unref(new_zone);
+ }
} else if (!strcasecmp(data, "callgroup"))
chan->callgroup = ast_get_group(value);
else if (!strcasecmp(data, "txgain")) {
Modified: team/russell/indications/include/asterisk/_private.h
URL: http://svn.digium.com/svn-view/asterisk/team/russell/indications/include/asterisk/_private.h?view=diff&rev=174365&r1=174364&r2=174365
==============================================================================
--- team/russell/indications/include/asterisk/_private.h (original)
+++ team/russell/indications/include/asterisk/_private.h Mon Feb 9 17:56:13 2009
@@ -39,6 +39,8 @@
int ast_http_reload(void); /*!< Provided by http.c */
int ast_tps_init(void); /*!< Provided by taskprocessor.c */
int ast_timing_init(void); /*!< Provided by timing.c */
+int ast_indications_init(void); /*!< Provided by indications.c */
+int ast_indications_reload(void);/*!< Provided by indications.c */
/*!
* \brief Reload asterisk modules.
Modified: team/russell/indications/include/asterisk/channel.h
URL: http://svn.digium.com/svn-view/asterisk/team/russell/indications/include/asterisk/channel.h?view=diff&rev=174365&r1=174364&r2=174365
==============================================================================
--- team/russell/indications/include/asterisk/channel.h (original)
+++ team/russell/indications/include/asterisk/channel.h Mon Feb 9 17:56:13 2009
@@ -424,7 +424,7 @@
struct ast_trans_pvt *readtrans; /*!< Read translation path */
struct ast_audiohook_list *audiohooks;
struct ast_cdr *cdr; /*!< Call Detail Record */
- struct tone_zone *zone; /*!< Tone zone as set in indications.conf or
+ struct ast_tone_zone *zone; /*!< Tone zone as set in indications.conf or
in the CHANNEL dialplan function */
struct ast_channel_monitor *monitor; /*!< Channel monitoring */
#ifdef HAVE_EPOLL
Modified: team/russell/indications/include/asterisk/indications.h
URL: http://svn.digium.com/svn-view/asterisk/team/russell/indications/include/asterisk/indications.h?view=diff&rev=174365&r1=174364&r2=174365
==============================================================================
--- team/russell/indications/include/asterisk/indications.h (original)
+++ team/russell/indications/include/asterisk/indications.h Mon Feb 9 17:56:13 2009
@@ -1,91 +1,78 @@
/*
* Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2002, Pauline Middelink
+ * Copyright (C) 2009, Digium, Inc.
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
*/
-/*! \file
- * \brief BSD Telephony Of Mexico "Tormenta" Tone Zone Support 2/22/01
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+/*!
+ * \file
+ * \brief Tone Indication Support
*
- * Primary Author: Pauline Middelink <middelink at polyware.nl>
- *
+ * \author Pauline Middelink <middelink at polyware.nl>
+ * \author Russell Bryant <russell at digium.com>
*/
#ifndef _ASTERISK_INDICATIONS_H
#define _ASTERISK_INDICATIONS_H
-#include "asterisk/lock.h"
+#include "asterisk/astobj2.h"
-/*! \brief Description is a series of tones of the format:
- [!]freq1[+freq2][/duration] separated by commas. There
- are no spaces. The sequence is repeated back to the
- first tone description not preceeded by !. Duration is
- specified in milliseconds */
-struct tone_zone_sound {
- const char *name; /*!< Identifing name */
- const char *data; /*!< Actual zone description */
- AST_LIST_ENTRY(tone_zone_sound) list;
+/*!
+ * \brief Description of a tone
+ *
+ * Description is a series of tones of the format:
+ * [!]freq1[+freq2][/duration] separated by commas. There
+ * are no spaces. The sequence is repeated back to the
+ * first tone description not preceeded by !. Duration is
+ * specified in milliseconds
+ */
+struct ast_tone_zone_sound {
+ const char *name; /*!< Identifying name */
+ const char *data; /*!< Actual zone description */
+ AST_LIST_ENTRY(ast_tone_zone_sound) entry;
};
-struct tone_zone {
- AST_RWLIST_ENTRY(tone_zone) list;
- char country[5]; /*!< Country code */
- char alias[5]; /*!< is this an alias? */
- char description[40]; /*!< Description */
- int nrringcadence; /*!< # registered ringcadence elements */
- int *ringcadence; /*!< Ring cadence */
- AST_LIST_HEAD_NOLOCK(, tone_zone_sound) tones; /*!< The known tones for this zone */
+struct ast_tone_zone {
+ char country[5]; /*!< Country code */
+ char description[40]; /*!< Description */
+ int nrringcadence; /*!< # registered ringcadence elements */
+ int *ringcadence; /*!< Ring cadence */
+ AST_LIST_HEAD_NOLOCK(, ast_tone_zone_sound) tones; /*!< The known tones for this zone */
};
-/*! \brief set the default tone country */
-int ast_set_indication_country(const char *country);
+/*!
+ * \brief locate ast_tone_zone
+ *
+ * \param county country to find, if== NULL, get the default country
+ */
+struct ast_tone_zone *ast_get_indication_zone(const char *country);
-/*! \brief locate tone_zone, given the country. if country == NULL, use the default country */
-struct tone_zone *ast_get_indication_zone(const char *country);
-/*! \brief locate a tone_zone_sound, given the tone_zone. if tone_zone == NULL, use the default tone_zone */
-struct tone_zone_sound *ast_get_indication_tone(const struct tone_zone *zone, const char *indication);
-/*! \brief deallocate the passed tone zone */
-void ast_destroy_indication_zone(struct tone_zone *zone);
-
-/*! \brief add a new country, if country exists, it will be replaced. */
-int ast_register_indication_country(struct tone_zone *country);
-/*! \brief remove an existing country and all its indications, country must exist */
-int ast_unregister_indication_country(const char *country);
-/*! \brief add a new indication to a tone_zone. tone_zone must exist. if the indication already
- * exists, it will be replaced. */
-int ast_register_indication(struct tone_zone *zone, const char *indication, const char *tonelist);
-/*! \brief remove an existing tone_zone's indication. tone_zone must exist */
-int ast_unregister_indication(struct tone_zone *zone, const char *indication);
+/*! \brief locate a ast_tone_zone_sound, given the ast_tone_zone. if ast_tone_zone == NULL, use the default ast_tone_zone */
+struct ast_tone_zone_sound *ast_get_indication_tone(const struct ast_tone_zone *zone, const char *indication);
/*! \brief Start a tone-list going */
int ast_playtones_start(struct ast_channel *chan, int vol, const char* tonelist, int interruptible);
+
/*! \brief Stop the tones from playing */
void ast_playtones_stop(struct ast_channel *chan);
-/*! \brief support for walking through a list of indications */
-struct tone_zone *ast_walk_indications(const struct tone_zone *cur);
+struct ao2_iterator ast_tone_zone_iterator_init(void);
-#if 0
-extern struct tone_zone *tone_zones;
-extern ast_mutex_t tzlock;
-#endif
+#define ast_tone_zone_lock(tz) ao2_lock(tz)
+#define ast_tone_zone_unlock(tz) ao2_unlock(tz)
+#define ast_tone_zone_trylock(tz) ao2_trylock(tz)
+#define ast_tone_zone_unref(tz) ({ ao2_ref(tz, -1); (NULL); })
+#define ast_tone_zone_ref(tz) ({ ao2_ref(tz, +1); (tz); })
#endif /* _ASTERISK_INDICATIONS_H */
Modified: team/russell/indications/main/app.c
URL: http://svn.digium.com/svn-view/asterisk/team/russell/indications/main/app.c?view=diff&rev=174365&r1=174364&r2=174365
==============================================================================
--- team/russell/indications/main/app.c (original)
+++ team/russell/indications/main/app.c Mon Feb 9 17:56:13 2009
@@ -75,21 +75,23 @@
*/
int ast_app_dtget(struct ast_channel *chan, const char *context, char *collect, size_t size, int maxlen, int timeout)
{
- struct tone_zone_sound *ts;
+ struct ast_tone_zone_sound *ts;
int res = 0, x = 0;
if (maxlen > size)
maxlen = size;
- if (!timeout && chan->pbx)
+ if (!timeout && chan->pbx) {
timeout = chan->pbx->dtimeoutms / 1000.0;
- else if (!timeout)
+ } else if (!timeout) {
timeout = 5;
-
- if ((ts = ast_get_indication_tone(chan->zone, "dial")) && ts->data[0])
+ }
+
+ if ((ts = ast_get_indication_tone(chan->zone, "dial")) && !ast_strlen_zero(ts->data)) {
res = ast_playtones_start(chan, 0, ts->data, 0);
- else
+ } else {
ast_log(LOG_NOTICE, "Huh....? no dial for indications?\n");
+ }
for (x = strlen(collect); x < maxlen; ) {
res = ast_waitfordigit(chan, timeout);
Modified: team/russell/indications/main/asterisk.c
URL: http://svn.digium.com/svn-view/asterisk/team/russell/indications/main/asterisk.c?view=diff&rev=174365&r1=174364&r2=174365
==============================================================================
--- team/russell/indications/main/asterisk.c (original)
+++ team/russell/indications/main/asterisk.c Mon Feb 9 17:56:13 2009
@@ -3583,6 +3583,11 @@
exit(1);
}
+ if (ast_indications_init()) {
+ printf("%s", term_quit());
+ exit(1);
+ }
+
if (load_modules(0)) {
printf("%s", term_quit());
exit(1);
Modified: team/russell/indications/main/channel.c
URL: http://svn.digium.com/svn-view/asterisk/team/russell/indications/main/channel.c?view=diff&rev=174365&r1=174364&r2=174365
==============================================================================
--- team/russell/indications/main/channel.c (original)
+++ team/russell/indications/main/channel.c Mon Feb 9 17:56:13 2009
@@ -1403,7 +1403,11 @@
ast_cdr_discard(chan->cdr);
chan->cdr = NULL;
}
-
+
+ if (chan->zone) {
+ chan->zone = ast_tone_zone_unref(chan->zone);
+ }
+
ast_mutex_destroy(&chan->lock_dont_use);
ast_string_field_free_memory(chan);
@@ -2899,7 +2903,7 @@
/* By using an enum, we'll get compiler warnings for values not handled
* in switch statements. */
enum ast_control_frame_type condition = _condition;
- const struct tone_zone_sound *ts = NULL;
+ const struct ast_tone_zone_sound *ts = NULL;
int res = -1;
ast_channel_lock(chan);
Modified: team/russell/indications/main/indications.c
URL: http://svn.digium.com/svn-view/asterisk/team/russell/indications/main/indications.c?view=diff&rev=174365&r1=174364&r2=174365
==============================================================================
--- team/russell/indications/main/indications.c (original)
+++ team/russell/indications/main/indications.c Mon Feb 9 17:56:13 2009
@@ -2,7 +2,7 @@
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2002, Pauline Middelink
- *
+ * Copyright (C) 2009, Digium, Inc.
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
@@ -15,17 +15,23 @@
* at the top of the source tree.
*/
-/*! \file
+/*!
+ * \file
+ * \brief Indication Tone Handling
*
- * \brief Tone Management
- *
* \author Pauline Middelink <middelink at polyware.nl>
- *
- * 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.
- *
+ * \author Russell Bryant <russell at digium.com>
+ */
+
+/*
+ * XXX TODO
+ * - API documentation
+ * - finish re-write of config parsing
+ * - re-use an object for a country if it already exists when loading config
+ * - fix users of the API to account for ref count (only chan_unistim left)
+ * - Integrate work to pull out tone parsing into an API
+ * - change the code such that tone definitions are only parsed once
+ * instead of every time they are used.
*/
#include "asterisk.h"
@@ -40,22 +46,74 @@
#include "asterisk/frame.h"
#include "asterisk/channel.h"
#include "asterisk/utils.h"
-
-static int midi_tohz[128] = {
- 8,8,9,9,10,10,11,12,12,13,14,
- 15,16,17,18,19,20,21,23,24,25,
- 27,29,30,32,34,36,38,41,43,46,
- 48,51,55,58,61,65,69,73,77,82,
- 87,92,97,103,110,116,123,130,138,146,
- 155,164,174,184,195,207,220,233,246,261,
- 277,293,311,329,349,369,391,415,440,466,
- 493,523,554,587,622,659,698,739,783,830,
- 880,932,987,1046,1108,1174,1244,1318,1396,1479,
- 1567,1661,1760,1864,1975,2093,2217,2349,2489,2637,
- 2793,2959,3135,3322,3520,3729,3951,4186,4434,4698,
- 4978,5274,5587,5919,6271,6644,7040,7458,7902,8372,
- 8869,9397,9956,10548,11175,11839,12543
- };
+#include "asterisk/cli.h"
+#include "asterisk/module.h"
+#include "asterisk/astobj2.h"
+
+#include "asterisk/_private.h" /* _init(), _reload() */
+
+/*** DOCUMENTATION
+ <application name="PlayTones" language="en_US">
+ <synopsis>
+ Play a tone list.
+ </synopsis>
+ <syntax>
+ <parameter name="arg" required="true">
+ <para>Arg is either the tone name defined in the <filename>indications.conf</filename>
+ configuration file, or a directly specified list of frequencies and durations.</para>
+ </parameter>
+ </syntax>
+ <description>
+ <para>Plays a tone list. Execution will continue with the next step immediately,
+ while the tones continue to play.</para>
+ <para>See the sample <filename>indications.conf</filename> for a description of the
+ specification of a tonelist.</para>
+ </description>
+ <see-also>
+ <ref type="application">StopPlayTones</ref>
+ </see-also>
+ </application>
+ <application name="StopPlayTones" language="en_US">
+ <synopsis>
+ Stop playing a tone list.
+ </synopsis>
+ <syntax />
+ <description>
+ <para>Stop playing a tone list, initiated by PlayTones().</para>
+ </description>
+ <see-also>
+ <ref type="application">PlayTones</ref>
+ </see-also>
+ </application>
+ ***/
+
+/* Globals */
+static const char config[] = "indications.conf";
+
+static const int midi_tohz[128] = {
+ 8, 8, 9, 9, 10, 10, 11, 12, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 23, 24,
+ 25, 27, 29, 30, 32, 34, 36, 38, 41, 43,
+ 46, 48, 51, 55, 58, 61, 65, 69, 73, 77,
+ 82, 87, 92, 97, 103, 110, 116, 123, 130, 138,
+ 146, 155, 164, 174, 184, 195, 207, 220, 233, 246,
+ 261, 277, 293, 311, 329, 349, 369, 391, 415, 440,
+ 466, 493, 523, 554, 587, 622, 659, 698, 739, 783,
+ 830, 880, 932, 987, 1046, 1108, 1174, 1244, 1318, 1396,
+ 1479, 1567, 1661, 1760, 1864, 1975, 2093, 2217, 2349, 2489,
+ 2637, 2793, 2959, 3135, 3322, 3520, 3729, 3951, 4186, 4434,
+ 4698, 4978, 5274, 5587, 5919, 6271, 6644, 7040, 7458, 7902,
+ 8372, 8869, 9397, 9956, 10548, 11175, 11839, 12543
+};
+
+static struct ao2_container *ast_tone_zones;
+
+#define NUM_TONE_ZONE_BUCKETS 53
+
+/*!
+ * \note Access to this is protected by locking the ast_tone_zones container
+ */
+static struct ast_tone_zone *default_tone_zone;
struct playtones_item {
int fac1;
@@ -100,21 +158,26 @@
{
struct playtones_state *ps = params;
- if (chan)
+ if (chan) {
ast_set_write_format(chan, ps->origwfmt);
- if (ps->items)
+ }
+
+ if (ps->items) {
ast_free(ps->items);
+ ps->items = NULL;
+ }
ast_free(ps);
}
-static void * playtones_alloc(struct ast_channel *chan, void *params)
+static void *playtones_alloc(struct ast_channel *chan, void *params)
{
struct playtones_def *pd = params;
struct playtones_state *ps = NULL;
- if (!(ps = ast_calloc(1, sizeof(*ps))))
+ if (!(ps = ast_calloc(1, sizeof(*ps)))) {
return NULL;
+ }
ps->origwfmt = chan->writeformat;
@@ -131,10 +194,11 @@
}
/* Let interrupts interrupt :) */
- if (pd->interruptible)
+ if (pd->interruptible) {
ast_set_flag(chan, AST_FLAG_WRITE_INT);
- else
+ } else {
ast_clear_flag(chan, AST_FLAG_WRITE_INT);
+ }
return ps;
}
@@ -144,17 +208,20 @@
struct playtones_state *ps = data;
struct playtones_item *pi;
int x;
- /* we need to prepare a frame with 16 * timelen samples as we're
- * generating SLIN audio
- */
+
+ /* we need to prepare a frame with 16 * timelen samples as we're
+ * generating SLIN audio */
+
len = samples * 2;
if (len > sizeof(ps->data) / 2 - 1) {
ast_log(LOG_WARNING, "Can't generate that much data!\n");
return -1;
}
+
memset(&ps->f, 0, sizeof(ps->f));
pi = &ps->items[ps->npos];
+
if (ps->oldnpos != ps->npos) {
/* Load new parameters */
ps->v1_1 = 0;
@@ -165,80 +232,94 @@
ps->v3_2 = pi->init_v3_2;
ps->oldnpos = ps->npos;
}
+
for (x = 0; x < len/2; x++) {
ps->v1_1 = ps->v2_1;
ps->v2_1 = ps->v3_1;
ps->v3_1 = (pi->fac1 * ps->v2_1 >> 15) - ps->v1_1;
-
+
ps->v1_2 = ps->v2_2;
ps->v2_2 = ps->v3_2;
ps->v3_2 = (pi->fac2 * ps->v2_2 >> 15) - ps->v1_2;
if (pi->modulate) {
int p;
p = ps->v3_2 - 32768;
- if (p < 0) p = -p;
+ if (p < 0) {
+ p = -p;
+ }
p = ((p * 9) / 10) + 1;
ps->data[x] = (ps->v3_1 * p) >> 15;
- } else
- ps->data[x] = ps->v3_1 + ps->v3_2;
- }
-
+ } else {
+ ps->data[x] = ps->v3_1 + ps->v3_2;
+ }
+ }
+
ps->f.frametype = AST_FRAME_VOICE;
ps->f.subclass = AST_FORMAT_SLINEAR;
ps->f.datalen = len;
ps->f.samples = samples;
ps->f.offset = AST_FRIENDLY_OFFSET;
ps->f.data.ptr = ps->data;
- ps->f.delivery.tv_sec = 0;
- ps->f.delivery.tv_usec = 0;
- ast_write(chan, &ps->f);
+
+ if (ast_write(chan, &ps->f)) {
+ return -1;
+ }
ps->pos += x;
+
if (pi->duration && ps->pos >= pi->duration * 8) { /* item finished? */
ps->pos = 0; /* start new item */
ps->npos++;
if (ps->npos >= ps->nitems) { /* last item? */
- if (ps->reppos == -1) /* repeat set? */
+ if (ps->reppos == -1) { /* repeat set? */
return -1;
+ }
ps->npos = ps->reppos; /* redo from top */
}
}
+
return 0;
}
static struct ast_generator playtones = {
- alloc: playtones_alloc,
- release: playtones_release,
- generate: playtones_generator,
+ .alloc = playtones_alloc,
+ .release = playtones_release,
+ .generate = playtones_generator,
};
int ast_playtones_start(struct ast_channel *chan, int vol, const char *playlst, int interruptible)
{
- char *s, *data = ast_strdupa(playlst); /* cute */
- struct playtones_def d = { vol, -1, 0, 1, NULL};
+ char *s, *data = ast_strdupa(playlst);
+ struct playtones_def d = { vol, -1, 0, 1, NULL };
char *stringp;
char *separator;
-
- if (vol < 1)
+
+ if (vol < 1) {
d.vol = 7219; /* Default to -8db */
+ }
d.interruptible = interruptible;
-
- stringp=data;
- /* the stringp/data is not null here */
+
+ stringp = data;
+
/* check if the data is separated with '|' or with ',' by default */
- if (strchr(stringp,'|'))
+ if (strchr(stringp,'|')) {
separator = "|";
- else
+ } else {
separator = ",";
- s = strsep(&stringp,separator);
- while (s && *s) {
+ }
+
+ while ((s = strsep(&stringp, separator)) && !ast_strlen_zero(s)) {
int freq1, freq2, duration, modulate = 0, midinote = 0;
- if (s[0]=='!')
+ s = ast_strip(s);
+
+ if (s[0]=='!') {
s++;
- else if (d.reppos == -1)
+ } else if (d.reppos == -1) {
d.reppos = d.nitems;
+ }
+
if (sscanf(s, "%d+%d/%d", &freq1, &freq2, &duration) == 3) {
/* f1+f2/time format */
} else if (sscanf(s, "%d+%d", &freq1, &freq2) == 2) {
@@ -284,26 +365,34 @@
duration = 0;
midinote = 1;
} else {
- ast_log(LOG_WARNING,"%s: tone component '%s' of '%s' is no good\n",chan->name,s,playlst);
+ ast_log(LOG_WARNING,"%s: tone component '%s' of '%s' is no good\n", chan->name, s, playlst);
return -1;
}
if (midinote) {
/* midi notes must be between 0 and 127 */
- if ((freq1 >= 0) && (freq1 <= 127))
+
+ switch (freq1) {
+ case 0 ... 127:
freq1 = midi_tohz[freq1];
- else
+ break;
+ default:
freq1 = 0;
-
- if ((freq2 >= 0) && (freq2 <= 127))
+ }
+
+ switch (freq2) {
+ case 0 ... 127:
freq2 = midi_tohz[freq2];
- else
+ break;
+ default:
freq2 = 0;
+ }
}
if (!(d.items = ast_realloc(d.items, (d.nitems + 1) * sizeof(*d.items)))) {
return -1;
}
+
d.items[d.nitems].fac1 = 2.0 * cos(2.0 * M_PI * (freq1 / 8000.0)) * 32768.0;
d.items[d.nitems].init_v2_1 = sin(-4.0 * M_PI * (freq1 / 8000.0)) * d.vol;
d.items[d.nitems].init_v3_1 = sin(-2.0 * M_PI * (freq1 / 8000.0)) * d.vol;
@@ -314,14 +403,13 @@
d.items[d.nitems].duration = duration;
d.items[d.nitems].modulate = modulate;
d.nitems++;
-
- s = strsep(&stringp,separator);
}
if (ast_activate_generator(chan, &playtones, &d)) {
ast_free(d.items);
return -1;
}
+
return 0;
}
@@ -332,263 +420,644 @@
/*--------------------------------------------*/
-static AST_RWLIST_HEAD_STATIC(tone_zones, tone_zone);
-static struct tone_zone *current_tonezone;
-
-struct tone_zone *ast_walk_indications(const struct tone_zone *cur)
-{
- struct tone_zone *tz = NULL;
-
- AST_RWLIST_RDLOCK(&tone_zones);
- /* If cur is not NULL, then we have to iterate through - otherwise just return the first entry */
- if (cur) {
- AST_RWLIST_TRAVERSE(&tone_zones, tz, list) {
- if (tz == cur)
- break;
- }
- tz = AST_RWLIST_NEXT(tz, list);
- } else {
- tz = AST_RWLIST_FIRST(&tone_zones);
- }
- AST_RWLIST_UNLOCK(&tone_zones);
-
- return tz;
+struct ao2_iterator ast_tone_zone_iterator_init(void)
+{
+ return ao2_iterator_init(ast_tone_zones, 0);
}
/* Set global indication country */
-int ast_set_indication_country(const char *country)
-{
- struct tone_zone *zone = NULL;
+static int ast_set_indication_country(const char *country)
+{
+ struct ast_tone_zone *zone = NULL;
/* If no country is specified or we are unable to find the zone, then return not found */
- if (!country || !(zone = ast_get_indication_zone(country)))
+ if (ast_strlen_zero(country) || !(zone = ast_get_indication_zone(country))) {
return 1;
-
+ }
+
ast_verb(3, "Setting default indication country to '%s'\n", country);
- /* Protect the current tonezone using the tone_zones lock as well */
- AST_RWLIST_WRLOCK(&tone_zones);
- current_tonezone = zone;
- AST_RWLIST_UNLOCK(&tone_zones);
-
- /* Zone was found */
+ ao2_lock(ast_tone_zones);
+ if (default_tone_zone) {
+ default_tone_zone = ast_tone_zone_unref(default_tone_zone);
+ }
+ default_tone_zone = ast_tone_zone_ref(zone);
+ ao2_unlock(ast_tone_zones);
+
+ zone = ast_tone_zone_unref(zone);
+
return 0;
}
-/* locate tone_zone, given the country. if country == NULL, use the default country */
-struct tone_zone *ast_get_indication_zone(const char *country)
-{
- struct tone_zone *tz = NULL;
- int alias_loop = 0;
-
- AST_RWLIST_RDLOCK(&tone_zones);
+/* locate ast_tone_zone, given the country. if country == NULL, use the default country */
+struct ast_tone_zone *ast_get_indication_zone(const char *country)
+{
+ struct ast_tone_zone *tz = NULL;
+ struct ast_tone_zone zone_arg = {
+ .nrringcadence = 0,
+ };
if (ast_strlen_zero(country)) {
- tz = current_tonezone ? current_tonezone : AST_LIST_FIRST(&tone_zones);
- } else {
- do {
- AST_RWLIST_TRAVERSE(&tone_zones, tz, list) {
- if (!strcasecmp(tz->country, country))
- break;
- }
- if (!tz)
- break;
- /* If this is an alias then we have to search yet again otherwise we have found the zonezone */
- if (tz->alias && tz->alias[0])
- country = tz->alias;
- else
- break;
- } while ((++alias_loop < 20) && tz);
- }
-
- AST_RWLIST_UNLOCK(&tone_zones);
-
- /* If we reached the maximum loops to find the proper country via alias, print out a notice */
- if (alias_loop == 20)
- ast_log(LOG_NOTICE, "Alias loop for '%s' is bonkers\n", country);
-
- return tz;
-}
-
-/* locate a tone_zone_sound, given the tone_zone. if tone_zone == NULL, use the default tone_zone */
-struct tone_zone_sound *ast_get_indication_tone(const struct tone_zone *zone, const char *indication)
-{
- struct tone_zone_sound *ts = NULL;
-
- AST_RWLIST_RDLOCK(&tone_zones);
-
- /* If no zone is already specified we need to try to pick one */
+ ao2_lock(ast_tone_zones);
+ if (default_tone_zone) {
+ tz = ast_tone_zone_ref(default_tone_zone);
+ }
+ ao2_unlock(ast_tone_zones);
+
+ return tz;
+ }
+
+ ast_copy_string(zone_arg.country, country, sizeof(zone_arg.country));
+
+ return ao2_find(ast_tone_zones, &zone_arg, OBJ_POINTER);
+}
+
+/* locate a ast_tone_zone_sound, given the ast_tone_zone. if ast_tone_zone == NULL, use the default ast_tone_zone */
+struct ast_tone_zone_sound *ast_get_indication_tone(const struct ast_tone_zone *_zone, const char *indication)
+{
+ struct ast_tone_zone_sound *ts = NULL;
+ /* _zone is const to the users of the API */
+ struct ast_tone_zone *zone = (struct ast_tone_zone *) _zone;
+
+ /* If no zone is specified, use the default */
if (!zone) {
- if (current_tonezone) {
- zone = current_tonezone;
- } else if (!(zone = AST_LIST_FIRST(&tone_zones))) {
- /* No zone has been found ;( */
- AST_RWLIST_UNLOCK(&tone_zones);
+ ao2_lock(ast_tone_zones);
+ if (default_tone_zone) {
+ zone = ast_tone_zone_ref(default_tone_zone);
+ }
+ ao2_unlock(ast_tone_zones);
+
+ if (!zone) {
return NULL;
}
}
+ ast_tone_zone_lock(zone);
+
/* Look through list of tones in the zone searching for the right one */
- AST_LIST_TRAVERSE(&zone->tones, ts, list) {
- if (!strcasecmp(ts->name, indication))
+ AST_LIST_TRAVERSE(&zone->tones, ts, entry) {
+ /* XXX THE TONE ZONE SOUNDS NEED TO BE REF COUNTED TOO! */
+ if (!strcasecmp(ts->name, indication)) {
break;
- }
-
- AST_RWLIST_UNLOCK(&tone_zones);
+ }
+ }
+
+ ast_tone_zone_unlock(zone);
return ts;
}
-static inline void clear_zone_sound(struct tone_zone_sound *ts)
+static void ast_tone_zone_sound_destroy(struct ast_tone_zone_sound *ts)
{
/* Deconstify the 'const char *'s so the compiler doesn't complain. (but it's safe) */
- ast_free((char *) ts->name);
- ast_free((char *) ts->data);
+ if (ts->name) {
+ ast_free((char *) ts->name);
+ ts->name = NULL;
+ }
+
+ if (ts->data) {
+ ast_free((char *) ts->data);
+ ts->data = NULL;
+ }
+
+ ast_free(ts);
}
/*! \brief deallocate the passed tone zone */
-void ast_destroy_indication_zone(struct tone_zone *zone)
-{
- struct tone_zone_sound *current;
-
- while ((current = AST_LIST_REMOVE_HEAD(&zone->tones, list))) {
- clear_zone_sound(current);
- ast_free(current);
- }
-
- if (zone->ringcadence)
+static void ast_tone_zone_destructor(void *obj)
+{
+ struct ast_tone_zone *zone = obj;
+ struct ast_tone_zone_sound *current;
+
+ while ((current = AST_LIST_REMOVE_HEAD(&zone->tones, entry))) {
+ ast_tone_zone_sound_destroy(current);
+ }
+
+ if (zone->ringcadence) {
ast_free(zone->ringcadence);
-
- ast_free(zone);
+ zone->ringcadence = NULL;
+ }
}
/*--------------------------------------------*/
/* add a new country, if country exists, it will be replaced. */
-int ast_register_indication_country(struct tone_zone *zone)
-{
- struct tone_zone *tz = NULL;
-
- AST_RWLIST_WRLOCK(&tone_zones);
- AST_RWLIST_TRAVERSE_SAFE_BEGIN(&tone_zones, tz, list) {
- /* If this is not the same zone, then just continue to the next entry */
- if (strcasecmp(zone->country, tz->country))
- continue;
- /* If this zone we are going to remove is the current default then make the new zone the default */
- if (tz == current_tonezone)
- current_tonezone = zone;
- /* Remove from the linked list */
- AST_RWLIST_REMOVE_CURRENT(list);
- /* Finally free the zone itself */
- ast_destroy_indication_zone(tz);
- break;
- }
- AST_RWLIST_TRAVERSE_SAFE_END;
-
- /* Add zone to the list */
- AST_RWLIST_INSERT_TAIL(&tone_zones, zone, list);
-
- /* It's all over. */
- AST_RWLIST_UNLOCK(&tone_zones);
+static int ast_register_indication_country(struct ast_tone_zone *zone)
+{
+ ao2_lock(ast_tone_zones);
+ if (!default_tone_zone) {
+ default_tone_zone = ast_tone_zone_ref(zone);
+ }
+ ao2_unlock(ast_tone_zones);
+
+ ao2_link(ast_tone_zones, zone);
ast_verb(3, "Registered indication country '%s'\n", zone->country);
return 0;
}
-/* remove an existing country and all its indications, country must exist.
- * Also, all countries which are an alias for the specified country are removed. */
-int ast_unregister_indication_country(const char *country)
-{
- struct tone_zone *tz = NULL;
+/* remove an existing country and all its indications, country must exist. */
+static int ast_unregister_indication_country(const char *country)
+{
+ struct ast_tone_zone *tz = NULL;
+ struct ast_tone_zone zone_arg = {
+ .nrringcadence = 0,
+ };
+
+ ast_copy_string(zone_arg.country, country, sizeof(zone_arg.country));
+
+ if (!(tz = ao2_find(ast_tone_zones, &zone_arg, OBJ_POINTER))) {
+ return -1;
+ }
+
+ ao2_lock(ast_tone_zones);
+ if (default_tone_zone == tz) {
+ ast_tone_zone_unref(default_tone_zone);
+ /* Get a new default, punt to the first one we find */
+ default_tone_zone = ao2_callback(ast_tone_zones, 0, NULL, NULL);
+ }
+ ao2_unlock(ast_tone_zones);
+
+ ao2_unlink(ast_tone_zones, tz);
+
+ tz = ast_tone_zone_unref(tz);
+
+ return 0;
+}
+
+/* add a new indication to a ast_tone_zone. ast_tone_zone must exist. if the indication already
+ * exists, it will be replaced. */
+static int ast_register_indication(struct ast_tone_zone *zone, const char *indication, const char *tonelist)
+{
+ struct ast_tone_zone_sound *ts;
+
+ ast_tone_zone_lock(zone);
+
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&zone->tones, ts, entry) {
+ if (!strcasecmp(indication, ts->name)) {
+ AST_LIST_REMOVE_CURRENT(entry);
+ ast_tone_zone_sound_destroy(ts);
+ break;
+ }
+ }
+ AST_LIST_TRAVERSE_SAFE_END
+
+ if (!(ts = ast_calloc(1, sizeof(*ts)))) {
+ ast_tone_zone_unlock(zone);
+ return -2;
+ }
+
+ if (!(ts->name = ast_strdup(indication)) || !(ts->data = ast_strdup(tonelist))) {
+ ast_tone_zone_unlock(zone);
+ ast_tone_zone_sound_destroy(ts);
+ return -2;
+ }
+
+ AST_LIST_INSERT_TAIL(&zone->tones, ts, entry);
+
+ ast_tone_zone_unlock(zone);
+
+ return 0;
+}
+
+/* remove an existing country's indication. Both country and indication must exist */
+static int ast_unregister_indication(struct ast_tone_zone *zone, const char *indication)
+{
+ struct ast_tone_zone_sound *ts;
int res = -1;
- AST_RWLIST_WRLOCK(&tone_zones);
- AST_RWLIST_TRAVERSE_SAFE_BEGIN(&tone_zones, tz, list) {
- if (country && (strcasecmp(country, tz->country) && strcasecmp(country, tz->alias)))
- continue;
- /* If this tonezone is the current default then unset it */
- if (tz == current_tonezone) {
- ast_log(LOG_NOTICE,"Removed default indication country '%s'\n", tz->country);
- current_tonezone = NULL;
- }
- /* Remove from the list */
- AST_RWLIST_REMOVE_CURRENT(list);
- ast_verb(3, "Unregistered indication country '%s'\n", tz->country);
- ast_destroy_indication_zone(tz);
- res = 0;
- }
- AST_RWLIST_TRAVERSE_SAFE_END;
- AST_RWLIST_UNLOCK(&tone_zones);
-
- return res;
-}
-
-/* add a new indication to a tone_zone. tone_zone must exist. if the indication already
- * exists, it will be replaced. */
[... 641 lines stripped ...]
More information about the svn-commits
mailing list