1 /*  SpiralSynth
2  *  Copyleft (C) 2000 David Griffiths <dave@pawfal.org>
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18 
19 #ifndef MIDI
20 #define MIDI
21 
22 #include <sys/types.h>
23 #include <stdio.h>
24 #include <fcntl.h>
25 #include <unistd.h>
26 #include <iostream>
27 #include <limits.h>
28 #include <queue>
29 #include <string>
30 #include "../config.h"
31 
32 using namespace std;
33 
34 #ifdef USE_ALSA_MIDI
35 #include <alsa/asoundlib.h>
36 #endif
37 
38 #if __APPLE__
39 #include <CoreMIDI/MIDIServices.h>
40 #endif
41 
42 class MidiEvent
43 {
44 public:
45 	enum type{NONE,ON,OFF,AFTERTOUCH,PARAMETER,CHANNELPRESSURE,PITCHBEND};
46 
47 	MidiEvent() {m_Type=NONE;}
48 	MidiEvent(type t, int note, float v)
49 		{m_Type=t; m_Note=note; m_Volume=v;}
50 
51 	type GetType() const {return m_Type;}
52 	float GetVolume() const {return m_Volume;}
53 	int GetNote() const {return m_Note;}
54 private:
55 	float m_Volume;
56 	type  m_Type;
57 	int   m_Note;
58 };
59 
60 class MidiDevice
61 {
62 public:
63 	~MidiDevice();
64 
65 	enum Type{READ,WRITE};
66 
67 	static void Init(const string &name, Type t);
68 	static void SetDeviceName(string s) {
69                #ifdef USE_OSS_MIDI
70                m_DeviceName=s;
71                #endif
72         }
73         static MidiDevice *Get()      { return m_Singleton; }
74 	static void PackUpAndGoHome() { if (m_Singleton) delete m_Singleton; m_Singleton=NULL; }
75 
76 	MidiEvent GetEvent(int Device);
77 	void SendEvent(int Device,const MidiEvent &Event);
78 
79 	void SetPoly(int s) { m_Poly=s; }
80 
81 	float GetClock() { return m_Clock; }
82 
83 private:
84 	MidiDevice(Type t);
85 
86 	int  m_Poly;
87 	float m_Clock;
88 	int   m_ClockCount;
89 
90 	queue<MidiEvent> m_EventVec[16];
91 
92 	static MidiDevice *m_Singleton;
93 
94 	pthread_t        m_MidiReader;
95 	pthread_mutex_t* m_Mutex;
96 
97 	static string m_AppName;
98 #ifdef USE_ALSA_MIDI
99 	static void *MidiReaderCallback (void *o) { ((MidiDevice*)o)->AlsaCollectEvents(); return NULL; }
100 	void AlsaCollectEvents();
101 	void AlsaSendEvent(int Device, const MidiEvent &Event);
102 
103         void AlsaClose ();
104 
105 	//snd_seq_t *seq_handle;
106 
107 	//I appears that ALsa does not support both a read and write handle
108 	//so we must have two handle one for each mode
109 	snd_seq_t *seq_rhandle;
110 	snd_seq_t *seq_whandle;
111 
112 	void AlsaOpen();
113 #endif
114 #ifdef USE_OSS_MIDI
115         static void *MidiReaderCallback (void *o) { ((MidiDevice*)o)->OssCollectEvents(); return NULL; }
116 	void OssCollectEvents();
117 	void OssAddEvent(unsigned char* midi);
118 	void OssReadByte(unsigned char *c);
119 	void OssClose();
120         bool OssOpen();
121         static string m_DeviceName;
122 	int m_MidiFd, m_MidiWrFd;
123 #endif
124 #if __APPLE__
125 	MIDIClientRef					mMIDIClient;
126 	MIDIEndpointRef					mMIDISource;
127 	MIDIEndpointRef					mMIDIDestination;
128 
129 	#define midi_ReadSize			4096
130 	unsigned char					m_ReadBuffer[midi_ReadSize];
131 	volatile int					m_ReadFillIndex;
132 	volatile int					m_ReadReadIndex;
133 
134 	void MidiDevice::AppleOpen();
135 	void MidiDevice::AppleClose();
136 	int MidiDevice::AppleWrite(int dummy, unsigned char *outbuffer, int maxlen);
137 	int MidiDevice::AppleRead(int dummy, unsigned char *outbuffer, int maxlen);
138 
139 	static void MidiDevice::sMIDIRead(const MIDIPacketList *pktlist, void *readProcRefCon, void *srcConnRefCon);
140 
141 #endif
142 };
143 
144 #endif
145