audiofax.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. #include "precompile.h"
  2. #include "audiofax.h"
  3. #include "audiolog.h"
  4. #include "audiocontext.h"
  5. #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
  6. #include <spandsp.h>
  7. #include <spandsp/version.h>
  8. #define DEFAULT_IDENT "SpanDSP Fax Ident"
  9. #define DEFAULT_HEADER "SpanDSP Fax Header"
  10. static void spanfax_log_message(int level, const char *msg)
  11. {
  12. int log_level;
  13. switch (level) {
  14. case SPAN_LOG_NONE:
  15. return;
  16. case SPAN_LOG_ERROR:
  17. case SPAN_LOG_PROTOCOL_ERROR:
  18. log_level = AUDIO_LOG_LEVEL_ERROR;
  19. break;
  20. case SPAN_LOG_WARNING:
  21. case SPAN_LOG_PROTOCOL_WARNING:
  22. log_level = AUDIO_LOG_LEVEL_WARN;
  23. break;
  24. case SPAN_LOG_FLOW:
  25. case SPAN_LOG_FLOW_2:
  26. case SPAN_LOG_FLOW_3:
  27. default: /* SPAN_LOG_DEBUG, SPAN_LOG_DEBUG_2, SPAN_LOG_DEBUG_3 */
  28. log_level = AUDIO_LOG_LEVEL_DEBUG;
  29. break;
  30. }
  31. if (msg && strlen(msg)) {
  32. audio_log(log_level, msg);
  33. }
  34. }
  35. /*
  36. * Called at the end of the document
  37. */
  38. static void phase_e_handler(t30_state_t * s, void *user_data, int result)
  39. {
  40. audiofax_t *fax = (audiofax_t *)user_data;
  41. audiostream_raise_event(&fax->base, STREAM_EVT_FAX_END, result == T30_ERR_OK ? 0 : -1, 0);
  42. }
  43. static apr_status_t read_frame(void *self, audioframe_t *frame)
  44. {
  45. audiofax_t *fax = CONTAINING_RECORD(self, audiofax_t, base);
  46. int tx;
  47. frame->dtmf = 0;
  48. frame->size = 2 * FRAME_TIME * 8000 / 1000;
  49. tx = fax_tx(fax->fax_state, (short*)frame->buffer, frame->size>>1);
  50. return APR_SUCCESS;
  51. }
  52. static apr_status_t write_frame(void *self, const audioframe_t *frame)
  53. {
  54. audiofax_t *fax = CONTAINING_RECORD(self, audiofax_t, base);
  55. char tmp[SUGGEST_FRAME_SIZE];
  56. memcpy(tmp, frame->buffer, frame->size);
  57. fax_rx(fax->fax_state, (short*)&tmp[0], frame->size >> 1);
  58. return APR_SUCCESS;
  59. }
  60. static audiostream_vtbl_t g_stream_vtbl = {
  61. &read_frame,
  62. &write_frame,
  63. };
  64. apr_status_t audiofax_create(apr_pool_t *pool, audioengine_t *engine, audiofax_t **p_fax)
  65. {
  66. audiofax_t *fax;
  67. fax = apr_palloc(pool, sizeof(audiofax_t));
  68. memset(fax, 0, sizeof(audiofax_t));
  69. fax->ident = DEFAULT_IDENT;
  70. fax->header = DEFAULT_HEADER;
  71. fax->disable_v17 = FALSE;
  72. fax->tx_page_start = -1;
  73. fax->tx_page_end = -1;
  74. fax->fax_state = 0;
  75. fax->ecm = TRUE;
  76. audiostream_init(engine, &g_stream_vtbl, &fax->base);
  77. fax->base.direction = STREAM_DIR_BOTH;
  78. *p_fax = fax;
  79. return APR_SUCCESS;
  80. }
  81. void audiofax_destroy(audiofax_t *fax)
  82. {
  83. if (fax->file) {
  84. free(fax->file);
  85. fax->file = NULL;
  86. }
  87. if (fax->ident) {
  88. free(fax->ident);
  89. fax->ident = NULL;
  90. }
  91. if (fax->header) {
  92. free(fax->header);
  93. fax->header = NULL;
  94. }
  95. }
  96. apr_status_t audiofax_set_caller(audiofax_t *fax, int on)
  97. {
  98. fax->caller = !!on;
  99. return APR_SUCCESS;
  100. }
  101. apr_status_t audiofax_set_file(audiofax_t *fax, const char *file)
  102. {
  103. if (!file)
  104. return APR_EINVAL;
  105. if (fax->file)
  106. free(fax->file);
  107. fax->file = strdup(file);
  108. return APR_SUCCESS;
  109. }
  110. apr_status_t audiofax_set_ident(audiofax_t *fax, const char *ident)
  111. {
  112. if (!ident)
  113. return APR_EINVAL;
  114. if (fax->ident)
  115. free(fax->ident);
  116. fax->ident = strdup(ident);
  117. return APR_SUCCESS;
  118. }
  119. apr_status_t audiofax_set_header(audiofax_t *fax, const char *header)
  120. {
  121. if (!header)
  122. return APR_EINVAL;
  123. if (fax->header)
  124. free(fax->header);
  125. fax->header = strdup(header);
  126. return APR_SUCCESS;
  127. }
  128. apr_status_t audiofax_set_page_range(audiofax_t *fax, int start, int end)
  129. {
  130. fax->tx_page_start = start;
  131. fax->tx_page_end = end;
  132. return APR_SUCCESS;
  133. }
  134. apr_status_t audiofax_enable_v17(audiofax_t *fax, int on)
  135. {
  136. fax->disable_v17 = !on;
  137. return APR_SUCCESS;
  138. }
  139. apr_status_t audiofax_enable_ecm(audiofax_t *fax, int on)
  140. {
  141. fax->ecm = on;
  142. return APR_SUCCESS;
  143. }
  144. apr_status_t audiofax_init(audiofax_t *fax)
  145. {
  146. t30_state_t *t30;
  147. fax->fax_state = malloc(sizeof(fax_state_t));
  148. t30 = fax_get_t30_state(fax->fax_state);
  149. memset(fax->fax_state, 0, sizeof(fax_state_t));
  150. if (fax_init(fax->fax_state, fax->caller) == NULL)
  151. return APR_EGENERAL;
  152. fax_set_transmit_on_idle(fax->fax_state, TRUE);
  153. span_log_set_message_handler(&(((fax_state_t*)fax->fax_state)->logging), spanfax_log_message);
  154. span_log_set_message_handler(&t30->logging, spanfax_log_message);
  155. t30_set_tx_ident(t30, fax->ident ? fax->ident : DEFAULT_IDENT);
  156. t30_set_tx_page_header_info(t30, fax->header ? fax->header : DEFAULT_HEADER);
  157. t30_set_phase_e_handler(t30, phase_e_handler, fax);
  158. t30_set_supported_image_sizes(t30,
  159. T30_SUPPORT_US_LETTER_LENGTH | T30_SUPPORT_US_LEGAL_LENGTH | T30_SUPPORT_UNLIMITED_LENGTH
  160. | T30_SUPPORT_215MM_WIDTH | T30_SUPPORT_255MM_WIDTH | T30_SUPPORT_303MM_WIDTH);
  161. t30_set_supported_resolutions(t30,
  162. T30_SUPPORT_STANDARD_RESOLUTION | T30_SUPPORT_FINE_RESOLUTION | T30_SUPPORT_SUPERFINE_RESOLUTION
  163. | T30_SUPPORT_R8_RESOLUTION | T30_SUPPORT_R16_RESOLUTION);
  164. if (fax->disable_v17) {
  165. t30_set_supported_modems(t30, T30_SUPPORT_V29 | T30_SUPPORT_V27TER);
  166. } else {
  167. t30_set_supported_modems(t30, T30_SUPPORT_V29 | T30_SUPPORT_V27TER | T30_SUPPORT_V17);
  168. }
  169. if (fax->ecm) {
  170. t30_set_supported_compressions(t30, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);
  171. t30_set_ecm_capability(t30, TRUE);
  172. } else {
  173. t30_set_supported_compressions(t30, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION);
  174. }
  175. if (fax->caller) {
  176. t30_set_tx_file(t30, fax->file, fax->tx_page_start, fax->tx_page_end);
  177. } else {
  178. t30_set_rx_file(t30, fax->file, -1);
  179. }
  180. return APR_SUCCESS;
  181. }
  182. apr_status_t audiofax_term(audiofax_t *fax)
  183. {
  184. if (fax->fax_state) {
  185. t30_state_t *t30;
  186. t30 = fax_get_t30_state(fax->fax_state);
  187. if (t30) {
  188. t30_terminate(t30);
  189. }
  190. fax_release(fax->fax_state);
  191. free(fax->fax_state);
  192. fax->fax_state = 0;
  193. }
  194. return APR_SUCCESS;
  195. }