Issue #713 - Automatic Switch Audio Files (part 1)
This commit is contained in:
+137
-82
@@ -117,132 +117,190 @@ const char * audioFilenames[] = {
|
||||
};
|
||||
|
||||
uint64_t sdAvailableSystemAudioFiles = 0;
|
||||
uint8_t sdAvailablePhaseAudioFiles[MAX_PHASES] = { 0 };
|
||||
uint8_t sdAvailableMixerAudioFiles[MAX_MIXERS] = { 0 };
|
||||
uint32_t sdAvailablePhaseAudioFiles = 0;
|
||||
uint32_t sdAvailableSwitchAudioFiles = 0;
|
||||
uint64_t sdAvailableLogicalSwitchAudioFiles = 0;
|
||||
|
||||
void refreshSystemAudioFiles()
|
||||
#define MASK_SYSTEM_AUDIO_FILE(index) ((uint64_t)1 << index)
|
||||
#define MASK_PHASE_AUDIO_FILE(index, event) ((uint32_t)1 << (2*index+event))
|
||||
#define MASK_SWITCH_AUDIO_FILE(index) ((uint32_t)1 << index)
|
||||
#define MASK_LOGICAL_SWITCH_AUDIO_FILE(index, event) ((uint64_t)1 << (2*index+event))
|
||||
|
||||
bool isFileAvailable(const char * filename)
|
||||
{
|
||||
FILINFO info;
|
||||
#if _USE_LFN
|
||||
TCHAR lfn[_MAX_LFN + 1];
|
||||
info.lfname = lfn;
|
||||
info.lfsize = sizeof(lfn);
|
||||
#endif
|
||||
return f_stat(filename, &info) == FR_OK;
|
||||
}
|
||||
|
||||
char filename[32] = SYSTEM_SOUNDS_PATH "/";
|
||||
void getSystemAudioFile(char * filename, int index)
|
||||
{
|
||||
strcpy(filename, SYSTEM_SOUNDS_PATH "/");
|
||||
strncpy(filename+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2);
|
||||
strcpy(filename+sizeof(SYSTEM_SOUNDS_PATH), audioFilenames[index]);
|
||||
strcat(filename+sizeof(SYSTEM_SOUNDS_PATH), SOUNDS_EXT);
|
||||
}
|
||||
|
||||
void referenceSystemAudioFiles()
|
||||
{
|
||||
char filename[AUDIO_FILENAME_MAXLEN+1];
|
||||
uint64_t availableAudioFiles = 0;
|
||||
|
||||
assert(sizeof(audioFilenames)==AU_FRSKY_FIRST*sizeof(char *));
|
||||
assert(sizeof(sdAvailableSystemAudioFiles)*8 >= AU_FRSKY_FIRST);
|
||||
|
||||
uint64_t availableAudioFiles = 0;
|
||||
|
||||
for (uint32_t i=0; i<AU_FRSKY_FIRST; i++) {
|
||||
strcpy(filename+sizeof(SYSTEM_SOUNDS_PATH), audioFilenames[i]);
|
||||
strcat(filename+sizeof(SYSTEM_SOUNDS_PATH), SOUNDS_EXT);
|
||||
if (f_stat(filename, &info) == FR_OK)
|
||||
availableAudioFiles |= ((uint64_t)1 << i);
|
||||
for (int i=0; i<AU_FRSKY_FIRST; i++) {
|
||||
getSystemAudioFile(filename, i);
|
||||
if (isFileAvailable(filename)) {
|
||||
availableAudioFiles |= MASK_SYSTEM_AUDIO_FILE(i);
|
||||
}
|
||||
}
|
||||
|
||||
sdAvailableSystemAudioFiles = availableAudioFiles;
|
||||
}
|
||||
|
||||
const char * suffixes[] = { "-OFF", "-ON", /*"-BG", */NULL };
|
||||
const char * suffixes[] = { "-off", "-on" };
|
||||
|
||||
inline uint8_t getAvailableFiles(char *prefix, FILINFO &info, char *filename)
|
||||
void getPhaseAudioFile(char * filename, int index, unsigned int event)
|
||||
{
|
||||
uint8_t result = 0;
|
||||
|
||||
for (uint8_t i=0; suffixes[i]; i++) {
|
||||
strcpy(prefix, suffixes[i]);
|
||||
strcat(prefix, SOUNDS_EXT);
|
||||
if (f_stat(filename, &info) == FR_OK)
|
||||
result |= ((uint8_t)1 << i);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void refreshModelAudioFiles()
|
||||
{
|
||||
FILINFO info;
|
||||
TCHAR lfn[_MAX_LFN + 1];
|
||||
info.lfname = lfn;
|
||||
info.lfsize = sizeof(lfn);
|
||||
|
||||
char filename[AUDIO_FILENAME_MAXLEN+1] = SOUNDS_PATH "/";
|
||||
strcpy(filename, SOUNDS_PATH "/");
|
||||
strncpy(filename+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2);
|
||||
|
||||
if (sdMounted()) {
|
||||
char *buf = strcat_modelname(&filename[sizeof(SOUNDS_PATH)], g_eeGeneral.currModel);
|
||||
*buf++ = '/';
|
||||
char *str = strcat_modelname(filename+sizeof(SOUNDS_PATH), g_eeGeneral.currModel);
|
||||
*str++ = '/';
|
||||
char * tmp = strcat_phasename(str, index);
|
||||
strcpy(tmp, suffixes[event]);
|
||||
strcat(tmp, SOUNDS_EXT);
|
||||
}
|
||||
|
||||
for (uint32_t i=0; i<MAX_PHASES; i++) {
|
||||
char *tmp = strcat_phasename(buf, i);
|
||||
sdAvailablePhaseAudioFiles[i] = (tmp != buf ? getAvailableFiles(strcat_phasename(buf, i), info, filename) : 0);
|
||||
void getSwitchAudioFile(char * filename, int index)
|
||||
{
|
||||
strcpy(filename, SOUNDS_PATH "/");
|
||||
strncpy(filename+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2);
|
||||
char *str = strcat_modelname(filename+sizeof(SOUNDS_PATH), g_eeGeneral.currModel);
|
||||
*str++ = '/';
|
||||
int len = STR_VSWITCHES[0];
|
||||
strncpy(str, &STR_VSWITCHES[1+len*index], len);
|
||||
str += len-1;
|
||||
if (*str == '\300') {
|
||||
strcpy(str, "-up");
|
||||
str += 3;
|
||||
}
|
||||
else if (*str == '-') {
|
||||
strcpy(str, "-mid");
|
||||
str += 4;
|
||||
}
|
||||
else if (*str == '\301') {
|
||||
strcpy(str, "-down");
|
||||
str += 5;
|
||||
}
|
||||
else {
|
||||
str += 1;
|
||||
}
|
||||
strcat(str, SOUNDS_EXT);
|
||||
}
|
||||
|
||||
void getLogicalSwitchAudioFile(char * filename, int index, unsigned int event)
|
||||
{
|
||||
strcpy(filename, SOUNDS_PATH "/");
|
||||
strncpy(filename+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2);
|
||||
char *str = strcat_modelname(filename+sizeof(SOUNDS_PATH), g_eeGeneral.currModel);
|
||||
*str++ = '/';
|
||||
int len = STR_VSWITCHES[0];
|
||||
strncpy(str, &STR_VSWITCHES[1+len*(index+SWSRC_FIRST_CSW-1)], len);
|
||||
str += len;
|
||||
strcpy(str, suffixes[event]);
|
||||
strcat(str, SOUNDS_EXT);
|
||||
}
|
||||
|
||||
void referenceModelAudioFiles()
|
||||
{
|
||||
char filename[AUDIO_FILENAME_MAXLEN+1];
|
||||
|
||||
{
|
||||
// Phases Audio Files <phasename>-[on|off].wav
|
||||
uint32_t mask = 0;
|
||||
for (int i=0; i<MAX_PHASES; i++) {
|
||||
for (int event=0; event<2; event++) {
|
||||
getPhaseAudioFile(filename, i, event);
|
||||
if (isFileAvailable(filename)) {
|
||||
mask |= MASK_PHASE_AUDIO_FILE(i, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
sdAvailablePhaseAudioFiles = mask;
|
||||
}
|
||||
|
||||
/* for (uint32_t i=0; i<MAX_MIXERS; i++) {
|
||||
char *tmp = strcat_mixername_nodefault(buf, i);
|
||||
sdAvailableMixerAudioFiles[i] = (tmp != buf ? getAvailableFiles(tmp, info, filename) : 0);
|
||||
} */
|
||||
{
|
||||
// Switches Audio Files <switchname>-[up|mid|down].wav
|
||||
uint32_t mask = 0;
|
||||
for (int i=0; i<SWSRC_LAST_SWITCH+NUM_XPOTS*POTS_POS_COUNT; i++) {
|
||||
getSwitchAudioFile(filename, i);
|
||||
if (isFileAvailable(filename)) {
|
||||
mask |= MASK_SWITCH_AUDIO_FILE(i);
|
||||
}
|
||||
}
|
||||
sdAvailableSwitchAudioFiles = mask;
|
||||
}
|
||||
|
||||
{
|
||||
// Logical Switches Audio Files <switchname>-[on|off].wav
|
||||
uint64_t mask = 0;
|
||||
for (int i=0; i<NUM_CSW; i++) {
|
||||
for (int event=0; event<2; event++) {
|
||||
getLogicalSwitchAudioFile(filename, i, event);
|
||||
if (isFileAvailable(filename)) {
|
||||
mask |= MASK_LOGICAL_SWITCH_AUDIO_FILE(i, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
sdAvailableLogicalSwitchAudioFiles = mask;
|
||||
}
|
||||
}
|
||||
|
||||
bool isAudioFileAvailable(uint32_t i, char * filename)
|
||||
bool isAudioFileReferenced(uint32_t i, char * filename)
|
||||
{
|
||||
uint8_t category = (i >> 24);
|
||||
uint8_t index = (i >> 16) & 0xFF;
|
||||
uint8_t event = i & 0xFF;
|
||||
|
||||
#if 0
|
||||
printf("isAudioFileAvailable(%08x)\n", i); fflush(stdout);
|
||||
printf("isAudioFileReferenced(%08x)\n", i); fflush(stdout);
|
||||
#endif
|
||||
|
||||
if (category == SYSTEM_AUDIO_CATEGORY) {
|
||||
if (sdAvailableSystemAudioFiles & ((uint64_t)1 << event)) {
|
||||
strcpy(filename, SYSTEM_SOUNDS_PATH "/");
|
||||
strncpy(filename+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2);
|
||||
strcpy(filename+sizeof(SYSTEM_SOUNDS_PATH), audioFilenames[i]);
|
||||
strcat(filename+sizeof(SYSTEM_SOUNDS_PATH), SOUNDS_EXT);
|
||||
if (sdAvailableSystemAudioFiles & MASK_SYSTEM_AUDIO_FILE(index)) {
|
||||
getSystemAudioFile(filename, index);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (category == PHASE_AUDIO_CATEGORY) {
|
||||
if (sdAvailablePhaseAudioFiles[index] & ((uint32_t)1 << event)) {
|
||||
strcpy(filename, SOUNDS_PATH "/");
|
||||
strncpy(filename+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2);
|
||||
char *str = strcat_modelname(filename+sizeof(SOUNDS_PATH), g_eeGeneral.currModel);
|
||||
*str++ = '/';
|
||||
char * tmp = strcat_phasename(str, index);
|
||||
if (tmp != str) {
|
||||
strcpy(tmp, suffixes[event]);
|
||||
strcat(tmp, SOUNDS_EXT);
|
||||
return true;
|
||||
}
|
||||
if (sdAvailablePhaseAudioFiles & MASK_PHASE_AUDIO_FILE(index, event)) {
|
||||
getPhaseAudioFile(filename, index, event);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (category == MIXER_AUDIO_CATEGORY) {
|
||||
if (sdAvailableMixerAudioFiles[index] & ((uint32_t)1 << event)) {
|
||||
strcpy(filename, SOUNDS_PATH "/");
|
||||
strncpy(filename+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2);
|
||||
char *str = strcat_modelname(filename+sizeof(SOUNDS_PATH), g_eeGeneral.currModel);
|
||||
*str++ = '/';
|
||||
char * tmp = strcat_mixername(str, index);
|
||||
if (tmp != str) {
|
||||
strcpy(tmp, suffixes[event]);
|
||||
strcat(tmp, SOUNDS_EXT);
|
||||
return true;
|
||||
}
|
||||
else if (category == SWITCH_AUDIO_CATEGORY) {
|
||||
if (sdAvailableSwitchAudioFiles & MASK_SWITCH_AUDIO_FILE(index)) {
|
||||
getSwitchAudioFile(filename, index);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (category == LOGICAL_SWITCH_AUDIO_CATEGORY) {
|
||||
if (sdAvailableLogicalSwitchAudioFiles & MASK_LOGICAL_SWITCH_AUDIO_FILE(index, event)) {
|
||||
getLogicalSwitchAudioFile(filename, index, event);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
#define isAudioFileAvailable(i, f) false
|
||||
#define isAudioFileReferenced(i, f) false
|
||||
#endif
|
||||
|
||||
// TODO should be generated and in flash rather than in ram
|
||||
int16_t alawTable[256];
|
||||
int16_t ulawTable[256];
|
||||
|
||||
@@ -757,10 +815,6 @@ void AudioQueue::reset()
|
||||
|
||||
void audioEvent(uint8_t e, uint16_t f)
|
||||
{
|
||||
#if defined(SDCARD)
|
||||
char filename[AUDIO_FILENAME_MAXLEN+1];
|
||||
#endif
|
||||
|
||||
#if defined(HAPTIC)
|
||||
haptic.event(e); //do this before audio to help sync timings
|
||||
#endif
|
||||
@@ -773,7 +827,8 @@ void audioEvent(uint8_t e, uint16_t f)
|
||||
|
||||
if (g_eeGeneral.beepMode>0 || (g_eeGeneral.beepMode==0 && e>=AU_TRIM_MOVE) || (g_eeGeneral.beepMode>=-1 && e<=AU_ERROR)) {
|
||||
#if defined(SDCARD)
|
||||
if (e < AU_FRSKY_FIRST && isAudioFileAvailable(e, filename)) {
|
||||
char filename[AUDIO_FILENAME_MAXLEN+1];
|
||||
if (e < AU_FRSKY_FIRST && isAudioFileReferenced(e, filename)) {
|
||||
audioQueue.playFile(filename);
|
||||
}
|
||||
else
|
||||
|
||||
+19
-13
@@ -277,16 +277,21 @@ void audioStart();
|
||||
|
||||
#define AUDIO_HEARTBEAT()
|
||||
|
||||
#define SYSTEM_AUDIO_CATEGORY 0
|
||||
#define MODEL_AUDIO_CATEGORY 1
|
||||
#define PHASE_AUDIO_CATEGORY 2
|
||||
#define MIXER_AUDIO_CATEGORY 3
|
||||
enum AutomaticPromptsCategories {
|
||||
SYSTEM_AUDIO_CATEGORY,
|
||||
MODEL_AUDIO_CATEGORY,
|
||||
PHASE_AUDIO_CATEGORY,
|
||||
SWITCH_AUDIO_CATEGORY,
|
||||
LOGICAL_SWITCH_AUDIO_CATEGORY,
|
||||
};
|
||||
|
||||
#define AUDIO_EVENT_OFF 0
|
||||
#define AUDIO_EVENT_ON 1
|
||||
#define AUDIO_EVENT_BG 2
|
||||
enum AutomaticPromptsEvents {
|
||||
AUDIO_EVENT_OFF,
|
||||
AUDIO_EVENT_ON,
|
||||
AUDIO_EVENT_MID,
|
||||
};
|
||||
|
||||
extern void pushPrompt(uint16_t prompt, uint8_t id=0);
|
||||
void pushPrompt(uint16_t prompt, uint8_t id=0);
|
||||
|
||||
#define I18N_PLAY_FUNCTION(lng, x, ...) void lng ## _ ## x(__VA_ARGS__, uint8_t id)
|
||||
#define PLAY_FUNCTION(x, ...) void x(__VA_ARGS__, uint8_t id)
|
||||
@@ -300,15 +305,16 @@ extern void pushPrompt(uint16_t prompt, uint8_t id=0);
|
||||
#define AUDIO_RESET() audioQueue.reset()
|
||||
|
||||
#if defined(SDCARD)
|
||||
#define PLAY_PHASE_OFF(phase) do { char filename[AUDIO_FILENAME_MAXLEN+1]; if (isAudioFileAvailable((PHASE_AUDIO_CATEGORY << 24) + (phase << 16) + AUDIO_EVENT_OFF, filename)) audioQueue.playFile(filename); } while (0)
|
||||
#define PLAY_PHASE_ON(phase) do { char filename[AUDIO_FILENAME_MAXLEN+1]; if (isAudioFileAvailable((PHASE_AUDIO_CATEGORY << 24) + (phase << 16) + AUDIO_EVENT_ON, filename)) audioQueue.playFile(filename); } while (0)
|
||||
#define PLAY_PHASE_OFF(phase) do { char filename[AUDIO_FILENAME_MAXLEN+1]; if (isAudioFileReferenced((PHASE_AUDIO_CATEGORY << 24) + (phase << 16) + AUDIO_EVENT_OFF, filename)) audioQueue.playFile(filename); } while (0)
|
||||
#define PLAY_PHASE_ON(phase) do { char filename[AUDIO_FILENAME_MAXLEN+1]; if (isAudioFileReferenced((PHASE_AUDIO_CATEGORY << 24) + (phase << 16) + AUDIO_EVENT_ON, filename)) audioQueue.playFile(filename); } while (0)
|
||||
#else
|
||||
#define PLAY_PHASE_OFF(phase)
|
||||
#define PLAY_PHASE_ON(phase)
|
||||
#endif
|
||||
|
||||
extern void refreshSystemAudioFiles();
|
||||
extern void refreshModelAudioFiles();
|
||||
extern bool isAudioFileAvailable(uint32_t i, char * filename);
|
||||
void referenceSystemAudioFiles();
|
||||
void referenceModelAudioFiles();
|
||||
|
||||
bool isAudioFileReferenced(uint32_t i, char * filename/*at least AUDIO_FILENAME_MAXLEN+1 long*/);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -404,7 +404,7 @@ void eeLoadModel(uint8_t id)
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM) && defined(SDCARD)
|
||||
refreshModelAudioFiles();
|
||||
referenceModelAudioFiles();
|
||||
#endif
|
||||
|
||||
LOAD_MODEL_BITMAP();
|
||||
|
||||
@@ -978,7 +978,7 @@ void eeLoadModel(uint8_t id)
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM) && defined(SDCARD)
|
||||
refreshModelAudioFiles();
|
||||
referenceModelAudioFiles();
|
||||
#endif
|
||||
|
||||
LOAD_MODEL_BITMAP();
|
||||
|
||||
+1
-2
@@ -1616,8 +1616,7 @@ uint8_t zlen(const char *str, uint8_t size);
|
||||
bool zexist(const char *str, uint8_t size);
|
||||
char * strcat_zchar(char * dest, char * name, uint8_t size, const char *defaultName, uint8_t defaultNameSize, uint8_t defaultIdx);
|
||||
#define strcat_modelname(dest, idx) strcat_zchar(dest, modelHeaders[idx].name, LEN_MODEL_NAME, STR_MODEL, PSIZE(TR_MODEL), idx+1)
|
||||
#define strcat_phasename(dest, idx) strcat_zchar(dest, g_model.phaseData[idx].name, LEN_FP_NAME, NULL, 0, 0)
|
||||
#define strcat_mixername(dest, idx) strcat_zchar(dest, g_model.mixData[idx].name, LEN_EXPOMIX_NAME, NULL, 0, 0)
|
||||
#define strcat_phasename(dest, idx) strcat_zchar(dest, g_model.phaseData[idx].name, LEN_FP_NAME, STR_FP, PSIZE(TR_FP), idx+1)
|
||||
#define ZLEN(s) zlen(s, sizeof(s))
|
||||
#define ZEXIST(s) zexist(s, sizeof(s))
|
||||
#endif
|
||||
|
||||
@@ -300,7 +300,7 @@ void *main_thread(void *)
|
||||
eeReadAll(); // load general setup and selected model
|
||||
|
||||
#if defined(CPUARM) && defined(SDCARD)
|
||||
refreshSystemAudioFiles();
|
||||
referenceSystemAudioFiles();
|
||||
#endif
|
||||
|
||||
if (g_eeGeneral.backlightMode != e_backlight_mode_off) backlightOn(); // on Tx start turn the light on
|
||||
@@ -473,9 +473,10 @@ char *convertSimuPath(const char *path)
|
||||
|
||||
FRESULT f_stat (const TCHAR * name, FILINFO *)
|
||||
{
|
||||
char *path = convertSimuPath(name);
|
||||
struct stat tmp;
|
||||
// printf("f_stat(%s)\n", path); fflush(stdout);
|
||||
return stat(convertSimuPath(name), &tmp) ? FR_INVALID_NAME : FR_OK;
|
||||
TRACE("f_stat(%s)", path);
|
||||
return stat(path, &tmp) ? FR_INVALID_NAME : FR_OK;
|
||||
}
|
||||
|
||||
FRESULT f_mount (BYTE, FATFS*)
|
||||
|
||||
@@ -1014,7 +1014,7 @@ void sdMountPoll()
|
||||
|
||||
case SD_ST_DATA:
|
||||
if (!usbPlugged() && f_mount(0, &g_FATFS_Obj) == FR_OK) {
|
||||
refreshSystemAudioFiles();
|
||||
referenceSystemAudioFiles();
|
||||
Card_state = SD_ST_MOUNTED;
|
||||
}
|
||||
break;
|
||||
@@ -1082,7 +1082,7 @@ void sdInit()
|
||||
Card_state = SD_ST_DATA;
|
||||
|
||||
if (f_mount(0, &g_FATFS_Obj) == FR_OK) {
|
||||
refreshSystemAudioFiles();
|
||||
referenceSystemAudioFiles();
|
||||
Card_state = SD_ST_MOUNTED;
|
||||
}
|
||||
|
||||
|
||||
@@ -969,7 +969,7 @@ FIL g_telemetryFile = {0};
|
||||
void sdInit()
|
||||
{
|
||||
if (f_mount(0, &g_FATFS_Obj) == FR_OK) {
|
||||
refreshSystemAudioFiles();
|
||||
referenceSystemAudioFiles();
|
||||
|
||||
#if defined(DEBUG)
|
||||
f_open(&g_telemetryFile, LOGS_PATH "/sport.log", FA_OPEN_ALWAYS | FA_WRITE);
|
||||
|
||||
Reference in New Issue
Block a user