Asterisk - The Open Source Telephony Project  18.5.0
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.

Referenced by ast_media_get_media(), and ast_media_index_create().

◆ 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.

Referenced by ast_media_get_variants(), and media_info_alloc().

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.

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

Referenced by ast_media_get_media().

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

◆ 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.

References ast_str_container_add(), and media_variant::variant.

Referenced by ast_media_get_variants().

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
Generic container type.
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:206
char variant[0]
Definition: media_index.c:51

◆ 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.

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

Referenced by process_description_file(), and update_file_format_info().

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 OBJ_KEY
Definition: astobj2.h:1155
struct ao2_container * variants
Definition: media_index.c:100
#define NULL
Definition: resample.c:96
Structure to hold a list of the format variations for a media file for a specific variant...
Definition: media_index.c:46
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static struct media_info * media_info_alloc(const char *name)
Definition: media_index.c:111
Structure to hold information about a media file.
Definition: media_index.c:99
def info(msg)
struct ao2_container * index
Definition: media_index.c:149
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
static struct media_variant * media_variant_alloc(const char *variant_str)
Definition: media_index.c:62
char variant[0]
Definition: media_index.c:51
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ 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.

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().

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 }
static struct media_variant * find_variant(struct ast_media_index *index, const char *filename, const char *variant)
Definition: media_index.c:184
#define NULL
Definition: resample.c:96
Structure to hold a list of the format variations for a media file for a specific variant...
Definition: media_index.c:46
#define ast_strlen_zero(foo)
Definition: strings.h:52
#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:911
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
char variant[0]
Definition: media_index.c:51

◆ 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.

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(), NULL, RAII_VAR, and media_variant::variant.

Referenced by add_format_information_cb(), and show_sound_info_cb().

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) {
260  ast_format_cap_append_from_cap(dupcap, variant->formats, AST_MEDIA_TYPE_UNKNOWN);
261  }
262  return dupcap;
263 }
static struct media_variant * find_variant(struct ast_media_index *index, const char *filename, const char *variant)
Definition: media_index.c:184
#define NULL
Definition: resample.c:96
Structure to hold a list of the format variations for a media file for a specific variant...
Definition: media_index.c:46
#define ast_strlen_zero(foo)
Definition: strings.h:52
#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:911
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
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

◆ 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.

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().

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)
Definition: astobj2.h:1716
#define ast_str_container_alloc(buckets)
Allocates a hash container for bare strings.
Definition: strings.h:1312
#define INDEX_BUCKETS
The number of buckets to be used for storing media filename-keyed objects.
Definition: media_index.c:43
#define NULL
Definition: resample.c:96
struct ao2_container * media_list_cache
Definition: media_index.c:150
#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:911
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ao2_container * index
Definition: media_index.c:149
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static int add_media_cb(void *obj, void *arg, int flags)
Add the media_info&#39;s filename to the container of filenames requested.
Definition: media_index.c:299
Generic container type.

◆ 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.

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().

275 {
276  RAII_VAR(struct media_info *, info, NULL, ao2_cleanup);
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 }
#define OBJ_KEY
Definition: astobj2.h:1155
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
#define ast_str_container_alloc(buckets)
Allocates a hash container for bare strings.
Definition: strings.h:1312
#define NULL
Definition: resample.c:96
#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:911
#define ao2_ref(o, delta)
Definition: astobj2.h:464
Structure to hold information about a media file.
Definition: media_index.c:99
def info(msg)
struct ao2_container * index
Definition: media_index.c:149
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
#define VARIANT_BUCKETS
The number of buckets to be used for storing variant-keyed objects.
Definition: media_index.c:40
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
Generic container type.
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

◆ 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.

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().

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 }
static int media_info_cmp(void *obj, void *arg, int flags)
Definition: media_index.c:141
#define INDEX_BUCKETS
The number of buckets to be used for storing media filename-keyed objects.
Definition: media_index.c:43
#define NULL
Definition: resample.c:96
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
struct ao2_container * index
Definition: media_index.c:149
static void media_index_dtor(void *obj)
Definition: media_index.c:154
char base_dir[0]
Definition: media_index.c:151
static int media_info_hash(const void *obj, const int flags)
Definition: media_index.c:135

◆ 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.

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, 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().

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 }
static int read_dirs_cb(const char *dir_name, const char *filename, void *obj)
Definition: media_index.c:510
const char * search_filename
Definition: media_index.c:503
#define NULL
Definition: resample.c:96
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:1231
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
size_t dirname_len
Definition: media_index.c:507
const char * search_variant
Definition: media_index.c:505
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
char base_dir[0]
Definition: media_index.c:151
struct ast_media_index * index
Definition: media_index.c:506
int64_t ast_tvdiff_us(struct timeval end, struct timeval start)
Computes the difference (in microseconds) between two struct timeval instances.
Definition: time.h:78

◆ 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.

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

Referenced by ast_media_get_description(), and ast_media_get_format_cap().

185 {
186  RAII_VAR(struct media_info *, info, NULL, ao2_cleanup);
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 }
#define OBJ_KEY
Definition: astobj2.h:1155
#define NULL
Definition: resample.c:96
#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:911
Structure to hold information about a media file.
Definition: media_index.c:99
def info(msg)
struct ao2_container * index
Definition: media_index.c:149
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ media_index_dtor()

static void media_index_dtor ( void *  obj)
static

Definition at line 154 of file media_index.c.

References ao2_cleanup, ast_media_index::index, and ast_media_index::media_list_cache.

Referenced by ast_media_index_create().

155 {
156  struct ast_media_index *index = obj;
157 
158  ao2_cleanup(index->index);
160 }
struct ao2_container * media_list_cache
Definition: media_index.c:150
struct ao2_container * index
Definition: media_index.c:149
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ media_info_alloc()

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

Definition at line 111 of file media_index.c.

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(), media_info::name, NULL, VARIANT_BUCKETS, and media_info::variants.

Referenced by alloc_variant().

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 }
static int media_variant_cmp(void *obj, void *arg, int flags)
Definition: media_index.c:91
struct ao2_container * variants
Definition: media_index.c:100
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define NULL
Definition: resample.c:96
#define ao2_ref(o, delta)
Definition: astobj2.h:464
char name[0]
Definition: media_index.c:101
Structure to hold information about a media file.
Definition: media_index.c:99
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
static int media_variant_hash(const void *obj, const int flags)
Definition: media_index.c:85
def info(msg)
static const char name[]
Definition: cdr_mysql.c:74
#define VARIANT_BUCKETS
The number of buckets to be used for storing variant-keyed objects.
Definition: media_index.c:40
static void media_info_destroy(void *obj)
Definition: media_index.c:104

◆ media_info_cmp()

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

Definition at line 141 of file media_index.c.

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

Referenced by ast_media_index_create().

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 }
#define OBJ_KEY
Definition: astobj2.h:1155
char name[0]
Definition: media_index.c:101
Structure to hold information about a media file.
Definition: media_index.c:99
static const char name[]
Definition: cdr_mysql.c:74

◆ media_info_destroy()

static void media_info_destroy ( void *  obj)
static

Definition at line 104 of file media_index.c.

References ao2_cleanup, sip_to_pjsip::info(), and media_info::variants.

Referenced by media_info_alloc().

105 {
106  struct media_info *info = obj;
107 
108  ao2_cleanup(info->variants);
109 }
struct ao2_container * variants
Definition: media_index.c:100
Structure to hold information about a media file.
Definition: media_index.c:99
def info(msg)
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ media_info_hash()

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

Definition at line 135 of file media_index.c.

References ast_str_case_hash(), name, and OBJ_KEY.

Referenced by ast_media_index_create().

136 {
137  const char *name = (flags & OBJ_KEY) ? obj : ((struct media_info*) obj)->name;
138  return ast_str_case_hash(name);
139 }
#define OBJ_KEY
Definition: astobj2.h:1155
Structure to hold information about a media file.
Definition: media_index.c:99
static const char name[]
Definition: cdr_mysql.c:74
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:1250

◆ media_variant_alloc()

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

Definition at line 62 of file media_index.c.

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::formats, media_variant_destroy(), NULL, and media_variant::variant.

Referenced by alloc_variant().

63 {
64  size_t str_sz = strlen(variant_str) + 1;
65  struct media_variant *variant;
66 
67  variant = ao2_alloc_options(sizeof(*variant) + str_sz, media_variant_destroy,
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 ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define NULL
Definition: resample.c:96
Structure to hold a list of the format variations for a media file for a specific variant...
Definition: media_index.c:46
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
struct ast_format_cap * formats
Definition: media_index.c:50
char variant[0]
Definition: media_index.c:51

◆ media_variant_cmp()

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

Definition at line 91 of file media_index.c.

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

Referenced by media_info_alloc().

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 }
#define OBJ_KEY
Definition: astobj2.h:1155
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

◆ media_variant_destroy()

static void media_variant_destroy ( void *  obj)
static

Definition at line 54 of file media_index.c.

References ao2_cleanup, ast_string_field_free_memory, media_variant::formats, and media_variant::variant.

Referenced by media_variant_alloc().

55 {
56  struct media_variant *variant = obj;
57 
59  ao2_cleanup(variant->formats);
60 }
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
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368
char variant[0]
Definition: media_index.c:51

◆ media_variant_hash()

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

Definition at line 85 of file media_index.c.

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

Referenced by media_info_alloc().

86 {
87  const char *variant = (flags & OBJ_KEY) ? obj : ((struct media_variant*) obj)->variant;
88  return ast_str_case_hash(variant);
89 }
#define OBJ_KEY
Definition: astobj2.h:1155
Structure to hold a list of the format variations for a media file for a specific variant...
Definition: media_index.c:46
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:1250
char variant[0]
Definition: media_index.c:51

◆ 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.

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().

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 
440  ast_trim_blanks(buf);
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);
473  description = ast_skip_blanks(description);
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 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define LOG_WARNING
Definition: logger.h:274
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
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:1091
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
Structure to hold a list of the format variations for a media file for a specific variant...
Definition: media_index.c:46
#define ast_strlen_zero(foo)
Definition: strings.h:52
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:1065
#define ast_log
Definition: astobj2.c:42
#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:911
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define LOG_ERROR
Definition: logger.h:285
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
int errno
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:157
const ast_string_field description
Definition: media_index.c:49
char * ast_trim_blanks(char *str)
Trims trailing whitespace characters from a string.
Definition: strings.h:182
#define ast_free(a)
Definition: astmm.h:182
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
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:653
char * strsep(char **str, const char *delims)
char base_dir[0]
Definition: media_index.c:151
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
char variant[0]
Definition: media_index.c:51
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ 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.

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

Referenced by read_dirs_cb().

347 {
348  struct ast_format *file_format;
349  const char *file_identifier = filename_stripped;
350  char *file_id_str = NULL;
351  int res;
352 
353  file_format = ast_get_format_for_file_ext(ext);
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 }
Definition of a media format.
Definition: format.c:43
#define NULL
Definition: resample.c:96
const char * ext
Definition: http.c:147
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:269
file_format
Definition: func_env.c:318
#define ast_free(a)
Definition: astmm.h:182
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:1938
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

◆ 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.

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().

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++;
581  process_media_file(data->index, data->search_variant, NULL, match, ext);
582  }
583 
584  return 0;
585 }
if(!yyg->yy_init)
Definition: ast_expr2f.c:868
const char * search_filename
Definition: media_index.c:503
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:2315
#define NULL
Definition: resample.c:96
const char * ext
Definition: http.c:147
#define ast_strlen_zero(foo)
Definition: strings.h:52
size_t search_filename_len
Definition: media_index.c:504
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
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 dirname_len
Definition: media_index.c:507
const char * search_variant
Definition: media_index.c:505
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
struct ast_media_index * index
Definition: media_index.c:506

◆ 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.

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

Referenced by process_media_file().

331 {
332  struct media_variant *variant;
333 
334  variant = alloc_variant(index, filename, variant_str);
335  if (!variant) {
336  return -1;
337  }
338 
339  ast_format_cap_append(variant->formats, file_format, 0);
340  ao2_ref(variant, -1);
341 
342  return 0;
343 }
Structure to hold a list of the format variations for a media file for a specific variant...
Definition: media_index.c:46
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_format_cap_append(cap, format, framing)
Definition: format_cap.h:103
struct ast_format_cap * formats
Definition: media_index.c:50
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
char variant[0]
Definition: media_index.c:51