talk.h add init status to debug menu

g#2272 adds checks for incompatible version & proper number of clips

Currently incompatible talk files will logf when failure to load occurs

Adds a message to Debug > Talk engine stats
'Talk Status: OK'
'Talk Status: ERR Incompatible voice file'
'Talk Status: ERR (#)' -- OOM, Alloc Error

Change-Id: Ifd2c1f38f710541c9cd929b8abf67bba4363ca53
This commit is contained in:
William Wilgus 2020-05-21 12:55:32 -05:00
parent bbe8c73bb8
commit 74f358cf8b
3 changed files with 49 additions and 12 deletions

View file

@ -2362,33 +2362,42 @@ static const char* dbg_talk_get_name(int selected_item, void *data,
switch(selected_item) switch(selected_item)
{ {
case 0: case 0:
if (talk_data) if (talk_data->status != TALK_STATUS_ERR_NOFILE)
snprintf(buffer, buffer_len, "Current voice file: %s", snprintf(buffer, buffer_len, "Current voice file: %s",
talk_data->voicefile); talk_data->voicefile);
else else
buffer = "No voice information available"; buffer = "No voice information available";
break; break;
case 1: case 1:
if (talk_data->status == TALK_STATUS_OK)
buffer = "Talk Status: OK";
else if (talk_data->status != TALK_STATUS_ERR_INCOMPATIBLE)
snprintf(buffer, buffer_len, "Talk Status: ERR (%i)",
talk_data->status);
else
buffer = "Talk Status: ERR Incompatible voice file";
break;
case 2:
snprintf(buffer, buffer_len, "Number of (empty) clips in voice file: (%d) %d", snprintf(buffer, buffer_len, "Number of (empty) clips in voice file: (%d) %d",
talk_data->num_empty_clips, talk_data->num_clips); talk_data->num_empty_clips, talk_data->num_clips);
break; break;
case 2: case 3:
snprintf(buffer, buffer_len, "Min/Avg/Max size of clips: %d / %d / %d", snprintf(buffer, buffer_len, "Min/Avg/Max size of clips: %d / %d / %d",
talk_data->min_clipsize, talk_data->avg_clipsize, talk_data->max_clipsize); talk_data->min_clipsize, talk_data->avg_clipsize, talk_data->max_clipsize);
break; break;
case 3: case 4:
snprintf(buffer, buffer_len, "Memory allocated: %ld.%02ld KB", snprintf(buffer, buffer_len, "Memory allocated: %ld.%02ld KB",
talk_data->memory_allocated / 1024, talk_data->memory_allocated % 1024); talk_data->memory_allocated / 1024, talk_data->memory_allocated % 1024);
break; break;
case 4: case 5:
snprintf(buffer, buffer_len, "Memory used: %ld.%02ld KB", snprintf(buffer, buffer_len, "Memory used: %ld.%02ld KB",
talk_data->memory_used / 1024, talk_data->memory_used % 1024); talk_data->memory_used / 1024, talk_data->memory_used % 1024);
break; break;
case 5: case 6:
snprintf(buffer, buffer_len, "Number of clips in cache: %d", snprintf(buffer, buffer_len, "Number of clips in cache: %d",
talk_data->cached_clips); talk_data->cached_clips);
break; break;
case 6: case 7:
snprintf(buffer, buffer_len, "Cache hits / misses: %d / %d", snprintf(buffer, buffer_len, "Cache hits / misses: %d / %d",
talk_data->cache_hits, talk_data->cache_misses); talk_data->cache_hits, talk_data->cache_misses);
break; break;
@ -2405,9 +2414,9 @@ static bool dbg_talk(void)
struct simplelist_info list; struct simplelist_info list;
struct talk_debug_data data; struct talk_debug_data data;
if (talk_get_debug_data(&data)) if (talk_get_debug_data(&data))
simplelist_info_init(&list, "Voice Information:", 7, &data); simplelist_info_init(&list, "Voice Information:", 8, &data);
else else
simplelist_info_init(&list, "Voice Information:", 1, NULL); simplelist_info_init(&list, "Voice Information:", 2, &data);
list.scroll_all = true; list.scroll_all = true;
list.hide_selection = true; list.hide_selection = true;
list.timeout = HZ; list.timeout = HZ;

View file

@ -131,6 +131,7 @@ static bool need_shutup; /* is there possibly any voice playing to be shutup */
static bool force_enqueue_next; /* enqueue next utterance even if enqueue is false */ static bool force_enqueue_next; /* enqueue next utterance even if enqueue is false */
static int queue_write; /* write index of queue, by application */ static int queue_write; /* write index of queue, by application */
static int queue_read; /* read index of queue, by ISR context */ static int queue_read; /* read index of queue, by ISR context */
static enum talk_status talk_status = TALK_STATUS_OK;
#if CONFIG_CODEC == SWCODEC #if CONFIG_CODEC == SWCODEC
/* protects queue_read, queue_write and thumbnail_buf_used */ /* protects queue_read, queue_write and thumbnail_buf_used */
static struct mutex queue_mutex SHAREDBSS_ATTR; static struct mutex queue_mutex SHAREDBSS_ATTR;
@ -595,6 +596,7 @@ static bool create_clip_buffer(size_t max_size)
return true; return true;
alloc_err: alloc_err:
talk_status = TALK_STATUS_ERR_ALLOC;
index_handle = core_free(index_handle); index_handle = core_free(index_handle);
return false; return false;
} }
@ -603,11 +605,17 @@ alloc_err:
static bool load_voicefile_index(int fd) static bool load_voicefile_index(int fd)
{ {
if (fd < 0) /* failed to open */ if (fd < 0) /* failed to open */
{
talk_status = TALK_STATUS_ERR_NOFILE;
return false; return false;
}
/* load the header first */ /* load the header first */
if (!load_header(fd, &voicefile)) if (!load_header(fd, &voicefile))
{
talk_status = TALK_STATUS_ERR_INCOMPATIBLE;
return false; return false;
}
/* format check */ /* format check */
if (voicefile.table == sizeof(struct voicefile_header)) if (voicefile.table == sizeof(struct voicefile_header))
@ -622,6 +630,7 @@ static bool load_voicefile_index(int fd)
} }
} }
talk_status = TALK_STATUS_ERR_INCOMPATIBLE;
logf("Incompatible voice file"); logf("Incompatible voice file");
logf("version %d expected %d", voicefile.version, VOICE_VERSION); logf("version %d expected %d", voicefile.version, VOICE_VERSION);
logf("target_id %d expected %d", voicefile.target_id, TARGET_ID); logf("target_id %d expected %d", voicefile.target_id, TARGET_ID);
@ -648,6 +657,7 @@ static bool load_voicefile_data(int fd)
if (UNLIKELY(cap < 0)) if (UNLIKELY(cap < 0))
{ {
logf("Not enough memory for voice. Disabling...\n"); logf("Not enough memory for voice. Disabling...\n");
talk_status = TALK_STATUS_ERR_OOM;
return false; return false;
} }
else if (voicebuf_size > (size_t)cap) else if (voicebuf_size > (size_t)cap)
@ -1629,17 +1639,25 @@ bool talk_get_debug_data(struct talk_debug_data *data)
memset(data, 0, sizeof(*data)); memset(data, 0, sizeof(*data));
if (!has_voicefile || index_handle <= 0) data->status = talk_status;
return false;
if (global_settings.lang_file[0] && global_settings.lang_file[0] != 0xff) if (global_settings.lang_file[0] && global_settings.lang_file[0] != 0xff)
p_lang = (char *)global_settings.lang_file; p_lang = (char *)global_settings.lang_file;
strlcpy(data->voicefile, p_lang, sizeof(data->voicefile));
if (!has_voicefile || index_handle <= 0)
{
if (data->status == TALK_STATUS_OK)
data->status = TALK_STATUS_ERR_NOFILE;
return false;
}
struct clip_entry *clips = core_get_data(index_handle); struct clip_entry *clips = core_get_data(index_handle);
int cached = 0; int cached = 0;
int real_clips = 0; int real_clips = 0;
strlcpy(data->voicefile, p_lang, sizeof(data->voicefile));
data->num_clips = voicefile.id1_max + voicefile.id2_max; data->num_clips = voicefile.id1_max + voicefile.id2_max;
data->avg_clipsize = data->max_clipsize = 0; data->avg_clipsize = data->max_clipsize = 0;
data->min_clipsize = INT_MAX; data->min_clipsize = INT_MAX;

View file

@ -55,6 +55,15 @@ enum {
UNIT_LAST /* END MARKER */ UNIT_LAST /* END MARKER */
}; };
/* Status of loading talk file, shown in debug_menu */
enum talk_status {
TALK_STATUS_OK = 0,
TALK_STATUS_ERR_OOM,
TALK_STATUS_ERR_ALLOC,
TALK_STATUS_ERR_NOFILE,
TALK_STATUS_ERR_INCOMPATIBLE
};
#define UNIT_SHIFT (32-5) /* this many bits left from UNIT_xx enum */ #define UNIT_SHIFT (32-5) /* this many bits left from UNIT_xx enum */
#define DECIMAL_SHIFT (32 - 8) #define DECIMAL_SHIFT (32 - 8)
@ -174,6 +183,7 @@ struct talk_debug_data {
int cached_clips; int cached_clips;
int cache_hits; int cache_hits;
int cache_misses; int cache_misses;
enum talk_status status;
}; };
bool talk_get_debug_data(struct talk_debug_data *data); bool talk_get_debug_data(struct talk_debug_data *data);