ft2_audioselector.c (11751B)
1 // for finding memory leaks in debug mode with Visual Studio 2 #if defined _DEBUG && defined _MSC_VER 3 #include <crtdbg.h> 4 #endif 5 6 #include <stdio.h> 7 #include <stdint.h> 8 #include "ft2_header.h" 9 #include "ft2_config.h" 10 #include "ft2_audio.h" 11 #include "ft2_gui.h" 12 #include "ft2_mouse.h" 13 #include "ft2_audioselector.h" 14 #include "ft2_structs.h" 15 16 enum 17 { 18 INPUT_DEVICE = 0, 19 OUTPUT_DEVICE = 1 20 }; 21 22 #define MAX_DEV_STR_LEN 256 23 24 // hide POSIX warnings 25 #ifdef _MSC_VER 26 #pragma warning(disable: 4996) 27 #endif 28 29 char *getAudioOutputDeviceFromConfig(void) 30 { 31 bool audioDeviceRead = false; 32 char *devString = NULL; 33 34 FILE *f = UNICHAR_FOPEN(editor.audioDevConfigFileLocationU, "r"); 35 if (f != NULL) 36 { 37 devString = (char *)malloc(MAX_DEV_STR_LEN+1); 38 if (devString == NULL) 39 { 40 fclose(f); 41 return NULL; // out of memory 42 } 43 44 devString[0] = '\0'; 45 fgets(devString, MAX_DEV_STR_LEN, f); 46 fclose(f); 47 48 const int32_t devStringLen = (int32_t)strlen(devString); 49 if (devStringLen > 0) 50 { 51 if (devString[devStringLen-1] == '\n') 52 devString[devStringLen-1] = '\0'; 53 54 if (!(devStringLen == 1 && devString[0] == ' ')) // space only = no device 55 audioDeviceRead = true; 56 } 57 } 58 59 if (!audioDeviceRead) 60 { 61 if (devString != NULL) 62 free(devString); 63 64 devString = strdup(DEFAULT_AUDIO_DEV_STR); 65 } 66 67 // SDL_OpenAudioDevice() doesn't seem to like an empty audio device string 68 if (devString != NULL && devString[0] == '\0') 69 { 70 free(devString); 71 return NULL; 72 } 73 74 return devString; 75 } 76 77 char *getAudioInputDeviceFromConfig(void) 78 { 79 bool audioDeviceRead = false; 80 char *devString = NULL; 81 82 FILE *f = UNICHAR_FOPEN(editor.audioDevConfigFileLocationU, "r"); 83 if (f != NULL) 84 { 85 devString = (char *)malloc(MAX_DEV_STR_LEN+1); 86 if (devString == NULL) 87 { 88 fclose(f); 89 return NULL; // out of memory 90 } 91 92 devString[0] = '\0'; 93 fgets(devString, MAX_DEV_STR_LEN, f); // skip first line (we want the input device) 94 fgets(devString, MAX_DEV_STR_LEN, f); 95 fclose(f); 96 97 const int32_t devStringLen = (int32_t)strlen(devString); 98 if (devStringLen > 0) 99 { 100 if (devString[devStringLen-1] == '\n') 101 devString[devStringLen-1] = '\0'; 102 103 if (!(devStringLen == 1 && devString[0] == ' ')) // space only = no device 104 audioDeviceRead = true; 105 } 106 } 107 108 if (!audioDeviceRead) 109 { 110 if (devString != NULL) 111 free(devString); 112 113 devString = strdup(DEFAULT_AUDIO_DEV_STR); 114 } 115 116 // SDL_OpenAudioDevice() doesn't seem to like an empty audio device string 117 if (devString != NULL && devString[0] == '\0') 118 { 119 free(devString); 120 return NULL; 121 } 122 123 return devString; 124 } 125 126 bool saveAudioDevicesToConfig(const char *outputDevice, const char *inputDevice) 127 { 128 FILE *f = UNICHAR_FOPEN(editor.audioDevConfigFileLocationU, "w"); 129 if (f == NULL) 130 return false; 131 132 if (outputDevice != NULL) 133 fputs(outputDevice, f); 134 else 135 fputc(' ', f); 136 137 fputc('\n', f); 138 139 if (inputDevice != NULL) 140 fputs(inputDevice, f); 141 else 142 fputc(' ', f); 143 144 fclose(f); 145 return true; 146 } 147 148 void drawAudioOutputList(void) 149 { 150 clearRect(114, 18, AUDIO_SELECTORS_BOX_WIDTH, 66); 151 152 if (audio.outputDeviceNum == 0) 153 { 154 textOut(114, 18, PAL_FORGRND, "No audio output devices found!"); 155 return; 156 } 157 158 for (int32_t i = 0; i < 6; i++) 159 { 160 const int32_t deviceEntry = getScrollBarPos(SB_AUDIO_OUTPUT_SCROLL) + i; 161 if (deviceEntry < audio.outputDeviceNum) 162 { 163 if (audio.outputDeviceNames[deviceEntry] == NULL) 164 continue; 165 166 const uint16_t y = 18 + (uint16_t)(i * 11); 167 168 if (audio.currOutputDevice != NULL) 169 { 170 if (strcmp(audio.currOutputDevice, audio.outputDeviceNames[deviceEntry]) == 0) 171 fillRect(114, y, AUDIO_SELECTORS_BOX_WIDTH, 10, PAL_BOXSLCT); // selection background color 172 } 173 else if (i == 0) // default audio device (always on top) 174 { 175 fillRect(114, y, AUDIO_SELECTORS_BOX_WIDTH, 10, PAL_BOXSLCT); // selection background color 176 } 177 178 char *tmpString = utf8ToCp850(audio.outputDeviceNames[deviceEntry], true); 179 if (tmpString != NULL) 180 { 181 textOutClipX(114, y, PAL_FORGRND, tmpString, 114 + AUDIO_SELECTORS_BOX_WIDTH); 182 free(tmpString); 183 } 184 } 185 } 186 } 187 188 void drawAudioInputList(void) 189 { 190 clearRect(114, 105, AUDIO_SELECTORS_BOX_WIDTH, 44); 191 192 if (audio.inputDeviceNum == 0) 193 { 194 textOut(114, 105, PAL_FORGRND, "No audio input devices found!"); 195 return; 196 } 197 198 for (int32_t i = 0; i < 4; i++) 199 { 200 const int32_t deviceEntry = getScrollBarPos(SB_AUDIO_INPUT_SCROLL) + i; 201 if (deviceEntry < audio.inputDeviceNum) 202 { 203 if (audio.inputDeviceNames[deviceEntry] == NULL) 204 continue; 205 206 const uint16_t y = 105 + (uint16_t)(i * 11); 207 208 if (audio.currInputDevice != NULL) 209 { 210 if (strcmp(audio.currInputDevice, audio.inputDeviceNames[deviceEntry]) == 0) 211 fillRect(114, y, AUDIO_SELECTORS_BOX_WIDTH, 10, PAL_BOXSLCT); // selection background color 212 } 213 else if (i == 0) // default audio device (always on top) 214 { 215 fillRect(114, y, AUDIO_SELECTORS_BOX_WIDTH, 10, PAL_BOXSLCT); // selection background color 216 } 217 218 char *tmpString = utf8ToCp850(audio.inputDeviceNames[deviceEntry], true); 219 if (tmpString != NULL) 220 { 221 textOutClipX(114, y, PAL_FORGRND, tmpString, 114 + AUDIO_SELECTORS_BOX_WIDTH); 222 free(tmpString); 223 } 224 } 225 } 226 } 227 228 bool testAudioDeviceListsMouseDown(void) 229 { 230 if (!ui.configScreenShown || editor.currConfigScreen != CONFIG_SCREEN_AUDIO) 231 return false; 232 233 const int32_t mx = mouse.x; 234 const int32_t my = mouse.y; 235 236 if (my < 18 || my > 149 || mx < 114 || mx >= 114+AUDIO_SELECTORS_BOX_WIDTH) 237 return false; 238 239 if (my < 84) 240 { 241 // output device list 242 243 const int32_t deviceNum = (int32_t)scrollBars[SB_AUDIO_OUTPUT_SCROLL].pos + ((my - 18) / 11); 244 if (audio.outputDeviceNum <= 0 || deviceNum >= audio.outputDeviceNum) 245 return true; 246 247 char *devString = audio.outputDeviceNames[deviceNum]; 248 if (devString != NULL && (audio.currOutputDevice == NULL || strcmp(audio.currOutputDevice, devString) != 0)) 249 { 250 if (audio.currOutputDevice != NULL) 251 free(audio.currOutputDevice); 252 253 const uint32_t devStringLen = (uint32_t)strlen(devString); 254 255 audio.currOutputDevice = (char *)malloc(devStringLen+1); 256 if (audio.currOutputDevice == NULL) 257 return true; 258 259 audio.currOutputDevice[0] = '\0'; 260 261 if (devStringLen > 0) 262 strcpy(audio.currOutputDevice, devString); 263 264 if (!setNewAudioSettings()) 265 okBox(0, "System message", "Couldn't open audio output device!", NULL); 266 else 267 drawAudioOutputList(); 268 } 269 270 return true; 271 } 272 else if (my >= 105) 273 { 274 // input device list 275 276 const int32_t deviceNum = (int32_t)scrollBars[SB_AUDIO_INPUT_SCROLL].pos + ((my - 105) / 11); 277 if (audio.inputDeviceNum <= 0 || deviceNum >= audio.inputDeviceNum) 278 return true; 279 280 char *devString = audio.inputDeviceNames[deviceNum]; 281 if (devString != NULL && (audio.currInputDevice == NULL || strcmp(audio.currInputDevice, devString) != 0)) 282 { 283 if (audio.currInputDevice != NULL) 284 free(audio.currInputDevice); 285 286 const uint32_t devStringLen = (uint32_t)strlen(devString); 287 288 audio.currInputDevice = (char *)malloc(devStringLen+1); 289 if (audio.currInputDevice == NULL) 290 return true; 291 292 audio.currInputDevice[0] = '\0'; 293 294 if (devStringLen > 0) 295 strcpy(audio.currInputDevice, devString); 296 297 drawAudioInputList(); 298 } 299 300 return true; 301 } 302 303 return false; 304 } 305 306 void freeAudioDeviceLists(void) 307 { 308 for (int32_t i = 0; i < MAX_AUDIO_DEVICES; i++) 309 { 310 if (audio.outputDeviceNames[i] != NULL) 311 { 312 free(audio.outputDeviceNames[i]); 313 audio.outputDeviceNames[i] = NULL; 314 } 315 316 if (audio.inputDeviceNames[i] != NULL) 317 { 318 free(audio.inputDeviceNames[i]); 319 audio.inputDeviceNames[i] = NULL; 320 } 321 322 audio.outputDeviceNum = 0; 323 audio.inputDeviceNum = 0; 324 } 325 } 326 327 void freeAudioDeviceSelectorBuffers(void) 328 { 329 if (editor.audioDevConfigFileLocationU != NULL) 330 { 331 free(editor.audioDevConfigFileLocationU); 332 editor.audioDevConfigFileLocationU = NULL; 333 } 334 335 if (audio.currOutputDevice != NULL) 336 { 337 free(audio.currOutputDevice); 338 audio.currOutputDevice = NULL; 339 } 340 341 if (audio.currInputDevice != NULL) 342 { 343 free(audio.currInputDevice); 344 audio.currInputDevice = NULL; 345 } 346 347 if (audio.lastWorkingAudioDeviceName != NULL) 348 { 349 free(audio.lastWorkingAudioDeviceName); 350 audio.lastWorkingAudioDeviceName = NULL; 351 } 352 353 freeAudioDeviceLists(); 354 } 355 356 void setToDefaultAudioOutputDevice(void) 357 { 358 if (audio.currOutputDevice != NULL) 359 { 360 free(audio.currOutputDevice); 361 audio.currOutputDevice = NULL; 362 } 363 364 /* If we have more than one device, we can't know which one 365 ** is the default (and thus not get its device name). 366 ** SDL2 ought to have a function for this! 367 */ 368 if (SDL_GetNumAudioDevices(false) == 1) 369 { 370 const char *devName = SDL_GetAudioDeviceName(0, false); 371 if (devName != NULL) 372 audio.currOutputDevice = strdup(devName); 373 } 374 } 375 376 void setToDefaultAudioInputDevice(void) 377 { 378 if (audio.currInputDevice != NULL) 379 { 380 free(audio.currInputDevice); 381 audio.currInputDevice = NULL; 382 } 383 384 /* If we have more than one device, we can't know which one 385 ** is the default (and thus not get its device name). 386 ** SDL2 ought to have a function for this! 387 */ 388 if (SDL_GetNumAudioDevices(true) == 1) 389 { 390 const char *devName = SDL_GetAudioDeviceName(0, true); 391 if (devName != NULL) 392 audio.currInputDevice = strdup(devName); 393 } 394 } 395 396 void rescanAudioDevices(void) 397 { 398 const bool listShown = (ui.configScreenShown && editor.currConfigScreen == CONFIG_SCREEN_AUDIO); 399 400 freeAudioDeviceLists(); 401 402 // GET AUDIO OUTPUT DEVICES 403 404 audio.outputDeviceNum = 1 + SDL_GetNumAudioDevices(false); 405 if (audio.outputDeviceNum > MAX_AUDIO_DEVICES) 406 audio.outputDeviceNum = MAX_AUDIO_DEVICES; 407 408 audio.outputDeviceNames[0] = strdup(DEFAULT_AUDIO_DEV_STR); 409 410 for (int32_t i = 1; i < audio.outputDeviceNum; i++) 411 { 412 const char *deviceName = SDL_GetAudioDeviceName(i-1, false); 413 if (deviceName == NULL) 414 { 415 audio.outputDeviceNum--; // hide device 416 continue; 417 } 418 419 const uint32_t stringLen = (uint32_t)strlen(deviceName); 420 421 audio.outputDeviceNames[i] = (char *)malloc(stringLen + 1); 422 if (audio.outputDeviceNames[i] == NULL) 423 break; 424 425 if (stringLen > 0) 426 strcpy(audio.outputDeviceNames[i], deviceName); 427 } 428 429 // GET AUDIO INPUT DEVICES 430 431 audio.inputDeviceNum = 1 + SDL_GetNumAudioDevices(true); 432 if (audio.inputDeviceNum > MAX_AUDIO_DEVICES) 433 audio.inputDeviceNum = MAX_AUDIO_DEVICES; 434 435 audio.inputDeviceNames[0] = strdup(DEFAULT_AUDIO_DEV_STR); 436 437 for (int32_t i = 1; i < audio.inputDeviceNum; i++) 438 { 439 const char *deviceName = SDL_GetAudioDeviceName(i-1, true); 440 if (deviceName == NULL) 441 { 442 audio.inputDeviceNum--; // hide device 443 continue; 444 } 445 446 const uint32_t stringLen = (uint32_t)strlen(deviceName); 447 448 audio.inputDeviceNames[i] = (char *)malloc(stringLen + 1); 449 if (audio.inputDeviceNames[i] == NULL) 450 break; 451 452 if (stringLen > 0) 453 strcpy(audio.inputDeviceNames[i], deviceName); 454 } 455 456 setScrollBarEnd(SB_AUDIO_OUTPUT_SCROLL, audio.outputDeviceNum); 457 setScrollBarPos(SB_AUDIO_OUTPUT_SCROLL, 0, false); 458 setScrollBarEnd(SB_AUDIO_INPUT_SCROLL, audio.inputDeviceNum); 459 setScrollBarPos(SB_AUDIO_INPUT_SCROLL, 0, false); 460 461 // DRAW LISTS 462 463 if (listShown) 464 { 465 drawAudioOutputList(); 466 drawAudioInputList(); 467 drawScrollBar(SB_AUDIO_OUTPUT_SCROLL); 468 drawScrollBar(SB_AUDIO_INPUT_SCROLL); 469 } 470 } 471 472 void scrollAudInputDevListUp(void) 473 { 474 scrollBarScrollUp(SB_AUDIO_INPUT_SCROLL, 1); 475 } 476 477 void scrollAudInputDevListDown(void) 478 { 479 scrollBarScrollDown(SB_AUDIO_INPUT_SCROLL, 1); 480 } 481 482 void scrollAudOutputDevListUp(void) 483 { 484 scrollBarScrollUp(SB_AUDIO_OUTPUT_SCROLL, 1); 485 } 486 487 void scrollAudOutputDevListDown(void) 488 { 489 scrollBarScrollDown(SB_AUDIO_OUTPUT_SCROLL, 1); 490 } 491 492 void sbAudOutputSetPos(uint32_t pos) 493 { 494 if (ui.configScreenShown && (editor.currConfigScreen == CONFIG_SCREEN_AUDIO)) 495 drawAudioOutputList(); 496 497 (void)pos; 498 } 499 500 void sbAudInputSetPos(uint32_t pos) 501 { 502 if (ui.configScreenShown && (editor.currConfigScreen == CONFIG_SCREEN_AUDIO)) 503 drawAudioInputList(); 504 505 (void)pos; 506 }