Asterisk - The Open Source Telephony Project GIT-master-f36a736
media_index.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2013, Digium, Inc.
5 *
6 * Kinsey Moore <markster@digium.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19/*! \file
20 * \brief Sound file format and description indexer.
21 */
22
23#include "asterisk.h"
24
25#include <dirent.h>
26#include <sys/stat.h>
27
28#include "asterisk/utils.h"
29#include "asterisk/lock.h"
30#include "asterisk/format.h"
31#include "asterisk/format_cap.h"
33#include "asterisk/file.h"
34
35/*** MODULEINFO
36 <support_level>core</support_level>
37 ***/
38
39/*! \brief The number of buckets to be used for storing variant-keyed objects */
40#define VARIANT_BUCKETS 7
41
42/*! \brief The number of buckets to be used for storing media filename-keyed objects */
43#define INDEX_BUCKETS 157
44
45/*! \brief Structure to hold a list of the format variations for a media file for a specific variant */
48 AST_STRING_FIELD(description); /*!< The description of the media */
49 );
50 struct ast_format_cap *formats; /*!< The formats this media is available in for this variant */
51 char variant[0]; /*!< The variant this media is available in */
52};
53
54static void media_variant_destroy(void *obj)
55{
56 struct media_variant *variant = obj;
57
59 ao2_cleanup(variant->formats);
60}
61
62static struct media_variant *media_variant_alloc(const char *variant_str)
63{
64 size_t str_sz = strlen(variant_str) + 1;
65 struct media_variant *variant;
66
69 if (!variant) {
70 return NULL;
71 }
72
73 memcpy(variant->variant, variant_str, str_sz);
74
76 if (!variant->formats || ast_string_field_init(variant, 8)) {
77 ao2_ref(variant, -1);
78
79 return NULL;
80 }
81
82 return variant;
83}
84
85static int media_variant_hash(const void *obj, const int flags)
86{
87 const char *variant = (flags & OBJ_KEY) ? obj : ((struct media_variant*) obj)->variant;
89}
90
91static int media_variant_cmp(void *obj, void *arg, int flags)
92{
93 struct media_variant *opt1 = obj, *opt2 = arg;
94 const char *variant = (flags & OBJ_KEY) ? arg : opt2->variant;
95 return strcasecmp(opt1->variant, variant) ? 0 : CMP_MATCH | CMP_STOP;
96}
97
98/*! \brief Structure to hold information about a media file */
99struct media_info {
100 struct ao2_container *variants; /*!< The variants for which this media is available */
101 char name[0]; /*!< The file name of the media */
102};
103
104static void media_info_destroy(void *obj)
105{
106 struct media_info *info = obj;
107
108 ao2_cleanup(info->variants);
109}
110
111static struct media_info *media_info_alloc(const char *name)
112{
113 size_t name_sz = strlen(name) + 1;
114 struct media_info *info;
115
116 info = ao2_alloc_options(sizeof(*info) + name_sz, media_info_destroy,
118 if (!info) {
119 return NULL;
120 }
121
122 memcpy(info->name, name, name_sz);
123
126 if (!info->variants) {
127 ao2_ref(info, -1);
128
129 return NULL;
130 }
131
132 return info;
133}
134
135static int media_info_hash(const void *obj, const int flags)
136{
137 const char *name = (flags & OBJ_KEY) ? obj : ((struct media_info*) obj)->name;
138 return ast_str_case_hash(name);
139}
140
141static int media_info_cmp(void *obj, void *arg, int flags)
142{
143 struct media_info *opt1 = obj, *opt2 = arg;
144 const char *name = (flags & OBJ_KEY) ? arg : opt2->name;
145 return strcasecmp(opt1->name, name) ? 0 : CMP_MATCH | CMP_STOP;
146}
147
149 struct ao2_container *index; /*!< The index of media that has requested */
150 struct ao2_container *media_list_cache; /*!< Cache of filenames to prevent them from being regenerated so often */
151 char base_dir[0]; /*!< Base directory for indexing */
152};
153
154static void media_index_dtor(void *obj)
155{
156 struct ast_media_index *index = obj;
157
158 ao2_cleanup(index->index);
159 ao2_cleanup(index->media_list_cache);
160}
161
163{
164 size_t base_dir_sz = strlen(base_dir) + 1;
165 struct ast_media_index *index = ao2_alloc(sizeof(*index) + base_dir_sz, media_index_dtor);
166
167 if (!index) {
168 return NULL;
169 }
170
171 memcpy(index->base_dir, base_dir, base_dir_sz);
172
175 if (!index->index) {
176 ao2_ref(index, -1);
177
178 return NULL;
179 }
180
181 return index;
182}
183
184static struct media_variant *find_variant(struct ast_media_index *index, const char *filename, const char *variant)
185{
187
188 info = ao2_find(index->index, filename, OBJ_KEY);
189 if (!info) {
190 return NULL;
191 }
192
193 return ao2_find(info->variants, variant, OBJ_KEY);
194}
195
196/*! \brief create the appropriate media_variant and any necessary structures */
197static struct media_variant *alloc_variant(struct ast_media_index *index, const char *filename, const char *variant_str)
198{
199 struct media_info *info;
200 struct media_variant *variant = NULL;
201
202 info = ao2_find(index->index, filename, OBJ_KEY);
203 if (!info) {
204 /* This is the first time the index has seen this filename,
205 * allocate and link */
206 info = media_info_alloc(filename);
207 if (!info) {
208 return NULL;
209 }
210
211 ao2_link(index->index, info);
212 } else {
213 variant = ao2_find(info->variants, variant_str, OBJ_KEY);
214 }
215
216 if (!variant) {
217 /* This is the first time the index has seen this variant for
218 * this filename, allocate and link */
219 variant = media_variant_alloc(variant_str);
220 if (variant) {
221 ao2_link(info->variants, variant);
222 }
223 }
224
225 ao2_ref(info, -1);
226
227 return variant;
228}
229
230const char *ast_media_get_description(struct ast_media_index *index, const char *filename, const char *variant_str)
231{
233 if (ast_strlen_zero(filename) || ast_strlen_zero(variant_str)) {
234 return NULL;
235 }
236
237 variant = find_variant(index, filename, variant_str);
238 if (!variant) {
239 return NULL;
240 }
241
242 return variant->description;
243}
244
245struct ast_format_cap *ast_media_get_format_cap(struct ast_media_index *index, const char *filename, const char *variant_str)
246{
247 struct ast_format_cap *dupcap;
248 RAII_VAR(struct media_variant *, variant, NULL, ao2_cleanup);
249 if (ast_strlen_zero(filename) || ast_strlen_zero(variant_str)) {
250 return NULL;
251 }
252
253 variant = find_variant(index, filename, variant_str);
254 if (!variant) {
255 return NULL;
256 }
257
259 if (dupcap) {
261 }
262 return dupcap;
263}
264
265/*! \brief Add the variant to the list of variants requested */
266static int add_variant_cb(void *obj, void *arg, int flags)
267{
268 struct media_variant *variant = obj;
269 struct ao2_container *variants= arg;
270 ast_str_container_add(variants, variant->variant);
271 return 0;
272}
273
274struct ao2_container *ast_media_get_variants(struct ast_media_index *index, const char *filename)
275{
277 RAII_VAR(struct ao2_container *, variants, NULL, ao2_cleanup);
278 if (!filename) {
279 return NULL;
280 }
281
283 if (!variants) {
284 return NULL;
285 }
286
287 info = ao2_find(index->index, filename, OBJ_KEY);
288 if (!info) {
289 return NULL;
290 }
291
292 ao2_callback(info->variants, OBJ_NODATA, add_variant_cb, variants);
293
294 ao2_ref(variants, +1);
295 return variants;
296}
297
298/*! \brief Add the media_info's filename to the container of filenames requested */
299static int add_media_cb(void *obj, void *arg, int flags)
300{
301 struct media_info *info = obj;
302 struct ao2_container *media = arg;
303 ast_str_container_add(media, info->name);
304 return 0;
305}
306
308{
309 RAII_VAR(struct ao2_container *, media, NULL, ao2_cleanup);
310
311 if (!index->media_list_cache) {
313 if (!media) {
314 return NULL;
315 }
316
317 ao2_callback(index->index, OBJ_NODATA, add_media_cb, media);
318
319 /* Ref to the cache */
320 ao2_ref(media, +1);
321 index->media_list_cache = media;
322 }
323
324 /* Ref to the caller */
325 ao2_ref(index->media_list_cache, +1);
326 return index->media_list_cache;
327}
328
329/*! \brief Update an index with new format/variant information */
330static int update_file_format_info(struct ast_media_index *index, const char *filename, const char *variant_str, struct ast_format *file_format)
331{
332 struct media_variant *variant;
333
334 variant = alloc_variant(index, filename, variant_str);
335 if (!variant) {
336 return -1;
337 }
338
340 ao2_ref(variant, -1);
341
342 return 0;
343}
344
345/*! \brief Process a media file into the index */
346static int process_media_file(struct ast_media_index *index, const char *variant, const char *subdir, const char *filename_stripped, const char *ext)
347{
348 struct ast_format *file_format;
349 const char *file_identifier = filename_stripped;
350 char *file_id_str = NULL;
351 int res;
352
354 if (!file_format) {
355 /* extension not registered */
356 return 0;
357 }
358
359 /* handle updating the file information */
360 if (subdir) {
361 if (ast_asprintf(&file_id_str, "%s/%s", subdir, filename_stripped) == -1) {
362 return -1;
363 }
364
365 file_identifier = file_id_str;
366 }
367
368 res = update_file_format_info(index, file_identifier, variant, file_format);
369 ast_free(file_id_str);
370
371 return res;
372}
373
374/*!
375 * \brief Process a media description text file
376 *
377 * This currently processes core-sounds-*.txt and extra-sounds-*.txt, but will
378 * process others if present.
379 */
381 const char *subdir,
382 const char *variant_str,
383 const char *filename,
384 const char *match_filename)
385{
386 RAII_VAR(struct ast_str *, description_file_path, ast_str_create(64), ast_free);
387 RAII_VAR(struct ast_str *, cumulative_description, ast_str_create(64), ast_free);
388 char *file_id_persist = NULL;
389 int res = 0;
390 FILE *f = NULL;
391#if defined(LOW_MEMORY)
392 char buf[256];
393#else
394 char buf[2048];
395#endif
396
397 if (!description_file_path || !cumulative_description) {
398 return -1;
399 }
400
401 if (ast_strlen_zero(subdir)) {
402 ast_str_set(&description_file_path, 0, "%s/%s/%s", index->base_dir, variant_str, filename);
403 } else {
404 ast_str_set(&description_file_path, 0, "%s/%s/%s/%s", index->base_dir, variant_str, subdir, filename);
405 }
406 f = fopen(ast_str_buffer(description_file_path), "r");
407 if (!f) {
408 ast_log(LOG_WARNING, "Could not open media description file '%s': %s\n", ast_str_buffer(description_file_path), strerror(errno));
409 return -1;
410 }
411
412 while (!feof(f)) {
413 char *file_identifier, *description;
414 if (!fgets(buf, sizeof(buf), f)) {
415 if (ferror(f)) {
416 ast_log(LOG_ERROR, "Error reading from file %s: %s\n", ast_str_buffer(description_file_path), strerror(errno));
417 }
418 continue;
419 }
420
421 /* Skip lines that are too long */
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') {
426 break;
427 }
428 }
429 if (ferror(f)) {
430 ast_log(LOG_ERROR, "Error reading from file %s: %s\n", ast_str_buffer(description_file_path), strerror(errno));
431 }
432 continue;
433 }
434
435 if (buf[0] == ';') {
436 /* ignore comments */
437 continue;
438 }
439
441 description = buf;
442 file_identifier = strsep(&description, ":");
443 if (!description) {
444 /* no ':' means this is a continuation */
445 if (file_id_persist) {
446 ast_str_append(&cumulative_description, 0, "\n%s", file_identifier);
447 }
448 continue;
449 } else {
450 /* if there's text in cumulative_description, archive it and start anew */
451 if (file_id_persist && !ast_strlen_zero(ast_str_buffer(cumulative_description))) {
452 struct media_variant *variant;
453
454 /*
455 * If we were only searching for a specific sound filename
456 * don't include others.
457 */
458 if (ast_strlen_zero(match_filename) || strcmp(match_filename, file_id_persist) == 0) {
459 variant = alloc_variant(index, file_id_persist, variant_str);
460 if (!variant) {
461 res = -1;
462 break;
463 }
464 ast_string_field_set(variant, description, ast_str_buffer(cumulative_description));
465 ao2_ref(variant, -1);
466 }
467
468 ast_str_reset(cumulative_description);
469 }
470
471 ast_free(file_id_persist);
472 file_id_persist = ast_strdup(file_identifier);
474 ast_str_set(&cumulative_description, 0, "%s", description);
475 }
476 }
477
478 /* handle the last one */
479 if (file_id_persist && !ast_strlen_zero(ast_str_buffer(cumulative_description))) {
480 struct media_variant *variant;
481
482 /*
483 * If we were only searching for a specific sound filename
484 * don't include others.
485 */
486 if (ast_strlen_zero(match_filename) || strcmp(match_filename, file_id_persist) == 0) {
487 variant = alloc_variant(index, file_id_persist, variant_str);
488 if (variant) {
489 ast_string_field_set(variant, description, ast_str_buffer(cumulative_description));
490 ao2_ref(variant, -1);
491 } else {
492 res = -1;
493 }
494 }
495 }
496
497 ast_free(file_id_persist);
498 fclose(f);
499 return res;
500}
501
503 const char *search_filename;
505 const char *search_variant;
508};
509
510static int read_dirs_cb(const char *dir_name, const char *filename, void *obj)
511{
512 struct read_dirs_data *data = obj;
513 char *ext;
514 size_t match_len;
515 char *match;
516 size_t match_base_len;
517 char *subdirs = (char *)dir_name + data->dirname_len;
518
519 /*
520 * Example:
521 * From the filesystem:
522 * index's base_dir = "/var/lib/asterisk/sounds"
523 * search_variant = "en"
524 * search directory base = "/var/lib/asterisk/sounds/en"
525 * dirname_len = 27
526 * current dir_name = "/var/lib/asterisk/sounds/en/digits"
527 * subdirs = "/digits"
528 * filename = "1.ulaw"
529 *
530 * From the search criteria:
531 * search_filename = "digits/1"
532 * search_filename_len = 8
533 */
534
535 if (*subdirs == '/') {
536 subdirs++;
537 }
538
539 /* subdirs = "digits" */
540
541 match_len = strlen(subdirs) + strlen(filename) + 2;
542 match = ast_alloca(match_len);
543 snprintf(match, match_len, "%s%s%s", subdirs,
544 ast_strlen_zero(subdirs) ? "" : "/", filename);
545
546 /* match = discovered filename relative to language = "digits/1.ulaw" */
547
548 ext = strrchr(match, '.');
549 if (!ext) {
550 return 0;
551 }
552
553 /* ext = ".ulaw" */
554
555 if (data->search_filename_len > 0) {
556 match_base_len = ext - match;
557 /*
558 * match_base_len = length of "digits/1" = 8 which
559 * happens to match the length of search_filename.
560 * However if the discovered filename was 11.ulaw
561 * it would be length of "digits/11" = 9.
562 * We need to use the larger during the compare to
563 * make sure we don't match just search_filename
564 * as a substring of the discovered filename.
565 */
566 if (data->search_filename_len > match_base_len) {
567 match_base_len = data->search_filename_len;
568 }
569 }
570
571 /* We always process txt files because they should contain description. */
572 if (strcmp(ext, ".txt") == 0) {
574 match, data->search_filename)) {
575 return -1;
576 }
577 } else if (data->search_filename_len == 0
578 || strncmp(data->search_filename, match, match_base_len ) == 0) {
579 *ext = '\0';
580 ext++;
582 }
583
584 return 0;
585}
586
588 const char *variant, const char *filename)
589{
590 struct timeval start;
591 struct timeval end;
592 int64_t elapsed;
593 int rc;
594 size_t dirname_len = strlen(index->base_dir) + strlen(S_OR(variant, "")) + 1;
595 struct read_dirs_data data = {
596 .search_filename = S_OR(filename, ""),
597 .search_filename_len = strlen(S_OR(filename, "")),
598 .search_variant = S_OR(variant, ""),
599 .index = index,
600 .dirname_len = dirname_len,
601 };
602 char *search_dir = ast_alloca(dirname_len + 1);
603
604 sprintf(search_dir, "%s%s%s", index->base_dir, ast_strlen_zero(variant) ? "" : "/",
605 data.search_variant);
606
607 gettimeofday(&start, NULL);
608 rc = ast_file_read_dirs(search_dir, read_dirs_cb, &data, -1);
609 gettimeofday(&end, NULL);
610 elapsed = ast_tvdiff_us(end, start);
611 ast_debug(1, "Media for language '%s' indexed in %8.6f seconds\n", data.search_variant, elapsed / 1E6);
612
613 return rc;
614}
if(!yyg->yy_init)
Definition: ast_expr2f.c:854
Asterisk main include file. File version handling, generic pbx functions.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
#define ast_log
Definition: astobj2.c:42
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
@ CMP_MATCH
Definition: astobj2.h:1027
@ CMP_STOP
Definition: astobj2.h:1028
#define OBJ_KEY
Definition: astobj2.h:1151
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition: astobj2.h:1693
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:404
@ OBJ_NODATA
Definition: astobj2.h:1044
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
#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.
Definition: astobj2.h:1303
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition: chan_iax2.c:2362
@ AST_MEDIA_TYPE_UNKNOWN
Definition: codec.h:31
char * end
Definition: eagi_proxy.c:73
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
Generic File Format Support. Should be included by clients of the file handling routines....
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.
Definition: file.c:1274
struct ast_format * ast_get_format_for_file_ext(const char *file_ext)
Get the ast_format associated with the given file extension.
Definition: file.c:2006
Media Format API.
Format Capabilities API.
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition: format_cap.h:38
int ast_format_cap_append_from_cap(struct ast_format_cap *dst, const struct ast_format_cap *src, enum ast_media_type type)
Append the formats of provided type in src to dst.
Definition: format_cap.c:269
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition: format_cap.h:99
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
static const char name[]
Definition: format_mp3.c:68
file_format
Definition: func_env.c:427
const char * ext
Definition: http.c:150
char * strsep(char **str, const char *delims)
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define LOG_WARNING
Asterisk locking-related definitions:
int errno
static struct media_variant * media_variant_alloc(const char *variant_str)
Definition: media_index.c:62
static struct media_variant * find_variant(struct ast_media_index *index, const char *filename, const char *variant)
Definition: media_index.c:184
static int media_info_hash(const void *obj, const int flags)
Definition: media_index.c:135
int ast_media_index_update_for_file(struct ast_media_index *index, const char *variant, const char *filename)
Update a media index for a specific sound file.
Definition: media_index.c:587
static int process_description_file(struct ast_media_index *index, const char *subdir, const char *variant_str, const char *filename, const char *match_filename)
Process a media description text file.
Definition: media_index.c:380
static int add_variant_cb(void *obj, void *arg, int flags)
Add the variant to the list of variants requested.
Definition: media_index.c:266
static struct media_info * media_info_alloc(const char *name)
Definition: media_index.c:111
static int media_info_cmp(void *obj, void *arg, int flags)
Definition: media_index.c:141
static int add_media_cb(void *obj, void *arg, int flags)
Add the media_info's filename to the container of filenames requested.
Definition: media_index.c:299
struct ao2_container * ast_media_get_media(struct ast_media_index *index)
Get the a container of all media available on the system.
Definition: media_index.c:307
static void media_index_dtor(void *obj)
Definition: media_index.c:154
static struct media_variant * alloc_variant(struct ast_media_index *index, const char *filename, const char *variant_str)
create the appropriate media_variant and any necessary structures
Definition: media_index.c:197
struct ast_media_index * ast_media_index_create(const char *base_dir)
Creates a new media index.
Definition: media_index.c:162
static int update_file_format_info(struct ast_media_index *index, const char *filename, const char *variant_str, struct ast_format *file_format)
Update an index with new format/variant information.
Definition: media_index.c:330
static int process_media_file(struct ast_media_index *index, const char *variant, const char *subdir, const char *filename_stripped, const char *ext)
Process a media file into the index.
Definition: media_index.c:346
struct ast_format_cap * ast_media_get_format_cap(struct ast_media_index *index, const char *filename, const char *variant_str)
Get the ast_format_cap for a media file.
Definition: media_index.c:245
#define VARIANT_BUCKETS
The number of buckets to be used for storing variant-keyed objects.
Definition: media_index.c:40
static int media_variant_hash(const void *obj, const int flags)
Definition: media_index.c:85
static void media_info_destroy(void *obj)
Definition: media_index.c:104
#define INDEX_BUCKETS
The number of buckets to be used for storing media filename-keyed objects.
Definition: media_index.c:43
static void media_variant_destroy(void *obj)
Definition: media_index.c:54
static int read_dirs_cb(const char *dir_name, const char *filename, void *obj)
Definition: media_index.c:510
struct ao2_container * ast_media_get_variants(struct ast_media_index *index, const char *filename)
Get the languages in which a media file is available.
Definition: media_index.c:274
static int media_variant_cmp(void *obj, void *arg, int flags)
Definition: media_index.c:91
const char * ast_media_get_description(struct ast_media_index *index, const char *filename, const char *variant_str)
Get the description for a media file.
Definition: media_index.c:230
Media file format and description indexing engine.
def info(msg)
#define NULL
Definition: resample.c:96
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
Definition: stringfields.h:341
#define AST_STRING_FIELD(name)
Declare a string field.
Definition: stringfields.h:303
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
#define ast_str_container_alloc(buckets)
Allocates a hash container for bare strings.
Definition: strings.h:1365
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:693
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
static force_inline int attribute_pure ast_str_case_hash(const char *str)
Compute a hash value on a case-insensitive string.
Definition: strings.h:1303
char * ast_trim_blanks(char *str)
Trims trailing whitespace characters from a string.
Definition: strings.h:186
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.
Definition: strings.c:205
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:161
Generic container type.
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
struct ast_format_cap::@355 formats
Vector of formats, indexed using the codec identifier.
Definition of a media format.
Definition: format.c:43
char base_dir[0]
Definition: media_index.c:151
struct ao2_container * index
Definition: media_index.c:149
struct ao2_container * media_list_cache
Definition: media_index.c:150
Support for dynamic strings.
Definition: strings.h:623
Structure to hold information about a media file.
Definition: media_index.c:99
struct ao2_container * variants
Definition: media_index.c:100
char name[0]
Definition: media_index.c:101
Structure to hold a list of the format variations for a media file for a specific variant.
Definition: media_index.c:46
struct ast_format_cap * formats
Definition: media_index.c:50
char variant[0]
Definition: media_index.c:51
const ast_string_field description
Definition: media_index.c:49
const char * search_filename
Definition: media_index.c:503
struct ast_media_index * index
Definition: media_index.c:506
const char * search_variant
Definition: media_index.c:505
size_t dirname_len
Definition: media_index.c:507
size_t search_filename_len
Definition: media_index.c:504
int64_t ast_tvdiff_us(struct timeval end, struct timeval start)
Computes the difference (in microseconds) between two struct timeval instances.
Definition: time.h:87
Utility functions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941