static int cw_get_time_to_empty(struct cw_battery *cw_bat) { int ret; u8 reg_val; u16 value16; ret = cw_read(cw_bat->client, REG_RRT_ALERT, ®_val); if (ret < 0) return ret; value16 = reg_val; ret = cw_read(cw_bat->client, REG_RRT_ALERT + 1, ®_val); if (ret < 0) return ret; value16 = ((value16 << 8) + reg_val) & 0x1fff; return value16; }
static int changrab_exec(struct cw_channel *chan, int argc, char **argv) { int res=0; struct localuser *u; struct cw_channel *newchan; struct cw_channel *oldchan; struct cw_frame *f; struct cw_bridge_config config; if (argc < 1 || argc > 2) { cw_log(LOG_ERROR, "Syntax: %s\n", changrab_syntax); return -1; } if ((oldchan = my_cw_get_channel_by_name_locked(argv[0]))) { cw_mutex_unlock(&oldchan->lock); } else { cw_log(LOG_WARNING, "No Such Channel: %s\n", argv[0]); return -1; } if (argc > 1) { if (oldchan->_bridge && strchr(argv[1], 'b')) oldchan = oldchan->_bridge; if (strchr(argv[1],'r') && oldchan->_state == CW_STATE_UP) return -1; } LOCAL_USER_ADD(u); newchan = cw_channel_alloc(0); snprintf(newchan->name, sizeof (newchan->name), "ChanGrab/%s",oldchan->name); newchan->readformat = oldchan->readformat; newchan->writeformat = oldchan->writeformat; cw_channel_masquerade(newchan, oldchan); if((f = cw_read(newchan))) { cw_fr_free(f); memset(&config,0,sizeof(struct cw_bridge_config)); cw_set_flag(&(config.features_callee), CW_FEATURE_REDIRECT); cw_set_flag(&(config.features_caller), CW_FEATURE_REDIRECT); if(newchan->_state != CW_STATE_UP) { cw_answer(newchan); } chan->appl = "Bridged Call"; res = cw_bridge_call(chan, newchan, &config); cw_hangup(newchan); } LOCAL_USER_REMOVE(u); return res ? 0 : -1; }
static void *autoservice_run(void *ign) { struct cw_channel *mons[MAX_AUTOMONS]; int x; int ms; struct cw_channel *chan; struct asent *as; struct cw_frame *f; for(;;) { x = 0; cw_mutex_lock(&autolock); as = aslist; while(as) { if (!as->chan->_softhangup) { if (x < MAX_AUTOMONS) mons[x++] = as->chan; else cw_log(LOG_WARNING, "Exceeded maximum number of automatic monitoring events. Fix autoservice.c\n"); } as = as->next; } cw_mutex_unlock(&autolock); /* if (!aslist) break; */ ms = 500; chan = cw_waitfor_n(mons, x, &ms); if (chan) { /* Read and ignore anything that occurs */ f = cw_read(chan); if (f) cw_fr_free(f); } } asthread = CW_PTHREADT_NULL; return NULL; }
static int cw_get_alt(struct cw_battery *cw_bat) { int ret = 0; u8 reg_val; u8 value8 = 0; int alrt; ret = cw_read(cw_bat->client, REG_RRT_ALERT, ®_val); if (ret < 0) return ret; value8 = reg_val; alrt = value8 >>7; //dev_info(&cw_bat->client->dev, "read RRT %d%%. value16 0x%x\n", alrt, value16); value8 = value8&0x7f; reg_val = value8; ret = cw_write(cw_bat->client, REG_RRT_ALERT, ®_val); if(ret < 0) { dev_err(&cw_bat->client->dev, "Error clear ALRT\n"); return ret; } return alrt; }
int member_exec( struct cw_channel* chan, int argc, char **argv ) { int left = 0 ; int res; struct cw_conference *conf = NULL; struct cw_conf_member *member = NULL; struct cw_frame *f = NULL; cw_log( CW_CONF_DEBUG, "Launching NConference %s\n", "$Revision: 5349 $" ) ; if (chan->_state != CW_STATE_UP) if ( (res = cw_answer( chan )) ) { cw_log( LOG_ERROR, "unable to answer call\n" ) ; return -1 ; } member = create_member( chan, argc, argv ) ; // unable to create member, return an error if ( member == NULL ) { cw_log( LOG_ERROR, "unable to create member\n" ) ; return -1 ; } // // setup CallWeaver read/write formats // cw_log(CW_CONF_DEBUG, "CHANNEL INFO, CHANNEL => %s, DNID => %s, CALLER_ID => %s, ANI => %s\n", chan->name ? chan->name : "----", chan->cid.cid_dnid ? chan->cid.cid_dnid : "----", chan->cid.cid_num ? chan->cid.cid_num : "----", chan->cid.cid_ani ? chan->cid.cid_ani : "----"); cw_log(CW_CONF_DEBUG, "CHANNEL CODECS, CHANNEL => %s, NATIVE => %d, READ => %d, WRITE => %d\n", chan->name, chan->nativeformats, member->read_format, member->write_format); if ( cw_set_read_format( chan, member->read_format ) < 0 ) { cw_log( LOG_ERROR, "unable to set read format.\n" ) ; delete_member( member ) ; return -1 ; } // for right now, we'll send everything as slinear if ( cw_set_write_format( chan, member->write_format ) < 0 ) { cw_log( LOG_ERROR, "unable to set write format.\n" ) ; delete_member( member ) ; return -1 ; } // // setup a conference for the new member // conf = start_conference( member ) ; if ( conf == NULL ) { cw_log( LOG_ERROR, "unable to setup member conference\n" ) ; delete_member( member) ; return -1 ; } else { if (conf->is_locked && (member->type != MEMBERTYPE_MASTER) ) { if ( strcmp(conf->pin,member->pin) ) { conference_queue_sound(member,"conf-locked"); conf_play_soundqueue( member ); member->force_remove_flag = 1 ; } } else { member->conf = conf; if ( member->type == MEMBERTYPE_MASTER ) conf->auto_destroy = member->auto_destroy; } } if ( member->type == MEMBERTYPE_MASTER ) { conf->auto_destroy = member->auto_destroy; if ( strlen( member->pin ) > 0 ) { strncpy(conf->pin,member->pin,sizeof(conf->pin)); cw_log( CW_CONF_DEBUG, "Conference pin set to => %s\n", conf->pin ) ; } } // // process loop for new member ( this runs in it's own thread // cw_log( CW_CONF_DEBUG, "begin member event loop, channel => %s\n", chan->name ) ; // Activate the generator for the channel. res = cw_conf_member_genactivate( member ); if ( !res ) { member->force_remove_flag = 1; cw_log( CW_CONF_DEBUG, "member marked for removal => %s\n", chan->name ) ; } //Play the join info messages if (!member->force_remove_flag && !member->quiet_mode) { conference_queue_sound( member, "conf-youareinconfnum" ); conference_queue_number( member, member->id ); } // The member at the very beginningis speaking member->is_speaking = 1 ; // tell conference_exec we're ready for frames member->active_flag = 1 ; //Main loop. while ( !member->force_remove_flag || member->soundq != NULL ) { usleep(1000); // make sure we have a channel to process if ( chan == NULL ) { cw_log( LOG_NOTICE, "member channel has closed\n" ) ; break ; } //-----------------// // INCOMING FRAMES // //-----------------// if ( member->force_remove_flag == 1 ) { // break to the loop break; } // wait for an event on this channel int waittime = ( member->framelen == 0 ) ? CW_CONF_WAITFOR_TIME : member->framelen; left = cw_waitfor( chan, waittime ) ; f = NULL; if ( left < 0 ) { // an error occured cw_log( LOG_NOTICE, "an error occured waiting for a frame, channel => %s, error => %d\n", chan->name, left ) ; } else if ( left == 0 ) { // No frame avalaible member->lostframecount ++; // We have lost a frame. // In this case, we queue some silence // Sothat if we keep loosing frames, // there will be no glitching in the conference. // Set the speaking state to 0. if ( member->lostframecount == 1 ) { queue_incoming_silent_frame(member,1); } member->is_speaking = 0; } else if ( left > 0 ) { // a frame has come in before the latency timeout // was reached, so we process the frame // let's reset the lost frame count if ( member->lostframecount ) { member->lostframecount = 0; // If vad is not enabled, then set the speaking state back to 1 if ( !member->enable_vad ) member->is_speaking = 1; } f = cw_read( chan ) ; if ( f == NULL ) { cw_log( CW_CONF_DEBUG, "unable to read from channel, channel => %s. Got Hangup.\n", chan->name ) ; queue_incoming_silent_frame(member,5); member->is_speaking = 0; break ; } else { /* cw_log( CW_CONF_DEBUG, "Read (PRE dsp), channel => %s, datalen: %d samplefreq: %ld len: %ld samples %d class: %d\n", chan->name, f->datalen, member->samplefreq, f->len, f->samples, f->subclass) ; */ if ( member->samplefreq == 0 && f->samples != 0 ) { if ( ( f->len == 0 ) && ( f->datalen == 320 ) && ( f->samples == 160 ) ) member->framelen = 20; // This is probably chan_zap not setting the correct len. else member->framelen = f->len; // frame length in milliseconds member->datalen = f->datalen; // frame length in milliseconds member->samples = f->samples; // number of samples in framelen member->samplefreq = (int)(member->samples/member->framelen)*1000; // calculated sample frequency cw_log( CW_CONF_DEBUG, "MEMBER FRAME DATA: datalen %d samples %d len(ms) %ld, offset: %d \n", f->datalen, f->samples, f->len, f->offset ); /* // Try to initialize the smoother, only once queue_incoming_silent_frame(member); if ( member->smooth_size_in < 0 ) { member->smooth_size_in = f->samples ; cw_log( CW_CONF_DEBUG, "Initializing Smooother.\n"); member->inSmoother = cw_smoother_new(member->smooth_size_in); if ( member->inSmoother == NULL ) cw_log( CW_CONF_DEBUG, "Smoother initialization failed\n"); } */ } if ( ( (member->framelen != f->len ) && ( f->len !=0 ) ) || ( (member->samples != f->samples ) && ( f->samples !=0 ) && ( f->len !=0 ) ) ) { cw_log( CW_CONF_DEBUG, "FRAME CHANGE : samples %d len(ms) %ld\n", f->samples, f->len ); cw_log( CW_CONF_DEBUG, "FRAME SHOULDBE: samples %d len(ms) %ld\n", member->samples, member->framelen ); if (member->samples == 0 ) { member->framelen = f->len; // frame length in milliseconds member->datalen = f->datalen; // frame length in milliseconds member->samples = f->samples; // number of samples in framelen member->samplefreq = (int) ( f->samples/f->len)*1000; // calculated sample frequency } } // This fix is for chan_zap // Chan_zap NEVER sets framelen value. // Probably when adding support to 16Khz we should add a check for this. if ( ( member->framelen == 0 ) && ( member->datalen == 320 ) && ( member->samples == 160 ) ) member->framelen = 20; } } // actually process the frame. res = process_incoming(member, f); if (member->force_remove_flag) member->remove_flag = 1 ; } // // clean up // if ( member != NULL ) member->remove_flag = 1 ; cw_log( CW_CONF_DEBUG, "end member event loop, time_entered => %ld - removal: %d\n", member->time_entered.tv_sec, member->remove_flag ) ; //cw_log( CW_CONF_DEBUG, "Deactivating generator - Channel => %s\n", member->chan->name ) ; cw_generator_deactivate(chan); return -1 ; }
static int pipe_exec(struct cw_channel *chan, int argc, char **argv) { int res=0; struct localuser *u; int fds[2]; int ms = -1; int pid = -1; int owriteformat; int oreadformat; int timeout = 2000; struct timeval last; struct cw_frame *f; struct myframe { struct cw_frame f; char offset[CW_FRIENDLY_OFFSET]; short frdata[160]; } myf; last.tv_usec = 0; last.tv_sec = 0; if (argc < 2 || argc > 3) { cw_log(LOG_ERROR, "Syntax: %s\n", pipe_syntax); return -1; } LOCAL_USER_ADD(u); if (pipe(fds)) { cw_log(LOG_WARNING, "Unable to create pipe\n"); LOCAL_USER_REMOVE(u); return -1; } // MOC: Setting non blocking doesn't seem to change anything // flags = fcntl(fds[1], F_GETFL); // fcntl(fds[1], F_SETFL, flags | O_NONBLOCK); // flags = fcntl(fds[0], F_GETFL); // fcntl(fds[0], F_SETFL, flags | O_NONBLOCK); cw_stopstream(chan); if (chan->_state != CW_STATE_UP) res = cw_answer(chan); if (res) { close(fds[0]); close(fds[1]); cw_log(LOG_WARNING, "Answer failed!\n"); LOCAL_USER_REMOVE(u); return -1; } oreadformat = chan->readformat; res = cw_set_read_format(chan, CW_FORMAT_SLINEAR); owriteformat = chan->writeformat; res += cw_set_write_format(chan, CW_FORMAT_SLINEAR); if (res < 0) { close(fds[0]); close(fds[1]); cw_log(LOG_WARNING, "Unable to set write format to signed linear\n"); LOCAL_USER_REMOVE(u); return -1; } res = pipeencode(argv[1], argv[2], fds[0], fds[1]); if (res >= 0) { last = cw_tvnow(); last.tv_sec += 1; pid = res; for (;;) { /* Wait for audio, and stream */ if (argv[0][0] == '0') { /* START WRITE TO FD */ ms = cw_waitfor(chan, 10); if (ms < 0) { cw_log(LOG_DEBUG, "Hangup detected\n"); res = -1; break; } else if (ms > 0) { f = cw_read(chan); if (!f) { cw_log(LOG_DEBUG, "Null frame == hangup() detected\n"); res = -1; break; } if (f->frametype == CW_FRAME_DTMF) { cw_log(LOG_DEBUG, "User pressed a key\n"); cw_fr_free(f); res = 0; break; } if (f->frametype == CW_FRAME_VOICE) { res = write(fds[1], f->data, f->datalen); if (res < 0) { if (errno != EAGAIN) { cw_log(LOG_WARNING, "Write failed to pipe: %s\n", strerror(errno)); cw_fr_free(f); res = -1; break; } } } cw_fr_free(f); } /* END WRITE TO FD */ } else { /* START WRITE CHANNEL */ ms = cw_tvdiff_ms(last, cw_tvnow()); if (ms <= 0) { res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata), timeout); if (res > 0) { cw_fr_init_ex(&myf.f, CW_FRAME_VOICE, CW_FORMAT_SLINEAR, __PRETTY_FUNCTION__); myf.f.datalen = res; myf.f.samples = res/sizeof(int16_t); myf.f.offset = CW_FRIENDLY_OFFSET; myf.f.data = myf.frdata; if (cw_write(chan, &myf.f) < 0) { res = -1; break; } } else { cw_log(LOG_DEBUG, "No more stream\n"); res = 0; break; } last = cw_tvadd(last, cw_samp2tv(myf.f.samples, 8000)); } else { ms = cw_waitfor(chan, ms); if (ms < 0) { cw_log(LOG_DEBUG, "Hangup detected\n"); res = -1; break; } if (ms) { f = cw_read(chan); if (!f) { cw_log(LOG_DEBUG, "Null frame == hangup() detected\n"); res = -1; break; } if (f->frametype == CW_FRAME_DTMF) { cw_log(LOG_DEBUG, "User pressed a key\n"); cw_fr_free(f); res = 0; break; } cw_fr_free(f); } } /* END WRITE CHANNEL */ } } } close(fds[0]); close(fds[1]); LOCAL_USER_REMOVE(u); if (pid > -1) kill(pid, SIGKILL); if (!res && oreadformat) cw_set_read_format(chan, oreadformat); if (!res && owriteformat) cw_set_write_format(chan, owriteformat); return res; }
static int record_exec(struct cw_channel *chan, int argc, char **argv) { int res = 0; int count = 0; int percentflag = 0; char *ext = NULL; int i = 0; char tmp[256]; struct cw_filestream *s = '\0'; struct localuser *u; struct cw_frame *f = NULL; struct cw_dsp *sildet = NULL; /* silence detector dsp */ int totalsilence = 0; int dspsilence = 0; int silence = 0; /* amount of silence to allow */ int gotsilence = 0; /* did we timeout for silence? */ int maxduration = 0; /* max duration of recording in milliseconds */ int gottimeout = 0; /* did we timeout for maxduration exceeded? */ int option_skip = 0; int option_noanswer = 0; int option_append = 0; int terminator = '#'; int option_quiet = 0; int rfmt = 0; int flags; if (argc < 1 || argc > 4 || !argv[0][0]) { cw_log(LOG_ERROR, "Syntax: %s\n", record_syntax); return -1; } LOCAL_USER_ADD(u); if (strstr(argv[0], "%d")) percentflag = 1; ext = strrchr(argv[0], '.'); /* to support filename with a . in the filename, not format */ if (!ext) ext = strchr(argv[0], ':'); if (ext) { *ext = '\0'; ext++; } if (!ext) { cw_log(LOG_WARNING, "No extension specified to filename!\n"); LOCAL_USER_REMOVE(u); return -1; } if (argc > 1) { silence = atoi(argv[1]); if (silence > 0) silence *= 1000; else if (silence < 0) silence = 0; } if (argc > 2) { maxduration = atoi(argv[2]); if (maxduration > 0) maxduration *= 1000; else if (maxduration < 0) maxduration = 0; } if (argc > 3) { /* Retain backwards compatibility with old style options */ if (!strcasecmp(argv[3], "skip")) option_skip = 1; else if (!strcasecmp(argv[3], "noanswer")) option_noanswer = 1; else { if (strchr(argv[3], 's')) option_skip = 1; if (strchr(argv[3], 'n')) option_noanswer = 1; if (strchr(argv[3], 'a')) option_append = 1; if (strchr(argv[3], 't')) terminator = '*'; if (strchr(argv[3], 'q')) option_quiet = 1; } } /* done parsing */ /* these are to allow the use of the %d in the config file for a wild card of sort to create a new file with the inputed name scheme */ if (percentflag) { char *piece[100]; int pieces; /* Separate each piece out by the format specifier */ pieces = cw_separate_app_args(argv[0], '%', arraysize(piece), piece); do { int tmplen; /* First piece has no leading percent, so it's copied verbatim */ cw_copy_string(tmp, piece[0], sizeof(tmp)); tmplen = strlen(tmp); for (i = 1; i < pieces; i++) { if (piece[i][0] == 'd') { /* Substitute the count */ snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "%d", count); tmplen += strlen(tmp + tmplen); } else if (tmplen + 2 < sizeof(tmp)) { /* Unknown format specifier - just copy it verbatim */ tmp[tmplen++] = '%'; tmp[tmplen++] = piece[i][0]; } /* Copy the remaining portion of the piece */ cw_copy_string(tmp + tmplen, &(piece[i][1]), sizeof(tmp) - tmplen); } count++; } while ( cw_fileexists(tmp, ext, chan->language) != -1 ); pbx_builtin_setvar_helper(chan, "RECORDED_FILE", tmp); } else strncpy(tmp, argv[0], sizeof(tmp)-1); /* end of routine mentioned */ if (chan->_state != CW_STATE_UP) { if (option_skip) { /* At the user's option, skip if the line is not up */ LOCAL_USER_REMOVE(u); return 0; } else if (!option_noanswer) { /* Otherwise answer unless we're supposed to record while on-hook */ res = cw_answer(chan); } } if (!res) { if (!option_quiet) { /* Some code to play a nice little beep to signify the start of the record operation */ res = cw_streamfile(chan, "beep", chan->language); if (!res) { res = cw_waitstream(chan, ""); } else { cw_log(LOG_WARNING, "cw_streamfile failed on %s\n", chan->name); } cw_stopstream(chan); } /* The end of beep code. Now the recording starts */ if (silence > 0) { rfmt = chan->readformat; res = cw_set_read_format(chan, CW_FORMAT_SLINEAR); if (res < 0) { cw_log(LOG_WARNING, "Unable to set to linear mode, giving up\n"); LOCAL_USER_REMOVE(u); return -1; } sildet = cw_dsp_new(); if (!sildet) { cw_log(LOG_WARNING, "Unable to create silence detector :(\n"); LOCAL_USER_REMOVE(u); return -1; } cw_dsp_set_threshold(sildet, 256); } flags = option_append ? O_CREAT|O_APPEND|O_WRONLY : O_CREAT|O_TRUNC|O_WRONLY; s = cw_writefile( tmp, ext, NULL, flags , 0, 0644); if (s) { int waitres; /* Request a video update */ cw_indicate(chan, CW_CONTROL_VIDUPDATE); if (maxduration <= 0) maxduration = -1; while ((waitres = cw_waitfor(chan, maxduration)) > -1) { if (maxduration > 0) { if (waitres == 0) { gottimeout = 1; break; } maxduration = waitres; } f = cw_read(chan); if (!f) { res = -1; break; } if (f->frametype == CW_FRAME_VOICE) { res = cw_writestream(s, f); if (res) { cw_log(LOG_WARNING, "Problem writing frame\n"); cw_fr_free(f); break; } if (silence > 0) { dspsilence = 0; cw_dsp_silence(sildet, f, &dspsilence); if (dspsilence) { totalsilence = dspsilence; } else { totalsilence = 0; } if (totalsilence > silence) { /* Ended happily with silence */ cw_fr_free(f); gotsilence = 1; break; } } } if (f->frametype == CW_FRAME_VIDEO) { res = cw_writestream(s, f); if (res) { cw_log(LOG_WARNING, "Problem writing frame\n"); cw_fr_free(f); break; } } if ((f->frametype == CW_FRAME_DTMF) && (f->subclass == terminator)) { cw_fr_free(f); break; } cw_fr_free(f); } if (!f) { cw_log(LOG_DEBUG, "Got hangup\n"); res = -1; } if (gotsilence) { cw_stream_rewind(s, silence-1000); cw_truncstream(s); } else if (!gottimeout) { /* Strip off the last 1/4 second of it */ cw_stream_rewind(s, 250); cw_truncstream(s); } cw_closestream(s); } else cw_log(LOG_WARNING, "Could not create file %s\n", tmp); } else cw_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name); if ((silence > 0) && rfmt) { res = cw_set_read_format(chan, rfmt); if (res) cw_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name); if (sildet) cw_dsp_free(sildet); } LOCAL_USER_REMOVE(u); return res; }
static int fax_audio(struct cw_channel *chan, fax_state_t *fax, const char *file, int calling_party, int verbose) { char *x; struct cw_frame *inf = NULL; struct cw_frame outf; int ready = 1; int samples = 0; int res = 0; int len = 0; int generator_mode = 0; uint64_t begin = 0; uint64_t received_frames = 0; uint8_t __buf[sizeof(uint16_t)*MAX_BLOCK_SIZE + 2*CW_FRIENDLY_OFFSET]; uint8_t *buf = __buf + CW_FRIENDLY_OFFSET; #if 0 struct cw_frame *dspf = NULL; struct cw_dsp *dsp = NULL; #endif uint64_t voice_frames; t30_state_t *t30; memset(fax, 0, sizeof(*fax)); if (fax_init(fax, calling_party) == NULL) { cw_log(LOG_WARNING, "Unable to start FAX\n"); return -1; } t30 = fax_get_t30_state(fax); fax_set_transmit_on_idle(fax, TRUE); span_log_set_message_handler(&fax->logging, span_message); span_log_set_message_handler(&t30->logging, span_message); if (verbose) { span_log_set_level(&fax->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); span_log_set_level(&t30->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); } fax_set_common(chan, t30, file, calling_party, verbose); fax_set_transmit_on_idle(fax, TRUE); if (calling_party) { voice_frames = 0; } else { #if 0 /* Initializing the DSP */ if ((dsp = cw_dsp_new()) == NULL) { cw_log(LOG_WARNING, "Unable to allocate DSP!\n"); } else { cw_dsp_set_threshold(dsp, 256); cw_dsp_set_features(dsp, DSP_FEATURE_DTMF_DETECT | DSP_FEATURE_FAX_CNG_DETECT); cw_dsp_digitmode(dsp, DSP_DIGITMODE_DTMF | DSP_DIGITMODE_RELAXDTMF); } #endif voice_frames = 1; } /* This is the main loop */ begin = nowis(); while (ready && ready_to_talk(chan)) { if (chan->t38_status == T38_NEGOTIATED) break; if ((res = cw_waitfor(chan, 20)) < 0) { ready = 0; break; } if (!t30_call_active(t30)) break; if ((inf = cw_read(chan)) == NULL) { ready = 0; break; } /* We got a frame */ if (inf->frametype == CW_FRAME_VOICE) { #if 0 if (dsp) { if ((dspf = cw_frdup(inf))) dspf = cw_dsp_process(chan, dsp, dspf); if (dspf) { if (dspf->frametype == CW_FRAME_DTMF) { if (dspf->subclass == 'f') { cw_log(LOG_DEBUG, "Fax detected in RxFax !!!\n"); cw_app_request_t38(chan); /* Prevent any further attempts to negotiate T.38 */ cw_dsp_free(dsp); dsp = NULL; } } cw_fr_free(dspf); dspf = NULL; } } #else if (voice_frames) { /* Wait a little before trying to switch to T.38, as some things don't seem to like entirely missing the audio. */ if (++voice_frames == 100) { cw_log(LOG_DEBUG, "Requesting T.38 negotation in RxFax !!!\n"); cw_app_request_t38(chan); voice_frames = 0; } } #endif received_frames++; if (fax_rx(fax, inf->data, inf->samples)) break; samples = (inf->samples <= MAX_BLOCK_SIZE) ? inf->samples : MAX_BLOCK_SIZE; if ((len = fax_tx(fax, (int16_t *) &buf[CW_FRIENDLY_OFFSET], samples)) > 0) { cw_fr_init_ex(&outf, CW_FRAME_VOICE, CW_FORMAT_SLINEAR, "FAX"); outf.datalen = len*sizeof(int16_t); outf.samples = len; outf.data = &buf[CW_FRIENDLY_OFFSET]; outf.offset = CW_FRIENDLY_OFFSET; if (cw_write(chan, &outf) < 0) { cw_log(LOG_WARNING, "Unable to write frame to channel; %s\n", strerror(errno)); break; } } } else { if ((nowis() - begin) > 1000000) { if (received_frames < 20) { /* Just to be sure we have had no frames ... */ cw_log(LOG_NOTICE, "Switching to generator mode\n"); generator_mode = 1; break; } } } cw_fr_free(inf); inf = NULL; } if (inf) { cw_fr_free(inf); inf = NULL; } if (generator_mode) { /* This is activated when we don't receive any frame for X seconds (see above)... */ cw_log(LOG_NOTICE, "Starting generator\n"); #if 0 if (dsp) cw_dsp_reset(dsp); #endif cw_generator_activate(chan, &faxgen, fax); while (ready && ready_to_talk(chan)) { if (chan->t38_status == T38_NEGOTIATED) break; if ((res = cw_waitfor(chan, 20)) < 0) { ready = 0; break; } if (!t30_call_active(t30)) break; if ((inf = cw_read(chan)) == NULL) { ready = 0; break; } /* We got a frame */ if (inf->frametype == CW_FRAME_VOICE) { #if 0 if (dsp) { if ((dspf = cw_frdup(inf))) dspf = cw_dsp_process(chan, dsp, dspf); if (dspf) { if (dspf->frametype == CW_FRAME_DTMF) { if (dspf->subclass == 'f') { cw_log(LOG_DEBUG, "Fax detected in RxFax !!!\n"); cw_app_request_t38(chan); /* Prevent any further attempts to negotiate T.38 */ cw_dsp_free(dsp); dsp = NULL; } } cw_fr_free(dspf); dspf = NULL; } } #else if (voice_frames) { if (++voice_frames == 100) { cw_log(LOG_DEBUG, "Requesting T.38 negotation in RxFax !!!\n"); cw_app_request_t38(chan); voice_frames = 0; } } #endif if (fax_rx(fax, inf->data, inf->samples)) { ready = 0; break; } } cw_fr_free(inf); inf = NULL; } if (inf) { cw_fr_free(inf); inf = NULL; } cw_log(LOG_NOTICE, "Stopping generator\n"); cw_generator_deactivate(chan); } #if 0 if (dsp) cw_dsp_free(dsp); #endif return ready; }
static int fax_t38(struct cw_channel *chan, t38_terminal_state_t *t38, const char *file, int calling_party, int verbose) { char *x; struct cw_frame *inf = NULL; int ready = 1; int res = 0; uint64_t now; uint64_t passage; t30_state_t *t30; t38_core_state_t *t38_core; memset(t38, 0, sizeof(*t38)); if (t38_terminal_init(t38, calling_party, t38_tx_packet_handler, chan) == NULL) { cw_log(LOG_WARNING, "Unable to start T.38 termination.\n"); return -1; } t30 = t38_terminal_get_t30_state(t38); t38_core = t38_terminal_get_t38_core_state(t38); span_log_set_message_handler(&t38->logging, span_message); span_log_set_message_handler(&t30->logging, span_message); span_log_set_message_handler(&t38_core->logging, span_message); if (verbose) { span_log_set_level(&t38->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); span_log_set_level(&t30->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); span_log_set_level(&t38_core->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); } fax_set_common(chan, t30, file, calling_party, verbose); passage = nowis(); t38_terminal_set_tep_mode(t38, TRUE); while (ready && ready_to_talk(chan)) { if (chan->t38_status != T38_NEGOTIATED) break; if ((res = cw_waitfor(chan, 20)) < 0) { ready = 0; break; } now = nowis(); t38_terminal_send_timeout(t38, (now - passage)/125); passage = now; /* End application when T38/T30 has finished */ if (!t30_call_active(t30)) break; if ((inf = cw_read(chan)) == NULL) { ready = 0; break; } if (inf->frametype == CW_FRAME_MODEM && inf->subclass == CW_MODEM_T38) t38_core_rx_ifp_packet(t38_core, inf->data, inf->datalen, inf->seq_no); cw_fr_free(inf); } return ready; }
static int visdn_ppp_exec(struct cw_channel *chan, int argc, char **argv) { struct visdn_chan *visdn_chan; const char **nargv; struct localuser *u; struct cw_frame *f; int res=-1; LOCAL_USER_ADD(u); if (chan->_state != CW_STATE_UP) cw_answer(chan); cw_mutex_lock(&chan->lock); if (strcmp(chan->type, "VISDN")) { cw_log(LOG_WARNING, "Only VISDN channels may be connected to" " this application\n"); cw_mutex_unlock(&chan->lock); return -1; } visdn_chan = chan->tech_pvt; if (!strlen(visdn_chan->visdn_chanid)) { cw_log(LOG_WARNING, "vISDN crossconnector channel ID not present\n"); cw_mutex_unlock(&chan->lock); return -1; } nargv = alloca((2 + argc + 3 + 1) * sizeof(nargv[0])); nargv[0] = PPP_EXEC; nargv[1] = "nodetach"; memcpy(nargv + 2, argc, argv * sizeof(argv[0])); nargv[2 + argc + 0] = "plugin"; nargv[2 + argc + 1] = "visdn.so"; nargv[2 + argc + 2] = visdn_chan->visdn_chanid; nargv[2 + argc + 3] = NULL; cw_mutex_unlock(&chan->lock); #if 0 int i; for (i=0;i<argc;i++) { cw_log(LOG_NOTICE, "Arg %d: %s\n", i, argv[i]); } #endif signal(SIGCHLD, SIG_DFL); pid_t pid = spawn_ppp(chan, nargv); if (pid < 0) { cw_log(LOG_WARNING, "Failed to spawn pppd\n"); return -1; } while(cw_waitfor(chan, -1) > -1) { f = cw_read(chan); if (!f) { cw_log(LOG_NOTICE, "Channel '%s' hungup." " Signalling PPP at %d to die...\n", chan->name, pid); kill(pid, SIGTERM); break; } cw_fr_free(f); int status; res = wait4(pid, &status, WNOHANG, NULL); if (res < 0) { cw_log(LOG_WARNING, "wait4 returned %d: %s\n", res, strerror(errno)); break; } else if (res > 0) { if (option_verbose > 2) { if (WIFEXITED(status)) { cw_verbose(VERBOSE_PREFIX_3 "PPP on %s terminated with status %d\n", chan->name, WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { cw_verbose(VERBOSE_PREFIX_3 "PPP on %s terminated with signal %d\n", chan->name, WTERMSIG(status)); } else { cw_verbose(VERBOSE_PREFIX_3 "PPP on %s terminated weirdly.\n", chan->name); } } break; } } LOCAL_USER_REMOVE(u); return res; }
static int cw_init(struct cw_battery *cw_bat) { int ret; int i; u8 reg_val = MODE_SLEEP; #if 0 ret = cw_read(cw_bat->client, REG_MODE, ®_val); if (ret < 0) return ret; #endif if ((reg_val & MODE_SLEEP_MASK) == MODE_SLEEP) { reg_val = MODE_NORMAL; ret = cw_write(cw_bat->client, REG_MODE, ®_val); if (ret < 0) return ret; } ret = cw_read(cw_bat->client, REG_CONFIG, ®_val); if (ret < 0) return ret; if ((reg_val & 0xf8) != ATHD) { dev_info(&cw_bat->client->dev, "the new ATHD have not set\n"); reg_val &= 0x07; /* clear ATHD */ reg_val |= ATHD; /* set ATHD */ ret = cw_write(cw_bat->client, REG_CONFIG, ®_val); if (ret < 0) return ret; } ret = cw_read(cw_bat->client, REG_CONFIG, ®_val); if (ret < 0) return ret; if (!(reg_val & CONFIG_UPDATE_FLG)) { dev_info(&cw_bat->client->dev, "update flag for new battery info have not set\n"); ret = cw_update_config_info(cw_bat); if (ret < 0) return ret; } else { for(i = 0; i < SIZE_BATINFO; i++) { ret = cw_read(cw_bat->client, (REG_BATINFO + i), ®_val); if (ret < 0) return ret; if (cw_bat->plat_data->cw_bat_config_info[i] != reg_val) break; } if (i != SIZE_BATINFO) { dev_info(&cw_bat->client->dev, "update flag for new battery info have not set\n"); ret = cw_update_config_info(cw_bat); if (ret < 0) return ret; } } for (i = 0; i < 30; i++) { ret = cw_read(cw_bat->client, REG_SOC, ®_val); if (ret < 0) return ret; else if (ret != 0xff) break; msleep(100); if (i > 25) dev_err(&cw_bat->client->dev, "cw2015/cw2013 input unvalid power error\n"); } return 0; }
static int cw_update_config_info(struct cw_battery *cw_bat) { int ret; u8 reg_val; int i; u8 reset_val; dev_info(&cw_bat->client->dev, "func: %s-------\n", __func__); /* make sure no in sleep mode */ ret = cw_read(cw_bat->client, REG_MODE, ®_val); if (ret < 0) return ret; reset_val = reg_val; if((reg_val & MODE_SLEEP_MASK) == MODE_SLEEP) { dev_err(&cw_bat->client->dev, "Error, device in sleep mode, cannot update battery info\n"); return -1; } /* update new battery info */ for (i = 0; i < SIZE_BATINFO; i++) { dev_info(&cw_bat->client->dev, "cw_bat->plat_data->cw_bat_config_info[%d] = 0x%x\n", i, \ cw_bat->plat_data->cw_bat_config_info[i]); ret = cw_write(cw_bat->client, REG_BATINFO + i, &cw_bat->plat_data->cw_bat_config_info[i]); if (ret < 0) return ret; } /* readback & check */ for (i = 0; i < SIZE_BATINFO; i++) { ret = cw_read(cw_bat->client, REG_BATINFO + i, ®_val); if (reg_val != cw_bat->plat_data->cw_bat_config_info[i]) return -1; } /* set cw2015/cw2013 to use new battery info */ ret = cw_read(cw_bat->client, REG_CONFIG, ®_val); if (ret < 0) return ret; reg_val |= CONFIG_UPDATE_FLG; /* set UPDATE_FLAG */ reg_val &= 0x07; /* clear ATHD */ reg_val |= ATHD; /* set ATHD */ ret = cw_write(cw_bat->client, REG_CONFIG, ®_val); if (ret < 0) return ret; /* check 2015/cw2013 for ATHD & update_flag */ ret = cw_read(cw_bat->client, REG_CONFIG, ®_val); if (ret < 0) return ret; if (!(reg_val & CONFIG_UPDATE_FLG)) { dev_info(&cw_bat->client->dev, "update flag for new battery info have not set..\n"); } if ((reg_val & 0xf8) != ATHD) { dev_info(&cw_bat->client->dev, "the new ATHD have not set..\n"); } /* reset */ reset_val &= ~(MODE_RESTART); reg_val = reset_val | MODE_RESTART; ret = cw_write(cw_bat->client, REG_MODE, ®_val); if (ret < 0) return ret; msleep(10); ret = cw_write(cw_bat->client, REG_MODE, &reset_val); if (ret < 0) return ret; return 0; }
int cw_play_and_prepend(struct cw_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int *duration, int beep, int silencethreshold, int maxsilence) { int d = 0; char *fmts; char comment[256]; int x, fmtcnt=1, res=-1,outmsg=0; struct cw_frame *f; struct cw_filestream *others[MAX_OTHER_FORMATS]; struct cw_filestream *realfiles[MAX_OTHER_FORMATS]; char *sfmt[MAX_OTHER_FORMATS]; char *stringp=NULL; time_t start, end; struct cw_dsp *sildet; /* silence detector dsp */ int totalsilence = 0; int dspsilence = 0; int gotsilence = 0; /* did we timeout for silence? */ int rfmt=0; char prependfile[80]; if (silencethreshold < 0) silencethreshold = global_silence_threshold; if (maxsilence < 0) maxsilence = global_maxsilence; /* barf if no pointer passed to store duration in */ if (duration == NULL) { cw_log(LOG_WARNING, "Error play_and_prepend called without duration pointer\n"); return -1; } cw_log(LOG_DEBUG,"play_and_prepend: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt); snprintf(comment,sizeof(comment),"Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name); if (playfile || beep) { if (!beep) d = cw_play_and_wait(chan, playfile); if (d > -1) d = cw_streamfile(chan, "beep",chan->language); if (!d) d = cw_waitstream(chan,""); if (d < 0) return -1; } cw_copy_string(prependfile, recordfile, sizeof(prependfile)); strncat(prependfile, "-prepend", sizeof(prependfile) - strlen(prependfile) - 1); fmts = cw_strdupa(fmt); stringp=fmts; strsep(&stringp, "|,"); cw_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts); sfmt[0] = cw_strdupa(fmts); while((fmt = strsep(&stringp, "|,"))) { if (fmtcnt > MAX_OTHER_FORMATS - 1) { cw_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app_voicemail.c\n"); break; } sfmt[fmtcnt++] = cw_strdupa(fmt); } time(&start); end=start; /* pre-initialize end to be same as start in case we never get into loop */ for (x=0;x<fmtcnt;x++) { others[x] = cw_writefile(prependfile, sfmt[x], comment, O_TRUNC, 0, 0700); cw_verbose( VERBOSE_PREFIX_3 "x=%d, open writing: %s format: %s, %p\n", x, prependfile, sfmt[x], others[x]); if (!others[x]) { break; } } sildet = cw_dsp_new(); /* Create the silence detector */ if (!sildet) { cw_log(LOG_WARNING, "Unable to create silence detector :(\n"); return -1; } cw_dsp_set_threshold(sildet, silencethreshold); if (maxsilence > 0) { rfmt = chan->readformat; res = cw_set_read_format(chan, CW_FORMAT_SLINEAR); if (res < 0) { cw_log(LOG_WARNING, "Unable to set to linear mode, giving up\n"); return -1; } } if (x == fmtcnt) { /* Loop forever, writing the packets we read to the writer(s), until we read a # or get a hangup */ f = NULL; for(;;) { res = cw_waitfor(chan, 2000); if (!res) { cw_log(LOG_DEBUG, "One waitfor failed, trying another\n"); /* Try one more time in case of masq */ res = cw_waitfor(chan, 2000); if (!res) { cw_log(LOG_WARNING, "No audio available on %s??\n", chan->name); res = -1; } } if (res < 0) { f = NULL; break; } f = cw_read(chan); if (!f) break; if (f->frametype == CW_FRAME_VOICE) { /* write each format */ for (x=0;x<fmtcnt;x++) { if (!others[x]) break; res = cw_writestream(others[x], f); } /* Silence Detection */ if (maxsilence > 0) { dspsilence = 0; cw_dsp_silence(sildet, f, &dspsilence); if (dspsilence) totalsilence = dspsilence; else totalsilence = 0; if (totalsilence > maxsilence) { /* Ended happily with silence */ if (option_verbose > 2) cw_verbose( VERBOSE_PREFIX_3 "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000); cw_fr_free(f); gotsilence = 1; outmsg=2; break; } } /* Exit on any error */ if (res) { cw_log(LOG_WARNING, "Error writing frame\n"); cw_fr_free(f); break; } } else if (f->frametype == CW_FRAME_VIDEO) { /* Write only once */ cw_writestream(others[0], f); } else if (f->frametype == CW_FRAME_DTMF) { /* stop recording with any digit */ if (option_verbose > 2) cw_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass); res = 't'; outmsg = 2; cw_fr_free(f); break; } if (maxtime) { time(&end); if (maxtime < (end - start)) { if (option_verbose > 2) cw_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n"); res = 't'; outmsg=2; cw_fr_free(f); break; } } cw_fr_free(f); } if (end == start) time(&end); if (!f) { if (option_verbose > 2) cw_verbose( VERBOSE_PREFIX_3 "User hung up\n"); res = -1; outmsg=1; #if 0 /* delete all the prepend files */ for (x=0;x<fmtcnt;x++) { if (!others[x]) break; cw_closestream(others[x]); cw_filedelete(prependfile, sfmt[x]); } #endif } } else { cw_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", prependfile, sfmt[x]); } *duration = end - start; #if 0 if (outmsg > 1) { #else if (outmsg) { #endif struct cw_frame *fr; for (x=0;x<fmtcnt;x++) { snprintf(comment, sizeof(comment), "Opening the real file %s.%s\n", recordfile, sfmt[x]); realfiles[x] = cw_readfile(recordfile, sfmt[x], comment, O_RDONLY, 0, 0); if (!others[x] || !realfiles[x]) break; if (totalsilence) cw_stream_rewind(others[x], totalsilence-200); else cw_stream_rewind(others[x], 200); cw_truncstream(others[x]); /* add the original file too */ while ((fr = cw_readframe(realfiles[x]))) { cw_writestream(others[x],fr); } cw_closestream(others[x]); cw_closestream(realfiles[x]); cw_filerename(prependfile, recordfile, sfmt[x]); #if 0 cw_verbose("Recording Format: sfmts=%s, prependfile %s, recordfile %s\n", sfmt[x],prependfile,recordfile); #endif cw_filedelete(prependfile, sfmt[x]); } } if (rfmt) { if (cw_set_read_format(chan, rfmt)) { cw_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", cw_getformatname(rfmt), chan->name); } } if (outmsg) { if (outmsg > 1) { /* Let them know it worked */ cw_streamfile(chan, "auth-thankyou", chan->language); cw_waitstream(chan, ""); } } return res; } /* Channel group core functions */ int cw_app_group_split_group(char *data, char *group, int group_max, char *category, int category_max) { int res=0; char tmp[256]; char *grp=NULL, *cat=NULL; if (!cw_strlen_zero(data)) { cw_copy_string(tmp, data, sizeof(tmp)); grp = tmp; cat = strchr(tmp, '@'); if (cat) { *cat = '\0'; cat++; } } if (!cw_strlen_zero(grp)) cw_copy_string(group, grp, group_max); else res = -1; if (cat) snprintf(category, category_max, "%s_%s", GROUP_CATEGORY_PREFIX, cat); else cw_copy_string(category, GROUP_CATEGORY_PREFIX, category_max); return res; }
int cw_play_and_record(struct cw_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int silencethreshold, int maxsilence, const char *path) { int d; char *fmts; char comment[256]; int x, fmtcnt=1, res=-1,outmsg=0; struct cw_frame *f; struct cw_filestream *others[MAX_OTHER_FORMATS]; char *sfmt[MAX_OTHER_FORMATS]; char *stringp=NULL; time_t start, end; struct cw_dsp *sildet=NULL; /* silence detector dsp */ int totalsilence = 0; int dspsilence = 0; int gotsilence = 0; /* did we timeout for silence? */ int rfmt=0; if (silencethreshold < 0) silencethreshold = global_silence_threshold; if (maxsilence < 0) maxsilence = global_maxsilence; /* barf if no pointer passed to store duration in */ if (duration == NULL) { cw_log(LOG_WARNING, "Error play_and_record called without duration pointer\n"); return -1; } cw_log(LOG_DEBUG,"play_and_record: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt); snprintf(comment,sizeof(comment),"Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name); if (playfile) { d = cw_play_and_wait(chan, playfile); if (d > -1) d = cw_streamfile(chan, "beep",chan->language); if (!d) d = cw_waitstream(chan,""); if (d < 0) return -1; } fmts = cw_strdupa(fmt); stringp=fmts; strsep(&stringp, "|,"); cw_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts); sfmt[0] = cw_strdupa(fmts); while((fmt = strsep(&stringp, "|,"))) { if (fmtcnt > MAX_OTHER_FORMATS - 1) { cw_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app_voicemail.c\n"); break; } sfmt[fmtcnt++] = cw_strdupa(fmt); } time(&start); end=start; /* pre-initialize end to be same as start in case we never get into loop */ for (x=0;x<fmtcnt;x++) { others[x] = cw_writefile(recordfile, sfmt[x], comment, O_TRUNC, 0, 0700); cw_verbose( VERBOSE_PREFIX_3 "x=%d, open writing: %s format: %s, %p\n", x, recordfile, sfmt[x], others[x]); if (!others[x]) { break; } } if (path) cw_unlock_path(path); if (maxsilence > 0) { sildet = cw_dsp_new(); /* Create the silence detector */ if (!sildet) { cw_log(LOG_WARNING, "Unable to create silence detector :(\n"); return -1; } cw_dsp_set_threshold(sildet, silencethreshold); rfmt = chan->readformat; res = cw_set_read_format(chan, CW_FORMAT_SLINEAR); if (res < 0) { cw_log(LOG_WARNING, "Unable to set to linear mode, giving up\n"); cw_dsp_free(sildet); return -1; } } /* Request a video update */ cw_indicate(chan, CW_CONTROL_VIDUPDATE); if (x == fmtcnt) { /* Loop forever, writing the packets we read to the writer(s), until we read a # or get a hangup */ f = NULL; for(;;) { res = cw_waitfor(chan, 2000); if (!res) { cw_log(LOG_DEBUG, "One waitfor failed, trying another\n"); /* Try one more time in case of masq */ res = cw_waitfor(chan, 2000); if (!res) { cw_log(LOG_WARNING, "No audio available on %s??\n", chan->name); res = -1; } } if (res < 0) { f = NULL; break; } f = cw_read(chan); if (!f) break; if (f->frametype == CW_FRAME_VOICE) { /* write each format */ for (x=0;x<fmtcnt;x++) { res = cw_writestream(others[x], f); } /* Silence Detection */ if (maxsilence > 0) { dspsilence = 0; cw_dsp_silence(sildet, f, &dspsilence); if (dspsilence) totalsilence = dspsilence; else totalsilence = 0; if (totalsilence > maxsilence) { /* Ended happily with silence */ if (option_verbose > 2) cw_verbose( VERBOSE_PREFIX_3 "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000); cw_fr_free(f); gotsilence = 1; outmsg=2; break; } } /* Exit on any error */ if (res) { cw_log(LOG_WARNING, "Error writing frame\n"); cw_fr_free(f); break; } } else if (f->frametype == CW_FRAME_VIDEO) { /* Write only once */ cw_writestream(others[0], f); } else if (f->frametype == CW_FRAME_DTMF) { if (f->subclass == '#') { if (option_verbose > 2) cw_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass); res = '#'; outmsg = 2; cw_fr_free(f); break; } if (f->subclass == '0') { /* Check for a '0' during message recording also, in case caller wants operator */ if (option_verbose > 2) cw_verbose(VERBOSE_PREFIX_3 "User cancelled by pressing %c\n", f->subclass); res = '0'; outmsg = 0; cw_fr_free(f); break; } } if (maxtime) { time(&end); if (maxtime < (end - start)) { if (option_verbose > 2) cw_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n"); outmsg = 2; res = 't'; cw_fr_free(f); break; } } cw_fr_free(f); } if (end == start) time(&end); if (!f) { if (option_verbose > 2) cw_verbose( VERBOSE_PREFIX_3 "User hung up\n"); res = -1; outmsg=1; } } else { cw_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", recordfile, sfmt[x]); } *duration = end - start; for (x=0;x<fmtcnt;x++) { if (!others[x]) break; if (res > 0) { if (totalsilence) cw_stream_rewind(others[x], totalsilence-200); else cw_stream_rewind(others[x], 200); } cw_truncstream(others[x]); cw_closestream(others[x]); } if (rfmt) { if (cw_set_read_format(chan, rfmt)) { cw_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", cw_getformatname(rfmt), chan->name); } } if (outmsg > 1) { /* Let them know recording is stopped */ if(!cw_streamfile(chan, "auth-thankyou", chan->language)) cw_waitstream(chan, ""); } if (sildet) cw_dsp_free(sildet); return res; }
int cw_app_getvoice(struct cw_channel *c, char *dest, char *dstfmt, char *prompt, int silence, int maxsec) { int res; struct cw_filestream *writer; int rfmt; int totalms=0, total; struct cw_frame *f; struct cw_dsp *sildet; /* Play prompt if requested */ if (prompt) { res = cw_streamfile(c, prompt, c->language); if (res < 0) return res; res = cw_waitstream(c,""); if (res < 0) return res; } rfmt = c->readformat; res = cw_set_read_format(c, CW_FORMAT_SLINEAR); if (res < 0) { cw_log(LOG_WARNING, "Unable to set to linear mode, giving up\n"); return -1; } sildet = cw_dsp_new(); if (!sildet) { cw_log(LOG_WARNING, "Unable to create silence detector :(\n"); return -1; } writer = cw_writefile(dest, dstfmt, "Voice file", 0, 0, 0666); if (!writer) { cw_log(LOG_WARNING, "Unable to open file '%s' in format '%s' for writing\n", dest, dstfmt); cw_dsp_free(sildet); return -1; } for(;;) { if ((res = cw_waitfor(c, 2000)) < 0) { cw_log(LOG_NOTICE, "Waitfor failed while recording file '%s' format '%s'\n", dest, dstfmt); break; } if (res) { f = cw_read(c); if (!f) { cw_log(LOG_NOTICE, "Hungup while recording file '%s' format '%s'\n", dest, dstfmt); break; } if ((f->frametype == CW_FRAME_DTMF) && (f->subclass == '#')) { /* Ended happily with DTMF */ cw_fr_free(f); break; } else if (f->frametype == CW_FRAME_VOICE) { cw_dsp_silence(sildet, f, &total); if (total > silence) { /* Ended happily with silence */ cw_fr_free(f); break; } totalms += f->samples / 8; if (totalms > maxsec * 1000) { /* Ended happily with too much stuff */ cw_log(LOG_NOTICE, "Constraining voice on '%s' to %d seconds\n", c->name, maxsec); cw_fr_free(f); break; } res = cw_writestream(writer, f); if (res < 0) { cw_log(LOG_WARNING, "Failed to write to stream at %s!\n", dest); cw_fr_free(f); break; } } cw_fr_free(f); } } res = cw_set_read_format(c, rfmt); if (res) cw_log(LOG_WARNING, "Unable to restore read format on '%s'\n", c->name); cw_dsp_free(sildet); cw_closestream(writer); return 0; }
static int changrab_cli(int fd, int argc, char *argv[]) { char *chan_name_1, *chan_name_2 = NULL, *context,*exten,*flags=NULL; char *pria = NULL; struct cw_channel *xferchan_1, *xferchan_2; int pri=0,x=1; if(argc < 3) { cw_cli(fd,CGUSAGE); return -1; } chan_name_1 = argv[x++]; if(chan_name_1[0] == '-') { flags = cw_strdupa(chan_name_1); if (strchr(flags,'h')) { chan_name_1 = argv[x++]; if((xferchan_1 = my_cw_get_channel_by_name_locked(chan_name_1))) { cw_mutex_unlock(&xferchan_1->lock); cw_hangup(xferchan_1); cw_verbose("OK, good luck!\n"); return 0; } else return -1; } else if (strchr(flags,'m') || strchr(flags,'M')) { chan_name_1 = argv[x++]; if((xferchan_1 = my_cw_get_channel_by_name_locked(chan_name_1))) { cw_mutex_unlock(&xferchan_1->lock); strchr(flags,'m') ? cw_moh_start(xferchan_1,NULL) : cw_moh_stop(xferchan_1); } else return 1; return 0; } if(argc < 4) { cw_cli(fd,CGUSAGE); return -1; } chan_name_1 = argv[x++]; } exten = cw_strdupa(argv[x++]); if((context = strchr(exten,'@'))) { *context = 0; context++; if(!(context && exten)) { cw_cli(fd,CGUSAGE); return -1; } if((pria = strchr(context,':'))) { *pria = '\0'; pria++; pri = atoi(pria); } else { pri = argv[x] ? atoi(argv[x++]) : 1; } if(!pri) pri = 1; } else if (strchr(exten,'/')) { chan_name_2 = exten; } xferchan_1 = my_cw_get_channel_by_name_locked(chan_name_1); if(!xferchan_1) { cw_log(LOG_WARNING, "No Such Channel: %s\n",chan_name_1); return -1; } cw_mutex_unlock(&xferchan_1->lock); if(flags && strchr(flags,'b')) { if(cw_bridged_channel(xferchan_1)) { xferchan_1 = cw_bridged_channel(xferchan_1); } } if(chan_name_2) { struct cw_frame *f; struct cw_channel *newchan_1, *newchan_2; if (!(newchan_1 = cw_channel_alloc(0))) { cw_log(LOG_WARNING, "Memory Error!\n"); cw_hangup(newchan_1); return -1; } else { snprintf(newchan_1->name, sizeof (newchan_1->name), "ChanGrab/%s", xferchan_1->name); newchan_1->readformat = xferchan_1->readformat; newchan_1->writeformat = xferchan_1->writeformat; cw_channel_masquerade(newchan_1, xferchan_1); if ((f = cw_read(newchan_1))) { cw_fr_free(f); } else { cw_hangup(newchan_1); return -1; } } if(!(xferchan_2 = my_cw_get_channel_by_name_locked(chan_name_2))) { cw_log(LOG_WARNING, "No Such Channel: %s\n",chan_name_2); cw_hangup(newchan_1); return -1; } cw_mutex_unlock(&xferchan_2->lock); if(flags && strchr(flags, 'B')) { if(cw_bridged_channel(xferchan_2)) { xferchan_2 = cw_bridged_channel(xferchan_2); } } if(!(newchan_2 = cw_channel_alloc(0))) { cw_log(LOG_WARNING, "Memory Error!\n"); cw_hangup(newchan_1); return -1; } else { snprintf(newchan_2->name, sizeof (newchan_2->name), "ChanGrab/%s", xferchan_2->name); newchan_2->readformat = xferchan_2->readformat; newchan_2->writeformat = xferchan_2->writeformat; cw_channel_masquerade(newchan_2, xferchan_2); if ((f = cw_read(newchan_2))) { cw_fr_free(f); } else { cw_hangup(newchan_1); cw_hangup(newchan_2); return -1; } } cw_bridge_call_thread_launch(newchan_1, newchan_2); } else { cw_verbose("Transferring_to context %s, extension %s, priority %d\n", context, exten, pri); cw_async_goto(xferchan_1, context, exten, pri); if(xferchan_1) cw_mutex_unlock(&xferchan_1->lock); } return 0; }