1 /* 2 * Copyright (c) 2002-2007, Jerome Duval (jerome.duval@free.fr) 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "MultiAudioDevice.h" 8 9 #include <errno.h> 10 #include <string.h> 11 12 #include <MediaDefs.h> 13 14 #include "debug.h" 15 #include "MultiAudioUtility.h" 16 17 18 using namespace MultiAudio; 19 20 21 MultiAudioDevice::MultiAudioDevice(const char* name, const char* path) 22 { 23 CALLED(); 24 25 strlcpy(fPath, path, B_PATH_NAME_LENGTH); 26 PRINT(("name: %s, path: %s\n", name, fPath)); 27 28 fInitStatus = _InitDriver(); 29 } 30 31 32 MultiAudioDevice::~MultiAudioDevice() 33 { 34 CALLED(); 35 if (fDevice >= 0) 36 close(fDevice); 37 } 38 39 40 status_t 41 MultiAudioDevice::InitCheck() const 42 { 43 CALLED(); 44 return fInitStatus; 45 } 46 47 48 status_t 49 MultiAudioDevice::_InitDriver() 50 { 51 int num_outputs, num_inputs, num_channels; 52 53 CALLED(); 54 55 // open the device driver 56 57 fDevice = open(fPath, O_WRONLY); 58 if (fDevice == -1) { 59 fprintf(stderr, "Failed to open %s: %s\n", fPath, strerror(errno)); 60 return B_ERROR; 61 } 62 63 // Get description 64 65 fDescription.info_size = sizeof(fDescription); 66 fDescription.request_channel_count = MAX_CHANNELS; 67 fDescription.channels = fChannelInfo; 68 status_t status = get_description(fDevice, &fDescription); 69 if (status != B_OK) { 70 fprintf(stderr, "Failed on B_MULTI_GET_DESCRIPTION: %s\n", 71 strerror(status)); 72 return status; 73 } 74 75 PRINT(("Friendly name:\t%s\nVendor:\t\t%s\n", 76 fDescription.friendly_name, fDescription.vendor_info)); 77 PRINT(("%ld outputs\t%ld inputs\n%ld out busses\t%ld in busses\n", 78 fDescription.output_channel_count, fDescription.input_channel_count, 79 fDescription.output_bus_channel_count, 80 fDescription.input_bus_channel_count)); 81 PRINT(("\nChannels\n" 82 "ID\tKind\tDesig\tConnectors\n")); 83 84 for (int32 i = 0; i < fDescription.output_channel_count 85 + fDescription.input_channel_count; i++) { 86 PRINT(("%ld\t%d\t0x%lx\t0x%lx\n", fDescription.channels[i].channel_id, 87 fDescription.channels[i].kind, 88 fDescription.channels[i].designations, 89 fDescription.channels[i].connectors)); 90 } 91 PRINT(("\n")); 92 93 PRINT(("Output rates\t\t0x%lx\n", fDescription.output_rates)); 94 PRINT(("Input rates\t\t0x%lx\n", fDescription.input_rates)); 95 PRINT(("Max CVSR\t\t%.0f\n", fDescription.max_cvsr_rate)); 96 PRINT(("Min CVSR\t\t%.0f\n", fDescription.min_cvsr_rate)); 97 PRINT(("Output formats\t\t0x%lx\n", fDescription.output_formats)); 98 PRINT(("Input formats\t\t0x%lx\n", fDescription.input_formats)); 99 PRINT(("Lock sources\t\t0x%lx\n", fDescription.lock_sources)); 100 PRINT(("Timecode sources\t0x%lx\n", fDescription.timecode_sources)); 101 PRINT(("Interface flags\t\t0x%lx\n", fDescription.interface_flags)); 102 PRINT(("Control panel string:\t\t%s\n", fDescription.control_panel)); 103 PRINT(("\n")); 104 105 num_outputs = fDescription.output_channel_count; 106 num_inputs = fDescription.input_channel_count; 107 num_channels = num_outputs + num_inputs; 108 109 // Get and set enabled channels 110 111 multi_channel_enable enable; 112 uint32 enableBits; 113 enable.info_size = sizeof(enable); 114 enable.enable_bits = (uchar*)&enableBits; 115 116 status = get_enabled_channels(fDevice, &enable); 117 if (status != B_OK) { 118 fprintf(stderr, "Failed on B_MULTI_GET_ENABLED_CHANNELS: %s\n", 119 strerror(status)); 120 return status; 121 } 122 123 enableBits = (1 << num_channels) - 1; 124 enable.lock_source = B_MULTI_LOCK_INTERNAL; 125 126 status = set_enabled_channels(fDevice, &enable); 127 if (status != B_OK) { 128 fprintf(stderr, "Failed on B_MULTI_SET_ENABLED_CHANNELS 0x%x: %s\n", 129 *enable.enable_bits, strerror(status)); 130 return status; 131 } 132 133 // Set the sample rate 134 135 fFormatInfo.info_size = sizeof(multi_format_info); 136 fFormatInfo.output.rate = select_sample_rate(fDescription.output_rates); 137 fFormatInfo.output.cvsr = 0; 138 fFormatInfo.output.format = select_format(fDescription.output_formats); 139 fFormatInfo.input.rate = select_sample_rate(fDescription.input_rates); 140 fFormatInfo.input.cvsr = fFormatInfo.output.cvsr; 141 fFormatInfo.input.format = select_format(fDescription.input_formats); 142 143 status = set_global_format(fDevice, &fFormatInfo); 144 if (status != B_OK) { 145 fprintf(stderr, "Failed on B_MULTI_SET_GLOBAL_FORMAT: %s\n", 146 strerror(status)); 147 } 148 149 status = get_global_format(fDevice, &fFormatInfo); 150 if (status != B_OK) { 151 fprintf(stderr, "Failed on B_MULTI_GET_GLOBAL_FORMAT: %s\n", 152 strerror(status)); 153 return status; 154 } 155 156 // Get the buffers 157 158 for (uint32 i = 0; i < MAX_BUFFERS; i++) { 159 fPlayBuffers[i] = &fPlayBufferList[i * MAX_CHANNELS]; 160 fRecordBuffers[i] = &fRecordBufferList[i * MAX_CHANNELS]; 161 } 162 fBufferList.info_size = sizeof(multi_buffer_list); 163 fBufferList.request_playback_buffer_size = 0; 164 // use the default... 165 fBufferList.request_playback_buffers = MAX_BUFFERS; 166 fBufferList.request_playback_channels = num_outputs; 167 fBufferList.playback_buffers = (buffer_desc **) fPlayBuffers; 168 fBufferList.request_record_buffer_size = 0; 169 // use the default... 170 fBufferList.request_record_buffers = MAX_BUFFERS; 171 fBufferList.request_record_channels = num_inputs; 172 fBufferList.record_buffers = /*(buffer_desc **)*/ fRecordBuffers; 173 174 status = get_buffers(fDevice, &fBufferList); 175 if (status != B_OK) { 176 fprintf(stderr, "Failed on B_MULTI_GET_BUFFERS: %s\n", 177 strerror(status)); 178 return status; 179 } 180 181 for (int32 i = 0; i < fBufferList.return_playback_buffers; i++) { 182 for (int32 j = 0; j < fBufferList.return_playback_channels; j++) { 183 PRINT(("fBufferList.playback_buffers[%ld][%ld].base: %p\n", 184 i, j, fBufferList.playback_buffers[i][j].base)); 185 PRINT(("fBufferList.playback_buffers[%ld][%ld].stride: %li\n", 186 i, j, fBufferList.playback_buffers[i][j].stride)); 187 } 188 } 189 190 for (int32 i = 0; i < fBufferList.return_record_buffers; i++) { 191 for (int32 j = 0; j < fBufferList.return_record_channels; j++) { 192 PRINT(("fBufferList.record_buffers[%ld][%ld].base: %p\n", 193 i, j, fBufferList.record_buffers[i][j].base)); 194 PRINT(("fBufferList.record_buffers[%ld][%ld].stride: %li\n", 195 i, j, fBufferList.record_buffers[i][j].stride)); 196 } 197 } 198 199 fMixControlInfo.info_size = sizeof(fMixControlInfo); 200 fMixControlInfo.control_count = MAX_CONTROLS; 201 fMixControlInfo.controls = fMixControl; 202 203 status = list_mix_controls(fDevice, &fMixControlInfo); 204 if (status != B_OK) { 205 fprintf(stderr, "Failed on DRIVER_LIST_MIX_CONTROLS: %s\n", 206 strerror(status)); 207 return status; 208 } 209 210 return B_OK; 211 } 212 213 214 status_t 215 MultiAudioDevice::BufferExchange(multi_buffer_info *info) 216 { 217 return buffer_exchange(fDevice, info); 218 } 219 220 221 status_t 222 MultiAudioDevice::SetMix(multi_mix_value_info *info) 223 { 224 return set_mix(fDevice, info); 225 } 226 227 228 status_t 229 MultiAudioDevice::GetMix(multi_mix_value_info *info) 230 { 231 return get_mix(fDevice, info); 232 } 233