ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/BeOS/audio_beos.cpp
Revision: 1.10
Committed: 2008-01-01T09:40:32Z (16 years, 11 months ago) by gbeauche
Branch: MAIN
CVS Tags: HEAD
Changes since 1.9: +1 -1 lines
Log Message:
Happy New Year!

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * audio_beos.cpp - Audio support, BeOS implementation
3     *
4 gbeauche 1.10 * Basilisk II (C) 1997-2008 Christian Bauer
5 cebix 1.7 * 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     #include "sysdeps.h"
23    
24     #include <KernelKit.h>
25     #include <MediaKit.h>
26    
27     #include "cpu_emulation.h"
28     #include "main.h"
29     #include "prefs.h"
30     #include "user_strings.h"
31     #include "audio.h"
32     #include "audio_defs.h"
33    
34     #define DEBUG 0
35     #include "debug.h"
36    
37    
38     // Global variables
39     static int audio_irq_done_sem = -1; // Signal from interrupt to streaming thread: data block read
40     static BSoundPlayer *the_player;
41    
42     // Prototypes
43     static void playbuffer_func(void *arg, void *buf, size_t size, const media_raw_audio_format &format);
44    
45    
46     /*
47     * Audio manager thread (for calling media kit functions;
48     * this is not safe under R4 when running on the MacOS stack in kernel space)
49     */
50    
51     // Message constants
52     const uint32 MSG_QUIT_AUDIO_MANAGER = 'quit';
53     const uint32 MSG_ENTER_STREAM = 'entr';
54     const uint32 MSG_EXIT_STREAM = 'exit';
55     const uint32 MSG_GET_VOLUME = 'getv';
56     const uint32 MSG_SET_VOLUME = 'setv';
57    
58     static thread_id am_thread = -1;
59     static sem_id am_done_sem = -1;
60    
61     static volatile float am_volume;
62    
63     static status_t audio_manager(void *arg)
64     {
65     for (;;) {
66    
67     // Receive message
68     thread_id sender;
69     uint32 code = receive_data(&sender, NULL, 0);
70     D(bug("Audio manager received %08lx\n", code));
71     switch (code) {
72     case MSG_QUIT_AUDIO_MANAGER:
73     return 0;
74    
75     case MSG_ENTER_STREAM:
76     the_player->Start();
77     break;
78    
79     case MSG_EXIT_STREAM:
80     the_player->Stop();
81     break;
82    
83     case MSG_GET_VOLUME:
84     am_volume = the_player->Volume();
85     break;
86    
87     case MSG_SET_VOLUME:
88     the_player->SetVolume(am_volume);
89     break;
90     }
91    
92     // Acknowledge
93     release_sem(am_done_sem);
94     }
95     }
96    
97    
98     /*
99     * Initialization
100     */
101    
102 cebix 1.6 // Set AudioStatus to reflect current audio stream format
103     static void set_audio_status_format(void)
104 cebix 1.1 {
105     AudioStatus.sample_rate = audio_sample_rates[0];
106     AudioStatus.sample_size = audio_sample_sizes[0];
107     AudioStatus.channels = audio_channel_counts[0];
108 cebix 1.6 }
109    
110     void AudioInit(void)
111     {
112     // Init audio status and feature flags
113     audio_sample_rates.push_back(44100 << 16);
114     audio_sample_sizes.push_back(16);
115     audio_channel_counts.push_back(2);
116     set_audio_status_format();
117 cebix 1.1 AudioStatus.mixer = 0;
118     AudioStatus.num_sources = 0;
119     audio_component_flags = cmpWantsRegisterMessage | kStereoOut | k16BitOut;
120    
121     // Sound disabled in prefs? Then do nothing
122     if (PrefsFindBool("nosound"))
123     return;
124    
125     // Init semaphores
126     audio_irq_done_sem = create_sem(0, "Audio IRQ Done");
127     am_done_sem = create_sem(0, "Audio Manager Done");
128    
129     // Start audio manager thread
130     am_thread = spawn_thread(audio_manager, "Audio Manager", B_NORMAL_PRIORITY, NULL);
131     resume_thread(am_thread);
132    
133     // Start stream
134     media_raw_audio_format format;
135     format.frame_rate = AudioStatus.sample_rate >> 16;
136     format.channel_count = AudioStatus.channels;
137     format.format = media_raw_audio_format::B_AUDIO_SHORT;
138     format.byte_order = B_MEDIA_BIG_ENDIAN;
139     audio_frames_per_block = 4096;
140     size_t block_size = (AudioStatus.sample_size >> 3) * AudioStatus.channels * audio_frames_per_block;
141     D(bug("AudioInit: block size %d\n", block_size));
142     format.buffer_size = block_size;
143     the_player = new BSoundPlayer(&format, "MacOS Audio", playbuffer_func, NULL, NULL);
144     if (the_player->InitCheck() != B_NO_ERROR) {
145     printf("FATAL: Cannot initialize BSoundPlayer\n");
146     delete the_player;
147     the_player = NULL;
148     return;
149     } else
150     the_player->SetHasData(true);
151    
152     // Everything OK
153     audio_open = true;
154     }
155    
156    
157     /*
158     * Deinitialization
159     */
160    
161     void AudioExit(void)
162     {
163     // Stop stream
164     if (the_player) {
165     the_player->Stop();
166     delete the_player;
167     the_player = NULL;
168     }
169    
170     // Stop audio manager
171     if (am_thread > 0) {
172     status_t l;
173     send_data(am_thread, MSG_QUIT_AUDIO_MANAGER, NULL, 0);
174     wait_for_thread(am_thread, &l);
175     }
176    
177     // Delete semaphores
178     delete_sem(am_done_sem);
179     delete_sem(audio_irq_done_sem);
180     }
181    
182    
183     /*
184     * First source added, start audio stream
185     */
186    
187     void audio_enter_stream()
188     {
189     while (send_data(am_thread, MSG_ENTER_STREAM, NULL, 0) == B_INTERRUPTED) ;
190     while (acquire_sem(am_done_sem) == B_INTERRUPTED) ;
191     }
192    
193    
194     /*
195     * Last source removed, stop audio stream
196     */
197    
198     void audio_exit_stream()
199     {
200     while (send_data(am_thread, MSG_EXIT_STREAM, NULL, 0) == B_INTERRUPTED) ;
201     while (acquire_sem(am_done_sem) == B_INTERRUPTED) ;
202     }
203    
204    
205     /*
206     * Streaming function
207     */
208    
209     static uint32 apple_stream_info; // Mac address of SoundComponentData struct describing next buffer
210    
211     static void playbuffer_func(void *arg, void *buf, size_t size, const media_raw_audio_format &format)
212     {
213     // Check if new buffer is available
214     if (acquire_sem_etc(audio_irq_done_sem, 1, B_TIMEOUT, 0) == B_NO_ERROR) {
215    
216     // Get size of audio data
217     D(bug("stream: new buffer present\n"));
218     uint32 apple_stream_info = ReadMacInt32(audio_data + adatStreamInfo);
219     if (apple_stream_info) {
220     size_t work_size = ReadMacInt32(apple_stream_info + scd_sampleCount) * (AudioStatus.sample_size >> 3) * AudioStatus.channels;
221     D(bug("stream: size %d, work_size %d\n", size, work_size));
222     if (work_size > size)
223     work_size = size;
224    
225     if (format.format != media_raw_audio_format::B_AUDIO_SHORT) {
226     D(bug("Wrong audio format %04x\n", format.format));
227     return;
228     }
229    
230     // Place data into Media Kit buffer
231 cebix 1.3 Mac2Host_memcpy(buf, ReadMacInt32(apple_stream_info + scd_buffer), work_size);
232 cebix 1.1 if (work_size != size)
233     memset((uint8 *)buf + work_size, 0, size - work_size);
234     }
235    
236     } else
237     memset(buf, 0, size);
238    
239     // Trigger audio interrupt to get new buffer
240     if (AudioStatus.num_sources) {
241     D(bug("stream: triggering irq\n"));
242     SetInterruptFlag(INTFLAG_AUDIO);
243     TriggerInterrupt();
244     }
245     }
246    
247    
248     /*
249     * MacOS audio interrupt, read next data block
250     */
251    
252     void AudioInterrupt(void)
253     {
254     D(bug("AudioInterrupt\n"));
255    
256     // Get data from apple mixer
257     if (AudioStatus.mixer) {
258     M68kRegisters r;
259     r.a[0] = audio_data + adatStreamInfo;
260     r.a[1] = AudioStatus.mixer;
261     Execute68k(audio_data + adatGetSourceData, &r);
262     D(bug(" GetSourceData() returns %08lx\n", r.d[0]));
263     } else
264     WriteMacInt32(audio_data + adatStreamInfo, 0);
265    
266     // Signal stream function
267     release_sem(audio_irq_done_sem);
268     D(bug("AudioInterrupt done\n"));
269     }
270    
271    
272     /*
273     * Set sampling parameters
274     * "index" is an index into the audio_sample_rates[] etc. arrays
275     * It is guaranteed that AudioStatus.num_sources == 0
276     */
277    
278 cebix 1.6 bool audio_set_sample_rate(int index)
279 cebix 1.1 {
280 cebix 1.6 return true;
281 cebix 1.1 }
282    
283 cebix 1.6 bool audio_set_sample_size(int index)
284 cebix 1.1 {
285 cebix 1.6 return true;
286 cebix 1.1 }
287    
288 cebix 1.6 bool audio_set_channels(int index)
289 cebix 1.1 {
290 cebix 1.6 return true;
291 cebix 1.1 }
292    
293    
294     /*
295     * Get/set audio info
296     */
297    
298     bool audio_get_main_mute(void)
299     {
300     return false;
301     }
302    
303     uint32 audio_get_main_volume(void)
304     {
305     if (audio_open) {
306     while (send_data(am_thread, MSG_GET_VOLUME, NULL, 0) == B_INTERRUPTED) ;
307     while (acquire_sem(am_done_sem) == B_INTERRUPTED) ;
308     return int(am_volume * 256.0) * 0x00010001;
309     } else
310     return 0x01000100;
311     }
312    
313 cebix 1.2 bool audio_get_speaker_mute(void)
314 cebix 1.1 {
315     return false;
316     }
317    
318 cebix 1.2 uint32 audio_get_speaker_volume(void)
319 cebix 1.1 {
320     return 0x01000100;
321     }
322    
323     void audio_set_main_mute(bool mute)
324     {
325     }
326    
327     void audio_set_main_volume(uint32 vol)
328     {
329     if (audio_open) {
330     am_volume = float((vol >> 16) + (vol & 0xffff)) / 512.0;
331     while (send_data(am_thread, MSG_SET_VOLUME, NULL, 0) == B_INTERRUPTED) ;
332     while (acquire_sem(am_done_sem) == B_INTERRUPTED) ;
333     }
334     }
335    
336 cebix 1.2 void audio_set_speaker_mute(bool mute)
337 cebix 1.1 {
338     }
339    
340 cebix 1.2 void audio_set_speaker_volume(uint32 vol)
341 cebix 1.1 {
342     }