add so I can tag.
[platform/core/uifw/at-spi2-atk.git] / test / simple-at.c
1 /*
2  * AT-SPI - Assistive Technology Service Provider Interface
3  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4  *
5  * Copyright 2001 Sun Microsystems Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include <stdlib.h>
24 #include <sys/socket.h>
25 #include <sys/un.h>
26 #include "spi.h"
27
28 static void report_focus_event (void *fp);
29 static void report_button_press (void *fp);
30 static boolean report_command_key_event (void *fp);
31 static boolean report_ordinary_key_event (void *fp);
32 static void check_property_change (void *fp);
33 static void get_environment_vars (void);
34
35 static int _festival_init ();
36 static void _festival_say (const char *text, const char *voice, boolean shutup);
37 static void _festival_write (const char *buff, int fd);
38
39 static boolean use_magnifier = FALSE;
40 static boolean use_festival = FALSE;
41 static boolean festival_chatty = FALSE;
42
43 static AccessibleEventListener *focus_listener;
44 static AccessibleEventListener *property_listener;
45 static AccessibleEventListener *button_listener;
46 static AccessibleKeystrokeListener *command_key_listener;
47 static AccessibleKeystrokeListener *ordinary_key_listener;
48
49 int
50 main(int argc, char **argv)
51 {
52   int i, j;
53   int n_desktops;
54   int n_apps;
55   Accessible *desktop;
56   Accessible *application;
57
58   if ((argc > 1) && (!strncmp(argv[1],"-h",2)))
59   {
60     printf ("Usage: simple-at\n");
61     printf ("\tEnvironment variables used:\n\t\tFESTIVAL\n\t\tMAGNIFIER\n\t\tFESTIVAL_CHATTY\n");
62     exit(0);
63   }
64
65   SPI_init();
66
67   focus_listener = createAccessibleEventListener (report_focus_event);
68   property_listener = createAccessibleEventListener (check_property_change); 
69   button_listener = createAccessibleEventListener (report_button_press);
70   registerGlobalEventListener (focus_listener, "focus:");
71   registerGlobalEventListener (property_listener, "object:property-change:accessible-selection"); 
72   registerGlobalEventListener (button_listener, "Gtk:GtkWidget:button-press-event");
73   n_desktops = getDesktopCount ();
74
75   for (i=0; i<n_desktops; ++i)
76     {
77       desktop = getDesktop (i);
78       fprintf (stderr, "desktop %d name: %s\n", i, Accessible_getName (desktop));
79       n_apps = Accessible_getChildCount (desktop);
80       for (j=0; j<n_apps; ++j)
81         {
82           application = Accessible_getChildAtIndex (desktop, j);
83           fprintf (stderr, "app %d name: %s\n", j, Accessible_getName (application));
84           Accessible_unref (application);
85         }
86     }
87
88   /* prepare the keyboard snoopers */
89   command_key_listener = createAccessibleKeystrokeListener(report_command_key_event);
90   ordinary_key_listener = createAccessibleKeystrokeListener(report_ordinary_key_event);
91   
92   /* will listen only to Alt-key combinations, and only to KeyPress events */
93   registerAccessibleKeystrokeListener(command_key_listener,
94                                       (AccessibleKeySet *) SPI_KEYSET_ALL_KEYS,
95                                       SPI_KEYMASK_ALT,
96                                       (unsigned long) ( KeyPress ),
97                                       SPI_KEYLISTENER_ALL_WINDOWS);
98   
99   /* will listen only to unshifted key events, both press and release */
100   registerAccessibleKeystrokeListener(ordinary_key_listener,
101                                       (AccessibleKeySet *) SPI_KEYSET_ALL_KEYS,
102                                       SPI_KEYMASK_UNMODIFIED,
103                                       (unsigned long) ( KeyPress | KeyRelease),
104                                       SPI_KEYLISTENER_NOSYNC);
105                                       
106   /* will listen only to shifted key events, both press and release */
107   registerAccessibleKeystrokeListener(ordinary_key_listener,
108                                       (AccessibleKeySet *) SPI_KEYSET_ALL_KEYS,
109                                       SPI_KEYMASK_SHIFT,
110                                       (unsigned long) ( KeyPress | KeyRelease),
111                                       SPI_KEYLISTENER_NOSYNC);
112
113   get_environment_vars();
114
115   SPI_event_main(TRUE);
116 }
117
118 static void
119 get_environment_vars()
120 {
121   if (getenv ("FESTIVAL"))
122   {
123     use_festival = TRUE;
124     if (getenv ("FESTIVAL_CHATTY"))
125     {
126       festival_chatty = TRUE;
127     }
128   }
129   if (getenv("MAGNIFIER"))
130   {
131     use_magnifier = TRUE;
132   }  
133 }
134
135 void
136 report_focussed_accessible (Accessible *obj, boolean shutup_previous_speech)
137 {
138   if (use_festival)
139     {
140     if (festival_chatty)            
141       {
142         _festival_say (Accessible_getRole (obj), "voice_don_diphone", shutup_previous_speech);
143       }
144       fprintf (stderr, "getting Name\n");
145       _festival_say (Accessible_getName (obj), "voice_kal_diphone",
146                      shutup_previous_speech || festival_chatty);
147     }
148   
149   if (Accessible_isComponent (obj))
150     {
151       long x, y, width, height;
152       AccessibleComponent *component = Accessible_getComponent (obj);
153       AccessibleComponent_getExtents (component, &x, &y, &width, &height,
154                                       SPI_COORD_TYPE_SCREEN);
155       fprintf (stderr, "Bounding box: (%ld, %ld) ; (%ld, %ld)\n",
156                x, y, x+width, y+height);
157       if (use_magnifier) {
158               magnifier_set_roi ((short) 0, x, y, width, height);
159       }
160     }
161   /* if this is a text object, speak the first sentence. */
162
163   if (Accessible_isText(obj))
164
165   {
166      AccessibleText *text_interface;
167      long start_offset, end_offset;
168      char *first_sentence = "empty";
169      text_interface = Accessible_getText (obj);
170      fprintf (stderr, "isText...%p %p\n", text_interface, (void *)*text_interface);
171      first_sentence = AccessibleText_getTextAtOffset (
172                text_interface, (long) 0, SPI_TEXT_BOUNDARY_SENTENCE_START, &start_offset, &end_offset);
173      if (first_sentence) _festival_say(first_sentence, "voice_don_diphone", FALSE);
174      fprintf (stderr, "done reporting on focussed object\n");
175   }
176 }
177
178 void
179 report_focus_event (void *p)
180 {
181   AccessibleEvent *ev = (AccessibleEvent *) p;
182   fprintf (stderr, "%s event from %s\n", ev->type,
183            Accessible_getName (&ev->source));
184   report_focussed_accessible (&ev->source, TRUE);
185 }
186
187 void
188 report_button_press (void *p)
189 {
190   AccessibleEvent *ev = (AccessibleEvent *) p;
191   fprintf (stderr, "%s event from %s\n", ev->type,
192            Accessible_getName (&ev->source));
193   fprintf (stderr, "Object description %s\n",
194            Accessible_getDescription (&ev->source));
195 }
196
197
198 void
199 check_property_change (void *p)
200 {
201   AccessibleEvent *ev = (AccessibleEvent *) p;
202   AccessibleSelection *selection = Accessible_getSelection (&ev->source);
203   int n_selections;
204   int i;
205   if (selection)
206   {
207     n_selections = (int) AccessibleSelection_getNSelectedChildren (selection);
208     fprintf (stderr, "(Property) %s event from %s, %d selected children\n", ev->type,
209            Accessible_getName (&ev->source), n_selections);
210   /* for now, speak entire selection set */
211     for (i=0; i<n_selections; ++i)
212     {
213           Accessible *obj = AccessibleSelection_getSelectedChild (selection, (long) i);
214           g_return_if_fail (obj);
215           fprintf (stderr, "Child %d, name=%s\n", i, Accessible_getName (obj));
216           report_focussed_accessible (obj, i==0);
217     }
218   }
219 }
220
221 static void
222 simple_at_exit()
223 {
224   deregisterGlobalEventListenerAll (focus_listener);
225   deregisterGlobalEventListenerAll (property_listener);
226   deregisterGlobalEventListenerAll (button_listener);
227   deregisterAccessibleKeystrokeListener (command_key_listener, SPI_KEYMASK_ALT );
228   deregisterAccessibleKeystrokeListener (ordinary_key_listener, SPI_KEYMASK_UNMODIFIED );
229   deregisterAccessibleKeystrokeListener (ordinary_key_listener, SPI_KEYMASK_SHIFT );
230   
231   SPI_exit ();
232 }
233
234 static boolean
235 is_command_key (AccessibleKeyStroke *key)
236 {
237   switch (key->keyID)
238     {
239     case 'Q':
240     case 'q':
241             simple_at_exit(); 
242             return TRUE; /* not reached */
243     case 'M':
244     case 'm':
245             use_magnifier = ! use_magnifier;
246             return TRUE;
247     case 'F':
248     case 'f':
249             use_festival = ! use_festival;
250             return TRUE;
251     default:
252             return FALSE;
253     }
254 }
255
256 static boolean
257 report_command_key_event (void *p)
258 {
259   AccessibleKeyStroke *key = (AccessibleKeyStroke *) p;
260   fprintf (stderr, "Command KeyEvent %s%c (keycode %d)\n",
261           (key->modifiers & SPI_KEYMASK_ALT)?"Alt-":"",
262           ((key->modifiers & SPI_KEYMASK_SHIFT)^(key->modifiers & SPI_KEYMASK_SHIFTLOCK))?
263           (char) toupper((int) key->keyID) : (char) tolower((int) key->keyID),
264           (int) key->keycode);
265   return is_command_key (key);
266 }
267
268
269 static boolean
270 report_ordinary_key_event (void *p)
271 {
272   AccessibleKeyStroke *key = (AccessibleKeyStroke *) p;
273   fprintf (stderr, "Received key event:\tsym %ld\n\tmods %x\n\tcode %d\n\ttime %ld\n",
274            (long) key->keyID,
275            (unsigned int) key->modifiers,
276            (int) key->keycode,
277            (long int) key->timestamp);
278 }
279
280 static int _festival_init ()
281 {
282   int fd;
283   struct sockaddr_in name;
284   int tries = 2;
285
286   name.sin_family = AF_INET;
287   name.sin_port = htons (1314);
288   name.sin_addr.s_addr = htonl(INADDR_ANY);
289   fd = socket (PF_INET, SOCK_STREAM, 0);
290
291   while (connect(fd, (struct sockaddr *) &name, sizeof (name)) < 0) {
292     if (!tries--) {
293       perror ("connect");
294       return -1;
295     }
296   }
297
298   _festival_write ("(audio_mode'async)\n", fd);
299   _festival_write ("(Parameter.set 'Duration_Model 'Tree_ZScore)\n", fd);
300   _festival_write ("(Parameter.set 'Duration_Stretch 0.75)\n", fd);
301   return fd;
302 }
303
304 static void _festival_say (const char *text, const char *voice, boolean shutup)
305 {
306   static int fd = 0;
307   gchar *quoted;
308   gchar *p;
309   gchar prefix[50];
310   static gchar voice_spec[32];
311   
312   if (!fd)
313     {
314       fd = _festival_init ();
315     }
316
317   fprintf (stderr, "saying text: %s\n", text);
318   
319   quoted = g_malloc(64+strlen(text)*2);
320
321   sprintf (prefix, "(SayText \"");
322
323   strncpy(quoted, prefix, 10);
324   p = quoted+strlen(prefix);
325   while (*text) {
326     if ( *text == '\\' || *text == '"' )
327       *p = '\\';
328     *p++ = *text++;
329   }
330   *p++ = '"';
331   *p++ = ')';
332   *p++ = '\n';
333   *p = 0;
334
335   if (shutup) _festival_write ("(audio_mode'shutup)\n", fd);
336   if (voice && (strncmp (voice, (char *) (voice_spec+1), strlen(voice))))
337     {
338       snprintf (voice_spec, 32, "(%s)\n", voice); 
339       _festival_write (voice_spec, fd);
340       _festival_write ("(Parameter.set 'Duration_Model 'Tree_ZScore)\n", fd);
341       _festival_write ("(Parameter.set 'Duration_Stretch 0.75)\n", fd);
342     }
343
344   _festival_write (quoted, fd);
345
346   g_free(quoted);
347 }
348
349 static void _festival_write (const gchar *command_string, int fd)
350 {
351   fprintf(stderr, command_string);
352   if (fd < 0) {
353     perror("socket");
354     return;
355   }
356   write(fd, command_string, strlen(command_string));
357 }
358