Imported Upstream version 0.8.2
Alessio Treglia
14 years ago
0 | AEOLUS 0.8.0 BUILD INSTRUCTIONS | |
1 | ________________________________ | |
0 | AEOLUS 0.8.2 BUILD INSTRUCTIONS (LINUX) | |
1 | _______________________________________ | |
2 | 2 | |
3 | 3 | |
4 | 4 | To build this version, you need to have the shared |
5 | 5 | libraries |
6 | 6 | |
7 | 7 | * 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 | |
10 | 10 | |
11 | 11 | and the corresponding header files installed. |
12 | 12 | They should be available from the same place where |
18 | 18 | * aeolus_x11.so GUI plugin, |
19 | 19 | * aeolus_txt.so text mode user interface. |
20 | 20 | |
21 | In this version the latter is just an empty stub. | |
21 | In this version the latter is functional but not complete. | |
22 | 22 | |
23 | 23 | The default Makefile will install the Aeolus binary |
24 | 24 | in /usr/local/bin, and the user interface plugins in |
42 | 42 | |
43 | 43 | See also the README file for run-time configuration. |
44 | 44 | |
45 | ||
46 | AEOLUS 0.8.2 BUILD INSTRUCTIONS (OSX) | |
47 | _____________________________________ | |
48 | ||
49 | ||
50 | See the file BUILD-osx | |
51 | ||
52 | ||
45 | 53 | -- |
46 | 54 | 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> |
17 | 17 | PREFIX = /usr/local |
18 | 18 | SUFFIX := $(shell uname -m | sed -e 's/^unknown/$//' -e 's/^i.86/$//' -e 's/^x86_64/$/64/') |
19 | 19 | LIBDIR = lib$(SUFFIX) |
20 | VERSION = 0.8.1 | |
20 | VERSION = 0.8.2 | |
21 | 21 | DISTDIR = aeolus-$(VERSION) |
22 | 22 | CPPFLAGS += -O3 -Wall -MMD -MP -DVERSION=\"$(VERSION)\" -DLIBDIR=\"$(PREFIX)/$(LIBDIR)\" |
23 | 23 | #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); |
17 | 17 | |
18 | 18 | |
19 | 19 | #include <string.h> |
20 | #include <endian.h> | |
20 | #include "global.h" | |
21 | 21 | #include "addsynth.h" |
22 | 22 | |
23 | 23 | |
117 | 117 | fwrite (d, N_NOTE, sizeof (float), F); |
118 | 118 | |
119 | 119 | #else |
120 | #error Byte order is undefined ! | |
120 | #error Byte order is not supported ! | |
121 | 121 | #endif |
122 | 122 | #else |
123 | 123 | #error Byte order is undefined ! |
145 | 145 | for (i = 0; i < N_NOTE; i++) swap4 ((char *)(_v + i), d + i * sizeof (float)); |
146 | 146 | |
147 | 147 | #else |
148 | #error Byte order is undefined ! | |
148 | #error Byte order is not supported ! | |
149 | 149 | #endif |
150 | 150 | #else |
151 | 151 | #error Byte order is undefined ! |
30 | 30 | _qcomm (qcomm), |
31 | 31 | _qmidi (0), |
32 | 32 | _running (false), |
33 | #ifdef __linux__ | |
33 | 34 | _alsa_handle (0), |
35 | #endif | |
34 | 36 | _jack_handle (0), |
35 | 37 | _abspri (0), |
36 | 38 | _relpri (0), |
48 | 50 | { |
49 | 51 | int i; |
50 | 52 | |
53 | #ifdef __linux__ | |
51 | 54 | if (_alsa_handle) close_alsa (); |
55 | #endif | |
52 | 56 | if (_jack_handle) close_jack (); |
53 | 57 | for (i = 0; i < _nasect; i++) delete _asectp [i]; |
54 | 58 | for (i = 0; i < _ndivis; i++) delete _divisp [i]; |
104 | 108 | } |
105 | 109 | |
106 | 110 | |
111 | #ifdef __linux__ | |
107 | 112 | void Audio::init_alsa (const char *device, int fsamp, int fsize, int nfrag) |
108 | 113 | { |
109 | 114 | _alsa_handle = new Alsa_driver (device, fsamp, fsize, nfrag, true, false, false); |
129 | 134 | } |
130 | 135 | } |
131 | 136 | } |
132 | ||
133 | ||
137 | #endif | |
138 | ||
139 | ||
140 | #ifdef __linux__ | |
134 | 141 | void Audio::close_alsa () |
135 | 142 | { |
136 | _running = false; | |
143 | _running = false; | |
137 | 144 | fprintf (stderr, "Closing ALSA.\n"); |
138 | 145 | get_event (1 << EV_EXIT); |
139 | 146 | for (int i = 0; i < _nplay; i++) delete[] _outbuf [i]; |
140 | 147 | delete _alsa_handle; |
141 | 148 | } |
149 | #endif | |
142 | 150 | |
143 | 151 | |
144 | 152 | void Audio::thr_main (void) |
145 | 153 | { |
154 | #ifdef __linux__ | |
146 | 155 | unsigned long k; |
147 | 156 | |
148 | 157 | _alsa_handle->pcm_start (); |
167 | 176 | |
168 | 177 | _alsa_handle->pcm_stop (); |
169 | 178 | put_event (EV_EXIT); |
179 | #endif | |
170 | 180 | } |
171 | 181 | |
172 | 182 | |
436 | 446 | union { uint32_t i; float f; } u; |
437 | 447 | |
438 | 448 | // Execute commands from the model thread (qcomm), |
439 | // or from the midi thread (qmidi). | |
449 | // or from the midi thread (qnote). | |
440 | 450 | |
441 | 451 | n = Q->read_avail (); |
442 | 452 | while (n > 0) |
22 | 22 | |
23 | 23 | #include <stdlib.h> |
24 | 24 | #include <clthreads.h> |
25 | #ifdef __linux__ | |
25 | 26 | #include <clalsadrv.h> |
27 | #endif | |
26 | 28 | #include <jack/jack.h> |
27 | 29 | #include "asection.h" |
28 | 30 | #include "division.h" |
37 | 39 | |
38 | 40 | Audio (const char *jname, Lfq_u32 *qnote, Lfq_u32 *qcomm); |
39 | 41 | virtual ~Audio (void); |
42 | #ifdef __linux__ | |
40 | 43 | void init_alsa (const char *device, int fsamp, int fsize, int nfrag); |
44 | #endif | |
41 | 45 | void init_jack (bool bform, Lfq_u8 *qmidi); |
42 | 46 | void start (void); |
43 | 47 | |
52 | 56 | enum { VOLUME, REVSIZE, REVTIME, STPOSIT }; |
53 | 57 | |
54 | 58 | void init_audio (void); |
59 | #ifdef __linux__ | |
55 | 60 | void close_alsa (void); |
61 | #endif | |
56 | 62 | void close_jack (void); |
57 | 63 | virtual void thr_main (void); |
58 | 64 | void jack_shutdown (void); |
113 | 119 | Lfq_u32 *_qcomm; |
114 | 120 | Lfq_u8 *_qmidi; |
115 | 121 | volatile bool _running; |
122 | #ifdef __linux__ | |
116 | 123 | Alsa_driver *_alsa_handle; |
124 | #endif | |
117 | 125 | jack_client_t *_jack_handle; |
118 | 126 | jack_port_t *_jack_opport [8]; |
119 | 127 | jack_port_t *_jack_midipt; |
20 | 20 | #define __CALLBACKS_H |
21 | 21 | |
22 | 22 | |
23 | #include "clxclient.h" | |
23 | #include <clxclient.h> | |
24 | 24 | |
25 | 25 | |
26 | 26 | enum |
20 | 20 | #define __EDITWIN_H |
21 | 21 | |
22 | 22 | |
23 | #include "clxclient.h" | |
23 | #include <clxclient.h> | |
24 | 24 | #include "multislider.h" |
25 | 25 | #include "functionwin.h" |
26 | 26 | #include "addsynth.h" |
20 | 20 | #define __FUNCTIONWIN_H |
21 | 21 | |
22 | 22 | |
23 | #include "clxclient.h" | |
23 | #include <clxclient.h> | |
24 | 24 | |
25 | 25 | |
26 | 26 | class Functionwin : public X_window |
0 | 0 | /* |
1 | 1 | Copyright (C) 2003-2008 Fons Adriaensen <fons@kokkinizita.net> |
2 | Copyright (C) 2008 Hans Fugal <hans@fugal.net> (OSX version) | |
2 | 3 | |
3 | 4 | This program is free software; you can redistribute it and/or modify |
4 | 5 | it under the terms of the GNU General Public License as published by |
20 | 21 | #define __GLOBAL_H |
21 | 22 | |
22 | 23 | |
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 | |
23 | 31 | #include <endian.h> |
24 | #include "lfqueue.h" | |
25 | ||
32 | #endif | |
26 | 33 | |
27 | 34 | #ifdef __BYTE_ORDER |
28 | 35 | #if (__BYTE_ORDER == __LITTLE_ENDIAN) |
36 | 43 | #define RD2(p) ((p)[1] + ((p)[0] << 8)); |
37 | 44 | #define RD4(p) ((p)[3] + ((p)[2] << 8) + ((p)[1] << 16) + ((p)[0] << 24)); |
38 | 45 | #else |
39 | #error Byte order is undefined ! | |
46 | #error Byte order is not supported ! | |
40 | 47 | #endif |
41 | 48 | #else |
42 | 49 | #error Byte order is undefined ! |
43 | 50 | #endif |
51 | ||
52 | #include "lfqueue.h" | |
44 | 53 | |
45 | 54 | |
46 | 55 | 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 | } |
0 | 0 | /* |
1 | 1 | Copyright (C) 2003-2008 Fons Adriaensen <fons@kokkinizita.net> |
2 | Copyright (C) 2008 Hans Fugal <hans@fugal.net> | |
2 | 3 | |
3 | 4 | This program is free software; you can redistribute it and/or modify |
4 | 5 | it under the terms of the GNU General Public License as published by |
23 | 24 | #include <stdlib.h> |
24 | 25 | #include <stdio.h> |
25 | 26 | #include <clthreads.h> |
27 | #ifdef __linux__ | |
26 | 28 | #include <alsa/asoundlib.h> |
29 | #endif | |
30 | #ifdef __APPLE__ | |
31 | #include <CoreMIDI/MIDIServices.h> | |
32 | #endif | |
27 | 33 | #include "lfqueue.h" |
28 | 34 | #include "messages.h" |
29 | 35 | |
37 | 43 | virtual ~Imidi (void); |
38 | 44 | |
39 | 45 | void terminate (void); |
46 | #ifdef __APPLE__ | |
47 | void coremidi_proc (const MIDIPacketList *pktlist, void *refCon, void *connRefCon); | |
48 | #endif | |
40 | 49 | |
41 | 50 | private: |
42 | 51 | |
51 | 60 | Lfq_u8 *_qmidi; |
52 | 61 | uint16_t *_midimap; |
53 | 62 | const char *_appname; |
63 | #ifdef __linux__ | |
54 | 64 | snd_seq_t *_handle; |
65 | #endif | |
66 | #ifdef __APPLE__ | |
67 | MIDIClientRef _handle; | |
68 | #endif | |
55 | 69 | int _client; |
56 | 70 | int _ipport; |
57 | 71 | int _opport; |
59 | 73 | |
60 | 74 | |
61 | 75 | #endif |
62 |
164 | 164 | } |
165 | 165 | D++; |
166 | 166 | } |
167 | ||
167 | 168 | if (n1) |
168 | 169 | { |
169 | 170 | add_text (x1, 5, 80, 20, "Trem freq", &text0, -1); |
32 | 32 | #include "iface.h" |
33 | 33 | |
34 | 34 | |
35 | #ifdef __linux__ | |
35 | 36 | 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 | |
36 | 40 | static char optline [1024]; |
37 | 41 | static bool t_opt = false; |
38 | 42 | static bool u_opt = false; |
60 | 64 | fprintf (stderr, " -h Display this text\n"); |
61 | 65 | fprintf (stderr, " -t Text mode user interface\n"); |
62 | 66 | fprintf (stderr, " -u Use presets file in user's home dir\n"); |
67 | #ifdef __linux__ | |
63 | 68 | 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 | |
64 | 72 | fprintf (stderr, " -S <stops> Name of stops directory [stops]\n"); |
65 | 73 | fprintf (stderr, " -I <instr> Name of instrument directory [Aeolus]\n"); |
66 | 74 | fprintf (stderr, " -W <waves> Name of waves directory [waves]\n"); |
67 | 75 | fprintf (stderr, " -B Ambisonics B format output (JACK only)\n"); |
68 | 76 | fprintf (stderr, " -J Use JACK (default)\n"); |
77 | #ifdef __linux__ | |
69 | 78 | fprintf (stderr, " -A Use ALSA, with options:\n"); |
70 | 79 | fprintf (stderr, " -d <device> Alsa device [default]\n"); |
71 | 80 | fprintf (stderr, " -r <rate> Sample frequency [48000]\n"); |
72 | 81 | fprintf (stderr, " -p <period> Period size [1024]\n"); |
73 | 82 | fprintf (stderr, " -n <nfrags> Number of fragments [2]\n\n"); |
83 | #endif | |
74 | 84 | exit (1); |
75 | 85 | } |
76 | 86 | |
196 | 206 | } |
197 | 207 | |
198 | 208 | audio = new Audio (N_val, ¬e_queue, &comm_queue); |
209 | #ifdef __linux__ | |
199 | 210 | if (A_opt) audio->init_alsa (d_val, r_val, p_val, n_val); |
200 | 211 | else audio->init_jack (B_opt, &midi_queue); |
212 | #else | |
213 | audio->init_jack (B_opt, &midi_queue); | |
214 | #endif | |
201 | 215 | model = new Model (&comm_queue, &midi_queue, audio->midimap (), audio->appname (), S_val, I_val, W_val, u_opt); |
202 | 216 | imidi = new Imidi (¬e_queue, &midi_queue, audio->midimap (), audio->appname ()); |
203 | 217 | slave = new Slave (); |
33 | 33 | FM_MODEL = 10, |
34 | 34 | FM_IMIDI = 11, |
35 | 35 | FM_AUDIO = 12, |
36 | FM_TXTIP = 13, | |
36 | 37 | TO_SLAVE = 8, |
37 | 38 | TO_IFACE = 9, |
38 | 39 | TO_MODEL = 10, |
78 | 79 | MT_IFC_PRGET, |
79 | 80 | MT_IFC_EDIT, |
80 | 81 | MT_IFC_APPLY, |
81 | MT_IFC_SAVE | |
82 | MT_IFC_SAVE, | |
83 | MT_IFC_TXTIP | |
82 | 84 | }; |
83 | 85 | |
84 | 86 | |
331 | 333 | }; |
332 | 334 | |
333 | 335 | |
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 | ||
334 | 349 | #endif |
335 | 350 |
20 | 20 | #define __MIDIMATRIX_H |
21 | 21 | |
22 | 22 | |
23 | #include "clxclient.h" | |
23 | #include <clxclient.h> | |
24 | 24 | #include "messages.h" |
25 | 25 | |
26 | 26 |
92 | 92 | y = _matrix->ysize () + 20; |
93 | 93 | but1.size.x = 30; |
94 | 94 | but1.size.y = 20; |
95 | ||
95 | 96 | for (i = 0; i < 8; i++) |
96 | 97 | { |
97 | 98 | sprintf (s, "%d", i + 1); |
99 | 100 | _bpres [i]->x_map (); |
100 | 101 | x += 32; |
101 | 102 | } |
103 | ||
102 | 104 | x += 10; |
103 | 105 | add_text (x, y, 200, 20, "Shift-click to store preset", &text0, -1); |
104 | 106 | _xs = _matrix->xsize () + 20; |
119 | 121 | void Midiwin::setconf (M_ifc_chconf *M) |
120 | 122 | { |
121 | 123 | int k; |
122 | ||
124 | ||
123 | 125 | k = M->_index; |
124 | 126 | if (k >= 0) |
125 | 127 | { |
1319 | 1319 | FILE *F; |
1320 | 1320 | Preset *P; |
1321 | 1321 | |
1322 | F = 0; | |
1323 | 1322 | if (_uhome) |
1324 | 1323 | { |
1325 | 1324 | p = (unsigned char *)(getenv ("HOME")); |
1326 | 1325 | if (p) sprintf (name, "%s/.aeolus-presets", p); |
1327 | 1326 | 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 | |
1335 | 1329 | { |
1336 | 1330 | sprintf (name, "%s/presets", _instr); |
1337 | F = fopen (name, "r"); | |
1338 | } | |
1339 | if (F == 0) | |
1331 | } | |
1332 | if (! (F = fopen (name, "r"))) | |
1340 | 1333 | { |
1341 | 1334 | fprintf (stderr, "Can't open '%s' for reading\n", name); |
1342 | 1335 | return 1; |
86 | 86 | |
87 | 87 | XftFonts.spla1 = disp->alloc_xftfont (xrm->get (".font.spla1", "times:pixelsize=24")); |
88 | 88 | 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")); | |
93 | 93 | XftFonts.scales = disp->alloc_xftfont (xrm->get (".font.scales", "luxi:pixelsize=9")); |
94 | 94 | XftFonts.midimt = disp->alloc_xftfont (xrm->get (".font.midimt", "luxi:bold:pixelsize=9")); |
95 | 95 |
20 | 20 | #define __STYLES_H |
21 | 21 | |
22 | 22 | |
23 | #include "clxclient.h" | |
23 | #include <clxclient.h> | |
24 | 24 | |
25 | 25 | |
26 | 26 | struct colors |
19 | 19 | |
20 | 20 | #include <stdlib.h> |
21 | 21 | #include <stdio.h> |
22 | #define USE_VARARGS | |
23 | #define PREFER_STDARG | |
22 | #include <ctype.h> | |
24 | 23 | #include <readline/readline.h> |
25 | 24 | #include <readline/history.h> |
26 | 25 | #include "tiface.h" |
34 | 33 | |
35 | 34 | |
36 | 35 | |
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; | |
39 | 82 | } |
40 | 83 | |
41 | 84 | |
46 | 89 | |
47 | 90 | void Tiface::stop (void) |
48 | 91 | { |
49 | _stop = true; | |
50 | 92 | } |
51 | 93 | |
52 | 94 | |
53 | 95 | void Tiface::thr_main (void) |
54 | 96 | { |
55 | _stop = false; | |
56 | 97 | set_time (0); |
57 | 98 | inc_time (125000); |
58 | 99 | |
59 | 100 | while (! _stop) |
60 | 101 | { |
61 | switch (get_event_timed ()) | |
102 | switch (get_event ()) | |
62 | 103 | { |
63 | case EV_TIME: | |
64 | handle_time (); | |
65 | inc_time (125000); | |
66 | break; | |
67 | ||
68 | 104 | case FM_MODEL: |
105 | case FM_TXTIP: | |
69 | 106 | handle_mesg (get_message ()); |
70 | 107 | break; |
71 | 108 | |
77 | 114 | } |
78 | 115 | |
79 | 116 | |
80 | void Tiface::handle_time (void) | |
81 | { | |
82 | } | |
83 | ||
84 | ||
85 | 117 | void Tiface::handle_mesg (ITC_mesg *M) |
86 | 118 | { |
87 | 119 | switch (M->type ()) |
88 | 120 | { |
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 | ||
89 | 168 | 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 | } |
19 | 19 | #ifndef __TIFACE_H |
20 | 20 | #define __TIFACE_H |
21 | 21 | |
22 | ||
22 | 23 | #include "iface.h" |
23 | 24 | |
24 | 25 | |
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 | ||
25 | 42 | class Tiface : public Iface |
26 | 43 | { |
27 | 44 | public: |
36 | 53 | |
37 | 54 | void handle_mesg (ITC_mesg *); |
38 | 55 | 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]; | |
41 | 86 | }; |
42 | 87 | |
43 | 88 |