1 /*
2 Copyright (C) 2008 Grame
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., 675 Mass Ave, Cambridge, MA 02139, USA.
17 
18 */
19 
20 #ifndef __JackCoreAudioAdapter__
21 #define __JackCoreAudioAdapter__
22 
23 #include "JackAudioAdapterInterface.h"
24 #include "jack.h"
25 #include "jslist.h"
26 #include <AudioToolbox/AudioConverter.h>
27 #include <CoreAudio/CoreAudio.h>
28 #include <AudioUnit/AudioUnit.h>
29 
30 #include <vector>
31 
32 using namespace std;
33 
34 namespace Jack
35 {
36 
37 typedef	UInt8	CAAudioHardwareDeviceSectionID;
38 #define	kAudioDeviceSectionInput	((CAAudioHardwareDeviceSectionID)0x01)
39 #define	kAudioDeviceSectionOutput	((CAAudioHardwareDeviceSectionID)0x00)
40 #define	kAudioDeviceSectionGlobal	((CAAudioHardwareDeviceSectionID)0x00)
41 #define	kAudioDeviceSectionWildcard	((CAAudioHardwareDeviceSectionID)0xFF)
42 
43 #define WAIT_COUNTER 60
44 
45 /*!
46 \brief Audio adapter using CoreAudio API.
47 */
48 
49 class JackCoreAudioAdapter : public JackAudioAdapterInterface
50 {
51 
52     private:
53 
54         AudioUnit fAUHAL;
55         AudioBufferList* fInputData;
56 
57         char fCaptureUID[256];
58         char fPlaybackUID[256];
59 
60         bool fCapturing;
61         bool fPlaying;
62 
63         AudioDeviceID fDeviceID;    // Used "duplex" device
64         AudioObjectID fPluginID;    // Used for aggregate device
65 
66         vector<int> fInputLatencies;
67         vector<int> fOutputLatencies;
68 
69         bool fState;
70 
71         AudioUnitRenderActionFlags* fActionFags;
72         AudioTimeStamp* fCurrentTime;
73         bool fClockDriftCompensate;
74 
75         static	OSStatus Render(void *inRefCon,
76                                 AudioUnitRenderActionFlags *ioActionFlags,
77                                 const AudioTimeStamp *inTimeStamp,
78                                 UInt32 inBusNumber,
79                                 UInt32 inNumberFrames,
80                                 AudioBufferList *ioData);
81 
82         static OSStatus AudioHardwareNotificationCallback(AudioHardwarePropertyID inPropertyID,void* inClientData);
83 
84         static OSStatus SRNotificationCallback(AudioDeviceID inDevice,
85                                                 UInt32 inChannel,
86                                                 Boolean	isInput,
87                                                 AudioDevicePropertyID inPropertyID,
88                                                 void* inClientData);
89         static OSStatus DeviceNotificationCallback(AudioDeviceID inDevice,
90                                                     UInt32 inChannel,
91                                                     Boolean	isInput,
92                                                     AudioDevicePropertyID inPropertyID,
93                                                     void* inClientData);
94 
95         OSStatus GetDefaultDevice(AudioDeviceID* id);
96         OSStatus GetTotalChannels(AudioDeviceID device, int& channelCount, bool isInput);
97         OSStatus GetDeviceIDFromUID(const char* UID, AudioDeviceID* id);
98         OSStatus GetDefaultInputDevice(AudioDeviceID* id);
99         OSStatus GetDefaultOutputDevice(AudioDeviceID* id);
100         OSStatus GetDeviceNameFromID(AudioDeviceID id, char* name);
101         AudioDeviceID GetDeviceIDFromName(const char* name);
102 
103         // Setup
104         OSStatus CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice);
105         OSStatus CreateAggregateDeviceAux(vector<AudioDeviceID> captureDeviceID, vector<AudioDeviceID> playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice);
106         OSStatus DestroyAggregateDevice();
107         bool IsAggregateDevice(AudioDeviceID device);
108 
109         int SetupDevices(const char* capture_driver_uid,
110                          const char* playback_driver_uid,
111                          char* capture_driver_name,
112                          char* playback_driver_name,
113                          jack_nframes_t samplerate);
114 
115         int SetupChannels(bool capturing,
116                           bool playing,
117                           int& inchannels,
118                           int& outchannels,
119                           int& in_nChannels,
120                           int& out_nChannels,
121                           bool strict);
122 
123         int OpenAUHAL(bool capturing,
124                     bool playing,
125                     int inchannels,
126                     int outchannels,
127                     int in_nChannels,
128                     int out_nChannels,
129                     jack_nframes_t buffer_size,
130                     jack_nframes_t samplerate);
131 
132         int SetupBufferSize(jack_nframes_t buffer_size);
133         int SetupSampleRate(jack_nframes_t samplerate);
134         int SetupSampleRateAux(AudioDeviceID inDevice, jack_nframes_t samplerate);
135 
136         int SetupBuffers(int inchannels);
137         void DisposeBuffers();
138         void CloseAUHAL();
139 
140         int AddListeners();
141         void RemoveListeners();
142 
143         int GetLatency(int port_index, bool input);
144         OSStatus GetStreamLatencies(AudioDeviceID device, bool isInput, vector<int>& latencies);
145 
146         OSStatus Render(AudioUnitRenderActionFlags *ioActionFlags,
147                         const AudioTimeStamp *inTimeStamp,
148                         UInt32 inNumberFrames,
149                         AudioBufferList *ioData);
150 
151     public:
152 
153         JackCoreAudioAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params);
~JackCoreAudioAdapter()154         ~JackCoreAudioAdapter()
155         {}
156 
157         virtual int Open();
158         virtual int Close();
159 
160         virtual int SetSampleRate(jack_nframes_t sample_rate);
161         virtual int SetBufferSize(jack_nframes_t buffer_size);
162 
163         virtual int GetInputLatency(int port_index);
164         virtual int GetOutputLatency(int port_index);
165 };
166 
167 
168 } // end of namespace
169 
170 #ifdef __cplusplus
171 extern "C"
172 {
173 #endif
174 
175 #include "JackCompilerDeps.h"
176 #include "driver_interface.h"
177 
178 SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor();
179 
180 #ifdef __cplusplus
181 }
182 #endif
183 
184 #endif
185