diff options
| author | XANTRONIX Development | 2022-02-01 16:58:46 -0500 | 
|---|---|---|
| committer | XANTRONIX Development | 2022-02-01 16:58:46 -0500 | 
| commit | 27960adc8926dbcc0399bf1b2f8408ebeaaa5700 (patch) | |
| tree | b14673d9b12630e9888c70267dfd574f484b307b /src | |
| parent | a048f5848e6d57098d4524cb8b97853ef8329854 (diff) | |
| download | xas-27960adc8926dbcc0399bf1b2f8408ebeaaa5700.tar.gz xas-27960adc8926dbcc0399bf1b2f8408ebeaaa5700.tar.bz2 xas-27960adc8926dbcc0399bf1b2f8408ebeaaa5700.zip | |
Again, with the whole "this stuff compiles" thing
Diffstat (limited to 'src')
| -rw-r--r-- | src/vox.c | 229 | 
1 files changed, 218 insertions, 11 deletions
| @@ -1,34 +1,175 @@  #include <stdlib.h> +#include <string.h>  #include <unistd.h> +#include <fcntl.h> +#include <sysexits.h>  #include <sys/wait.h> +#include <errno.h> +#include <xas/riff.h>  #include <xas/vox.h> -static void vox_cleanup(xas_vox *vox, xas_audio_stream *stream) { -    int status; +static int vox_stop(xas_vox *vox) { +    if (vox->stdin >= 0) { +        (void)close(vox->stdin); + +        vox->stdin = -1; +    } + +    if (vox->stdout >= 0) { +        (void)close(vox->stdout); + +        vox->stdout = -1; +    } + +    if (vox->in) { +        (void)fclose(vox->in); + +        vox->in = NULL; +    } + +    if (vox->output) { +        xas_audio_stream_destroy(vox->output); + +        vox->output = NULL; +    } + +    if (vox->pid) { +        int status; + +        if (waitpid(vox->pid, &status, 0) < 0) { +            goto error_waitpid; +        } + +        vox->pid = -1; +    } + +    vox->flags &= ~XAS_VOX_ACTIVE; + +    return 0; + +error_waitpid: +    return -1; +} -    if (vox->flags & XAS_VOX_ACTIVE) { -        if (vox->pid >= 0) { -            (void)waitpid(vox->pid, &status, 0); +static int vox_start(xas_vox *vox) { +    int pipe_stdin[2], +        pipe_stdout[2]; + +    int pid; + +    char sample_rate[40]; + +    char *args[] = { +        (char *)vox->text2wave_path, +        "-F", +        sample_rate, +        "-", +        "-o", +        "-", +        NULL +    }; + +    snprintf(sample_rate, sizeof(sample_rate)-1, "%zu", vox->sample_rate); + +    (void)vox_stop(vox); + +    if (pipe(pipe_stdin) < 0) { +        goto error_pipe_stdin; +    } + +    if (pipe(pipe_stdout) < 0) { +        goto error_pipe_stdout; +    } + +    if ((pid = fork()) < 0) { +        goto error_fork; +    } + +    if (pid == 0) { +        int fd; + +        if ((fd = open("/dev/null", O_WRONLY)) < 0) { +            goto error_child; +        } + +        close(pipe_stdin[1]); +        close(pipe_stdout[0]); + +        if (dup2(pipe_stdin[0], 0) < 0) { +            goto error_child;          } -        if (vox->stdout >= 0) { -            (void)close(vox->stdout); +        if (dup2(pipe_stdout[1], 1) < 0) { +            goto error_child;          } + +        if (dup2(fd, 2) < 0) { +            goto error_child; +        } + +        if (execv(vox->text2wave_path, args) < 0) { +            goto error_child; +        } + +error_child: +        exit(EX_OSERR);      } + +    close(pipe_stdin[0]); +    close(pipe_stdout[1]); + +    vox->pid    = pid; +    vox->stdin  = pipe_stdin[1]; +    vox->stdout = pipe_stdout[0]; +    vox->in     = fdopen(pipe_stdin[1], "w"); +    vox->output = NULL; + +    return 0; + +error_fork: +    (void)close(pipe_stdout[1]); +    (void)close(pipe_stdout[0]); + +error_pipe_stdout: +    (void)close(pipe_stdin[1]); +    (void)close(pipe_stdin[0]); + +error_pipe_stdin: +    return -1; +} + +static void vox_cleanup(xas_vox *vox, xas_audio_stream *stream) { +    (void)vox_stop(vox);  }  static ssize_t vox_fill(xas_vox *vox,                          int16_t *samples,                          size_t count,                          xas_audio_stream *stream) { -    size_t i; +    ssize_t readlen; +    int16_t *buf; -    for (i=0; i<count; i++) { -        samples[i] = 0; +    if (!(vox->flags & XAS_VOX_ACTIVE)) { +        memset(samples, '\0', count * vox->sample_size); + +        return count;      } -    return i; +    if ((readlen = xas_audio_stream_read(vox->output, +                                           (void **)&buf, +                                           count)) < 0) { +        goto error_audio_stream_read; +    } + +    if (readlen == 0) { +        vox_stop(vox); +    } + +    return readlen; + +error_audio_stream_read: +    return -1;  }  xas_vox *xas_vox_new(const char *text2wave_path, @@ -50,7 +191,9 @@ xas_vox *xas_vox_new(const char *text2wave_path,      vox->flags          = XAS_VOX_IDLE;      vox->pid    = -1; +    vox->stdin  = -1;      vox->stdout = -1; +    vox->in     = NULL;      return vox; @@ -58,6 +201,70 @@ error_malloc_vox:      return NULL;  } +void xas_vox_destroy(xas_vox *vox) { +    free(vox); +} + +int xas_vox_stop(xas_vox *vox) { +    return vox_stop(vox); +} + +int xas_vox_vsayf(xas_vox *vox, const char *format, va_list args) { +    int ret; + +    if (vox_start(vox) < 0) { +        goto error_vox_start; +    } + +    if ((ret = vfprintf(vox->in, format, args)) < 0) { +        goto error_vfprintf; +    } + +    (void)close(vox->stdin); +    vox->stdin = -1; + +    (void)fclose(vox->in); +    vox->in = NULL; + +    if ((vox->output = xas_riff_open_fd(vox->stdout)) == NULL) { +        goto error_riff_open_fd; +    } + +    if (vox->output->sample_size != vox->sample_size +     || vox->output->sample_rate != vox->sample_rate) { +        errno = EINVAL; + +        goto error_invalid_stream; +    } + +    return ret; + +error_invalid_stream: +    xas_audio_stream_destroy(vox->output); + +error_riff_open_fd: +error_vfprintf: +    (void)vox_stop(vox); + +error_vox_start: +    return -1; +} + +int xas_vox_sayf(xas_vox *vox, const char *format, ...) { +    int ret; +    va_list args; + +    va_start(args, format); +    ret = xas_vox_vsayf(vox, format, args); +    va_end(args); + +    return ret; +} + +int xas_vox_say(xas_vox *vox, const char *message) { +    return xas_vox_sayf(vox, "%\n", message); +} +  xas_audio_stream *xas_vox_stream_new(xas_vox *vox) {      return xas_audio_stream_new_source((xas_audio_fill)vox_fill,                                           (xas_audio_cleanup)vox_cleanup, | 
 
    