test_devices.cpp (8177B)
1 /* 2 * Copyright © 2015 Haakon Sporsheim <haakon.sporsheim@telenordigital.com> 3 * 4 * This program is made available under an ISC-style license. See the 5 * accompanying file LICENSE for details. 6 */ 7 8 /* libcubeb enumerate device test/example. 9 * Prints out a list of devices enumerated. */ 10 #include "cubeb/cubeb.h" 11 #include "gtest/gtest.h" 12 #include <memory> 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <string.h> 16 17 // #define ENABLE_NORMAL_LOG 18 // #define ENABLE_VERBOSE_LOG 19 #include "common.h" 20 21 static long 22 data_cb_duplex(cubeb_stream * stream, void * user, const void * inputbuffer, 23 void * outputbuffer, long nframes) 24 { 25 // noop, unused 26 return 0; 27 } 28 29 static void 30 state_cb_duplex(cubeb_stream * stream, void * /*user*/, cubeb_state state) 31 { 32 // noop, unused 33 } 34 35 static void 36 print_device_info(cubeb_device_info * info, FILE * f) 37 { 38 char devfmts[64] = ""; 39 const char *devtype, *devstate, *devdeffmt; 40 41 switch (info->type) { 42 case CUBEB_DEVICE_TYPE_INPUT: 43 devtype = "input"; 44 break; 45 case CUBEB_DEVICE_TYPE_OUTPUT: 46 devtype = "output"; 47 break; 48 case CUBEB_DEVICE_TYPE_UNKNOWN: 49 default: 50 devtype = "unknown?"; 51 break; 52 }; 53 54 switch (info->state) { 55 case CUBEB_DEVICE_STATE_DISABLED: 56 devstate = "disabled"; 57 break; 58 case CUBEB_DEVICE_STATE_UNPLUGGED: 59 devstate = "unplugged"; 60 break; 61 case CUBEB_DEVICE_STATE_ENABLED: 62 devstate = "enabled"; 63 break; 64 default: 65 devstate = "unknown?"; 66 break; 67 }; 68 69 switch (info->default_format) { 70 case CUBEB_DEVICE_FMT_S16LE: 71 devdeffmt = "S16LE"; 72 break; 73 case CUBEB_DEVICE_FMT_S16BE: 74 devdeffmt = "S16BE"; 75 break; 76 case CUBEB_DEVICE_FMT_F32LE: 77 devdeffmt = "F32LE"; 78 break; 79 case CUBEB_DEVICE_FMT_F32BE: 80 devdeffmt = "F32BE"; 81 break; 82 default: 83 devdeffmt = "unknown?"; 84 break; 85 }; 86 87 if (info->format & CUBEB_DEVICE_FMT_S16LE) 88 strcat(devfmts, " S16LE"); 89 if (info->format & CUBEB_DEVICE_FMT_S16BE) 90 strcat(devfmts, " S16BE"); 91 if (info->format & CUBEB_DEVICE_FMT_F32LE) 92 strcat(devfmts, " F32LE"); 93 if (info->format & CUBEB_DEVICE_FMT_F32BE) 94 strcat(devfmts, " F32BE"); 95 96 fprintf(f, 97 "dev: \"%s\"%s\n" 98 "\tName: \"%s\"\n" 99 "\tGroup: \"%s\"\n" 100 "\tVendor: \"%s\"\n" 101 "\tType: %s\n" 102 "\tState: %s\n" 103 "\tCh: %u\n" 104 "\tFormat: %s (0x%x) (default: %s)\n" 105 "\tRate: %u - %u (default: %u)\n" 106 "\tLatency: lo %u frames, hi %u frames\n", 107 info->device_id, info->preferred ? " (PREFERRED)" : "", 108 info->friendly_name, info->group_id, info->vendor_name, devtype, 109 devstate, info->max_channels, 110 (devfmts[0] == '\0') ? devfmts : devfmts + 1, 111 (unsigned int)info->format, devdeffmt, info->min_rate, info->max_rate, 112 info->default_rate, info->latency_lo, info->latency_hi); 113 } 114 115 static void 116 print_device_collection(cubeb_device_collection * collection, FILE * f) 117 { 118 uint32_t i; 119 120 for (i = 0; i < collection->count; i++) 121 print_device_info(&collection->device[i], f); 122 } 123 124 TEST(cubeb, destroy_default_collection) 125 { 126 int r; 127 cubeb * ctx = NULL; 128 cubeb_device_collection collection{nullptr, 0}; 129 130 r = common_init(&ctx, "Cubeb audio test"); 131 ASSERT_EQ(r, CUBEB_OK) << "Error initializing cubeb library"; 132 133 std::unique_ptr<cubeb, decltype(&cubeb_destroy)> cleanup_cubeb_at_exit( 134 ctx, cubeb_destroy); 135 136 ASSERT_EQ(collection.device, nullptr); 137 ASSERT_EQ(collection.count, (size_t)0); 138 139 r = cubeb_device_collection_destroy(ctx, &collection); 140 if (r != CUBEB_ERROR_NOT_SUPPORTED) { 141 ASSERT_EQ(r, CUBEB_OK); 142 ASSERT_EQ(collection.device, nullptr); 143 ASSERT_EQ(collection.count, (size_t)0); 144 } 145 } 146 147 TEST(cubeb, enumerate_devices) 148 { 149 int r; 150 cubeb * ctx = NULL; 151 cubeb_device_collection collection; 152 153 r = common_init(&ctx, "Cubeb audio test"); 154 ASSERT_EQ(r, CUBEB_OK) << "Error initializing cubeb library"; 155 156 std::unique_ptr<cubeb, decltype(&cubeb_destroy)> cleanup_cubeb_at_exit( 157 ctx, cubeb_destroy); 158 159 fprintf(stdout, "Enumerating input devices for backend %s\n", 160 cubeb_get_backend_id(ctx)); 161 162 r = cubeb_enumerate_devices(ctx, CUBEB_DEVICE_TYPE_INPUT, &collection); 163 if (r == CUBEB_ERROR_NOT_SUPPORTED) { 164 fprintf(stderr, "Device enumeration not supported" 165 " for this backend, skipping this test.\n"); 166 return; 167 } 168 ASSERT_EQ(r, CUBEB_OK) << "Error enumerating devices " << r; 169 170 fprintf(stdout, "Found %zu input devices\n", collection.count); 171 print_device_collection(&collection, stdout); 172 cubeb_device_collection_destroy(ctx, &collection); 173 174 fprintf(stdout, "Enumerating output devices for backend %s\n", 175 cubeb_get_backend_id(ctx)); 176 177 r = cubeb_enumerate_devices(ctx, CUBEB_DEVICE_TYPE_OUTPUT, &collection); 178 ASSERT_EQ(r, CUBEB_OK) << "Error enumerating devices " << r; 179 180 fprintf(stdout, "Found %zu output devices\n", collection.count); 181 print_device_collection(&collection, stdout); 182 cubeb_device_collection_destroy(ctx, &collection); 183 184 uint32_t count_before_creating_duplex_stream; 185 r = cubeb_enumerate_devices(ctx, CUBEB_DEVICE_TYPE_OUTPUT, &collection); 186 ASSERT_EQ(r, CUBEB_OK) << "Error enumerating devices " << r; 187 count_before_creating_duplex_stream = collection.count; 188 cubeb_device_collection_destroy(ctx, &collection); 189 190 if (!can_run_audio_input_test(ctx)) { 191 return; 192 } 193 cubeb_stream * stream; 194 cubeb_stream_params input_params; 195 cubeb_stream_params output_params; 196 197 input_params.format = output_params.format = CUBEB_SAMPLE_FLOAT32NE; 198 input_params.rate = output_params.rate = 48000; 199 input_params.channels = output_params.channels = 1; 200 input_params.layout = output_params.layout = CUBEB_LAYOUT_MONO; 201 input_params.prefs = output_params.prefs = CUBEB_STREAM_PREF_NONE; 202 203 r = cubeb_stream_init(ctx, &stream, "Cubeb duplex", NULL, &input_params, NULL, 204 &output_params, 1024, data_cb_duplex, state_cb_duplex, 205 nullptr); 206 207 ASSERT_EQ(r, CUBEB_OK) << "Error initializing cubeb stream"; 208 209 r = cubeb_enumerate_devices(ctx, CUBEB_DEVICE_TYPE_OUTPUT, &collection); 210 ASSERT_EQ(r, CUBEB_OK) << "Error enumerating devices " << r; 211 ASSERT_EQ(count_before_creating_duplex_stream, collection.count); 212 cubeb_device_collection_destroy(ctx, &collection); 213 214 cubeb_stream_destroy(stream); 215 } 216 217 TEST(cubeb, stream_get_current_device) 218 { 219 cubeb * ctx = NULL; 220 int r = common_init(&ctx, "Cubeb audio test"); 221 ASSERT_EQ(r, CUBEB_OK) << "Error initializing cubeb library"; 222 223 std::unique_ptr<cubeb, decltype(&cubeb_destroy)> cleanup_cubeb_at_exit( 224 ctx, cubeb_destroy); 225 226 fprintf(stdout, "Getting current devices for backend %s\n", 227 cubeb_get_backend_id(ctx)); 228 229 if (!can_run_audio_input_test(ctx)) { 230 return; 231 } 232 233 cubeb_stream * stream = NULL; 234 cubeb_stream_params input_params; 235 cubeb_stream_params output_params; 236 237 input_params.format = output_params.format = CUBEB_SAMPLE_FLOAT32NE; 238 input_params.rate = output_params.rate = 48000; 239 input_params.channels = output_params.channels = 1; 240 input_params.layout = output_params.layout = CUBEB_LAYOUT_MONO; 241 input_params.prefs = output_params.prefs = CUBEB_STREAM_PREF_NONE; 242 243 r = cubeb_stream_init(ctx, &stream, "Cubeb duplex", NULL, &input_params, NULL, 244 &output_params, 1024, data_cb_duplex, state_cb_duplex, 245 nullptr); 246 ASSERT_EQ(r, CUBEB_OK) << "Error initializing cubeb stream"; 247 std::unique_ptr<cubeb_stream, decltype(&cubeb_stream_destroy)> 248 cleanup_stream_at_exit(stream, cubeb_stream_destroy); 249 250 cubeb_device * device; 251 r = cubeb_stream_get_current_device(stream, &device); 252 if (r == CUBEB_ERROR_NOT_SUPPORTED) { 253 fprintf(stderr, "Getting current device is not supported" 254 " for this backend, skipping this test.\n"); 255 return; 256 } 257 ASSERT_EQ(r, CUBEB_OK) << "Error getting current devices"; 258 259 fprintf(stdout, "Current output device: %s\n", device->output_name); 260 fprintf(stdout, "Current input device: %s\n", device->input_name); 261 262 r = cubeb_stream_device_destroy(stream, device); 263 ASSERT_EQ(r, CUBEB_OK) << "Error destroying current devices"; 264 }