static struct ast_frame *g723_read(struct ast_filestream *s, int *whennext) { unsigned short size; int res; int delay; /* Read the delay for the next packet, and schedule again if necessary */ /* XXX is this ignored ? */ if (fread(&delay, 1, 4, s->f) == 4) delay = ntohl(delay); else delay = -1; if (fread(&size, 1, 2, s->f) != 2) { /* Out of data, or the file is no longer valid. In any case go ahead and stop the stream */ return NULL; } /* Looks like we have a frame to read from here */ size = ntohs(size); if (size > G723_MAX_SIZE) { ast_log(LOG_WARNING, "Size %d is invalid\n", size); /* The file is apparently no longer any good, as we shouldn't ever get frames even close to this size. */ return NULL; } /* Read the data into the buffer */ AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, size); if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) != size) { ast_log(LOG_WARNING, "Short read (%d of %d bytes) (%s)!\n", res, size, strerror(errno)); return NULL; } *whennext = s->fr.samples = 240; return &s->fr; }
static struct ast_frame *wav_read(struct ast_filestream *s, int *whennext) { /* Send a frame from the file to the appropriate channel */ struct wavg_desc *fs = (struct wavg_desc *)s->_private; s->fr.frametype = AST_FRAME_VOICE; ast_format_set(&s->fr.subclass.format, AST_FORMAT_GSM, 0); s->fr.offset = AST_FRIENDLY_OFFSET; s->fr.samples = GSM_SAMPLES; s->fr.mallocd = 0; AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, GSM_FRAME_SIZE); if (fs->secondhalf) { /* Just return a frame based on the second GSM frame */ s->fr.data.ptr = (char *)s->fr.data.ptr + GSM_FRAME_SIZE; s->fr.offset += GSM_FRAME_SIZE; } else { /* read and convert */ unsigned char msdata[MSGSM_FRAME_SIZE]; int res; if ((res = fread(msdata, 1, MSGSM_FRAME_SIZE, s->f)) != MSGSM_FRAME_SIZE) { if (res && (res != 1)) ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno)); return NULL; } /* Convert from MS format to two real GSM frames */ conv65(msdata, s->fr.data.ptr); } fs->secondhalf = !fs->secondhalf; *whennext = GSM_SAMPLES; return &s->fr; }
static int fax_generator_generate(struct ast_channel *chan, void *data, int len, int samples) { fax_state_t *fax = (fax_state_t*) data; uint8_t buffer[AST_FRIENDLY_OFFSET + MAX_SAMPLES * sizeof(uint16_t)]; int16_t *buf = (int16_t *) (buffer + AST_FRIENDLY_OFFSET); struct ast_frame outf = { .frametype = AST_FRAME_VOICE, .src = __FUNCTION__, }; ast_format_set(&outf.subclass.format, AST_FORMAT_SLINEAR, 0); if (samples > MAX_SAMPLES) { ast_log(LOG_WARNING, "Only generating %d samples, where %d requested\n", MAX_SAMPLES, samples); samples = MAX_SAMPLES; } if ((len = fax_tx(fax, buf, samples)) > 0) { outf.samples = len; AST_FRAME_SET_BUFFER(&outf, buffer, AST_FRIENDLY_OFFSET, len * sizeof(int16_t)); if (ast_write(chan, &outf) < 0) { ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", ast_channel_name(chan), strerror(errno)); return -1; } } return 0; }
static struct ast_frame *ilbc_read(struct ast_filestream *s, int *whennext) { int res; /* Send a frame from the file to the appropriate channel */ AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, ILBC_BUF_SIZE); if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) != s->fr.datalen) { if (res) ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno)); return NULL; } *whennext = s->fr.samples = ILBC_SAMPLES; return &s->fr; }
static struct ast_frame *generic_read(struct ast_filestream *s, int *whennext, unsigned int buf_size) { int res; /* Send a frame from the file to the appropriate channel */ AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, buf_size); if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) < 1) { if (res) ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno)); return NULL; } *whennext = s->fr.samples = res/2; s->fr.datalen = res; return &s->fr; }
static struct ast_frame *gsm_read(struct ast_filestream *s, int *whennext) { int res; s->fr.frametype = AST_FRAME_VOICE; ast_format_set(&s->fr.subclass.format, AST_FORMAT_GSM, 0); AST_FRAME_SET_BUFFER(&(s->fr), s->buf, AST_FRIENDLY_OFFSET, GSM_FRAME_SIZE) s->fr.mallocd = 0; if ((res = fread(s->fr.data.ptr, 1, GSM_FRAME_SIZE, s->f)) != GSM_FRAME_SIZE) { if (res) ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno)); return NULL; } *whennext = s->fr.samples = GSM_SAMPLES; return &s->fr; }
static struct ast_frame *g726_read(struct ast_filestream *s, int *whennext) { int res; struct g726_desc *fs = (struct g726_desc *)s->_private; /* Send a frame from the file to the appropriate channel */ AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, frame_size[fs->rate]); s->fr.samples = 8 * FRAME_TIME; if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) != s->fr.datalen) { if (res) ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno)); return NULL; } *whennext = s->fr.samples; return &s->fr; }
/*! * \brief Read a frame full of audio data from the filestream. * \param fs 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 ast_frame *ogg_speex_read(struct ast_filestream *fs, int *whennext) { struct speex_desc *s = (struct speex_desc *)fs->_private; if (read_packet(fs) < 0) { return NULL; } AST_FRAME_SET_BUFFER(&fs->fr, fs->buf, AST_FRIENDLY_OFFSET, BUF_SIZE); memcpy(fs->fr.data.ptr, s->op.packet, s->op.bytes); fs->fr.datalen = s->op.bytes; fs->fr.samples = *whennext = ast_codec_samples_count(&fs->fr); return &fs->fr; }
static struct ast_frame *mp3_read(struct ast_filestream *s, int *whennext) { struct mp3_private *p = s->_private; int delay =0; int save=0; /* Pre-populate the buffer that holds audio to be returned (dbuf) */ if (mp3_queue(s)) { return NULL; } if (p->dbuflen) { /* Read out what's waiting in dbuf */ for (p->buflen = 0; p->buflen < MP3_BUFLEN && p->buflen < p->dbuflen; p->buflen++) { s->buf[p->buflen + AST_FRIENDLY_OFFSET] = p->dbuf[p->buflen + p->dbufoffset]; } p->dbufoffset += p->buflen; p->dbuflen -= p->buflen; } if (p->buflen < MP3_BUFLEN) { /* dbuf didn't have enough, so reset dbuf, fill it back up and continue */ p->dbuflen = p->dbufoffset = 0; if (mp3_queue(s)) { return NULL; } /* Make sure dbuf has enough to complete this read attempt */ if (p->dbuflen >= (MP3_BUFLEN - p->buflen)) { for (save = p->buflen; p->buflen < MP3_BUFLEN; p->buflen++) { s->buf[p->buflen + AST_FRIENDLY_OFFSET] = p->dbuf[(p->buflen - save) + p->dbufoffset]; } p->dbufoffset += (MP3_BUFLEN - save); p->dbuflen -= (MP3_BUFLEN - save); } } p->offset += p->buflen; delay = p->buflen / 2; AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, p->buflen); s->fr.samples = delay; *whennext = delay; return &s->fr; }
static struct ast_frame *g719read(struct ast_filestream *s, int *whennext) { size_t res; /* Send a frame from the file to the appropriate channel */ AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE); if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) != s->fr.datalen) { if (res) { ast_log(LOG_WARNING, "Short read of %s data (expected %d bytes, read %zu): %s\n", ast_format_get_name(s->fr.subclass.format), s->fr.datalen, res, strerror(errno)); } return NULL; } *whennext = s->fr.samples = BYTES_TO_SAMPLES(res); return &s->fr; }
static struct ast_frame *siren14read(struct ast_filestream *s, int *whennext) { int res; /* Send a frame from the file to the appropriate channel */ s->fr.frametype = AST_FRAME_VOICE; s->fr.subclass.codec = AST_FORMAT_SIREN14; s->fr.mallocd = 0; AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE); if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) != s->fr.datalen) { if (res) ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno)); return NULL; } *whennext = s->fr.samples = BYTES_TO_SAMPLES(res); return &s->fr; }
static struct ast_frame *g729_read(struct ast_filestream *s, int *whennext) { int res; /* Send a frame from the file to the appropriate channel */ s->fr.frametype = AST_FRAME_VOICE; s->fr.subclass = AST_FORMAT_G729A; s->fr.mallocd = 0; s->fr.samples = G729A_SAMPLES; AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE); if ((res = fread(s->fr.data, 1, s->fr.datalen, s->f)) != s->fr.datalen) { if (res && (res != 10)) /* XXX what for ? */ ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno)); return NULL; } *whennext = s->fr.samples; return &s->fr; }
static struct ast_frame *mp3_read(struct ast_filestream *s, int *whennext) { struct mp3_private *p = s->_private; int delay =0; int save=0; /* Send a frame from the file to the appropriate channel */ if(mp3_queue(s)) return NULL; if(p->dbuflen) { for(p->buflen=0; p->buflen < MP3_BUFLEN && p->buflen < p->dbuflen; p->buflen++) { s->buf[p->buflen + AST_FRIENDLY_OFFSET] = p->dbuf[p->buflen+p->dbufoffset]; p->sbufoffset++; } p->dbufoffset += p->buflen; p->dbuflen -= p->buflen; if(p->buflen < MP3_BUFLEN) { if(mp3_queue(s)) return NULL; for(save = p->buflen; p->buflen < MP3_BUFLEN; p->buflen++) { s->buf[p->buflen + AST_FRIENDLY_OFFSET] = p->dbuf[(p->buflen-save)+p->dbufoffset]; p->sbufoffset++; } p->dbufoffset += (MP3_BUFLEN - save); p->dbuflen -= (MP3_BUFLEN - save); } } p->offset += p->buflen; delay = p->buflen/2; s->fr.frametype = AST_FRAME_VOICE; s->fr.subclass = AST_FORMAT_SLINEAR; AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, p->buflen); s->fr.mallocd = 0; s->fr.samples = delay; *whennext = delay; return &s->fr; }
static struct ast_frame *slinear_read(struct ast_filestream *s, int *whennext) { int res; /* Send a frame from the file to the appropriate channel */ s->fr.frametype = AST_FRAME_VOICE; s->fr.subclass = AST_FORMAT_SLINEAR; s->fr.mallocd = 0; AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE); if ((res = fread(s->fr.data, 1, s->fr.datalen, s->f)) < 1) { if (res) ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno)); return NULL; } *whennext = s->fr.samples = res/2; s->fr.datalen = res; return &s->fr; }
static struct ast_frame *generic_read(struct ast_filestream *s, int *whennext, unsigned int buf_size, enum ast_format_id id) { int res; /* Send a frame from the file to the appropriate channel */ s->fr.frametype = AST_FRAME_VOICE; ast_format_set(&s->fr.subclass.format, id, 0); s->fr.mallocd = 0; AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, buf_size); if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) < 1) { if (res) ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno)); return NULL; } *whennext = s->fr.samples = res/2; s->fr.datalen = res; return &s->fr; }
/*! * \brief Read a frame full of audio data from the filestream. * \param fs 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 ast_frame *ogg_vorbis_read(struct ast_filestream *fs, int *whennext) { struct ogg_vorbis_desc *desc = (struct ogg_vorbis_desc *) fs->_private; int current_bitstream = -10; char *out_buf; long bytes_read; if (desc->writing) { ast_log(LOG_WARNING, "Reading is not supported on OGG/Vorbis on write files.\n"); return NULL; } /* initialize frame */ fs->fr.frametype = AST_FRAME_VOICE; ast_format_set(&fs->fr.subclass.format, AST_FORMAT_SLINEAR, 0); fs->fr.mallocd = 0; AST_FRAME_SET_BUFFER(&fs->fr, fs->buf, AST_FRIENDLY_OFFSET, BUF_SIZE); out_buf = (char *) (fs->fr.data.ptr); /* SLIN data buffer */ /* read samples from OV interface */ bytes_read = ov_read( &desc->ov_f, out_buf, /* Buffer to write data */ BUF_SIZE, /* Size of buffer */ (__BYTE_ORDER == __BIG_ENDIAN), /* Endianes (0 for little) */ 2, /* 1 = 8bit, 2 = 16bit */ 1, /* 0 = unsigned, 1 = signed */ ¤t_bitstream /* Returns the current bitstream section */ ); /* check returned data */ if (bytes_read <= 0) { /* End of stream */ return NULL; } /* Return decoded bytes */ fs->fr.datalen = bytes_read; fs->fr.samples = bytes_read / 2; *whennext = fs->fr.samples; return &fs->fr; }
static struct ast_frame *g726_read(struct ast_filestream *s, int *whennext) { size_t res; struct g726_desc *fs = (struct g726_desc *)s->_private; /* Send a frame from the file to the appropriate channel */ AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, frame_size[fs->rate]); s->fr.samples = 8 * FRAME_TIME; if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) != s->fr.datalen) { if (res) { ast_log(LOG_WARNING, "Short read of %s data (expected %d bytes, read %zu): %s\n", ast_format_get_name(s->fr.subclass.format), s->fr.datalen, res, strerror(errno)); } return NULL; } *whennext = s->fr.samples; return &s->fr; }
static struct ast_frame *h263_read(struct ast_filestream *s, int *whennext) { int res; uint32_t mark; unsigned short len; unsigned int ts; struct h263_desc *fs = (struct h263_desc *)s->_private; /* Send a frame from the file to the appropriate channel */ if ((res = fread(&len, 1, sizeof(len), s->f)) < 1) return NULL; len = ntohs(len); mark = (len & 0x8000) ? 1 : 0; len &= 0x7fff; if (len > BUF_SIZE) { ast_log(LOG_WARNING, "Length %d is too long\n", len); return NULL; } s->fr.frametype = AST_FRAME_VIDEO; ast_format_set(&s->fr.subclass.format, AST_FORMAT_H263, 0); s->fr.mallocd = 0; AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, len); if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) != s->fr.datalen) { if (res) ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno)); return NULL; } s->fr.samples = fs->lastts; /* XXX what ? */ s->fr.datalen = len; if (mark) { ast_format_set_video_mark(&s->fr.subclass.format); } s->fr.delivery.tv_sec = 0; s->fr.delivery.tv_usec = 0; if ((res = fread(&ts, 1, sizeof(ts), s->f)) == sizeof(ts)) { fs->lastts = ntohl(ts); *whennext = fs->lastts * 4/45; } else *whennext = 0; return &s->fr; }
static int t38_tx_packet_handler(t38_core_state_t *s, void *user_data, const uint8_t *buf, int len, int count) { struct ast_channel *chan = (struct ast_channel *) user_data; struct ast_frame outf = { .frametype = AST_FRAME_MODEM, .subclass = AST_MODEM_T38, .src = __FUNCTION__, }; /* TODO: Asterisk does not provide means of resending the same packet multiple times so count is ignored at the moment */ AST_FRAME_SET_BUFFER(&outf, buf, 0, len); if (ast_write(chan, &outf) < 0) { ast_log(LOG_WARNING, "Unable to write frame to channel; %s\n", strerror(errno)); return -1; } return 0; }
static struct ast_frame *pcm_read(struct ast_filestream *s, int *whennext) { int res; /* Send a frame from the file to the appropriate channel */ s->fr.frametype = AST_FRAME_VOICE; ast_format_copy(&s->fr.subclass.format, &s->fmt->format); s->fr.mallocd = 0; AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE); if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) < 1) { if (res) ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno)); return NULL; } s->fr.datalen = res; if (s->fmt->format.id == AST_FORMAT_G722) *whennext = s->fr.samples = res * 2; else *whennext = s->fr.samples = res; return &s->fr; }
static int t38_tx_packet_handler(t38_core_state_t *s, void *user_data, const uint8_t *buf, int len, int count) { struct ast_channel *chan = (struct ast_channel *) user_data; struct ast_frame outf = { .frametype = AST_FRAME_MODEM, .subclass.integer = AST_MODEM_T38, .src = __FUNCTION__, }; /* TODO: Asterisk does not provide means of resending the same packet multiple times so count is ignored at the moment */ AST_FRAME_SET_BUFFER(&outf, buf, 0, len); if (ast_write(chan, &outf) < 0) { ast_log(LOG_WARNING, "Unable to write frame to channel; %s\n", strerror(errno)); return -1; } return 0; } static void phase_e_handler(t30_state_t *f, void *user_data, int result) { RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref); RAII_VAR(struct ast_json *, json_filenames, NULL, ast_json_unref); RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup); const char *local_ident; const char *far_ident; char buf[20]; fax_session *s = (fax_session *) user_data; t30_stats_t stat; int pages_transferred; ast_debug(1, "Fax phase E handler. result=%d\n", result); t30_get_transfer_statistics(f, &stat); s = (fax_session *) user_data; if (result != T30_ERR_OK) { s->finished = -1; /* FAXSTATUS is already set to FAILED */ pbx_builtin_setvar_helper(s->chan, "FAXERROR", t30_completion_code_to_str(result)); ast_log(LOG_WARNING, "Error transmitting fax. result=%d: %s.\n", result, t30_completion_code_to_str(result)); return; } s->finished = 1; local_ident = S_OR(t30_get_tx_ident(f), ""); far_ident = S_OR(t30_get_rx_ident(f), ""); pbx_builtin_setvar_helper(s->chan, "FAXSTATUS", "SUCCESS"); pbx_builtin_setvar_helper(s->chan, "FAXERROR", NULL); pbx_builtin_setvar_helper(s->chan, "REMOTESTATIONID", far_ident); #if SPANDSP_RELEASE_DATE >= 20090220 pages_transferred = (s->direction) ? stat.pages_tx : stat.pages_rx; #else pages_transferred = stat.pages_transferred; #endif snprintf(buf, sizeof(buf), "%d", pages_transferred); pbx_builtin_setvar_helper(s->chan, "FAXPAGES", buf); snprintf(buf, sizeof(buf), "%d", stat.y_resolution); pbx_builtin_setvar_helper(s->chan, "FAXRESOLUTION", buf); snprintf(buf, sizeof(buf), "%d", stat.bit_rate); pbx_builtin_setvar_helper(s->chan, "FAXBITRATE", buf); ast_debug(1, "Fax transmitted successfully.\n"); ast_debug(1, " Remote station ID: %s\n", far_ident); ast_debug(1, " Pages transferred: %d\n", pages_transferred); ast_debug(1, " Image resolution: %d x %d\n", stat.x_resolution, stat.y_resolution); ast_debug(1, " Transfer Rate: %d\n", stat.bit_rate); json_filenames = ast_json_pack("[s]", s->file_name); if (!json_filenames) { return; } ast_json_ref(json_filenames); json_object = ast_json_pack("{s: s, s: s, s: s, s: i, s: i, s: i, s: o}", "type", s->direction ? "send" : "receive", "remote_station_id", far_ident, "local_station_id", local_ident, "fax_pages", pages_transferred, "fax_resolution", stat.y_resolution, "fax_bitrate", stat.bit_rate, "filenames", json_filenames); message = ast_channel_blob_create_from_cache(ast_channel_uniqueid(s->chan), ast_channel_fax_type(), json_object); if (!message) { return; } stasis_publish(ast_channel_topic(s->chan), message); }
static int t38_tx_packet_handler(t38_core_state_t *s, void *user_data, const uint8_t *buf, int len, int count) { struct ast_channel *chan = (struct ast_channel *) user_data; struct ast_frame outf = { .frametype = AST_FRAME_MODEM, .subclass.integer = AST_MODEM_T38, .src = __FUNCTION__, }; /* TODO: Asterisk does not provide means of resending the same packet multiple times so count is ignored at the moment */ AST_FRAME_SET_BUFFER(&outf, buf, 0, len); if (ast_write(chan, &outf) < 0) { ast_log(LOG_WARNING, "Unable to write frame to channel; %s\n", strerror(errno)); return -1; } return 0; } static void phase_e_handler(t30_state_t *f, void *user_data, int result) { const char *local_ident; const char *far_ident; char buf[20]; fax_session *s = (fax_session *) user_data; t30_stats_t stat; int pages_transferred; ast_debug(1, "Fax phase E handler. result=%d\n", result); t30_get_transfer_statistics(f, &stat); s = (fax_session *) user_data; if (result != T30_ERR_OK) { s->finished = -1; /* FAXSTATUS is already set to FAILED */ pbx_builtin_setvar_helper(s->chan, "FAXERROR", t30_completion_code_to_str(result)); ast_log(LOG_WARNING, "Error transmitting fax. result=%d: %s.\n", result, t30_completion_code_to_str(result)); return; } s->finished = 1; local_ident = S_OR(t30_get_tx_ident(f), ""); far_ident = S_OR(t30_get_rx_ident(f), ""); pbx_builtin_setvar_helper(s->chan, "FAXSTATUS", "SUCCESS"); pbx_builtin_setvar_helper(s->chan, "FAXERROR", NULL); pbx_builtin_setvar_helper(s->chan, "REMOTESTATIONID", far_ident); #if SPANDSP_RELEASE_DATE >= 20090220 pages_transferred = (s->direction) ? stat.pages_tx : stat.pages_rx; #else pages_transferred = stat.pages_transferred; #endif snprintf(buf, sizeof(buf), "%d", pages_transferred); pbx_builtin_setvar_helper(s->chan, "FAXPAGES", buf); snprintf(buf, sizeof(buf), "%d", stat.y_resolution); pbx_builtin_setvar_helper(s->chan, "FAXRESOLUTION", buf); snprintf(buf, sizeof(buf), "%d", stat.bit_rate); pbx_builtin_setvar_helper(s->chan, "FAXBITRATE", buf); ast_debug(1, "Fax transmitted successfully.\n"); ast_debug(1, " Remote station ID: %s\n", far_ident); ast_debug(1, " Pages transferred: %d\n", pages_transferred); ast_debug(1, " Image resolution: %d x %d\n", stat.x_resolution, stat.y_resolution); ast_debug(1, " Transfer Rate: %d\n", stat.bit_rate); ast_manager_event(s->chan, EVENT_FLAG_CALL, s->direction ? "FaxSent" : "FaxReceived", "Channel: %s\r\n" "Exten: %s\r\n" "CallerID: %s\r\n" "CallerIDName: %s\r\n" "ConnectedLineNum: %s\r\n" "ConnectedLineName: %s\r\n" "RemoteStationID: %s\r\n" "LocalStationID: %s\r\n" "PagesTransferred: %d\r\n" "Resolution: %d\r\n" "TransferRate: %d\r\n" "FileName: %s\r\n", ast_channel_name(s->chan), ast_channel_exten(s->chan), S_COR(ast_channel_caller(s->chan)->id.number.valid, ast_channel_caller(s->chan)->id.number.str, ""), S_COR(ast_channel_caller(s->chan)->id.name.valid, ast_channel_caller(s->chan)->id.name.str, ""), S_COR(ast_channel_connected(s->chan)->id.number.valid, ast_channel_connected(s->chan)->id.number.str, ""), S_COR(ast_channel_connected(s->chan)->id.name.valid, ast_channel_connected(s->chan)->id.name.str, ""), far_ident, local_ident, pages_transferred, stat.y_resolution, stat.bit_rate, s->file_name); } /* === Helper functions to configure fax === */ /* Setup SPAN logging according to Asterisk debug level */ static int set_logging(logging_state_t *state) { int level = SPAN_LOG_WARNING + option_debug; span_log_set_message_handler(state, span_message); span_log_set_level(state, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | level); return 0; }
/*! * \brief Read a frame full of audio data from the filestream. * \param fs 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 ast_frame *ogg_vorbis_read(struct ast_filestream *fs, int *whennext) { int clipflag = 0; int i; int j; double accumulator[SAMPLES_MAX]; int val; int samples_in; int samples_out = 0; struct vorbis_desc *s = (struct vorbis_desc *)fs->_private; short *buf; /* SLIN data buffer */ fs->fr.frametype = AST_FRAME_VOICE; fs->fr.subclass = AST_FORMAT_SLINEAR; fs->fr.mallocd = 0; AST_FRAME_SET_BUFFER(&fs->fr, fs->buf, AST_FRIENDLY_OFFSET, BUF_SIZE); buf = (short *)(fs->fr.data); /* SLIN data buffer */ while (samples_out != SAMPLES_MAX) { float **pcm; int len = SAMPLES_MAX - samples_out; /* See ifVorbis decoder has some audio data for us ... */ samples_in = read_samples(fs, &pcm); if (samples_in <= 0) break; /* Got some audio data from Vorbis... */ /* Convert the float audio data to 16-bit signed linear */ clipflag = 0; if (samples_in > len) samples_in = len; for (j = 0; j < samples_in; j++) accumulator[j] = 0.0; for (i = 0; i < s->vi.channels; i++) { float *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; } else if (val < -32768) { val = -32768; clipflag = 1; } buf[samples_out + j] = val; } if (clipflag) ast_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) { fs->fr.datalen = samples_out * 2; fs->fr.samples = samples_out; *whennext = samples_out; return &fs->fr; } else { return NULL; } }