Saving mix_mute and solo with set files and working around a gtk+
[terminatorX.git] / src / tX_mouse.cc
1 /*
2     terminatorX - realtime audio scratching software
3     Copyright (C) 1999-2003  Alexander K├Ânig
4  
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9  
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14  
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  
19     File: tX_mouse.cc
20  
21     Description: This implements the mouse AND keyboard Input handling in
22                  Grab-Mode.
23 */
24
25 #include <sys/wait.h>
26 #include <X11/Xlib.h>
27 #include <X11/extensions/xf86dga.h>
28
29 #include "tX_mouse.h"
30 #include "tX_mastergui.h"
31 #include "tX_global.h"
32 #include "tX_engine.h"
33 #include "tX_vtt.h"
34
35 #define TX_MOUSE_SPEED_NORMAL 0.05
36 #define TX_MOUSE_SPEED_WARP 250000
37
38 tx_mouse :: tx_mouse() {
39         mask=PointerMotionMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask;
40         xmot=(XMotionEvent *) &xev;
41         xkey=(XKeyEvent *) &xev;
42         xbut=(XButtonEvent *) &xev;
43         
44 #ifdef USE_DGA2
45         xdgamot=(XDGAMotionEvent *) &xev;
46         xdgakey=(XDGAKeyEvent *) &xev;
47         xdgabut=(XDGAButtonEvent *) &xev;
48 #endif  
49         
50         grabbed=0;
51         warp=TX_MOUSE_SPEED_NORMAL;
52 }
53
54
55 int tx_mouse :: grab() {        
56 #ifdef USE_DGA2
57         XDGAMode *mode;
58 #endif  
59
60         if (grabbed) return(0);
61
62         dpy=XOpenDisplay(NULL);
63         if (!dpy)
64         {
65                 fputs("GrabMode Error: couldn't connect to XDisplay.", stderr);
66                 return(ENG_ERR_XOPEN);
67         }
68
69
70 #ifdef USE_DGA2
71         mode=XDGAQueryModes(dpy,DefaultScreen(dpy), &num);
72         
73         printf("Found %i DGA2-Modes:\n", num);
74         
75         for(i=0; i<num; i++)
76         {
77                 printf("%2i: %s\n", i, mode[i].name);
78         }
79         XFree(mode);
80 #endif  
81                                 
82         XSelectInput(dpy, xwindow, mask);       
83
84         XSetInputFocus(dpy, xwindow, None, CurrentTime);
85
86         if (globals.xinput_enable)
87         {
88                 if (set_xinput())
89                 {
90                         XCloseDisplay(dpy);
91                         fputs("GrabMode Error: failed to setup XInput.", stderr);
92                         return(ENG_ERR_XINPUT);
93                 }
94         }
95
96         if (GrabSuccess != XGrabPointer(dpy, xwindow, False, ButtonPressMask|ButtonReleaseMask|PointerMotionMask, GrabModeAsync,GrabModeAsync,None,None,CurrentTime))
97         {
98                 reset_xinput();
99                 XCloseDisplay(dpy);
100                 fputs("GrabMode Error: XGrabPointer failed.", stderr);
101                 return(ENG_ERR_GRABMOUSE);
102         }       
103         
104         if (GrabSuccess != XGrabKeyboard(dpy, xwindow, False, GrabModeAsync,GrabModeAsync,CurrentTime))
105         {
106                 XUngrabPointer (dpy, CurrentTime);
107                 reset_xinput();         
108                 XCloseDisplay(dpy);
109                 fputs("GrabMode Error: XGrabKeyboard failed.", stderr);
110                 return(ENG_ERR_GRABKEY);
111         }
112         
113
114 #ifdef USE_DGA2
115         if (!XDGASetMode(dpy, DefaultScreen(dpy), 1))
116 #else   
117         if (!XF86DGADirectVideo(dpy,DefaultScreen(dpy),XF86DGADirectMouse))
118 #endif
119         {
120                 XUngrabKeyboard(dpy, CurrentTime);                              
121                 XUngrabPointer (dpy, CurrentTime);
122                 reset_xinput();         
123                 XCloseDisplay(dpy);
124                 fputs("GrabMode Error: Failed to enable XF86DGA.", stderr);             
125                 return(ENG_ERR_DGA);
126         }
127
128 #ifdef USE_DGA2
129         XDGASelectInput(dpy, DefaultScreen(dpy), mask);
130 #endif  
131
132         XAutoRepeatOff(dpy);    
133         otime=CurrentTime;
134         
135         grabbed=1;
136         vtt_class::focus_no(0);
137         warp=TX_MOUSE_SPEED_NORMAL;
138         
139         tX_debug("tX_mouse::grab(): this: %08x, dpy: %08x", (int) this, (int) dpy);
140         
141         return(0);
142 }
143
144 void tx_mouse :: ungrab()
145 {
146         if (!grabbed) return;
147
148         tX_debug("tX_mouse::ungrab(): this: %08x, dpy: %08x", (int) this, (int) dpy);
149         
150 #ifdef USE_DGA2 
151         XDGASetMode(dpy, DefaultScreen(dpy), 0);
152 #else
153         XF86DGADirectVideo(dpy,DefaultScreen(dpy),0);
154 #endif  
155
156         XUngrabKeyboard(dpy, CurrentTime);              
157         XUngrabPointer (dpy, CurrentTime);
158         XAutoRepeatOn(dpy);
159         
160         XCloseDisplay(dpy);
161
162         if (globals.xinput_enable)
163         {
164                 reset_xinput(); 
165         }
166
167         vtt_class::unfocus();
168
169         tX_debug("tX_mouse::ungrab(): done");
170         
171         grabbed=0;
172 }
173
174 #ifdef USE_XSETPOINTER
175
176 void tx_mouse :: set_x_pointer(char *devname)
177 {
178         pid_t pid;
179         int status;
180                 
181         pid = fork();
182         
183         if (pid==-1) 
184         { 
185                 /* OOPS. fork failed */
186                 perror("tX: Error: Couldn't fork process!");
187                 return; 
188         }
189         
190         if (pid==0) 
191         {
192                 /* The child execlps xsetpointer */
193                 execlp("xsetpointer", "xsetpointer", devname, NULL);
194                 perror("tX: Error: Failed to execute xpointer!");
195                 exit(0);
196         }
197         
198         /* parent waits for xsetpointer to finish */
199         waitpid(pid,  &status, WUNTRACED);
200 }
201
202 #else
203
204 void tx_mouse :: set_x_pointer(char *devname)
205 {
206         XDeviceInfo *devlist;                   
207         XDevice *device;
208         int listmax, i;
209         
210         devlist=XListInputDevices(dpy, &listmax);
211         
212         for (i=0; i<listmax; i++)
213         {
214                 if(strcmp(devlist[i].name, devname)==0)
215                 {
216                         device=XOpenDevice(dpy, devlist[i].id);
217                         if (device)
218                         {
219                                 if (XChangePointerDevice(dpy, device, 0, 1))
220                                 {
221                                         printf("tX: Error: failed to set pointer device.");                     
222                                 }
223                                 XCloseDevice(dpy, device);
224                         }
225                         else
226                         {
227                                 printf("tX: Error: failed to open XInput device.");
228                         }               
229                 }
230         }
231                 
232         XFreeDeviceList(devlist);               
233 }
234
235 #endif
236
237 int tx_mouse :: set_xinput()
238 {
239         XDeviceInfo *devlist;                   
240         int listmax, i;
241         
242         OrgXPointer=0;
243         
244         if (globals.xinput_enable)
245         {       
246                 devlist=XListInputDevices(dpy, &listmax);
247         
248                 for (i=0; i<listmax; i++)
249                 {
250                         if(devlist[i].use == IsXPointer)
251                         {
252                                 OrgXPointer=devlist[i].id;
253                                 strcpy(OrgXPointerName, devlist[i].name);
254                         }
255                 }
256                 
257                 XFreeDeviceList(devlist);               
258                 
259                 set_x_pointer(globals.xinput_device);
260         }
261         
262         if (OrgXPointer==0) printf("tX: Error failed to detect core pointer.");
263         return(0);
264 }
265
266
267 void tx_mouse :: reset_xinput()
268 {
269         if (globals.xinput_enable)
270         {
271                 if (OrgXPointer) set_x_pointer(OrgXPointerName);
272         }
273 }
274
275
276 #define vtt vtt_class::focused_vtt
277
278 int tx_mouse :: check_event()
279 {
280         if (XCheckWindowEvent(dpy, xwindow, mask, &xev))
281         {
282 #ifdef USE_DGA2
283                 puts("Got an event");
284 #endif          
285                 if (vtt)
286                 switch(xev.type)
287                 {
288                         case MotionNotify:
289                                 vtt->xy_input(((f_prec) xmot->x_root)*warp,((f_prec) xmot->y_root)*warp);
290                                 break;
291                         
292                         case ButtonPress:
293                                 switch(xbut->button)
294                                 {
295                                         case 1: if (vtt->is_playing)
296                                                         vtt->set_scratch(1); 
297                                                 else
298                                                         vtt->sp_trigger.receive_input_value(1);
299                                                 break;
300                                         case 2: vtt->sp_mute.receive_input_value(1); break;
301                                         case 3: vtt_class::focus_next(); break;
302                                 }
303                                 break;
304                         
305                         case ButtonRelease:
306                                 switch (xbut->button)
307                                 {       
308                                         case 1: vtt->set_scratch(0); break;
309                                         case 2: vtt->sp_mute.receive_input_value(0); break;
310                                 }
311                                 break;
312                         case KeyPress:
313 #ifdef USE_DGA2
314                                 puts("Yeah its a key");
315                                 XDGAKeyEventToXKeyEvent(xdgakey, (XKeyEvent *) &xev_copy);
316                                 memcpy(&xev, &xev_copy, sizeof(XEvent));
317 #endif                  
318                         {
319                                 key=XKeycodeToKeysym(dpy, xkey->keycode, 0);
320                                 
321                                 switch(key)
322                                 {
323                                         case XK_space: vtt->set_scratch(1); break;
324                                         case XK_Escape: return(1);
325                                         
326                                         case XK_Return: vtt->sp_trigger.receive_input_value(1); break;
327                                         case XK_BackSpace : vtt->sp_trigger.receive_input_value(0); break;
328                                         
329                                         case XK_Tab: vtt_class::focus_next(); break;
330                                         
331                                         case XK_s: vtt->sp_sync_client.receive_input_value(!vtt->is_sync_client); break;
332                                         
333                                         case XK_m:
334                                         case XK_Control_L:
335                                         case XK_Control_R:                                              
336                                         vtt->sp_mute.receive_input_value(1);
337                                         break;
338                                                 
339                                         case XK_Alt_L:
340                                         case XK_Alt_R:
341                                         vtt->sp_mute.receive_input_value(0);
342                                         break;
343                                         
344                                         case XK_w:
345                                         vtt->sp_mute.receive_input_value(1);
346                                         case XK_f: 
347                                         warp=((float) vtt->samples_in_buffer)/TX_MOUSE_SPEED_WARP;      
348                                         vtt->set_scratch(1);
349                                         break;
350                                                 
351                                         case XK_F1: vtt_class::focus_no(0); break;
352                                         case XK_F2: vtt_class::focus_no(1); break;
353                                         case XK_F3: vtt_class::focus_no(2); break;
354                                         case XK_F4: vtt_class::focus_no(3); break;
355                                         case XK_F5: vtt_class::focus_no(4); break;
356                                         case XK_F6: vtt_class::focus_no(5); break;
357                                         case XK_F7: vtt_class::focus_no(6); break;
358                                         case XK_F8: vtt_class::focus_no(7); break;
359                                         case XK_F9: vtt_class::focus_no(8); break;
360                                         case XK_F10: vtt_class::focus_no(9); break;
361                                         case XK_F11: vtt_class::focus_no(10); break;
362                                         case XK_F12: vtt_class::focus_no(11); break;
363                                 }
364                         } break;
365                         
366                         case KeyRelease:
367                         {
368                                 key=XKeycodeToKeysym (dpy, xkey->keycode, 0);
369                                 
370                                 switch(key)
371                                 {
372                                         case XK_space: vtt->set_scratch(0); break;
373                                         
374                                         case XK_m:
375                                         case XK_Control_L:
376                                         case XK_Control_R:                                              
377                                         vtt->sp_mute.receive_input_value(0);
378                                         break;
379                                                 
380                                         case XK_Alt_L:
381                                         case XK_Alt_R:
382                                         vtt->sp_mute.receive_input_value(1);
383                                         break;
384                                         
385                                         case XK_w:
386                                         vtt->sp_mute.receive_input_value(0);
387                                         case XK_f: warp=TX_MOUSE_SPEED_NORMAL;
388                                         vtt->set_scratch(0);
389                                         break;                                  
390                                 }
391                         }
392                 }
393                 else {  puts("no vtt"); return(1); }
394         }
395         return(0);
396 }