]>
Commit | Line | Data |
---|---|---|
5c281989 MG |
1 | #include <gtk/gtk.h> |
2 | #include <glade/glade.h> | |
3 | #include <libxml/parser.h> | |
4 | #include <libxml/tree.h> | |
5 | #include <string.h> | |
6 | #include <time.h> | |
7 | #include <unistd.h> | |
8 | #include <sys/types.h> | |
9 | #include <signal.h> | |
10 | #include <sys/wait.h> | |
11 | ||
12 | #define MAX_SAMPLES 10 | |
13 | #define MAX_TRIALS 80 | |
14 | ||
15 | #include "rateit_glade.h" | |
16 | ||
17 | typedef struct { | |
18 | char *name; | |
19 | char *path; | |
20 | int id; | |
21 | int pos; | |
22 | int score; | |
23 | char *comment; | |
24 | } Sample; | |
25 | ||
26 | typedef struct Trial { | |
27 | int id; | |
28 | int nbSamples; | |
29 | char *name; | |
30 | int refID; | |
31 | Sample *samp; | |
32 | } Trial; | |
33 | ||
34 | typedef struct { | |
35 | int active; | |
36 | char *basepath; | |
37 | char *participant; | |
38 | int nbSamples; | |
39 | int nbTrials; | |
40 | char *experiment_name; | |
41 | char *savepath; | |
42 | Trial *trials; | |
43 | int curr_trial; | |
44 | int last_played; | |
45 | } Session; | |
46 | ||
47 | Session *session = NULL; | |
48 | ||
49 | GladeXML *main_window; | |
50 | ||
51 | GtkWidget *vscales[MAX_SAMPLES]; | |
52 | GtkWidget *commentButtons[MAX_SAMPLES]; | |
53 | GtkWidget *playButtons[MAX_SAMPLES]; | |
54 | ||
55 | pid_t play_pid=0; | |
56 | ||
57 | void chld_handler(int sig) | |
58 | { | |
59 | pid_t pid; | |
60 | fprintf(stderr, "Got SIGCHLD\n"); | |
61 | while ((pid=waitpid(-1, NULL, WNOHANG))>0) | |
62 | { | |
63 | if (pid==play_pid) | |
64 | play_pid = 0; | |
65 | } | |
66 | play_pid = 0; | |
67 | } | |
68 | ||
69 | int xmlGetInt(xmlNode *node, const char *prop, int def) | |
70 | { | |
71 | xmlChar *tmpStr; | |
72 | int val = def; | |
73 | tmpStr = xmlGetProp(node, (const xmlChar*)prop); | |
74 | if (tmpStr) | |
75 | { | |
76 | val = atoi((char*)tmpStr); | |
77 | xmlFree(tmpStr); | |
78 | } | |
79 | return val; | |
80 | } | |
81 | ||
82 | char *xmlGetString(xmlNode *node, const char *prop, char *def) | |
83 | { | |
84 | xmlChar *tmpStr; | |
85 | char *val = def; | |
86 | tmpStr = xmlGetProp(node, (const xmlChar*)prop); | |
87 | if (tmpStr) | |
88 | { | |
89 | val = strdup((char*)tmpStr); | |
90 | xmlFree(tmpStr); | |
91 | } | |
92 | return val; | |
93 | } | |
94 | ||
95 | void free_session() | |
96 | { | |
97 | /* FIXME: LEAK HERE -- Must delete a few here if we don't want to leak */ | |
98 | } | |
99 | ||
100 | void destroy_session() | |
101 | { | |
102 | /* FIXME: BIG LEAK HERE -- Must delete lots of stuff here if we don't want to leak */ | |
103 | session=NULL; | |
104 | } | |
105 | ||
106 | /*int pos2ID(int pos) | |
107 | { | |
108 | int id, i; | |
109 | Trial *tr = &session->trials[session->curr_trial]; | |
110 | for (i=0;i<session->nbSamples;i++) | |
111 | { | |
112 | if (tr->samp[i].pos == ID) | |
113 | return tr->samp[i].id; | |
114 | } | |
115 | return -1; | |
116 | }*/ | |
117 | ||
118 | void save_session() | |
119 | { | |
120 | int i,j; | |
121 | xmlDocPtr doc = NULL; /* document pointer */ | |
122 | xmlNodePtr root_node = NULL, trial_node = NULL, sample_node = NULL; /* node pointers */ | |
123 | /*xmlDtdPtr dtd = NULL;*/ /* DTD pointer */ | |
124 | char buf[256]; | |
125 | printf ("Saving to %s\n", session->savepath); | |
126 | doc = xmlNewDoc(BAD_CAST "1.0"); | |
127 | root_node = xmlNewNode(NULL, BAD_CAST "MUSHRAEval"); | |
128 | xmlDocSetRootElement(doc, root_node); | |
129 | ||
130 | snprintf(buf, 256, "%d", session->curr_trial); | |
131 | xmlNewProp(root_node, BAD_CAST "currTrial", BAD_CAST buf); | |
132 | xmlNewProp(root_node, BAD_CAST "expName", BAD_CAST session->experiment_name); | |
133 | ||
134 | for (i=0;i<session->nbTrials;i++) | |
135 | { | |
136 | trial_node = xmlNewChild(root_node, NULL, BAD_CAST "SessionTrial", NULL); | |
137 | snprintf(buf, 256, "%d", i); | |
138 | xmlNewProp(trial_node, BAD_CAST "id", BAD_CAST buf); | |
139 | for (j=0;j<session->nbSamples;j++) | |
140 | { | |
141 | sample_node = xmlNewChild(trial_node, NULL, BAD_CAST "PlayedSample", BAD_CAST session->trials[i].samp[j].comment); | |
142 | snprintf(buf, 256, "%d", session->trials[i].samp[j].id); | |
143 | xmlNewProp(sample_node, BAD_CAST "id", BAD_CAST buf); | |
144 | snprintf(buf, 256, "%d", session->trials[i].samp[j].pos); | |
145 | xmlNewProp(sample_node, BAD_CAST "pos", BAD_CAST buf); | |
146 | snprintf(buf, 256, "%d", session->trials[i].samp[j].score); | |
147 | xmlNewProp(sample_node, BAD_CAST "score", BAD_CAST buf); | |
148 | } | |
149 | } | |
150 | xmlSaveFormatFileEnc(session->savepath, doc, "UTF-8", 1); | |
151 | ||
152 | /*free the document */ | |
153 | xmlFreeDoc(doc); | |
154 | } | |
155 | ||
156 | void on_save_as_activate (GtkWidget *widget, gpointer user_data) | |
157 | { | |
158 | GtkWidget *saveasDialog = glade_xml_get_widget (main_window, "SaveAsDialog"); | |
159 | /* | |
160 | if (!session->savepath) | |
161 | { | |
162 | gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (saveasDialog), "."); | |
163 | gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (saveasDialog), "Untitled session"); | |
164 | } | |
165 | else | |
166 | gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (saveasDialog), session->savepath); | |
167 | */ | |
168 | if (gtk_dialog_run (GTK_DIALOG (saveasDialog)) == GTK_RESPONSE_OK) | |
169 | { | |
170 | char *filename; | |
171 | filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (saveasDialog)); | |
172 | session->savepath = strdup(filename); | |
173 | save_session(); | |
174 | g_free (filename); | |
175 | } else { | |
176 | printf ("Cancel open\n"); | |
177 | } | |
178 | gtk_widget_hide(saveasDialog); | |
179 | } | |
180 | ||
181 | void updateGUI() | |
182 | { | |
183 | int i; | |
184 | GtkWidget *w; | |
185 | const char *expStr, *trialStr=""; | |
186 | if (session) | |
187 | { | |
188 | for (i=0;i<session->nbSamples;i++) | |
189 | { | |
190 | gtk_range_set_value (GTK_RANGE(vscales[session->trials[session->curr_trial].samp[i].pos]), | |
191 | session->trials[session->curr_trial].samp[i].score); | |
192 | /*gtk_widget_set_sensitive(vscales[session->trials[session->curr_trial].samp[i].pos],session->active); | |
193 | gtk_widget_set_sensitive(commentButtons[session->trials[session->curr_trial].samp[i].pos],session->active); | |
194 | gtk_widget_set_sensitive(playButtons[session->trials[session->curr_trial].samp[i].pos],session->active);*/ | |
195 | gtk_widget_set_sensitive(vscales[session->trials[session->curr_trial].samp[i].pos],session->last_played==session->trials[session->curr_trial].samp[i].id); | |
196 | gtk_widget_set_sensitive(commentButtons[session->trials[session->curr_trial].samp[i].pos],session->last_played==session->trials[session->curr_trial].samp[i].id); | |
197 | } | |
198 | expStr = session->experiment_name; | |
199 | if (session->active) | |
200 | trialStr=session->trials[session->curr_trial].name; | |
201 | } else { | |
202 | expStr = "No experiment loaded"; | |
203 | } | |
204 | ||
205 | w = glade_xml_get_widget (main_window, "labelExperiment"); | |
206 | gtk_label_set_text(GTK_LABEL(w), expStr); | |
207 | w = glade_xml_get_widget (main_window, "labelTrial"); | |
208 | gtk_label_set_text(GTK_LABEL(w), trialStr); | |
209 | ||
210 | w = glade_xml_get_widget (main_window, "new1"); | |
211 | gtk_widget_set_sensitive(w, session!=NULL); | |
212 | w = glade_xml_get_widget (main_window, "open1"); | |
213 | gtk_widget_set_sensitive(w, session!=NULL); | |
214 | w = glade_xml_get_widget (main_window, "save1"); | |
215 | gtk_widget_set_sensitive(w, session!=NULL && session->active); | |
216 | w = glade_xml_get_widget (main_window, "save_as1"); | |
217 | gtk_widget_set_sensitive(w, session!=NULL && session->active); | |
218 | ||
219 | w = glade_xml_get_widget (main_window, "table1"); | |
220 | gtk_widget_set_sensitive(w, session!=NULL && session->active); | |
221 | w = glade_xml_get_widget (main_window, "buttonNext"); | |
222 | gtk_widget_set_sensitive(w, session!=NULL && session->active); | |
223 | if (session!=NULL && session->active) | |
224 | { | |
225 | if (session->curr_trial == session->nbTrials-1) | |
226 | { | |
227 | w = glade_xml_get_widget (main_window, "labelNext"); | |
228 | gtk_label_set_markup(GTK_LABEL(w), "<b>Finish</b>"); | |
229 | } else { | |
230 | w = glade_xml_get_widget (main_window, "labelNext"); | |
231 | gtk_label_set_markup(GTK_LABEL(w), "<b>Next trial</b>"); | |
232 | } | |
233 | } | |
234 | w = glade_xml_get_widget (main_window, "buttonPrev"); | |
235 | gtk_widget_set_sensitive(w, session!=NULL && session->active && session->curr_trial != 0); | |
236 | w = glade_xml_get_widget (main_window, "buttonPlayRef"); | |
237 | gtk_widget_set_sensitive(w, session!=NULL && session->active); | |
238 | w = glade_xml_get_widget (main_window, "buttonPause"); | |
239 | gtk_widget_set_sensitive(w, session!=NULL && session->active && play_pid); | |
240 | w = glade_xml_get_widget (main_window, "buttonStop"); | |
241 | gtk_widget_set_sensitive(w, session!=NULL && session->active && play_pid); | |
242 | } | |
243 | ||
244 | void on_save_activate (GtkWidget *widget, gpointer user_data) | |
245 | { | |
246 | if (session->savepath) | |
247 | save_session(); | |
248 | else | |
249 | on_save_as_activate(NULL, NULL); | |
250 | } | |
251 | ||
252 | ||
253 | int close_request() | |
254 | { | |
255 | GtkWidget *dialog = glade_xml_get_widget (main_window, "CloseConfirm"); | |
256 | gint response = gtk_dialog_run (GTK_DIALOG (dialog)); | |
257 | gtk_widget_hide(dialog); | |
258 | if (response == GTK_RESPONSE_YES) | |
259 | { | |
260 | on_save_activate(NULL, NULL); | |
261 | return 1; | |
262 | } else if (response == GTK_RESPONSE_NO) | |
263 | { | |
264 | return 1; | |
265 | } else | |
266 | { | |
267 | return 0; | |
268 | } | |
269 | } | |
270 | ||
271 | void new_session() | |
272 | { | |
273 | int i,j; | |
274 | if (!session) | |
275 | return; | |
276 | if (session->active) | |
277 | { | |
278 | /* Close current session */ | |
279 | if (!close_request()) | |
280 | return; | |
281 | free_session(); | |
282 | } | |
283 | session->active = 1; | |
284 | session->curr_trial = 0; | |
285 | for (i=0;i<session->nbTrials;i++) | |
286 | { | |
287 | for (j=0;j<session->nbSamples;j++) | |
288 | { | |
289 | int unique; | |
290 | session->trials[i].samp[j].score = 100; | |
291 | do | |
292 | { | |
293 | unique = 1; | |
294 | int k; | |
295 | /* FIXME: Must randomize properly */ | |
296 | session->trials[i].samp[j].pos = rand()%session->nbSamples; | |
297 | for (k=0;k<j;k++) | |
298 | { | |
299 | if (session->trials[i].samp[k].pos == session->trials[i].samp[j].pos) | |
300 | { | |
301 | unique = 0; | |
302 | break; | |
303 | } | |
304 | } | |
305 | } while (!unique); | |
306 | } | |
307 | } | |
308 | printf ("New session\n"); | |
309 | updateGUI(); | |
310 | } | |
311 | ||
312 | int create_session(xmlDocPtr current_experiment) | |
313 | { | |
314 | xmlNode *root; | |
315 | xmlNode *trial_node; | |
316 | xmlNode *sample_node; | |
317 | xmlChar *tmpStr; | |
318 | int i,j; | |
319 | int corrupted = 0; | |
320 | ||
321 | session = malloc(sizeof(Session)); | |
322 | session->active = 0; | |
323 | root = xmlDocGetRootElement(current_experiment); | |
324 | ||
325 | tmpStr = xmlGetProp(root, (const xmlChar*)"nbSamples"); | |
326 | if (tmpStr) | |
327 | { | |
328 | int i; | |
329 | session->nbSamples = atoi((char*)tmpStr); | |
330 | xmlFree(tmpStr); | |
331 | } else { | |
332 | session->nbSamples = 0; | |
333 | } | |
334 | ||
335 | tmpStr = xmlGetProp(root, (const xmlChar*)"nbTrials"); | |
336 | if (tmpStr) | |
337 | { | |
338 | session->nbTrials = atoi((char*)tmpStr); | |
339 | xmlFree(tmpStr); | |
340 | } else { | |
341 | session->nbTrials = 0; | |
342 | } | |
343 | if (session->nbTrials < 1 || session->nbTrials>= MAX_TRIALS || session->nbSamples<1 || session->nbSamples>=MAX_SAMPLES) | |
344 | { | |
345 | fprintf (stderr, "Attempted to create a session with %d trials and %d samples\n", session->nbTrials, session->nbSamples); | |
346 | free(session); | |
347 | session = NULL; | |
348 | return 0; | |
349 | } | |
350 | for (i=0;i<session->nbSamples;i++) | |
351 | { | |
352 | gtk_widget_show(vscales[i]); | |
353 | gtk_widget_show(commentButtons[i]); | |
354 | gtk_widget_show(playButtons[i]); | |
355 | } | |
356 | for (i=session->nbSamples;i<MAX_SAMPLES;i++) | |
357 | { | |
358 | gtk_widget_hide(vscales[i]); | |
359 | gtk_widget_hide(commentButtons[i]); | |
360 | gtk_widget_hide(playButtons[i]); | |
361 | } | |
362 | ||
363 | session->last_played = -1; | |
364 | session->experiment_name = xmlGetString(root, "name", "unknown experiment"); | |
365 | session->trials = malloc(sizeof(Trial)*session->nbTrials); | |
366 | session->participant = NULL; | |
367 | session->savepath = NULL; | |
368 | session->curr_trial = 0; | |
369 | session->basepath = xmlGetString(root, "samplePath", ""); | |
370 | for (i=0;i<session->nbTrials;i++) | |
371 | { | |
372 | session->trials[i].samp = malloc(sizeof(Session)*session->nbSamples); | |
373 | session->trials[i].id = i; | |
374 | session->trials[i].refID = 0; | |
375 | session->trials[i].name = NULL; | |
376 | session->trials[i].nbSamples = session->nbSamples; | |
377 | for (j=0;j<session->nbSamples;j++) | |
378 | { | |
379 | session->trials[i].samp[j].score = 100; | |
380 | session->trials[i].samp[j].id = j; | |
381 | session->trials[i].samp[j].pos = j; | |
382 | session->trials[i].samp[j].comment = NULL; | |
383 | session->trials[i].samp[j].name = NULL; | |
384 | session->trials[i].samp[j].path = NULL; | |
385 | } | |
386 | } | |
387 | ||
388 | trial_node = root->children; | |
389 | while (trial_node) | |
390 | { | |
391 | if (trial_node->type == XML_ELEMENT_NODE) | |
392 | { | |
393 | int tid=0; | |
394 | tid = xmlGetInt(trial_node, "id", 0); | |
395 | if (tid >= session->nbTrials || tid <0) | |
396 | { | |
397 | fprintf (stderr, "Attempted to load trial %d of %d\n", tid, session->nbTrials); | |
398 | trial_node = trial_node->next; | |
399 | corrupted = 1; | |
400 | continue; | |
401 | } | |
402 | /*fprintf (stderr, "tid = %d of %d\n", tid, session->nbTrials);*/ | |
403 | session->trials[tid].name = xmlGetString(trial_node, "name", NULL); | |
404 | sample_node = trial_node->children; | |
405 | while (sample_node) | |
406 | { | |
407 | if (trial_node->type == XML_ELEMENT_NODE && strcmp((char*)sample_node->name, "Sample")==0) | |
408 | { | |
409 | char *tmpStr; | |
410 | int sid = xmlGetInt(sample_node, "id", 0); | |
411 | if (sid >= session->nbSamples || sid <0) | |
412 | { | |
413 | fprintf (stderr, "Attempted to load sample %d of %d\n", sid, session->nbSamples); | |
414 | sample_node = sample_node->next; | |
415 | corrupted = 1; | |
416 | continue; | |
417 | } | |
418 | session->trials[tid].samp[sid].name = xmlGetString(sample_node, "name", NULL); | |
419 | /*session->trials[tid].samp[sid].path = xmlGetString(sample_node, "file", NULL);*/ | |
420 | tmpStr = (char*)xmlGetProp(sample_node, (xmlChar*)"file"); | |
421 | if (tmpStr) | |
422 | { | |
423 | session->trials[tid].samp[sid].path = malloc(strlen(tmpStr)+strlen(session->basepath)+2); | |
424 | strcpy(session->trials[tid].samp[sid].path, session->basepath); | |
425 | strcat(session->trials[tid].samp[sid].path, "/"); | |
426 | strcat(session->trials[tid].samp[sid].path, tmpStr); | |
427 | } | |
428 | tmpStr = xmlGetString(sample_node, "ref", NULL); | |
429 | if (tmpStr && strcmp(tmpStr, "true")==0) | |
430 | session->trials[tid].refID = sid; | |
431 | free(tmpStr); | |
432 | session->trials[tid].samp[sid].id = sid; | |
433 | } | |
434 | sample_node = sample_node->next; | |
435 | } | |
436 | } | |
437 | trial_node = trial_node->next; | |
438 | } | |
439 | for (i=0;i<session->nbTrials;i++) | |
440 | { | |
441 | for (j=0;j<session->nbSamples;j++) | |
442 | { | |
443 | if (!session->trials[i].samp[j].path) | |
444 | { | |
445 | fprintf (stderr, "Sample has no path\n"); | |
446 | corrupted = 1; | |
447 | break; | |
448 | } | |
449 | } | |
450 | } | |
451 | if (corrupted) | |
452 | { | |
453 | for (i=0;i<session->nbTrials;i++) | |
454 | free(session->trials[i].samp); | |
455 | fprintf (stderr, "Loading of experiment failed (bad file)\n"); | |
456 | free(session); | |
457 | session = NULL; | |
458 | return 0; | |
459 | } | |
460 | return 1; | |
461 | } | |
462 | ||
463 | ||
464 | void loadSession(const char *filename) | |
465 | { | |
466 | xmlDocPtr current_session; | |
467 | xmlNode *session_root; | |
468 | xmlNode *trial_node; | |
469 | xmlChar *sname; | |
470 | if (!session) | |
471 | return; | |
472 | if (session->active) | |
473 | { | |
474 | /* Close current session */ | |
475 | if (!close_request()) | |
476 | return; | |
477 | free_session(); | |
478 | } | |
479 | session->savepath = strdup(filename); | |
480 | current_session = xmlReadFile(filename, NULL, 0); | |
481 | if (current_session == NULL) { | |
482 | fprintf(stderr, "Failed to parse %s\n", filename); | |
483 | return; | |
484 | } else { | |
485 | fprintf(stderr, "Successfully loaded %s\n", filename); | |
486 | } | |
487 | session_root = xmlDocGetRootElement(current_session); | |
488 | sname = xmlGetProp(session_root, (const xmlChar*)"expName"); | |
489 | if (!sname || strcmp((char*)sname, session->experiment_name) != 0) | |
490 | { | |
491 | fprintf(stderr, "Session name doesn't match: %s\n", filename); | |
492 | if (sname) | |
493 | xmlFree(sname); | |
494 | xmlFreeDoc(current_session); | |
495 | return; | |
496 | } | |
497 | xmlFree(sname); | |
498 | session->curr_trial = xmlGetInt(session_root, "currTrial", 0); | |
499 | trial_node = session_root->children; | |
500 | while (trial_node) | |
501 | { | |
502 | if (trial_node->type == XML_ELEMENT_NODE) | |
503 | { | |
504 | int tid; | |
505 | xmlNode *sample_node; | |
506 | tid = xmlGetInt(trial_node, "id", 0); | |
507 | sample_node = trial_node->children; | |
508 | while (sample_node) | |
509 | { | |
510 | if (sample_node->type == XML_ELEMENT_NODE) | |
511 | { | |
512 | int sid; | |
513 | sid = xmlGetInt(sample_node, "id", 0); | |
514 | session->trials[tid].samp[sid].pos = xmlGetInt(sample_node, "pos", 0); | |
515 | session->trials[tid].samp[sid].score = xmlGetInt(sample_node, "score", 0); | |
516 | /*fprintf(stderr, "name: %s at %s\n", session->trials[tid].name, session->trials[tid].samp[sid].path);*/ | |
517 | } | |
518 | sample_node = sample_node->next; | |
519 | } | |
520 | } | |
521 | trial_node = trial_node->next; | |
522 | } | |
523 | xmlFreeDoc(current_session); | |
524 | session->active = 1; | |
525 | updateGUI(); | |
526 | } | |
527 | ||
528 | ||
529 | void loadExperiment(const char *filename) | |
530 | { | |
531 | xmlDocPtr current_experiment; | |
532 | xmlNode *root; | |
533 | if (session) | |
534 | { | |
535 | if (!close_request()) | |
536 | return; | |
537 | /* Close current session */ | |
538 | destroy_session(); | |
539 | } | |
540 | current_experiment = xmlReadFile(filename, NULL, 0); | |
541 | if (current_experiment == NULL) { | |
542 | fprintf(stderr, "Failed to parse %s\n", filename); | |
543 | return; | |
544 | } else { | |
545 | fprintf(stderr, "Successfully loaded %s\n", filename); | |
546 | } | |
547 | root = xmlDocGetRootElement(current_experiment); | |
548 | if (strcmp((char*)root->name, "MUSHRA") != 0) | |
549 | { | |
550 | fprintf(stderr, "Failed validate %s\n", filename); | |
551 | xmlFreeDoc(current_experiment); | |
552 | current_experiment = NULL; | |
553 | return; | |
554 | } | |
555 | create_session(current_experiment); | |
556 | updateGUI(); | |
557 | xmlFreeDoc(current_experiment); | |
558 | } | |
559 | ||
560 | int getIDFromLabel(GtkWidget *label) | |
561 | { | |
562 | const char *name = gtk_label_get_text(GTK_LABEL(label)); | |
563 | if (strcmp(name, "Ref")==0) | |
564 | return -1; | |
565 | else | |
566 | return name[0]-'A'; | |
567 | } | |
568 | ||
569 | ||
570 | Sample *getSampleFromLabel(GtkWidget *label, int update_last_played) | |
571 | { | |
572 | int i; | |
573 | Trial *tr; | |
574 | int ID = getIDFromLabel(label); | |
575 | /*printf ("pos = %d\n", ID);*/ | |
576 | tr = &session->trials[session->curr_trial]; | |
577 | for (i=0;i<session->nbSamples;i++) | |
578 | { | |
579 | if (tr->samp[i].pos == ID) | |
580 | { | |
581 | if (update_last_played) | |
582 | session->last_played = i; | |
583 | return &tr->samp[i]; | |
584 | } | |
585 | } | |
586 | return &tr->samp[tr->refID]; | |
587 | } | |
588 | ||
589 | void on_new_activate (GtkWidget *widget, gpointer user_data) | |
590 | { | |
591 | new_session(); | |
592 | } | |
593 | ||
594 | void on_open_activate (GtkWidget *widget, gpointer user_data) | |
595 | { | |
596 | GtkWidget *openDialog = glade_xml_get_widget (main_window, "OpenDialog"); | |
597 | gtk_widget_show(openDialog); | |
598 | if (gtk_dialog_run (GTK_DIALOG (openDialog)) == GTK_RESPONSE_OK) | |
599 | { | |
600 | char *filename; | |
601 | filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (openDialog)); | |
602 | /*open_file (filename);*/ | |
603 | /*printf ("Opening %s\n", filename);*/ | |
604 | loadSession(filename); | |
605 | g_free (filename); | |
606 | } | |
607 | gtk_widget_hide(openDialog); | |
608 | } | |
609 | ||
610 | void on_open_experiment (GtkWidget *widget, gpointer user_data) | |
611 | { | |
612 | GtkWidget *openDialog = glade_xml_get_widget (main_window, "OpenDialog"); | |
613 | gtk_widget_show(openDialog); | |
614 | if (gtk_dialog_run (GTK_DIALOG (openDialog)) == GTK_RESPONSE_OK) | |
615 | { | |
616 | char *filename; | |
617 | filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (openDialog)); | |
618 | /*printf ("Opening %s\n", filename);*/ | |
619 | loadExperiment(filename); | |
620 | g_free (filename); | |
621 | } | |
622 | gtk_widget_hide(openDialog); | |
623 | } | |
624 | ||
625 | ||
626 | ||
627 | void on_vscale_value_changed (GtkWidget *widget, gpointer user_data) | |
628 | { | |
629 | Sample *s = getSampleFromLabel(widget, 0); | |
630 | s->score = gtk_range_get_value(GTK_RANGE(vscales[s->pos])); | |
631 | /*printf ("%d -> %d\n", s->id, s->score);*/ | |
632 | } | |
633 | ||
634 | void on_buttonPlay_clicked (GtkWidget *widget, gpointer user_data) | |
635 | { | |
636 | Sample *s = getSampleFromLabel(widget, 1); | |
637 | /*snprintf(command, 256, "play \"%s\" >& /dev/null &", s->path);*/ | |
638 | /*printf ("%s\n", command);*/ | |
639 | /*system("killall play >& /dev/null; killall sox >& /dev/null");*/ | |
640 | /*system(command);*/ | |
641 | if (play_pid) | |
642 | { | |
643 | kill(play_pid, SIGINT); | |
644 | waitpid(play_pid, NULL, 0); | |
645 | } | |
646 | if ((play_pid=fork())==0) | |
647 | { | |
648 | close(0); | |
649 | close(1); | |
650 | close(2); | |
651 | execlp("sox", "sox", s->path, "-t", "ossdsp", "/dev/dsp", NULL); | |
652 | perror("execlp"); | |
653 | _exit(0); | |
654 | } | |
655 | updateGUI(); | |
656 | } | |
657 | ||
658 | void on_buttonPause_clicked (GtkWidget *widget, gpointer user_data) | |
659 | { | |
660 | /*system("killall play >& /dev/null; killall sox >& /dev/null");*/ | |
661 | if (play_pid) | |
662 | { | |
663 | kill(play_pid, SIGINT); | |
664 | waitpid(play_pid, NULL, 0); | |
665 | printf ("Pause!\n"); | |
666 | } | |
667 | updateGUI(); | |
668 | } | |
669 | ||
670 | void on_buttonStop_clicked (GtkWidget *widget, gpointer user_data) | |
671 | { | |
672 | /*system("killall play >& /dev/null; killall sox >& /dev/null");*/ | |
673 | if (play_pid) | |
674 | { | |
675 | kill(play_pid, SIGINT); | |
676 | waitpid(play_pid, NULL, 0); | |
677 | printf ("Stop!\n"); | |
678 | } | |
679 | updateGUI(); | |
680 | } | |
681 | ||
682 | void on_buttonNext_clicked (GtkWidget *widget, gpointer user_data) | |
683 | { | |
684 | if (session->curr_trial < session->nbTrials-1) | |
685 | { | |
686 | session->curr_trial++; | |
687 | session->last_played=-1; | |
688 | updateGUI(); | |
689 | on_buttonStop_clicked(NULL, NULL); | |
690 | printf ("Next!\n"); | |
691 | } else { | |
692 | on_save_activate(NULL, NULL); | |
693 | printf ("Completed!\n"); | |
694 | } | |
695 | } | |
696 | ||
697 | void on_buttonPrev_clicked (GtkWidget *widget, gpointer user_data) | |
698 | { | |
699 | if (session->curr_trial > 0) | |
700 | { | |
701 | session->curr_trial--; | |
702 | session->last_played=-1; | |
703 | updateGUI(); | |
704 | printf ("Prev!\n"); | |
705 | } else { | |
706 | printf ("Already at the beginning!\n"); | |
707 | } | |
708 | } | |
709 | ||
710 | void on_buttonComment_clicked (GtkWidget *widget, gpointer user_data) | |
711 | { | |
712 | GtkWidget *commentDialog; | |
713 | GtkTextIter startIter, endIter; | |
714 | GtkTextBuffer *buffer; | |
715 | ||
716 | Sample *s = getSampleFromLabel(widget, 0); | |
717 | ||
718 | commentDialog = glade_xml_get_widget (main_window, "CommentDialog"); | |
719 | GtkWidget *textview = glade_xml_get_widget (main_window, "textviewComments"); | |
720 | buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)); | |
721 | gtk_text_buffer_set_text(buffer, s->comment ? s->comment : "", -1); | |
722 | ||
723 | if (gtk_dialog_run (GTK_DIALOG (commentDialog)) == GTK_RESPONSE_CLOSE) | |
724 | { | |
725 | char *commentStr; | |
726 | gtk_text_buffer_get_start_iter(buffer, &startIter); | |
727 | gtk_text_buffer_get_end_iter(buffer, &endIter); | |
728 | commentStr = gtk_text_buffer_get_text(buffer, &startIter, &endIter, FALSE); | |
729 | free(s->comment); | |
730 | s->comment = strdup(commentStr); | |
731 | g_free(commentStr); | |
732 | } else { | |
733 | printf ("Cancel open\n"); | |
734 | } | |
735 | gtk_widget_hide(commentDialog); | |
736 | } | |
737 | ||
738 | void on_instructions_activate (GtkWidget *widget, gpointer user_data) | |
739 | { | |
740 | GtkWidget *dialog; | |
741 | dialog = glade_xml_get_widget (main_window, "InstructionsDialog"); | |
742 | gtk_dialog_run (GTK_DIALOG (dialog)); | |
743 | gtk_widget_hide(dialog); | |
744 | } | |
745 | ||
746 | void on_hscale_value_changed (GtkWidget *widget, gpointer user_data) | |
747 | { | |
748 | } | |
749 | ||
750 | void quit_request (GtkWidget *widget, gpointer user_data) | |
751 | { | |
752 | if (session && session->active) | |
753 | { | |
754 | if (!close_request()) | |
755 | return; | |
756 | } | |
757 | on_buttonStop_clicked(NULL, NULL); | |
758 | gtk_main_quit(); | |
759 | } | |
760 | ||
761 | ||
762 | void | |
763 | on_about_activate (GtkWidget *widget, gpointer user_data) | |
764 | { | |
765 | GtkWidget *about = glade_xml_get_widget (main_window, "AboutDialog"); | |
766 | gtk_widget_show(about); | |
767 | } | |
768 | ||
769 | int | |
770 | main (int argc, char *argv[]) | |
771 | { | |
772 | int i; | |
773 | srand(time(NULL)); | |
774 | gtk_init (&argc, &argv); | |
775 | LIBXML_TEST_VERSION | |
776 | ||
777 | signal (SIGCHLD, chld_handler); | |
778 | /* load the interface */ | |
779 | /*main_window = glade_xml_new ("rateit.glade", NULL, NULL);*/ | |
780 | main_window = glade_xml_new_from_memory((char*)rateit_glade, 1+strlen((char*)rateit_glade), NULL, NULL); | |
781 | ||
782 | /* connect the signals in the interface */ | |
783 | glade_xml_signal_autoconnect (main_window); | |
784 | ||
785 | /* Extract widgets to a table */ | |
786 | for (i=0;i<MAX_SAMPLES;i++) | |
787 | { | |
788 | char widget_name[100]; | |
789 | snprintf(widget_name, 100, "vscale%c", 'A'+i); | |
790 | vscales[i] = glade_xml_get_widget (main_window, widget_name); | |
791 | snprintf(widget_name, 100, "buttonComment%c", 'A'+i); | |
792 | commentButtons[i] = glade_xml_get_widget (main_window, widget_name); | |
793 | snprintf(widget_name, 100, "buttonPlay%c", 'A'+i); | |
794 | playButtons[i] = glade_xml_get_widget (main_window, widget_name); | |
795 | } | |
796 | ||
797 | if (argc>=2) | |
798 | loadExperiment(argv[1]); | |
799 | if (argc>=3) | |
800 | loadSession(argv[2]); | |
801 | updateGUI(); | |
802 | /* start the event loop */ | |
803 | gtk_main (); | |
804 | xmlCleanupParser(); | |
805 | return 0; | |
806 | } |