]> git.mxchange.org Git - flightgear.git/blob - 3rdparty/iaxclient/lib/portmixer/px_mac/px_mac.c
Move IAXClient library into 3rdparty directory
[flightgear.git] / 3rdparty / iaxclient / lib / portmixer / px_mac / px_mac.c
1 /*
2  * PortMixer
3  * Mac OS 9 implementation
4  *
5  * Copyright (c) 2002
6  *
7  * Written by Dominic Mazzoni
8  *
9  * PortMixer is intended to work side-by-side with PortAudio,
10  * the Portable Real-Time Audio Library by Ross Bencina and
11  * Phil Burk.
12  *
13  * Permission is hereby granted, free of charge, to any person obtaining
14  * a copy of this software and associated documentation files
15  * (the "Software"), to deal in the Software without restriction,
16  * including without limitation the rights to use, copy, modify, merge,
17  * publish, distribute, sublicense, and/or sell copies of the Software,
18  * and to permit persons to whom the Software is furnished to do so,
19  * subject to the following conditions:
20  *
21  * The above copyright notice and this permission notice shall be
22  * included in all copies or substantial portions of the Software.
23  *
24  * Any person wishing to distribute modifications to the Software is
25  * requested to send the modifications to the original developer so that
26  * they can be incorporated into the canonical version.
27  *
28  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
31  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
32  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
33  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
34  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35  *
36  */
37
38 #include <stdlib.h>
39 #include <string.h>
40
41 #include "portaudio.h"
42 #include "pa_host.h"
43 #include "portmixer.h"
44
45 #define PA_MAX_NUM_HOST_BUFFERS           (16)   /* Do not exceed!! */
46
47 typedef struct MultiBuffer
48 {
49     char    *buffers[PA_MAX_NUM_HOST_BUFFERS];
50     int      numBuffers;
51     int      nextWrite;
52     int      nextRead;
53 }
54 MultiBuffer;
55
56 /* Define structure to contain all Macintosh specific data. */
57 typedef struct PaHostSoundControl
58 {
59     UInt64                  pahsc_EntryCount;
60         double                  pahsc_InverseMicrosPerHostBuffer; /* 1/Microseconds of real-time audio per user buffer. */
61
62     /* Use char instead of Boolean for atomic operation. */
63     volatile char           pahsc_IsRecording;   /* Recording in progress. Set by foreground. Cleared by background. */
64     volatile char           pahsc_StopRecording; /* Signal sent to background. */
65     volatile char           pahsc_IfInsideCallback;
66     /* Input */
67     SPB                     pahsc_InputParams;
68     SICompletionUPP         pahsc_InputCompletionProc;
69     MultiBuffer             pahsc_InputMultiBuffer;
70     int32                   pahsc_BytesPerInputHostBuffer;
71     int32                   pahsc_InputRefNum;
72     /* Output */
73     CmpSoundHeader          pahsc_SoundHeaders[PA_MAX_NUM_HOST_BUFFERS];
74     int32                   pahsc_BytesPerOutputHostBuffer;
75     SndChannelPtr           pahsc_Channel;
76     SndCallBackUPP          pahsc_OutputCompletionProc;
77     int32                   pahsc_NumOutsQueued;
78     int32                   pahsc_NumOutsPlayed;
79     PaTimestamp             pahsc_NumFramesDone;
80     UInt64                  pahsc_WhenFramesDoneIncremented;
81     /* Init Time -------------- */
82     int32                   pahsc_NumHostBuffers;
83     int32                   pahsc_FramesPerHostBuffer;
84     int32                   pahsc_UserBuffersPerHostBuffer;
85     int32                   pahsc_MinFramesPerHostBuffer; /* Can vary depending on virtual memory usage. */
86 }
87 PaHostSoundControl;
88
89 typedef struct PxSource
90 {
91    char name[256];
92 } PxSource;
93
94 typedef struct PxInfo
95 {
96    SPB           *input;
97    int32          inputRefNum;
98    SndChannelPtr  output;
99    int32          numSources;
100    PxSource      *sources;
101 } PxInfo;
102
103 int Px_GetNumMixers( void *pa_stream )
104 {
105    return 0;
106 }
107
108 const char *Px_GetMixerName( void *pa_stream, int index )
109 {
110    return "Mac Sound Manager";
111 }
112
113 PxMixer *Px_OpenMixer( void *pa_stream, int index )
114 {
115    PxInfo                      *info;
116    internalPortAudioStream     *past;
117    PaHostSoundControl          *macInfo;
118    OSErr                        err;
119    int                          i, j;
120    Handle                       h;
121    unsigned char               *data;
122    
123    info = (PxInfo *)malloc(sizeof(PxInfo));   
124    past = (internalPortAudioStream *) pa_stream;
125    macInfo = (PaHostSoundControl *) past->past_DeviceData;
126
127    info->input = &macInfo->pahsc_InputParams;
128    info->inputRefNum = macInfo->pahsc_InputRefNum;
129    info->output = macInfo->pahsc_Channel;
130
131    info->numSources = 0;
132    info->sources = NULL;
133    
134    err = SPBGetDeviceInfo (info->inputRefNum, siInputSourceNames, &h);
135    if (err)
136       return (PxMixer *)info;
137    
138    HLock(h);
139    HNoPurge(h);
140    
141    data = (unsigned char *)*h;
142    info->numSources = ((short *)data)[0];
143    if (info->numSources <= 0 || info->numSources > 50) {
144       HUnlock(h);
145       return (PxMixer *)info;
146    }
147    
148    info->sources = (PxSource *)malloc(info->numSources * sizeof(PxSource));
149    data += 2;
150    for(i=0; i<info->numSources; i++) {
151       int len = *data++;
152       
153       if (len > 63) {
154          info->numSources = 0;
155          free(info->sources);
156          info->sources = NULL;
157          HUnlock(h);
158          return (PxMixer *)info;
159       }
160
161       for(j=0; j<len; j++)
162          info->sources[i].name[j] = *data++;
163
164       info->sources[i].name[len] = 0;
165    }
166    HUnlock(h);
167    
168    return (PxMixer *)info;
169 }
170
171 /*
172  Px_CloseMixer() closes a mixer opened using Px_OpenMixer and frees any
173  memory associated with it. 
174 */
175
176 void Px_CloseMixer(PxMixer *mixer)
177 {
178    PxInfo *info = (PxInfo *)mixer;
179    
180    if (info->sources)
181       free(info->sources);
182    free(info);
183 }
184
185 /*
186  Master (output) volume
187 */
188
189 PxVolume Px_GetMasterVolume( PxMixer *mixer )
190 {
191    PxInfo *info = (PxInfo *)mixer;
192
193    return 0.0;
194 }
195
196 void Px_SetMasterVolume( PxMixer *mixer, PxVolume volume )
197 {
198    PxInfo *info = (PxInfo *)mixer;
199 }
200
201 /*
202  PCM output volume
203 */
204
205 int Px_SupportsPCMOutputVolume( PxMixer* mixer ) 
206 {
207         return 1 ; 
208 }
209
210 PxVolume Px_GetPCMOutputVolume( PxMixer *mixer )
211 {
212    PxInfo *info = (PxInfo *)mixer;
213    OSErr err;
214    long packedVol;
215    SndCommand cmd;
216
217    cmd.cmd = getVolumeCmd;
218    cmd.param1 = 0;
219    cmd.param2 = (long)&packedVol;
220    
221    err = SndDoImmediate(info->output, &cmd);
222    if (err)
223       return 0.0;
224    
225    return ((packedVol & 0xFFFF) + ((packedVol & 0xFFFF0000) >> 16) / 2.0) / 256.0;
226 }
227
228 void Px_SetPCMOutputVolume( PxMixer *mixer, PxVolume volume )
229 {
230    PxInfo *info = (PxInfo *)mixer;
231    OSErr err;
232    long packedVol;
233    SndCommand cmd;
234
235    packedVol = (unsigned long)volume * 256.0;
236    packedVol += (packedVol << 16);
237    
238    cmd.cmd = volumeCmd;
239    cmd.param1 = 0;
240    cmd.param2 = packedVol;
241    err = SndDoImmediate(info->output, &cmd);
242 }
243
244 /*
245  All output volumes
246 */
247
248 int Px_GetNumOutputVolumes( PxMixer *mixer )
249 {
250    PxInfo *info = (PxInfo *)mixer;
251
252    return 0;
253 }
254
255 const char *Px_GetOutputVolumeName( PxMixer *mixer, int i )
256 {
257    PxInfo *info = (PxInfo *)mixer;
258    
259    return NULL;
260 }
261
262 PxVolume Px_GetOutputVolume( PxMixer *mixer, int i )
263 {
264    PxInfo *info = (PxInfo *)mixer;
265
266    return NULL;
267 }
268
269 void Px_SetOutputVolume( PxMixer *mixer, int i, PxVolume volume )
270 {
271    PxInfo *info = (PxInfo *)mixer;
272 }
273
274 /*
275  Input sources
276 */
277
278 int Px_GetNumInputSources( PxMixer *mixer )
279 {
280    PxInfo *info = (PxInfo *)mixer;
281    
282    return info->numSources;
283 }
284
285 const char *Px_GetInputSourceName( PxMixer *mixer, int i)
286 {
287    PxInfo *info = (PxInfo *)mixer;
288    
289    if (i >= 0 && i < info->numSources)
290       return info->sources[i].name;
291    else
292       return "";
293 }
294
295 int Px_GetCurrentInputSource( PxMixer *mixer )
296 {
297    PxInfo *info = (PxInfo *)mixer;
298    short selected;
299    OSErr err;
300
301    err = SPBGetDeviceInfo (info->inputRefNum, siInputSource, &selected);
302    if (err)
303       return 0;
304
305    return selected - 1;
306 }
307
308 void Px_SetCurrentInputSource( PxMixer *mixer, int i )
309 {
310    PxInfo *info = (PxInfo *)mixer;
311    short selected = i+1;
312    OSErr err;
313    
314    err = SPBSetDeviceInfo (info->inputRefNum, siInputSource, &selected);
315 }
316
317 /*
318  Input volume
319 */
320
321 PxVolume Px_GetInputVolume( PxMixer *mixer )
322 {
323    PxInfo *info = (PxInfo *)mixer;
324    Fixed fixedGain;
325    PxVolume vol;
326    OSErr err;
327    
328    if (info->input) {
329       err = SPBGetDeviceInfo(info->inputRefNum, siInputGain, (Ptr)&fixedGain);
330       if (err)
331          return 0.0;
332       
333       vol = (fixedGain / 65536.0) - 0.5;
334       return vol;
335    }
336
337    return 0.0;
338 }
339
340 void Px_SetInputVolume( PxMixer *mixer, PxVolume volume )
341 {
342    PxInfo *info = (PxInfo *)mixer;
343    Fixed fixedGain;
344    OSErr err;
345    
346    if (info->input) {
347       fixedGain = (Fixed)((volume + 0.5) * 65536.0);
348       err = SPBSetDeviceInfo(info->inputRefNum, siInputGain, (Ptr)&fixedGain);
349    }
350 }
351
352 /*
353   Balance
354 */
355
356 int Px_SupportsOutputBalance( PxMixer *mixer )
357 {
358    return 0;
359 }
360
361 PxBalance Px_GetOutputBalance( PxMixer *mixer )
362 {
363    return 0.0;
364 }
365
366 void Px_SetOutputBalance( PxMixer *mixer, PxBalance balance )
367 {
368 }
369
370 /*
371   Playthrough
372 */
373
374 int Px_SupportsPlaythrough( PxMixer *mixer )
375 {
376    PxInfo *info = (PxInfo *)mixer;
377
378    return (info->input != NULL);
379 }
380
381 PxVolume Px_GetPlaythrough( PxMixer *mixer )
382 {
383    PxInfo *info = (PxInfo *)mixer;
384    OSErr err;
385    short level;
386
387    err = SPBGetDeviceInfo(info->inputRefNum, siPlayThruOnOff, (Ptr)&level);
388    if (err)
389       return 0.0;
390
391    if (level < 0)
392       level = 0;
393    if (level > 7)
394       level = 7;
395    
396    return (PxVolume)(level / 7.0);
397 }
398
399 void Px_SetPlaythrough( PxMixer *mixer, PxVolume volume )
400 {
401    PxInfo *info = (PxInfo *)mixer;
402    OSErr err;
403    short level = (int)(volume * 7.0 + 0.5);
404
405    err = SPBSetDeviceInfo(info->inputRefNum, siPlayThruOnOff, (Ptr)&level);
406 }