Asterisk - The Open Source Telephony Project GIT-master-2de1a68
Data Structures | Macros | Functions
media_index.c File Reference

Sound file format and description indexer. More...

#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/media_index.h"
#include "asterisk/file.h"
Include dependency graph for media_index.c:

Go to the source code of this file.

Data Structures

struct  ast_media_index
 
struct  media_info
 Structure to hold information about a media file. More...
 
struct  media_variant
 Structure to hold a list of the format variations for a media file for a specific variant. More...
 
struct  read_dirs_data
 

Macros

#define INDEX_BUCKETS   157
 The number of buckets to be used for storing media filename-keyed objects. More...
 
#define VARIANT_BUCKETS   7
 The number of buckets to be used for storing variant-keyed objects. More...
 

Functions

static int add_media_cb (void *obj, void *arg, int flags)
 Add the media_info's filename to the container of filenames requested. More...
 
static int add_variant_cb (void *obj, void *arg, int flags)
 Add the variant to the list of variants requested. More...
 
static struct media_variantalloc_variant (struct ast_media_index *index, const char *filename, const char *variant_str)
 create the appropriate media_variant and any necessary structures More...
 
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. More...
 
struct ast_format_capast_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. More...
 
struct ao2_containerast_media_get_media (struct ast_media_index *index)
 Get the a container of all media available on the system. More...
 
struct ao2_containerast_media_get_variants (struct ast_media_index *index, const char *filename)
 Get the languages in which a media file is available. More...
 
struct ast_media_indexast_media_index_create (const char *base_dir)
 Creates a new media index. More...
 
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. More...
 
static struct media_variantfind_variant (struct ast_media_index *index, const char *filename, const char *variant)
 
static void media_index_dtor (void *obj)
 
static struct media_infomedia_info_alloc (const char *name)
 
static int media_info_cmp (void *obj, void *arg, int flags)
 
static void media_info_destroy (void *obj)
 
static int media_info_hash (const void *obj, const int flags)
 
static struct media_variantmedia_variant_alloc (const char *variant_str)
 
static int media_variant_cmp (void *obj, void *arg, int flags)
 
static void media_variant_destroy (void *obj)
 
static int media_variant_hash (const void *obj, const int flags)
 
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. More...
 
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. More...
 
static int read_dirs_cb (const char *dir_name, const char *filename, void *obj)
 
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. More...
 

Detailed Description

Sound file format and description indexer.

Definition in file media_index.c.

Macro Definition Documentation

◆ INDEX_BUCKETS

#define INDEX_BUCKETS   157

The number of buckets to be used for storing media filename-keyed objects.

Definition at line 43 of file media_index.c.

◆ VARIANT_BUCKETS

#define VARIANT_BUCKETS   7

The number of buckets to be used for storing variant-keyed objects.

Definition at line 40 of file media_index.c.

Function Documentation

◆ add_media_cb()

static int add_media_cb ( void *  obj,
void *  arg,
int  flags 
)
static

Add the media_info's filename to the container of filenames requested.

Definition at line 299 of file media_index.c.

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}
def info(msg)
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
Generic container type.
Structure to hold information about a media file.
Definition: media_index.c:99

References ast_str_container_add(), and sip_to_pjsip::info().

Referenced by ast_media_get_media().

◆ add_variant_cb()

static int add_variant_cb ( void *  obj,
void *  arg,
int  flags 
)
static

Add the variant to the list of variants requested.

Definition at line 266 of file media_index.c.

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}
Structure to hold a list of the format variations for a media file for a specific variant.
Definition: media_index.c:46
char variant[0]
Definition: media_index.c:51

References ast_str_container_add(), and media_variant::variant.

Referenced by ast_media_get_variants().

◆ alloc_variant()

static struct media_variant * alloc_variant ( struct ast_media_index index,
const char *  filename,
const char *  variant_str 
)
static

create the appropriate media_variant and any necessary structures

Definition at line 197 of file media_index.c.

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}
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
#define OBJ_KEY
Definition: astobj2.h:1151
#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
static struct media_variant * media_variant_alloc(const char *variant_str)
Definition: media_index.c:62
static struct media_info * media_info_alloc(const char *name)
Definition: media_index.c:111
#define NULL
Definition: resample.c:96
struct ao2_container * index
Definition: media_index.c:149

References ao2_find, ao2_link, ao2_ref, ast_media_index::index, sip_to_pjsip::info(), media_info_alloc(), media_variant_alloc(), NULL, OBJ_KEY, and media_variant::variant.

Referenced by process_description_file(), and update_file_format_info().

◆ ast_media_get_description()

const char * ast_media_get_description ( struct ast_media_index index,
const char *  filename,
const char *  variant 
)

Get the description for a media file.

Parameters
indexMedia index in which to query information
filenameName of the file for which to get the description
variantMedia variant for which to get the description
Return values
NULLif not found
Returns
The description requested (must be copied to be kept)

Definition at line 230 of file media_index.c.

231{
232 RAII_VAR(struct media_variant *, variant, NULL, ao2_cleanup);
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}
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
static struct media_variant * find_variant(struct ast_media_index *index, const char *filename, const char *variant)
Definition: media_index.c:184
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
#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

References ao2_cleanup, ast_strlen_zero(), find_variant(), NULL, RAII_VAR, and media_variant::variant.

Referenced by create_sound_blob(), and show_sound_info_cb().

◆ ast_media_get_format_cap()

struct ast_format_cap * ast_media_get_format_cap ( struct ast_media_index index,
const char *  filename,
const char *  variant 
)

Get the ast_format_cap for a media file.

Parameters
indexMedia index in which to query information
filenameName of the file for which to get the description
variantMedia variant for which to get the description
Return values
NULLif not found
Returns
a copy of the format capabilities (must be destroyed with ast_format_cap_destroy)

Definition at line 245 of file media_index.c.

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}
@ AST_MEDIA_TYPE_UNKNOWN
Definition: codec.h:31
@ 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_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54

References ao2_cleanup, ast_format_cap_alloc, ast_format_cap_append_from_cap(), AST_FORMAT_CAP_FLAG_DEFAULT, AST_MEDIA_TYPE_UNKNOWN, ast_strlen_zero(), find_variant(), ast_format_cap::formats, NULL, and RAII_VAR.

Referenced by add_format_information_cb(), and show_sound_info_cb().

◆ ast_media_get_media()

struct ao2_container * ast_media_get_media ( struct ast_media_index index)

Get the a container of all media available on the system.

Parameters
indexMedia index in which to query information
Return values
NULLon error
Returns
an ast_str_container filled with media file name strings

Definition at line 307 of file media_index.c.

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}
#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
@ OBJ_NODATA
Definition: astobj2.h:1044
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
#define INDEX_BUCKETS
The number of buckets to be used for storing media filename-keyed objects.
Definition: media_index.c:43
#define ast_str_container_alloc(buckets)
Allocates a hash container for bare strings.
Definition: strings.h:1365
struct ao2_container * media_list_cache
Definition: media_index.c:150

References add_media_cb(), ao2_callback, ao2_cleanup, ao2_ref, ast_str_container_alloc, ast_media_index::index, INDEX_BUCKETS, ast_media_index::media_list_cache, NULL, OBJ_NODATA, and RAII_VAR.

Referenced by ast_ari_sounds_list(), handle_cli_sound_show(), and handle_cli_sounds_show().

◆ ast_media_get_variants()

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.

Parameters
indexMedia index in which to query information
filenameName of the file for which to get available languages
Return values
NULLon error
Returns
an ast_str_container filled with language strings

Definition at line 274 of file media_index.c.

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}
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
#define VARIANT_BUCKETS
The number of buckets to be used for storing variant-keyed objects.
Definition: media_index.c:40

References add_variant_cb(), ao2_callback, ao2_cleanup, ao2_find, ao2_ref, ast_str_container_alloc, ast_media_index::index, sip_to_pjsip::info(), NULL, OBJ_KEY, OBJ_NODATA, RAII_VAR, and VARIANT_BUCKETS.

Referenced by create_sound_blob(), and handle_cli_sound_show().

◆ ast_media_index_create()

struct ast_media_index * ast_media_index_create ( const char *  base_dir)

Creates a new media index.

Parameters
base_dirBase directory for indexing
Return values
NULLon error
Anew AO2 refcounted media index

Definition at line 162 of file media_index.c.

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}
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
#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 media_info_hash(const void *obj, const int flags)
Definition: media_index.c:135
static int media_info_cmp(void *obj, void *arg, int flags)
Definition: media_index.c:141
static void media_index_dtor(void *obj)
Definition: media_index.c:154
char base_dir[0]
Definition: media_index.c:151

References ao2_alloc, AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_hash, ao2_ref, ast_media_index::base_dir, ast_media_index::index, INDEX_BUCKETS, media_index_dtor(), media_info_cmp(), media_info_hash(), and NULL.

Referenced by ast_sounds_get_index_for_file().

◆ ast_media_index_update_for_file()

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.

Since
13.25.0
16.2.0
Parameters
indexMedia index in which to query information
variantMedia variant for which to get the description
filenameSound file name without extension
Note
If filename is NULL, this function will act as ast_media_index_update and add all sound files to the index.
Return values
non-zeroon error
Returns
zero on success

Definition at line 587 of file media_index.c.

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}
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
char * end
Definition: eagi_proxy.c:73
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
#define ast_debug(level,...)
Log a DEBUG message.
static int read_dirs_cb(const char *dir_name, const char *filename, void *obj)
Definition: media_index.c:510
#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
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
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

References ast_alloca, ast_debug, ast_file_read_dirs(), ast_strlen_zero(), ast_tvdiff_us(), ast_media_index::base_dir, read_dirs_data::dirname_len, end, read_dirs_data::index, NULL, read_dirs_cb(), S_OR, read_dirs_data::search_filename, and read_dirs_data::search_variant.

Referenced by update_index_cb().

◆ find_variant()

static struct media_variant * find_variant ( struct ast_media_index index,
const char *  filename,
const char *  variant 
)
static

Definition at line 184 of file media_index.c.

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}

References ao2_cleanup, ao2_find, ast_media_index::index, sip_to_pjsip::info(), NULL, OBJ_KEY, RAII_VAR, and media_variant::variant.

Referenced by ast_media_get_description(), and ast_media_get_format_cap().

◆ media_index_dtor()

static void media_index_dtor ( void *  obj)
static

Definition at line 154 of file media_index.c.

155{
156 struct ast_media_index *index = obj;
157
158 ao2_cleanup(index->index);
159 ao2_cleanup(index->media_list_cache);
160}

References ao2_cleanup, and ast_media_index::index.

Referenced by ast_media_index_create().

◆ media_info_alloc()

static struct media_info * media_info_alloc ( const char *  name)
static

Definition at line 111 of file media_index.c.

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}
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:404
static const char name[]
Definition: format_mp3.c:68
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
static int media_variant_cmp(void *obj, void *arg, int flags)
Definition: media_index.c:91

References AO2_ALLOC_OPT_LOCK_MUTEX, AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_container_alloc_hash, ao2_ref, sip_to_pjsip::info(), media_info_destroy(), media_variant_cmp(), media_variant_hash(), name, NULL, and VARIANT_BUCKETS.

Referenced by alloc_variant().

◆ media_info_cmp()

static int media_info_cmp ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 141 of file media_index.c.

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}
@ CMP_MATCH
Definition: astobj2.h:1027
@ CMP_STOP
Definition: astobj2.h:1028
char name[0]
Definition: media_index.c:101

References CMP_MATCH, CMP_STOP, media_info::name, name, and OBJ_KEY.

Referenced by ast_media_index_create().

◆ media_info_destroy()

static void media_info_destroy ( void *  obj)
static

Definition at line 104 of file media_index.c.

105{
106 struct media_info *info = obj;
107
108 ao2_cleanup(info->variants);
109}

References ao2_cleanup, and sip_to_pjsip::info().

Referenced by media_info_alloc().

◆ media_info_hash()

static int media_info_hash ( const void *  obj,
const int  flags 
)
static

Definition at line 135 of file media_index.c.

136{
137 const char *name = (flags & OBJ_KEY) ? obj : ((struct media_info*) obj)->name;
138 return ast_str_case_hash(name);
139}
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

References ast_str_case_hash(), name, and OBJ_KEY.

Referenced by ast_media_index_create().

◆ media_variant_alloc()

static struct media_variant * media_variant_alloc ( const char *  variant_str)
static

Definition at line 62 of file media_index.c.

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}
static void media_variant_destroy(void *obj)
Definition: media_index.c:54
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_ref, ast_format_cap_alloc, AST_FORMAT_CAP_FLAG_DEFAULT, ast_string_field_init, media_variant_destroy(), NULL, and media_variant::variant.

Referenced by alloc_variant().

◆ media_variant_cmp()

static int media_variant_cmp ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 91 of file media_index.c.

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}

References CMP_MATCH, CMP_STOP, OBJ_KEY, and media_variant::variant.

Referenced by media_info_alloc().

◆ media_variant_destroy()

static void media_variant_destroy ( void *  obj)
static

Definition at line 54 of file media_index.c.

55{
56 struct media_variant *variant = obj;
57
59 ao2_cleanup(variant->formats);
60}
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374

References ao2_cleanup, ast_string_field_free_memory, and media_variant::variant.

Referenced by media_variant_alloc().

◆ media_variant_hash()

static int media_variant_hash ( const void *  obj,
const int  flags 
)
static

Definition at line 85 of file media_index.c.

86{
87 const char *variant = (flags & OBJ_KEY) ? obj : ((struct media_variant*) obj)->variant;
88 return ast_str_case_hash(variant);
89}

References ast_str_case_hash(), OBJ_KEY, and media_variant::variant.

Referenced by media_info_alloc().

◆ process_description_file()

static int process_description_file ( struct ast_media_index index,
const char *  subdir,
const char *  variant_str,
const char *  filename,
const char *  match_filename 
)
static

Process a media description text file.

This currently processes core-sounds-*.txt and extra-sounds-*.txt, but will process others if present.

Definition at line 380 of file media_index.c.

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}
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_log
Definition: astobj2.c:42
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
char * strsep(char **str, const char *delims)
#define LOG_ERROR
#define LOG_WARNING
int errno
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
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
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
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
char * ast_trim_blanks(char *str)
Trims trailing whitespace characters from a string.
Definition: strings.h:186
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:161
Support for dynamic strings.
Definition: strings.h:623
const ast_string_field description
Definition: media_index.c:49

References alloc_variant(), ao2_ref, ast_free, ast_log, ast_skip_blanks(), ast_str_append(), ast_str_buffer(), ast_str_create, ast_str_reset(), ast_str_set(), ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_trim_blanks(), ast_media_index::base_dir, buf, media_variant::description, errno, LOG_ERROR, LOG_WARNING, NULL, RAII_VAR, strsep(), and media_variant::variant.

Referenced by read_dirs_cb().

◆ process_media_file()

static int process_media_file ( struct ast_media_index index,
const char *  variant,
const char *  subdir,
const char *  filename_stripped,
const char *  ext 
)
static

Process a media file into the index.

Definition at line 346 of file media_index.c.

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}
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
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:2005
file_format
Definition: func_env.c:427
const char * ext
Definition: http.c:150
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
Definition of a media format.
Definition: format.c:43

References ast_asprintf, ast_free, ast_get_format_for_file_ext(), ext, NULL, and update_file_format_info().

Referenced by read_dirs_cb().

◆ read_dirs_cb()

static int read_dirs_cb ( const char *  dir_name,
const char *  filename,
void *  obj 
)
static

Definition at line 510 of file media_index.c.

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}
if(!yyg->yy_init)
Definition: ast_expr2f.c:854
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:2365
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 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
size_t search_filename_len
Definition: media_index.c:504

References ast_alloca, ast_strlen_zero(), read_dirs_data::dirname_len, ext, if(), read_dirs_data::index, match(), NULL, process_description_file(), process_media_file(), read_dirs_data::search_filename, read_dirs_data::search_filename_len, and read_dirs_data::search_variant.

Referenced by ast_media_index_update_for_file().

◆ update_file_format_info()

static int update_file_format_info ( struct ast_media_index index,
const char *  filename,
const char *  variant_str,
struct ast_format file_format 
)
static

Update an index with new format/variant information.

Definition at line 330 of file media_index.c.

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}
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition: format_cap.h:99

References alloc_variant(), ao2_ref, ast_format_cap_append, and media_variant::variant.

Referenced by process_media_file().