3 multi_channel_info chans
[] = {
4 { 0, B_MULTI_OUTPUT_CHANNEL
, B_CHANNEL_LEFT
| B_CHANNEL_STEREO_BUS
, 0 },
5 { 1, B_MULTI_OUTPUT_CHANNEL
, B_CHANNEL_RIGHT
| B_CHANNEL_STEREO_BUS
, 0 },
6 { 2, B_MULTI_INPUT_CHANNEL
, B_CHANNEL_LEFT
| B_CHANNEL_STEREO_BUS
, 0 },
7 { 3, B_MULTI_INPUT_CHANNEL
, B_CHANNEL_RIGHT
| B_CHANNEL_STEREO_BUS
, 0 },
8 { 4, B_MULTI_OUTPUT_BUS
, B_CHANNEL_LEFT
| B_CHANNEL_STEREO_BUS
, B_CHANNEL_MINI_JACK_STEREO
},
9 { 5, B_MULTI_OUTPUT_BUS
, B_CHANNEL_RIGHT
| B_CHANNEL_STEREO_BUS
, B_CHANNEL_MINI_JACK_STEREO
},
10 { 6, B_MULTI_INPUT_BUS
, B_CHANNEL_LEFT
| B_CHANNEL_STEREO_BUS
, B_CHANNEL_MINI_JACK_STEREO
},
11 { 7, B_MULTI_INPUT_BUS
, B_CHANNEL_RIGHT
| B_CHANNEL_STEREO_BUS
, B_CHANNEL_MINI_JACK_STEREO
},
15 format2size(uint32 format
)
28 get_description(sb16_dev_t
* dev
, multi_description
* data
)
30 data
->interface_version
= B_CURRENT_INTERFACE_VERSION
;
31 data
->interface_minimum
= B_CURRENT_INTERFACE_VERSION
;
33 strcpy(data
->friendly_name
,"SoundBlaster 16");
34 strcpy(data
->vendor_info
,"Haiku");
36 data
->output_channel_count
= 2;
37 data
->input_channel_count
= 2;
38 data
->output_bus_channel_count
= 2;
39 data
->input_bus_channel_count
= 2;
40 data
->aux_bus_channel_count
= 0;
42 if (data
->request_channel_count
>= (int)(sizeof(chans
) / sizeof(chans
[0]))) {
43 memcpy(data
->channels
,&chans
,sizeof(chans
));
46 /* determine output/input rates */
48 data
->input_rates
= B_SR_44100
| B_SR_22050
| B_SR_11025
;
50 data
->max_cvsr_rate
= 0;
51 data
->min_cvsr_rate
= 0;
53 data
->output_formats
=
54 data
->input_formats
= B_FMT_8BIT_S
| B_FMT_16BIT
;
55 data
->lock_sources
= B_MULTI_LOCK_INTERNAL
;
56 data
->timecode_sources
= 0;
57 data
->interface_flags
= B_MULTI_INTERFACE_PLAYBACK
| B_MULTI_INTERFACE_RECORD
;
58 data
->start_latency
= 30000;
60 strcpy(data
->control_panel
,"");
66 get_enabled_channels(sb16_dev_t
* dev
, multi_channel_enable
* data
)
68 B_SET_CHANNEL(data
->enable_bits
, 0, true);
69 B_SET_CHANNEL(data
->enable_bits
, 1, true);
70 B_SET_CHANNEL(data
->enable_bits
, 2, true);
71 B_SET_CHANNEL(data
->enable_bits
, 3, true);
72 data
->lock_source
= B_MULTI_LOCK_INTERNAL
;
78 get_global_format(sb16_dev_t
* dev
, multi_format_info
* data
)
80 data
->output_latency
= 0;
81 data
->input_latency
= 0;
82 data
->timecode_kind
= 0;
84 data
->output
.format
= dev
->playback_stream
.sampleformat
;
85 data
->output
.rate
= dev
->playback_stream
.samplerate
;
87 data
->input
.format
= dev
->record_stream
.sampleformat
;
88 data
->input
.rate
= dev
->record_stream
.samplerate
;
94 set_global_format(sb16_dev_t
* dev
, multi_format_info
* data
)
96 dev
->playback_stream
.sampleformat
= data
->output
.format
;
97 dev
->playback_stream
.samplerate
= data
->output
.rate
;
98 dev
->playback_stream
.sample_size
= format2size(dev
->playback_stream
.sampleformat
);
100 dev
->record_stream
.sampleformat
= data
->input
.format
;
101 dev
->record_stream
.samplerate
= data
->input
.rate
;
102 dev
->record_stream
.sample_size
= format2size(dev
->record_stream
.sampleformat
);
108 create_group_control(multi_mix_control
* multi
, int32 idx
, int32 parent
, int32 string
, const char* name
)
110 multi
->id
= SB16_MULTI_CONTROL_FIRSTID
+ idx
;
111 multi
->parent
= parent
;
112 multi
->flags
= B_MULTI_MIX_GROUP
;
113 multi
->master
= SB16_MULTI_CONTROL_MASTERID
;
114 multi
->string
= string
;
116 strcpy(multi
->name
, name
);
122 list_mix_controls(sb16_dev_t
* dev
, multi_mix_control_info
* data
)
126 parent
= create_group_control(data
->controls
+0, 0, 0, 0, "Record");
127 parent
= create_group_control(data
->controls
+1, 1, 0, 0, "AC97 Mixer");
128 parent
= create_group_control(data
->controls
+2, 2, 0, S_SETUP
, NULL
);
129 data
->control_count
= 3;
135 list_mix_connections(sb16_dev_t
* dev
, multi_mix_connection_info
* data
)
141 list_mix_channels(sb16_dev_t
* dev
, multi_mix_channel_info
*data
)
147 get_buffers(sb16_dev_t
* dev
, multi_buffer_list
* data
)
149 uint32 playback_sample_size
= dev
->playback_stream
.sample_size
;
150 uint32 record_sample_size
= dev
->record_stream
.sample_size
;
154 dprintf("%s: playback: %ld buffers, %ld channels, %ld samples\n", __func__
,
155 data
->request_playback_buffers
, data
->request_playback_channels
, data
->request_playback_buffer_size
);
156 dprintf("%s: record: %ld buffers, %ld channels, %ld samples\n", __func__
,
157 data
->request_record_buffers
, data
->request_record_channels
, data
->request_record_buffer_size
);
159 /* Workaround for Haiku multi_audio API, since it prefers to let the driver pick
160 values, while the BeOS multi_audio actually gives the user's defaults. */
161 if (data
->request_playback_buffers
> STRMAXBUF
||
162 data
->request_playback_buffers
< STRMINBUF
) {
163 data
->request_playback_buffers
= STRMINBUF
;
166 if (data
->request_record_buffers
> STRMAXBUF
||
167 data
->request_record_buffers
< STRMINBUF
) {
168 data
->request_record_buffers
= STRMINBUF
;
171 if (data
->request_playback_buffer_size
== 0)
172 data
->request_playback_buffer_size
= DEFAULT_FRAMESPERBUF
;
174 if (data
->request_record_buffer_size
== 0)
175 data
->request_record_buffer_size
= DEFAULT_FRAMESPERBUF
;
177 /* ... from here on, we can assume again that a reasonable request is being made */
181 /* Copy the requested settings into the streams */
182 dev
->playback_stream
.num_buffers
= data
->request_playback_buffers
;
183 dev
->playback_stream
.num_channels
= data
->request_playback_channels
;
184 dev
->playback_stream
.buffer_length
= data
->request_playback_buffer_size
;
185 if ((rc
=sb16_stream_setup_buffers(dev
, &dev
->playback_stream
, "Playback")) != B_OK
) {
186 dprintf("%s: Error setting up playback buffers (%s)\n", __func__
, strerror(rc
));
190 dev
->record_stream
.num_buffers
= data
->request_record_buffers
;
191 dev
->record_stream
.num_channels
= data
->request_record_channels
;
192 dev
->record_stream
.buffer_length
= data
->request_record_buffer_size
;
193 if ((rc
=sb16_stream_setup_buffers(dev
, &dev
->record_stream
, "Recording")) != B_OK
) {
194 dprintf("%s: Error setting up recording buffers (%s)\n", __func__
, strerror(rc
));
198 /* Setup data structure for multi_audio API... */
199 data
->return_playback_buffers
= data
->request_playback_buffers
;
200 data
->return_playback_channels
= data
->request_playback_channels
;
201 data
->return_playback_buffer_size
= data
->request_playback_buffer_size
; /* frames */
203 for (bidx
=0; bidx
< data
->return_playback_buffers
; bidx
++) {
204 for (cidx
=0; cidx
< data
->return_playback_channels
; cidx
++) {
205 data
->playback_buffers
[bidx
][cidx
].base
= dev
->playback_stream
.buffers
[bidx
] + (playback_sample_size
* cidx
);
206 data
->playback_buffers
[bidx
][cidx
].stride
= playback_sample_size
* data
->return_playback_channels
;
210 data
->return_record_buffers
= data
->request_record_buffers
;
211 data
->return_record_channels
= data
->request_record_channels
;
212 data
->return_record_buffer_size
= data
->request_record_buffer_size
; /* frames */
214 for (bidx
=0; bidx
< data
->return_record_buffers
; bidx
++) {
215 for (cidx
=0; cidx
< data
->return_record_channels
; cidx
++) {
216 data
->record_buffers
[bidx
][cidx
].base
= dev
->record_stream
.buffers
[bidx
] + (record_sample_size
* cidx
);
217 data
->record_buffers
[bidx
][cidx
].stride
= record_sample_size
* data
->return_record_channels
;
225 buffer_exchange(sb16_dev_t
* dev
, multi_buffer_info
* data
)
227 static int debug_buffers_exchanged
= 0;
231 if (!dev
->playback_stream
.running
)
232 sb16_stream_start(dev
, &dev
->playback_stream
);
235 rc
=acquire_sem(dev
->playback_stream
.buffer_ready_sem
);
237 dprintf("%s: Error waiting for playback buffer to finish (%s)!\n", __func__
,
242 status
= disable_interrupts();
243 acquire_spinlock(&dev
->playback_stream
.lock
);
245 data
->playback_buffer_cycle
= dev
->playback_stream
.buffer_cycle
;
246 data
->played_real_time
= dev
->playback_stream
.real_time
;
247 data
->played_frames_count
= dev
->playback_stream
.frames_count
;
249 release_spinlock(&dev
->playback_stream
.lock
);
250 restore_interrupts(status
);
252 debug_buffers_exchanged
++;
253 if (((debug_buffers_exchanged
% 100) == 1) && (debug_buffers_exchanged
< 1111)) {
254 dprintf("%s: %d buffers processed\n", __func__
, debug_buffers_exchanged
);
261 buffer_force_stop(sb16_dev_t
* dev
)
263 sb16_stream_stop(dev
, &dev
->playback_stream
);
264 sb16_stream_stop(dev
, &dev
->record_stream
);
266 delete_sem(dev
->playback_stream
.buffer_ready_sem
);
267 delete_sem(dev
->record_stream
.buffer_ready_sem
);
273 multi_audio_control(void* cookie
, uint32 op
, void* arg
, size_t len
)
276 case B_MULTI_GET_DESCRIPTION
: return get_description(cookie
, arg
);
277 case B_MULTI_GET_EVENT_INFO
: return B_ERROR
;
278 case B_MULTI_SET_EVENT_INFO
: return B_ERROR
;
279 case B_MULTI_GET_EVENT
: return B_ERROR
;
280 case B_MULTI_GET_ENABLED_CHANNELS
: return get_enabled_channels(cookie
, arg
);
281 case B_MULTI_SET_ENABLED_CHANNELS
: return B_OK
;
282 case B_MULTI_GET_GLOBAL_FORMAT
: return get_global_format(cookie
, arg
);
283 case B_MULTI_SET_GLOBAL_FORMAT
: return set_global_format(cookie
, arg
);
284 case B_MULTI_GET_CHANNEL_FORMATS
: return B_ERROR
;
285 case B_MULTI_SET_CHANNEL_FORMATS
: return B_ERROR
;
286 case B_MULTI_GET_MIX
: return B_ERROR
;
287 case B_MULTI_SET_MIX
: return B_ERROR
;
288 case B_MULTI_LIST_MIX_CHANNELS
: return list_mix_channels(cookie
, arg
);
289 case B_MULTI_LIST_MIX_CONTROLS
: return list_mix_controls(cookie
, arg
);
290 case B_MULTI_LIST_MIX_CONNECTIONS
: return list_mix_connections(cookie
, arg
);
291 case B_MULTI_GET_BUFFERS
: return get_buffers(cookie
, arg
);
292 case B_MULTI_SET_BUFFERS
: return B_ERROR
;
293 case B_MULTI_SET_START_TIME
: return B_ERROR
;
294 case B_MULTI_BUFFER_EXCHANGE
: return buffer_exchange(cookie
, arg
);
295 case B_MULTI_BUFFER_FORCE_STOP
: return buffer_force_stop(cookie
);