40 #define VARIANT_BUCKETS 7
43 #define INDEX_BUCKETS 157
54 static void media_variant_destroy(
void *obj)
62 static struct media_variant *media_variant_alloc(
const char *variant_str)
64 size_t str_sz = strlen(variant_str) + 1;
67 variant = ao2_alloc_options(
sizeof(*variant) + str_sz, media_variant_destroy,
73 memcpy(variant->
variant, variant_str, str_sz);
85 static int media_variant_hash(
const void *obj,
const int flags)
91 static int media_variant_cmp(
void *obj,
void *arg,
int flags)
104 static void media_info_destroy(
void *obj)
113 size_t name_sz = strlen(name) + 1;
116 info = ao2_alloc_options(
sizeof(*info) + name_sz, media_info_destroy,
122 memcpy(info->
name, name, name_sz);
135 static int media_info_hash(
const void *obj,
const int flags)
141 static int media_info_cmp(
void *obj,
void *arg,
int flags)
144 const char *name = (flags &
OBJ_KEY) ? arg : opt2->name;
154 static void media_index_dtor(
void *obj)
158 ao2_cleanup(index->
index);
164 size_t base_dir_sz = strlen(base_dir) + 1;
171 memcpy(index->
base_dir, base_dir, base_dir_sz);
174 media_info_hash, NULL, media_info_cmp);
206 info = media_info_alloc(filename);
219 variant = media_variant_alloc(variant_str);
233 if (ast_strlen_zero(filename) || ast_strlen_zero(variant_str)) {
237 variant = find_variant(index, filename, variant_str);
242 return variant->description;
249 if (ast_strlen_zero(filename) || ast_strlen_zero(variant_str)) {
253 variant = find_variant(index, filename, variant_str);
349 const char *file_identifier = filename_stripped;
350 char *file_id_str = NULL;
361 if (
ast_asprintf(&file_id_str,
"%s/%s", subdir, filename_stripped) == -1) {
365 file_identifier = file_id_str;
369 ast_free(file_id_str);
382 const char *variant_str,
383 const char *filename,
384 const char *match_filename)
388 char *file_id_persist = NULL;
391 #if defined(LOW_MEMORY)
397 if (!description_file_path || !cumulative_description) {
401 if (ast_strlen_zero(subdir)) {
402 ast_str_set(&description_file_path, 0,
"%s/%s/%s", index->
base_dir, variant_str, filename);
404 ast_str_set(&description_file_path, 0,
"%s/%s/%s/%s", index->
base_dir, variant_str, subdir, filename);
408 ast_log(LOG_WARNING,
"Could not open media description file '%s': %s\n",
ast_str_buffer(description_file_path), strerror(errno));
413 char *file_identifier, *description;
414 if (!fgets(buf,
sizeof(buf), f)) {
416 ast_log(LOG_ERROR,
"Error reading from file %s: %s\n",
ast_str_buffer(description_file_path), strerror(errno));
422 if (strlen(buf) ==
sizeof(buf) - 1 && buf[
sizeof(buf) - 1] !=
'\n') {
423 ast_log(LOG_WARNING,
"Line too long, skipping. It begins with: %.32s...\n", buf);
424 while (fgets(buf,
sizeof(buf), f)) {
425 if (strlen(buf) !=
sizeof(buf) - 1 || buf[
sizeof(buf) - 1] ==
'\n') {
430 ast_log(LOG_ERROR,
"Error reading from file %s: %s\n",
ast_str_buffer(description_file_path), strerror(errno));
442 file_identifier = strsep(&description,
":");
445 if (file_id_persist) {
446 ast_str_append(&cumulative_description, 0,
"\n%s", file_identifier);
451 if (file_id_persist && !ast_strlen_zero(
ast_str_buffer(cumulative_description))) {
458 if (ast_strlen_zero(match_filename) || strcmp(match_filename, file_id_persist) == 0) {
459 variant =
alloc_variant(index, file_id_persist, variant_str);
471 ast_free(file_id_persist);
472 file_id_persist =
ast_strdup(file_identifier);
474 ast_str_set(&cumulative_description, 0,
"%s", description);
479 if (file_id_persist && !ast_strlen_zero(
ast_str_buffer(cumulative_description))) {
486 if (ast_strlen_zero(match_filename) || strcmp(match_filename, file_id_persist) == 0) {
487 variant =
alloc_variant(index, file_id_persist, variant_str);
497 ast_free(file_id_persist);
503 const char *search_filename;
504 size_t search_filename_len;
505 const char *search_variant;
510 static int read_dirs_cb(
const char *dir_name,
const char *filename,
void *obj)
516 size_t match_base_len;
517 char *subdirs = (
char *)dir_name + data->dirname_len;
535 if (*subdirs ==
'/') {
541 match_len = strlen(subdirs) + strlen(filename) + 2;
543 snprintf(match, match_len,
"%s%s%s", subdirs,
544 ast_strlen_zero(subdirs) ?
"" :
"/", filename);
548 ext = strrchr(match,
'.');
555 if (data->search_filename_len > 0) {
556 match_base_len = ext - match;
566 if (data->search_filename_len > match_base_len) {
567 match_base_len = data->search_filename_len;
572 if (strcmp(ext,
".txt") == 0) {
574 match, data->search_filename)) {
577 }
else if (data->search_filename_len == 0
578 || strncmp(data->search_filename, match, match_base_len ) == 0) {
588 const char *variant,
const char *filename)
590 struct timeval start;
594 size_t dirname_len = strlen(index->
base_dir) + strlen(
S_OR(variant,
"")) + 1;
596 .search_filename =
S_OR(filename,
""),
597 .search_filename_len = strlen(
S_OR(filename,
"")),
598 .search_variant =
S_OR(variant,
""),
600 .dirname_len = dirname_len,
602 char *search_dir =
ast_alloca(dirname_len + 1);
604 sprintf(search_dir,
"%s%s%s", index->
base_dir, ast_strlen_zero(variant) ?
"" :
"/",
605 data.search_variant);
607 gettimeofday(&start, NULL);
609 gettimeofday(&end, NULL);
611 ast_debug(1,
"Media for language '%s' indexed in %8.6f seconds\n", data.search_variant, elapsed / 1E6);
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
#define ast_str_container_alloc(buckets)
Allocates a hash container for bare strings.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
#define ast_strdup(str)
A wrapper for strdup()
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
int ast_file_read_dirs(const char *dir_name, ast_file_on_file on_file, void *obj, int max_depth)
Recursively iterate through files and directories up to max_depth.
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define AST_STRING_FIELD(name)
Declare a string field.
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Support for dynamic strings.
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
char * ast_trim_blanks(char *str)
Trims trailing whitespace characters from a string.
struct ast_format * ast_get_format_for_file_ext(const char *file_ext)
Get the ast_format associated with the given file extension.
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
int64_t ast_tvdiff_us(struct timeval end, struct timeval start)
Computes the difference (in microseconds) between two struct timeval instances.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
int ast_str_container_add(struct ao2_container *str_container, const char *add)
Adds a string to a string container allocated by ast_str_container_alloc.
static force_inline int attribute_pure ast_str_case_hash(const char *str)
Compute a hash value on a case-insensitive string.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
#define ao2_link(container, obj)
Add an object to a container.