예제 #1
0
static int faxgen_generate(struct cw_channel *chan, void *data, int samples)
{
    int len;
    fax_state_t *fax;
    struct cw_frame outf;

    uint8_t __buf[sizeof(uint16_t)*MAX_BLOCK_SIZE + 2*CW_FRIENDLY_OFFSET];
    uint8_t *buf = __buf + CW_FRIENDLY_OFFSET;
    
    fax = (fax_state_t*) data;

    samples = (samples <= MAX_BLOCK_SIZE)  ?  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));
    }

    return 0;
}
예제 #2
0
static struct cw_filestream *pcm_open(FILE *f)
{
    /* We don't have any header to read or anything really, but
       if we did, it would go here.  We also might want to check
       and be sure it's a valid file.  */
    struct cw_filestream *tmp;
    
    if ((tmp = malloc(sizeof(struct cw_filestream))))
    {
        memset(tmp, 0, sizeof(struct cw_filestream));
        if (cw_mutex_lock(&pcm_lock))
        {
            cw_log(LOG_WARNING, "Unable to lock pcm list\n");
            free(tmp);
            return NULL;
        }
        tmp->f = f;
        cw_fr_init_ex(&tmp->fr, CW_FRAME_VOICE, CW_FORMAT_ULAW, name);
        tmp->fr.data = tmp->buf;
        /* datalen will vary for each frame */
        glistcnt++;
        cw_mutex_unlock(&pcm_lock);
        cw_update_use_count();
    }
    return tmp;
}
예제 #3
0
static struct cw_filestream *au_open(FILE *f)
{
    struct cw_filestream *tmp;

    if (!(tmp = malloc(sizeof(struct cw_filestream))))
    {
        cw_log(LOG_ERROR, "Out of memory\n");
        return NULL;
    }

    memset(tmp, 0, sizeof(struct cw_filestream));
    if (check_header(f) < 0)
    {
        free(tmp);
        return NULL;
    }
    if (cw_mutex_lock(&au_lock))
    {
        cw_log(LOG_WARNING, "Unable to lock au count\n");
        free(tmp);
        return NULL;
    }
    tmp->f = f;
    cw_fr_init_ex(&tmp->fr, CW_FRAME_VOICE, CW_FORMAT_ULAW, NULL);
    tmp->fr.data = tmp->buf;
    /* datalen will vary for each frame */
    tmp->fr.src = name;

    localusecnt++;
    cw_mutex_unlock(&au_lock);
    cw_update_use_count();
    return tmp;
}
예제 #4
0
static int linear_generator(struct cw_channel *chan, void *data, int samples)
{
	struct cw_frame f;
	short buf[2048 + CW_FRIENDLY_OFFSET / 2];
	struct linear_state *ls = data;
	int res, len;

	len = samples*sizeof(int16_t);
	if (len > sizeof(buf) - CW_FRIENDLY_OFFSET)
    {
		cw_log(LOG_WARNING, "Can't generate %d bytes of data!\n" ,len);
		len = sizeof(buf) - CW_FRIENDLY_OFFSET;
	}
	memset(&f, 0, sizeof(f));
	res = read(ls->fd, buf + CW_FRIENDLY_OFFSET/2, len);
	if (res > 0)
    {
        cw_fr_init_ex(&f, CW_FRAME_VOICE, CW_FORMAT_SLINEAR, NULL);
		f.data = buf + CW_FRIENDLY_OFFSET/sizeof(int16_t);
		f.datalen = res;
		f.samples = res/sizeof(int16_t);
		f.offset = CW_FRIENDLY_OFFSET;
		cw_write(chan, &f);
		if (res == len)
			return 0;
	}
	return -1;
}
예제 #5
0
static struct cw_filestream *g726_16_open(FILE *f)
{
    /* We don't have any header to read or anything really, but
       if we did, it would go here.  We also might want to check
       and be sure it's a valid file.  */
    struct cw_filestream *tmp;
    if ((tmp = malloc(sizeof(struct cw_filestream)))) {
        memset(tmp, 0, sizeof(struct cw_filestream));
        if (cw_mutex_lock(&g726_lock)) {
            cw_log(LOG_WARNING, "Unable to lock g726 list.\n");
            free(tmp);
            return NULL;
        }
        tmp->f = f;
        cw_fr_init_ex(&tmp->fr, CW_FRAME_VOICE, CW_FORMAT_G726, name16);
        tmp->rate = RATE_16;
        tmp->fr.data = tmp->g726;
        /* datalen will vary for each frame */
        glistcnt++;
        if (option_debug)
            cw_log(LOG_DEBUG, "Created filestream G.726-%dk.\n", 
                                    40 - tmp->rate * 8);
        cw_mutex_unlock(&g726_lock);
        cw_update_use_count();
    }
    return tmp;
}
예제 #6
0
static struct cw_filestream *h263_open(FILE *f)
{
    /* We don't have any header to read or anything really, but
       if we did, it would go here.  We also might want to check
       and be sure it's a valid file.  */
    struct cw_filestream *tmp;
    unsigned int ts;
    int res;

    if ((res = fread(&ts, 1, sizeof(ts), f)) < sizeof(ts))
    {
        cw_log(LOG_WARNING, "Empty file!\n");
        return NULL;
    }
        
    if ((tmp = malloc(sizeof(struct cw_filestream))))
    {
        memset(tmp, 0, sizeof(struct cw_filestream));
        if (cw_mutex_lock(&h263_lock))
        {
            cw_log(LOG_WARNING, "Unable to lock h263 list\n");
            free(tmp);
            return NULL;
        }
        tmp->f = f;
        cw_fr_init_ex(&tmp->fr, CW_FRAME_VIDEO, CW_FORMAT_H263, name);
        tmp->fr.data = tmp->h263;
        /* datalen will vary for each frame */
        glistcnt++;
        cw_mutex_unlock(&h263_lock);
        cw_update_use_count();
    }
    return tmp;
}
예제 #7
0
static struct cw_frame *g722tolin_sample(void)
{
    static struct cw_frame f;
 
    cw_fr_init_ex(&f, CW_FRAME_VOICE, CW_FORMAT_G722, __PRETTY_FUNCTION__);
    f.datalen = sizeof(g722_ex);
    f.samples = sizeof(g722_ex)*2;
    f.data = (uint8_t *) g722_ex;
    return &f;
}
예제 #8
0
static struct cw_frame *lintog722_sample(void)
{
    static struct cw_frame f;
  
    cw_fr_init_ex(&f, CW_FRAME_VOICE, CW_FORMAT_SLINEAR, __PRETTY_FUNCTION__);
    f.datalen = sizeof (slin_ex);
    /* Assume 8000 Hz */
    f.samples = sizeof (slin_ex)/sizeof(int16_t);
    f.data = (int16_t *) slin_ex;
    return &f;
}
예제 #9
0
static struct cw_frame *lpc10tolin_sample(void)
{
    static struct cw_frame f;

    cw_fr_init_ex(&f, CW_FRAME_VOICE, CW_FORMAT_LPC10, __PRETTY_FUNCTION__);
    f.datalen = sizeof(lpc10_ex);
    /* All frames are 22 ms long (maybe a little more -- why did he choose
       LPC10_SAMPLES_PER_FRAME sample frames anyway?? */
    f.samples = LPC10_SAMPLES_PER_FRAME;
    f.data = lpc10_ex;
    return &f;
}
예제 #10
0
static int playtones_generator(struct cw_channel *chan, void *data, int samples)
{
	struct playtones_state *ps = data;
	struct playtones_item *pi;
	int len;
    int x;

	/*
	 * We need to prepare a frame with 16 * timelen samples as we're 
	 * generating SLIN audio
	 */
	len = samples + samples;
	if (len > sizeof(ps->data)/sizeof(int16_t) - 1)
    {
		cw_log(LOG_WARNING, "Can't generate that much data!\n");
		return -1;
	}

    x = tone_gen(&ps->tone_state, ps->data, samples);
	pi = &ps->items[ps->npos];

	/* Assemble frame */
	cw_fr_init_ex(&ps->f, CW_FRAME_VOICE, CW_FORMAT_SLINEAR, NULL);
	ps->f.datalen = len;
	ps->f.samples = samples;
	ps->f.offset = CW_FRIENDLY_OFFSET;
	ps->f.data = ps->data;
	cw_write(chan, &ps->f);

	ps->pos += x;
	if (pi->duration  &&  ps->pos >= pi->duration*8)
    {
    	/* item finished? */
		ps->pos = 0;					/* start new item */
		ps->npos++;
		if (ps->npos >= ps->nitems)
        {
            /* last item */
			if (ps->reppos == -1)			/* repeat set? */
				return -1;
			ps->npos = ps->reppos;			/* redo from top */
		}

		/* Prepare the tone generator for more */
		pi = &ps->items[ps->npos];
		tone_setup(ps, pi);
	}
	return 0;
}
예제 #11
0
static struct cw_frame *lintog722_frameout(struct cw_translator_pvt *pvt)
{
    struct g722_encoder_pvt *tmp = (struct g722_encoder_pvt *) pvt;
  
    if (tmp->tail == 0)
        return NULL;
    cw_fr_init_ex(&tmp->f, CW_FRAME_VOICE, CW_FORMAT_G722, __PRETTY_FUNCTION__);
    tmp->f.samples = tmp->tail*2;
    tmp->f.offset = CW_FRIENDLY_OFFSET;
    tmp->f.data = tmp->outbuf;
    tmp->f.datalen = tmp->tail;

    tmp->tail = 0;
    return &tmp->f;
}
예제 #12
0
static int t38_tx_packet_handler(t38_core_state_t *s, void *user_data, const uint8_t *buf, int len, int count)
{
    struct cw_frame outf;
    struct cw_channel *chan;

    chan = (struct cw_channel *) user_data;

    cw_fr_init_ex(&outf, CW_FRAME_MODEM, CW_MODEM_T38, "FAX");
    outf.datalen = len;
    outf.data = (char *) buf;
    outf.tx_copies = count;
    if (cw_write(chan, &outf) < 0)
        cw_log(LOG_WARNING, "Unable to write frame to channel; %s\n", strerror(errno));
    return 0;
}
예제 #13
0
static struct cw_frame *h263_read(struct cw_filestream *s, int *whennext)
{
    int res;
    int mark=0;
    unsigned short len;
    unsigned int ts;

    /* Send a frame from the file to the appropriate channel */
    cw_fr_init_ex(&s->fr, CW_FRAME_VIDEO, CW_FORMAT_H263, NULL);
    s->fr.offset = CW_FRIENDLY_OFFSET;
    s->fr.data = s->h263;
    if ((res = fread(&len, 1, sizeof(len), s->f)) < 1)
        return NULL;
    len = ntohs(len);
    if (len & 0x8000)
    {
        mark = 1;
    }
    len &= 0x7fff;
    if (len > sizeof(s->h263))
    {
        cw_log(LOG_WARNING, "Length %d is too long\n", len);
        return NULL;
    }
    if ((res = fread(s->h263, 1, len, s->f)) != len)
    {
        if (res)
            cw_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
        return NULL;
    }
    s->fr.samples = s->lastts;
    s->fr.datalen = len;
    s->fr.subclass |= mark;
    s->fr.delivery.tv_sec = 0;
    s->fr.delivery.tv_usec = 0;
    if ((res = fread(&ts, 1, sizeof(ts), s->f)) == sizeof(ts))
    {
        s->lastts = ntohl(ts);
        *whennext = s->lastts * 4/45;
    }
    else
    {
        *whennext = 0;
    }
    return &s->fr;
}
예제 #14
0
static struct cw_frame *lpc10tolin_frameout(struct cw_translator_pvt *tmp)
{
    if (tmp->tail == 0)
        return NULL;

    /* Signed linear is no particular frame size, so just send whatever
       we have in the buffer in one lump sum */
    cw_fr_init_ex(&tmp->f, CW_FRAME_VOICE, CW_FORMAT_SLINEAR, __PRETTY_FUNCTION__);
    tmp->f.datalen = tmp->tail*sizeof(int16_t);
    /* Assume 8000 Hz */
    tmp->f.samples = tmp->tail;
    tmp->f.offset = CW_FRIENDLY_OFFSET;
    tmp->f.data = tmp->buf;
    /* Reset tail pointer */
    tmp->tail = 0;

    return &tmp->f;    
}
예제 #15
0
int queue_incoming_silent_frame( struct cw_conf_member *member, int count) {
    struct cw_frame f;
    int t = 0;

    memset(member->framedata,0,sizeof(member->framedata));

    cw_fr_init_ex(&f, CW_FRAME_VOICE, CW_FORMAT_SLINEAR, "Nconf");
    f.data = member->framedata;
    f.datalen = member->samples * sizeof(int16_t);
    f.samples = member->samples;
    f.offset = 0;

    // Actually queue some frames
    for (t = 0;  t < count;  t++)
        queue_incoming_frame(member, &f);

    return 0;
}
예제 #16
0
static struct cw_frame *gsm_read(struct cw_filestream *s, int *whennext)
{
    int res;

    cw_fr_init_ex(&s->fr, CW_FRAME_VOICE, CW_FORMAT_GSM, NULL);
    s->fr.offset = CW_FRIENDLY_OFFSET;
    s->fr.samples = 160;
    s->fr.datalen = 33;
    s->fr.data = s->gsm;
    if ((res = fread(s->gsm, 1, 33, s->f)) != 33)
    {
        if (res)
            cw_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
        return NULL;
    }
    *whennext = 160;
    return &s->fr;
}
예제 #17
0
int cw_dtmf_stream(struct cw_channel *chan,struct cw_channel *peer,char *digits,int between) 
{
	char *ptr;
	int res = 0;
	struct cw_frame f;
	if (!between)
		between = 100;

	if (peer)
		res = cw_autoservice_start(peer);

	if (!res) {
		res = cw_waitfor(chan,100);
		if (res > -1) {
			for (ptr=digits; *ptr; ptr++) {
				if (*ptr == 'w') {
					res = cw_safe_sleep(chan, 500);
					if (res) 
						break;
					continue;
				}
                cw_fr_init_ex(&f, CW_FRAME_DTMF, *ptr, NULL);
				f.src = "cw_dtmf_stream";
				if (strchr("0123456789*#abcdABCD",*ptr) == NULL)
                {
					cw_log(LOG_WARNING, "Illegal DTMF character '%c' in string. (0-9*#aAbBcCdD allowed)\n",*ptr);
				}
                else
                {
					res = cw_write(chan, &f);
					if (res) 
						break;
					/* pause between digits */
					res = cw_safe_sleep(chan,between);
					if (res) 
						break;
				}
			}
		}
		if (peer)
			res = cw_autoservice_stop(peer);
	}
	return res;
}
예제 #18
0
static struct cw_frame *g726_read(struct cw_filestream *s, int *whennext)
{
    int res;

    /* Send a frame from the file to the appropriate channel */
    cw_fr_init_ex(&s->fr, CW_FRAME_VOICE, CW_FORMAT_G726, NULL);
    s->fr.offset = CW_FRIENDLY_OFFSET;
    s->fr.samples = 8*FRAME_TIME;
    s->fr.datalen = frame_size[s->rate];
    s->fr.data = s->g726;
    if ((res = fread(s->g726, 1, s->fr.datalen, s->f)) != s->fr.datalen)
    {
        if (res)
            cw_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
        return NULL;
    }
    *whennext = s->fr.samples;
    return &s->fr;
}
예제 #19
0
static struct cw_frame *pcm_read(struct cw_filestream *s, int *whennext)
{
    int res;
    int delay;
    /* Send a frame from the file to the appropriate channel */

    cw_fr_init_ex(&s->fr, CW_FRAME_VOICE, CW_FORMAT_ULAW, NULL);
    s->fr.offset = CW_FRIENDLY_OFFSET;
    s->fr.data = s->buf;
    if ((res = fread(s->buf, 1, BUF_SIZE, s->f)) < 1)
    {
        if (res)
            cw_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
        return NULL;
    }
    s->fr.samples = res;
    s->fr.datalen = res;
    delay = s->fr.samples;
    *whennext = delay;
    return &s->fr;
}
예제 #20
0
static struct cw_frame *lintolpc10_frameout(struct cw_translator_pvt *tmp)
{
    int consumed = 0;

    /* We can't work on anything less than a frame in size */
    if (tmp->tail < LPC10_SAMPLES_PER_FRAME)
        return NULL;
    /* Start with an empty frame */
    cw_fr_init_ex(&tmp->f, CW_FRAME_VOICE, CW_FORMAT_LPC10, __PRETTY_FUNCTION__);
    while (tmp->tail >=  LPC10_SAMPLES_PER_FRAME)
    {
        if (tmp->f.datalen + LPC10_BYTES_IN_COMPRESSED_FRAME > sizeof(tmp->outbuf))
        {
            cw_log(LOG_WARNING, "Out of buffer space\n");
            return NULL;
        }
        /* Encode a frame of data */
        lpc10_encode(tmp->lpc10.enc, ((uint8_t *)tmp->outbuf) + tmp->f.datalen, &tmp->buf[consumed], 180);
        tmp->f.datalen += LPC10_BYTES_IN_COMPRESSED_FRAME;
        tmp->f.samples += LPC10_SAMPLES_PER_FRAME;
        /* Use one of the two left over bits to record if this is a 22 or 23 ms frame...
           important for IAX use */
        tmp->longer = 1 - tmp->longer;
#if 0
        /* What the heck was this for? */
        ((char *)(tmp->f.data))[consumed - 1] |= tmp->longer;
#endif        
        tmp->tail -= LPC10_SAMPLES_PER_FRAME;
        consumed += LPC10_SAMPLES_PER_FRAME;
    }
    tmp->f.mallocd = 0;
    tmp->f.offset = CW_FRIENDLY_OFFSET;
    tmp->f.src = __PRETTY_FUNCTION__;
    tmp->f.data = tmp->outbuf;
    /* Move the data at the end of the buffer to the front */
    if (tmp->tail)
        memmove(tmp->buf, tmp->buf + consumed, tmp->tail*sizeof(int16_t));
    return &tmp->f;    
}
예제 #21
0
/*!
 * \brief Read a frame full of audio data from the filestream.
 * \param s The filestream.
 * \param whennext Number of sample times to schedule the next call.
 * \return A pointer to a frame containing audio data or NULL ifthere is no more audio data.
 */
static struct cw_frame *ogg_vorbis_read(struct cw_filestream *s, int *whennext)
{
    int clipflag = 0;
    int i;
    int j;
    float **pcm;
    float *mono;
    double accumulator[SAMPLES_MAX];
    int val;
    int samples_in;
    int samples_out = 0;

    for (;;)
    {
        /* See if we have filled up an audio frame yet */
        if (samples_out == SAMPLES_MAX)
            break;

        /* See ifVorbis decoder has some audio data for us ... */
        samples_in = read_samples(s, &pcm);
        if (samples_in <= 0)
            break;

        /* Got some audio data from Vorbis... */
        /* Convert the float audio data to 16-bit signed linear */
        clipflag = 0;

        samples_in = samples_in < (SAMPLES_MAX - samples_out)  ?  samples_in  :  (SAMPLES_MAX - samples_out);
  
        for(j = 0;  j < samples_in;  j++)
            accumulator[j] = 0.0;

        for (i = 0;  i < s->vi.channels;  i++)
        {
            mono = pcm[i];
            for (j = 0;  j < samples_in;  j++)
                accumulator[j] += mono[j];
        }

        for (j = 0; j < samples_in; j++)
        {
            val =  accumulator[j] * 32767.0 / s->vi.channels;
            if (val > 32767)
            {
                val = 32767;
                clipflag = 1;
            }
            if (val < -32768)
            {
                val = -32768;
                clipflag = 1;
            }
            s->buffer[samples_out + j] = val;
        }
            
        if (clipflag)
            cw_log(LOG_WARNING, "Clipping in frame %ld\n", (long)(s->vd.sequence));
        
        /* Tell the Vorbis decoder how many samples we actually used. */
        vorbis_synthesis_read(&s->vd, samples_in);
        samples_out += samples_in;
    }

    if (samples_out > 0)
    {
        cw_fr_init_ex(&s->fr, CW_FRAME_VOICE, CW_FORMAT_SLINEAR, name);
        s->fr.offset = CW_FRIENDLY_OFFSET;
        s->fr.datalen = samples_out*sizeof(int16_t);
        s->fr.data = s->buffer;
        s->fr.samples = samples_out;
        *whennext = samples_out;
        
        return &s->fr;
    }
    return NULL;
}
예제 #22
0
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;
}
예제 #23
0
struct cw_frame* get_outgoing_frame( struct cw_conference *conf, struct cw_conf_member* member, int samples ) 
{
    //
    // sanity checks
    //
        
    // check on conf
    if ( conf == NULL ) 
    {
        cw_log( LOG_ERROR, "unable to queue null conference\n" ) ;
        return NULL ;
    }

    if ( conf->memberlist == NULL ) 
    {
        cw_log( LOG_ERROR, "unable to queue for a null memberlist\n" ) ;
        return NULL ;
    }

    // check on member
    if ( member == NULL )
    {
        cw_log( LOG_ERROR, "unable to queue frame for null member\n" ) ;
        return NULL ;
    }

    // ***********************************
    // Mixing procedure
    // ***********************************

    int members =0;
    struct cw_frame *f = NULL;
    struct cw_conf_member *mixmember;
    int16_t *dst = member->framedata;
    int16_t *src = NULL;

    memset(member->framedata,0,sizeof(member->framedata));

    mixmember=conf->memberlist;
    while ( mixmember ) {
        if (
            mixmember!=member && mixmember->is_speaking
            &&
            ( mixmember->type != MEMBERTYPE_CONSULTANT || ( mixmember->type == MEMBERTYPE_CONSULTANT && member->type == MEMBERTYPE_MASTER ) ) 
           ) {
            members++;

                src = mixmember->cbuf->buffer8k;
#if  ( APP_NCONFERENCE_DEBUG == 1 )
            if(vdebug) 
            cw_log(CW_CONF_DEBUG,
                "Mixing memb %s Chan %s Ind %d Samples %d "
                " bufpos: %p with offset %p  FOR MEMBER %s\n", 
                mixmember->id, mixmember->chan->name, mixmember->cbuf->index8k, samples,
                member->framedata, member->framedata + CW_FRIENDLY_OFFSET/sizeof(int16_t),
                member->chan->name
            );
#endif
            mix_slinear_frames( 
                    dst, src,
                    samples, mixmember->cbuf->index8k, sizeof(mixmember->cbuf->buffer8k)/sizeof(int16_t) 
            );
        }
        mixmember=mixmember->next;
    }

    //Building the frame
    f = calloc(1, sizeof(struct cw_frame));
    if (f != NULL) {
        cw_fr_init_ex(f, CW_FRAME_VOICE, CW_FORMAT_SLINEAR, "Nconf");
        f->data = member->framedata;
        f->datalen = samples*sizeof(int16_t);
        f->samples = samples;
        f->offset = 0;
    } else
        return NULL;

#if  ( APP_NCONFERENCE_DEBUG == 1 )
    if (vdebug && members) {
        int count=0;
        int16_t *msrc;
        msrc = f->data + CW_FRIENDLY_OFFSET;

        if (vdebug) cw_log(CW_CONF_DEBUG,
                        "Offset %d  OFO: %d    Data at %p  SRC at %p memberdata at %p \n",
                        f->offset, CW_FRIENDLY_OFFSET,
                        f->data, &msrc, member->framedata 
                    );

        for( count=0; count<f->samples; count++ ) {
                cw_log(CW_CONF_DEBUG,
                "DUMP POS %04d VALUE %08d    at %p \n",
                          count, msrc[count], &msrc[count] );
        }
    }
#endif
    return f ;
}
예제 #24
0
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;
}