Пример #1
0
static gboolean
read_response (GstFestival * festival)
{
  char ack[4];
  char *data;
  int filesize;
  int fd;
  int n;
  gboolean ret = TRUE;

  fd = festival->info->server_fd;
  do {
    for (n = 0; n < 3;)
      n += read (fd, ack + n, 3 - n);
    ack[3] = '\0';
    GST_DEBUG_OBJECT (festival, "got response %s", ack);

    if (strcmp (ack, "WV\n") == 0) {
      GstBuffer *buffer;

      /* receive a waveform */
      data = socket_receive_file_to_buff (fd, &filesize);
      GST_DEBUG_OBJECT (festival, "received %d bytes of waveform data",
          filesize);

      /* push contents as a buffer */
      buffer = gst_buffer_new ();
      GST_BUFFER_SIZE (buffer) = (filesize);
      GST_BUFFER_DATA (buffer) = (guint8 *) data;
      GST_BUFFER_MALLOCDATA (buffer) = (guint8 *) data;
      GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;

      gst_pad_push (festival->srcpad, buffer);

    } else if (strcmp (ack, "LP\n") == 0) {
      /* receive an s-expr */
      data = client_accept_s_expr (fd);
      GST_DEBUG_OBJECT (festival, "received s-expression: %s", data);
      g_free (data);
    } else if (strcmp (ack, "ER\n") == 0) {
      /* server got an error */
      GST_ELEMENT_ERROR (festival,
          LIBRARY,
          FAILED,
          ("Festival speech server returned an error"),
          ("Make sure you have voices/languages installed"));
      ret = FALSE;
      break;
    }

  } while (strcmp (ack, "OK\n") != 0);

  return ret;
}
Пример #2
0
static char *
client_accept_s_expr (int fd)
{
  /* Read s-expression from server, as a char * */
  char *expr;
  int filesize;

  expr = socket_receive_file_to_buff (fd, &filesize);
  expr[filesize] = '\0';

  return expr;
}
Пример #3
0
static int festival_exec(struct ast_channel *chan, void *vdata)
{
    int usecache;
    int res=0;
    struct localuser *u;
    struct sockaddr_in serv_addr;
    struct hostent *serverhost;
    struct ast_hostent ahp;
    int fd;
    FILE *fs;
    char *host;
    char *cachedir;
    char *temp;
    char *festivalcommand;
    int port=1314;
    int n;
    char ack[4];
    char *waveform;
    int filesize;
    int wave;
    char bigstring[MAXFESTLEN];
    int i;
    struct MD5Context md5ctx;
    unsigned char MD5Res[16];
    char MD5Hex[33] = "";
    char koko[4] = "";
    char cachefile[MAXFESTLEN]="";
    int readcache=0;
    int writecache=0;
    int strln;
    int fdesc = -1;
    char buffer[16384];
    int seekpos = 0;
    char *data;
    char *intstr;
    struct ast_config *cfg;
    char *newfestivalcommand;

    if (ast_strlen_zero(vdata)) {
        ast_log(LOG_WARNING, "festival requires an argument (text)\n");
        return -1;
    }

    LOCAL_USER_ADD(u);

    cfg = ast_config_load(FESTIVAL_CONFIG);
    if (!cfg) {
        ast_log(LOG_WARNING, "No such configuration file %s\n", FESTIVAL_CONFIG);
        LOCAL_USER_REMOVE(u);
        return -1;
    }
    if (!(host = ast_variable_retrieve(cfg, "general", "host"))) {
        host = "localhost";
    }
    if (!(temp = ast_variable_retrieve(cfg, "general", "port"))) {
        port = 1314;
    } else {
        port = atoi(temp);
    }
    if (!(temp = ast_variable_retrieve(cfg, "general", "usecache"))) {
        usecache=0;
    } else {
        usecache = ast_true(temp);
    }
    if (!(cachedir = ast_variable_retrieve(cfg, "general", "cachedir"))) {
        cachedir = "/tmp/";
    }
    if (!(festivalcommand = ast_variable_retrieve(cfg, "general", "festivalcommand"))) {
        festivalcommand = "(tts_textasterisk \"%s\" 'file)(quit)\n";
    } else { /* This else parses the festivalcommand that we're sent from the config file for \n's, etc */
        int i, j;
        newfestivalcommand = alloca(strlen(festivalcommand) + 1);

        for (i = 0, j = 0; i < strlen(festivalcommand); i++) {
            if (festivalcommand[i] == '\\' && festivalcommand[i + 1] == 'n') {
                newfestivalcommand[j++] = '\n';
                i++;
            } else if (festivalcommand[i] == '\\') {
                newfestivalcommand[j++] = festivalcommand[i + 1];
                i++;
            } else
                newfestivalcommand[j++] = festivalcommand[i];
        }
        newfestivalcommand[j] = '\0';
        festivalcommand = newfestivalcommand;
    }

    data = ast_strdupa(vdata);

    intstr = strchr(data, '|');
    if (intstr) {
        *intstr = '\0';
        intstr++;
        if (!strcasecmp(intstr, "any"))
            intstr = AST_DIGIT_ANY;
    }

    ast_log(LOG_DEBUG, "Text passed to festival server : %s\n",(char *)data);
    /* Connect to local festival server */

    fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    if (fd < 0) {
        ast_log(LOG_WARNING,"festival_client: can't get socket\n");
        ast_config_destroy(cfg);
        LOCAL_USER_REMOVE(u);
        return -1;
    }
    memset(&serv_addr, 0, sizeof(serv_addr));
    if ((serv_addr.sin_addr.s_addr = inet_addr(host)) == -1) {
        /* its a name rather than an ipnum */
        serverhost = ast_gethostbyname(host, &ahp);
        if (serverhost == (struct hostent *)0) {
            ast_log(LOG_WARNING,"festival_client: gethostbyname failed\n");
            ast_config_destroy(cfg);
            LOCAL_USER_REMOVE(u);
            return -1;
        }
        memmove(&serv_addr.sin_addr,serverhost->h_addr, serverhost->h_length);
    }
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(port);

    if (connect(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != 0) {
        ast_log(LOG_WARNING,"festival_client: connect to server failed\n");
        ast_config_destroy(cfg);
        LOCAL_USER_REMOVE(u);
        return -1;
    }

    /* Compute MD5 sum of string */
    MD5Init(&md5ctx);
    MD5Update(&md5ctx,(unsigned char const *)data,strlen(data));
    MD5Final(MD5Res,&md5ctx);
    MD5Hex[0] = '\0';

    /* Convert to HEX and look if there is any matching file in the cache
    	directory */
    for (i=0; i<16; i++) {
        snprintf(koko, sizeof(koko), "%X",MD5Res[i]);
        strncat(MD5Hex, koko, sizeof(MD5Hex) - strlen(MD5Hex) - 1);
    }
    readcache=0;
    writecache=0;
    if (strlen(cachedir)+strlen(MD5Hex)+1<=MAXFESTLEN && (usecache==-1)) {
        snprintf(cachefile, sizeof(cachefile), "%s/%s", cachedir, MD5Hex);
        fdesc=open(cachefile,O_RDWR);
        if (fdesc==-1) {
            fdesc=open(cachefile,O_CREAT|O_RDWR,0777);
            if (fdesc!=-1) {
                writecache=1;
                strln=strlen((char *)data);
                ast_log(LOG_DEBUG,"line length : %d\n",strln);
                write(fdesc,&strln,sizeof(int));
                write(fdesc,data,strln);
                seekpos=lseek(fdesc,0,SEEK_CUR);
                ast_log(LOG_DEBUG,"Seek position : %d\n",seekpos);
            }
        } else {
            read(fdesc,&strln,sizeof(int));
            ast_log(LOG_DEBUG,"Cache file exists, strln=%d, strlen=%d\n",strln,(int)strlen((char *)data));
            if (strlen((char *)data)==strln) {
                ast_log(LOG_DEBUG,"Size OK\n");
                read(fdesc,&bigstring,strln);
                bigstring[strln] = 0;
                if (strcmp(bigstring,data)==0) {
                    readcache=1;
                } else {
                    ast_log(LOG_WARNING,"Strings do not match\n");
                }
            } else {
                ast_log(LOG_WARNING,"Size mismatch\n");
            }
        }
    }

    if (readcache==1) {
        close(fd);
        fd=fdesc;
        ast_log(LOG_DEBUG,"Reading from cache...\n");
    } else {
        ast_log(LOG_DEBUG,"Passing text to festival...\n");
        fs=fdopen(dup(fd),"wb");
        fprintf(fs,festivalcommand,(char *)data);
        fflush(fs);
        fclose(fs);
    }

    /* Write to cache and then pass it down */
    if (writecache==1) {
        ast_log(LOG_DEBUG,"Writing result to cache...\n");
        while ((strln=read(fd,buffer,16384))!=0) {
            write(fdesc,buffer,strln);
        }
        close(fd);
        close(fdesc);
        fd=open(cachefile,O_RDWR);
        lseek(fd,seekpos,SEEK_SET);
    }

    ast_log(LOG_DEBUG,"Passing data to channel...\n");

    /* Read back info from server */
    /* This assumes only one waveform will come back, also LP is unlikely */
    wave = 0;
    do {
        int read_data;
        for (n=0; n < 3; )
        {
            read_data = read(fd,ack+n,3-n);
            /* this avoids falling in infinite loop
             * in case that festival server goes down
             * */
            if ( read_data == -1 )
            {
                ast_log(LOG_WARNING,"Unable to read from cache/festival fd");
                close(fd);
                ast_config_destroy(cfg);
                LOCAL_USER_REMOVE(u);
                return -1;
            }
            n += read_data;
        }
        ack[3] = '\0';
        if (strcmp(ack,"WV\n") == 0) {         /* receive a waveform */
            ast_log(LOG_DEBUG,"Festival WV command\n");
            waveform = socket_receive_file_to_buff(fd,&filesize);
            res = send_waveform_to_channel(chan,waveform,filesize, intstr);
            free(waveform);
            break;
        }
        else if (strcmp(ack,"LP\n") == 0) {   /* receive an s-expr */
            ast_log(LOG_DEBUG,"Festival LP command\n");
            waveform = socket_receive_file_to_buff(fd,&filesize);
            waveform[filesize]='\0';
            ast_log(LOG_WARNING,"Festival returned LP : %s\n",waveform);
            free(waveform);
        } else if (strcmp(ack,"ER\n") == 0) {    /* server got an error */
            ast_log(LOG_WARNING,"Festival returned ER\n");
            res=-1;
            break;
        }
    } while (strcmp(ack,"OK\n") != 0);
    close(fd);
    ast_config_destroy(cfg);
    LOCAL_USER_REMOVE(u);
    return res;

}