1
2 /*
3 * Diverse Bristol midi routines.
4 * Copyright (c) by Nick Copeland <nickycopeland@hotmail.com> 1996,2012
5 *
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program 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
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22 /*#define DEBUG */
23
24 #include <sys/unistd.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <sys/stat.h>
28 #include <sys/un.h>
29 #include <string.h>
30 #include <stdio.h>
31 #include <fcntl.h>
32
33 #include "bristol.h"
34 #include "bristolmidi.h"
35
36 extern bristolMidiMain bmidi;
37 extern int open_remote_socket(char *, int, int, int);
38 extern int bristolMidiFindDev(char *);
39 extern int bristolMidiFindFreeHandle();
40
41 static char bristol_sockname[128];
42
43 int
bristolMidiTCPPassive(char * devname,int conntype,int chan,int msgs,int (* callback)(),void * param,int dev,int handle)44 bristolMidiTCPPassive(char *devname, int conntype, int chan, int msgs,
45 int (*callback)(), void *param, int dev, int handle)
46 {
47 struct sockaddr address;
48
49 //printf("bristolMidiTCPPassive(%s, %i, %i)\n", devname, dev, handle);
50
51 if ((conntype & BRISTOL_CONN_UNIX) ||
52 ((strncmp("unix", devname, 4) == 0)
53 && (strlen(devname) > 4)
54 && (devname[4] == ':')))
55 conntype = 0;
56 else
57 conntype = 1;
58
59 if (chan <= 0)
60 chan = 5028;
61
62 if (conntype)
63 {
64 int count = 0;
65
66 while ((bmidi.dev[dev].fd = open_remote_socket(devname, chan, 8, -1))
67 < 0)
68 {
69 printf("Could not open control socket, count %i\n", count);
70 if (--count <= 0)
71 break;
72 sleep(10);
73 }
74
75 if (bmidi.dev[dev].fd < 0)
76 {
77 printf("No controlling socket available: anticipating MIDI\n");
78 return(-1);
79 } else
80 printf("Opened listening control socket: %i\n", chan);
81 } else {
82 /*
83 * Open a unix domain control socket.
84 */
85 unlink(devname);
86
87 if ((bmidi.dev[dev].fd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0)
88 {
89 printf("Could not get control socket\n");
90 return(BRISTOL_MIDI_DEVICE);
91 }
92
93 /*
94 * Make it non-blocking
95 */
96 if (fcntl(bmidi.dev[dev].fd, F_SETFL, O_NONBLOCK|O_ASYNC) < 0)
97 printf("Could not set non-blocking\n");
98
99 printf("Opened Unix named control socket\n");
100
101 address.sa_family = AF_LOCAL;
102 if ((strlen(devname) > 5) && (devname[4] == ':'))
103 snprintf(bristol_sockname, 64, "/tmp/br.%s", &devname[5]);
104 else
105 sprintf(bristol_sockname, "%s", BRISTOL_SOCKNAME);
106
107 snprintf(&address.sa_data[0], 14, "%s", bristol_sockname);
108
109 if (bind(bmidi.dev[dev].fd, &address, sizeof(struct sockaddr)))
110 printf("Could not bind name: %s\n", bristol_sockname);
111 else
112 printf("Bound name to socket: %s\n", bristol_sockname);
113
114 if (listen(bmidi.dev[dev].fd, 8) < 0)
115 printf("Could not configure listens\n");
116 else
117 printf("Activated listens on socket\n");
118
119 /*
120 * Make it world read/writeable.
121 */
122 chmod(devname, 0777);
123 }
124
125 /*
126 * Configure this device as used, with decoding using the ALSA interface.
127 * We use ALSA basically since it workd.
128 */
129 bmidi.dev[dev].flags = BRISTOL_ACCEPT_SOCKET|BRISTOL_CONN_TCP;
130
131 return(handle);
132 }
133
134 int
acceptConnection(int acceptdev)135 acceptConnection(int acceptdev)
136 {
137 int dev, handle, chandle;
138 socklen_t addrlen;
139 struct sockaddr address;
140 struct linger blinger;
141
142 /*
143 * We have read on the control socket, attempt to accept the connection.
144 */
145 while ((dev = bristolMidiFindDev(NULL)) < 0)
146 {
147 printf("No dev available for accept()\n");
148 /*
149 * We cannot leave the socket dangling, otherwise we get into a closed
150 * loop of accept failing.
151 */
152 close(accept(bmidi.dev[acceptdev].fd, &address, &addrlen));
153 return(-1);
154 }
155
156 addrlen = sizeof(struct sockaddr);
157
158 if ((bmidi.dev[dev].fd =
159 accept(bmidi.dev[acceptdev].fd, &address, &addrlen)) < 0)
160 {
161 //printf("No accepts waiting\n");
162 return(-1);
163 }
164
165 bmidi.dev[dev].state = BRISTOL_MIDI_OK;
166 bmidi.dev[dev].handleCount = 1;
167 bmidi.dev[dev].flags = BRISTOL_CONN_TCP|BRISTOL_CONTROL_SOCKET;
168
169 printf("Accepted connection from %i (%i) onto %i (%i)\n",
170 acceptdev, bmidi.dev[acceptdev].fd, dev, bmidi.dev[dev].fd);
171
172 /*
173 * Make sure we have a handle available
174 */
175 if ((handle = bristolMidiFindFreeHandle()) < 0)
176 return(handle);
177
178 for (chandle = 0; chandle < BRISTOL_MIDI_HANDLES; chandle++)
179 {
180 if ((bmidi.handle[chandle].dev == acceptdev) &&
181 (bmidi.dev[bmidi.handle[chandle].dev].flags
182 & BRISTOL_ACCEPT_SOCKET))
183 break;
184 }
185 if (chandle == BRISTOL_MIDI_HANDLES)
186 {
187 printf("Did not find related accept socket\n");
188 close(bmidi.dev[dev].fd);
189 bmidi.dev[dev].fd = -1;
190 return(-1);
191 }
192
193 bmidi.handle[handle].handle = handle; /* That looks kind of wierd! */
194 bmidi.handle[handle].handle = handle; /* That looks kind of wierd! */
195 bmidi.handle[handle].state = BRISTOL_MIDI_OK;
196 bmidi.handle[handle].channel = bmidi.handle[chandle].channel;
197 bmidi.handle[handle].dev = dev;
198 bmidi.handle[handle].flags = BRISTOL_MIDI_OK;
199 bmidi.handle[handle].messagemask = bmidi.handle[chandle].messagemask;
200 bmidi.handle[handle].callback = bmidi.handle[chandle].callback;
201 bmidi.handle[handle].param = bmidi.handle[chandle].param;
202
203 blinger.l_onoff = 1;
204 blinger.l_linger = 2;
205
206 if (setsockopt(bmidi.dev[dev].fd, SOL_SOCKET, SO_LINGER,
207 &blinger, sizeof(struct linger)) < 0)
208 printf("server linger failed\n");
209
210 //printf("inetServer received: %i %i %i\n", handle, bmidi.handle[handle].dev, bmidi.dev[bmidi.handle[handle].dev].fd);
211
212 return(0);
213 }
214
215