1 /* 2 * Copyright 2007-2009, Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Bek, host.haiku@gmx.de 7 */ 8 #include "driver.h" 9 10 11 // Convenience function to determine the byte count 12 // of a sample for a given format. 13 // Note: Currently null_audio only supports 16 bit, 14 // but that is supposed to change later 15 int32 16 format_to_sample_size(uint32 format) 17 { 18 switch(format) { 19 case B_FMT_8BIT_S: 20 return 1; 21 case B_FMT_16BIT: 22 return 2; 23 24 case B_FMT_18BIT: 25 case B_FMT_24BIT: 26 case B_FMT_32BIT: 27 case B_FMT_FLOAT: 28 return 4; 29 30 default: 31 return 0; 32 } 33 } 34 35 36 multi_channel_info channel_descriptions[] = { 37 { 0, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 38 { 1, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 39 { 2, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 40 { 3, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 41 { 4, B_MULTI_OUTPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 42 { 5, B_MULTI_OUTPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 43 { 6, B_MULTI_INPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 44 { 7, B_MULTI_INPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 45 }; 46 47 48 static status_t 49 get_description(void* cookie, multi_description* data) 50 { 51 multi_description description; 52 53 dprintf("null_audio: %s\n" , __func__ ); 54 55 if (user_memcpy(&description, data, sizeof(multi_description)) != B_OK) { 56 return B_BAD_ADDRESS; 57 } 58 59 description.interface_version = B_CURRENT_INTERFACE_VERSION; 60 description.interface_minimum = B_CURRENT_INTERFACE_VERSION; 61 62 strcpy(description.friendly_name,"Virtual audio (null_audio)"); 63 strcpy(description.vendor_info,"Host/Haiku"); 64 65 description.output_channel_count = 2; 66 description.input_channel_count = 2; 67 description.output_bus_channel_count = 2; 68 description.input_bus_channel_count = 2; 69 description.aux_bus_channel_count = 0; 70 71 description.output_rates = B_SR_44100; 72 description.input_rates = B_SR_44100; 73 74 description.max_cvsr_rate = 0; 75 description.min_cvsr_rate = 0; 76 77 description.output_formats = B_FMT_16BIT; 78 description.input_formats = B_FMT_16BIT; 79 description.lock_sources = B_MULTI_LOCK_INTERNAL; 80 description.timecode_sources = 0; 81 description.interface_flags = B_MULTI_INTERFACE_PLAYBACK | B_MULTI_INTERFACE_RECORD; 82 description.start_latency = 30000; 83 84 strcpy(description.control_panel,""); 85 86 if (user_memcpy(data, &description, sizeof(multi_description)) != B_OK) 87 return B_BAD_ADDRESS; 88 89 if (description.request_channel_count 90 >= sizeof(channel_descriptions) / sizeof(channel_descriptions[0])) { 91 if (user_memcpy(data->channels, 92 &channel_descriptions, sizeof(channel_descriptions)) != B_OK) 93 return B_BAD_ADDRESS; 94 } 95 96 return B_OK; 97 } 98 99 100 static status_t 101 get_enabled_channels(void* cookie, multi_channel_enable* data) 102 { 103 dprintf("null_audio: %s\n" , __func__ ); 104 // By default we say, that all channels are enabled 105 // and that this cannot be changed 106 B_SET_CHANNEL(data->enable_bits, 0, true); 107 B_SET_CHANNEL(data->enable_bits, 1, true); 108 B_SET_CHANNEL(data->enable_bits, 2, true); 109 B_SET_CHANNEL(data->enable_bits, 3, true); 110 return B_OK; 111 } 112 113 114 static status_t 115 set_global_format(device_t* device, multi_format_info* data) 116 { 117 // The media kit asks us to set our streams 118 // according to its settings 119 dprintf("null_audio: %s\n" , __func__ ); 120 device->playback_stream.format = data->output.format; 121 device->playback_stream.rate = data->output.rate; 122 123 device->record_stream.format = data->input.format; 124 device->record_stream.rate = data->input.rate; 125 126 return B_OK; 127 } 128 129 130 static status_t 131 get_global_format(device_t* device, multi_format_info* data) 132 { 133 dprintf("null_audio: %s\n" , __func__ ); 134 // Zero latency is unlikely to happen, so we fake some 135 // additional latency 136 data->output_latency = 30; 137 data->input_latency = 30; 138 data->timecode_kind = 0; 139 140 data->output.format = device->playback_stream.format; 141 data->output.rate = device->playback_stream.rate; 142 data->input.format = device->record_stream.format; 143 data->input.rate = device->record_stream.rate; 144 145 return B_OK; 146 } 147 148 149 static int32 150 create_group_control(multi_mix_control* multi, int32 idx, int32 parent, 151 int32 string, const char* name) 152 { 153 multi->id = MULTI_AUDIO_BASE_ID + idx; 154 multi->parent = parent; 155 multi->flags = B_MULTI_MIX_GROUP; 156 multi->master = MULTI_AUDIO_MASTER_ID; 157 multi->string = string; 158 if (name) 159 strcpy(multi->name, name); 160 161 return multi->id; 162 } 163 164 165 static status_t 166 list_mix_controls(device_t* device, multi_mix_control_info * data) 167 { 168 int32 parent; 169 dprintf("null_audio: %s\n" , __func__ ); 170 171 parent = create_group_control(data->controls +0, 0, 0, 0, "Record"); 172 parent = create_group_control(data->controls +1, 1, 0, 0, "Playback"); 173 data->control_count = 2; 174 175 return B_OK; 176 } 177 178 179 static status_t 180 list_mix_connections(void* cookie, multi_mix_connection_info* connection_info) 181 { 182 dprintf("null_audio: %s\n" , __func__ ); 183 return B_ERROR; 184 } 185 186 187 static status_t 188 list_mix_channels(void* cookie, multi_mix_channel_info* channel_info) 189 { 190 dprintf("null_audio: %s\n" , __func__ ); 191 return B_ERROR; 192 } 193 194 195 static status_t 196 get_buffers(device_t* device, multi_buffer_list* data) 197 { 198 uint32 playback_sample_size 199 = format_to_sample_size(device->playback_stream.format); 200 uint32 record_sample_size 201 = format_to_sample_size(device->record_stream.format); 202 uint32 cidx, bidx; 203 status_t result; 204 205 dprintf("null_audio: %s\n" , __func__ ); 206 207 // Workaround for Haiku multi_audio API, since it prefers 208 // to let the driver pick values, while the BeOS multi_audio 209 // actually gives the user's defaults. 210 if (data->request_playback_buffers > STRMAXBUF 211 || data->request_playback_buffers < STRMINBUF) { 212 data->request_playback_buffers = STRMINBUF; 213 } 214 215 if (data->request_record_buffers > STRMAXBUF 216 || data->request_record_buffers < STRMINBUF) { 217 data->request_record_buffers = STRMINBUF; 218 } 219 220 if (data->request_playback_buffer_size == 0) 221 data->request_playback_buffer_size = FRAMES_PER_BUFFER; 222 223 if (data->request_record_buffer_size == 0) 224 data->request_record_buffer_size = FRAMES_PER_BUFFER; 225 226 // ... from here on, we can assume again that 227 // a reasonable request is being made 228 229 data->flags = 0; 230 231 // Copy the requested settings into the streams 232 // and initialize the virtual buffers properly 233 device->playback_stream.num_buffers = data->request_playback_buffers; 234 device->playback_stream.num_channels = data->request_playback_channels; 235 device->playback_stream.buffer_length = data->request_playback_buffer_size; 236 result = null_hw_create_virtual_buffers(&device->playback_stream, 237 "null_audio_playback_sem"); 238 if (result != B_OK) { 239 dprintf("null_audio %s: Error setting up playback buffers (%s)\n", 240 __func__, strerror(result)); 241 return result; 242 } 243 244 device->record_stream.num_buffers = data->request_record_buffers; 245 device->record_stream.num_channels = data->request_record_channels; 246 device->record_stream.buffer_length = data->request_record_buffer_size; 247 result = null_hw_create_virtual_buffers(&device->record_stream, 248 "null_audio_record_sem"); 249 if (result != B_OK) { 250 dprintf("null_audio %s: Error setting up recording buffers (%s)\n", 251 __func__, strerror(result)); 252 return result; 253 } 254 255 /* Setup data structure for multi_audio API... */ 256 data->return_playback_buffers = data->request_playback_buffers; 257 data->return_playback_channels = data->request_playback_channels; 258 data->return_playback_buffer_size = data->request_playback_buffer_size; 259 260 for (bidx = 0; bidx < data->return_playback_buffers; bidx++) { 261 for (cidx = 0; cidx < data->return_playback_channels; cidx++) { 262 data->playback_buffers[bidx][cidx].base 263 = device->playback_stream.buffers[bidx] + (playback_sample_size * cidx); 264 data->playback_buffers[bidx][cidx].stride 265 = playback_sample_size * data->return_playback_channels; 266 } 267 } 268 269 data->return_record_buffers = data->request_record_buffers; 270 data->return_record_channels = data->request_record_channels; 271 data->return_record_buffer_size = data->request_record_buffer_size; 272 273 for (bidx = 0; bidx < data->return_record_buffers; bidx++) { 274 for (cidx = 0; cidx < data->return_record_channels; cidx++) { 275 data->record_buffers[bidx][cidx].base 276 = device->record_stream.buffers[bidx] + (record_sample_size * cidx); 277 data->record_buffers[bidx][cidx].stride 278 = record_sample_size * data->return_record_channels; 279 } 280 } 281 282 return B_OK; 283 } 284 285 286 static status_t 287 buffer_exchange(device_t* device, multi_buffer_info* info) 288 { 289 //dprintf("null_audio: %s\n" , __func__ ); 290 static int debug_buffers_exchanged = 0; 291 cpu_status status; 292 status_t result; 293 294 multi_buffer_info buffer_info; 295 if (user_memcpy(&buffer_info, info, sizeof(multi_buffer_info)) != B_OK) 296 return B_BAD_ADDRESS; 297 298 // On first call, we start our fake hardware. 299 // Usually one would jump into his interrupt handler now 300 if (!device->running) 301 null_start_hardware(device); 302 303 result = acquire_sem(device->playback_stream.buffer_ready_sem); 304 if (result != B_OK) { 305 dprintf("null_audio: %s, Could not get playback buffer\n", __func__); 306 return result; 307 } 308 309 result = acquire_sem(device->record_stream.buffer_ready_sem); 310 if (result != B_OK) { 311 dprintf("null_audio: %s, Could not get record buffer\n", __func__); 312 return result; 313 } 314 315 status = disable_interrupts(); 316 acquire_spinlock(&device->playback_stream.lock); 317 318 buffer_info.playback_buffer_cycle = device->playback_stream.buffer_cycle; 319 buffer_info.played_real_time = device->playback_stream.real_time; 320 buffer_info.played_frames_count = device->playback_stream.frames_count; 321 322 buffer_info.record_buffer_cycle = device->record_stream.buffer_cycle; 323 buffer_info.recorded_real_time = device->record_stream.real_time; 324 buffer_info.recorded_frames_count = device->record_stream.frames_count; 325 326 release_spinlock(&device->playback_stream.lock); 327 restore_interrupts(status); 328 329 debug_buffers_exchanged++; 330 if (((debug_buffers_exchanged % 5000) == 0) ) { 331 dprintf("null_audio: %s: %d buffers processed\n", 332 __func__, debug_buffers_exchanged); 333 } 334 335 if (user_memcpy(info, &buffer_info, sizeof(multi_buffer_info)) != B_OK) 336 return B_BAD_ADDRESS; 337 338 return B_OK; 339 } 340 341 342 static status_t 343 buffer_force_stop(device_t* device) 344 { 345 dprintf("null_audio: %s\n" , __func__ ); 346 347 if (device && device->running) 348 null_stop_hardware(device); 349 350 delete_area(device->playback_stream.buffer_area); 351 delete_area(device->record_stream.buffer_area); 352 353 delete_sem(device->playback_stream.buffer_ready_sem); 354 delete_sem(device->record_stream.buffer_ready_sem); 355 356 return B_OK; 357 } 358 359 360 status_t 361 multi_audio_control(void* cookie, uint32 op, void* arg, size_t len) 362 { 363 switch(op) { 364 case B_MULTI_GET_DESCRIPTION: return get_description(cookie, arg); 365 case B_MULTI_GET_EVENT_INFO: return B_ERROR; 366 case B_MULTI_SET_EVENT_INFO: return B_ERROR; 367 case B_MULTI_GET_EVENT: return B_ERROR; 368 case B_MULTI_GET_ENABLED_CHANNELS: return get_enabled_channels(cookie, arg); 369 case B_MULTI_SET_ENABLED_CHANNELS: return B_OK; 370 case B_MULTI_GET_GLOBAL_FORMAT: return get_global_format(cookie, arg); 371 case B_MULTI_SET_GLOBAL_FORMAT: return set_global_format(cookie, arg); 372 case B_MULTI_GET_CHANNEL_FORMATS: return B_ERROR; 373 case B_MULTI_SET_CHANNEL_FORMATS: return B_ERROR; 374 case B_MULTI_GET_MIX: return B_ERROR; 375 case B_MULTI_SET_MIX: return B_ERROR; 376 case B_MULTI_LIST_MIX_CHANNELS: return list_mix_channels(cookie, arg); 377 case B_MULTI_LIST_MIX_CONTROLS: return list_mix_controls(cookie, arg); 378 case B_MULTI_LIST_MIX_CONNECTIONS: return list_mix_connections(cookie, arg); 379 case B_MULTI_GET_BUFFERS: return get_buffers(cookie, arg); 380 case B_MULTI_SET_BUFFERS: return B_ERROR; 381 case B_MULTI_SET_START_TIME: return B_ERROR; 382 case B_MULTI_BUFFER_EXCHANGE: return buffer_exchange(cookie, arg); 383 case B_MULTI_BUFFER_FORCE_STOP: return buffer_force_stop(cookie); 384 } 385 386 dprintf("null_audio: %s - unknown op\n" , __func__); 387 return B_BAD_VALUE; 388 } 389 390