[asterisk-commits] kmoore: branch kmoore/stasis-http_sounds r389585 - in /team/kmoore/stasis-htt...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu May 23 14:29:25 CDT 2013


Author: kmoore
Date: Thu May 23 14:29:21 2013
New Revision: 389585

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=389585
Log:
Pull res_sounds back into main and drop the API

Removed:
    team/kmoore/stasis-http_sounds/res/res_sounds.c
Modified:
    team/kmoore/stasis-http_sounds/include/asterisk/_private.h
    team/kmoore/stasis-http_sounds/include/asterisk/sounds.h
    team/kmoore/stasis-http_sounds/main/asterisk.c
    team/kmoore/stasis-http_sounds/main/sounds.c
    team/kmoore/stasis-http_sounds/res/stasis_http/resource_sounds.c

Modified: team/kmoore/stasis-http_sounds/include/asterisk/_private.h
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/stasis-http_sounds/include/asterisk/_private.h?view=diff&rev=389585&r1=389584&r2=389585
==============================================================================
--- team/kmoore/stasis-http_sounds/include/asterisk/_private.h (original)
+++ team/kmoore/stasis-http_sounds/include/asterisk/_private.h Thu May 23 14:29:21 2013
@@ -123,4 +123,7 @@
 
 /*! \brief initializes the rtp engine arrays */
 int ast_rtp_engine_init(void);
+
+/*! \brief initialize the sounds indexer */
+int ast_sounds_init(void);
 #endif /* _ASTERISK__PRIVATE_H */

Modified: team/kmoore/stasis-http_sounds/include/asterisk/sounds.h
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/stasis-http_sounds/include/asterisk/sounds.h?view=diff&rev=389585&r1=389584&r2=389585
==============================================================================
--- team/kmoore/stasis-http_sounds/include/asterisk/sounds.h (original)
+++ team/kmoore/stasis-http_sounds/include/asterisk/sounds.h Thu May 23 14:29:21 2013
@@ -28,46 +28,6 @@
 #endif
 
 struct ast_format_cap;
-
-/*! \brief Interface for sound indexers to use when registering themselves */
-struct ast_sounds_indexer {
-	/*! \brief Function pointer called by ast_sounds_get_description */
-	char *(*get_description)(const char *filename, const char *lang);
-
-	/*! \brief Function pointer called by ast_sounds_get_format_cap */
-	struct ast_format_cap *(*get_format_cap)(const char *filename, const char *lang);
-
-	/*! \brief Function pointer called by ast_sounds_get_languages */
-	struct ao2_container *(*get_languages)(const char *filename);
-
-	/*! \brief Function pointer called by ast_sounds_get_sounds */
-	struct ao2_container *(*get_sounds)(void);
-
-	/*! \brief Function pointer called by ast_sounds_reindex */
-	int (*reindex)(void);
-};
-
-/*!
- * \brief Register callbacks for a sound indexer
- *
- * \param indexer Struct containing necessary callback functions
- */
-void ast_sounds_indexer_register(struct ast_sounds_indexer *indexer);
-
-/*!
- * \brief Unregister callbacks for a sound indexer
- *
- * \param indexer The struct that was used to register the functions
- */
-void ast_sounds_indexer_unregister(struct ast_sounds_indexer *indexer);
-
-/*!
- * \brief Determine whether a sounds indexer is registered
- *
- * \retval zero if not registered
- * \retval non-zero if registered
- */
-int ast_sounds_indexer_registered(void);
 
 /*!
  * \brief Get the description for a sound

Modified: team/kmoore/stasis-http_sounds/main/asterisk.c
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/stasis-http_sounds/main/asterisk.c?view=diff&rev=389585&r1=389584&r2=389585
==============================================================================
--- team/kmoore/stasis-http_sounds/main/asterisk.c (original)
+++ team/kmoore/stasis-http_sounds/main/asterisk.c Thu May 23 14:29:21 2013
@@ -4350,6 +4350,11 @@
 		exit(1);
 	}
 
+	if (ast_sounds_init()) {
+		printf("%s", term_quit());
+		exit(1);
+	}
+
 	if ((moduleresult = load_modules(0))) {		/* Load modules */
 		printf("%s", term_quit());
 		exit(moduleresult == -2 ? 2 : 1);

Modified: team/kmoore/stasis-http_sounds/main/sounds.c
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/stasis-http_sounds/main/sounds.c?view=diff&rev=389585&r1=389584&r2=389585
==============================================================================
--- team/kmoore/stasis-http_sounds/main/sounds.c (original)
+++ team/kmoore/stasis-http_sounds/main/sounds.c Thu May 23 14:29:21 2013
@@ -21,70 +21,723 @@
  */
 
 #include "asterisk.h"
+
+#include <dirent.h>
+#include <sys/stat.h>
+
+#include "asterisk/utils.h"
+#include "asterisk/lock.h"
+#include "asterisk/format.h"
+#include "asterisk/format_cap.h"
+#include "asterisk/paths.h"	/* use ast_config_AST_DATA_DIR */
 #include "asterisk/sounds.h"
-
-/*! \brief Holder for the registered indexer interface */
-static struct ast_sounds_indexer *sounds_indexer = NULL;
-
-void ast_sounds_indexer_register(struct ast_sounds_indexer *indexer)
-{
-	sounds_indexer = indexer;
-}
-
-void ast_sounds_indexer_unregister(struct ast_sounds_indexer *indexer)
-{
-	if (indexer == sounds_indexer) {
-		indexer = NULL;
-	}
-}
-
-int ast_sounds_indexer_registered(void)
-{
-	return sounds_indexer ? 1 : 0;
-}
-
+#include "asterisk/file.h"
+#include "asterisk/cli.h"
+#include "asterisk/module.h"
+#include "asterisk/_private.h"
+
+/*** MODULEINFO
+	<support_level>core</support_level>
+ ***/
+
+/*! \brief The number of buckets to be used for storing language-keyed objects */
+#define LANGUAGE_BUCKETS 7
+
+/*! \brief The number of buckets to be used for storing sound filename-keyed objects */
+#define SOUNDS_BUCKETS 157
+
+static struct ao2_container *sounds_index;
+
+/*! \brief Structure to hold a list of the format variations for a sound file in a specific language */
+struct sound_variant {
+	AST_DECLARE_STRING_FIELDS(
+		AST_STRING_FIELD(language);	/*!< The language this sound is available in */
+		AST_STRING_FIELD(description);	/*!< The description of the sound */
+	);
+	struct ast_format_cap *formats;	/*!< The formats this sound is available in for this language */
+};
+
+static void sound_variant_destroy(void *obj)
+{
+	struct sound_variant *variant = obj;
+
+	ast_string_field_free_memory(variant);
+	variant->formats = ast_format_cap_destroy(variant->formats);
+}
+
+static struct sound_variant *sound_variant_alloc(const char *language)
+{
+	RAII_VAR(struct sound_variant *, variant, ao2_alloc(sizeof(*variant), sound_variant_destroy), ao2_cleanup);
+
+	if (ast_string_field_init(variant, 8)) {
+		return NULL;
+	}
+
+	variant->formats = ast_format_cap_alloc();
+	if (!variant->formats) {
+		return NULL;
+	}
+
+	ast_string_field_set(variant, language, language);
+
+	ao2_ref(variant, 1);
+	return variant;
+}
+
+static int sound_variant_hash(const void *obj, const int flags)
+{
+	const char *language = (flags & OBJ_KEY) ? obj : ((struct sound_variant*) obj)->language;
+	return ast_str_case_hash(language);
+}
+
+static int sound_variant_cmp(void *obj, void *arg, int flags)
+{
+	struct sound_variant *opt1 = obj, *opt2 = arg;
+	const char *language = (flags & OBJ_KEY) ? arg : opt2->language;
+	return strcasecmp(opt1->language, language) ? 0 : CMP_MATCH | CMP_STOP;
+}
+
+/*! \brief Structure to hold information about a sound file */
+struct sound_info {
+	AST_DECLARE_STRING_FIELDS(
+		AST_STRING_FIELD(name);		/*!< The name of the sound */
+	);
+	struct ao2_container *variant_list;	/*!< The list of (language, format) tuples for which this sound is available */
+};
+
+static void sound_info_destroy(void *obj)
+{
+	struct sound_info *info = obj;
+
+	ast_string_field_free_memory(info);
+	ao2_cleanup(info->variant_list);
+	info->variant_list = NULL;
+}
+
+static struct sound_info *sound_info_alloc(const char *name)
+{
+	RAII_VAR(struct sound_info *, info, ao2_alloc(sizeof(*info), sound_info_destroy), ao2_cleanup);
+
+	if (ast_string_field_init(info, 128)) {
+		return NULL;
+	}
+
+	info->variant_list = ao2_container_alloc(LANGUAGE_BUCKETS, sound_variant_hash, sound_variant_cmp);
+	if (!info->variant_list) {
+		return NULL;
+	}
+
+	ast_string_field_set(info, name, name);
+
+	ao2_ref(info, 1);
+	return info;
+}
+
+static int sound_info_hash(const void *obj, const int flags)
+{
+	const char *name = (flags & OBJ_KEY) ? obj : ((struct sound_info*) obj)->name;
+	return ast_str_case_hash(name);
+}
+
+static int sound_info_cmp(void *obj, void *arg, int flags)
+{
+	struct sound_info *opt1 = obj, *opt2 = arg;
+	const char *name = (flags & OBJ_KEY) ? arg : opt2->name;
+	return strcasecmp(opt1->name, name) ? 0 : CMP_MATCH | CMP_STOP;
+}
+
+/*! \brief Get the languages in which sound files are available */
+static struct ao2_container *get_languages(void)
+{
+	RAII_VAR(struct ao2_container *, lang_dirs, NULL, ao2_cleanup);
+	struct dirent* dent;
+	DIR* srcdir;
+	RAII_VAR(struct ast_str *, sounds_dir, ast_str_create(64), ast_free);
+
+	lang_dirs = ast_str_container_alloc(LANGUAGE_BUCKETS);
+	if (!sounds_dir || !lang_dirs) {
+		return NULL;
+	}
+
+	ast_str_set(&sounds_dir, 0, "%s/sounds", ast_config_AST_DATA_DIR);
+
+	srcdir = opendir(ast_str_buffer(sounds_dir));
+
+	if (srcdir == NULL) {
+		ast_log(LOG_ERROR, "Failed to open %s\n", ast_str_buffer(sounds_dir));
+		return NULL;
+	}
+
+	while((dent = readdir(srcdir)) != NULL) {
+		struct stat st;
+
+		if(!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) {
+			continue;
+		}
+
+		if (fstatat(dirfd(srcdir), dent->d_name, &st, 0) < 0) {
+			ast_log(LOG_ERROR, "Failed to stat %s\n", dent->d_name);
+			continue;
+		}
+
+		if (S_ISDIR(st.st_mode)) {
+			ast_str_container_add(lang_dirs, dent->d_name);
+		}
+	}
+
+	closedir(srcdir);
+	ao2_ref(lang_dirs, +1);
+	return lang_dirs;
+}
+
+static struct sound_variant *find_variant(const char *filename, const char *lang)
+{
+	RAII_VAR(struct sound_info *, info, NULL, ao2_cleanup);
+
+	info = ao2_find(sounds_index, filename, OBJ_KEY);
+	if (!info) {
+		return NULL;
+	}
+
+	return ao2_find(info->variant_list, lang, OBJ_KEY);
+}
+
+/*! \brief create the appropriate sound_variant and any necessary structures */
+static struct sound_variant *alloc_variant(const char *filename, const char *lang)
+{
+	RAII_VAR(struct sound_info *, info, NULL, ao2_cleanup);
+	RAII_VAR(struct sound_variant *, variant, NULL, ao2_cleanup);
+
+	info = ao2_find(sounds_index, filename, OBJ_KEY);
+	if (!info) {
+		/* This is the first time the index has seen this filename,
+		 * allocate and link */
+		info = sound_info_alloc(filename);
+		if (!info) {
+			return NULL;
+		}
+
+		ao2_link(sounds_index, info);
+	}
+
+	variant = ao2_find(info->variant_list, lang, OBJ_KEY);
+	if (!variant) {
+		/* This is the first time the index has seen this language for
+		 * this filename, allocate and link */
+		variant = sound_variant_alloc(lang);
+		if (!variant) {
+			return NULL;
+		}
+
+		ao2_link(info->variant_list, variant);
+	}
+
+	ao2_ref(variant, +1);
+	return variant;
+}
+
+/*! \brief Get the description associated with the sound filename for the given language if available */
 char *ast_sounds_get_description(const char *filename, const char *lang)
 {
-	if (sounds_indexer && sounds_indexer->get_description) {
-		return sounds_indexer->get_description(filename, lang);
-	}
-
-	return NULL;
-}
-
+	RAII_VAR(struct sound_variant *, variant, NULL, ao2_cleanup);
+	if (ast_strlen_zero(filename) || ast_strlen_zero(lang)) {
+		return NULL;
+	}
+
+	variant = find_variant(filename, lang);
+	if (!variant) {
+		return NULL;
+	}
+
+	return ast_strdup(variant->description);
+}
+
+/*! \brief Get the ast_format_cap associated with the sound filename and language if available */
 struct ast_format_cap *ast_sounds_get_format_cap(const char *filename, const char *lang)
 {
-	if (sounds_indexer && sounds_indexer->get_format_cap) {
-		return sounds_indexer->get_format_cap(filename, lang);
-	}
-
-	return NULL;
-}
-
+	RAII_VAR(struct sound_variant *, variant, NULL, ao2_cleanup);
+	if (ast_strlen_zero(filename) || ast_strlen_zero(lang)) {
+		return NULL;
+	}
+
+	variant = find_variant(filename, lang);
+	if (!variant) {
+		return NULL;
+	}
+
+	return ast_format_cap_dup(variant->formats);
+}
+
+/*! \brief Add the variant's language to the list of languages requested */
+static int add_language_cb(void *obj, void *arg, int flags)
+{
+	struct sound_variant *variant = obj;
+	struct ao2_container *languages = arg;
+	ast_str_container_add(languages, variant->language);
+	return 0;
+}
+
+/*! \brief Return the requested container of languages */
 struct ao2_container *ast_sounds_get_languages(const char *filename)
 {
-	if (sounds_indexer && sounds_indexer->get_languages) {
-		return sounds_indexer->get_languages(filename);
-	}
-
-	return NULL;
-}
-
+	RAII_VAR(struct sound_info *, info, NULL, ao2_cleanup);
+	RAII_VAR(struct ao2_container *, languages, NULL, ao2_cleanup);
+	if (!filename) {
+		return NULL;
+	}
+
+	languages = ast_str_container_alloc(LANGUAGE_BUCKETS);
+	if (!languages) {
+		return NULL;
+	}
+
+	info = ao2_find(sounds_index, filename, OBJ_KEY);
+	if (!info) {
+		return NULL;
+	}
+
+	ao2_callback(info->variant_list, OBJ_NODATA, add_language_cb, languages);
+
+	ao2_ref(languages, +1);
+	return languages;
+}
+
+/*! \brief Add the sound_info's sound filename to the container of filenames requested */
+static int add_sound_cb(void *obj, void *arg, int flags)
+{
+	struct sound_info *info = obj;
+	struct ao2_container *sounds = arg;
+	ast_str_container_add(sounds, info->name);
+	return 0;
+}
+
+/*! \brief Return the requested container of sounds */
 struct ao2_container *ast_sounds_get_sounds(void)
 {
-	if (sounds_indexer && sounds_indexer->get_sounds) {
-		return sounds_indexer->get_sounds();
-	}
-
-	return NULL;
-}
-
+	RAII_VAR(struct ao2_container *, sounds, NULL, ao2_cleanup);
+
+	sounds = ast_str_container_alloc(SOUNDS_BUCKETS);
+	if (!sounds) {
+		return NULL;
+	}
+
+	ao2_callback(sounds_index, OBJ_NODATA, add_sound_cb, sounds);
+
+	ao2_ref(sounds, +1);
+	return sounds;
+}
+
+/*! \brief Update an index with new format/language information */
+static int update_file_format_info(const char *filename, const char *lang, const struct ast_format *file_format)
+{
+	RAII_VAR(struct sound_variant *, variant, find_variant(filename, lang), ao2_cleanup);
+	if (!variant) {
+		variant = alloc_variant(filename, lang);
+		if (!variant) {
+			return -1;
+		}
+	}
+
+	ast_format_cap_add(variant->formats, file_format);
+	return 0;
+}
+
+/*! \brief Process a sound file into the index */
+static int process_sound_file(const char *lang, const char *subdir, const char *filename_stripped, const char *ext)
+{
+	const struct ast_format *file_format;
+	const char *file_identifier = filename_stripped;
+	RAII_VAR(struct ast_str *, file_id_str, NULL, ast_free);
+
+	file_format = ast_get_format_for_file_ext(ext);
+	if (!file_format) {
+		/* extension not registered */
+		return 0;
+	}
+
+	/* handle updating the file information */
+	if (subdir) {
+		file_id_str = ast_str_create(64);
+		if (!file_id_str) {
+			return -1;
+		}
+
+		ast_str_set(&file_id_str, 0, "%s/%s", subdir, filename_stripped);
+		file_identifier = ast_str_buffer(file_id_str);
+	}
+
+	if (update_file_format_info(file_identifier, lang, file_format)) {
+		return -1;
+	}
+	return 0;
+}
+
+/*!
+ * \brief Process a sounds description text file
+ *
+ * This currently processes core-sounds-*.txt and extra-sounds-*.txt, but will
+ * process others if present.
+ */
+static int process_description_file(const char *lang, const char *filename)
+{
+	RAII_VAR(struct ast_str *, description_file_path, ast_str_create(64), ast_free);
+	RAII_VAR(struct ast_str *, cumulative_description, ast_str_create(64), ast_free);
+	char *file_id_persist = NULL;
+	int res = 0;
+	FILE *f = NULL;
+#if defined(LOW_MEMORY)
+	char buf[256];
+#else
+	char buf[2048];
+#endif
+
+	if (!description_file_path || !cumulative_description) {
+		return -1;
+	}
+
+	ast_str_set(&description_file_path, 0, "%s/sounds/%s/%s", ast_config_AST_DATA_DIR, lang, filename);
+	f = fopen(ast_str_buffer(description_file_path), "r");
+	if (!f) {
+		ast_log(LOG_WARNING, "Could not open sound description file '%s'\n", ast_str_buffer(description_file_path));
+		return -1;
+	}
+
+	while (!feof(f)) {
+		char *file_identifier, *description;
+		if (!fgets(buf, sizeof(buf), f)) {
+			if (ferror(f)) {
+				ast_log(LOG_ERROR, "Error reading from file %s\n", ast_str_buffer(description_file_path));
+			}
+			continue;
+		}
+
+		/* Skip lines that are too long */
+		if (strlen(buf) == sizeof(buf) - 1 && buf[sizeof(buf) - 1] != '\n') {
+			ast_log(LOG_WARNING, "Line too long, skipping. It begins with: %.32s...\n", buf);
+			while (fgets(buf, sizeof(buf), f)) {
+				if (strlen(buf) != sizeof(buf) - 1 || buf[sizeof(buf) - 1] == '\n') {
+					break;
+				}
+			}
+			if (ferror(f)) {
+				ast_log(LOG_ERROR, "Error reading from file %s\n", ast_str_buffer(description_file_path));
+			}
+			continue;
+		}
+
+		if (buf[0] == ';') {
+			/* ignore comments */
+			continue;
+		}
+
+		ast_trim_blanks(buf);
+		description = buf;
+		file_identifier = strsep(&description, ":");
+		if (!description) {
+			/* no ':' means this is a continuation */
+			if (file_id_persist) {
+				ast_str_append(&cumulative_description, 0, "\n%s", file_identifier);
+			}
+			continue;
+		} else {
+			/* if there's text in cumulative_description, archive it and start anew */
+			if (file_id_persist && !ast_strlen_zero(ast_str_buffer(cumulative_description))) {
+				RAII_VAR(struct sound_variant *, variant, NULL, ao2_cleanup);
+				variant = find_variant(file_id_persist, lang);
+				if (!variant) {
+					variant = alloc_variant(filename, lang);
+					if (!variant) {
+						res = -1;
+						break;
+					}
+				}
+
+				ast_string_field_set(variant, description, ast_str_buffer(cumulative_description));
+
+				ast_str_reset(cumulative_description);
+				ast_free(file_id_persist);
+				file_id_persist = NULL;
+			}
+
+			file_id_persist = strdup(file_identifier);
+			description = ast_skip_blanks(description);
+			ast_str_set(&cumulative_description, 0, "%s", description);
+		}
+	}
+
+	/* handle the last one */
+	if (file_id_persist && !ast_strlen_zero(ast_str_buffer(cumulative_description))) {
+		RAII_VAR(struct sound_variant *, variant, NULL, ao2_cleanup);
+		variant = find_variant(file_id_persist, lang);
+		if (!variant) {
+			variant = alloc_variant(filename, lang);
+		}
+
+		if (variant) {
+			ast_string_field_set(variant, description, ast_str_buffer(cumulative_description));
+			ast_free(file_id_persist);
+		} else {
+			res = -1;
+		}
+	}
+
+	fclose(f);
+	return res;
+}
+
+/*! \brief process an individual file listing */
+static int process_file(const char *lang, const char *subdir, const char *filename)
+{
+	RAII_VAR(char *, filename_stripped, ast_strdup(filename), ast_free);
+	char *ext;
+
+	if (!filename_stripped) {
+		return -1;
+	}
+
+	ext = strrchr(filename_stripped, '.');
+	if (!ext) {
+		/* file has no extension */
+		return 0;
+	}
+
+	*ext++ = '\0';
+	if (!strcmp(ext, "txt")) {
+		if (!subdir && process_description_file(lang, filename)) {
+			return -1;
+		}
+	} else {
+		if (process_sound_file(lang, subdir, filename_stripped, ext)) {
+			return -1;
+		}
+	}
+	return 0;
+}
+
+/*! \brief Callback to process an individual language directory or subdirectory */
+static int update_index_cb(void *obj, void *arg, int flags)
+{
+	char *lang = obj;
+	char *subdir = arg;
+	struct dirent* dent;
+	DIR* srcdir;
+	RAII_VAR(struct ast_str *, sounds_lang_dir, ast_str_create(64), ast_free);
+	int res = 0;
+
+	if (!sounds_lang_dir) {
+		return 0;
+	}
+
+	if (subdir) {
+		ast_str_set(&sounds_lang_dir, 0, "%s/sounds/%s/%s", ast_config_AST_DATA_DIR, lang, subdir);
+	} else {
+		ast_str_set(&sounds_lang_dir, 0, "%s/sounds/%s", ast_config_AST_DATA_DIR, lang);
+	}
+
+	srcdir = opendir(ast_str_buffer(sounds_lang_dir));
+	if (srcdir == NULL) {
+		ast_log(LOG_ERROR, "Failed to open %s\n", ast_str_buffer(sounds_lang_dir));
+		return -1;
+	}
+
+	while((dent = readdir(srcdir)) != NULL) {
+		struct stat st;
+
+		if(!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) {
+			continue;
+		}
+
+		if (fstatat(dirfd(srcdir), dent->d_name, &st, 0) < 0) {
+			ast_log(LOG_ERROR, "Failed to stat %s\n", dent->d_name);
+			res = -1;
+			break;
+		}
+
+		if (S_ISDIR(st.st_mode)) {
+			/* only recurse one level */
+			if (!subdir) {
+				update_index_cb(lang, dent->d_name, 0);
+			} else {
+				ast_log(LOG_ERROR, "Not recursing again on lang %s subdir %s, subsubdir %s\n", lang, subdir, dent->d_name);
+			}
+			continue;
+		}
+
+		if (!S_ISREG(st.st_mode)) {
+			continue;
+		}
+
+		if (process_file(lang, subdir, dent->d_name)) {
+			res = -1;
+			break;
+		}
+	}
+
+	closedir(srcdir);
+	return res;
+}
+
+/*! \brief Reindex sounds and sound descriptions */
+static int index_sounds(void)
+{
+	RAII_VAR(struct ao2_container *, languages, get_languages(), ao2_cleanup);
+
+	if (sounds_index || !languages) {
+		return -1;
+	}
+
+	sounds_index = ao2_container_alloc(SOUNDS_BUCKETS, sound_info_hash, sound_info_cmp);
+	if (!sounds_index) {
+		return -1;
+	}
+
+	ao2_callback(languages, OBJ_NODATA, update_index_cb, NULL);
+	return 0;
+}
+
+/*! \brief Free the current sounds index */
+static void drop_sound_index(void)
+{
+	ao2_cleanup(sounds_index);
+	sounds_index = NULL;
+}
+
+/*! \brief Drop and then reindex available sounds */
 int ast_sounds_reindex(void)
 {
-	if (sounds_indexer && sounds_indexer->reindex) {
-		return sounds_indexer->reindex();
-	}
-
-	return -1;
-}
-
+	drop_sound_index();
+	if (index_sounds()) {
+		return -1;
+	}
+	return 0;
+}
+
+static int show_sounds_cb(void *obj, void *arg, int flags)
+{
+	struct sound_info *info = obj;
+	struct ast_cli_args *a = arg;
+	ast_cli(a->fd, "%s\n", info->name);
+	return 0;
+}
+
+static int show_sound_info_cb(void *obj, void *arg, int flags)
+{
+	struct sound_variant *variant = obj;
+	struct ast_cli_args *a = arg;
+        struct ast_format format;
+
+	ast_cli(a->fd, "  Language %s:\n", variant->language);
+	ast_cli(a->fd, "    Description: %s\n", variant->description);
+
+        ast_format_cap_iter_start(variant->formats);
+        while (!ast_format_cap_iter_next(variant->formats, &format)) {
+		ast_cli(a->fd, "    Format: %s\n", ast_getformatname(&format));
+        }
+        ast_format_cap_iter_end(variant->formats);
+
+	return 0;
+}
+
+/*! \brief Allow for reloading of sounds via the command line */
+static char *handle_cli_sounds_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "sounds reload";
+		e->usage =
+			"Usage: sounds reload\n"
+			"       Reloads the index of sound files and their descriptions.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 2) {
+		return CLI_SHOWUSAGE;
+	}
+
+	if (ast_sounds_reindex()) {
+		ast_cli(a->fd, "Sound re-indexing failed.\n");
+		return CLI_FAILURE;
+	}
+
+	ast_cli(a->fd, "Sound files re-indexed.\n");
+	return CLI_SUCCESS;
+}
+
+/*! \brief Allow for reloading of sounds via the command line */
+static char *handle_cli_sounds_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "sounds show";
+		e->usage =
+			"Usage: sounds show[ soundid]\n"
+			"       Shows a listing of sound files or information about the specified sound.\n";
+		return NULL;
+	case CLI_GENERATE:
+	{
+                int length = strlen(a->word);
+                int which = 0;
+                struct ao2_iterator it_sounds;
+		char *match = NULL;
+		struct sound_info *info;
+
+		it_sounds = ao2_iterator_init(sounds_index, 0);
+                while ((info = ao2_iterator_next(&it_sounds))) {
+                        if (!strncasecmp(a->word, info->name, length) && ++which > a->n) {
+                                match = ast_strdup(info->name);
+                                ao2_ref(info, -1);
+                                break;
+                        }
+                        ao2_ref(info, -1);
+                }
+                ao2_iterator_destroy(&it_sounds);
+                return match;
+	}
+	}
+
+	if (a->argc == 2) {
+		ast_cli(a->fd, "Available audio files:\n");
+		ao2_callback(sounds_index, OBJ_MULTIPLE | OBJ_NODATA, show_sounds_cb, a);
+		return CLI_SUCCESS;
+	}
+
+	if (a->argc == 3) {
+		RAII_VAR(struct sound_info *, info, ao2_find(sounds_index, a->argv[2], OBJ_KEY), ao2_cleanup);
+		if (!info) {
+			ast_cli(a->fd, "ERROR: File %s not found in index\n", a->argv[2]);
+			return CLI_FAILURE;
+		}
+
+		ast_cli(a->fd, "Indexed Information for %s:\n", info->name);
+		ao2_callback(info->variant_list, OBJ_MULTIPLE | OBJ_NODATA, show_sound_info_cb, a);
+		return CLI_SUCCESS;
+	}
+
+	return CLI_SHOWUSAGE;
+}
+
+/*! \brief Struct for registering CLI commands */
+static struct ast_cli_entry cli_sounds[] = {
+	AST_CLI_DEFINE(handle_cli_sounds_show, "Shows available sounds"),
+	AST_CLI_DEFINE(handle_cli_sounds_reload, "Reload sounds index"),
+};
+
+static void sounds_cleanup(void)
+{
+	ast_cli_unregister_multiple(cli_sounds, ARRAY_LEN(cli_sounds));
+	drop_sound_index();
+}
+
+int ast_sounds_init(void)
+{
+	sounds_index = NULL;
+	if (index_sounds()) {
+		return -1;
+	}
+	ast_cli_register_multiple(cli_sounds, ARRAY_LEN(cli_sounds));
+	ast_register_atexit(sounds_cleanup);
+	return 0;
+}
+

Modified: team/kmoore/stasis-http_sounds/res/stasis_http/resource_sounds.c
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/stasis-http_sounds/res/stasis_http/resource_sounds.c?view=diff&rev=389585&r1=389584&r2=389585
==============================================================================
--- team/kmoore/stasis-http_sounds/res/stasis_http/resource_sounds.c (original)
+++ team/kmoore/stasis-http_sounds/res/stasis_http/resource_sounds.c Thu May 23 14:29:21 2013
@@ -162,11 +162,6 @@
 	RAII_VAR(struct ao2_container *, sound_files, NULL, ao2_cleanup);
 	struct ast_json *sounds_blob;
 
-	if (!ast_sounds_indexer_registered()) {
-		stasis_http_response_error(response, 500, "Internal Error", "Sound indexer not available");
-		return;
-	}
-
 	sound_files = ast_sounds_get_sounds();
 	if (!sound_files) {
 		stasis_http_response_error(response, 500, "Internal Error", "Allocation Error");
@@ -191,11 +186,6 @@
 {
 	struct ast_json *sound_blob;
 
-	if (!ast_sounds_indexer_registered()) {
-		stasis_http_response_error(response, 500, "Internal Error", "Sound indexer not available");
-		return;
-	}
-
 	sound_blob = create_sound_blob(args->sound_id, NULL);
 	if (sound_blob) {
 		stasis_http_response_ok(response, sound_blob);




More information about the asterisk-commits mailing list