0
|
1 |
/**
|
|
2 |
* $Id: main.c 53 2008-01-10 00:19:41Z mbroeker $
|
|
3 |
* $URL: http://localhost/svn/c/VirtualReader/trunk/src/main.c $
|
|
4 |
*/
|
|
5 |
|
|
6 |
#include <sentence.h>
|
|
7 |
#include <keyboard.h>
|
|
8 |
#include <thread.h>
|
|
9 |
#include <audioplayer.h>
|
|
10 |
#include <interface.h>
|
|
11 |
|
|
12 |
#define STARTWRITER 0
|
|
13 |
#define WRITER 1
|
|
14 |
#define READER 2
|
|
15 |
|
|
16 |
#define STEP 2 // jump back n-steps
|
|
17 |
|
|
18 |
void find_next (ThreadData * data)
|
|
19 |
{
|
|
20 |
long tm = (long)audioplayer_gettime ();
|
|
21 |
long position;
|
|
22 |
int i, max;
|
|
23 |
|
|
24 |
max = words (data->sentences[data->satz]);
|
|
25 |
|
|
26 |
for (i = 0; i < max; i++) {
|
|
27 |
if (data->timings[data->satz][i] > tm)
|
|
28 |
break;
|
|
29 |
}
|
|
30 |
|
|
31 |
position = data->timings[data->satz][i];
|
|
32 |
audioplayer_settime (position);
|
|
33 |
}
|
|
34 |
|
|
35 |
void find_prev (ThreadData * data)
|
|
36 |
{
|
|
37 |
long tm = (long)audioplayer_gettime ();
|
|
38 |
long position;
|
|
39 |
int i, max;
|
|
40 |
|
|
41 |
max = words (data->sentences[data->satz]);
|
|
42 |
|
|
43 |
for (i = STEP; i < max; i++) {
|
|
44 |
if (data->timings[data->satz][i] > tm)
|
|
45 |
break;
|
|
46 |
}
|
|
47 |
|
|
48 |
position = data->timings[data->satz][i - STEP];
|
|
49 |
audioplayer_settime (position);
|
|
50 |
}
|
|
51 |
|
|
52 |
int main (int argc, char **argv)
|
|
53 |
{
|
|
54 |
char **sentences = NULL; // to store an array of strings
|
|
55 |
char *Text = NULL; // to store the content of a textfile
|
|
56 |
long **timings = NULL; // to store the timings
|
|
57 |
int i, count; // sentence counter
|
|
58 |
int verbose = 0;
|
|
59 |
|
|
60 |
pthread_t p_thread, w_thread;
|
|
61 |
|
|
62 |
ThreadData *data[3]; // independent thread data
|
|
63 |
|
|
64 |
tts_options ttsopt = interface_get_cl_opts (argc, argv);
|
|
65 |
ttshandles ttsh = interface_init (ttsopt);
|
|
66 |
|
|
67 |
if ((Text = readbuffer (ttsopt.TextFile)) != NULL) {
|
|
68 |
sentences = getstrings (Text, &count);
|
|
69 |
free (Text);
|
|
70 |
} else {
|
|
71 |
printf ("ERROR: Textfile %s is corrupt.\n", ttsopt.TextFile);
|
|
72 |
free (ttsopt.TextFile);
|
|
73 |
free (ttsopt.AudioFile);
|
|
74 |
free (ttsopt.Voice);
|
|
75 |
free (ttsopt.Path);
|
|
76 |
|
|
77 |
return EXIT_SUCCESS;
|
|
78 |
}
|
|
79 |
|
|
80 |
// Timinganalyse des Textes
|
|
81 |
if ((timings = calloc ((size_t) count, sizeof (long *) + 1)) == NULL) {
|
|
82 |
free (ttsopt.TextFile);
|
|
83 |
free (ttsopt.AudioFile);
|
|
84 |
free (ttsopt.Voice);
|
|
85 |
free (ttsopt.Path);
|
|
86 |
|
|
87 |
return EXIT_SUCCESS;
|
|
88 |
}
|
|
89 |
|
|
90 |
for (i = 0; i < count; i++) {
|
|
91 |
timings[i] = interface_get_timing (ttsh, sentences[i]);
|
|
92 |
}
|
|
93 |
|
|
94 |
/*
|
|
95 |
* Initialize Sound
|
|
96 |
*/
|
|
97 |
if (audio_init ())
|
|
98 |
fprintf (stderr, "AUDIO ERROR\n");
|
|
99 |
|
|
100 |
for (i = 0; i < 3; i++) {
|
|
101 |
data[i] = malloc (sizeof (ThreadData) + 1);
|
|
102 |
if (data[i] == NULL)
|
|
103 |
exit (0);
|
|
104 |
data[i]->ttsopt = ttsopt;
|
|
105 |
data[i]->ttsh = ttsh;
|
|
106 |
data[i]->fname = ttsopt.TextFile;
|
|
107 |
data[i]->sentences = sentences;
|
|
108 |
data[i]->timings = timings;
|
|
109 |
}
|
|
110 |
|
|
111 |
/*
|
|
112 |
* write sentences from 0-1 :)
|
|
113 |
*/
|
|
114 |
data[STARTWRITER]->satz = 0;
|
|
115 |
data[STARTWRITER]->items = 1;
|
|
116 |
|
|
117 |
pthread_create (&w_thread, NULL, (void *)writewav, data[STARTWRITER]);
|
|
118 |
pthread_join (w_thread, NULL);
|
|
119 |
|
|
120 |
/*
|
|
121 |
* write sentences from 1-count :)
|
|
122 |
*/
|
|
123 |
data[WRITER]->satz = 1;
|
|
124 |
data[WRITER]->items = count;
|
|
125 |
pthread_create (&w_thread, NULL, (void *)writewav, data[WRITER]);
|
|
126 |
|
|
127 |
data[READER]->satz = 0;
|
|
128 |
data[READER]->items = count;
|
|
129 |
pthread_create (&p_thread, NULL, (void *)readtext, data[READER]);
|
|
130 |
|
|
131 |
while (data[READER]->satz < data[READER]->items) {
|
|
132 |
switch (getSingleKey ()) {
|
|
133 |
case 'i':
|
|
134 |
// next word
|
|
135 |
if (data[READER]->satz < data[READER]->items)
|
|
136 |
find_next (data[READER]);
|
|
137 |
else
|
|
138 |
printf ("ERROR: Cannot seek anymore\n");
|
|
139 |
break;
|
|
140 |
|
|
141 |
case 'j':
|
|
142 |
// previous sentence
|
|
143 |
if (data[READER]->satz > 0) {
|
|
144 |
data[READER]->satz--;
|
|
145 |
p_thread_restart (p_thread, readtext, data[READER]);
|
|
146 |
}
|
|
147 |
break;
|
|
148 |
|
|
149 |
case 'k':
|
|
150 |
// previous word
|
|
151 |
find_prev (data[READER]);
|
|
152 |
break;
|
|
153 |
|
|
154 |
case 'l':
|
|
155 |
// next sentence
|
|
156 |
if (data[READER]->satz < data[READER]->items) {
|
|
157 |
data[READER]->satz++;
|
|
158 |
p_thread_restart (p_thread, readtext, data[READER]);
|
|
159 |
}
|
|
160 |
break;
|
|
161 |
|
|
162 |
case 'p':
|
|
163 |
// print useful informations
|
|
164 |
printf ("Current Position: [%5d/%5d]ms = #%d\n",
|
|
165 |
audioplayer_gettime (), audioplayer_getwavelength (NULL), audioplayer_getposition ());
|
|
166 |
break;
|
|
167 |
|
|
168 |
case 'q':
|
|
169 |
// quit
|
|
170 |
pthread_cancel (w_thread);
|
|
171 |
pthread_cancel (p_thread);
|
|
172 |
data[READER]->satz = data[READER]->items;
|
|
173 |
break;
|
|
174 |
|
|
175 |
case 'r':
|
|
176 |
// reset player
|
|
177 |
pthread_cancel (p_thread);
|
|
178 |
if (!pthread_join (p_thread, NULL))
|
|
179 |
printf ("RESET\n");
|
|
180 |
break;
|
|
181 |
case 's':
|
|
182 |
printf ("S[%d]: %s\n", data[READER]->satz, sentences[data[READER]->satz]);
|
|
183 |
break;
|
|
184 |
case 'v':
|
|
185 |
verbose ^= 1;
|
|
186 |
audioplayer_setverbose (verbose);
|
|
187 |
break;
|
|
188 |
|
|
189 |
default:
|
|
190 |
/*
|
|
191 |
* unknown command
|
|
192 |
*/
|
|
193 |
break;
|
|
194 |
}
|
|
195 |
}
|
|
196 |
|
|
197 |
if (!pthread_join (p_thread, NULL))
|
|
198 |
printf ("The last thread exited\n");
|
|
199 |
|
|
200 |
// cleanup memory
|
|
201 |
for (i = 0; i < count; i++) {
|
|
202 |
if (sentences[i] != NULL)
|
|
203 |
free (sentences[i]);
|
|
204 |
if (timings[i] != NULL)
|
|
205 |
free (timings[i]);
|
|
206 |
}
|
|
207 |
|
|
208 |
if (sentences != NULL)
|
|
209 |
free (sentences);
|
|
210 |
|
|
211 |
if (timings != NULL)
|
|
212 |
free (timings);
|
|
213 |
|
|
214 |
for (i = 0; i < 3; i++)
|
|
215 |
if (data[i] != NULL)
|
|
216 |
free (data[i]);
|
|
217 |
|
|
218 |
/*
|
|
219 |
* Cleanup sound
|
|
220 |
*/
|
|
221 |
audio_shutdown ();
|
|
222 |
pthread_exit (NULL);
|
|
223 |
}
|