#include "asterisk/frame.h"
#include "asterisk/plc.h"
#include "asterisk/linkedlists.h"
Go to the source code of this file.
Data Structures | |
struct | ast_trans_pvt |
Default structure for translators, with the basic fields and buffers, all allocated as part of the same chunk of memory. The buffer is preceded by AST_FRIENDLY_OFFSET bytes in front of the user portion. 'buf' points right after this space. More... | |
struct | ast_translator |
Descriptor of a translator. Name, callbacks, and various options related to run-time operation (size of buffers, auxiliary descriptors, etc). More... | |
Defines | |
#define | ast_register_translator(t) __ast_register_translator(t, ast_module_info->self) |
#define | MAX_AUDIO_FORMAT 15 |
#define | MAX_FORMAT 32 |
Functions | |
int | __ast_register_translator (struct ast_translator *t, struct ast_module *module) |
Register a translator This registers a codec translator with asterisk. | |
ast_frame * | ast_trans_frameout (struct ast_trans_pvt *pvt, int datalen, int samples) |
generic frameout function | |
ast_frame * | ast_translate (struct ast_trans_pvt *tr, struct ast_frame *f, int consume) |
translates one or more frames Apply an input frame into the translator and receive zero or one output frames. Consume determines whether the original frame should be freed | |
unsigned int | ast_translate_available_formats (unsigned int dest, unsigned int src) |
Mask off unavailable formats from a format bitmask. | |
void | ast_translate_frame_freed (struct ast_frame *fr) |
Hint that a frame from a translator has been freed. | |
unsigned int | ast_translate_path_steps (unsigned int dest, unsigned int src) |
Returns the number of steps required to convert from 'src' to 'dest'. | |
void | ast_translator_activate (struct ast_translator *t) |
Activate a previously deactivated translator. | |
int | ast_translator_best_choice (int *dsts, int *srcs) |
Chooses the best translation path. | |
ast_trans_pvt * | ast_translator_build_path (int dest, int source) |
Builds a translator path Build a path (possibly NULL) from source to dest. | |
void | ast_translator_deactivate (struct ast_translator *t) |
Deactivate a translator. | |
void | ast_translator_free_path (struct ast_trans_pvt *tr) |
Frees a translator path Frees the given translator path structure. | |
int | ast_unregister_translator (struct ast_translator *t) |
Unregister a translator Unregisters the given tranlator. |
Definition in file translate.h.
#define ast_register_translator | ( | t | ) | __ast_register_translator(t, ast_module_info->self) |
#define MAX_AUDIO_FORMAT 15 |
#define MAX_FORMAT 32 |
Definition at line 27 of file translate.h.
Referenced by __ast_register_translator(), and rebuild_matrix().
int __ast_register_translator | ( | struct ast_translator * | t, | |
struct ast_module * | module | |||
) |
Register a translator This registers a codec translator with asterisk.
t | populated ast_translator structure | |
module | handle to the module that owns this translator |
Definition at line 682 of file translate.c.
References ast_cli_register_multiple(), AST_FORMAT_SLINEAR, ast_getformatname(), AST_LIST_INSERT_BEFORE_CURRENT, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_verbose(), calc_cost(), cli_translate, COLOR_BLACK, COLOR_MAGENTA, ast_translator::cost, default_frameout(), ast_translator::dstfmt, LOG_WARNING, MAX_FORMAT, option_verbose, powerof(), rebuild_matrix(), ast_translator::srcfmt, t, term_color(), and VERBOSE_PREFIX_2.
00683 { 00684 static int added_cli = 0; 00685 struct ast_translator *u; 00686 00687 if (!mod) { 00688 ast_log(LOG_WARNING, "Missing module pointer, you need to supply one\n"); 00689 return -1; 00690 } 00691 00692 if (!t->buf_size) { 00693 ast_log(LOG_WARNING, "empty buf size, you need to supply one\n"); 00694 return -1; 00695 } 00696 00697 t->module = mod; 00698 00699 t->srcfmt = powerof(t->srcfmt); 00700 t->dstfmt = powerof(t->dstfmt); 00701 t->active = 1; 00702 00703 if (t->srcfmt == -1 || t->dstfmt == -1) { 00704 ast_log(LOG_WARNING, "Invalid translator path: (%s codec is not valid)\n", t->srcfmt == -1 ? "starting" : "ending"); 00705 return -1; 00706 } 00707 if (t->plc_samples) { 00708 if (t->buffer_samples < t->plc_samples) { 00709 ast_log(LOG_WARNING, "plc_samples %d buffer_samples %d\n", 00710 t->plc_samples, t->buffer_samples); 00711 return -1; 00712 } 00713 if (t->dstfmt != powerof(AST_FORMAT_SLINEAR)) 00714 ast_log(LOG_WARNING, "plc_samples %d format %x\n", 00715 t->plc_samples, t->dstfmt); 00716 } 00717 if (t->srcfmt >= MAX_FORMAT) { 00718 ast_log(LOG_WARNING, "Source format %s is larger than MAX_FORMAT\n", ast_getformatname(t->srcfmt)); 00719 return -1; 00720 } 00721 00722 if (t->dstfmt >= MAX_FORMAT) { 00723 ast_log(LOG_WARNING, "Destination format %s is larger than MAX_FORMAT\n", ast_getformatname(t->dstfmt)); 00724 return -1; 00725 } 00726 00727 if (t->buf_size) { 00728 /* 00729 * Align buf_size properly, rounding up to the machine-specific 00730 * alignment for pointers. 00731 */ 00732 struct _test_align { void *a, *b; } p; 00733 int align = (char *)&p.b - (char *)&p.a; 00734 00735 t->buf_size = ((t->buf_size + align - 1) / align) * align; 00736 } 00737 00738 if (t->frameout == NULL) 00739 t->frameout = default_frameout; 00740 00741 calc_cost(t, 1); 00742 00743 if (option_verbose > 1) { 00744 char tmp[80]; 00745 00746 ast_verbose(VERBOSE_PREFIX_2 "Registered translator '%s' from format %s to %s, cost %d\n", 00747 term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), 00748 ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt), t->cost); 00749 } 00750 00751 if (!added_cli) { 00752 ast_cli_register_multiple(cli_translate, sizeof(cli_translate) / sizeof(struct ast_cli_entry)); 00753 added_cli++; 00754 } 00755 00756 AST_LIST_LOCK(&translators); 00757 00758 /* find any existing translators that provide this same srcfmt/dstfmt, 00759 and put this one in order based on cost */ 00760 AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) { 00761 if ((u->srcfmt == t->srcfmt) && 00762 (u->dstfmt == t->dstfmt) && 00763 (u->cost > t->cost)) { 00764 AST_LIST_INSERT_BEFORE_CURRENT(&translators, t, list); 00765 t = NULL; 00766 } 00767 } 00768 AST_LIST_TRAVERSE_SAFE_END; 00769 00770 /* if no existing translator was found for this format combination, 00771 add it to the beginning of the list */ 00772 if (t) 00773 AST_LIST_INSERT_HEAD(&translators, t, list); 00774 00775 rebuild_matrix(0); 00776 00777 AST_LIST_UNLOCK(&translators); 00778 00779 return 0; 00780 }
struct ast_frame* ast_trans_frameout | ( | struct ast_trans_pvt * | pvt, | |
int | datalen, | |||
int | samples | |||
) |
generic frameout function
Definition at line 221 of file translate.c.
References AST_FRAME_VOICE, AST_FRFLAG_FROM_TRANSLATOR, AST_FRIENDLY_OFFSET, ast_set_flag, ast_trans_pvt::datalen, ast_translator::dstfmt, ast_trans_pvt::f, f, ast_translator::name, ast_trans_pvt::outbuf, ast_trans_pvt::samples, and ast_trans_pvt::t.
Referenced by default_frameout(), lintoadpcm_frameout(), lintogsm_frameout(), lintoilbc_frameout(), and lintolpc10_frameout().
00223 { 00224 struct ast_frame *f = &pvt->f; 00225 00226 if (samples) 00227 f->samples = samples; 00228 else { 00229 if (pvt->samples == 0) 00230 return NULL; 00231 f->samples = pvt->samples; 00232 pvt->samples = 0; 00233 } 00234 if (datalen) 00235 f->datalen = datalen; 00236 else { 00237 f->datalen = pvt->datalen; 00238 pvt->datalen = 0; 00239 } 00240 00241 f->frametype = AST_FRAME_VOICE; 00242 f->subclass = 1 << (pvt->t->dstfmt); 00243 f->mallocd = 0; 00244 f->offset = AST_FRIENDLY_OFFSET; 00245 f->src = pvt->t->name; 00246 f->data = pvt->outbuf; 00247 00248 ast_set_flag(f, AST_FRFLAG_FROM_TRANSLATOR); 00249 00250 return f; 00251 }
struct ast_frame* ast_translate | ( | struct ast_trans_pvt * | tr, | |
struct ast_frame * | f, | |||
int | consume | |||
) |
translates one or more frames Apply an input frame into the translator and receive zero or one output frames. Consume determines whether the original frame should be freed
tr | translator structure to use for translation | |
f | frame to translate | |
consume | Whether or not to free the original frame |
Definition at line 315 of file translate.c.
References ast_format_rate(), AST_FRAME_CNG, AST_FRFLAG_HAS_TIMING_INFO, ast_frfree, ast_samp2tv(), ast_set2_flag, ast_test_flag, ast_tv(), ast_tvadd(), ast_tveq(), ast_tvnow(), ast_tvsub(), ast_tvzero(), ast_frame::delivery, f, framein(), ast_frame::frametype, ast_frame::len, len(), ast_trans_pvt::next, ast_trans_pvt::nextin, ast_trans_pvt::nextout, ast_frame::samples, ast_frame::seqno, ast_frame::subclass, and ast_frame::ts.
Referenced by __ast_read(), ast_audiohook_read_frame(), ast_slinfactory_feed(), ast_write(), ast_writestream(), audio_audiohook_write_list(), conf_run(), and process_ast_dsp().
00316 { 00317 struct ast_trans_pvt *p = path; 00318 struct ast_frame *out = f; 00319 struct timeval delivery; 00320 int has_timing_info; 00321 long ts; 00322 long len; 00323 int seqno; 00324 00325 has_timing_info = ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO); 00326 ts = f->ts; 00327 len = f->len; 00328 seqno = f->seqno; 00329 00330 /* XXX hmmm... check this below */ 00331 if (!ast_tvzero(f->delivery)) { 00332 if (!ast_tvzero(path->nextin)) { 00333 /* Make sure this is in line with what we were expecting */ 00334 if (!ast_tveq(path->nextin, f->delivery)) { 00335 /* The time has changed between what we expected and this 00336 most recent time on the new packet. If we have a 00337 valid prediction adjust our output time appropriately */ 00338 if (!ast_tvzero(path->nextout)) { 00339 path->nextout = ast_tvadd(path->nextout, 00340 ast_tvsub(f->delivery, path->nextin)); 00341 } 00342 path->nextin = f->delivery; 00343 } 00344 } else { 00345 /* This is our first pass. Make sure the timing looks good */ 00346 path->nextin = f->delivery; 00347 path->nextout = f->delivery; 00348 } 00349 /* Predict next incoming sample */ 00350 path->nextin = ast_tvadd(path->nextin, ast_samp2tv(f->samples, ast_format_rate(f->subclass))); 00351 } 00352 delivery = f->delivery; 00353 for ( ; out && p ; p = p->next) { 00354 framein(p, out); 00355 if (out != f) 00356 ast_frfree(out); 00357 out = p->t->frameout(p); 00358 } 00359 if (consume) 00360 ast_frfree(f); 00361 if (out == NULL) 00362 return NULL; 00363 /* we have a frame, play with times */ 00364 if (!ast_tvzero(delivery)) { 00365 /* Regenerate prediction after a discontinuity */ 00366 if (ast_tvzero(path->nextout)) 00367 path->nextout = ast_tvnow(); 00368 00369 /* Use next predicted outgoing timestamp */ 00370 out->delivery = path->nextout; 00371 00372 /* Predict next outgoing timestamp from samples in this 00373 frame. */ 00374 path->nextout = ast_tvadd(path->nextout, ast_samp2tv(out->samples, ast_format_rate(out->subclass))); 00375 } else { 00376 out->delivery = ast_tv(0, 0); 00377 ast_set2_flag(out, has_timing_info, AST_FRFLAG_HAS_TIMING_INFO); 00378 if (has_timing_info) { 00379 out->ts = ts; 00380 out->len = len; 00381 out->seqno = seqno; 00382 } 00383 } 00384 /* Invalidate prediction if we're entering a silence period */ 00385 if (out->frametype == AST_FRAME_CNG) 00386 path->nextout = ast_tv(0, 0); 00387 return out; 00388 }
unsigned int ast_translate_available_formats | ( | unsigned int | dest, | |
unsigned int | src | |||
) |
Mask off unavailable formats from a format bitmask.
dest | possible destination formats | |
src | source formats |
Note that only a single audio format and a single video format can be present in 'src', or the function will produce unexpected results.
Definition at line 895 of file translate.c.
References AST_FORMAT_AUDIO_MASK, AST_FORMAT_MAX_AUDIO, AST_FORMAT_MAX_VIDEO, AST_FORMAT_VIDEO_MASK, AST_LIST_LOCK, AST_LIST_UNLOCK, powerof(), and tr_matrix.
Referenced by sip_call().
00896 { 00897 unsigned int res = dest; 00898 unsigned int x; 00899 unsigned int src_audio = src & AST_FORMAT_AUDIO_MASK; 00900 unsigned int src_video = src & AST_FORMAT_VIDEO_MASK; 00901 00902 /* if we don't have a source format, we just have to try all 00903 possible destination formats */ 00904 if (!src) 00905 return dest; 00906 00907 /* If we have a source audio format, get its format index */ 00908 if (src_audio) 00909 src_audio = powerof(src_audio); 00910 00911 /* If we have a source video format, get its format index */ 00912 if (src_video) 00913 src_video = powerof(src_video); 00914 00915 AST_LIST_LOCK(&translators); 00916 00917 /* For a given source audio format, traverse the list of 00918 known audio formats to determine whether there exists 00919 a translation path from the source format to the 00920 destination format. */ 00921 for (x = 1; src_audio && x < AST_FORMAT_MAX_AUDIO; x <<= 1) { 00922 /* if this is not a desired format, nothing to do */ 00923 if (!dest & x) 00924 continue; 00925 00926 /* if the source is supplying this format, then 00927 we can leave it in the result */ 00928 if (src & x) 00929 continue; 00930 00931 /* if we don't have a translation path from the src 00932 to this format, remove it from the result */ 00933 if (!tr_matrix[src_audio][powerof(x)].step) { 00934 res &= ~x; 00935 continue; 00936 } 00937 00938 /* now check the opposite direction */ 00939 if (!tr_matrix[powerof(x)][src_audio].step) 00940 res &= ~x; 00941 } 00942 00943 /* For a given source video format, traverse the list of 00944 known video formats to determine whether there exists 00945 a translation path from the source format to the 00946 destination format. */ 00947 for (; src_video && x < AST_FORMAT_MAX_VIDEO; x <<= 1) { 00948 /* if this is not a desired format, nothing to do */ 00949 if (!dest & x) 00950 continue; 00951 00952 /* if the source is supplying this format, then 00953 we can leave it in the result */ 00954 if (src & x) 00955 continue; 00956 00957 /* if we don't have a translation path from the src 00958 to this format, remove it from the result */ 00959 if (!tr_matrix[src_video][powerof(x)].step) { 00960 res &= ~x; 00961 continue; 00962 } 00963 00964 /* now check the opposite direction */ 00965 if (!tr_matrix[powerof(x)][src_video].step) 00966 res &= ~x; 00967 } 00968 00969 AST_LIST_UNLOCK(&translators); 00970 00971 return res; 00972 }
void ast_translate_frame_freed | ( | struct ast_frame * | fr | ) |
Hint that a frame from a translator has been freed.
This is sort of a hack. This function gets called when ast_frame_free() gets called on a frame that has the AST_FRFLAG_FROM_TRANSLATOR flag set. This is because it is possible for a translation path to be destroyed while a frame from a translator is still in use. Specifically, this happens if a masquerade happens after a call to ast_read() but before the frame is done being processed, since the frame processing is generally done without the channel lock held.
Definition at line 974 of file translate.c.
References ast_clear_flag, AST_FRFLAG_FROM_TRANSLATOR, destroy(), f, and ast_trans_pvt::pvt.
Referenced by ast_frame_free().
00975 { 00976 struct ast_trans_pvt *pvt; 00977 00978 ast_clear_flag(fr, AST_FRFLAG_FROM_TRANSLATOR); 00979 00980 pvt = (struct ast_trans_pvt *) (((char *) fr) - offsetof(struct ast_trans_pvt, f)); 00981 00982 if (pvt->datalen != -1) 00983 return; 00984 00985 destroy(pvt); 00986 }
unsigned int ast_translate_path_steps | ( | unsigned int | dest, | |
unsigned int | src | |||
) |
Returns the number of steps required to convert from 'src' to 'dest'.
dest | destination format | |
src | source format |
Definition at line 873 of file translate.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), LOG_WARNING, translator_path::multistep, powerof(), and tr_matrix.
Referenced by ast_channel_make_compatible().
00874 { 00875 unsigned int res = -1; 00876 00877 /* convert bitwise format numbers into array indices */ 00878 src = powerof(src); 00879 dest = powerof(dest); 00880 00881 if (src == -1 || dest == -1) { 00882 ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", src == -1 ? "starting" : "ending"); 00883 return -1; 00884 } 00885 AST_LIST_LOCK(&translators); 00886 00887 if (tr_matrix[src][dest].step) 00888 res = tr_matrix[src][dest].multistep + 1; 00889 00890 AST_LIST_UNLOCK(&translators); 00891 00892 return res; 00893 }
void ast_translator_activate | ( | struct ast_translator * | t | ) |
Activate a previously deactivated translator.
t | translator to activate |
Definition at line 809 of file translate.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, rebuild_matrix(), and t.
00810 { 00811 AST_LIST_LOCK(&translators); 00812 t->active = 1; 00813 rebuild_matrix(0); 00814 AST_LIST_UNLOCK(&translators); 00815 }
int ast_translator_best_choice | ( | int * | dsts, | |
int * | srcs | |||
) |
Chooses the best translation path.
Given a list of sources, and a designed destination format, which should I choose?
Definition at line 826 of file translate.c.
References AST_FORMAT_AUDIO_MASK, AST_LIST_LOCK, AST_LIST_UNLOCK, translator_path::cost, ast_translator::cost, MAX_AUDIO_FORMAT, translator_path::multistep, and tr_matrix.
Referenced by ast_channel_make_compatible(), ast_request(), iax2_request(), and set_format().
00827 { 00828 int x,y; 00829 int best = -1; 00830 int bestdst = 0; 00831 int cur, cursrc; 00832 int besttime = INT_MAX; 00833 int beststeps = INT_MAX; 00834 int common = ((*dst) & (*srcs)) & AST_FORMAT_AUDIO_MASK; /* are there common formats ? */ 00835 00836 if (common) { /* yes, pick one and return */ 00837 for (cur = 1, y = 0; y <= MAX_AUDIO_FORMAT; cur <<= 1, y++) { 00838 if (cur & common) /* guaranteed to find one */ 00839 break; 00840 } 00841 /* We are done, this is a common format to both. */ 00842 *srcs = *dst = cur; 00843 return 0; 00844 } else { /* No, we will need to translate */ 00845 AST_LIST_LOCK(&translators); 00846 for (cur = 1, y = 0; y <= MAX_AUDIO_FORMAT; cur <<= 1, y++) { 00847 if (! (cur & *dst)) 00848 continue; 00849 for (cursrc = 1, x = 0; x <= MAX_AUDIO_FORMAT; cursrc <<= 1, x++) { 00850 if (!(*srcs & cursrc) || !tr_matrix[x][y].step || 00851 tr_matrix[x][y].cost > besttime) 00852 continue; /* not existing or no better */ 00853 if (tr_matrix[x][y].cost < besttime || 00854 tr_matrix[x][y].multistep < beststeps) { 00855 /* better than what we have so far */ 00856 best = cursrc; 00857 bestdst = cur; 00858 besttime = tr_matrix[x][y].cost; 00859 beststeps = tr_matrix[x][y].multistep; 00860 } 00861 } 00862 } 00863 AST_LIST_UNLOCK(&translators); 00864 if (best > -1) { 00865 *srcs = best; 00866 *dst = bestdst; 00867 best = 0; 00868 } 00869 return best; 00870 } 00871 }
struct ast_trans_pvt* ast_translator_build_path | ( | int | dest, | |
int | source | |||
) |
Builds a translator path Build a path (possibly NULL) from source to dest.
dest | destination format | |
source | source format |
Definition at line 270 of file translate.c.
References ast_getformatname(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_translator_free_path(), ast_tv(), ast_translator::dstfmt, LOG_WARNING, newpvt(), ast_trans_pvt::next, ast_trans_pvt::nextin, ast_trans_pvt::nextout, powerof(), translator_path::step, ast_trans_pvt::t, t, and tr_matrix.
Referenced by ast_audiohook_read_frame(), ast_slinfactory_feed(), ast_writestream(), audio_audiohook_write_list(), conf_run(), misdn_set_opt_exec(), read_config(), and set_format().
00271 { 00272 struct ast_trans_pvt *head = NULL, *tail = NULL; 00273 00274 source = powerof(source); 00275 dest = powerof(dest); 00276 00277 if (source == -1 || dest == -1) { 00278 ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", source == -1 ? "starting" : "ending"); 00279 return NULL; 00280 } 00281 00282 AST_LIST_LOCK(&translators); 00283 00284 while (source != dest) { 00285 struct ast_trans_pvt *cur; 00286 struct ast_translator *t = tr_matrix[source][dest].step; 00287 if (!t) { 00288 ast_log(LOG_WARNING, "No translator path from %s to %s\n", 00289 ast_getformatname(source), ast_getformatname(dest)); 00290 AST_LIST_UNLOCK(&translators); 00291 return NULL; 00292 } 00293 if (!(cur = newpvt(t))) { 00294 ast_log(LOG_WARNING, "Failed to build translator step from %d to %d\n", source, dest); 00295 if (head) 00296 ast_translator_free_path(head); 00297 AST_LIST_UNLOCK(&translators); 00298 return NULL; 00299 } 00300 if (!head) 00301 head = cur; 00302 else 00303 tail->next = cur; 00304 tail = cur; 00305 cur->nextin = cur->nextout = ast_tv(0, 0); 00306 /* Keep going if this isn't the final destination */ 00307 source = cur->t->dstfmt; 00308 } 00309 00310 AST_LIST_UNLOCK(&translators); 00311 return head; 00312 }
void ast_translator_deactivate | ( | struct ast_translator * | t | ) |
Deactivate a translator.
t | translator to deactivate |
Definition at line 817 of file translate.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, rebuild_matrix(), and t.
00818 { 00819 AST_LIST_LOCK(&translators); 00820 t->active = 0; 00821 rebuild_matrix(0); 00822 AST_LIST_UNLOCK(&translators); 00823 }
void ast_translator_free_path | ( | struct ast_trans_pvt * | tr | ) |
Frees a translator path Frees the given translator path structure.
tr | translator path to get rid of |
Definition at line 260 of file translate.c.
References destroy(), and ast_trans_pvt::next.
Referenced by ast_audiohook_destroy(), ast_audiohook_detach_list(), ast_audiohook_read_frame(), ast_channel_free(), ast_slinfactory_destroy(), ast_slinfactory_feed(), ast_slinfactory_flush(), ast_translator_build_path(), ast_writestream(), audio_audiohook_write_list(), cl_dequeue_chan(), conf_free(), filestream_destructor(), free_translation(), and set_format().
00261 { 00262 struct ast_trans_pvt *pn = p; 00263 while ( (p = pn) ) { 00264 pn = p->next; 00265 destroy(p); 00266 } 00267 }
int ast_unregister_translator | ( | struct ast_translator * | t | ) |
Unregister a translator Unregisters the given tranlator.
t | translator to unregister |
Definition at line 783 of file translate.c.
References ast_getformatname(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_verbose(), COLOR_BLACK, COLOR_MAGENTA, ast_translator::list, option_verbose, rebuild_matrix(), t, term_color(), and VERBOSE_PREFIX_2.
Referenced by drop_translator(), load_module(), unload_module(), and unregister_translators().
00784 { 00785 char tmp[80]; 00786 struct ast_translator *u; 00787 int found = 0; 00788 00789 AST_LIST_LOCK(&translators); 00790 AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) { 00791 if (u == t) { 00792 AST_LIST_REMOVE_CURRENT(&translators, list); 00793 if (option_verbose > 1) 00794 ast_verbose(VERBOSE_PREFIX_2 "Unregistered translator '%s' from format %s to %s\n", term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt)); 00795 found = 1; 00796 break; 00797 } 00798 } 00799 AST_LIST_TRAVERSE_SAFE_END; 00800 00801 if (found) 00802 rebuild_matrix(0); 00803 00804 AST_LIST_UNLOCK(&translators); 00805 00806 return (u ? 0 : -1); 00807 }