Codebase list aeolus / upstream/0.8.2
Imported Upstream version 0.8.2 Alessio Treglia 14 years ago
25 changed file(s) with 1066 addition(s) and 64 deletion(s). Raw diff Collapse all Expand all
00 Fons Adriaensen <fons@kokkinizita.net>
1 Hans Fugal <hans@fugal.net>
0 AEOLUS 0.8.0 BUILD INSTRUCTIONS
1 ________________________________
0 AEOLUS 0.8.2 BUILD INSTRUCTIONS (LINUX)
1 _______________________________________
22
33
44 To build this version, you need to have the shared
55 libraries
66
77 * libclalsadrv.so.1.2.2
8 * libclthreads.so.2.2.1
9 * libclxclient.so.3.3.2
8 * libclthreads.so.2.4.0
9 * libclxclient.so.3.6.0
1010
1111 and the corresponding header files installed.
1212 They should be available from the same place where
1818 * aeolus_x11.so GUI plugin,
1919 * aeolus_txt.so text mode user interface.
2020
21 In this version the latter is just an empty stub.
21 In this version the latter is functional but not complete.
2222
2323 The default Makefile will install the Aeolus binary
2424 in /usr/local/bin, and the user interface plugins in
4242
4343 See also the README file for run-time configuration.
4444
45
46 AEOLUS 0.8.2 BUILD INSTRUCTIONS (OSX)
47 _____________________________________
48
49
50 See the file BUILD-osx
51
52
4553 --
4654 FA
0 AEOLUS 0.8.2 BUILD INSTRUCTIONS (OSX)
1 _____________________________________
2
3
4 As of version 0.8.2 Aeolus now works on OS X. At the time of this writing
5 (March 2008) you need a newer JACK[1] than that provided by Jack OSX[2]
6 version 0.76. This means you won't be able to use JackPilot to manage
7 connections, but you can use QjackCtl[3] instead.
8
9 Aeolus registers itself as a CoreMIDI virtual destination. This means programs
10 like MidiKeys[4] will allow you to select Aeolus as a destination. A USB MIDI
11 driver will probably not automatically select Aeolus as a destination and
12 provide you no means for doing so yourself. For this you need to either use
13 MidiKeys with MIDI thru, or a patch bay such as MIDI Patchbay[5]. In my
14 experience MidiKeys is easier and more reliable, at least in the face of my
15 apparently-buggy USB MIDI driver.
16
17 1. http://jackaudio.org/
18 2. http://jackosx.com/
19 3. http://qjackctl.sourceforge.net/
20 4. http://www.manyetas.com/creed/midikeys.html
21 5. http://pete.yandell.com/software/
22
23 Building Aeolus
24 ---------------
25 Assuming you have all the dependencies worked out (see below), you just need to
26 make and make install using the proper makefile.
27
28 ln -s Makefile-osx makefile
29 make
30 sudo make install
31
32 Building clthreads and clxclient works the same way.
33
34
35 Building JACK
36 -------------
37 Version 0.109.2 as of this writing.
38
39 ./configure --with-default-tmpdir=/tmp
40 make
41 sudo make install
42
43 Building QjackCtl
44 -----------------
45 First, install Qt/Mac[6] (version 4.3.4 at the time of this writing). Then, in
46 the qjackctl-0.3.2 subdirectory,
47
48 ./configure
49 make
50
51 This will produce an error like the following:
52
53 make[1]: qjackctl.mak: No such file or directory
54 make[1]: *** No rule to make target `qjackctl.mak'. Stop.
55 make: *** [qjackctl] Error 2
56
57 This is because Qt/Mac's qmake generates an Xcode project, not a makefile. Now
58 open that project in Xcode:
59
60 open qjackctl.mak.xcodeproj
61
62 Build it and stash the resulting qjackctl.app somewhere convenient.
63
64
65 6. http://trolltech.com/developer/downloads/qt/mac
66
67 Author
68 ------
69 Please contact me if these instructions are incomplete or erroneous.
70 Hans Fugal <hans@fugal.net>
1717 PREFIX = /usr/local
1818 SUFFIX := $(shell uname -m | sed -e 's/^unknown/$//' -e 's/^i.86/$//' -e 's/^x86_64/$/64/')
1919 LIBDIR = lib$(SUFFIX)
20 VERSION = 0.8.1
20 VERSION = 0.8.2
2121 DISTDIR = aeolus-$(VERSION)
2222 CPPFLAGS += -O3 -Wall -MMD -MP -DVERSION=\"$(VERSION)\" -DLIBDIR=\"$(PREFIX)/$(LIBDIR)\"
2323 #CPPFLAGS += -march=pentium4
0 # Copyright (C) 2003-2008 Fons Adriaensen <fons@kokkinizita.net>
1 # Copyright (C) 2008 Hans Fugal <hans@fugal.net>
2 #
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
7 #
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
12
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software
15 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16
17
18 PREFIX = /usr/local
19 SUFFIX := $(shell uname -m | sed -e 's/^unknown/$//' -e 's/^i.86/$//' -e 's/^x86_64/$/64/')
20 LIBDIR = lib$(SUFFIX)
21 VERSION = 0.8.2
22 DISTDIR = aeolus-$(VERSION)
23 CPPFLAGS += -O3 -Wall -MMD -MP -DVERSION=\"$(VERSION)\" -DLIBDIR=\"$(PREFIX)/$(LIBDIR)\"
24 #CPPFLAGS += -march=pentium4
25
26 all: aeolus aeolus_x11.so aeolus_txt.so
27
28
29 AEOLUS_O = main.o audio.o model.o slave.o imidi-osx.o addsynth.o scales.o \
30 reverb.o asection.o division.o rankwave.o rngen.o exp2ap.o lfqueue.o
31 aeolus: LDLIBS += -lclthreads -lpthread -ljack -lpthread -framework Cocoa -framework CoreMIDI
32 aeolus: LDFLAGS += -L$(PREFIX)/$(LIBDIR)
33 aeolus: $(AEOLUS_O)
34 g++ $(LDFLAGS) -o $@ $(AEOLUS_O) $(LDLIBS)
35
36 addsynth.o: CPPFLAGS += -dynamic -D_REENTRANT
37 $(AEOLUS_O):
38 -include $(AEOLUS_O:%.o=%.d)
39
40
41 XIFACE_O = styles.o mainwin.o midiwin.o audiowin.o instrwin.o editwin.o midimatrix.o \
42 multislider.o functionwin.o xiface.o addsynth.o
43 aeolus_x11.so: CPPFLAGS += -dynamic -D_REENTRANT -I/usr/X11R6/include `freetype-config --cflags`
44 aeolus_x11.so: LDLIBS += -lclthreads -lclxclient -lXft -lX11
45 aeolus_x11.so: LDFLAGS += -dynamiclib -L$(PREFIX)/$(LIBDIR) -L/usr/X11R6/$(LIBDIR)
46 aeolus_x11.so: $(XIFACE_O) $(LIBCLX)
47 g++ $(LDFLAGS) -o $@ $(XIFACE_O) $(LDLIBS)
48
49 $(XIFACE_O):
50 -include $(XIFACE_O:%.o=%.d)
51
52
53
54 TIFACE_O = tiface.o
55 aeolus_txt.so: CPPFLAGS += -dynamic -D_REENTRANT
56 aeolus_txt.so: LDLIBS += -lclthreads -lreadline
57 aeolus_txt.so: LDFLAGS += -dynamiclib -L$(PREFIX)/$(LIBDIR)
58 aeolus_txt.so: $(TIFACE_O)
59 g++ $(LDFLAGS) -o $@ $(TIFACE_O) $(LDLIBS)
60
61 $(TIFACE_O):
62 -include $(TIFACE_O:%.o=%.d)
63
64
65
66 install: aeolus aeolus_x11.so aeolus_txt.so
67 /usr/bin/install -d $(PREFIX)/$(LIBDIR)
68 /usr/bin/install -m 755 aeolus $(PREFIX)/bin
69 /usr/bin/install -m 755 aeolus_x11.so $(PREFIX)/$(LIBDIR)
70 /usr/bin/install -m 755 aeolus_txt.so $(PREFIX)/$(LIBDIR)
71
72 clean:
73 /bin/rm -f *~ *.o *.d *.a *.so aeolus
74
75
76 tarball:
77 cd ..; \
78 /bin/rm -f -r $(DISTDIR)*; \
79 svn export aeolus $(DISTDIR); \
80 tar cvf $(DISTDIR).tar $(DISTDIR); \
81 bzip2 $(DISTDIR).tar; \
82 /bin/rm -f -r $(DISTDIR);
1717
1818
1919 #include <string.h>
20 #include <endian.h>
20 #include "global.h"
2121 #include "addsynth.h"
2222
2323
117117 fwrite (d, N_NOTE, sizeof (float), F);
118118
119119 #else
120 #error Byte order is undefined !
120 #error Byte order is not supported !
121121 #endif
122122 #else
123123 #error Byte order is undefined !
145145 for (i = 0; i < N_NOTE; i++) swap4 ((char *)(_v + i), d + i * sizeof (float));
146146
147147 #else
148 #error Byte order is undefined !
148 #error Byte order is not supported !
149149 #endif
150150 #else
151151 #error Byte order is undefined !
3030 _qcomm (qcomm),
3131 _qmidi (0),
3232 _running (false),
33 #ifdef __linux__
3334 _alsa_handle (0),
35 #endif
3436 _jack_handle (0),
3537 _abspri (0),
3638 _relpri (0),
4850 {
4951 int i;
5052
53 #ifdef __linux__
5154 if (_alsa_handle) close_alsa ();
55 #endif
5256 if (_jack_handle) close_jack ();
5357 for (i = 0; i < _nasect; i++) delete _asectp [i];
5458 for (i = 0; i < _ndivis; i++) delete _divisp [i];
104108 }
105109
106110
111 #ifdef __linux__
107112 void Audio::init_alsa (const char *device, int fsamp, int fsize, int nfrag)
108113 {
109114 _alsa_handle = new Alsa_driver (device, fsamp, fsize, nfrag, true, false, false);
129134 }
130135 }
131136 }
132
133
137 #endif
138
139
140 #ifdef __linux__
134141 void Audio::close_alsa ()
135142 {
136 _running = false;
143 _running = false;
137144 fprintf (stderr, "Closing ALSA.\n");
138145 get_event (1 << EV_EXIT);
139146 for (int i = 0; i < _nplay; i++) delete[] _outbuf [i];
140147 delete _alsa_handle;
141148 }
149 #endif
142150
143151
144152 void Audio::thr_main (void)
145153 {
154 #ifdef __linux__
146155 unsigned long k;
147156
148157 _alsa_handle->pcm_start ();
167176
168177 _alsa_handle->pcm_stop ();
169178 put_event (EV_EXIT);
179 #endif
170180 }
171181
172182
436446 union { uint32_t i; float f; } u;
437447
438448 // Execute commands from the model thread (qcomm),
439 // or from the midi thread (qmidi).
449 // or from the midi thread (qnote).
440450
441451 n = Q->read_avail ();
442452 while (n > 0)
2222
2323 #include <stdlib.h>
2424 #include <clthreads.h>
25 #ifdef __linux__
2526 #include <clalsadrv.h>
27 #endif
2628 #include <jack/jack.h>
2729 #include "asection.h"
2830 #include "division.h"
3739
3840 Audio (const char *jname, Lfq_u32 *qnote, Lfq_u32 *qcomm);
3941 virtual ~Audio (void);
42 #ifdef __linux__
4043 void init_alsa (const char *device, int fsamp, int fsize, int nfrag);
44 #endif
4145 void init_jack (bool bform, Lfq_u8 *qmidi);
4246 void start (void);
4347
5256 enum { VOLUME, REVSIZE, REVTIME, STPOSIT };
5357
5458 void init_audio (void);
59 #ifdef __linux__
5560 void close_alsa (void);
61 #endif
5662 void close_jack (void);
5763 virtual void thr_main (void);
5864 void jack_shutdown (void);
113119 Lfq_u32 *_qcomm;
114120 Lfq_u8 *_qmidi;
115121 volatile bool _running;
122 #ifdef __linux__
116123 Alsa_driver *_alsa_handle;
124 #endif
117125 jack_client_t *_jack_handle;
118126 jack_port_t *_jack_opport [8];
119127 jack_port_t *_jack_midipt;
2020 #define __CALLBACKS_H
2121
2222
23 #include "clxclient.h"
23 #include <clxclient.h>
2424
2525
2626 enum
2020 #define __EDITWIN_H
2121
2222
23 #include "clxclient.h"
23 #include <clxclient.h>
2424 #include "multislider.h"
2525 #include "functionwin.h"
2626 #include "addsynth.h"
2020 #define __FUNCTIONWIN_H
2121
2222
23 #include "clxclient.h"
23 #include <clxclient.h>
2424
2525
2626 class Functionwin : public X_window
00 /*
11 Copyright (C) 2003-2008 Fons Adriaensen <fons@kokkinizita.net>
2 Copyright (C) 2008 Hans Fugal <hans@fugal.net> (OSX version)
23
34 This program is free software; you can redistribute it and/or modify
45 it under the terms of the GNU General Public License as published by
2021 #define __GLOBAL_H
2122
2223
24 #ifdef __APPLE__
25 #include <machine/endian.h>
26 #define __LITTLE_ENDIAN __DARWIN_LITTLE_ENDIAN
27 #define __BIG_ENDIAN __DARWIN_BIG_ENDIAN
28 #define __PDP_ENDIAN __DARWIN_PDP_ENDIAN
29 #define __BYTE_ORDER __DARWIN_BYTE_ORDER
30 #else
2331 #include <endian.h>
24 #include "lfqueue.h"
25
32 #endif
2633
2734 #ifdef __BYTE_ORDER
2835 #if (__BYTE_ORDER == __LITTLE_ENDIAN)
3643 #define RD2(p) ((p)[1] + ((p)[0] << 8));
3744 #define RD4(p) ((p)[3] + ((p)[2] << 8) + ((p)[1] << 16) + ((p)[0] << 24));
3845 #else
39 #error Byte order is undefined !
46 #error Byte order is not supported !
4047 #endif
4148 #else
4249 #error Byte order is undefined !
4350 #endif
51
52 #include "lfqueue.h"
4453
4554
4655 enum // GLOBAL LIMITS
0 /*
1 Copyright (C) 2008 Hans Fugal <hans@fugal.net>
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16 */
17
18 /* OS X CoreMIDI version of Imidi. Might be cleaner to do some kind of
19 * inheritance, but for now this will do. Makefile.osx doesn't build imidi.cc
20 * but rather this file, and vice versa for the normal Linux Makefile.
21 */
22
23
24 #include "imidi.h"
25
26
27 Imidi::Imidi (Lfq_u32 *qnote, Lfq_u8 *qmidi, uint16_t *midimap, const char *appname) :
28 A_thread ("Imidi"),
29 _qnote (qnote),
30 _qmidi (qmidi),
31 _midimap (midimap),
32 _appname (appname)
33 {
34 }
35
36
37 Imidi::~Imidi (void)
38 {
39 }
40
41
42 void Imidi::terminate (void)
43 {
44 put_event (EV_EXIT, 1);
45 }
46
47
48 void Imidi::thr_main (void)
49 {
50 open_midi ();
51 get_event (1 << EV_EXIT);
52 close_midi ();
53 send_event (EV_EXIT, 1);
54 }
55
56
57 static void coremidi_proc_static (const MIDIPacketList *pktlist, void *refCon, void *connRefCon)
58 {
59 Imidi *imidi = (Imidi*)refCon;
60 imidi->coremidi_proc (pktlist, 0, connRefCon);
61 }
62
63
64 void Imidi::open_midi (void)
65 {
66 // If in the future dest is needed in close_midi (or elsewhere) this could
67 // be made an instance variable.
68 MIDIEndpointRef dest;
69
70 _handle = NULL;
71 CFStringRef name = CFStringCreateWithCString(0, _appname, kCFStringEncodingUTF8);
72 MIDIClientCreate(name, NULL, NULL, &_handle);
73 MIDIDestinationCreate(_handle, name, coremidi_proc_static, this, &dest);
74
75 #if 0
76 // is this stuff needed? I'm guessing no, but we'll see when I plugin the
77 // USB keyboard
78 MIDIPortRef inPort = NULL;
79 MIDIInputPortCreate(_handle, CFSTR("In"), coremidi_proc_static, this, &inPort);
80
81 // open connections from all sources (TODO is this what we want?)
82 int n = MIDIGetNumberOfSources();
83 for (int i=0; i<n; i++)
84 {
85 MIDIEndpointRef src = MIDIGetSource(i);
86 MIDIPortConnectSource(inPort, src, (void*)src);
87 }
88 #endif
89
90 // FA
91 // _client and _ippport are printed in the main window's title as [_client:_ipport]
92 // They are the info required to connect to a source using the ALSA sequencer.
93 // Anything equivalent for OSX ?
94
95 // hcf
96 // _appname is the name of the destination, and that's what users are
97 // likely to use when connecting MIDI sources to it.
98
99 M_midi_info *M = new M_midi_info ();
100 M->_client = 0;
101 M->_ipport = 0;
102 memcpy (M->_chbits, _midimap, 16);
103 send_event (TO_MODEL, M);
104 }
105
106
107 void Imidi::close_midi (void)
108 {
109 // nothing to do here - everything is closed automagically (if I
110 // understand the docs correctly)
111 }
112
113
114 void Imidi::coremidi_proc(const MIDIPacketList *pktlist, void *refCon, void *connRefCon)
115 {
116 int c, d, f, m, n, p, t, v, s;
117 MIDIPacket *packet = (MIDIPacket *)pktlist->packet;
118
119 for (unsigned int j=0; j < pktlist->numPackets; j++)
120 {
121 for (int i=0; i < packet->length; i++)
122 {
123 // FA
124 // Maybe this should be factored out so it can be
125 // shared with the ALSA version. But not urgent.
126
127 // hcf
128 // Yeah, and the JACK MIDI version too.
129
130 Byte *E = &packet->data[i];
131 s = E[0];
132 t = s & 0xF0;
133 c = s & 0x0F;
134
135 if (!(s & 0x80))
136 continue; // skip data bytes
137
138 m = _midimap [c] & 127; // Keyboard and hold bits
139 d = (_midimap [c] >> 8) & 7; // Division number if (f & 2)
140 f = (_midimap [c] >> 12) & 7; // Control enabled if (f & 4)
141
142 switch (t)
143 {
144 case 0x80:
145 case 0x90:
146 // Note on or off.
147 n = E[1];
148 v = E[2];
149 if ((t == 0x90) && v)
150 {
151 // Note on.
152 if (n < 36)
153 {
154 if ((f & 4) && (n >= 24) && (n < 34))
155 {
156 // Preset selection, sent to model thread
157 // if on control-enabled channel.
158 if (_qmidi->write_avail () >= 3)
159 {
160 _qmidi->write (0, 0x90);
161 _qmidi->write (1, n);
162 _qmidi->write (2, v);
163 _qmidi->write_commit (3);
164 }
165 }
166 }
167 else if (n <= 96)
168 {
169 if (m)
170 {
171 if (_qnote->write_avail () > 0)
172 {
173 _qnote->write (0, (1 << 24) | ((n - 36) << 8) | m);
174 _qnote->write_commit (1);
175 }
176 }
177 }
178 }
179 else
180 {
181 // Note off.
182 if (n < 36)
183 {
184 }
185 else if (n <= 96)
186 {
187 if (m)
188 {
189 if (_qnote->write_avail () > 0)
190 {
191 _qnote->write (0, ((n - 36) << 8) | m);
192 _qnote->write_commit (1);
193 }
194 }
195 }
196 }
197 break;
198
199 case 0xB0:
200 p = E[0];
201 v = E[1];
202 switch (p)
203 {
204 case MIDICTL_HOLD:
205 // Hold pedal.
206 if (m & HOLD_MASK)
207 {
208 v = (v > 63) ? 9 : 8;
209 if (_qnote->write_avail () > 0)
210 {
211 _qnote->write (0, (v << 24) | (m << 16));
212 _qnote->write_commit (1);
213 }
214 }
215 break;
216
217 case MIDICTL_ASOFF:
218 // All sound off, accepted on control channels only.
219 // Clears all keyboards, including held notes.
220 if (f & 4)
221 {
222 if (_qnote->write_avail () > 0)
223 {
224 _qnote->write (0, (2 << 24) | ( ALL_MASK << 16) | ALL_MASK);
225 _qnote->write_commit (1);
226 }
227 }
228 break;
229
230 case MIDICTL_ANOFF:
231 // All notes off, accepted on channels controlling
232 // a keyboard. Does not clear held notes.
233 if (m)
234 {
235 if (_qnote->write_avail () > 0)
236 {
237 _qnote->write (0, (2 << 24) | (m << 16) | m);
238 _qnote->write_commit (1);
239 }
240 }
241 break;
242
243 case MIDICTL_BANK:
244 case MIDICTL_IFELM:
245 // Program bank selection or stop control, sent
246 // to model thread if on control-enabled channel.
247 if (f & 4)
248 {
249 if (_qmidi->write_avail () >= 3)
250 {
251 _qmidi->write (0, 0xB0 | c);
252 _qmidi->write (1, p);
253 _qmidi->write (2, v);
254 _qmidi->write_commit (3);
255 }
256 }
257 case MIDICTL_SWELL:
258 case MIDICTL_TFREQ:
259 case MIDICTL_TMODD:
260 // Per-division performance controls, sent to model
261 // thread if on a channel that controls a division.
262 if (f & 2)
263 {
264 if (_qmidi->write_avail () >= 3)
265 {
266 _qmidi->write (0, 0xB0 | c);
267 _qmidi->write (1, p);
268 _qmidi->write (2, v);
269 _qmidi->write_commit (3);
270 }
271 }
272 break;
273 }
274 break;
275
276 case 0xC0:
277 // Program change sent to model thread
278 // if on control-enabled channel.
279 n = E[1];
280 if (f & 4)
281 {
282 if (_qmidi->write_avail () >= 3)
283 {
284 _qmidi->write (0, 0xC0);
285 _qmidi->write (1, n);
286 _qmidi->write (2, 0);
287 _qmidi->write_commit (3);
288 }
289 }
290 break;
291 }
292 }
293
294 packet = MIDIPacketNext(packet);
295 }
296 }
00 /*
11 Copyright (C) 2003-2008 Fons Adriaensen <fons@kokkinizita.net>
2 Copyright (C) 2008 Hans Fugal <hans@fugal.net>
23
34 This program is free software; you can redistribute it and/or modify
45 it under the terms of the GNU General Public License as published by
2324 #include <stdlib.h>
2425 #include <stdio.h>
2526 #include <clthreads.h>
27 #ifdef __linux__
2628 #include <alsa/asoundlib.h>
29 #endif
30 #ifdef __APPLE__
31 #include <CoreMIDI/MIDIServices.h>
32 #endif
2733 #include "lfqueue.h"
2834 #include "messages.h"
2935
3743 virtual ~Imidi (void);
3844
3945 void terminate (void);
46 #ifdef __APPLE__
47 void coremidi_proc (const MIDIPacketList *pktlist, void *refCon, void *connRefCon);
48 #endif
4049
4150 private:
4251
5160 Lfq_u8 *_qmidi;
5261 uint16_t *_midimap;
5362 const char *_appname;
63 #ifdef __linux__
5464 snd_seq_t *_handle;
65 #endif
66 #ifdef __APPLE__
67 MIDIClientRef _handle;
68 #endif
5569 int _client;
5670 int _ipport;
5771 int _opport;
5973
6074
6175 #endif
62
164164 }
165165 D++;
166166 }
167
167168 if (n1)
168169 {
169170 add_text (x1, 5, 80, 20, "Trem freq", &text0, -1);
3232 #include "iface.h"
3333
3434
35 #ifdef __linux__
3536 static char *options = "htuAJBM:N:S:I:W:d:r:p:n:";
37 #else
38 static char *options = "htuJBM:N:S:I:W:";
39 #endif
3640 static char optline [1024];
3741 static bool t_opt = false;
3842 static bool u_opt = false;
6064 fprintf (stderr, " -h Display this text\n");
6165 fprintf (stderr, " -t Text mode user interface\n");
6266 fprintf (stderr, " -u Use presets file in user's home dir\n");
67 #ifdef __linux__
6368 fprintf (stderr, " -N <name> Name to use as JACK and ALSA client [aeolus]\n");
69 #else
70 fprintf (stderr, " -N <name> Name to use as JACK and CoreMIDI client [aeolus]\n");
71 #endif
6472 fprintf (stderr, " -S <stops> Name of stops directory [stops]\n");
6573 fprintf (stderr, " -I <instr> Name of instrument directory [Aeolus]\n");
6674 fprintf (stderr, " -W <waves> Name of waves directory [waves]\n");
6775 fprintf (stderr, " -B Ambisonics B format output (JACK only)\n");
6876 fprintf (stderr, " -J Use JACK (default)\n");
77 #ifdef __linux__
6978 fprintf (stderr, " -A Use ALSA, with options:\n");
7079 fprintf (stderr, " -d <device> Alsa device [default]\n");
7180 fprintf (stderr, " -r <rate> Sample frequency [48000]\n");
7281 fprintf (stderr, " -p <period> Period size [1024]\n");
7382 fprintf (stderr, " -n <nfrags> Number of fragments [2]\n\n");
83 #endif
7484 exit (1);
7585 }
7686
196206 }
197207
198208 audio = new Audio (N_val, &note_queue, &comm_queue);
209 #ifdef __linux__
199210 if (A_opt) audio->init_alsa (d_val, r_val, p_val, n_val);
200211 else audio->init_jack (B_opt, &midi_queue);
212 #else
213 audio->init_jack (B_opt, &midi_queue);
214 #endif
201215 model = new Model (&comm_queue, &midi_queue, audio->midimap (), audio->appname (), S_val, I_val, W_val, u_opt);
202216 imidi = new Imidi (&note_queue, &midi_queue, audio->midimap (), audio->appname ());
203217 slave = new Slave ();
3333 FM_MODEL = 10,
3434 FM_IMIDI = 11,
3535 FM_AUDIO = 12,
36 FM_TXTIP = 13,
3637 TO_SLAVE = 8,
3738 TO_IFACE = 9,
3839 TO_MODEL = 10,
7879 MT_IFC_PRGET,
7980 MT_IFC_EDIT,
8081 MT_IFC_APPLY,
81 MT_IFC_SAVE
82 MT_IFC_SAVE,
83 MT_IFC_TXTIP
8284 };
8385
8486
331333 };
332334
333335
336 class M_ifc_txtip : public ITC_mesg
337 {
338 public:
339
340 M_ifc_txtip (void) :
341 ITC_mesg (MT_IFC_TXTIP),
342 _line (0)
343 {}
344
345 char *_line;
346 };
347
348
334349 #endif
335350
2020 #define __MIDIMATRIX_H
2121
2222
23 #include "clxclient.h"
23 #include <clxclient.h>
2424 #include "messages.h"
2525
2626
9292 y = _matrix->ysize () + 20;
9393 but1.size.x = 30;
9494 but1.size.y = 20;
95
9596 for (i = 0; i < 8; i++)
9697 {
9798 sprintf (s, "%d", i + 1);
99100 _bpres [i]->x_map ();
100101 x += 32;
101102 }
103
102104 x += 10;
103105 add_text (x, y, 200, 20, "Shift-click to store preset", &text0, -1);
104106 _xs = _matrix->xsize () + 20;
119121 void Midiwin::setconf (M_ifc_chconf *M)
120122 {
121123 int k;
122
124
123125 k = M->_index;
124126 if (k >= 0)
125127 {
13191319 FILE *F;
13201320 Preset *P;
13211321
1322 F = 0;
13231322 if (_uhome)
13241323 {
13251324 p = (unsigned char *)(getenv ("HOME"));
13261325 if (p) sprintf (name, "%s/.aeolus-presets", p);
13271326 else strcpy (name, ".aeolus-presets");
1328 F = fopen (name, "r");
1329 if (F == 0)
1330 {
1331 fprintf (stderr, "Can't open '%s' for reading\n", name);
1332 }
1333 }
1334 if (F == 0)
1327 }
1328 else
13351329 {
13361330 sprintf (name, "%s/presets", _instr);
1337 F = fopen (name, "r");
1338 }
1339 if (F == 0)
1331 }
1332 if (! (F = fopen (name, "r")))
13401333 {
13411334 fprintf (stderr, "Can't open '%s' for reading\n", name);
13421335 return 1;
8686
8787 XftFonts.spla1 = disp->alloc_xftfont (xrm->get (".font.spla1", "times:pixelsize=24"));
8888 XftFonts.spla2 = disp->alloc_xftfont (xrm->get (".font.spla2", "times:pixelsize=15"));
89 XftFonts.main = disp->alloc_xftfont (xrm->get (".font.main", "suse sans,luxi:pixelsize=13"));
90 XftFonts.large = disp->alloc_xftfont (xrm->get (".font.large", "times:bold:pixelsize=20"));
91 XftFonts.stops = disp->alloc_xftfont (xrm->get (".font.stops", "times:bold:pixelsize=11"));
92 XftFonts.button = disp->alloc_xftfont (xrm->get (".font.button", "suse sans,luxi:pixelsize=13"));
89 XftFonts.main = disp->alloc_xftfont (xrm->get (".font.main", "suse sans,luxi:pixelsize=12"));
90 XftFonts.large = disp->alloc_xftfont (xrm->get (".font.large", "times:bold:pixelsize=18"));
91 XftFonts.stops = disp->alloc_xftfont (xrm->get (".font.stops", "times:bold:pixelsize=14"));
92 XftFonts.button = disp->alloc_xftfont (xrm->get (".font.button", "suse sans,luxi:pixelsize=12"));
9393 XftFonts.scales = disp->alloc_xftfont (xrm->get (".font.scales", "luxi:pixelsize=9"));
9494 XftFonts.midimt = disp->alloc_xftfont (xrm->get (".font.midimt", "luxi:bold:pixelsize=9"));
9595
2020 #define __STYLES_H
2121
2222
23 #include "clxclient.h"
23 #include <clxclient.h>
2424
2525
2626 struct colors
1919
2020 #include <stdlib.h>
2121 #include <stdio.h>
22 #define USE_VARARGS
23 #define PREFER_STDARG
22 #include <ctype.h>
2423 #include <readline/readline.h>
2524 #include <readline/history.h>
2625 #include "tiface.h"
3433
3534
3635
37 Tiface::Tiface (int ac, char *av [])
38 {
36
37 Reader::Reader (Edest *edest, int ipind) :
38 H_thread (edest, ipind)
39 {
40 }
41
42
43 Reader::~Reader (void)
44 {
45 }
46
47
48 void Reader::read (void)
49 {
50 put_event (0, new M_ifc_txtip);
51 }
52
53
54 void Reader::thr_main (void)
55 {
56 M_ifc_txtip *M;
57
58 using_history ();
59 while (1)
60 {
61 get_event (1);
62 M = (M_ifc_txtip *) get_message ();
63 M->_line = readline ("Aeolus> ");
64 if (M->_line) add_history (M->_line);
65 reply (M);
66 }
67 }
68
69
70
71
72 Tiface::Tiface (int ac, char *av []) :
73 _reader (this, FM_TXTIP),
74 _stop (false),
75 _init (true),
76 _initdata (0),
77 _mididata (0)
78 {
79 int i;
80
81 for (i = 0; i < NGROUP; i++) _ifelms [i] = 0;
3982 }
4083
4184
4689
4790 void Tiface::stop (void)
4891 {
49 _stop = true;
5092 }
5193
5294
5395 void Tiface::thr_main (void)
5496 {
55 _stop = false;
5697 set_time (0);
5798 inc_time (125000);
5899
59100 while (! _stop)
60101 {
61 switch (get_event_timed ())
102 switch (get_event ())
62103 {
63 case EV_TIME:
64 handle_time ();
65 inc_time (125000);
66 break;
67
68104 case FM_MODEL:
105 case FM_TXTIP:
69106 handle_mesg (get_message ());
70107 break;
71108
77114 }
78115
79116
80 void Tiface::handle_time (void)
81 {
82 }
83
84
85117 void Tiface::handle_mesg (ITC_mesg *M)
86118 {
87119 switch (M->type ())
88120 {
121 case MT_IFC_INIT:
122 handle_ifc_init ((M_ifc_init *) M);
123 M = 0;
124 break;
125
126 case MT_IFC_READY:
127 handle_ifc_ready ();
128 break;
129
130 case MT_IFC_ELCLR:
131 handle_ifc_elclr ((M_ifc_ifelm *) M);
132 break;
133
134 case MT_IFC_ELSET:
135 handle_ifc_elset ((M_ifc_ifelm *) M);
136 break;
137
138 case MT_IFC_ELATT:
139 handle_ifc_elatt ((M_ifc_ifelm *) M);
140 break;
141
142 case MT_IFC_GRCLR:
143 handle_ifc_grclr ((M_ifc_ifelm *) M);
144 break;
145
146 case MT_IFC_AUPAR:
147 break;
148
149 case MT_IFC_DIPAR:
150 break;
151
152 case MT_IFC_RETUNE:
153 handle_ifc_retune ((M_ifc_retune *) M);
154 break;
155
156 case MT_IFC_MCSET:
157 handle_ifc_mcset ((M_ifc_chconf *) M);
158 M = 0;
159 break;
160
161 case MT_IFC_TXTIP:
162 handle_ifc_txtip ((M_ifc_txtip *) M);
163 break;
164
165 case MT_IFC_PRRCL:
166 break;
167
89168 default:
90 M->recover ();
91 }
92 }
93
94
169 printf ("Received message of unknown type %5ld\n", M->type ());
170 }
171 if (M) M->recover ();
172 }
173
174
175 void Tiface::handle_ifc_ready (void)
176 {
177 if (_init)
178 {
179 printf ("Aeolus is ready.\n");
180 print_info ();
181 _reader.thr_start (SCHED_OTHER, 0, 0x10000);
182 _reader.read ();
183 }
184 _init = false;
185 }
186
187
188 void Tiface::handle_ifc_init (M_ifc_init *M)
189 {
190 if (_initdata) _initdata ->recover ();
191 _initdata = M;
192 }
193
194
195 void Tiface::handle_ifc_mcset (M_ifc_chconf *M)
196 {
197 if (_mididata) _mididata ->recover ();
198 _mididata = M;
199 if (!_init) print_midimap ();
200 }
201
202
203 void Tiface::handle_ifc_retune (M_ifc_retune *M)
204 {
205 printf ("Retuning Aeolus, A = %3.1lf Hz, %s (%s)\n",
206 M->_freq,
207 _initdata->_temped [M->_temp]._label,
208 _initdata->_temped [M->_temp]._mnemo);
209 }
210
211
212 void Tiface::handle_ifc_grclr (M_ifc_ifelm *M)
213 {
214 _ifelms [M->_group] = 0;
215 }
216
217
218 void Tiface::handle_ifc_elclr (M_ifc_ifelm *M)
219 {
220 _ifelms [M->_group] &= ~(1 << M->_ifelm);
221 }
222
223
224 void Tiface::handle_ifc_elset (M_ifc_ifelm *M)
225 {
226 _ifelms [M->_group] |= (1 << M->_ifelm);
227 }
228
229
230 void Tiface::handle_ifc_elatt (M_ifc_ifelm *M)
231 {
232 rewrite_label (_initdata->_groupd [M->_group]._ifelmd [M->_ifelm]._label);
233 printf ("Retuning %7s %-1s (%s)\n",
234 _initdata->_groupd [M->_group]._label,
235 _tempstr,
236 _initdata->_groupd [M->_group]._ifelmd [M->_ifelm]._mnemo);
237 }
238
239
240 void Tiface::handle_ifc_txtip (M_ifc_txtip *M)
241 {
242 if (M->_line == 0)
243 {
244 send_event (EV_EXIT, 1);
245 return;
246 }
247 parse_command (M->_line);
248 _reader.read ();
249 }
250
251
252 void Tiface::print_info (void)
253 {
254 printf ("Application id: %s\n", _initdata->_appid);
255 printf ("Stops directory: %s\n", _initdata->_stops);
256 printf ("Instrument: %s\n", _initdata->_instr);
257 printf ("ALSA Midi port: %d:%d\n", _initdata->_client, _initdata->_ipport);
258 print_keybdd ();
259 print_divisd ();
260 print_midimap ();
261 }
262
263
264 void Tiface::print_keybdd (void)
265 {
266 int i, b, k, n;
267
268 printf ("Keyboards:\n");
269 for (k = 0; k < NKEYBD; k++)
270 {
271 n = 0;
272 if (_initdata->_keybdd [k]._label [0])
273 {
274 printf (" %-7s midi", _initdata->_keybdd [k]._label);
275 for (i = 0; i < 16; i++)
276 {
277 b = _mididata->_bits [i];
278 if ((b & 0x1000) && ((b & 7) == k))
279 {
280 printf (" %2d", i + 1);
281 n++;
282 }
283 }
284 if (!n) printf (" -");
285 printf ("\n");
286 }
287 }
288 }
289
290
291 void Tiface::print_divisd (void)
292 {
293 int i, b, k, n;
294
295 printf ("Divisions:\n");
296 for (k = 0; k < NDIVIS; k++)
297 {
298 n = 0;
299 if (_initdata->_divisd [k]._label [0])
300 {
301 printf (" %-7s midi", _initdata->_divisd [k]._label);
302 for (i = 0; i < 16; i++)
303 {
304 b = _mididata->_bits [i];
305 if ((b & 0x2000) && (((b >> 8) & 7) == k))
306 {
307 printf (" %2d", i + 1);
308 n++;
309 }
310 }
311 if (!n) printf (" -");
312 printf ("\n");
313 }
314 }
315 }
316
317
318 void Tiface::print_midimap (void)
319 {
320 int c, d, f, k, n;
321
322 printf ("Midi routing:\n");
323 n = 0;
324 for (c = 0; c < 16; c++)
325 {
326 f = _mididata->_bits [c];
327 k = f & 7;
328 f >>= 8;
329 d = f & 7;
330 f >>= 4;
331 if (f)
332 {
333 printf (" %2d ", c + 1);
334 if (f & 1) printf ("keybd %-7s", _initdata->_keybdd [k]._label);
335 if (f & 2) printf ("divis %-7s", _initdata->_divisd [k]._label);
336 if (f & 4) printf ("instr");
337 printf ("\n");
338 n++;
339 }
340 }
341 if (n == 0) printf (" No channels are assigned.\n");
342 }
343
344
345 void Tiface::print_stops_short (int group)
346 {
347 int i, n;
348 uint32_t m;
349
350 rewrite_label (_initdata->_groupd [group]._label);
351 printf ("Stops in group %s\n", _tempstr);
352 m = _ifelms [group];
353 n = _initdata->_groupd [group]._nifelm;
354 for (i = 0; i < n; i++)
355 {
356 printf (" %c %-8s", (m & 1) ? '+' : '-',
357 _initdata->_groupd [group]._ifelmd [i]._mnemo);
358 if ((i % 5) == 4) printf ("\n");
359 m >>= 1;
360 }
361 if (n % 5) printf ("\n");
362 }
363
364
365 void Tiface::print_stops_long (int group)
366 {
367 int i, n;
368 uint32_t m;
369
370 rewrite_label (_initdata->_groupd [group]._label);
371 printf ("Stops in group %s\n", _tempstr);
372 m = _ifelms [group];
373 n = _initdata->_groupd [group]._nifelm;
374 for (i = 0; i < n; i++)
375 {
376 rewrite_label (_initdata->_groupd [group]._ifelmd [i]._label);
377 printf (" %c %-7s %-1s\n", (m & 1) ? '+' : '-',
378 _initdata->_groupd [group]._ifelmd [i]._mnemo, _tempstr);
379 m >>= 1;
380 }
381 }
382
383
384 void Tiface::rewrite_label (const char *p)
385 {
386 char *t;
387
388 strcpy (_tempstr, p);
389 t = strstr (_tempstr, "-$");
390 if (t) strcpy (t, t + 2);
391 else
392 {
393 t = strchr (_tempstr, '$');
394 if (t) *t = ' ';
395 }
396 }
397
398
399 void Tiface::parse_command (const char *p)
400 {
401 int c1, c2;
402
403 while (isspace (*p)) p++;
404 c1 = *p++;
405 if (c1 == 0) return;
406 c2 = *p++;
407 if (c2 && !isspace (c2))
408 {
409 printf ("Bad command\n");
410 return;
411 }
412 if (c1 == 0) return;
413 switch (c1)
414 {
415 case 'S':
416 case 's':
417 command_s (p);
418 break;
419
420 case 'Q':
421 case 'q':
422 fclose (stdin);
423 break;
424
425 case '!':
426 send_event (TO_MODEL, new ITC_mesg (MT_IFC_SAVE));
427 break;
428
429 default:
430 printf ("Unknown command '%c'\n", c1);
431 }
432 }
433
434
435 void Tiface::command_s (const char *p)
436 {
437 int g, i, k, n;
438 char s [64];
439
440 if ( (sscanf (p, "%s%n", s, &n) != 1)
441 || ((g = find_group (s)) < 0))
442 {
443 printf ("Expected a group name, ? or ??\n");
444 return;
445 }
446 p += n;
447 if (g == NGROUP + 1)
448 {
449 for (i = 0; i < _initdata->_ngroup; i++) print_stops_short (i);
450 return;
451 }
452 if (g == NGROUP + 2)
453 {
454 for (i = 0; i < _initdata->_ngroup; i++) print_stops_long (i);
455 return;
456 }
457 if ( (sscanf (p, "%s%n", s, &n) != 1)
458 || ((k = comm1 (s)) < 0))
459 {
460 printf ("Expected one of ? ?? + - =\n");
461 return;
462 }
463 p += n;
464 if (k == 0)
465 {
466 print_stops_short (g);
467 return;
468 }
469 if (k == 1)
470 {
471 print_stops_long (g);
472 return;
473 }
474 if (k == 4)
475 {
476 send_event (TO_MODEL, new M_ifc_ifelm (MT_IFC_GRCLR, g, 0));
477 k = 2;
478 }
479 if (k == 2) k = MT_IFC_ELSET;
480 else k = MT_IFC_ELCLR;
481 while (sscanf (p, "%s%n", s, &n) == 1)
482 {
483 i = find_ifelm (s, g);
484 if (i < 0) printf ("No stop '%s' in this group\n", s);
485 else send_event (TO_MODEL, new M_ifc_ifelm (k, g, i));
486 p += n;
487 }
488 }
489
490
491 int Tiface::find_group (const char *p)
492 {
493 int g;
494
495 if (! strcmp (p, "?")) return NGROUP + 1;
496 if (! strcmp (p, "??")) return NGROUP + 2;
497 for (g = 0; g < _initdata->_ngroup; g++)
498 {
499 if (! strcmp (p, _initdata->_groupd [g]._label)) return g;
500 }
501 return -1;
502 }
503
504
505 int Tiface::find_ifelm (const char *p, int g)
506 {
507 int i, n;
508
509 n = _initdata->_groupd [g]._nifelm;
510 for (i = 0; i < n; i++)
511 {
512 if (! strcmp (p, _initdata->_groupd [g]._ifelmd [i]._mnemo)) return i;
513 }
514 return -1;
515 }
516
517
518 int Tiface::comm1 (const char *p)
519 {
520 if (! strcmp (p, "?")) return 0;
521 if (! strcmp (p, "??")) return 1;
522 if (! strcmp (p, "+")) return 2;
523 if (! strcmp (p, "-")) return 3;
524 if (! strcmp (p, "=")) return 4;
525 return -1;
526 }
1919 #ifndef __TIFACE_H
2020 #define __TIFACE_H
2121
22
2223 #include "iface.h"
2324
2425
26 class Reader : public H_thread
27 {
28 public:
29
30 Reader (Edest *, int);
31 virtual ~Reader (void);
32
33 void read (void);
34
35 private:
36
37 virtual void thr_main (void);
38 };
39
40
41
2542 class Tiface : public Iface
2643 {
2744 public:
3653
3754 void handle_mesg (ITC_mesg *);
3855 void handle_time (void);
39
40 bool _stop;
56 void handle_ifc_ready (void);
57 void handle_ifc_init (M_ifc_init *);
58 void handle_ifc_mcset (M_ifc_chconf *);
59 void handle_ifc_retune (M_ifc_retune *);
60 void handle_ifc_grclr (M_ifc_ifelm *);
61 void handle_ifc_elclr (M_ifc_ifelm *);
62 void handle_ifc_elset (M_ifc_ifelm *);
63 void handle_ifc_elatt (M_ifc_ifelm *);
64 void handle_ifc_txtip (M_ifc_txtip *);
65 void print_info (void);
66 void print_midimap (void);
67 void print_keybdd (void);
68 void print_divisd (void);
69 void print_asectd (void);
70 void print_stops_short (int);
71 void print_stops_long (int);
72 void rewrite_label (const char *);
73 void parse_command (const char *);
74 void command_s (const char *);
75 int find_group (const char *);
76 int find_ifelm (const char *, int);
77 int comm1 (const char *);
78
79 Reader _reader;
80 bool _stop;
81 bool _init;
82 M_ifc_init *_initdata;
83 M_ifc_chconf *_mididata;
84 uint32_t _ifelms [NGROUP];
85 char _tempstr [64];
4186 };
4287
4388
7878 inc_time (125000);
7979 while (! _stop)
8080 {
81 switch (get_event_timed ())
81 switch (get_event_timed ())
8282 {
8383 case EV_TIME:
8484 handle_time ();