Newer
Older
zone = ast_tone_zone_unref(zone);
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
* Mark the zone and its tones before parsing configuration. We will use this
* to know what to remove after configuration is parsed.
*/
static int tone_zone_mark(void *obj, void *arg, int flags)
{
struct ast_tone_zone *zone = obj;
struct ast_tone_zone_sound *s;
ast_tone_zone_lock(zone);
zone->killme = 1;
AST_LIST_TRAVERSE(&zone->tones, s, entry) {
s->killme = 1;
}
ast_tone_zone_unlock(zone);
return 0;
}
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
* Prune tones no longer in the configuration, and have the tone zone unlinked
* if it is no longer in the configuration at all.
*/
static int prune_tone_zone(void *obj, void *arg, int flags)
{
struct ast_tone_zone *zone = obj;
struct ast_tone_zone_sound *s;
ast_tone_zone_lock(zone);
AST_LIST_TRAVERSE_SAFE_BEGIN(&zone->tones, s, entry) {
if (s->killme) {
AST_LIST_REMOVE_CURRENT(entry);
s = ast_tone_zone_sound_unref(s);
}
}
AST_LIST_TRAVERSE_SAFE_END;
ast_tone_zone_unlock(zone);
return zone->killme ? CMP_MATCH : 0;
}
/*! \brief load indications module */
static int load_indications(int reload)
struct ast_config *cfg;
const char *cxt = NULL;
const char *country = NULL;
struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
cfg = ast_config_load2(config, "indications", config_flags);
if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
ast_log(LOG_WARNING, "Can't find indications config file %s.\n", config);
return 0;
} else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
return 0;
}
/* Lock the container to prevent multiple simultaneous reloads */
ao2_lock(ast_tone_zones);
ao2_callback(ast_tone_zones, OBJ_NODATA, tone_zone_mark, NULL);
/* Use existing config to populate the Indication table */
while ((cxt = ast_category_browse(cfg, cxt))) {
/* All categories but "general" are considered countries */
if (!strcasecmp(cxt, "general")) {
continue;
}
if (parse_tone_zone(cfg, cxt)) {
goto return_cleanup;
ao2_callback(ast_tone_zones, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK,
prune_tone_zone, NULL);
/* determine which country is the default */
country = ast_variable_retrieve(cfg, "general", "country");
if (ast_strlen_zero(country) || ast_set_indication_country(country)) {
ast_log(LOG_WARNING, "Unable to set the default country (for indication tones)\n");
}
res = 0;
return_cleanup:
ao2_unlock(ast_tone_zones);
ast_config_destroy(cfg);
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
/*! \brief CLI entries for commands provided by this module */
static struct ast_cli_entry cli_indications[] = {
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")
};
static int ast_tone_zone_hash(const void *obj, const int flags)
{
const struct ast_tone_zone *zone = obj;
return ast_str_case_hash(zone->country);
}
static int ast_tone_zone_cmp(void *obj, void *arg, int flags)
{
struct ast_tone_zone *zone = obj;
struct ast_tone_zone *zone_arg = arg;
return (!strcasecmp(zone->country, zone_arg->country)) ?
CMP_MATCH | CMP_STOP : 0;
}
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
int ast_tone_zone_data_add_structure(struct ast_data *tree, struct ast_tone_zone *zone)
{
struct ast_data *data_zone_sound;
struct ast_tone_zone_sound *s;
ast_data_add_structure(ast_tone_zone, tree, zone);
if (AST_LIST_EMPTY(&zone->tones)) {
return 0;
}
data_zone_sound = ast_data_add_node(tree, "tones");
if (!data_zone_sound) {
return -1;
}
ast_tone_zone_lock(zone);
AST_LIST_TRAVERSE(&zone->tones, s, entry) {
ast_data_add_structure(ast_tone_zone_sound, data_zone_sound, s);
}
ast_tone_zone_unlock(zone);
return 0;
}
/*!
* \internal
* \brief Clean up resources on Asterisk shutdown
*/
static void indications_shutdown(void)
{
ast_cli_unregister_multiple(cli_indications, ARRAY_LEN(cli_indications));
if (default_tone_zone) {
ast_tone_zone_unref(default_tone_zone);
default_tone_zone = NULL;
}
if (ast_tone_zones) {
ao2_ref(ast_tone_zones, -1);
ast_tone_zones = NULL;
}
}
/*! \brief Load indications module */
int ast_indications_init(void)
{
if (!(ast_tone_zones = ao2_container_alloc(NUM_TONE_ZONE_BUCKETS,
ast_tone_zone_hash, ast_tone_zone_cmp))) {
return -1;
}
if (load_indications(0)) {
return -1;
}
ast_cli_register_multiple(cli_indications, ARRAY_LEN(cli_indications));
ast_register_cleanup(indications_shutdown);