Advertisement
Guest User

telemain.c

a guest
May 30th, 2015
264
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.26 KB | None | 0 0
  1. /***************************************************************************/
  2. /*
  3.  * main.c
  4.  *
  5.  *  Created on: Apr 16, 2012
  6.  *      Author: carlos
  7.  */
  8.  
  9. #include <errno.h>
  10. #include <string.h>
  11. #include <stdio.h>
  12. #include <unistd.h>
  13. #include <stdlib.h>
  14. #include <unistd.h>
  15.  
  16. #include <sys/types.h>
  17. #include <sys/stat.h>
  18. #include <fcntl.h>
  19.  
  20. #include "util.h"
  21. #include "huawei/modem.h"
  22. #include "huawei/at/at_clcc.h"
  23. #include "huawei/at/at_a.h"
  24. #include "huawei/at/at_cvoice.h"
  25. #include "huawei/at/at_ddsetex.h"
  26. #include "huawei/at/at_chup.h"
  27.  
  28. pthread_t threads[2];
  29. port_t data_port, audio_port;
  30. int fifo_in, fifo_out;
  31.  
  32. /***************************************************************************/
  33. static void print_usage()
  34. {
  35. }
  36.  
  37. /***************************************************************************/
  38. /*
  39. static _bool get_modem_info(port_t *data_port)
  40. {
  41.   at_io_t io;
  42.   at_cvoice_resp_t cvoice;
  43.   if (!get_pcm_frames(data_port))
  44.     return FALSE;
  45. }*/
  46.  
  47. /***************************************************************************/
  48. /* This loads up a large buffer with the contents of a recorded audio file.*/
  49. /***************************************************************************/
  50. static _bool get_pcm_frames(char *audio_file, pcm_data_t *audio)
  51. {
  52.   int file_length = 0, silent_frame = 0, bytes_read = 0;
  53.   FILE *file = fopen(audio_file, "rb");
  54.  
  55.   if (file == NULL)
  56.   {
  57.     LOG(L_ERROR, "%s: error opening file %s. %s\n", __FUNCTION__, audio_file, strerror(errno));
  58.     return FALSE;
  59.   }
  60.  
  61.   fseek(file, 0, SEEK_END);
  62.   file_length  = ftell(file);
  63.   rewind(file);
  64. //  file_length = 252000;
  65.  
  66.   silent_frame  = FRAME_SIZE - (file_length % FRAME_SIZE);
  67.   audio->data    = malloc(file_length + silent_frame);
  68.   audio->length  = file_length + silent_frame;
  69.  
  70.   if ((bytes_read  = fread(audio->data, 1, file_length, file)) != file_length)
  71.   {
  72.     //printf("br %d, l %d\n", bytes_read, file_length);
  73.     LOG(L_ERROR, "%s: couldn't read the whole audio file. %s\n", __FUNCTION__, strerror(errno));
  74.     return FALSE;
  75.   }
  76.  
  77.   memset(&audio->data[file_length], '\0', silent_frame);
  78.  
  79.   return TRUE;
  80. }
  81.  
  82. /***************************************************************************/
  83. static _bool get_modem_frame_rate(port_t *port)
  84. {
  85.   at_io_t io;
  86.   at_cvoice_resp_t cvoice;
  87.  
  88.   at_cvoice_query_all(&io.at_cmd);
  89.   if (!modem_write(port, &io))
  90.   {
  91.     LOG(L_ERROR, "%s: error writing to modem\n", __FUNCTION__);
  92.     return FALSE;
  93.   }
  94.   printf("response: %s\n", io.response.s);
  95.   if (!at_cvoice_parse_response(&io, &cvoice))
  96.   {
  97.     LOG(L_ERROR, "%s: error getting frame rate\n", __FUNCTION__);
  98.     return FALSE;
  99.   }
  100.   port->frame_period  = cvoice.ptime;
  101.   return TRUE;
  102. }
  103.  
  104. /***************************************************************************/
  105. /* Play frames of the recorded message into the  */
  106. /***************************************************************************/
  107. static void play_message(port_t *port, pcm_data_t *audio)
  108. {
  109.   int n = 0, offset = 0, i = 0;
  110.  
  111.   for(i = 0; i <= audio->length; i += FRAME_SIZE)
  112.   {
  113.     n = write(port->fd, &audio->data[offset], FRAME_SIZE);
  114.  
  115.     if (n < FRAME_SIZE)
  116.       LOG(L_DEBUG, "%s: wrote only %d of %d bytes\n", __FUNCTION__, n, FRAME_SIZE);
  117.  
  118.     offset  += FRAME_SIZE;
  119.     usleep(20000); //usleep(port->frame_period * 10000);
  120.   }
  121. }
  122.  
  123. /***************************************************************************/
  124. void *write_thread(void *arg)
  125. {
  126.   char buf[FRAME_SIZE];
  127.   int nwant = FRAME_SIZE;
  128.   int i;
  129.   char *p = buf;
  130.   while(1)
  131.   {
  132.     i = read(fifo_out, p, nwant);
  133.     if (i > 0) {
  134.       nwant -= i;
  135.       p += i;
  136.       if (nwant <= 0) {
  137.     write(audio_port.fd, &buf, FRAME_SIZE);
  138.     nwant = FRAME_SIZE;
  139.     p = buf;
  140.       }
  141.     }
  142.   }
  143. }
  144.  
  145. /***************************************************************************/
  146. void *read_thread(void *arg)
  147. {
  148.   char buf[FRAME_SIZE];
  149.   int nchars;
  150.   while(1)
  151.   {
  152.     nchars=read(audio_port.fd, &buf, sizeof(buf));
  153.     if (nchars > 0)
  154.       write(fifo_in, &buf, nchars);
  155.   }
  156. }
  157.  
  158. /***************************************************************************/
  159. int main(int argc, char **argv)
  160. {
  161.   at_cvoice_resp_t *cvoice = malloc(sizeof(at_cvoice_resp_t));
  162.   at_io_t io;
  163.   pcm_data_t audio;
  164.   _bool incoming  = FALSE;
  165.  
  166.   sscanf("AT^CVOICE\r\n^CVOICE:0,8000,16,20\r\nOK\r\n\0", "AT^CVOICE\r\n^CVOICE:%d,%d,%d,%d",
  167.      &cvoice->mode,
  168.      &cvoice->sampling_rate,
  169.      &cvoice->data_bit,
  170.      &cvoice->ptime);
  171.   LOG(L_DEBUG, "%s: CVOICE -> sampling rate=%d data_bit=%d frame_period=%d\n", __FUNCTION__,
  172.       cvoice->sampling_rate,
  173.       cvoice->data_bit,
  174.       cvoice->ptime);
  175.  
  176.   at_cvoice_query_all(&io.at_cmd);
  177.   /*io.response.s = "AT^CVOICE\r\n^CVOICE:0,8000,16,20\r\nOK\r\n";
  178.   io.response.len  = 44;
  179.   at_cvoice_parse_response(&io, cvoice);
  180.   //return 0;*/
  181.  
  182.   if ((argc > 4) || argc < 3)
  183.   {
  184.     print_usage();
  185.     exit(1);
  186.   }
  187.  
  188.   if (!modem_open_datafile(argv[1], &data_port)) // Open the Command control port.
  189.     exit(1);
  190.   if (!modem_open_audio(argv[2], &audio_port))   // Open the audio data port.
  191.     exit(1);
  192.   if (!get_modem_frame_rate(&data_port))
  193.     exit(1);
  194.   // The answering machine recorded file is now optional.
  195.   if (argc == 4) {
  196.     if (!get_pcm_frames(argv[3], &audio))          // Read the recorded audio file.
  197.       exit(1);
  198.   }
  199.  
  200.   /*******************************************/
  201.   // Make fifos and start the read and write threads
  202.   mkfifo ("/tmp/telein", S_IRUSR| S_IWUSR);
  203.   fifo_in = open("/tmp/telein", O_RDONLY);
  204.   pthread_create(&threads[0], NULL, read_thread, NULL);
  205.  
  206.   // If not answering machine, then open write fifo and thread.
  207.   if (argc != 4) {
  208.     mkfifo ("/tmp/telout", S_IRUSR| S_IWUSR);
  209.     fifo_out = open("/tmp/telout", O_WRONLY);
  210.     pthread_create(&threads[1], NULL, write_thread, NULL);
  211.   }
  212.  
  213.   /*******************************************/
  214.   for(;;) // Loop, handling incoming calls.
  215.   {
  216.     at_io_t io;
  217.     at_clcc_resp_t clcc;
  218.  
  219.     sleep(1);
  220.     at_clcc_query_all(&io.at_cmd);
  221.     if (!modem_write(&data_port, &io))
  222.     {
  223.       LOG(L_ERROR, "%s: error writing to modem\n", __FUNCTION__);
  224.       continue;
  225.     }
  226.     if (!at_clcc_parse_response(&io, &clcc))
  227.     {
  228.       LOG(L_ERROR, "%s: error parsing response\n", __FUNCTION__);
  229.       continue;
  230.     }
  231.     if (clcc.status == CS_INCOMING)
  232.     {
  233.       str_t a_port  = {"2", 1};
  234.       LOG(L_DEBUG, "%s: incoming call. Preparing to answer.\n", __FUNCTION__);
  235.       incoming  = TRUE;
  236.       STR_FREE(io.at_cmd.str_cmd);
  237.       at_a_assign(NULL, &io.at_cmd);
  238.       if (!modem_write(&data_port, &io))
  239.         continue;
  240.       at_ddsetex_assign(&a_port, &io.at_cmd);
  241.       if (!modem_write(&data_port, &io))
  242.         continue;
  243.     }
  244.     else if(clcc.status == CS_ACTIVE)
  245.     {
  246.       if (!incoming)
  247.       {
  248.         LOG(L_DEBUG, "%s: active call not originated by modem, ignoring\n", __FUNCTION__);
  249.         continue;
  250.       }
  251.       else
  252.         LOG(L_DEBUG, "%s: call was answered\n", __FUNCTION__);
  253.       incoming  = FALSE;
  254.  
  255.       if (argc == 4) { // The answering machine recorded file is now optional.
  256.     play_message(&audio_port, &audio);
  257.  
  258.     // If not answering machine, need to monitor stdin to see if the user wants to hang up.
  259.     at_chup_assign(NULL, &io.at_cmd);
  260.     if (!modem_write(&data_port, &io))
  261.       continue;
  262.       }
  263.     }
  264.   }
  265. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement