From 1bb624cb432fbaaf718abf3344a3597ce6055370 Mon Sep 17 00:00:00 2001 From: philmoz Date: Mon, 30 Oct 2023 20:07:47 +1100 Subject: [PATCH] fix(color): Broken search for model specific audio files for switches (#4162) Co-authored-by: raphaelcoeffic Co-authored-by: Peter Feerick --- radio/src/CMakeLists.txt | 9 + radio/src/audio.cpp | 141 ++++----------- radio/src/model_audio.cpp | 182 ++++++++++++++++++++ radio/src/model_audio.h | 34 ++++ radio/src/targets/common/arm/CMakeLists.txt | 8 - radio/src/tests/model_audio.cpp | 102 +++++++++++ 6 files changed, 358 insertions(+), 118 deletions(-) create mode 100644 radio/src/model_audio.cpp create mode 100644 radio/src/model_audio.h create mode 100644 radio/src/tests/model_audio.cpp diff --git a/radio/src/CMakeLists.txt b/radio/src/CMakeLists.txt index a6df9e9b09a..bc9fa4fe13f 100644 --- a/radio/src/CMakeLists.txt +++ b/radio/src/CMakeLists.txt @@ -41,6 +41,7 @@ option(RAS "RAS (SWR) enabled" ON) option(TEMPLATES "Model templates menu" OFF) option(TRACE_SIMPGMSPACE "Turn on traces in simpgmspace.cpp" ON) option(TRACE_LUA_INTERNALS "Turn on traces for Lua internals" OFF) +option(TRACE_AUDIO "Traces audio enabled" OFF) option(DEBUG_SEGGER_RTT "Debug output to Segger RTT" OFF) option(DEBUG_WINDOWS "Turn on windows traces" OFF) option(DEBUG_YAML "Turn on YAML traces" OFF) @@ -284,6 +285,12 @@ if(TRACE_LUA_INTERNALS) add_definitions(-DTRACE_LUA_INTERNALS_ENABLED) endif() +if(TRACE_AUDIO) + add_definitions(-DTRACE_AUDIO) + set(DEBUG ON) + set(DEBUG_TRACE_BUFFER ON) +endif() + if(DEBUG_SEGGER_RTT) add_definitions(-DDEBUG_SEGGER_RTT) set(SRC ${SRC} ${THIRDPARTY_DIR}/Segger_RTT/RTT/SEGGER_RTT.c) @@ -386,6 +393,8 @@ set(SRC trainer.cpp model_init.cpp serial.cpp + audio.cpp + model_audio.cpp sbus.cpp input_mapping.cpp inactivity_timer.cpp diff --git a/radio/src/audio.cpp b/radio/src/audio.cpp index 3b7c660d265..79f0bfaaccc 100644 --- a/radio/src/audio.cpp +++ b/radio/src/audio.cpp @@ -19,15 +19,18 @@ * GNU General Public License for more details. */ -#include "opentx.h" #include +#include "opentx.h" +#include "strhelpers.h" #include "switches.h" #if defined(LIBOPENUI) - #include "libopenui.h" +#include "libopenui.h" #endif +#include "model_audio.h" + extern RTOS_MUTEX_HANDLE audioMutex; const int16_t sineValues[] = @@ -306,133 +309,51 @@ void referenceSystemAudioFiles() } } -const char * const suffixes[] = { "-off", "-on" }; - -char *getModelAudioPath(char *path) -{ - strcpy(path, SOUNDS_PATH "/"); - strncpy(path + SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2); - char *buf = strcat_currentmodelname(path + sizeof(SOUNDS_PATH), ' '); - - if (!isFileAvailable(path)) { - buf = strcat_currentmodelname(path + sizeof(SOUNDS_PATH), 0); - } - - *buf++ = '/'; - *buf = '\0'; - return buf; -} - -void getFlightmodeAudioFile(char * filename, int index, unsigned int event) -{ - char * str = getModelAudioPath(filename); - char * tmp = strcatFlightmodeName(str, index); - strcpy(tmp, suffixes[event]); - strcat(tmp, SOUNDS_EXT); -} - -void getSwitchAudioFile(char * filename, swsrc_t index) -{ - char * str = getModelAudioPath(filename); - - if (index <= MAX_SWITCHES * 3) { - div_t swinfo = switchInfo(index); - *str++ = 'S'; - *str++ = switchGetLetter(swinfo.quot); - const char * positions[] = { "-up", "-mid", "-down" }; - strcpy(str, positions[swinfo.rem]); - } - else { - index -= MAX_SWITCHES * 3; - div_t swinfo = div((int)index, XPOTS_MULTIPOS_COUNT); - *str++ = 'S'; - *str++ = '1' + swinfo.quot; - *str++ = '1' + swinfo.rem; - *str = '\0'; - } - strcat(str, SOUNDS_EXT); -} - -void getLogicalSwitchAudioFile(char * filename, int index, unsigned int event) -{ - char * str = getModelAudioPath(filename); - - *str++ = 'L'; - if (index >= 9) { - div_t qr = div(index+1, 10); - *str++ = '0' + qr.quot; - *str++ = '0' + qr.rem; - } - else { - *str++ = '1' + index; - } - - strcpy(str, suffixes[event]); - strcat(str, SOUNDS_EXT); -} - void referenceModelAudioFiles() { - char path[AUDIO_FILENAME_MAXLEN+1]; - FILINFO fno; DIR dir; + FILINFO fno; + char path[AUDIO_FILENAME_MAXLEN + 1]; sdAvailableFlightmodeAudioFiles.reset(); sdAvailableSwitchAudioFiles.reset(); sdAvailableLogicalSwitchAudioFiles.reset(); - char * filename = getModelAudioPath(path); - *(filename-1) = '\0'; + getModelAudioPath(path, false); - FRESULT res = f_opendir(&dir, path); /* Open the directory */ + FRESULT res = f_opendir(&dir, path); /* Open the directory */ if (res == FR_OK) { for (;;) { - res = f_readdir(&dir, &fno); /* Read a directory item */ - if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */ + res = f_readdir(&dir, &fno); /* Read a directory item */ + if (res != FR_OK || fno.fname[0] == 0) + break; /* Break on error or end of dir */ uint8_t len = strlen(fno.fname); - bool found = false; // Eliminates directories / non wav files - if (len < 5 || strcasecmp(fno.fname+len-4, SOUNDS_EXT) || (fno.fattrib & AM_DIR)) continue; + if (fno.fattrib & AM_DIR) continue; + if (len < sizeof(SOUNDS_EXT)) continue; + + char *ext = fno.fname + len - (sizeof(SOUNDS_EXT) - 1); + if (strcasecmp(ext, SOUNDS_EXT)) continue; + TRACE("referenceModelAudioFiles(): using file: %s", fno.fname); - // Flight modes Audio Files -[on|off].wav - for (int i=0; i-[up|mid|down].wav - for (unsigned i = 0; i <= MAX_SWITCH_POSITIONS && !found; i++) { - getSwitchAudioFile(path, i); - // TRACE("referenceModelAudioFiles(): searching for %s in %s (%d)", path, fno.fname, i); - if (!strcasecmp(filename, fno.fname)) { - sdAvailableSwitchAudioFiles.setBit(i); - found = true; - TRACE("\tfound: %s", filename); - } + if (matchSwitchAudioFile(fno.fname, idx)) { + sdAvailableSwitchAudioFiles.setBit(idx); + continue; } - // Logical Switches Audio Files -[on|off].wav - for (int i=0; iid, 2); + char* buf = strcat_currentmodelname(path + sizeof(SOUNDS_PATH), ' '); + + if (!isFileAvailable(path)) { + buf = strcat_currentmodelname(path + sizeof(SOUNDS_PATH), 0); + } + + if (trailingSlash) + *buf++ = '/'; + *buf = '\0'; + return buf; +} + +void getFlightmodeAudioFile(char* path, int index, unsigned int event) +{ + char* str = getModelAudioPath(path); + char* tmp = strcatFlightmodeName(str, index); + tmp = strAppend(tmp, _suffixes[event]); + strAppend(tmp, SOUNDS_EXT); +} + +static const char* const _sw_positions[] = {"-up", "-mid", "-down"}; + +bool getSwitchAudioFile(char* path, swsrc_t index) +{ + char* str = getModelAudioPath(path); + + if (index <= SWSRC_LAST_SWITCH) { + div_t swinfo = switchInfo(index); + auto sw_name = switchGetName(swinfo.quot); + if (!sw_name) return false; + str = strAppend(str, sw_name); + str = strAppend(str, _sw_positions[swinfo.rem]); + } else { + div_t swinfo = + div((int)(index - SWSRC_FIRST_MULTIPOS_SWITCH), XPOTS_MULTIPOS_COUNT); + *str++ = 'S'; + *str++ = '1' + swinfo.quot; + *str++ = '1' + swinfo.rem; + *str = '\0'; + } + strAppend(str, SOUNDS_EXT); + return true; +} + +void getLogicalSwitchAudioFile(char* filename, int index, unsigned int event) +{ + char* str = getModelAudioPath(filename); + + *str++ = 'L'; + if (index >= 9) { + div_t qr = div(index + 1, 10); + *str++ = '0' + qr.quot; + *str++ = '0' + qr.rem; + } else { + *str++ = '1' + index; + } + + strcpy(str, _suffixes[event]); + strcat(str, SOUNDS_EXT); +} + +// Flight modes Audio Files -[on|off].wav +bool matchModeAudioFile(const char* filename, int& index, int& event) +{ + for (int i = 0; i < MAX_FLIGHT_MODES; i++) { + auto* c = filename; + auto* fm_name = g_model.flightModeData[i].name; + auto fm_name_len = strnlen(fm_name, LEN_FLIGHT_MODE_NAME); + if (strncasecmp(c, fm_name, fm_name_len) != 0) continue; + c += fm_name_len; + for (size_t e = 0; e < DIM(_suffixes); e++) { + auto suffix_len = strlen(_suffixes[e]); + if (strncasecmp(c, _suffixes[e], suffix_len) != 0) continue; + c += suffix_len; + if (*c != '.') continue; + index = i; + event = e; + return true; + } + } + return false; +} + +bool matchSwitchAudioFile(const char* filename, int& sw_pos) +{ + // Switches Audio Files -[up|mid|down].wav + for (int i = 0; i < switchGetMaxSwitches(); i++) { + auto* c = filename; + auto sw_name = switchGetName(i); + auto sw_name_len = strlen(sw_name); + if (strncasecmp(c, sw_name, sw_name_len) != 0) continue; + c += sw_name_len; + for (size_t pos = 0; pos < DIM(_sw_positions); pos++) { + auto pos_len = strlen(_sw_positions[pos]); + if (strncasecmp(c, _sw_positions[pos], pos_len) != 0) continue; + c += pos_len; + if (*c != '.') continue; + sw_pos = i * 3 + pos; + return true; + } + } + + // match multipos switches + { + auto* c = filename; + if (*c != 'S' && *c != 's') return false; + c += 1; + if (*c < '1' || *c > '9') return false; + uint8_t xpot = uint8_t(*c++ - '1'); + if (*c < '1' || *c > '9') return false; + uint8_t pos = uint8_t(*c++ - '1'); + if (pos >= XPOTS_MULTIPOS_COUNT) return false; + if (*c != '.') return false; + + for (int i = 0; i < MAX_POTS; i++) { + if (i != xpot) continue; + if (!IS_POT_MULTIPOS(i)) continue; + sw_pos = (MAX_SWITCHES * 3) + XPOTS_MULTIPOS_COUNT * xpot + pos; + return true; + } + } + + return false; +} + +// Logical Switches Audio Files -[on|off].wav +bool matchLogicalSwitchAudioFile(const char* filename, int& index, int& event) +{ + auto* c = filename; + if (*c != 'L' && *c != 'l') return false; + c += 1; + if (*c < '1' && *c > '9') return false; + int lsw = *c++ - '0'; + if (*c >= '0' && *c <= '9') { + lsw = (lsw * 10) + (*c++ - '0'); + } + if (*c != '-' || lsw < 1) return false; + + for (size_t e = 0; e < DIM(_suffixes); e++) { + auto* s = c; + auto suffix_len = strlen(_suffixes[e]); + if (strncasecmp(s, _suffixes[e], suffix_len) != 0) continue; + s += suffix_len; + if (*s != '.') continue; + index = lsw - 1; + event = e; + return true; + } + return false; +} diff --git a/radio/src/model_audio.h b/radio/src/model_audio.h new file mode 100644 index 00000000000..e680006fed3 --- /dev/null +++ b/radio/src/model_audio.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#pragma once + +#include "opentx_types.h" + +char* getModelAudioPath(char* path, bool trailingSlash = true); + +void getFlightmodeAudioFile(char* path, int index, unsigned int event); +bool getSwitchAudioFile(char* path, swsrc_t index); +void getLogicalSwitchAudioFile(char* path, int index, unsigned int event); + +bool matchModeAudioFile(const char* filename, int& index, int& event); +bool matchSwitchAudioFile(const char* filename, int& sw_pos); +bool matchLogicalSwitchAudioFile(const char* filename, int& index, int& event); diff --git a/radio/src/targets/common/arm/CMakeLists.txt b/radio/src/targets/common/arm/CMakeLists.txt index 3daf7cd693d..a24ee4e8242 100644 --- a/radio/src/targets/common/arm/CMakeLists.txt +++ b/radio/src/targets/common/arm/CMakeLists.txt @@ -7,7 +7,6 @@ option(LOG_TELEMETRY "Telemetry Logs on SD card" OFF) option(LOG_BLUETOOTH "Bluetooth Logs on SD card" OFF) option(TRACE_SD_CARD "Traces SD enabled" OFF) option(TRACE_FATFS "Traces FatFS enabled" OFF) -option(TRACE_AUDIO "Traces audio enabled" OFF) option(DEBUG_TRACE_BUFFER "Debug Trace Screen" OFF) option(XJT "XJT TX Module" ON) option(PPM "PPM TX Module" ON) @@ -124,12 +123,6 @@ if(TRACE_FATFS) set(DEBUG_TRACE_BUFFER ON) endif() -if(TRACE_AUDIO) - add_definitions(-DTRACE_AUDIO) - set(DEBUG ON) - set(DEBUG_TRACE_BUFFER ON) -endif() - if(DEBUG_TRACE_BUFFER) add_definitions(-DDEBUG_TRACE_BUFFER) endif() @@ -294,7 +287,6 @@ set(SRC ${SRC} main.cpp tasks.cpp - audio.cpp telemetry/telemetry.cpp telemetry/telemetry_sensors.cpp telemetry/frsky.cpp diff --git a/radio/src/tests/model_audio.cpp b/radio/src/tests/model_audio.cpp new file mode 100644 index 00000000000..3254e092215 --- /dev/null +++ b/radio/src/tests/model_audio.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "model_audio.h" + +#include "gtests.h" + +TEST(ModelAudio, flightModes) +{ + strncpy(g_model.flightModeData[0].name, "One", LEN_FLIGHT_MODE_NAME); + strncpy(g_model.flightModeData[1].name, "Two", LEN_FLIGHT_MODE_NAME); + strncpy(g_model.flightModeData[2].name, "Three", LEN_FLIGHT_MODE_NAME); + strncpy(g_model.flightModeData[3].name, "Four", LEN_FLIGHT_MODE_NAME); + strncpy(g_model.flightModeData[4].name, "Five", LEN_FLIGHT_MODE_NAME); + + int idx, event; + EXPECT_TRUE(matchModeAudioFile("one-on.wav", idx, event)); + EXPECT_EQ(0, idx); + EXPECT_EQ(1, event); + + EXPECT_TRUE(matchModeAudioFile("one-off.wav", idx, event)); + EXPECT_EQ(0, idx); + EXPECT_EQ(0, event); + + EXPECT_TRUE(matchModeAudioFile("tWo-ON.wav", idx, event)); + EXPECT_EQ(1, idx); + EXPECT_EQ(1, event); + + EXPECT_TRUE(matchModeAudioFile("five-OFF.wav", idx, event)); + EXPECT_EQ(4, idx); + EXPECT_EQ(0, event); + + EXPECT_FALSE(matchModeAudioFile("abc-off.wav", idx, event)); + EXPECT_FALSE(matchModeAudioFile("abc-on.wav", idx, event)); + + EXPECT_FALSE(matchModeAudioFile("", idx, event)); + EXPECT_FALSE(matchModeAudioFile("O", idx, event)); + EXPECT_FALSE(matchModeAudioFile("On", idx, event)); + EXPECT_FALSE(matchModeAudioFile("One", idx, event)); + EXPECT_FALSE(matchModeAudioFile("One.", idx, event)); +} + +TEST(ModelAudio, switches) +{ + int sw_pos; + EXPECT_TRUE(matchSwitchAudioFile("sa-up.wav", sw_pos)); + EXPECT_EQ(0, sw_pos); + + EXPECT_TRUE(matchSwitchAudioFile("Sa-mid.wav", sw_pos)); + EXPECT_EQ(1, sw_pos); + + EXPECT_TRUE(matchSwitchAudioFile("SA-down.wav", sw_pos)); + EXPECT_EQ(2, sw_pos); + + EXPECT_FALSE(matchSwitchAudioFile("SA-dow.wav", sw_pos)); + EXPECT_FALSE(matchSwitchAudioFile("SX-mid.wav", sw_pos)); + EXPECT_FALSE(matchSwitchAudioFile("AS-mid.wav", sw_pos)); + + g_eeGeneral.potsConfig = POT_MULTIPOS_SWITCH << (POT_CFG_BITS * 2); + EXPECT_TRUE(matchSwitchAudioFile("S34.wav", sw_pos)); + EXPECT_EQ(MAX_SWITCHES * 3 + 2 * XPOTS_MULTIPOS_COUNT + 3, sw_pos); + + sw_pos = 123; + EXPECT_FALSE(matchSwitchAudioFile("S12.wav", sw_pos)); + EXPECT_EQ(123, sw_pos); +} + +TEST(ModelAudio, logicalSwitches) +{ + int idx, event; + EXPECT_TRUE(matchLogicalSwitchAudioFile("l12-on.wav", idx, event)); + EXPECT_EQ(11, idx); + EXPECT_EQ(1, event); + + EXPECT_TRUE(matchLogicalSwitchAudioFile("L64-off.wav", idx, event)); + EXPECT_EQ(63, idx); + EXPECT_EQ(0, event); + + EXPECT_FALSE(matchLogicalSwitchAudioFile("", idx, event)); + EXPECT_FALSE(matchLogicalSwitchAudioFile("5", idx, event)); + EXPECT_FALSE(matchLogicalSwitchAudioFile("1L20", idx, event)); + EXPECT_FALSE(matchLogicalSwitchAudioFile("l24", idx, event)); + EXPECT_FALSE(matchLogicalSwitchAudioFile("l24-o.wav", idx, event)); +}