1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4 
5 #include "Elementary.h"
6 
7 #ifndef EFL_BUILD
8 # define EFL_BUILD
9 #endif
10 #undef ELM_MODULE_HELPER_H
11 #include "elm_module_helper.h"
12 
13 /* to enable this module
14 export ELM_MODULES="access_output>access/api"
15 export ELM_ACCESS_MODE=1
16  */
17 
18 static void (*cb_func) (void *data);
19 static void *cb_data;
20 static Ecore_Exe *espeak = NULL;
21 static Ecore_Event_Handler *exe_exit_handler = NULL;
22 static char *tmpf = NULL;
23 static int tmpfd = -1;
24 
25 static Eina_Bool
_exe_del(void * data EINA_UNUSED,int type EINA_UNUSED,void * event)26 _exe_del(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
27 {
28    Ecore_Exe_Event_Del *ev = event;
29 
30    if ((espeak) && (ev->exe == espeak))
31      {
32         if (tmpf)
33           {
34              unlink(tmpf);
35              free(tmpf);
36              tmpf = NULL;
37              close(tmpfd);
38              tmpfd = -1;
39           }
40         espeak = NULL;
41         if (cb_func) cb_func(cb_data);
42      }
43    return ECORE_CALLBACK_RENEW;
44 }
45 
46 // module api funcs needed
47 EAPI int
elm_modapi_init(void * m EINA_UNUSED)48 elm_modapi_init(void *m EINA_UNUSED)
49 {
50    exe_exit_handler =
51       ecore_event_handler_add(ECORE_EXE_EVENT_DEL,
52                               _exe_del, NULL);
53    return 1; // succeed always
54 }
55 
56 EAPI int
elm_modapi_shutdown(void * m EINA_UNUSED)57 elm_modapi_shutdown(void *m EINA_UNUSED)
58 {
59    if (exe_exit_handler)
60      {
61         ecore_event_handler_del(exe_exit_handler);
62         exe_exit_handler = NULL;
63      }
64    return 1; // succeed always
65 }
66 
67 // module fucns for the specific module type
68 EAPI void
out_read(const char * txt)69 out_read(const char *txt)
70 {
71    if (!tmpf)
72      {
73         char buf[PATH_MAX];
74         mode_t cur_umask;
75 
76         snprintf(buf, sizeof(buf), "/tmp/.elm-speak-XXXXXX");
77         cur_umask = umask(S_IRWXO | S_IRWXG);
78         tmpfd = mkstemp(buf);
79         umask(cur_umask);
80         if (tmpfd >= 0) tmpf = strdup(buf);
81         else return;
82      }
83    if (write(tmpfd, txt, strlen(txt)) < 0) perror("write to tmpfile (espeak)");
84 }
85 
86 EAPI void
out_read_done(void)87 out_read_done(void)
88 {
89    char buf[PATH_MAX];
90 
91    if (espeak)
92      {
93         ecore_exe_interrupt(espeak);
94         espeak = NULL;
95      }
96    if (tmpf)
97      {
98         // FIXME: espeak supporets -v XX for voice locale. should provide this
99         // based on actual lang/locale
100         if (tmpfd >= 0) close(tmpfd);
101         tmpfd = -1;
102         snprintf(buf, sizeof(buf), "espeak -p 2 -s 120 -k 10 -m -f %s", tmpf);
103         espeak = ecore_exe_pipe_run(buf,
104                                     ECORE_EXE_NOT_LEADER,
105                                     NULL);
106      }
107 }
108 
109 EAPI void
out_cancel(void)110 out_cancel(void)
111 {
112    if (espeak)
113      {
114         ecore_exe_interrupt(espeak);
115         espeak = NULL;
116      }
117    if (tmpf)
118      {
119         unlink(tmpf);
120         free(tmpf);
121         tmpf = NULL;
122         close(tmpfd);
123         tmpfd = -1;
124      }
125 }
126 
127 EAPI void
out_done_callback_set(void (* func)(void * data),const void * data)128 out_done_callback_set(void (*func) (void *data), const void *data)
129 {
130    cb_func = func;
131    cb_data = (void *)data;
132 }
133 
134 static Eina_Bool
_module_init(void)135 _module_init(void)
136 {
137    return EINA_TRUE;
138 }
139 
140 static void
_module_shutdown(void)141 _module_shutdown(void)
142 {
143 }
144 
145 EINA_MODULE_INIT(_module_init);
146 EINA_MODULE_SHUTDOWN(_module_shutdown);
147