Moving often used links into linkdb
[terminatorX.git] / aseqjoy / aseqjoy.c
1 /**
2  * aseqjoy - Tiny Jostick -> MIDI Controller Tool
3  * Copyright 2003 by Alexander Koenig - alex@lisas.de
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Note: that these sources contain a few lines of Vojtech Pavlik's jstest.c 
20  * example.
21  */
22
23 #include <sys/ioctl.h>
24 #include <sys/time.h>
25 #include <sys/types.h>
26 #include <stdlib.h>
27 #include <fcntl.h>
28 #include <unistd.h>
29 #include <stdio.h>
30 #include <errno.h>
31 #include <string.h>
32 #include <limits.h>
33
34 #include <linux/joystick.h>
35 #include <alsa/asoundlib.h>
36
37 #define NAME_LENGTH 128
38
39 #define TOOL_NAME "aseqjoy"
40
41 #ifdef HAVE_CONFIG_H
42 #include "config.h"
43 #endif
44
45 int joystick_no=0;
46
47 typedef struct {
48         int controller;
49         int last_value;
50 }  val;
51
52 snd_seq_t *seq_handle;
53 snd_seq_event_t ev;
54 int controllers[4];
55 int verbose=0;
56
57 int open_alsa_seq()
58 {
59         char client_name[32];
60         char port_name[48];
61         snd_seq_addr_t src;
62         
63         /* Create the sequencer port. */
64         
65         sprintf(client_name, "Joystick%i", joystick_no);
66         sprintf(port_name , "%s Output", client_name);
67
68         if (snd_seq_open(&seq_handle, "default", SND_SEQ_OPEN_OUTPUT, 0) < 0) {
69                 puts("Error: Failed to access the ALSA sequencer.");
70                 exit(-1);
71         }
72
73         snd_seq_set_client_name(seq_handle, client_name);
74         src.client = snd_seq_client_id(seq_handle);
75         src.port = snd_seq_create_simple_port(seq_handle, "Joystick Output",
76                 SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ, SND_SEQ_PORT_TYPE_APPLICATION);
77
78         /* Init the event structure */
79         
80         snd_seq_ev_clear(&ev);
81         snd_seq_ev_set_source(&ev, src.port);
82         snd_seq_ev_set_subs(&ev);
83         snd_seq_ev_set_direct(&ev);
84
85         return 0;
86 }
87
88 int axes;
89 int joy_fd;
90 int buttons;
91
92 int open_joystick()
93 {
94         char device[256];
95         char name[NAME_LENGTH] = "Unknown";     
96         
97         sprintf(device, "/dev/js%i", joystick_no);
98
99         if ((joy_fd = open(device, O_RDONLY)) < 0) {
100                 fprintf(stderr, "%s: ", TOOL_NAME); perror(device);
101                 sprintf(device, "/dev/input/js%i", joystick_no);
102                 
103                 if ((joy_fd = open(device, O_RDONLY)) < 0) {    
104                         fprintf(stderr, "%s: ", TOOL_NAME); perror(device);
105                         exit(-3);
106                 }
107         }
108
109         ioctl(joy_fd, JSIOCGAXES, &axes);
110         ioctl(joy_fd, JSIOCGBUTTONS, &buttons);
111         ioctl(joy_fd, JSIOCGNAME(NAME_LENGTH), name);
112
113         printf("Using Joystick (%s) through device %s with %i axes and %i buttons.\n", name, device, axes, buttons);
114
115         return 0;
116 }
117
118 void loop()
119 {
120         struct js_event js;
121         int current_channel=1;
122         double val_d;
123         int val_i;
124         int i;
125         val *values;
126         
127         values = calloc(axes, sizeof(val));
128         
129         puts("Axis -> MIDI controller mapping:");
130         
131         for (i=0; i<axes; i++) {
132                 if (i<4) {
133                         values[i].controller=controllers[i];
134                 } else {
135                         values[i].controller=10+i;
136                 }
137                 printf("  %2i -> %3i\n", i, values[i].controller);
138                 values[i].last_value=0;         
139         }
140         
141         
142         
143         puts("Ready, entering loop - use Ctrl-C to exit.");     
144
145         while (1) {
146                 if (read(joy_fd, &js, sizeof(struct js_event)) != sizeof(struct js_event)) {
147                         perror(TOOL_NAME ": error reading from joystick device");
148                         exit (-5);
149                 }
150
151                 switch(js.type & ~JS_EVENT_INIT) {              
152                         case JS_EVENT_BUTTON:
153                                 if (js.value) {                 
154                                         current_channel=js.number+1;
155                                 
156                                         if (verbose) {
157                                                 printf("Switched to MIDI channel %i.\n", current_channel);
158                                         }
159                                 }
160                         break;
161                         
162                         case JS_EVENT_AXIS:
163                                 val_d=(double) js.value;
164                                 val_d+=SHRT_MAX;
165                                 val_d=val_d/((double) USHRT_MAX);
166                                 val_d*=127.0;
167                         
168                                 val_i=(int) val_d;
169                         
170                                 if (values[js.number].last_value!=val_i) {
171                                         values[js.number].last_value!=val_i;
172                                         snd_seq_ev_set_controller(&ev, current_channel, values[js.number].controller, val_i);
173                                         snd_seq_event_output_direct(seq_handle, &ev);
174                                         
175                                         if (verbose) {
176                                                 printf("Sent controller %i with value: %i.\n", values[js.number].controller, val_i);
177                                         }
178                                 }
179                         break;
180                 }
181         }
182 }
183
184 int main (int argc, char **argv)
185 {
186         int i;
187         fprintf(stderr, "%s Version %s - Copyright (C) 2003 by Alexander K├Ânig\n",  TOOL_NAME, VERSION);
188         fprintf(stderr, "%s comes with ABSOLUTELY NO WARRANTY - for details read the license.\n", TOOL_NAME);
189
190         for (i=0; i<4; i++) {
191                 controllers[i]=10+i;
192         }
193         
194         while (1) {
195                 int i=getopt(argc, argv, "vhd:1:2:3:4:");
196                 if (i==-1) break;
197                 
198                 switch (i) {
199                         case '?':
200                         case 'h':
201                                 printf("usage: %s [-d joystick_no] [-v] [-0 ctrl0] [-1 ctrl1] [-2 ctrl2] [-3 ctrl3]\n\n", TOOL_NAME);
202                                 puts("\t-d Select the Joystick to use: 0..3");
203                                 puts("\t-0 Select the Controller for Axis 0 (1-127).");
204                                 puts("\t-1 Select the Controller for Axis 1 (1-127). Etc.");
205                                 puts("\t-v Verbose mode.");
206                                 exit(-2);
207                         break;
208                         
209                         case '0':
210                                 controllers[0]=atoi(optarg);
211                         break;
212
213                         case '1':
214                                 controllers[1]=atoi(optarg);
215                         break;
216
217                         case '2':
218                                 controllers[2]=atoi(optarg);
219                         break;
220
221                         case '3':
222                                 controllers[3]=atoi(optarg);
223                         break;
224                         
225                         case 'v':
226                                 verbose=1;
227                         break;
228                         
229                         case 'd':
230                                 joystick_no=atoi(optarg);
231                         break;
232                 }
233         }
234
235
236         snd_seq_addr_t dest;
237
238         open_joystick();
239         open_alsa_seq();
240         
241         loop();
242
243         return 0;
244 }