Issue #713 - Automatic Switch Audio Files (part 1)

This commit is contained in:
Bertrand Songis
2014-02-19 10:41:03 +01:00
parent fbd0744431
commit e38a4d320f
8 changed files with 166 additions and 105 deletions
+137 -82
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -404,7 +404,7 @@ void eeLoadModel(uint8_t id)
#endif
#if defined(CPUARM) && defined(SDCARD)
refreshModelAudioFiles();
referenceModelAudioFiles();
#endif
LOAD_MODEL_BITMAP();
+1 -1
View File
@@ -978,7 +978,7 @@ void eeLoadModel(uint8_t id)
#endif
#if defined(CPUARM) && defined(SDCARD)
refreshModelAudioFiles();
referenceModelAudioFiles();
#endif
LOAD_MODEL_BITMAP();
+1 -2
View File
@@ -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
+4 -3
View File
@@ -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*)
+2 -2
View File
@@ -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;
}
+1 -1
View File
@@ -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);