#include <asterisk/frame.h>#include <asterisk/sched.h>#include <asterisk/chanvars.h>#include <unistd.h>#include <setjmp.h>#include <sys/poll.h>#include <asterisk/lock.h>#include <asterisk/cdr.h>#include <asterisk/monitor.h>Go to the source code of this file.
Data Structures | |
| struct | ast_generator |
| struct | ast_channel |
| Main Channel structure associated with a channel. More... | |
| struct | ast_bridge_config |
| struct | outgoing_helper |
Defines | |
| #define | AST_MAX_EXTENSION 80 |
| Max length of an extension. | |
| #define | AST_CHANNEL_NAME 80 |
| #define | AST_CHANNEL_MAX_STACK 32 |
| #define | MAX_LANGUAGE 20 |
| #define | AST_MAX_FDS 8 |
| #define | AST_FLAG_DIGITAL 1 |
| #define | LOAD_OH(oh) |
| #define | AST_CDR_TRANSFER (1 << 0) |
| #define | AST_CDR_FORWARD (1 << 1) |
| #define | AST_CDR_CALLWAIT (1 << 2) |
| #define | AST_CDR_CONFERENCE (1 << 3) |
| #define | AST_ADSI_UNKNOWN (0) |
| #define | AST_ADSI_AVAILABLE (1) |
| #define | AST_ADSI_UNAVAILABLE (2) |
| #define | AST_ADSI_OFFHOOKONLY (3) |
| #define | AST_SOFTHANGUP_DEV (1 << 0) |
| #define | AST_SOFTHANGUP_ASYNCGOTO (1 << 1) |
| #define | AST_SOFTHANGUP_SHUTDOWN (1 << 2) |
| #define | AST_SOFTHANGUP_TIMEOUT (1 << 3) |
| #define | AST_SOFTHANGUP_APPUNLOAD (1 << 4) |
| #define | AST_SOFTHANGUP_EXPLICIT (1 << 5) |
| #define | AST_STATE_DOWN 0 |
| #define | AST_STATE_RESERVED 1 |
| #define | AST_STATE_OFFHOOK 2 |
| #define | AST_STATE_DIALING 3 |
| #define | AST_STATE_RING 4 |
| #define | AST_STATE_RINGING 5 |
| #define | AST_STATE_UP 6 |
| #define | AST_STATE_BUSY 7 |
| #define | AST_STATE_DIALING_OFFHOOK 8 |
| #define | AST_STATE_PRERING 9 |
| #define | AST_STATE_MUTE (1 << 16) |
| #define | AST_DEVICE_UNKNOWN 0 |
| #define | AST_DEVICE_NOT_INUSE 1 |
| #define | AST_DEVICE_INUSE 2 |
| #define | AST_DEVICE_BUSY 3 |
| #define | AST_DEVICE_INVALID 4 |
| #define | AST_DEVICE_UNAVAILABLE 5 |
| #define | AST_BRIDGE_DTMF_CHANNEL_0 (1 << 0) |
| #define | AST_BRIDGE_DTMF_CHANNEL_1 (1 << 1) |
| #define | AST_BRIDGE_REC_CHANNEL_0 (1 << 2) |
| #define | AST_BRIDGE_REC_CHANNEL_1 (1 << 3) |
| #define | AST_BRIDGE_IGNORE_SIGS (1 << 4) |
| #define | CRASH do { } while(0) |
| #define | CHECK_BLOCKING(c) |
Functions | |
| ast_channel * | ast_request (char *type, int format, void *data) |
| Requests a channel. | |
| int | ast_parse_device_state (char *device) |
| Search the Channels by Name. | |
| int | ast_device_state (char *device) |
| Asks a channel for device state. | |
| ast_channel * | ast_request_and_dial (char *type, int format, void *data, int timeout, int *reason, char *callerid) |
| ast_channel * | __ast_request_and_dial (char *type, int format, void *data, int timeout, int *reason, char *callerid, struct outgoing_helper *oh) |
| int | ast_channel_register (char *type, char *description, int capabilities, struct ast_channel *(*requester)(char *type, int format, void *data)) |
| Registers a channel. | |
| int | ast_channel_register_ex (char *type, char *description, int capabilities, struct ast_channel *(*requester)(char *type, int format, void *data), int(*devicestate)(void *data)) |
| void | ast_channel_unregister (char *type) |
| Unregister a channel class. | |
| int | ast_hangup (struct ast_channel *chan) |
| Hang up a channel. | |
| int | ast_softhangup (struct ast_channel *chan, int cause) |
| Softly hangup up a channel. | |
| int | ast_softhangup_nolock (struct ast_channel *chan, int cause) |
| int | ast_check_hangup (struct ast_channel *chan) |
| Check to see if a channel is needing hang up. | |
| void | ast_channel_setwhentohangup (struct ast_channel *chan, time_t offset) |
| Set when to hang a channel up. | |
| int | ast_answer (struct ast_channel *chan) |
| Answer a ringing call. | |
| int | ast_call (struct ast_channel *chan, char *addr, int timeout) |
| Make a call. | |
| int | ast_indicate (struct ast_channel *chan, int condition) |
| Indicates condition of channel. | |
| int | ast_waitfor (struct ast_channel *chan, int ms) |
| Wait for input on a channel. | |
| int | ast_safe_sleep (struct ast_channel *chan, int ms) |
| Wait for a specied amount of time, looking for hangups. | |
| int | ast_safe_sleep_conditional (struct ast_channel *chan, int ms, int(*cond)(void *), void *data) |
| Wait for a specied amount of time, looking for hangups and a condition argument. | |
| ast_channel * | ast_waitfor_nandfds (struct ast_channel **chan, int n, int *fds, int nfds, int *exception, int *outfd, int *ms) |
| Waits for activity on a group of channels. | |
| ast_channel * | ast_waitfor_n (struct ast_channel **chan, int n, int *ms) |
| Waits for input on a group of channels. | |
| int | ast_waitfor_n_fd (int *fds, int n, int *ms, int *exception) |
| Waits for input on an fd. | |
| ast_frame * | ast_read (struct ast_channel *chan) |
| Reads a frame. | |
| int | ast_write (struct ast_channel *chan, struct ast_frame *frame) |
| Write a frame to a channel. | |
| int | ast_write_video (struct ast_channel *chan, struct ast_frame *frame) |
| Write video frame to a channel. | |
| int | ast_prod (struct ast_channel *chan) |
| int | ast_set_read_format (struct ast_channel *chan, int format) |
| Sets read format on channel chan. | |
| int | ast_set_write_format (struct ast_channel *chan, int format) |
| Sets write format on channel chan. | |
| int | ast_sendtext (struct ast_channel *chan, char *text) |
| Sends text to a channel. | |
| int | ast_senddigit (struct ast_channel *chan, char digit) |
| Receives a text character from a channel. | |
| int | ast_recvchar (struct ast_channel *chan, int timeout) |
| ast_channel * | ast_channel_walk_locked (struct ast_channel *prev) |
| Browse channels in use. | |
| ast_channel * | ast_get_channel_by_name_locked (char *channame) |
| Get channel by name (locks channel). | |
| int | ast_waitfordigit (struct ast_channel *c, int ms) |
| Waits for a digit. | |
| int | ast_waitfordigit_full (struct ast_channel *c, int ms, int audiofd, int ctrlfd) |
| int | ast_readstring (struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders) |
| Reads multiple digits. | |
| int | ast_readstring_full (struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders, int audiofd, int ctrlfd) |
| int | ast_channel_make_compatible (struct ast_channel *c0, struct ast_channel *c1) |
| Makes two channel formats compatible. | |
| int | ast_channel_bridge (struct ast_channel *c0, struct ast_channel *c1, struct ast_bridge_config *config, struct ast_frame **fo, struct ast_channel **rc) |
| Bridge two channels together. | |
| int | ast_channel_masquerade (struct ast_channel *original, struct ast_channel *clone) |
| Weird function made for call transfers. | |
| char * | ast_state2str (int state) |
| Gives the string form of a given state. | |
| int | ast_channel_setoption (struct ast_channel *channel, int option, void *data, int datalen, int block) |
| Sets an option on a channel. | |
| ast_frame * | ast_channel_queryoption (struct ast_channel *channel, int option, void *data, int *datalen, int block) |
| Checks the value of an option. | |
| int | ast_channel_supports_html (struct ast_channel *channel) |
| Checks for HTML support on a channel. | |
| int | ast_channel_sendhtml (struct ast_channel *channel, int subclass, char *data, int datalen) |
| Sends HTML on given channel. | |
| int | ast_channel_sendurl (struct ast_channel *channel, char *url) |
| Sends a URL on a given link. | |
| int | ast_channel_defer_dtmf (struct ast_channel *chan) |
| Defers DTMF. | |
| void | ast_channel_undefer_dtmf (struct ast_channel *chan) |
| Undeos a defer. | |
| void | ast_begin_shutdown (int hangup) |
| void | ast_cancel_shutdown (void) |
| int | ast_active_channels (void) |
| int | ast_shutting_down (void) |
| int | ast_activate_generator (struct ast_channel *chan, struct ast_generator *gen, void *params) |
| void | ast_deactivate_generator (struct ast_channel *chan) |
| void | ast_set_callerid (struct ast_channel *chan, char *callerid, int anitoo) |
| int | ast_tonepair_start (struct ast_channel *chan, int freq1, int freq2, int duration, int vol) |
| void | ast_tonepair_stop (struct ast_channel *chan) |
| int | ast_tonepair (struct ast_channel *chan, int freq1, int freq2, int duration, int vol) |
| int | ast_autoservice_start (struct ast_channel *chan) |
| int | ast_autoservice_stop (struct ast_channel *chan) |
| int | ast_settimeout (struct ast_channel *c, int samples, int(*func)(void *data), void *data) |
| int | ast_transfer (struct ast_channel *chan, char *dest) |
| int | ast_do_masquerade (struct ast_channel *chan) |
| unsigned int | ast_get_group (char *s) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Report DTMF on channel 0 Definition at line 669 of file channel.h. Referenced by ast_channel_bridge(), and ast_rtp_bridge(). |
|
|
Report DTMF on channel 1 Definition at line 671 of file channel.h. Referenced by ast_channel_bridge(), and ast_rtp_bridge(). |
|
|
Ignore all signal frames except NULL Definition at line 677 of file channel.h. Referenced by ast_channel_bridge(). |
|
|
Return all voice frames on channel 0 |
|
|
Return all voice frames on channel 1 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Definition at line 42 of file channel.h. Referenced by pbx_exec(). |
|
|
Definition at line 41 of file channel.h. Referenced by ast_channel_free(), and ast_parse_device_state(). |
|
|
Device is busy |
|
|
Device is in use Definition at line 357 of file channel.h. Referenced by ast_parse_device_state(). |
|
|
Device is invalid Definition at line 361 of file channel.h. Referenced by ast_device_state(). |
|
|
Device is not used |
|
|
Device is unavailable |
|
|
Device is valid but channel didn't know state Definition at line 353 of file channel.h. Referenced by ast_device_state(), and ast_parse_device_state(). |
|
|
|
|
|
Max length of an extension.
Definition at line 35 of file channel.h. Referenced by ast_cdr_init(), ast_cdr_setcid(), ast_cdr_update(), ast_device_state(), and ast_device_state_changed(). |
|
|
Definition at line 47 of file channel.h. Referenced by ast_channel_alloc(), ast_do_masquerade(), ast_read(), and ast_waitfor_nandfds(). |
|
|
|
|
|
Definition at line 320 of file channel.h. Referenced by ast_async_goto(), and ast_pbx_run(). |
|
|
Definition at line 319 of file channel.h. Referenced by ast_do_masquerade(), ast_dsp_process(), ast_queue_hangup(), ast_read(), and ast_write(). |
|
|
|
|
|
Definition at line 321 of file channel.h. Referenced by ast_begin_shutdown(). |
|
|
Definition at line 322 of file channel.h. Referenced by ast_check_hangup(), ast_pbx_run(), and ast_waitfor_nandfds(). |
|
|
Line is busy Definition at line 342 of file channel.h. Referenced by ast_state2str(). |
|
|
Digits (or equivalent) have been dialed Definition at line 334 of file channel.h. Referenced by ast_state2str(). |
|
|
Digits (or equivalent) have been dialed while offhook |
|
|
Channel is down and available Definition at line 328 of file channel.h. Referenced by ast_channel_alloc(), ast_request(), ast_setstate(), and ast_state2str(). |
|
|
Do not transmit voice data |
|
|
Channel is off hook Definition at line 332 of file channel.h. Referenced by ast_state2str(). |
|
|
Channel has detected an incoming call and is waiting for ring |
|
|
Channel is down, but reserved Definition at line 330 of file channel.h. Referenced by ast_state2str(). |
|
|
Line is ringing Definition at line 336 of file channel.h. Referenced by ast_answer(), and ast_state2str(). |
|
|
Remote end is ringing Definition at line 338 of file channel.h. Referenced by ast_answer(), and ast_state2str(). |
|
|
Line is up Definition at line 340 of file channel.h. Referenced by __ast_request_and_dial(), ast_answer(), ast_cdr_init(), ast_control_streamfile(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), ast_prod(), ast_read(), and ast_state2str(). |
|
|
Definition at line 883 of file channel.h. Referenced by ast_sendtext(), ast_waitfor_nandfds(), and ast_write(). |
|
|
Definition at line 880 of file channel.h. Referenced by ast_hangup(), ast_queue_frame(), ast_rtcp_read(), ast_rtp_read(), and ast_sched_del(). |
|
|
Definition at line 291 of file channel.h. Referenced by ast_pbx_outgoing_exten(). |
|
|
Definition at line 44 of file channel.h. Referenced by ast_fileexists(), and ast_openvstream(). |
|
||||||||||||||||||||||||||||||||
|
Definition at line 1758 of file channel.c. References ast_channel::_state, ast_call(), ast_cdr_alloc(), ast_cdr_disposition(), ast_cdr_end(), ast_cdr_failed(), ast_cdr_init(), ast_cdr_setaccount(), ast_cdr_setapp(), ast_cdr_start(), ast_cdr_update(), AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_FRAME_CONTROL, ast_frfree(), ast_hangup(), ast_log(), ast_read(), ast_request(), ast_set_callerid(), AST_STATE_UP, ast_waitfor(), ast_channel::callerid, ast_channel::cdr, ast_channel::context, ast_channel::exten, ast_frame::frametype, ast_channel::hangupcause, LOG_NOTICE, LOG_WARNING, pbx_builtin_setvar(), ast_channel::priority, and ast_frame::subclass. Referenced by ast_pbx_outgoing_exten(), and ast_request_and_dial(). 01759 { 01760 int state = 0; 01761 struct ast_channel *chan; 01762 struct ast_frame *f; 01763 int res = 0; 01764 char *variable; 01765 chan = ast_request(type, format, data); 01766 if (chan) { 01767 if (oh) { 01768 char *tmp, *var; 01769 /* JDG chanvar */ 01770 if (oh->variable) 01771 variable = ast_strdupa(oh->variable); 01772 else 01773 variable = NULL; 01774 tmp = variable; 01775 /* FIXME replace this call with strsep NOT*/ 01776 while( (var = strtok_r(NULL, "|", &tmp)) ) { 01777 pbx_builtin_setvar( chan, var ); 01778 } /* /JDG */ 01779 if (oh->callerid && *oh->callerid) 01780 ast_set_callerid(chan, oh->callerid, 1); 01781 if (oh->account && *oh->account) 01782 ast_cdr_setaccount(chan, oh->account); 01783 } 01784 if (callerid && !ast_strlen_zero(callerid)) 01785 ast_set_callerid(chan, callerid, 1); 01786 01787 if (!ast_call(chan, data, 0)) { 01788 while(timeout && (chan->_state != AST_STATE_UP)) { 01789 res = ast_waitfor(chan, timeout); 01790 if (res < 0) { 01791 /* Something not cool, or timed out */ 01792 break; 01793 } 01794 /* If done, break out */ 01795 if (!res) 01796 break; 01797 if (timeout > -1) 01798 timeout = res; 01799 f = ast_read(chan); 01800 if (!f) { 01801 state = AST_CONTROL_HANGUP; 01802 res = 0; 01803 break; 01804 } 01805 if (f->frametype == AST_FRAME_CONTROL) { 01806 if (f->subclass == AST_CONTROL_RINGING) 01807 state = AST_CONTROL_RINGING; 01808 else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) { 01809 state = f->subclass; 01810 ast_frfree(f); 01811 break; 01812 } else if (f->subclass == AST_CONTROL_ANSWER) { 01813 state = f->subclass; 01814 ast_frfree(f); 01815 break; 01816 } else if (f->subclass == AST_CONTROL_PROGRESS) { 01817 /* Ignore */ 01818 } else if (f->subclass == -1) { 01819 /* Ignore -- just stopping indications */ 01820 } else { 01821 ast_log(LOG_NOTICE, "Don't know what to do with control frame %d\n", f->subclass); 01822 } 01823 } 01824 ast_frfree(f); 01825 } 01826 } else 01827 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data); 01828 } else 01829 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data); 01830 if (chan) { 01831 /* Final fixups */ 01832 if (oh) { 01833 if (oh->context && *oh->context) 01834 strncpy(chan->context, oh->context, sizeof(chan->context) - 1); 01835 if (oh->exten && *oh->exten) 01836 strncpy(chan->exten, oh->exten, sizeof(chan->exten) - 1); 01837 chan->priority = oh->priority; 01838 } 01839 if (chan->_state == AST_STATE_UP) 01840 state = AST_CONTROL_ANSWER; 01841 } 01842 if (outstate) 01843 *outstate = state; 01844 if (chan && res <= 0) { 01845 if (!chan->cdr) { 01846 chan->cdr = ast_cdr_alloc(); 01847 if (chan->cdr) 01848 ast_cdr_init(chan->cdr, chan); 01849 } 01850 if (chan->cdr) { 01851 char tmp[256]; 01852 snprintf(tmp, 256, "%s/%s", type, (char *)data); 01853 ast_cdr_setapp(chan->cdr,"Dial",tmp); 01854 ast_cdr_update(chan); 01855 ast_cdr_start(chan->cdr); 01856 ast_cdr_end(chan->cdr); 01857 /* If the cause wasn't handled properly */ 01858 if (ast_cdr_disposition(chan->cdr,chan->hangupcause)) 01859 ast_cdr_failed(chan->cdr); 01860 } else 01861 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n"); 01862 ast_hangup(chan); 01863 chan = NULL; 01864 } 01865 return chan; 01866 }
|
|
||||||||||||||||
|
Activate a given generator Definition at line 849 of file channel.c. References ast_generator::alloc, ast_mutex_lock, ast_mutex_unlock, ast_prod(), ast_settimeout(), ast_channel::generator, ast_channel::generatordata, ast_channel::lock, and ast_generator::release. Referenced by ast_linear_stream(), ast_playtones_start(), and ast_tonepair_start(). 00850 { 00851 int res = 0; 00852 ast_mutex_lock(&chan->lock); 00853 if (chan->generatordata) { 00854 if (chan->generator && chan->generator->release) 00855 chan->generator->release(chan, chan->generatordata); 00856 chan->generatordata = NULL; 00857 } 00858 ast_prod(chan); 00859 if ((chan->generatordata = gen->alloc(chan, params))) { 00860 ast_settimeout(chan, 160, generator_force, chan); 00861 chan->generator = gen; 00862 } else { 00863 res = -1; 00864 } 00865 ast_mutex_unlock(&chan->lock); 00866 return res; 00867 }
|
|
|
Returns number of active/allocated channels Definition at line 120 of file channel.c. References ast_mutex_lock, ast_mutex_unlock, and ast_channel::next. 00121 { 00122 struct ast_channel *c; 00123 int cnt = 0; 00124 ast_mutex_lock(&chlock); 00125 c = channels; 00126 while(c) { 00127 cnt++; 00128 c = c->next; 00129 } 00130 ast_mutex_unlock(&chlock); 00131 return cnt; 00132 }
|
|
|
Answer a ringing call.
Definition at line 785 of file channel.c. References ast_channel::_state, ast_channel_pvt::answer, ast_cdr_answer(), ast_check_hangup(), ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_channel::cdr, ast_channel::lock, ast_channel::pvt, and ast_channel::zombie. Referenced by ast_control_streamfile(). 00786 { 00787 int res = 0; 00788 ast_mutex_lock(&chan->lock); 00789 /* Stop if we're a zombie or need a soft hangup */ 00790 if (chan->zombie || ast_check_hangup(chan)) { 00791 ast_mutex_unlock(&chan->lock); 00792 return -1; 00793 } 00794 switch(chan->_state) { 00795 case AST_STATE_RINGING: 00796 case AST_STATE_RING: 00797 if (chan->pvt->answer) 00798 res = chan->pvt->answer(chan); 00799 ast_setstate(chan, AST_STATE_UP); 00800 if (chan->cdr) 00801 ast_cdr_answer(chan->cdr); 00802 ast_mutex_unlock(&chan->lock); 00803 return res; 00804 break; 00805 case AST_STATE_UP: 00806 if (chan->cdr) 00807 ast_cdr_answer(chan->cdr); 00808 break; 00809 } 00810 ast_mutex_unlock(&chan->lock); 00811 return 0; 00812 }
|
|
|
Automatically service a channel for us... Definition at line 88 of file autoservice.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_pthread_create(), AST_PTHREADT_NULL, asent::chan, free, LOG_WARNING, malloc, ast_channel::next, and asent::next. Referenced by ast_dtmf_stream(), ast_get_enum(), ast_get_srv(), and ast_get_txt(). 00089 { 00090 int res = -1; 00091 struct asent *as; 00092 int needstart; 00093 ast_mutex_lock(&autolock); 00094 needstart = (asthread == AST_PTHREADT_NULL) ? 1 : 0 /* aslist ? 0 : 1 */; 00095 as = aslist; 00096 while(as) { 00097 if (as->chan == chan) 00098 break; 00099 as = as->next; 00100 } 00101 if (!as) { 00102 as = malloc(sizeof(struct asent)); 00103 if (as) { 00104 memset(as, 0, sizeof(struct asent)); 00105 as->chan = chan; 00106 as->next = aslist; 00107 aslist = as; 00108 res = 0; 00109 if (needstart) { 00110 if (ast_pthread_create(&asthread, NULL, autoservice_run, NULL)) { 00111 ast_log(LOG_WARNING, "Unable to create autoservice thread :(\n"); 00112 free(aslist); 00113 aslist = NULL; 00114 res = -1; 00115 } else 00116 pthread_kill(asthread, SIGURG); 00117 } 00118 } 00119 } 00120 ast_mutex_unlock(&autolock); 00121 return res; 00122 }
|
|
|
Stop servicing a channel for us... Returns -1 on error or if channel has been hungup Definition at line 124 of file autoservice.c. References ast_channel::_softhangup, ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, ast_channel::blocking, asent::chan, free, and asent::next. Referenced by ast_dtmf_stream(), ast_get_enum(), ast_get_srv(), and ast_get_txt(). 00125 { 00126 int res = -1; 00127 struct asent *as, *prev; 00128 ast_mutex_lock(&autolock); 00129 as = aslist; 00130 prev = NULL; 00131 while(as) { 00132 if (as->chan == chan) 00133 break; 00134 prev = as; 00135 as = as->next; 00136 } 00137 if (as) { 00138 if (prev) 00139 prev->next = as->next; 00140 else 00141 aslist = as->next; 00142 free(as); 00143 if (!chan->_softhangup) 00144 res = 0; 00145 } 00146 if (asthread != AST_PTHREADT_NULL) 00147 pthread_kill(asthread, SIGURG); 00148 ast_mutex_unlock(&autolock); 00149 /* Wait for it to un-block */ 00150 while(chan->blocking) 00151 usleep(1000); 00152 return res; 00153 }
|
|
|
Initiate system shutdown -- prevents new channels from being allocated. If "hangup" is non-zero, all existing channels will receive soft hangups Definition at line 105 of file channel.c. References ast_mutex_lock, ast_mutex_unlock, ast_softhangup(), AST_SOFTHANGUP_SHUTDOWN, and ast_channel::next. 00106 { 00107 struct ast_channel *c; 00108 shutting_down = 1; 00109 if (hangup) { 00110 ast_mutex_lock(&chlock); 00111 c = channels; 00112 while(c) { 00113 ast_softhangup(c, AST_SOFTHANGUP_SHUTDOWN); 00114 c = c->next; 00115 } 00116 ast_mutex_unlock(&chlock); 00117 } 00118 }
|
|
||||||||||||||||
|
Make a call.
Definition at line 1977 of file channel.c. References ast_check_hangup(), ast_mutex_lock, ast_mutex_unlock, ast_channel_pvt::call, ast_channel::lock, ast_channel::pvt, and ast_channel::zombie. Referenced by __ast_request_and_dial(). 01978 { 01979 /* Place an outgoing call, but don't wait any longer than timeout ms before returning. 01980 If the remote end does not answer within the timeout, then do NOT hang up, but 01981 return anyway. */ 01982 int res = -1; 01983 /* Stop if we're a zombie or need a soft hangup */ 01984 ast_mutex_lock(&chan->lock); 01985 if (!chan->zombie && !ast_check_hangup(chan)) 01986 if (chan->pvt->call) 01987 res = chan->pvt->call(chan, addr, timeout); 01988 ast_mutex_unlock(&chan->lock); 01989 return res; 01990 }
|
|
|
Cancels an existing shutdown and returns to normal operation Definition at line 134 of file channel.c.
|
|
||||||||||||||||||||||||
|
Bridge two channels together.
Definition at line 2517 of file channel.c. References ast_bridge_config::allowdisconnect_in, ast_bridge_config::allowdisconnect_out, ast_bridge_config::allowredirect_in, ast_bridge_config::allowredirect_out, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_IGNORE_SIGS, ast_channel_make_compatible(), ast_check_hangup(), AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_HTML, AST_FRAME_IMAGE, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree(), ast_log(), ast_read(), ast_verbose(), ast_waitfor_n(), ast_write(), ast_channel::bridge, ast_bridge_config::end_sound, EVENT_FLAG_CALL, ast_bridge_config::firstpass, ast_frame::frametype, LOG_DEBUG, LOG_WARNING, manager_event(), ast_channel::name, option_verbose, ast_bridge_config::play_to_callee, ast_bridge_config::play_to_caller, ast_bridge_config::play_warning, ast_bridge_config::start_sound, ast_frame::subclass, ast_bridge_config::timelimit, VERBOSE_PREFIX_3, ast_bridge_config::warning_freq, and ast_bridge_config::warning_sound. 02518 { 02519 /* Copy voice back and forth between the two channels. Give the peer 02520 the ability to transfer calls with '#<extension' syntax. */ 02521 int flags; 02522 struct ast_channel *cs[3]; 02523 int to = -1; 02524 struct ast_frame *f; 02525 struct ast_channel *who = NULL; 02526 int res=0; 02527 int nativefailed=0; 02528 int firstpass; 02529 int o0nativeformats; 02530 int o1nativeformats; 02531 struct timeval start_time,precise_now; 02532 long elapsed_ms=0, time_left_ms=0; 02533 int playit=0, playitagain=1, first_time=1; 02534 02535 flags = (config->allowdisconnect_out||config->allowredirect_out ? AST_BRIDGE_DTMF_CHANNEL_0 : 0) + (config->allowdisconnect_in||config->allowredirect_in ? AST_BRIDGE_DTMF_CHANNEL_1 : 0); 02536 02537 firstpass = config->firstpass; 02538 config->firstpass = 0; 02539 02540 /* timestamp */ 02541 gettimeofday(&start_time,NULL); 02542 time_left_ms = config->timelimit; 02543 02544 if (config->play_to_caller && config->start_sound && firstpass) 02545 bridge_playfile(c0,c1,config->start_sound,time_left_ms / 1000); 02546 if (config->play_to_callee && config->start_sound && firstpass) 02547 bridge_playfile(c1,c0,config->start_sound,time_left_ms / 1000); 02548 02549 /* Stop if we're a zombie or need a soft hangup */ 02550 if (c0->zombie || ast_check_hangup_locked(c0) || c1->zombie || ast_check_hangup_locked(c1)) 02551 return -1; 02552 if (c0->bridge) { 02553 ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 02554 c0->name, c0->bridge->name); 02555 return -1; 02556 } 02557 if (c1->bridge) { 02558 ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 02559 c1->name, c1->bridge->name); 02560 return -1; 02561 } 02562 02563 /* Keep track of bridge */ 02564 c0->bridge = c1; 02565 c1->bridge = c0; 02566 cs[0] = c0; 02567 cs[1] = c1; 02568 02569 manager_event(EVENT_FLAG_CALL, "Link", 02570 "Channel1: %s\r\n" 02571 "Channel2: %s\r\n" 02572 "Uniqueid1: %s\r\n" 02573 "Uniqueid2: %s\r\n", 02574 c0->name, c1->name, c0->uniqueid, c1->uniqueid); 02575 o1nativeformats = c1->nativeformats; 02576 o0nativeformats = c0->nativeformats; 02577 for (/* ever */;;) { 02578 /* timestamp */ 02579 if (config->timelimit) { 02580 gettimeofday(&precise_now,NULL); 02581 elapsed_ms = tvdiff(&precise_now,&start_time); 02582 time_left_ms = config->timelimit - elapsed_ms; 02583 02584 if (playitagain && (config->play_to_caller || config->play_to_callee) && (config->play_warning && time_left_ms <= config->play_warning)) { 02585 /* narrowing down to the end */ 02586 if (config->warning_freq == 0) { 02587 playit = 1; 02588 first_time=0; 02589 playitagain=0; 02590 } else if (first_time) { 02591 playit = 1; 02592 first_time=0; 02593 } else { 02594 if ((time_left_ms % config->warning_freq) <= 50) { 02595 playit = 1; 02596 } 02597 } 02598 } 02599 if (time_left_ms <= 0) { 02600 if (config->play_to_caller && config->end_sound) 02601 bridge_playfile(c0,c1,config->end_sound,0); 02602 if (config->play_to_callee && config->end_sound) 02603 bridge_playfile(c1,c0,config->end_sound,0); 02604 *fo = NULL; 02605 if (who) *rc = who; 02606 res = 0; 02607 break; 02608 } 02609 if (time_left_ms >= 5000 && playit) { 02610 if (config->play_to_caller && config->warning_sound && config->play_warning) 02611 bridge_playfile(c0,c1,config->warning_sound,time_left_ms / 1000); 02612 if (config->play_to_callee && config->warning_sound && config->play_warning) 02613 bridge_playfile(c1,c0,config->warning_sound,time_left_ms / 1000); 02614 playit = 0; 02615 } 02616 02617 } 02618 /* Stop if we're a zombie or need a soft hangup */ 02619 if (c0->zombie || ast_check_hangup_locked(c0) || c1->zombie || ast_check_hangup_locked(c1)) { 02620 *fo = NULL; 02621 if (who) *rc = who; 02622 res = 0; 02623 ast_log(LOG_DEBUG, "Bridge stops because we're zombie or need a soft hangup: c0=%s, c1=%s, flags: %s,%s,%s,%s\n",c0->name,c1->name,c0->zombie?"Yes":"No",ast_check_hangup(c0)?"Yes":"No",c1->zombie?"Yes":"No",ast_check_hangup(c1)?"Yes":"No"); 02624 break; 02625 } 02626 if (c0->pvt->bridge && config->timelimit==0 && 02627 (c0->pvt->bridge == c1->pvt->bridge) && !nativefailed && !c0->monitor && !c1->monitor) { 02628 /* Looks like they share a bridge code */ 02629 if (option_verbose > 2) 02630 ast_verbose(VERBOSE_PREFIX_3 "Attempting native bridge of %s and %s\n", c0->name, c1->name); 02631 if (!(res = c0->pvt->bridge(c0, c1, flags, fo, rc))) { 02632 c0->bridge = NULL; 02633 c1->bridge = NULL; 02634 manager_event(EVENT_FLAG_CALL, "Unlink", 02635 "Channel1: %s\r\n" 02636 "Channel2: %s\r\n" 02637 "Uniqueid1: %s\r\n" 02638 "Uniqueid2: %s\r\n", 02639 c0->name, c1->name, c0->uniqueid, c1->uniqueid); 02640 ast_log(LOG_DEBUG, "Returning from native bridge, channels: %s, %s\n",c0->name ,c1->name); 02641 return 0; 02642 } 02643 /* If they return non-zero then continue on normally. Let "-2" mean don't worry about 02644 my not wanting to bridge */ 02645 if ((res != -2) && (res != -3)) 02646 ast_log(LOG_WARNING, "Private bridge between %s and %s failed\n", c0->name, c1->name); 02647 if (res != -3) nativefailed++; 02648 } 02649 02650 if (((c0->writeformat != c1->readformat) || (c0->readformat != c1->writeformat) || (c0->nativeformats != o0nativeformats) || (c1->nativeformats != o1nativeformats)) && 02651 !(c0->generator || c1->generator)) { 02652 if (ast_channel_make_compatible(c0, c1)) { 02653 ast_log(LOG_WARNING, "Can't make %s and %s compatible\n", c0->name, c1->name); 02654 manager_event(EVENT_FLAG_CALL, "Unlink", 02655 "Channel1: %s\r\n" 02656 "Channel2: %s\r\n" 02657 "Uniqueid1: %s\r\n" 02658 "Uniqueid2: %s\r\n", 02659 c0->name, c1->name, c0->uniqueid, c1->uniqueid); 02660 return -1; 02661 } 02662 o0nativeformats = c0->nativeformats; 02663 o1nativeformats = c1->nativeformats; 02664 } 02665 who = ast_waitfor_n(cs, 2, &to); 02666 if (!who) { 02667 ast_log(LOG_DEBUG, "Nobody there, continuing...\n"); 02668 continue; 02669 } 02670 f = ast_read(who); 02671 if (!f) { 02672 *fo = NULL; 02673 *rc = who; 02674 res = 0; 02675 ast_log(LOG_DEBUG, "Didn't get a frame from channel: %s\n",who->name); 02676 break; 02677 } 02678 02679 if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 02680 *fo = f; 02681 *rc = who; 02682 res = 0; 02683 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", f->subclass, who->name); 02684 break; 02685 } 02686 if ((f->frametype == AST_FRAME_VOICE) || 02687 (f->frametype == AST_FRAME_TEXT) || 02688 (f->frametype == AST_FRAME_VIDEO) || 02689 (f->frametype == AST_FRAME_IMAGE) || 02690 (f->frametype == AST_FRAME_HTML) || 02691 (f->frametype == AST_FRAME_DTMF)) { 02692 if ((f->frametype == AST_FRAME_DTMF) && 02693 (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))) { 02694 if ((who == c0)) { 02695 if ((flags & AST_BRIDGE_DTMF_CHANNEL_0)) { 02696 *rc = c0; 02697 *fo = f; 02698 /* Take out of conference mode */ 02699 res = 0; 02700 ast_log(LOG_DEBUG, "Got AST_BRIDGE_DTMF_CHANNEL_0 on c0 (%s)\n",c0->name); 02701 break; 02702 } else 02703 goto tackygoto; 02704 } else 02705 if ((who == c1)) { 02706 if (flags & AST_BRIDGE_DTMF_CHANNEL_1) { 02707 *rc = c1; 02708 *fo = f; 02709 res = 0; 02710 ast_log(LOG_DEBUG, "Got AST_BRIDGE_DTMF_CHANNEL_1 on c1 (%s)\n",c1->name); 02711 break; 02712 } else 02713 goto tackygoto; 02714 } 02715 } else { 02716 #if 0 02717 ast_log(LOG_DEBUG, "Read from %s\n", who->name); 02718 if (who == last) 02719 ast_log(LOG_DEBUG, "Servicing channel %s twice in a row?\n", last->name); 02720 last = who; 02721 #endif 02722 tackygoto: 02723 /* Don't copy packets if there is a generator on either one, since they're 02724 not supposed to be listening anyway */ 02725 if (who == c0) 02726 ast_write(c1, f); 02727 else 02728 ast_write(c0, f); 02729 } 02730 ast_frfree(f); 02731 } else 02732 ast_frfree(f); 02733 /* Swap who gets priority */ 02734 cs[2] = cs[0]; 02735 cs[0] = cs[1]; 02736 cs[1] = cs[2]; 02737 } 02738 c0->bridge = NULL; 02739 c1->bridge = NULL; 02740 manager_event(EVENT_FLAG_CALL, "Unlink", 02741 "Channel1: %s\r\n" 02742 "Channel2: %s\r\n" 02743 "Uniqueid1: %s\r\n" 02744 "Uniqueid2: %s\r\n", 02745 c0->name, c1->name, c0->uniqueid, c1->uniqueid); 02746 ast_log(LOG_DEBUG, "Bridge stops bridging channels %s and %s\n",c0->name,c1->name); 02747 return res; 02748 }
|
|
|
Defers DTMF. Defer DTMF so that you only read things like hangups and audio. Returns non-zero if channel was already DTMF-deferred or 0 if channel is just now being DTMF-deferred Definition at line 441 of file channel.c. References ast_channel::deferdtmf. 00442 { 00443 int pre = 0; 00444 if (chan) { 00445 pre = chan->deferdtmf; 00446 chan->deferdtmf = 1; 00447 } 00448 return pre; 00449 }
|
|
||||||||||||
|
Makes two channel formats compatible.
Definition at line 2114 of file channel.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_set_read_format(), ast_set_write_format(), ast_translator_best_choice(), ast_channel::lock, LOG_WARNING, ast_channel::name, and ast_channel::nativeformats. Referenced by ast_channel_bridge(). 02115 { 02116 int peerf; 02117 int chanf; 02118 int res; 02119 ast_mutex_lock(&peer->lock); 02120 peerf = peer->nativeformats; 02121 ast_mutex_unlock(&peer->lock); 02122 ast_mutex_lock(&chan->lock); 02123 chanf = chan->nativeformats; 02124 ast_mutex_unlock(&chan->lock); 02125 res = ast_translator_best_choice(&peerf, &chanf); 02126 if (res < 0) { 02127 ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", chan->name, chan->nativeformats, peer->name, peer->nativeformats); 02128 return -1; 02129 } 02130 /* Set read format on channel */ 02131 res = ast_set_read_format(chan, peerf); 02132 if (res < 0) { 02133 ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", chan->name, chanf); 02134 return -1; 02135 } 02136 /* Set write format on peer channel */ 02137 res = ast_set_write_format(peer, peerf); 02138 if (res < 0) { 02139 ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", peer->name, peerf); 02140 return -1; 02141 } 02142 /* Now we go the other way */ 02143 peerf = peer->nativeformats; 02144 chanf = chan->nativeformats; 02145 res = ast_translator_best_choice(&chanf, &peerf); 02146 if (res < 0) { 02147 ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", peer->name, peer->nativeformats, chan->name, chan->nativeformats); 02148 return -1; 02149 } 02150 /* Set writeformat on channel */ 02151 res = ast_set_write_format(chan, chanf); 02152 if (res < 0) { 02153 ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", chan->name, chanf); 02154 return -1; 02155 } 02156 /* Set read format on peer channel */ 02157 res = ast_set_read_format(peer, chanf); 02158 if (res < 0) { 02159 ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", peer->name, peerf); 02160 return -1; 02161 } 02162 return 0; 02163 }
|
|
||||||||||||
|
Weird function made for call transfers.
Definition at line 2165 of file channel.c. References AST_FRAME_NULL, ast_log(), ast_mutex_lock, ast_mutex_trylock, ast_mutex_unlock, ast_queue_frame(), ast_channel::lock, LOG_DEBUG, LOG_WARNING, ast_channel::masq, ast_channel::masqr, and ast_channel::name. Referenced by ast_async_goto(). 02166 { 02167 struct ast_frame null = { AST_FRAME_NULL, }; 02168 int res = -1; 02169 ast_mutex_lock(&original->lock); 02170 while(ast_mutex_trylock(&clone->lock)) { 02171 ast_mutex_unlock(&original->lock); 02172 usleep(1); 02173 ast_mutex_lock(&original->lock); 02174 } 02175 ast_log(LOG_DEBUG, "Planning to masquerade %s into the structure of %s\n", 02176 clone->name, original->name); 02177 if (original->masq) { 02178 ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 02179 original->masq->name, original->name); 02180 } else if (clone->masqr) { 02181 ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 02182 clone->name, clone->masqr->name); 02183 } else { 02184 original->masq = clone; 02185 clone->masqr = original; 02186 ast_queue_frame(original, &null); 02187 ast_queue_frame(clone, &null); 02188 ast_log(LOG_DEBUG, "Done planning to masquerade %s into the structure of %s\n", original->name, clone->name); 02189 res = 0; 02190 } 02191 ast_mutex_unlock(&clone->lock); 02192 ast_mutex_unlock(&original->lock); 02193 return res; 02194 }
|
|
||||||||||||||||||||||||
|
Checks the value of an option. Query the value of an option, optionally blocking until a reply is received Works similarly to setoption except only reads the options. |
|
||||||||||||||||||||
|
Registers a channel.
Definition at line 156 of file channel.c. References ast_channel_register_ex(). 00158 { 00159 return ast_channel_register_ex(type, description, capabilities, requester, NULL); 00160 }
|
|
||||||||||||||||||||||||
|
Definition at line 162 of file channel.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), backends, chanlist::capabilities, chanlist::description, chanlist::devicestate, LOG_DEBUG, LOG_WARNING, malloc, chanlist::next, option_debug, option_verbose, chanlist::requester, chanlist::type, and VERBOSE_PREFIX_2. Referenced by ast_channel_register(). 00165 { 00166 struct chanlist *chan, *last=NULL; 00167 if (ast_mutex_lock(&chlock)) { 00168 ast_log(LOG_WARNING, "Unable to lock channel list\n"); 00169 return -1; 00170 } 00171 chan = backends; 00172 while (chan) { 00173 if (!strcasecmp(type, chan->type)) { 00174 ast_log(LOG_WARNING, "Already have a handler for type '%s'\n", type); 00175 ast_mutex_unlock(&chlock); 00176 return -1; 00177 } 00178 last = chan; 00179 chan = chan->next; 00180 } 00181 chan = malloc(sizeof(struct chanlist)); 00182 if (!chan) { 00183 ast_log(LOG_WARNING, "Out of memory\n"); 00184 ast_mutex_unlock(&chlock); 00185 return -1; 00186 } 00187 strncpy(chan->type, type, sizeof(chan->type)-1); 00188 strncpy(chan->description, description, sizeof(chan->description)-1); 00189 chan->capabilities = capabilities; 00190 chan->requester = requester; 00191 chan->devicestate = devicestate; 00192 chan->next = NULL; 00193 if (last) 00194 last->next = chan; 00195 else 00196 backends = chan; 00197 if (option_debug) 00198 ast_log(LOG_DEBUG, "Registered handler for '%s' (%s)\n", chan->type, chan->description); 00199 else if (option_verbose > 1) 00200 ast_verbose( VERBOSE_PREFIX_2 "Registered channel type '%s' (%s)\n", chan->type, chan->description); 00201 ast_mutex_unlock(&chlock); 00202 return 0; 00203 }
|
|
||||||||||||||||||||
|
Sends HTML on given channel. Send HTML or URL on link. Returns 0 on success or -1 on failure Definition at line 2100 of file channel.c. References ast_channel::pvt, and ast_channel_pvt::send_html. 02101 { 02102 if (chan->pvt->send_html) 02103 return chan->pvt->send_html(chan, subclass, data, datalen); 02104 return -1; 02105 }
|
|
||||||||||||
|
Sends a URL on a given link. Send URL on link. Returns 0 on success or -1 on failure Definition at line 2107 of file channel.c. References AST_HTML_URL, ast_channel::pvt, and ast_channel_pvt::send_html. 02108 { 02109 if (chan->pvt->send_html) 02110 return chan->pvt->send_html(chan, AST_HTML_URL, url, strlen(url) + 1); 02111 return -1; 02112 }
|
|
||||||||||||||||||||||||
|
Sets an option on a channel.
Definition at line 2750 of file channel.c. References ast_log(), LOG_ERROR, ast_channel::pvt, and ast_channel_pvt::setoption. 02751 { 02752 int res; 02753 if (chan->pvt->setoption) { 02754 res = chan->pvt->setoption(chan, option, data, datalen); 02755 if (res < 0) 02756 return res; 02757 } else { 02758 errno = ENOSYS; 02759 return -1; 02760 } 02761 if (block) { 02762 /* XXX Implement blocking -- just wait for our option frame reply, discarding 02763 intermediate packets. XXX */ 02764 ast_log(LOG_ERROR, "XXX Blocking not implemented yet XXX\n"); 02765 return -1; 02766 } 02767 return 0; 02768 }
|
|
||||||||||||
|
Set when to hang a channel up.
Definition at line 144 of file channel.c. References ast_channel::whentohangup. 00145 { 00146 time_t myt; 00147 00148 time(&myt); 00149 if (offset) 00150 chan->whentohangup = myt + offset; 00151 else 00152 chan->whentohangup = 0; 00153 return; 00154 }
|
|
|
Checks for HTML support on a channel. Returns 0 if channel does not support HTML or non-zero if it does Definition at line 2093 of file channel.c. References ast_channel::pvt, and ast_channel_pvt::send_html.
|
|
|
Undeos a defer. Undo defer. ast_read will return any dtmf characters that were queued Definition at line 451 of file channel.c. References ast_channel::deferdtmf.
|
|
|
Unregister a channel class.
Definition at line 756 of file channel.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), backends, free, LOG_DEBUG, LOG_WARNING, chanlist::next, option_debug, option_verbose, chanlist::type, and VERBOSE_PREFIX_2. 00757 { 00758 struct chanlist *chan, *last=NULL; 00759 if (option_debug) 00760 ast_log(LOG_DEBUG, "Unregistering channel type '%s'\n", type); 00761 if (ast_mutex_lock(&chlock)) { 00762 ast_log(LOG_WARNING, "Unable to lock channel list\n"); 00763 return; 00764 } 00765 if (option_verbose > 1) 00766 ast_verbose( VERBOSE_PREFIX_2 "Unregistered channel type '%s'\n", type); 00767 00768 chan = backends; 00769 while(chan) { 00770 if (!strcasecmp(chan->type, type)) { 00771 if (last) 00772 last->next = chan->next; 00773 else 00774 backends = backends->next; 00775 free(chan); 00776 ast_mutex_unlock(&chlock); 00777 return; 00778 } 00779 last = chan; 00780 chan = chan->next; 00781 } 00782 ast_mutex_unlock(&chlock); 00783 }
|
|
|
Browse channels in use.
Definition at line 457 of file channel.c. References ast_log(), ast_mutex_lock, ast_mutex_trylock, ast_mutex_unlock, ast_channel::lock, LOG_DEBUG, LOG_WARNING, ast_channel::name, and ast_channel::next. Referenced by ast_async_goto_by_name(), ast_get_channel_by_name_locked(), and ast_parse_device_state(). 00458 { 00459 /* Returns next channel (locked) */ 00460 struct ast_channel *l, *ret; 00461 int retries = 0; 00462 retry: 00463 ret=NULL; 00464 ast_mutex_lock(&chlock); 00465 l = channels; 00466 if (!prev) { 00467 if (l) { 00468 if (ast_mutex_trylock(&l->lock)) { 00469 if (retries < 10) 00470 ast_log(LOG_DEBUG, "Avoiding initial deadlock for '%s'\n", l->name); 00471 else 00472 ast_log(LOG_WARNING, "Avoided initial deadlock for '%s', %d retries!\n", l->name, retries); 00473 ast_mutex_unlock(&chlock); 00474 if (retries < 10) { 00475 usleep(1); 00476 retries++; 00477 goto retry; 00478 } else 00479 return NULL; 00480 } 00481 } 00482 ast_mutex_unlock(&chlock); 00483 return l; 00484 } 00485 while(l) { 00486 if (l == prev) 00487 ret = l->next; 00488 l = l->next; 00489 } 00490 if (ret) { 00491 if (ast_mutex_trylock(&ret->lock)) { 00492 if (retries < 10) 00493 ast_log(LOG_DEBUG, "Avoiding deadlock for '%s'\n", ret->name); 00494 else 00495 ast_log(LOG_WARNING, "Avoided deadlock for '%s', %d retries!\n", ret->name, retries); 00496 ast_mutex_unlock(&chlock); 00497 if (retries < 10) { 00498 usleep(1); 00499 retries++; 00500 goto retry; 00501 } else 00502 return NULL; 00503 } 00504 } 00505 ast_mutex_unlock(&chlock); 00506 return ret; 00507 00508 }
|
|
|
Check to see if a channel is needing hang up.
Definition at line 79 of file channel.c. References ast_channel::_softhangup, AST_SOFTHANGUP_TIMEOUT, ast_channel_pvt::pvt, ast_channel::pvt, and ast_channel::whentohangup. Referenced by ast_answer(), ast_call(), ast_channel_bridge(), ast_indicate(), ast_read(), ast_readstring(), ast_readstring_full(), ast_recvchar(), ast_rtp_bridge(), ast_sendtext(), ast_transfer(), ast_waitfordigit(), ast_waitfordigit_full(), and ast_write(). 00080 { 00081 time_t myt; 00082 00083 /* if soft hangup flag, return true */ 00084 if (chan->_softhangup) return 1; 00085 /* if no private structure, return true */ 00086 if (!chan->pvt->pvt) return 1; 00087 /* if no hangup scheduled, just return here */ 00088 if (!chan->whentohangup) return 0; 00089 time(&myt); /* get current time */ 00090 /* return, if not yet */ 00091 if (chan->whentohangup > myt) return 0; 00092 chan->_softhangup |= AST_SOFTHANGUP_TIMEOUT; 00093 return 1; 00094 }
|
|
|
Deactive an active generator Definition at line 816 of file channel.c. References ast_mutex_lock, ast_mutex_unlock, ast_settimeout(), ast_channel::generator, ast_channel::generatordata, ast_channel::lock, ast_generator::release, and ast_channel::writeinterrupt. Referenced by ast_openstream(), ast_playtones_stop(), ast_read(), ast_tonepair_stop(), and ast_write(). 00817 { 00818 ast_mutex_lock(&chan->lock); 00819 if (chan->generatordata) { 00820 if (chan->generator && chan->generator->release) 00821 chan->generator->release(chan, chan->generatordata); 00822 chan->generatordata = NULL; 00823 chan->generator = NULL; 00824 chan->writeinterrupt = 0; 00825 ast_settimeout(chan, 0, NULL, NULL); 00826 } 00827 ast_mutex_unlock(&chan->lock); 00828 }
|
|
|
Asks a channel for device state.
Definition at line 1938 of file channel.c. References AST_DEVICE_INVALID, AST_DEVICE_UNKNOWN, ast_log(), AST_MAX_EXTENSION, ast_mutex_lock, ast_mutex_unlock, ast_parse_device_state(), backends, chanlist::devicestate, LOG_WARNING, chanlist::next, and chanlist::type. 01939 { 01940 char tech[AST_MAX_EXTENSION] = ""; 01941 char *number; 01942 struct chanlist *chanls; 01943 int res = 0; 01944 01945 strncpy(tech, device, sizeof(tech)-1); 01946 number = strchr(tech, '/'); 01947 if (!number) { 01948 return AST_DEVICE_INVALID; 01949 } 01950 *number = 0; 01951 number++; 01952 01953 if (ast_mutex_lock(&chlock)) { 01954 ast_log(LOG_WARNING, "Unable to lock channel list\n"); 01955 return -1; 01956 } 01957 chanls = backends; 01958 while(chanls) { 01959 if (!strcasecmp(tech, chanls->type)) { 01960 ast_mutex_unlock(&chlock); 01961 if (!chanls->devicestate) 01962 return ast_parse_device_state(device); 01963 else { 01964 res = chanls->devicestate(number); 01965 if (res == AST_DEVICE_UNKNOWN) 01966 return ast_parse_device_state(device); 01967 else 01968 return res; 01969 } 01970 } 01971 chanls = chanls->next; 01972 } 01973 ast_mutex_unlock(&chlock); 01974 return AST_DEVICE_INVALID; 01975 }
|
|
|
Definition at line 2204 of file channel.c. References ast_channel::_softhangup, ast_channel::_state, ast_channel::adsicpe, ast_channel_pvt::alertpipe, ast_channel_free(), AST_FRAME_NULL, ast_log(), AST_MAX_FDS, ast_mutex_lock, ast_mutex_unlock, ast_queue_frame(), ast_set_read_format(), ast_set_write_format(), AST_SOFTHANGUP_DEV, ast_channel::blocker, ast_channel::blocking, ast_channel::callerid, ast_channel::dnid, EVENT_FLAG_CALL, ast_channel::exception, ast_channel::fdno, ast_channel::fds, ast_channel_pvt::fixup, ast_channel_pvt::hangup, ast_channel::language, ast_channel::lock, LOG_DEBUG, LOG_WARNING, manager_event(), ast_channel::masq, ast_channel::masqr, ast_channel::musicclass, ast_channel::name, ast_channel::nativeformats, ast_frame::next, ast_frame::prev, ast_channel::pvt, ast_channel::readformat, ast_channel_pvt::readq, ast_channel::timingfd, ast_channel::type, ast_channel::uniqueid, ast_channel::writeformat, and ast_channel::zombie. Referenced by ast_async_goto(), ast_hangup(), ast_read(), ast_waitfor_nandfds(), and ast_write(). 02205 { 02206 int x,i; 02207 int res=0; 02208 int origstate; 02209 char *tmp; 02210 struct ast_var_t *varptr; 02211 struct ast_frame *cur, *prev; 02212 struct ast_channel_pvt *p; 02213 struct ast_channel *clone = original->masq; 02214 int rformat = original->readformat; 02215 int wformat = original->writeformat; 02216 char newn[100]; 02217 char orig[100]; 02218 char masqn[100]; 02219 char zombn[100]; 02220 02221 #if 1 02222 ast_log(LOG_DEBUG, "Actually Masquerading %s(%d) into the structure of %s(%d)\n", 02223 clone->name, clone->_state, original->name, original->_state); 02224 #endif 02225 /* XXX This is a seriously wacked out operation. We're essentially putting the guts of 02226 the clone channel into the original channel. Start by killing off the original 02227 channel's backend. I'm not sure we're going to keep this function, because 02228 while the features are nice, the cost is very high in terms of pure nastiness. XXX */ 02229 02230 /* We need the clone's lock, too */ 02231 ast_mutex_lock(&clone->lock); 02232 02233 ast_log(LOG_DEBUG, "Got clone lock on '%s' at %p\n", clone->name, &clone->lock); 02234 02235 /* Having remembered the original read/write formats, we turn off any translation on either 02236 one */ 02237 free_translation(clone); 02238 free_translation(original); 02239 02240 02241 /* Unlink the masquerade */ 02242 original->masq = NULL; 02243 clone->masqr = NULL; 02244 02245 /* Save the original name */ 02246 strncpy(orig, original->name, sizeof(orig) - 1); 02247 /* Save the new name */ 02248 strncpy(newn, clone->name, sizeof(newn) - 1); 02249 /* Create the masq name */ 02250 snprintf(masqn, sizeof(masqn), "%s<MASQ>", newn); 02251 02252 /* Copy the name from the clone channel */ 02253 strncpy(original->name, newn, sizeof(original->name)-1); 02254 02255 /* Mangle the name of the clone channel */ 02256 strncpy(clone->name, masqn, sizeof(clone->name) - 1); 02257 02258 /* Notify any managers of the change, first the masq then the other */ 02259 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", newn, masqn, clone->uniqueid); 02260 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", orig, newn, original->uniqueid); 02261 02262 /* Swap the guts */ 02263 p = original->pvt; 02264 original->pvt = clone->pvt; 02265 clone->pvt = p; 02266 02267 /* Save any pending frames on both sides. Start by counting 02268 * how many we're going to need... */ 02269 prev = NULL; 02270 cur = clone->pvt->readq; 02271 x = 0; 02272 while(cur) { 02273 x++; 02274 prev = cur; 02275 cur = cur->next; 02276 } 02277 /* If we had any, prepend them to the ones already in the queue, and 02278 * load up the alertpipe */ 02279 if (prev) { 02280 prev->next = original->pvt->readq; 02281 original->pvt->readq = clone->pvt->readq; 02282 clone->pvt->readq = NULL; 02283 if (original->pvt->alertpipe[1] > -1) { 02284 for (i=0;i<x;i++) 02285 write(original->pvt->alertpipe[1], &x, sizeof(x)); 02286 } 02287 } 02288 clone->_softhangup = AST_SOFTHANGUP_DEV; 02289 02290 02291 /* And of course, so does our current state. Note we need not 02292 call ast_setstate since the event manager doesn't really consider 02293 these separate. We do this early so that the clone has the proper 02294 state of the original channel. */ 02295 origstate = original->_state; 02296 original->_state = clone->_state; 02297 clone->_state = origstate; 02298 02299 if (clone->pvt->fixup){ 02300 res = clone->pvt->fixup(original, clone); 02301 if (res) 02302 ast_log(LOG_WARNING, "Fixup failed on channel %s, strange things may happen.\n", clone->name); 02303 } 02304 02305 /* Start by disconnecting the original's physical side */ 02306 if (clone->pvt->hangup) 02307 res = clone->pvt->hangup(clone); 02308 if (res) { 02309 ast_log(LOG_WARNING, "Hangup failed! Strange things may happen!\n"); 02310 ast_mutex_unlock(&clone->lock); 02311 return -1; 02312 } 02313 02314 snprintf(zombn, sizeof(zombn), "%s<ZOMBIE>", orig); 02315 /* Mangle the name of the clone channel */ 02316 strncpy(clone->name, zombn, sizeof(clone->name) - 1); 02317 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", masqn, zombn, clone->uniqueid); 02318 02319 /* Update the type. */ 02320 original->type = clone->type; 02321 02322 /* Keep the same language. */ 02323 strncpy(original->language, clone->language, sizeof(original->language)); 02324 02325 /* Copy the FD's */ 02326 for (x=0;x<AST_MAX_FDS;x++) { 02327 original->fds[x] = clone->fds[x]; 02328 } 02329 /* Append variables from clone channel into original channel */ 02330 /* XXX Is this always correct? We have to in order to keep MACROS working XXX */ 02331 varptr = original->varshead.first; 02332 if (varptr) { 02333 while(varptr->entries.next) { 02334 varptr = varptr->entries.next; 02335 } 02336 varptr->entries.next = clone->varshead.first; 02337 } else { 02338 original->varshead.first = clone->varshead.first; 02339 } 02340 clone->varshead.first = NULL; 02341 /* Presense of ADSI capable CPE follows clone */ 02342 original->adsicpe = clone->adsicpe; 02343 /* Bridge remains the same */ 02344 /* CDR fields remain the same */ 02345 /* XXX What about blocking, softhangup, blocker, and lock and blockproc? XXX */ 02346 /* Application and data remain the same */ 02347 /* Clone exception becomes real one, as with fdno */ 02348 original->exception = clone->exception; 02349 original->fdno = clone->fdno; 02350 /* Schedule context remains the same */ 02351 /* Stream stuff stays the same */ 02352 /* Keep the original state. The fixup code will need to work with it most likely */ 02353 02354 /* dnid and callerid change to become the new, HOWEVER, we also link the original's 02355 fields back into the defunct 'clone' so that they will be freed when 02356 ast_frfree is eventually called */ 02357 tmp = original->dnid; 02358 original->dnid = clone->dnid; 02359 clone->dnid = tmp; 02360 02361 tmp = original->callerid; 02362 original->callerid = clone->callerid; 02363 clone->callerid = tmp; 02364 02365 /* Restore original timing file descriptor */ 02366 original->fds[AST_MAX_FDS - 2] = original->timingfd; 02367 02368 /* Our native formats are different now */ 02369 original->nativeformats = clone->nativeformats; 02370 02371 /* Context, extension, priority, app data, jump table, remain the same */ 02372 /* pvt switches. pbx stays the same, as does next */ 02373 02374 /* Set the write format */ 02375 ast_set_write_format(original, wformat); 02376 02377 /* Set the read format */ 02378 ast_set_read_format(original, rformat); 02379 02380 /* Copy the music class */ 02381 strncpy(original->musicclass, clone->musicclass, sizeof(original->musicclass) - 1); 02382 02383 ast_log(LOG_DEBUG, "Putting channel %s in %d/%d formats\n", original->name, wformat, rformat); 02384 02385 /* Okay. Last thing is to let the channel driver know about all this mess, so he 02386 can fix up everything as best as possible */ 02387 if (original->pvt->fixup) { 02388 res = original->pvt->fixup(clone, original); 02389 if (res) { 02390 ast_log(LOG_WARNING, "Driver for '%s' could not fixup channel %s\n", 02391 original->type, original->name); 02392 ast_mutex_unlock(&clone->lock); 02393 return -1; 02394 } 02395 } else 02396 ast_log(LOG_WARNING, "Driver '%s' does not have a fixup routine (for %s)! Bad things may happen.\n", 02397 original->type, original->name); 02398 02399 /* Now, at this point, the "clone" channel is totally F'd up. We mark it as 02400 a zombie so nothing tries to touch it. If it's already been marked as a 02401 zombie, then free it now (since it already is considered invalid). */ 02402 if (clone->zombie) { 02403 ast_log(LOG_DEBUG, "Destroying clone '%s'\n", clone->name); 02404 ast_mutex_unlock(&clone->lock); 02405 ast_channel_free(clone); 02406 manager_event(EVENT_FLAG_CALL, "Hangup", "Channel: %s\r\n", zombn); 02407 } else { 02408 struct ast_frame null_frame = { AST_FRAME_NULL, }; 02409 ast_log(LOG_DEBUG, "Released clone lock on '%s'\n", clone->name); 02410 clone->zombie=1; 02411 ast_queue_frame(clone, &null_frame); 02412 ast_mutex_unlock(&clone->lock); 02413 } 02414 02415 /* Signal any blocker */ 02416 if (original->blocking) 02417 pthread_kill(original->blocker, SIGURG); 02418 ast_log(LOG_DEBUG, "Done Masquerading %s (%d)\n", 02419 original->name, original->_state); 02420 return 0; 02421 }
|
|
|
Get channel by name (locks channel).
Definition at line 510 of file channel.c. References ast_channel_walk_locked(), ast_mutex_unlock, ast_channel::lock, and ast_channel::name. 00511 { 00512 struct ast_channel *chan; 00513 chan = ast_channel_walk_locked(NULL); 00514 while(chan) { 00515 if (!strcasecmp(chan->name, channame)) 00516 return chan; 00517 ast_mutex_unlock(&chan->lock); 00518 chan = ast_channel_walk_locked(chan); 00519 } 00520 return NULL; 00521 }
|
|
|
Definition at line 2902 of file channel.c. References ast_log(), LOG_ERROR, and LOG_WARNING. 02903 { 02904 char *copy; 02905 char *piece; 02906 char *c=NULL; 02907 int start=0, finish=0,x; 02908 unsigned int group = 0; 02909 copy = ast_strdupa(s); 02910 if (!copy) { 02911 ast_log(LOG_ERROR, "Out of memory\n"); 02912 return 0; 02913 } 02914 c = copy; 02915 02916 while((piece = strsep(&c, ","))) { 02917 if (sscanf(piece, "%d-%d", &start, &finish) == 2) { 02918 /* Range */ 02919 } else if (sscanf(piece, "%d", &start)) { 02920 /* Just one */ 02921 finish = start; 02922 } else { 02923 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'.\n", s, piece); 02924 continue; 02925 } 02926 for (x=start;x<=finish;x++) { 02927 if ((x > 31) || (x < 0)) { 02928 ast_log(LOG_WARNING, "Ignoring invalid group %d (maximum group is 31)\n", x); 02929 } else 02930 group |= (1 << x); 02931 } 02932 } 02933 return group; 02934 }
|
|
|
Hang up a channel.
Definition at line 689 of file channel.c. References ast_cdr_end(), ast_cdr_free(), ast_cdr_post(), ast_channel_free(), ast_closestream(), ast_do_masquerade(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_channel::blocker, ast_channel::blocking, ast_channel::blockproc, ast_channel::cdr, CRASH, EVENT_FLAG_CALL, ast_channel::generator, ast_channel::generatordata, ast_channel_pvt::hangup, ast_channel::hangupcause, ast_channel::lock, LOG_DEBUG, LOG_WARNING, manager_event(), ast_channel::masq, ast_channel::masqr, ast_channel::name, option_debug, ast_channel::pvt, ast_generator::release, ast_channel::sched, sched_context_destroy(), ast_channel::stream, ast_channel::uniqueid, ast_channel::vstream, and ast_channel::zombie. Referenced by __ast_request_and_dial(), ast_async_goto(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), and ast_pbx_run(). 00690 { 00691 int res = 0; 00692 /* Don't actually hang up a channel that will masquerade as someone else, or 00693 if someone is going to masquerade as us */ 00694 ast_mutex_lock(&chan->lock); 00695 if (chan->masq) { 00696 if (ast_do_masquerade(chan)) 00697 ast_log(LOG_WARNING, "Failed to perform masquerade\n"); 00698 } 00699 00700 if (chan->masq) { 00701 ast_log(LOG_WARNING, "%s getting hung up, but someone is trying to masq into us?!?\n", chan->name); 00702 ast_mutex_unlock(&chan->lock); 00703 return 0; 00704 } 00705 /* If this channel is one which will be masqueraded into something, 00706 mark it as a zombie already, so we know to free it later */ 00707 if (chan->masqr) { 00708 chan->zombie=1; 00709 ast_mutex_unlock(&chan->lock); 00710 return 0; 00711 } 00712 free_translation(chan); 00713 if (chan->stream) 00714 ast_closestream(chan->stream); 00715 if (chan->vstream) 00716 ast_closestream(chan->vstream); 00717 if (chan->sched) 00718 sched_context_destroy(chan->sched); 00719 /* Clear any tone stuff remaining */ 00720 if (chan->generatordata) 00721 chan->generator->release(chan, chan->generatordata); 00722 chan->generatordata = NULL; 00723 chan->generator = NULL; 00724 if (chan->cdr) { 00725 /* End the CDR if it hasn't already */ 00726 ast_cdr_end(chan->cdr); 00727 /* Post and Free the CDR */ 00728 ast_cdr_post(chan->cdr); 00729 ast_cdr_free(chan->cdr); 00730 } 00731 if (chan->blocking) { 00732 ast_log(LOG_WARNING, "Hard hangup called by thread %ld on %s, while fd " 00733 "is blocked by thread %ld in procedure %s! Expect a failure\n", 00734 (long)pthread_self(), chan->name, (long)chan->blocker, chan->blockproc); 00735 CRASH; 00736 } 00737 if (!chan->zombie) { 00738 if (option_debug) 00739 ast_log(LOG_DEBUG, "Hanging up channel '%s'\n", chan->name); 00740 if (chan->pvt->hangup) 00741 res = chan->pvt->hangup(chan); 00742 } else 00743 if (option_debug) 00744 ast_log(LOG_DEBUG, "Hanging up zombie '%s'\n", chan->name); 00745 00746 ast_mutex_unlock(&chan->lock); 00747 manager_event(EVENT_FLAG_CALL, "Hangup", 00748 "Channel: %s\r\n" 00749 "Uniqueid: %s\r\n" 00750 "Cause: %i\r\n", 00751 chan->name, chan->uniqueid, chan->hangupcause); 00752 ast_channel_free(chan); 00753 return res; 00754 }
|
|
||||||||||||
|
Indicates condition of channel.
Definition at line 1411 of file channel.c. References ast_check_hangup(), AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, ast_get_indication_tone(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_playtones_start(), ast_playtones_stop(), tone_zone_sound::data, ast_channel_pvt::indicate, ast_channel::lock, LOG_DEBUG, LOG_WARNING, ast_channel::name, ast_channel::pvt, ast_channel::zombie, and ast_channel::zone. 01412 { 01413 int res = -1; 01414 /* Stop if we're a zombie or need a soft hangup */ 01415 if (chan->zombie || ast_check_hangup(chan)) 01416 return -1; 01417 ast_mutex_lock(&chan->lock); 01418 if (chan->pvt->indicate) 01419 res = chan->pvt->indicate(chan, condition); 01420 ast_mutex_unlock(&chan->lock); 01421 if (!chan->pvt->indicate || res) { 01422 /* 01423 * Device does not support (that) indication, lets fake 01424 * it by doing our own tone generation. (PM2002) 01425 */ 01426 if (condition >= 0) { 01427 const struct tone_zone_sound *ts = NULL; 01428 switch (condition) { 01429 case AST_CONTROL_RINGING: 01430 ts = ast_get_indication_tone(chan->zone, "ring"); 01431 break; 01432 case AST_CONTROL_BUSY: 01433 ts = ast_get_indication_tone(chan->zone, "busy"); 01434 break; 01435 case AST_CONTROL_CONGESTION: 01436 ts = ast_get_indication_tone(chan->zone, "congestion"); 01437 break; 01438 } 01439 if (ts && ts->data[0]) { 01440 ast_log(LOG_DEBUG, "Driver for channel '%s' does not support indication %d, emulating it\n", chan->name, condition); 01441 ast_playtones_start(chan,0,ts->data, 1); 01442 res = 0; 01443 } else if (condition == AST_CONTROL_PROGRESS) { 01444 /* ast_playtones_stop(chan); */ 01445 } else if (condition == AST_CONTROL_PROCEEDING) { 01446 /* Do nothing, really */ 01447 } else { 01448 /* not handled */ 01449 ast_log(LOG_WARNING, "Unable to handle indication %d for '%s'\n", condition, chan->name); 01450 res = -1; 01451 } 01452 } 01453 else ast_playtones_stop(chan); 01454 } 01455 return res; 01456 }
|
|
|
Search the Channels by Name.
Definition at line 1918 of file channel.c. References AST_CHANNEL_NAME, ast_channel_walk_locked(), AST_DEVICE_INUSE, AST_DEVICE_UNKNOWN, ast_mutex_unlock, ast_channel::lock, and ast_channel::name. Referenced by ast_device_state(). 01919 { 01920 char name[AST_CHANNEL_NAME] = ""; 01921 char *cut; 01922 struct ast_channel *chan; 01923 01924 chan = ast_channel_walk_locked(NULL); 01925 while (chan) { 01926 strncpy(name, chan->name, sizeof(name)-1); 01927 ast_mutex_unlock(&chan->lock); 01928 cut = strchr(name,'-'); 01929 if (cut) 01930 *cut = 0; 01931 if (!strcmp(name, device)) 01932 return AST_DEVICE_INUSE; 01933 chan = ast_channel_walk_locked(chan); 01934 } 01935 return AST_DEVICE_UNKNOWN; 01936 }
|
|
|
Definition at line 1549 of file channel.c. References ast_channel::_state, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), AST_STATE_UP, ast_write(), ast_frame::data, LOG_DEBUG, LOG_WARNING, ast_channel::name, ast_channel::pvt, ast_channel_pvt::rawwriteformat, and ast_frame::subclass. Referenced by ast_activate_generator(). 01550 { 01551 struct ast_frame a = { AST_FRAME_VOICE }; 01552 char nothing[128]; 01553 /* Send an empty audio frame to get things moving */ 01554 if (chan->_state != AST_STATE_UP) { 01555 ast_log(LOG_DEBUG, "Prodding channel '%s'\n", chan->name); 01556 a.subclass = chan->pvt->rawwriteformat; 01557 a.data = nothing + AST_FRIENDLY_OFFSET; 01558 if (ast_write(chan, &a)) 01559 ast_log(LOG_WARNING, "Prodding channel '%s' failed\n", chan->name); 01560 } 01561 return 0; 01562 }
|
|
|
Reads a frame.
Definition at line 1192 of file channel.c. References ast_channel::_softhangup, ast_channel::_state, ast_channel_pvt::alertpipe, ast_cdr_answer(), ast_cdr_end(), ast_check_hangup(), AST_CONTROL_ANSWER, AST_CONTROL_HANGUP, ast_deactivate_generator(), ast_do_masquerade(), AST_FRAME_CNG, AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frame_dump(), AST_FRAME_NULL, AST_FRAME_VOICE, ast_frfree(), ast_getformatname(), ast_log(), AST_MAX_FDS, ast_mutex_lock, ast_mutex_unlock, ast_seekstream(), ast_setstate(), ast_settimeout(), AST_SOFTHANGUP_DEV, AST_STATE_UP, ast_translate(), ast_writestream(), ast_channel::blocker, ast_channel::cdr, ast_frame::datalen, ast_channel::deferdtmf, ast_channel::dtmff, ast_channel::dtmfq, ast_channel_pvt::exception, ast_channel::exception, ast_channel::fdno, ast_channel::fin, ast_frame::frametype, ast_generator::generate, ast_channel::generator, ast_channel::generatordata, ast_channel::insmpl, ast_channel::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_channel::masq, ast_channel::monitor, ast_channel::name, ast_channel::nativeformats, ast_frame::next, ast_channel::outsmpl, ast_channel::pvt, ast_channel_pvt::read, ast_channel_monitor::read_stream, ast_channel_pvt::readq, ast_channel_pvt::readtrans, ast_frame::samples, SEEK_FORCECUR, ast_frame::subclass, ast_channel::timingdata, ast_channel::timingfd, ast_channel::timingfunc, and ast_channel::zombie. Referenced by __ast_request_and_dial(), ast_app_getvoice(), ast_channel_bridge(), ast_play_and_prepend(), ast_play_and_record(), ast_recvchar(), ast_rtp_bridge(), ast_safe_sleep(), ast_safe_sleep_conditional(), ast_tonepair(), ast_waitfordigit(), ast_waitfordigit_full(), ast_waitstream(), ast_waitstream_fr(), and ast_waitstream_full(). 01193 { 01194 struct ast_frame *f = NULL; 01195 int blah; 01196 #ifdef ZAPTEL_OPTIMIZATIONS 01197 int (*func)(void *); 01198 void *data; 01199 int res; 01200 #endif 01201 static struct ast_frame null_frame = 01202 { 01203 AST_FRAME_NULL, 01204 }; 01205 01206 ast_mutex_lock(&chan->lock); 01207 if (chan->masq) { 01208 if (ast_do_masquerade(chan)) { 01209 ast_log(LOG_WARNING, "Failed to perform masquerade\n"); 01210 f = NULL; 01211 } else 01212 f = &null_frame; 01213 ast_mutex_unlock(&chan->lock); 01214 return f; 01215 } 01216 01217 /* Stop if we're a zombie or need a soft hangup */ 01218 if (chan->zombie || ast_check_hangup(chan)) { 01219 if (chan->generator) 01220 ast_deactivate_generator(chan); 01221 ast_mutex_unlock(&chan->lock); 01222 return NULL; 01223 } 01224 01225 if (!chan->deferdtmf && !ast_strlen_zero(chan->dtmfq)) { 01226 /* We have DTMF that has been deferred. Return it now */ 01227 chan->dtmff.frametype = AST_FRAME_DTMF; 01228 chan->dtmff.subclass = chan->dtmfq[0]; 01229 /* Drop first digit */ 01230 memmove(chan->dtmfq, chan->dtmfq + 1, sizeof(chan->dtmfq) - 1); 01231 ast_mutex_unlock(&chan->lock); 01232 return &chan->dtmff; 01233 } 01234 01235 /* Read and ignore anything on the alertpipe, but read only 01236 one sizeof(blah) per frame that we send from it */ 01237 if (chan->pvt->alertpipe[0] > -1) { 01238 read(chan->pvt->alertpipe[0], &blah, sizeof(blah)); 01239 } 01240 #ifdef ZAPTEL_OPTIMIZATIONS 01241 if ((chan->timingfd > -1) && (chan->fdno == AST_MAX_FDS - 2) && chan->exception) { 01242 chan->exception = 0; 01243 blah = -1; 01244 /* IF we can't get event, assume it's an expired as-per the old interface */ 01245 res = ioctl(chan->timingfd, ZT_GETEVENT, &blah); 01246 if (res) 01247 blah = ZT_EVENT_TIMER_EXPIRED; 01248 01249 if (blah == ZT_EVENT_TIMER_PING) { 01250 #if 0 01251 ast_log(LOG_NOTICE, "Oooh, there's a PING!\n"); 01252 #endif 01253 if (!chan->pvt->readq || !chan->pvt->readq->next) { 01254 /* Acknowledge PONG unless we need it again */ 01255 #if 0 01256 ast_log(LOG_NOTICE, "Sending a PONG!\n"); 01257 #endif 01258 if (ioctl(chan->timingfd, ZT_TIMERPONG, &blah)) { 01259 ast_log(LOG_WARNING, "Failed to pong timer on '%s': %s\n", chan->name, strerror(errno)); 01260 } 01261 } 01262 } else if (blah == ZT_EVENT_TIMER_EXPIRED) { 01263 ioctl(chan->timingfd, ZT_TIMERACK, &blah); 01264 func = chan->timingfunc; 01265 data = chan->timingdata; 01266 ast_mutex_unlock(&chan->lock); 01267 if (func) { 01268 #if 0 01269 ast_log(LOG_DEBUG, "Calling private function\n"); 01270 #endif 01271 func(data); 01272 } else { 01273 blah = 0; 01274 ast_mutex_lock(&chan->lock); 01275 ioctl(chan->timingfd, ZT_TIMERCONFIG, &blah); 01276 chan->timingdata = NULL; 01277 ast_mutex_unlock(&chan->lock); 01278 } 01279 f = &null_frame; 01280 return f; 01281 } else 01282 ast_log(LOG_NOTICE, "No/unknown event '%d' on timer for '%s'?\n", blah, chan->name); 01283 } 01284 #endif 01285 /* Check for pending read queue */ 01286 if (chan->pvt->readq) { 01287 f = chan->pvt->readq; 01288 chan->pvt->readq = f->next; 01289 /* Interpret hangup and return NULL */ 01290 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) { 01291 ast_frfree(f); 01292 f = NULL; 01293 } 01294 } else { 01295 chan->blocker = pthread_self(); 01296 if (chan->exception) { 01297 if (chan->pvt->exception) 01298 f = chan->pvt->exception(chan); 01299 else { 01300 ast_log(LOG_WARNING, "Exception flag set on '%s', but no exception handler\n", chan->name); 01301 f = &null_frame; 01302 } 01303 /* Clear the exception flag */ 01304 chan->exception = 0; 01305 } else 01306 if (chan->pvt->read) 01307 f = chan->pvt->read(chan); 01308 else 01309 ast_log(LOG_WARNING, "No read routine on channel %s\n", chan->name); 01310 } 01311 01312 01313 if (f && (f->frametype == AST_FRAME_VOICE)) { 01314 if (!(f->subclass & chan->nativeformats)) { 01315 /* This frame can't be from the current native formats -- drop it on the 01316 floor */ 01317 ast_log(LOG_NOTICE, "Dropping incompatible voice frame on %s of format %s since our native format has changed to %s\n", chan->name, ast_getformatname(f->subclass), ast_getformatname(chan->nativeformats)); 01318 ast_frfree(f); 01319 f = &null_frame; 01320 } else { 01321 if (chan->monitor && chan->monitor->read_stream ) { 01322 #ifndef MONITOR_CONSTANT_DELAY 01323 int jump = chan->outsmpl - chan->insmpl - 2 * f->samples; 01324 if (jump >= 0) { 01325 if (ast_seekstream(chan->monitor->read_stream, jump + f->samples, SEEK_FORCECUR) == -1) 01326 ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n"); 01327 chan->insmpl += jump + 2 * f->samples; 01328 } else 01329 chan->insmpl+= f->samples; 01330 #else 01331 int jump = chan->outsmpl - chan->insmpl; 01332 if (jump - MONITOR_DELAY >= 0) { 01333 if (ast_seekstream(chan->monitor->read_stream, jump - f->samples, SEEK_FORCECUR) == -1) 01334 ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n"); 01335 chan->insmpl += jump; 01336 } else 01337 chan->insmpl += f->samples; 01338 #endif 01339 if (ast_writestream(chan->monitor->read_stream, f) < 0) 01340 ast_log(LOG_WARNING, "Failed to write data to channel monitor read stream\n"); 01341 } 01342 if (chan->pvt->readtrans) { 01343 f = ast_translate(chan->pvt->readtrans, f, 1); 01344 if (!f) 01345 f = &null_frame; 01346 } 01347 } 01348 } 01349 01350 /* Make sure we always return NULL in the future */ 01351 if (!f) { 01352 chan->_softhangup |= AST_SOFTHANGUP_DEV; 01353 if (chan->generator) 01354 ast_deactivate_generator(chan); 01355 /* End the CDR if appropriate */ 01356 if (chan->cdr) 01357 ast_cdr_end(chan->cdr); 01358 } else if (chan->deferdtmf && f->frametype == AST_FRAME_DTMF) { 01359 if (strlen(chan->dtmfq) < sizeof(chan->dtmfq) - 2) 01360 chan->dtmfq[strlen(chan->dtmfq)] = f->subclass; 01361 else 01362 ast_log(LOG_WARNING, "Dropping deferred DTMF digits on %s\n", chan->name); 01363 f = &null_frame; 01364 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_ANSWER)) { 01365 if (chan->_state == AST_STATE_UP) { 01366 ast_log(LOG_DEBUG, "Dropping duplicate answer!\n"); 01367 f = &null_frame; 01368 } 01369 /* Answer the CDR */ 01370 ast_setstate(chan, AST_STATE_UP); 01371 ast_cdr_answer(chan->cdr); 01372 } 01373 01374 /* Run any generator sitting on the line */ 01375 if (f && (f->frametype == AST_FRAME_VOICE) && chan->generatordata) { 01376 /* Mask generator data temporarily and apply. If there is a timing function, it 01377 will be calling the generator instead */ 01378 void *tmp; 01379 int res; 01380 int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples); 01381 if (chan->timingfunc) { 01382 ast_log(LOG_DEBUG, "Generator got voice, switching to phase locked mode\n"); 01383 ast_settimeout(chan, 0, NULL, NULL); 01384 } 01385 tmp = chan->generatordata; 01386 chan->generatordata = NULL; 01387 generate = chan->generator->generate; 01388 res = generate(chan, tmp, f->datalen, f->samples); 01389 chan->generatordata = tmp; 01390 if (res) { 01391 ast_log(LOG_DEBUG, "Auto-deactivating generator\n"); 01392 ast_deactivate_generator(chan); 01393 } 01394 } else if (f && (f->frametype == AST_FRAME_CNG)) { 01395 if (chan->generator && !chan->timingfunc && (chan->timingfd > -1)) { 01396 ast_log(LOG_DEBUG, "Generator got CNG, switching to zap timed mode\n"); 01397 ast_settimeout(chan, 160, generator_force, chan); 01398 } 01399 } 01400 /* High bit prints debugging */ 01401 if (chan->fin & 0x80000000) 01402 ast_frame_dump(chan->name, f, "<<"); 01403 if ((chan->fin & 0x7fffffff) == 0x7fffffff) 01404 chan->fin &= 0x80000000; 01405 else 01406 chan->fin++; 01407 ast_mutex_unlock(&chan->lock); 01408 return f; 01409 }
|
|
||||||||||||||||||||||||||||
|
Reads multiple digits.
Definition at line 2012 of file channel.c. References ast_check_hangup(), AST_DIGIT_ANY, ast_stopstream(), ast_waitfordigit(), ast_waitstream(), ast_channel::stream, and ast_channel::zombie. Referenced by ast_app_getdata(). 02013 { 02014 int pos=0; 02015 int to = ftimeout; 02016 int d; 02017 /* XXX Merge with full version? XXX */ 02018 /* Stop if we're a zombie or need a soft hangup */ 02019 if (c->zombie || ast_check_hangup(c)) 02020 return -1; 02021 if (!len) 02022 return -1; 02023 do { 02024 if (c->stream) { 02025 d = ast_waitstream(c, AST_DIGIT_ANY); 02026 ast_stopstream(c); 02027 usleep(1000); 02028 if (!d) 02029 d = ast_waitfordigit(c, to); 02030 } else { 02031 d = ast_waitfordigit(c, to); 02032 } 02033 if (d < 0) 02034 return -1; 02035 if (d == 0) { 02036 s[pos]='\0'; 02037 return 1; 02038 } 02039 if (!strchr(enders, d)) 02040 s[pos++] = d; 02041 if (strchr(enders, d) || (pos >= len)) { 02042 s[pos]='\0'; 02043 return 0; 02044 } 02045 to = timeout; 02046 } while(1); 02047 /* Never reached */ 02048 return 0; 02049 }
|
|
||||||||||||||||||||||||||||||||||||
|
Definition at line 2051 of file channel.c. References ast_check_hangup(), AST_DIGIT_ANY, ast_stopstream(), ast_waitfordigit_full(), ast_waitstream_full(), ast_channel::stream, and ast_channel::zombie. Referenced by ast_app_getdata_full(). 02052 { 02053 int pos=0; 02054 int to = ftimeout; 02055 int d; 02056 /* Stop if we're a zombie or need a soft hangup */ 02057 if (c->zombie || ast_check_hangup(c)) 02058 return -1; 02059 if (!len) 02060 return -1; 02061 do { 02062 if (c->stream) { 02063 d = ast_waitstream_full(c, AST_DIGIT_ANY, audiofd, ctrlfd); 02064 ast_stopstream(c); 02065 usleep(1000); 02066 if (!d) 02067 d = ast_waitfordigit_full(c, to, audiofd, ctrlfd); 02068 } else { 02069 d = ast_waitfordigit_full(c, to, audiofd, ctrlfd); 02070 } 02071 if (d < 0) 02072 return -1; 02073 if (d == 0) { 02074 s[pos]='\0'; 02075 return 1; 02076 } 02077 if (d == 1) { 02078 s[pos]='\0'; 02079 return 2; 02080 } 02081 if (!strchr(enders, d)) 02082 s[pos++] = d; 02083 if (strchr(enders, d) || (pos >= len)) { 02084 s[pos]='\0'; 02085 return 0; 02086 } 02087 to = timeout; 02088 } while(1); 02089 /* Never reached */ 02090 return 0; 02091 }
|
|
||||||||||||
|
Definition at line 1458 of file channel.c. References ast_check_hangup(), AST_CONTROL_HANGUP, AST_FRAME_CONTROL, AST_FRAME_TEXT, ast_frfree(), ast_read(), ast_waitfor(), ast_frame::data, ast_frame::frametype, and ast_frame::subclass. 01459 { 01460 int res,ourto,c; 01461 struct ast_frame *f; 01462 01463 ourto = timeout; 01464 for(;;) 01465 { 01466 if (ast_check_hangup(chan)) return -1; 01467 res = ast_waitfor(chan,ourto); 01468 if (res <= 0) /* if timeout */ 01469 { 01470 return 0; 01471 } 01472 ourto = res; 01473 f = ast_read(chan); 01474 if (f == NULL) return -1; /* if hangup */ 01475 if ((f->frametype == AST_FRAME_CONTROL) && 01476 (f->subclass == AST_CONTROL_HANGUP)) return -1; /* if hangup */ 01477 if (f->frametype == AST_FRAME_TEXT) /* if a text frame */ 01478 { 01479 c = *((char *)f->data); /* get the data */ 01480 ast_frfree(f); 01481 return(c); 01482 } 01483 ast_frfree(f); 01484 } 01485 }
|
|
||||||||||||||||
|
Requests a channel.
Definition at line 1873 of file channel.c. References ast_channel::_state, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_state2str(), AST_STATE_DOWN, ast_translator_best_choice(), backends, ast_channel::callerid, chanlist::capabilities, EVENT_FLAG_CALL, LOG_WARNING, manager_event(), ast_channel::name, chanlist::next, chanlist::requester, chanlist::type, and ast_channel::uniqueid. Referenced by __ast_request_and_dial(). 01874 { 01875 struct chanlist *chan; 01876 struct ast_channel *c = NULL; 01877 int capabilities; 01878 int fmt; 01879 int res; 01880 if (ast_mutex_lock(&chlock)) { 01881 ast_log(LOG_WARNING, "Unable to lock channel list\n"); 01882 return NULL; 01883 } 01884 chan = backends; 01885 while(chan) { 01886 if (!strcasecmp(type, chan->type)) { 01887 capabilities = chan->capabilities; 01888 fmt = format; 01889 res = ast_translator_best_choice(&fmt, &capabilities); 01890 if (res < 0) { 01891 ast_log(LOG_WARNING, "No translator path exists for channel type %s (native %d) to %d\n", type, chan->capabilities, format); 01892 ast_mutex_unlock(&chlock); 01893 return NULL; 01894 } 01895 ast_mutex_unlock(&chlock); 01896 if (chan->requester) 01897 c = chan->requester(type, capabilities, data); 01898 if (c) { 01899 if (c->_state == AST_STATE_DOWN) { 01900 manager_event(EVENT_FLAG_CALL, "Newchannel", 01901 "Channel: %s\r\n" 01902 "State: %s\r\n" 01903 "CallerID: %s\r\n" 01904 "Uniqueid: %s\r\n", 01905 c->name, ast_state2str(c->_state), c->callerid ? c->callerid : "<unknown>", c->uniqueid); 01906 } 01907 } 01908 return c; 01909 } 01910 chan = chan->next; 01911 } 01912 if (!chan) 01913 ast_log(LOG_WARNING, "No channel type registered for '%s'\n", type); 01914 ast_mutex_unlock(&chlock); 01915 return c; 01916 }
|
|
||||||||||||||||||||||||||||
|
Definition at line 1868 of file channel.c. References __ast_request_and_dial(). Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten(). 01869 { 01870 return __ast_request_and_dial(type, format, data, timeout, outstate, callerid, NULL); 01871 }
|
|
||||||||||||
|
Wait for a specied amount of time, looking for hangups.
Definition at line 544 of file channel.c. References ast_frfree(), ast_read(), and ast_waitfor(). Referenced by ast_dtmf_stream(). 00545 { 00546 struct ast_frame *f; 00547 while(ms > 0) { 00548 ms = ast_waitfor(chan, ms); 00549 if (ms <0) 00550 return -1; 00551 if (ms > 0) { 00552 f = ast_read(chan); 00553 if (!f) 00554 return -1; 00555 ast_frfree(f); 00556 } 00557 } 00558 return 0; 00559 }
|
|
||||||||||||||||||||
|
Wait for a specied amount of time, looking for hangups and a condition argument.
Definition at line 523 of file channel.c. References ast_frfree(), ast_read(), and ast_waitfor(). 00525 { 00526 struct ast_frame *f; 00527 00528 while(ms > 0) { 00529 if( cond && ((*cond)(data) == 0 ) ) 00530 return 0; 00531 ms = ast_waitfor(chan, ms); 00532 if (ms <0) 00533 return -1; 00534 if (ms > 0) { 00535 f = ast_read(chan); 00536 if (!f) 00537 return -1; 00538 ast_frfree(f); 00539 } 00540 } 00541 return 0; 00542 }
|
|
||||||||||||
|
Receives a text character from a channel.
Definition at line 1544 of file channel.c.
|
|
||||||||||||
|
Sends text to a channel.
Definition at line 1487 of file channel.c. References ast_check_hangup(), ast_channel::blocking, CHECK_BLOCKING, ast_channel::pvt, ast_channel_pvt::send_text, and ast_channel::zombie. 01488 { 01489 int res = 0; 01490 /* Stop if we're a zombie or need a soft hangup */ 01491 if (chan->zombie || ast_check_hangup(chan)) 01492 return -1; 01493 CHECK_BLOCKING(chan); 01494 if (chan->pvt->send_text) 01495 res = chan->pvt->send_text(chan, text); 01496 chan->blocking = 0; 01497 return res; 01498 }
|
|
||||||||||||||||
|
Definition at line 2423 of file channel.c. References ast_channel::ani, ast_cdr_setcid(), ast_channel::callerid, ast_channel::cdr, EVENT_FLAG_CALL, free, manager_event(), ast_channel::name, strdup, and ast_channel::uniqueid. Referenced by __ast_request_and_dial(). 02424 { 02425 if (chan->callerid) 02426 free(chan->callerid); 02427 if (anitoo && chan->ani) 02428 free(chan->ani); 02429 if (callerid) { 02430 chan->callerid = strdup(callerid); 02431 if (anitoo) 02432 chan->ani = strdup(callerid); 02433 } else { 02434 chan->callerid = NULL; 02435 if (anitoo) 02436 chan->ani = NULL; 02437 } 02438 if (chan->cdr) 02439 ast_cdr_setcid(chan->cdr, chan); 02440 manager_event(EVENT_FLAG_CALL, "Newcallerid", 02441 "Channel: %s\r\n" 02442 "CallerID: %s\r\n" 02443 "Uniqueid: %s\r\n", 02444 chan->name, chan->callerid ? 02445 chan->callerid : "<Unknown>", 02446 chan->uniqueid); 02447 }
|
|
||||||||||||
|
Sets read format on channel chan.
Definition at line 1724 of file channel.c. References ast_getformatname(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_translator_best_choice(), ast_translator_build_path(), ast_translator_free_path(), ast_channel::lock, LOG_DEBUG, LOG_NOTICE, ast_channel::name, ast_channel::nativeformats, option_debug, ast_channel::pvt, ast_channel_pvt::rawreadformat, ast_channel::readformat, and ast_channel_pvt::readtrans. Referenced by ast_app_getvoice(), ast_channel_make_compatible(), ast_do_masquerade(), ast_play_and_prepend(), and ast_play_and_record(). 01725 { 01726 int fmt; 01727 int native; 01728 int res; 01729 01730 ast_mutex_lock(&chan->lock); 01731 native = chan->nativeformats; 01732 fmt = fmts; 01733 /* Find a translation path from the native read format to one of the user's read formats */ 01734 res = ast_translator_best_choice(&fmt, &native); 01735 if (res < 0) { 01736 ast_log(LOG_NOTICE, "Unable to find a path from %s to %s\n", 01737 ast_getformatname(chan->nativeformats), ast_getformatname(fmts)); 01738 ast_mutex_unlock(&chan->lock); 01739 return -1; 01740 } 01741 01742 /* Now we have a good choice for both. We'll write using our native format. */ 01743 chan->pvt->rawreadformat = native; 01744 /* User perspective is fmt */ 01745 chan->readformat = fmt; 01746 /* Free any read translation we have right now */ 01747 if (chan->pvt->readtrans) 01748 ast_translator_free_path(chan->pvt->readtrans); 01749 /* Build a translation path from the raw read format to the user reading format */ 01750 chan->pvt->readtrans = ast_translator_build_path(chan->readformat, chan->pvt->rawreadformat); 01751 if (option_debug) 01752 ast_log(LOG_DEBUG, "Set channel %s to read format %s\n", 01753 chan->name, ast_getformatname(chan->readformat)); 01754 ast_mutex_unlock(&chan->lock); 01755 return 0; 01756 }
|
|
||||||||||||
|
Sets write format on channel chan.
Definition at line 1691 of file channel.c. References ast_getformatname(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_translator_best_choice(), ast_translator_build_path(), ast_translator_free_path(), ast_channel::lock, LOG_DEBUG, LOG_NOTICE, ast_channel::name, ast_channel::nativeformats, option_debug, ast_channel::pvt, ast_channel_pvt::rawwriteformat, ast_channel::writeformat, and ast_channel_pvt::writetrans. Referenced by ast_channel_make_compatible(), ast_do_masquerade(), ast_openstream(), and ast_stopstream(). 01692 { 01693 int fmt; 01694 int native; 01695 int res; 01696 01697 ast_mutex_lock(&chan->lock); 01698 native = chan->nativeformats; 01699 fmt = fmts; 01700 01701 res = ast_translator_best_choice(&native, &fmt); 01702 if (res < 0) { 01703 ast_log(LOG_NOTICE, "Unable to find a path from %s to %s\n", 01704 ast_getformatname(fmts), ast_getformatname(chan->nativeformats)); 01705 ast_mutex_unlock(&chan->lock); 01706 return -1; 01707 } 01708 01709 /* Now we have a good choice for both. We'll write using our native format. */ 01710 chan->pvt->rawwriteformat = native; 01711 /* User perspective is fmt */ 01712 chan->writeformat = fmt; 01713 /* Free any write translation we have right now */ 01714 if (chan->pvt->writetrans) 01715 ast_translator_free_path(chan->pvt->writetrans); 01716 /* Build a translation path from the user write format to the raw writing format */ 01717 chan->pvt->writetrans = ast_translator_build_path(chan->pvt->rawwriteformat, chan->writeformat); 01718 if (option_debug) 01719 ast_log(LOG_DEBUG, "Set channel %s to write format %s\n", chan->name, ast_getformatname(chan->writeformat)); 01720 ast_mutex_unlock(&chan->lock); 01721 return 0; 01722 }
|
|
||||||||||||||||||||
|
Definition at line 1119 of file channel.c. References ast_log(), LOG_DEBUG, ast_channel::timingdata, ast_channel::timingfd, and ast_channel::timingfunc. Referenced by ast_activate_generator(), ast_closestream(), ast_deactivate_generator(), and ast_read(). 01120 { 01121 int res = -1; 01122 #ifdef ZAPTEL_OPTIMIZATIONS 01123 if (c->timingfd > -1) { 01124 if (!func) { 01125 samples = 0; 01126 data = 0; 01127 } 01128 ast_log(LOG_DEBUG, "Scheduling timer at %d sample intervals\n", samples); 01129 res = ioctl(c->timingfd, ZT_TIMERCONFIG, &samples); 01130 c->timingfunc = func; 01131 c->timingdata = data; 01132 } 01133 #endif 01134 return res; 01135 }
|
|
|
Returns non-zero if Asterisk is being shut down Definition at line 139 of file channel.c.
|
|
||||||||||||
|
Softly hangup up a channel.
Definition at line 668 of file channel.c. References ast_mutex_lock, ast_mutex_unlock, ast_softhangup_nolock(), and ast_channel::lock. Referenced by ast_begin_shutdown(). 00669 { 00670 int res; 00671 ast_mutex_lock(&chan->lock); 00672 res = ast_softhangup_nolock(chan, cause); 00673 ast_mutex_unlock(&chan->lock); 00674 return res; 00675 }
|
|
||||||||||||
|
Definition at line 653 of file channel.c. References ast_channel::_softhangup, AST_FRAME_NULL, ast_log(), ast_queue_frame(), ast_channel::blocker, ast_channel::blocking, LOG_DEBUG, ast_channel::name, and option_debug. Referenced by ast_async_goto(), and ast_softhangup(). 00654 { 00655 int res = 0; 00656 struct ast_frame f = { AST_FRAME_NULL }; 00657 if (option_debug) 00658 ast_log(LOG_DEBUG, "Soft-Hanging up channel '%s'\n", chan->name); 00659 /* Inform channel driver that we need to be hung up, if it cares */ 00660 chan->_softhangup |= cause; 00661 ast_queue_frame(chan, &f); 00662 /* Interrupt any poll call or such */ 00663 if (chan->blocking) 00664 pthread_kill(chan->blocker, SIGURG); 00665 return res; 00666 }
|
|
|
Gives the string form of a given state.
Definition at line 205 of file channel.c. References AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DOWN, AST_STATE_OFFHOOK, AST_STATE_RESERVED, AST_STATE_RING, AST_STATE_RINGING, and AST_STATE_UP. Referenced by ast_request(), and ast_setstate(). 00206 { 00207 /* XXX Not reentrant XXX */ 00208 static char localtmp[256]; 00209 switch(state) { 00210 case AST_STATE_DOWN: 00211 return "Down"; 00212 case AST_STATE_RESERVED: 00213 return "Rsrvd"; 00214 case AST_STATE_OFFHOOK: 00215 return "OffHook"; 00216 case AST_STATE_DIALING: 00217 return "Dialing"; 00218 case AST_STATE_RING: 00219 return "Ring"; 00220 case AST_STATE_RINGING: 00221 return "Ringing"; 00222 case AST_STATE_UP: 00223 return "Up"; 00224 case AST_STATE_BUSY: 00225 return "Busy"; 00226 default: 00227 snprintf(localtmp, sizeof(localtmp), "Unknown (%d)\n", state); 00228 return localtmp; 00229 } 00230 }
|
|
||||||||||||||||||||||||
|
Play a tone pair for a given amount of time Definition at line 2884 of file channel.c. References ast_frfree(), ast_read(), ast_tonepair_start(), ast_waitfor(), and ast_channel::generatordata. 02885 { 02886 struct ast_frame *f; 02887 int res; 02888 if ((res = ast_tonepair_start(chan, freq1, freq2, duration, vol))) 02889 return res; 02890 02891 /* Give us some wiggle room */ 02892 while(chan->generatordata && (ast_waitfor(chan, 100) >= 0)) { 02893 f = ast_read(chan); 02894 if (f) 02895 ast_frfree(f); 02896 else 02897 return -1; 02898 } 02899 return 0; 02900 }
|
|
||||||||||||||||||||||||
|
Start a tone going Definition at line 2864 of file channel.c. References ast_activate_generator(), tonepair_def::duration, tonepair_def::freq1, tonepair_def::freq2, and tonepair_def::vol. Referenced by ast_tonepair(). 02865 { 02866 struct tonepair_def d = { 0, }; 02867 d.freq1 = freq1; 02868 d.freq2 = freq2; 02869 d.duration = duration; 02870 if (vol < 1) 02871 d.vol = 8192; 02872 else 02873 d.vol = vol; 02874 if (ast_activate_generator(chan, &tonepair, &d)) 02875 return -1; 02876 return 0; 02877 }
|
|
|
Stop a tone from playing Definition at line 2879 of file channel.c. References ast_deactivate_generator(). 02880 { 02881 ast_deactivate_generator(chan); 02882 }
|
|
||||||||||||
|
Definition at line 1992 of file channel.c. References ast_check_hangup(), ast_mutex_lock, ast_mutex_unlock, ast_channel::lock, ast_channel::pvt, ast_channel_pvt::transfer, and ast_channel::zombie. 01993 { 01994 /* Place an outgoing call, but don't wait any longer than timeout ms before returning. 01995 If the remote end does not answer within the timeout, then do NOT hang up, but 01996 return anyway. */ 01997 int res = -1; 01998 /* Stop if we're a zombie or need a soft hangup */ 01999 ast_mutex_lock(&chan->lock); 02000 if (!chan->zombie && !ast_check_hangup(chan)) { 02001 if (chan->pvt->transfer) { 02002 res = chan->pvt->transfer(chan, dest); 02003 if (!res) 02004 res = 1; 02005 } else 02006 res = 0; 02007 } 02008 ast_mutex_unlock(&chan->lock); 02009 return res; 02010 }
|
|
||||||||||||
|
Wait for input on a channel.
Definition at line 1078 of file channel.c. References ast_waitfor_n(). Referenced by __ast_request_and_dial(), ast_app_getvoice(), ast_dtmf_stream(), ast_play_and_prepend(), ast_play_and_record(), ast_recvchar(), ast_safe_sleep(), ast_safe_sleep_conditional(), ast_tonepair(), ast_waitfordigit(), ast_waitstream(), and ast_waitstream_fr(). 01079 { 01080 struct ast_channel *chan; 01081 int oldms = ms; 01082 chan = ast_waitfor_n(&c, 1, &ms); 01083 if (ms < 0) { 01084 if (oldms < 0) 01085 return 0; 01086 else 01087 return -1; 01088 } 01089 return ms; 01090 }
|
|
||||||||||||||||
|
Waits for input on a group of channels. Wait for input on an array of channels for a given # of milliseconds. Return channel with activity, or NULL if none has activity. time "ms" is modified in-place, if applicable Definition at line 1073 of file channel.c. References ast_waitfor_nandfds(). Referenced by ast_channel_bridge(), ast_rtp_bridge(), and ast_waitfor(). 01074 { 01075 return ast_waitfor_nandfds(c, n, NULL, 0, NULL, NULL, ms); 01076 }
|
|
||||||||||||||||||||
|
Waits for input on an fd. This version works on fd's only. Be careful with it. Definition at line 869 of file channel.c. References ast_log(), pollfd::events, pollfd::fd, LOG_WARNING, poll(), POLLIN, and POLLPRI. 00870 { 00871 /* Wait for x amount of time on a file descriptor to have input. */ 00872 struct timeval start, now; 00873 int res; 00874 int x, y; 00875 int winner = -1; 00876 int spoint; 00877 struct pollfd *pfds; 00878 00879 pfds = alloca(sizeof(struct pollfd) * n); 00880 if (!pfds) { 00881 ast_log(LOG_WARNING, "alloca failed! bad things will happen.\n"); 00882 return -1; 00883 } 00884 if (*ms > 0) 00885 gettimeofday(&start, NULL); 00886 y = 0; 00887 for (x=0;x<n;x++) { 00888 if (fds[x] > -1) { 00889 pfds[y].fd = fds[x]; 00890 pfds[y].events = POLLIN | POLLPRI; 00891 y++; 00892 } 00893 } 00894 res = poll(pfds, y, *ms); 00895 if (res < 0) { 00896 /* Simulate a timeout if we were interrupted */ 00897 if (errno != EINTR) 00898 *ms = -1; 00899 else 00900 *ms = 0; 00901 return -1; 00902 } 00903 spoint = 0; 00904 for (x=0;x<n;x++) { 00905 if (fds[x] > -1) { 00906 if ((res = ast_fdisset(pfds, fds[x], y, &spoint))) { 00907 winner = fds[x]; 00908 if (exception) { 00909 if (res & POLLPRI) 00910 *exception = -1; 00911 else 00912 *exception = 0; 00913 } 00914 } 00915 } 00916 } 00917 if (*ms > 0) { 00918 long passed; 00919 gettimeofday(&now, NULL); 00920 passed = (now.tv_sec - start.tv_sec) * 1000; 00921 passed += (now.tv_usec - start.tv_usec) / 1000; 00922 if (passed <= *ms) 00923 *ms -= passed; 00924 else 00925 *ms = 0; 00926 } 00927 return winner; 00928 }
|
|
||||||||||||||||||||||||||||||||
|
Waits for activity on a group of channels.
Definition at line 930 of file channel.c. References ast_channel::_softhangup, ast_do_masquerade(), ast_log(), AST_MAX_FDS, ast_mutex_lock, ast_mutex_unlock, AST_SOFTHANGUP_TIMEOUT, ast_channel::blocking, CHECK_BLOCKING, pollfd::events, ast_channel::exception, pollfd::fd, ast_channel::fdno, ast_channel::fds, ast_channel::lock, LOG_WARNING, ast_channel::masq, poll(), POLLIN, POLLPRI, and ast_channel::whentohangup. Referenced by ast_waitfor_n(), ast_waitfordigit_full(), and ast_waitstream_full(). 00932 { 00933 /* Wait for x amount of time on a file descriptor to have input. */ 00934 struct timeval start, end; 00935 struct pollfd *pfds; 00936 int res; 00937 long rms; 00938 int x, y, max; 00939 int spoint; 00940 time_t now = 0; 00941 long whentohangup = 0, havewhen = 0, diff; 00942 struct ast_channel *winner = NULL; 00943 00944 pfds = alloca(sizeof(struct pollfd) * (n * AST_MAX_FDS + nfds)); 00945 if (!pfds) { 00946 ast_log(LOG_WARNING, "alloca failed! bad things will happen.\n"); 00947 *outfd = -1; 00948 return NULL; 00949 } 00950 00951 if (outfd) 00952 *outfd = -99999; 00953 if (exception) 00954 *exception = 0; 00955 00956 /* Perform any pending masquerades */ 00957 for (x=0;x<n;x++) { 00958 ast_mutex_lock(&c[x]->lock); 00959 if (c[x]->whentohangup) { 00960 if (!havewhen) 00961 time(&now); 00962 diff = c[x]->whentohangup - now; 00963 if (!havewhen || (diff < whentohangup)) { 00964 havewhen++; 00965 whentohangup = diff; 00966 } 00967 } 00968 if (c[x]->masq) { 00969 if (ast_do_masquerade(c[x])) { 00970 ast_log(LOG_WARNING, "Masquerade failed\n"); 00971 *ms = -1; 00972 ast_mutex_unlock(&c[x]->lock); 00973 return NULL; 00974 } 00975 } 00976 ast_mutex_unlock(&c[x]->lock); 00977 } 00978 00979 rms = *ms; 00980 00981 if (havewhen) { 00982 if ((*ms < 0) || (whentohangup * 1000 < *ms)) { 00983 rms = whentohangup * 1000; 00984 } 00985 } 00986 max = 0; 00987 for (x=0;x<n;x++) { 00988 for (y=0;y<AST_MAX_FDS;y++) { 00989 if (c[x]->fds[y] > -1) { 00990 pfds[max].fd = c[x]->fds[y]; 00991 pfds[max].events = POLLIN | POLLPRI; 00992 max++; 00993 } 00994 } 00995 CHECK_BLOCKING(c[x]); 00996 } 00997 for (x=0;x<nfds; x++) { 00998 if (fds[x] > -1) { 00999 pfds[max].fd = fds[x]; 01000 pfds[max].events = POLLIN | POLLPRI; 01001 max++; 01002 } 01003 } 01004 if (*ms > 0) 01005 gettimeofday(&start, NULL); 01006 res = poll(pfds, max, rms); 01007 if (res < 0) { 01008 for (x=0;x<n;x++) 01009 c[x]->blocking = 0; 01010 /* Simulate a timeout if we were interrupted */ 01011 if (errno != EINTR) 01012 *ms = -1; 01013 else { 01014 /* Just an interrupt */ 01015 #if 0 01016 *ms = 0; 01017 #endif 01018 } 01019 return NULL; 01020 } 01021 01022 if (havewhen) 01023 time(&now); 01024 spoint = 0; 01025 for (x=0;x<n;x++) { 01026 c[x]->blocking = 0; 01027 if (havewhen && c[x]->whentohangup && (now > c[x]->whentohangup)) { 01028 c[x]->_softhangup |= AST_SOFTHANGUP_TIMEOUT; 01029 if (!winner) 01030 winner = c[x]; 01031 } 01032 for (y=0;y<AST_MAX_FDS;y++) { 01033 if (c[x]->fds[y] > -1) { 01034 if ((res = ast_fdisset(pfds, c[x]->fds[y], max, &spoint))) { 01035 if (res & POLLPRI) 01036 c[x]->exception = -1; 01037 else 01038 c[x]->exception = 0; 01039 c[x]->fdno = y; 01040 winner = c[x]; 01041 } 01042 } 01043 } 01044 } 01045 for (x=0;x<nfds;x++) { 01046 if (fds[x] > -1) { 01047 if ((res = ast_fdisset(pfds, fds[x], max, &spoint))) { 01048 if (outfd) 01049 *outfd = fds[x]; 01050 if (exception) { 01051 if (res & POLLPRI) 01052 *exception = -1; 01053 else 01054 *exception = 0; 01055 } 01056 winner = NULL; 01057 } 01058 } 01059 } 01060 if (*ms > 0) { 01061 long diff; 01062 gettimeofday(&end, NULL); 01063 diff = (end.tv_sec - start.tv_sec) * 1000; 01064 diff += (end.tv_usec - start.tv_usec) / 1000; 01065 if (diff < *ms) 01066 *ms -= diff; 01067 else 01068 *ms = 0; 01069 } 01070 return winner; 01071 }
|
|
||||||||||||
|
Waits for a digit.
Definition at line 1092 of file channel.c. References ast_check_hangup(), AST_FRAME_DTMF, ast_frfree(), ast_read(), ast_waitfor(), ast_frame::frametype, ast_frame::subclass, and ast_channel::zombie. Referenced by ast_control_streamfile(), ast_pbx_run(), and ast_readstring(). 01093 { 01094 /* XXX Should I be merged with waitfordigit_full XXX */ 01095 struct ast_frame *f; 01096 int result = 0; 01097 /* Stop if we're a zombie or need a soft hangup */ 01098 if (c->zombie || ast_check_hangup(c)) 01099 return -1; 01100 /* Wait for a digit, no more than ms milliseconds total. */ 01101 while(ms && !result) { 01102 ms = ast_waitfor(c, ms); 01103 if (ms < 0) /* Error */ 01104 result = -1; 01105 else if (ms > 0) { 01106 /* Read something */ 01107 f = ast_read(c); 01108 if (f) { 01109 if (f->frametype == AST_FRAME_DTMF) 01110 result = f->subclass; 01111 ast_frfree(f); 01112 } else 01113 result = -1; 01114 } 01115 } 01116 return result; 01117 }
|
|
||||||||||||||||||||
|
Definition at line 1136 of file channel.c. References ast_check_hangup(), AST_CONTROL_ANSWER, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree(), ast_log(), ast_read(), ast_waitfor_nandfds(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, LOG_WARNING, ast_frame::subclass, and ast_channel::zombie. Referenced by ast_readstring_full(). 01137 { 01138 struct ast_frame *f; 01139 struct ast_channel *rchan; 01140 int outfd; 01141 int res; 01142 /* Stop if we're a zombie or need a soft hangup */ 01143 if (c->zombie || ast_check_hangup(c)) 01144 return -1; 01145 /* Wait for a digit, no more than ms milliseconds total. */ 01146 while(ms) { 01147 errno = 0; 01148 rchan = ast_waitfor_nandfds(&c, 1, &cmdfd, (cmdfd > -1) ? 1 : 0, NULL, &outfd, &ms); 01149 if ((!rchan) && (outfd < 0) && (ms)) { 01150 if (errno == 0 || errno == EINTR) 01151 continue; 01152 ast_log(LOG_WARNING, "Wait failed (%s)\n", strerror(errno)); 01153 return -1; 01154 } else if (outfd > -1) { 01155 /* The FD we were watching has something waiting */ 01156 return 1; 01157 } else if (rchan) { 01158 f = ast_read(c); 01159 if(!f) { 01160 return -1; 01161 } 01162 01163 switch(f->frametype) { 01164 case AST_FRAME_DTMF: 01165 res = f->subclass; 01166 ast_frfree(f); 01167 return res; 01168 case AST_FRAME_CONTROL: 01169 switch(f->subclass) { 01170 case AST_CONTROL_HANGUP: 01171 ast_frfree(f); 01172 return -1; 01173 case AST_CONTROL_RINGING: 01174 case AST_CONTROL_ANSWER: 01175 /* Unimportant */ 01176 break; 01177 default: 01178 ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", f->subclass); 01179 } 01180 case AST_FRAME_VOICE: 01181 /* Write audio if appropriate */ 01182 if (audiofd > -1) 01183 write(audiofd, f->data, f->datalen); 01184 } 01185 /* Ignore */ 01186 ast_frfree(f); 01187 } 01188 } 01189 return 0; // Time is up 01190 }
|
|
||||||||||||
|
Write a frame to a channel.
Definition at line 1575 of file channel.c. References ast_channel::_softhangup, ast_check_hangup(), ast_deactivate_generator(), ast_do_masquerade(), AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frame_dump(), AST_FRAME_HTML, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_seekstream(), AST_SOFTHANGUP_DEV, ast_translate(), ast_writestream(), ast_channel::blocking, CHECK_BLOCKING, ast_frame::data, ast_frame::datalen, ast_channel::fout, ast_frame::frametype, ast_channel::generatordata, ast_channel::insmpl, ast_channel::lock, LOG_WARNING, ast_channel::masq, ast_channel::masqr, ast_channel::monitor, ast_channel::name, ast_channel::outsmpl, ast_channel::pvt, ast_frame::samples, SEEK_FORCECUR, ast_channel_pvt::send_html, ast_channel_pvt::send_text, ast_frame::subclass, ast_channel_pvt::write, ast_channel_monitor::write_stream, ast_channel_pvt::write_video, ast_channel::writeinterrupt, ast_channel_pvt::writetrans, and ast_channel::zombie. Referenced by ast_channel_bridge(), ast_dtmf_stream(), ast_prod(), ast_rtp_bridge(), and ast_write_video(). 01576 { 01577 int res = -1; 01578 struct ast_frame *f = NULL; 01579 /* Stop if we're a zombie or need a soft hangup */ 01580 ast_mutex_lock(&chan->lock); 01581 if (chan->zombie || ast_check_hangup(chan)) { 01582 ast_mutex_unlock(&chan->lock); 01583 return -1; 01584 } 01585 /* Handle any pending masquerades */ 01586 if (chan->masq) { 01587 if (ast_do_masquerade(chan)) { 01588 ast_log(LOG_WARNING, "Failed to perform masquerade\n"); 01589 ast_mutex_unlock(&chan->lock); 01590 return -1; 01591 } 01592 } 01593 if (chan->masqr) { 01594 ast_mutex_unlock(&chan->lock); 01595 return 0; 01596 } 01597 if (chan->generatordata) { 01598 if (chan->writeinterrupt) 01599 ast_deactivate_generator(chan); 01600 else { 01601 ast_mutex_unlock(&chan->lock); 01602 return 0; 01603 } 01604 } 01605 /* High bit prints debugging */ 01606 if (chan->fout & 0x80000000) 01607 ast_frame_dump(chan->name, fr, ">>"); 01608 CHECK_BLOCKING(chan); 01609 switch(fr->frametype) { 01610 case AST_FRAME_CONTROL: 01611 /* XXX Interpret control frames XXX */ 01612 ast_log(LOG_WARNING, "Don't know how to handle control frames yet\n"); 01613 break; 01614 case AST_FRAME_DTMF: 01615 chan->blocking = 0; 01616 ast_mutex_unlock(&chan->lock); 01617 res = do_senddigit(chan,fr->subclass); 01618 ast_mutex_lock(&chan->lock); 01619 CHECK_BLOCKING(chan); 01620 break; 01621 case AST_FRAME_TEXT: 01622 if (chan->pvt->send_text) 01623 res = chan->pvt->send_text(chan, (char *) fr->data); 01624 else 01625 res = 0; 01626 break; 01627 case AST_FRAME_HTML: 01628 if (chan->pvt->send_html) 01629 res = chan->pvt->send_html(chan, fr->subclass, (char *) fr->data, fr->datalen); 01630 else 01631 res = 0; 01632 break; 01633 case AST_FRAME_VIDEO: 01634 /* XXX Handle translation of video codecs one day XXX */ 01635 if (chan->pvt->write_video) 01636 res = chan->pvt->write_video(chan, fr); 01637 else 01638 res = 0; 01639 break; 01640 default: 01641 if (chan->pvt->write) { 01642 if (chan->pvt->writetrans) { 01643 f = ast_translate(chan->pvt->writetrans, fr, 0); 01644 } else 01645 f = fr; 01646 if (f) { 01647 res = chan->pvt->write(chan, f); 01648 if( chan->monitor && 01649 chan->monitor->write_stream && 01650 f && ( f->frametype == AST_FRAME_VOICE ) ) { 01651 #ifndef MONITOR_CONSTANT_DELAY 01652 int jump = chan->insmpl - chan->outsmpl - 2 * f->samples; 01653 if (jump >= 0) { 01654 if (ast_seekstream(chan->monitor->write_stream, jump + f->samples, SEEK_FORCECUR) == -1) 01655 ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n"); 01656 chan->outsmpl += jump + 2 * f->samples; 01657 } else 01658 chan->outsmpl += f->samples; 01659 #else 01660 int jump = chan->insmpl - chan->outsmpl; 01661 if (jump - MONITOR_DELAY >= 0) { 01662 if (ast_seekstream(chan->monitor->write_stream, jump - f->samples, SEEK_FORCECUR) == -1) 01663 ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n"); 01664 chan->outsmpl += jump; 01665 } else 01666 chan->outsmpl += f->samples; 01667 #endif 01668 if (ast_writestream(chan->monitor->write_stream, f) < 0) 01669 ast_log(LOG_WARNING, "Failed to write data to channel monitor write stream\n"); 01670 } 01671 } else 01672 res = 0; 01673 } 01674 } 01675 if (f && (f != fr)) 01676 ast_frfree(f); 01677 chan->blocking = 0; 01678 /* Consider a write failure to force a soft hangup */ 01679 if (res < 0) 01680 chan->_softhangup |= AST_SOFTHANGUP_DEV; 01681 else { 01682 if ((chan->fout & 0x7fffffff) == 0x7fffffff) 01683 chan->fout &= 0x80000000; 01684 else 01685 chan->fout++; 01686 } 01687 ast_mutex_unlock(&chan->lock); 01688 return res; 01689 }
|
|
||||||||||||
|
Write video frame to a channel.
Definition at line 1564 of file channel.c. References ast_write(), ast_channel::pvt, and ast_channel_pvt::write_video. 01565 { 01566 int res; 01567 if (!chan->pvt->write_video) 01568 return 0; 01569 res = ast_write(chan, fr); 01570 if (!res) 01571 res = 1; 01572 return res; 01573 }
|
1.4.4