ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/audio.cpp
Revision: 1.15
Committed: 2005-01-30T21:42:13Z (19 years, 3 months ago) by gbeauche
Branch: MAIN
CVS Tags: nigel-build-19, nigel-build-17
Changes since 1.14: +1 -1 lines
Log Message:
Happy New Year!

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * audio.cpp - Audio support
3     *
4 gbeauche 1.15 * Basilisk II (C) 1997-2005 Christian Bauer
5 cebix 1.10 * Portions written by Marc Hellwig
6 cebix 1.1 *
7     * This program is free software; you can redistribute it and/or modify
8     * it under the terms of the GNU General Public License as published by
9     * the Free Software Foundation; either version 2 of the License, or
10     * (at your option) any later version.
11     *
12     * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20     */
21    
22     /*
23     * SEE ALSO
24     * Inside Macintosh: Sound, chapter 5 "Sound Components"
25     */
26    
27     #include "sysdeps.h"
28     #include "cpu_emulation.h"
29     #include "macos_util.h"
30     #include "emul_op.h"
31     #include "main.h"
32     #include "audio.h"
33     #include "audio_defs.h"
34    
35     #define DEBUG 0
36     #include "debug.h"
37    
38    
39 cebix 1.8 // Supported sample rates, sizes and channels
40     vector<uint32> audio_sample_rates;
41     vector<uint16> audio_sample_sizes;
42     vector<uint16> audio_channel_counts;
43    
44 cebix 1.1 // Global variables
45     struct audio_status AudioStatus; // Current audio status (sample rate etc.)
46     bool audio_open = false; // Flag: audio is initialized and ready
47     int audio_frames_per_block; // Number of audio frames per block
48     uint32 audio_component_flags; // Component feature flags
49     uint32 audio_data = 0; // Mac address of global data area
50     static int open_count = 0; // Open/close nesting count
51    
52     bool AudioAvailable = false; // Flag: audio output available (from the software point of view)
53    
54    
55     /*
56 cebix 1.4 * Reset audio emulation
57     */
58    
59     void AudioReset(void)
60     {
61     audio_data = 0;
62     }
63    
64    
65     /*
66 cebix 1.1 * Get audio info
67     */
68    
69     static int32 AudioGetInfo(uint32 infoPtr, uint32 selector, uint32 sourceID)
70     {
71     D(bug(" AudioGetInfo %c%c%c%c, infoPtr %08lx, source ID %08lx\n", selector >> 24, (selector >> 16) & 0xff, (selector >> 8) & 0xff, selector & 0xff, infoPtr, sourceID));
72     M68kRegisters r;
73    
74     switch (selector) {
75     case siSampleSize:
76     WriteMacInt16(infoPtr, AudioStatus.sample_size);
77     break;
78    
79     case siSampleSizeAvailable: {
80 cebix 1.8 r.d[0] = audio_sample_sizes.size() * 2;
81 cebix 1.1 Execute68kTrap(0xa122, &r); // NewHandle()
82     uint32 h = r.a[0];
83     if (h == 0)
84     return memFullErr;
85 cebix 1.8 WriteMacInt16(infoPtr + sil_count, audio_sample_sizes.size());
86 cebix 1.1 WriteMacInt32(infoPtr + sil_infoHandle, h);
87     uint32 sp = ReadMacInt32(h);
88 cebix 1.9 for (unsigned i=0; i<audio_sample_sizes.size(); i++)
89 cebix 1.1 WriteMacInt16(sp + i*2, audio_sample_sizes[i]);
90     break;
91     }
92    
93     case siNumberChannels:
94     WriteMacInt16(infoPtr, AudioStatus.channels);
95     break;
96    
97     case siChannelAvailable: {
98 cebix 1.8 r.d[0] = audio_channel_counts.size() * 2;
99 cebix 1.1 Execute68kTrap(0xa122, &r); // NewHandle()
100     uint32 h = r.a[0];
101     if (h == 0)
102     return memFullErr;
103 cebix 1.8 WriteMacInt16(infoPtr + sil_count, audio_channel_counts.size());
104 cebix 1.1 WriteMacInt32(infoPtr + sil_infoHandle, h);
105     uint32 sp = ReadMacInt32(h);
106 cebix 1.9 for (unsigned i=0; i<audio_channel_counts.size(); i++)
107 cebix 1.1 WriteMacInt16(sp + i*2, audio_channel_counts[i]);
108     break;
109     }
110    
111     case siSampleRate:
112     WriteMacInt32(infoPtr, AudioStatus.sample_rate);
113     break;
114    
115     case siSampleRateAvailable: {
116 cebix 1.8 r.d[0] = audio_sample_rates.size() * 4;
117 cebix 1.1 Execute68kTrap(0xa122, &r); // NewHandle()
118     uint32 h = r.a[0];
119     if (h == 0)
120     return memFullErr;
121 cebix 1.8 WriteMacInt16(infoPtr + sil_count, audio_sample_rates.size());
122 cebix 1.1 WriteMacInt32(infoPtr + sil_infoHandle, h);
123     uint32 lp = ReadMacInt32(h);
124 cebix 1.9 for (unsigned i=0; i<audio_sample_rates.size(); i++)
125 cebix 1.1 WriteMacInt32(lp + i*4, audio_sample_rates[i]);
126     break;
127     }
128    
129     case siSpeakerMute:
130 cebix 1.2 WriteMacInt16(infoPtr, audio_get_speaker_mute());
131 cebix 1.1 break;
132    
133     case siSpeakerVolume:
134 cebix 1.2 WriteMacInt32(infoPtr, audio_get_speaker_volume());
135     break;
136    
137 cebix 1.1 case siHardwareMute:
138 cebix 1.2 WriteMacInt16(infoPtr, audio_get_main_mute());
139 cebix 1.1 break;
140    
141     case siHardwareVolume:
142 cebix 1.2 WriteMacInt32(infoPtr, audio_get_main_volume());
143     break;
144    
145     case siHardwareVolumeSteps:
146 cebix 1.11 WriteMacInt16(infoPtr, 7);
147 cebix 1.1 break;
148    
149     case siHardwareBusy:
150     WriteMacInt16(infoPtr, AudioStatus.num_sources != 0);
151     break;
152    
153 cebix 1.11 case siHardwareFormat:
154     WriteMacInt32(infoPtr + scd_flags, 0);
155     WriteMacInt32(infoPtr + scd_format, AudioStatus.sample_size == 16 ? FOURCC('t','w','o','s') : FOURCC('r','a','w',' '));
156     WriteMacInt16(infoPtr + scd_numChannels, AudioStatus.channels);
157     WriteMacInt16(infoPtr + scd_sampleSize, AudioStatus.sample_size);
158     WriteMacInt32(infoPtr + scd_sampleRate, AudioStatus.sample_rate);
159     WriteMacInt32(infoPtr + scd_sampleCount, audio_frames_per_block);
160     WriteMacInt32(infoPtr + scd_buffer, 0);
161     WriteMacInt32(infoPtr + scd_reserved, 0);
162     break;
163    
164 cebix 1.1 default: // Delegate to Apple Mixer
165     if (AudioStatus.mixer == 0)
166     return badComponentSelector;
167     M68kRegisters r;
168     r.a[0] = infoPtr;
169     r.d[0] = selector;
170     r.a[1] = sourceID;
171     r.a[2] = AudioStatus.mixer;
172     Execute68k(audio_data + adatGetInfo, &r);
173     D(bug(" delegated to Apple Mixer, returns %08lx\n", r.d[0]));
174     return r.d[0];
175     }
176     return noErr;
177     }
178    
179    
180     /*
181     * Set audio info
182     */
183    
184     static int32 AudioSetInfo(uint32 infoPtr, uint32 selector, uint32 sourceID)
185     {
186     D(bug(" AudioSetInfo %c%c%c%c, infoPtr %08lx, source ID %08lx\n", selector >> 24, (selector >> 16) & 0xff, (selector >> 8) & 0xff, selector & 0xff, infoPtr, sourceID));
187     M68kRegisters r;
188    
189     switch (selector) {
190     case siSampleSize:
191     D(bug(" set sample size %08lx\n", infoPtr));
192     if (AudioStatus.num_sources)
193     return siDeviceBusyErr;
194 cebix 1.8 if (infoPtr == AudioStatus.sample_size)
195     return noErr;
196 cebix 1.9 for (unsigned i=0; i<audio_sample_sizes.size(); i++)
197 cebix 1.1 if (audio_sample_sizes[i] == infoPtr) {
198 cebix 1.8 if (audio_set_sample_size(i))
199     return noErr;
200     else
201     return siInvalidSampleSize;
202 cebix 1.1 }
203     return siInvalidSampleSize;
204    
205     case siSampleRate:
206     D(bug(" set sample rate %08lx\n", infoPtr));
207     if (AudioStatus.num_sources)
208     return siDeviceBusyErr;
209 cebix 1.8 if (infoPtr == AudioStatus.sample_rate)
210     return noErr;
211 cebix 1.9 for (unsigned i=0; i<audio_sample_rates.size(); i++)
212 cebix 1.1 if (audio_sample_rates[i] == infoPtr) {
213 cebix 1.8 if (audio_set_sample_rate(i))
214     return noErr;
215     else
216     return siInvalidSampleRate;
217 cebix 1.1 }
218     return siInvalidSampleRate;
219    
220     case siNumberChannels:
221     D(bug(" set number of channels %08lx\n", infoPtr));
222     if (AudioStatus.num_sources)
223     return siDeviceBusyErr;
224 cebix 1.8 if (infoPtr == AudioStatus.channels)
225     return noErr;
226 cebix 1.9 for (unsigned i=0; i<audio_channel_counts.size(); i++)
227 cebix 1.1 if (audio_channel_counts[i] == infoPtr) {
228 cebix 1.8 if (audio_set_channels(i))
229     return noErr;
230     else
231     return badChannel;
232 cebix 1.1 }
233     return badChannel;
234    
235     case siSpeakerMute:
236 cebix 1.2 audio_set_speaker_mute((uint16)infoPtr);
237 cebix 1.1 break;
238    
239     case siSpeakerVolume:
240     D(bug(" set speaker volume %08lx\n", infoPtr));
241 cebix 1.2 audio_set_speaker_volume(infoPtr);
242     break;
243    
244 cebix 1.1 case siHardwareMute:
245 cebix 1.2 audio_set_main_mute((uint16)infoPtr);
246 cebix 1.1 break;
247    
248     case siHardwareVolume:
249     D(bug(" set hardware volume %08lx\n", infoPtr));
250 cebix 1.2 audio_set_main_volume(infoPtr);
251 cebix 1.1 break;
252    
253     default: // Delegate to Apple Mixer
254     if (AudioStatus.mixer == 0)
255     return badComponentSelector;
256     r.a[0] = infoPtr;
257     r.d[0] = selector;
258     r.a[1] = sourceID;
259     r.a[2] = AudioStatus.mixer;
260     Execute68k(audio_data + adatSetInfo, &r);
261     D(bug(" delegated to Apple Mixer, returns %08lx\n", r.d[0]));
262     return r.d[0];
263     }
264     return noErr;
265     }
266    
267    
268     /*
269     * Sound output component dispatch
270     */
271    
272     int32 AudioDispatch(uint32 params, uint32 globals)
273     {
274     D(bug("AudioDispatch params %08lx (size %d), what %d\n", params, ReadMacInt8(params + cp_paramSize), (int16)ReadMacInt16(params + cp_what)));
275     M68kRegisters r;
276     uint32 p = params + cp_params;
277 cebix 1.11 int16 selector = (int16)ReadMacInt16(params + cp_what);
278    
279     switch (selector) {
280 cebix 1.1
281 cebix 1.11 // General component functions
282 cebix 1.1 case kComponentOpenSelect:
283     if (audio_data == 0) {
284    
285     // Allocate global data area
286     r.d[0] = SIZEOF_adat;
287 cebix 1.11 Execute68kTrap(0xa040, &r); // ResrvMem()
288     r.d[0] = SIZEOF_adat;
289     Execute68kTrap(0xa31e, &r); // NewPtrClear()
290 cebix 1.1 if (r.a[0] == 0)
291     return memFullErr;
292     audio_data = r.a[0];
293     D(bug(" global data at %08lx\n", audio_data));
294    
295     // Put in 68k routines
296     int p = audio_data + adatDelegateCall;
297     WriteMacInt16(p, 0x598f); p += 2; // subq.l #4,sp
298     WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
299     WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
300     WriteMacInt16(p, 0x7024); p += 2; // moveq #$24,d0
301     WriteMacInt16(p, 0xa82a); p += 2; // ComponentDispatch
302     WriteMacInt16(p, 0x201f); p += 2; // move.l (sp)+,d0
303     WriteMacInt16(p, M68K_RTS); p += 2; // rts
304     if (p - audio_data != adatOpenMixer)
305     goto adat_error;
306     WriteMacInt16(p, 0x558f); p += 2; // subq.l #2,sp
307     WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
308     WriteMacInt16(p, 0x2f00); p += 2; // move.l d0,-(sp)
309     WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
310     WriteMacInt16(p, 0x203c); p += 2; // move.l #$06140018,d0
311     WriteMacInt32(p, 0x06140018); p+= 4;
312     WriteMacInt16(p, 0xa800); p += 2; // SoundDispatch
313     WriteMacInt16(p, 0x301f); p += 2; // move.w (sp)+,d0
314     WriteMacInt16(p, 0x48c0); p += 2; // ext.l d0
315     WriteMacInt16(p, M68K_RTS); p += 2; // rts
316     if (p - audio_data != adatCloseMixer)
317     goto adat_error;
318     WriteMacInt16(p, 0x558f); p += 2; // subq.l #2,sp
319     WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
320     WriteMacInt16(p, 0x203c); p += 2; // move.l #$02180018,d0
321     WriteMacInt32(p, 0x02180018); p+= 4;
322     WriteMacInt16(p, 0xa800); p += 2; // SoundDispatch
323     WriteMacInt16(p, 0x301f); p += 2; // move.w (sp)+,d0
324     WriteMacInt16(p, 0x48c0); p += 2; // ext.l d0
325     WriteMacInt16(p, M68K_RTS); p += 2; // rts
326     if (p - audio_data != adatGetInfo)
327     goto adat_error;
328     WriteMacInt16(p, 0x598f); p += 2; // subq.l #4,sp
329     WriteMacInt16(p, 0x2f0a); p += 2; // move.l a2,-(sp)
330     WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
331     WriteMacInt16(p, 0x2f00); p += 2; // move.l d0,-(sp)
332     WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
333     WriteMacInt16(p, 0x2f3c); p += 2; // move.l #$000c0103,-(sp)
334     WriteMacInt32(p, 0x000c0103); p+= 4;
335     WriteMacInt16(p, 0x7000); p += 2; // moveq #0,d0
336     WriteMacInt16(p, 0xa82a); p += 2; // ComponentDispatch
337     WriteMacInt16(p, 0x201f); p += 2; // move.l (sp)+,d0
338     WriteMacInt16(p, M68K_RTS); p += 2; // rts
339     if (p - audio_data != adatSetInfo)
340     goto adat_error;
341     WriteMacInt16(p, 0x598f); p += 2; // subq.l #4,sp
342     WriteMacInt16(p, 0x2f0a); p += 2; // move.l a2,-(sp)
343     WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
344     WriteMacInt16(p, 0x2f00); p += 2; // move.l d0,-(sp)
345     WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
346     WriteMacInt16(p, 0x2f3c); p += 2; // move.l #$000c0104,-(sp)
347     WriteMacInt32(p, 0x000c0104); p+= 4;
348     WriteMacInt16(p, 0x7000); p += 2; // moveq #0,d0
349     WriteMacInt16(p, 0xa82a); p += 2; // ComponentDispatch
350     WriteMacInt16(p, 0x201f); p += 2; // move.l (sp)+,d0
351     WriteMacInt16(p, M68K_RTS); p += 2; // rts
352     if (p - audio_data != adatPlaySourceBuffer)
353     goto adat_error;
354     WriteMacInt16(p, 0x598f); p += 2; // subq.l #4,sp
355     WriteMacInt16(p, 0x2f0a); p += 2; // move.l a2,-(sp)
356     WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
357     WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
358     WriteMacInt16(p, 0x2f00); p += 2; // move.l d0,-(sp)
359     WriteMacInt16(p, 0x2f3c); p += 2; // move.l #$000c0108,-(sp)
360     WriteMacInt32(p, 0x000c0108); p+= 4;
361     WriteMacInt16(p, 0x7000); p += 2; // moveq #0,d0
362     WriteMacInt16(p, 0xa82a); p += 2; // ComponentDispatch
363     WriteMacInt16(p, 0x201f); p += 2; // move.l (sp)+,d0
364     WriteMacInt16(p, M68K_RTS); p += 2; // rts
365     if (p - audio_data != adatGetSourceData)
366     goto adat_error;
367     WriteMacInt16(p, 0x598f); p += 2; // subq.l #4,sp
368     WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
369     WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
370     WriteMacInt16(p, 0x2f3c); p += 2; // move.l #$00040004,-(sp)
371     WriteMacInt32(p, 0x00040004); p+= 4;
372     WriteMacInt16(p, 0x7000); p += 2; // moveq #0,d0
373     WriteMacInt16(p, 0xa82a); p += 2; // ComponentDispatch
374     WriteMacInt16(p, 0x201f); p += 2; // move.l (sp)+,d0
375     WriteMacInt16(p, M68K_RTS); p += 2; // rts
376 cebix 1.11 if (p - audio_data != adatStartSource)
377     goto adat_error;
378     WriteMacInt16(p, 0x598f); p += 2; // subq.l #4,sp
379     WriteMacInt16(p, 0x2f09); p += 2; // move.l a1,-(sp)
380     WriteMacInt16(p, 0x3f00); p += 2; // move.w d0,-(sp)
381     WriteMacInt16(p, 0x2f08); p += 2; // move.l a0,-(sp)
382     WriteMacInt16(p, 0x2f3c); p += 2; // move.l #$00060105,-(sp)
383     WriteMacInt32(p, 0x00060105); p+= 4;
384     WriteMacInt16(p, 0x7000); p += 2; // moveq #0,d0
385     WriteMacInt16(p, 0xa82a); p += 2; // ComponentDispatch
386     WriteMacInt16(p, 0x201f); p += 2; // move.l (sp)+,d0
387     WriteMacInt16(p, M68K_RTS); p += 2; // rts
388 cebix 1.1 if (p - audio_data != adatData)
389     goto adat_error;
390     }
391     AudioAvailable = true;
392     if (open_count == 0)
393     audio_enter_stream();
394     open_count++;
395     return noErr;
396    
397     adat_error: printf("FATAL: audio component data block initialization error\n");
398     QuitEmulator();
399     return openErr;
400    
401     case kComponentCloseSelect:
402     open_count--;
403     if (open_count == 0) {
404 cebix 1.11 if (audio_data) {
405     if (AudioStatus.mixer) {
406     // Close Apple Mixer
407     r.a[0] = AudioStatus.mixer;
408     Execute68k(audio_data + adatCloseMixer, &r);
409     AudioStatus.mixer = 0;
410     return r.d[0];
411     }
412     r.a[0] = audio_data;
413     Execute68kTrap(0xa01f, &r); // DisposePtr()
414     audio_data = 0;
415 cebix 1.1 }
416     AudioStatus.num_sources = 0;
417     audio_exit_stream();
418     }
419     return noErr;
420    
421 cebix 1.11 case kComponentCanDoSelect:
422     switch ((int16)ReadMacInt16(p)) {
423     case kComponentOpenSelect:
424     case kComponentCloseSelect:
425     case kComponentCanDoSelect:
426     case kComponentVersionSelect:
427     case kComponentRegisterSelect:
428     case kSoundComponentInitOutputDeviceSelect:
429     case kSoundComponentGetSourceSelect:
430     case kSoundComponentGetInfoSelect:
431     case kSoundComponentSetInfoSelect:
432     case kSoundComponentStartSourceSelect:
433     return 1;
434     default:
435     return 0;
436     }
437    
438     case kComponentVersionSelect:
439     return 0x00010003;
440    
441     case kComponentRegisterSelect:
442     return noErr;
443    
444     // Sound component functions (not delegated)
445 cebix 1.1 case kSoundComponentInitOutputDeviceSelect:
446     D(bug(" InitOutputDevice\n"));
447     if (!audio_open)
448     return noHardwareErr;
449     if (AudioStatus.mixer)
450     return noErr;
451    
452     // Init sound component data
453     WriteMacInt32(audio_data + adatData + scd_flags, 0);
454 cebix 1.5 WriteMacInt32(audio_data + adatData + scd_format, AudioStatus.sample_size == 16 ? FOURCC('t','w','o','s') : FOURCC('r','a','w',' '));
455 cebix 1.1 WriteMacInt16(audio_data + adatData + scd_numChannels, AudioStatus.channels);
456     WriteMacInt16(audio_data + adatData + scd_sampleSize, AudioStatus.sample_size);
457     WriteMacInt32(audio_data + adatData + scd_sampleRate, AudioStatus.sample_rate);
458     WriteMacInt32(audio_data + adatData + scd_sampleCount, audio_frames_per_block);
459     WriteMacInt32(audio_data + adatData + scd_buffer, 0);
460     WriteMacInt32(audio_data + adatData + scd_reserved, 0);
461     WriteMacInt32(audio_data + adatStreamInfo, 0);
462    
463     // Open Apple Mixer
464     r.a[0] = audio_data + adatMixer;
465     r.d[0] = 0;
466     r.a[1] = audio_data + adatData;
467     Execute68k(audio_data + adatOpenMixer, &r);
468     AudioStatus.mixer = ReadMacInt32(audio_data + adatMixer);
469     D(bug(" OpenMixer() returns %08lx, mixer %08lx\n", r.d[0], AudioStatus.mixer));
470     return r.d[0];
471    
472 cebix 1.11 case kSoundComponentGetSourceSelect:
473     D(bug(" GetSource source %08lx\n", ReadMacInt32(p)));
474     WriteMacInt32(ReadMacInt32(p), AudioStatus.mixer);
475     return noErr;
476    
477     // Sound component functions (delegated)
478 cebix 1.1 case kSoundComponentAddSourceSelect:
479     D(bug(" AddSource\n"));
480     AudioStatus.num_sources++;
481     goto delegate;
482    
483     case kSoundComponentRemoveSourceSelect:
484     D(bug(" RemoveSource\n"));
485     AudioStatus.num_sources--;
486     goto delegate;
487    
488 cebix 1.11 case kSoundComponentGetInfoSelect:
489     return AudioGetInfo(ReadMacInt32(p), ReadMacInt32(p + 4), ReadMacInt32(p + 8));
490    
491     case kSoundComponentSetInfoSelect:
492     return AudioSetInfo(ReadMacInt32(p), ReadMacInt32(p + 4), ReadMacInt32(p + 8));
493    
494     case kSoundComponentStartSourceSelect:
495     D(bug(" StartSource count %d\n", ReadMacInt16(p + 4)));
496     D(bug(" starting Apple Mixer\n"));
497     r.d[0] = ReadMacInt16(p + 4);
498     r.a[0] = ReadMacInt32(p);
499     r.a[1] = AudioStatus.mixer;
500     Execute68k(audio_data + adatStartSource, &r);
501     D(bug(" returns %08lx\n", r.d[0]));
502     return noErr;
503    
504 cebix 1.1 case kSoundComponentStopSourceSelect:
505     D(bug(" StopSource\n"));
506     goto delegate;
507    
508     case kSoundComponentPauseSourceSelect:
509     D(bug(" PauseSource\n"));
510     delegate: // Delegate call to Apple Mixer
511     D(bug(" delegating call to Apple Mixer\n"));
512     r.a[0] = AudioStatus.mixer;
513     r.a[1] = params;
514     Execute68k(audio_data + adatDelegateCall, &r);
515     D(bug(" returns %08lx\n", r.d[0]));
516     return r.d[0];
517    
518     case kSoundComponentPlaySourceBufferSelect:
519 cebix 1.11 D(bug(" PlaySourceBuffer flags %08lx\n", ReadMacInt32(p)));
520 cebix 1.1 r.d[0] = ReadMacInt32(p);
521     r.a[0] = ReadMacInt32(p + 4);
522     r.a[1] = ReadMacInt32(p + 8);
523     r.a[2] = AudioStatus.mixer;
524     Execute68k(audio_data + adatPlaySourceBuffer, &r);
525     D(bug(" returns %08lx\n", r.d[0]));
526     return r.d[0];
527    
528     default:
529 cebix 1.11 if (selector >= 0x100)
530     goto delegate;
531     else
532     return badComponentSelector;
533 cebix 1.1 }
534     }
535 cebix 1.6
536    
537     /*
538     * Sound input driver Open() routine
539     */
540    
541     int16 SoundInOpen(uint32 pb, uint32 dce)
542     {
543     D(bug("SoundInOpen\n"));
544     return noErr;
545     }
546    
547    
548     /*
549     * Sound input driver Prime() routine
550     */
551    
552     int16 SoundInPrime(uint32 pb, uint32 dce)
553     {
554     D(bug("SoundInPrime\n"));
555     //!!
556     return paramErr;
557     }
558    
559    
560     /*
561     * Sound input driver Control() routine
562     */
563    
564     int16 SoundInControl(uint32 pb, uint32 dce)
565     {
566     uint16 code = ReadMacInt16(pb + csCode);
567     D(bug("SoundInControl %d\n", code));
568    
569     if (code == 1) {
570     D(bug(" SoundInKillIO\n"));
571     //!!
572     return noErr;
573     }
574    
575     if (code != 2)
576     return -231; // siUnknownInfoType
577    
578     uint32 *param = (uint32 *)Mac2HostAddr(pb + csParam);
579     uint32 selector = param[0];
580     D(bug(" selector %c%c%c%c\n", selector >> 24, selector >> 16, selector >> 8, selector));
581    
582     switch (selector) {
583     default:
584     return -231; // siUnknownInfoType
585     }
586     }
587    
588    
589     /*
590     * Sound input driver Status() routine
591     */
592    
593     int16 SoundInStatus(uint32 pb, uint32 dce)
594     {
595     uint16 code = ReadMacInt16(pb + csCode);
596     D(bug("SoundInStatus %d\n", code));
597     if (code != 2)
598     return -231; // siUnknownInfoType
599    
600     uint32 *param = (uint32 *)Mac2HostAddr(pb + csParam);
601     uint32 selector = param[0];
602     D(bug(" selector %c%c%c%c\n", selector >> 24, selector >> 16, selector >> 8, selector));
603     switch (selector) {
604     #if 0
605     case siDeviceName: {
606     const char *str = GetString(STR_SOUND_IN_NAME);
607     param[0] = 0;
608     memcpy((void *)param[1], str, strlen(str));
609     return noErr;
610     }
611    
612     case siDeviceIcon: {
613     M68kRegisters r;
614 gbeauche 1.12 static const uint8 proc[] = {
615     0x55, 0x8f, // subq.l #2,sp
616     0xa9, 0x94, // CurResFile
617     0x42, 0x67, // clr.w -(sp)
618     0xa9, 0x98, // UseResFile
619     0x59, 0x8f, // subq.l #4,sp
620     0x48, 0x79, 0x49, 0x43, 0x4e, 0x23, // move.l #'ICN#',-(sp)
621     0x3f, 0x3c, 0xbf, 0x76, // move.w #-16522,-(sp)
622     0xa9, 0xa0, // GetResource
623     0x24, 0x5f, // move.l (sp)+,a2
624     0xa9, 0x98, // UseResFile
625     0x20, 0x0a, // move.l a2,d0
626     0x66, 0x04, // bne 1
627     0x70, 0x00, // moveq #0,d0
628     M68K_RTS >> 8, M68K_RTS & 0xff,
629     0x2f, 0x0a, //1 move.l a2,-(sp)
630     0xa9, 0x92, // DetachResource
631     0x20, 0x4a, // move.l a2,a0
632     0xa0, 0x4a, // HNoPurge
633     0x70, 0x01, // moveq #1,d0
634     M68K_RTS >> 8, M68K_RTS & 0xff
635 cebix 1.6 };
636 gbeauche 1.14 Execute68k(Host2MacAddr((uint8 *)proc), &r);
637 cebix 1.6 if (r.d[0]) {
638     param[0] = 4; // Length of returned data
639     param[1] = r.a[2]; // Handle to icon suite
640     return noErr;
641     } else
642     return -192; // resNotFound
643     }
644     #endif
645     default:
646     return -231; // siUnknownInfoType
647     }
648     }
649    
650    
651     /*
652     * Sound input driver Close() routine
653     */
654    
655     int16 SoundInClose(uint32 pb, uint32 dce)
656     {
657     D(bug("SoundInClose\n"));
658     return noErr;
659     }