summaryrefslogtreecommitdiff
path: root/src/modules/elementary/access_output/mod.c
blob: f51b512a477dab2860cefe37fcdb9bc095a497bb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif

#include "Elementary.h"

#ifndef EFL_BUILD
# define EFL_BUILD
#endif
#undef ELM_MODULE_HELPER_H
#include "elm_module_helper.h"

/* to enable this module
export ELM_MODULES="access_output>access/api"
export ELM_ACCESS_MODE=1
 */

static void (*cb_func) (void *data);
static void *cb_data;
static Ecore_Exe *espeak = NULL;
static Ecore_Event_Handler *exe_exit_handler = NULL;
static char *tmpf = NULL;
static int tmpfd = -1;

static Eina_Bool
_exe_del(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
   Ecore_Exe_Event_Del *ev = event;

   if ((espeak) && (ev->exe == espeak))
     {
        if (tmpf)
          {
             unlink(tmpf);
             free(tmpf);
             tmpf = NULL;
             close(tmpfd);
             tmpfd = -1;
          }
        espeak = NULL;
        if (cb_func) cb_func(cb_data);
     }
   return ECORE_CALLBACK_RENEW;
}

// module api funcs needed
EAPI int
elm_modapi_init(void *m EINA_UNUSED)
{
   exe_exit_handler =
      ecore_event_handler_add(ECORE_EXE_EVENT_DEL,
                              _exe_del, NULL);
   return 1; // succeed always
}

EAPI int
elm_modapi_shutdown(void *m EINA_UNUSED)
{
   if (exe_exit_handler)
     {
        ecore_event_handler_del(exe_exit_handler);
        exe_exit_handler = NULL;
     }
   return 1; // succeed always
}

// module fucns for the specific module type
EAPI void
out_read(const char *txt)
{
   if (!tmpf)
     {
        char buf[PATH_MAX];
        mode_t cur_umask;

        snprintf(buf, sizeof(buf), "/tmp/.elm-speak-XXXXXX");
        cur_umask = umask(S_IRWXO | S_IRWXG);
        tmpfd = mkstemp(buf);
        umask(cur_umask);
        if (tmpfd >= 0) tmpf = strdup(buf);
        else return;
     }
   if (write(tmpfd, txt, strlen(txt)) < 0) perror("write to tmpfile (espeak)");
}

EAPI void
out_read_done(void)
{
   char buf[PATH_MAX];

   if (espeak)
     {
        ecore_exe_interrupt(espeak);
        espeak = NULL;
     }
   if (tmpf)
     {
        // FIXME: espeak supporets -v XX for voice locale. should provide this
        // based on actual lang/locale
        if (tmpfd >= 0) close(tmpfd);
        tmpfd = -1;
        snprintf(buf, sizeof(buf), "espeak -p 2 -s 120 -k 10 -m -f %s", tmpf);
        espeak = ecore_exe_pipe_run(buf,
                                    ECORE_EXE_NOT_LEADER,
                                    NULL);
     }
}

EAPI void
out_cancel(void)
{
   if (espeak)
     {
        ecore_exe_interrupt(espeak);
        espeak = NULL;
     }
   if (tmpf)
     {
        unlink(tmpf);
        free(tmpf);
        tmpf = NULL;
        close(tmpfd);
        tmpfd = -1;
     }
}

EAPI void
out_done_callback_set(void (*func) (void *data), const void *data)
{
   cb_func = func;
   cb_data = (void *)data;
}

static Eina_Bool
_module_init(void)
{
   return EINA_TRUE;
}

static void
_module_shutdown(void)
{
}

EINA_MODULE_INIT(_module_init);
EINA_MODULE_SHUTDOWN(_module_shutdown);