summaryrefslogtreecommitdiff
path: root/apps/talk.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/talk.c')
-rw-r--r--apps/talk.c269
1 files changed, 104 insertions, 165 deletions
diff --git a/apps/talk.c b/apps/talk.c
index 820cb75c8d..a49de09e84 100644
--- a/apps/talk.c
+++ b/apps/talk.c
@@ -80,14 +80,6 @@ const char* const file_thumbnail_ext = ".talk";
80 80
81#define LOADED_MASK 0x80000000 /* MSB */ 81#define LOADED_MASK 0x80000000 /* MSB */
82 82
83/* swcodec: cap thumbnail buffer to MAX_THUMNAIL_BUFSIZE since audio keeps
84 * playing while voice
85 * hwcodec: just use whatever is left in the audiobuffer, music
86 * playback is impossible => no cap */
87#if CONFIG_CODEC == SWCODEC
88#define MAX_THUMBNAIL_BUFSIZE 0x10000
89#endif
90
91#define DEFAULT_VOICE_LANG "english" 83#define DEFAULT_VOICE_LANG "english"
92 84
93/***************** Data types *****************/ 85/***************** Data types *****************/
@@ -124,13 +116,14 @@ struct voicefile_header /* file format of our voice file */
124#endif 116#endif
125 117
126#ifndef MAX_CLIP_BUFFER_SIZE 118#ifndef MAX_CLIP_BUFFER_SIZE
127#define MAX_CLIP_BUFFER_SIZE (1<<30) /* 1GB should be enough for everybody */ 119/* 1GB should be enough for everybody; will be capped to voicefile size */
120#define MAX_CLIP_BUFFER_SIZE (1<<30)
128#endif 121#endif
122#define THUMBNAIL_RESERVE (50000)
129 123
130/* Multiple thumbnails can be loaded back-to-back in this buffer. */ 124/* Multiple thumbnails can be loaded back-to-back in this buffer. */
131static volatile int thumbnail_buf_used SHAREDBSS_ATTR; /* length of data in 125static volatile int thumbnail_buf_used SHAREDBSS_ATTR; /* length of data in
132 thumbnail buffer */ 126 thumbnail buffer */
133static long size_for_thumbnail; /* total thumbnail buffer size */
134static struct voicefile_header voicefile; /* loaded voicefile */ 127static struct voicefile_header voicefile; /* loaded voicefile */
135static bool has_voicefile; /* a voicefile file is present */ 128static bool has_voicefile; /* a voicefile file is present */
136static bool need_shutup; /* is there possibly any voice playing to be shutup */ 129static bool need_shutup; /* is there possibly any voice playing to be shutup */
@@ -158,16 +151,9 @@ static unsigned long voicefile_size, voicebuf_size;
158 151
159struct queue_entry /* one entry of the internal queue */ 152struct queue_entry /* one entry of the internal queue */
160{ 153{
161 int offset; /* actually a buflib handle if type == HANDLE */ 154 int handle; /* buflib handle to the clip data */
162 int length; /* total length of the clip */ 155 int length; /* total length of the clip */
163 int remaining; /* bytes that still need to be deoded */ 156 int remaining; /* bytes that still need to be deoded */
164 /* for large QUEUE_SIZE values it might be worthwhile to merge the type
165 * into the bits of the above members (as a space saver). For small values
166 * the required extra code outweights this so it's not done here */
167 enum offset_type {
168 TALK_HANDLE,
169 THUMB_OFFSET,
170 } type;
171}; 157};
172 158
173static struct buflib_context clip_ctx; 159static struct buflib_context clip_ctx;
@@ -186,7 +172,7 @@ static struct queue_entry silence, *last_clip;
186 172
187/***************** Private implementation *****************/ 173/***************** Private implementation *****************/
188 174
189static int index_handle, talk_handle, thumb_handle; 175static int index_handle, talk_handle;
190 176
191static int move_callback(int handle, void *current, void *new) 177static int move_callback(int handle, void *current, void *new)
192{ 178{
@@ -282,34 +268,12 @@ static int shrink_callback(int handle, unsigned hints, void *start, size_t old_s
282 return BUFLIB_CB_CANNOT_SHRINK; 268 return BUFLIB_CB_CANNOT_SHRINK;
283} 269}
284 270
285static int thumb_shrink_callback(int handle, unsigned hints, void *start, size_t old_size)
286{
287 (void)start;(void)old_size;(void)hints;
288
289 if (handle == thumb_handle && thumbnail_buf_used == 0)
290 {
291 mutex_lock(&read_buffer_mutex);
292 thumb_handle = core_free(handle);
293 mutex_unlock(&read_buffer_mutex);
294 return BUFLIB_CB_OK;
295 }
296
297 return BUFLIB_CB_CANNOT_SHRINK;
298}
299
300
301
302static struct buflib_callbacks talk_ops = { 271static struct buflib_callbacks talk_ops = {
303 .move_callback = move_callback, 272 .move_callback = move_callback,
304 .sync_callback = sync_callback, 273 .sync_callback = sync_callback,
305 .shrink_callback = shrink_callback, 274 .shrink_callback = shrink_callback,
306}; 275};
307 276
308static struct buflib_callbacks thumb_ops = {
309 .move_callback = move_callback,
310 .sync_callback = sync_callback,
311 .shrink_callback = thumb_shrink_callback,
312};
313 277
314static int open_voicefile(void) 278static int open_voicefile(void)
315{ 279{
@@ -375,19 +339,31 @@ static int free_oldest_clip(void)
375 struct clip_cache_metadata *cc = buflib_get_data(&clip_ctx, metadata_table_handle); 339 struct clip_cache_metadata *cc = buflib_get_data(&clip_ctx, metadata_table_handle);
376 for(age = i = 0, now = current_tick; i < max_clips; i++) 340 for(age = i = 0, now = current_tick; i < max_clips; i++)
377 { 341 {
378 if (cc[i].handle && (now - cc[i].tick) > age 342 if (cc[i].handle)
379 && cc[i].voice_id != VOICE_PAUSE) /* never consider silence */
380 { 343 {
381 age = now - cc[i].tick; 344 if ((now - cc[i].tick) > age && cc[i].voice_id != VOICE_PAUSE)
382 oldest = i; 345 {
346 /* find the last-used clip but never consider silence */
347 age = now - cc[i].tick;
348 oldest = i;
349 }
350 else if (cc[i].voice_id == VOICEONLY_DELIMITER)
351 {
352 /* thumb clips are freed immediately */
353 oldest = i;
354 break;
355 }
383 } 356 }
384 } 357 }
358 /* free the last one if no oldest one could be determined */
385 cc = &cc[oldest]; 359 cc = &cc[oldest];
386 cc->handle = buflib_free(&clip_ctx, cc->handle); 360 cc->handle = buflib_free(&clip_ctx, cc->handle);
387 /* need to clear the LOADED bit too */ 361 /* need to clear the LOADED bit too (not for thumb clips) */
388 clipbuf = core_get_data(index_handle); 362 if (cc->voice_id != VOICEONLY_DELIMITER)
389 clipbuf[id2index(cc->voice_id)].size &= ~LOADED_MASK; 363 {
390 364 clipbuf = core_get_data(index_handle);
365 clipbuf[id2index(cc->voice_id)].size &= ~LOADED_MASK;
366 }
391 return oldest; 367 return oldest;
392} 368}
393 369
@@ -458,6 +434,8 @@ static void load_initial_clips(int fd)
458 int handle; 434 int handle;
459 struct clip_entry* clipbuf = core_get_data(index_handle); 435 struct clip_entry* clipbuf = core_get_data(index_handle);
460 size_t clipsize = clipbuf[index].size; 436 size_t clipsize = clipbuf[index].size;
437 ssize_t ret;
438
461 if (clipsize == 0) /* clip not included in voicefile */ 439 if (clipsize == 0) /* clip not included in voicefile */
462 continue; 440 continue;
463 441
@@ -465,7 +443,8 @@ static void load_initial_clips(int fd)
465 if (handle < 0) 443 if (handle < 0)
466 break; 444 break;
467 445
468 if (read_clip_data(fd, index, handle) < 0) 446 ret = read_clip_data(fd, index, handle);
447 if (ret < 0)
469 break; 448 break;
470 449
471 add_cache_entry(handle, i++, index2id(index)); 450 add_cache_entry(handle, i++, index2id(index));
@@ -480,7 +459,6 @@ static int get_clip(long id, struct queue_entry *q)
480 int retval = -1; 459 int retval = -1;
481 struct clip_entry* clipbuf; 460 struct clip_entry* clipbuf;
482 size_t clipsize; 461 size_t clipsize;
483 enum offset_type type;
484 462
485 index = id2index(id); 463 index = id2index(id);
486 if (index == -1) 464 if (index == -1)
@@ -521,12 +499,10 @@ static int get_clip(long id, struct queue_entry *q)
521 clipsize &= ~LOADED_MASK; /* without the extra bit gives true size */ 499 clipsize &= ~LOADED_MASK; /* without the extra bit gives true size */
522 retval = cc[i].handle; 500 retval = cc[i].handle;
523 } 501 }
524 type = TALK_HANDLE;
525 502
526 q->offset = retval; 503 q->handle = retval;
527 q->length = clipsize; 504 q->length = clipsize;
528 q->remaining = clipsize; 505 q->remaining = clipsize;
529 q->type = type;
530 return 0; 506 return 0;
531} 507}
532 508
@@ -596,33 +572,6 @@ alloc_err:
596 index_handle = core_free(index_handle); 572 index_handle = core_free(index_handle);
597 return false; 573 return false;
598} 574}
599
600static bool alloc_thumbnail_buf(void)
601{
602 int handle;
603 size_t size;
604 if (thumb_handle > 0)
605 return true; /* nothing to do? */
606#if CONFIG_CODEC == SWCODEC
607 /* try to allocate the max. first, and take whatever we can get if that
608 * fails */
609 size = MAX_THUMBNAIL_BUFSIZE;
610 handle = core_alloc_ex("voice thumb", MAX_THUMBNAIL_BUFSIZE, &thumb_ops);
611 if (handle < 0)
612 {
613 size = core_allocatable();
614 handle = core_alloc_ex("voice thumb", size, &thumb_ops);
615 }
616#else
617 /* on HWCODEC, just use the rest of the remaining buffer,
618 * normal playback cannot happen anyway */
619 size = audio_buffer_available();
620 handle = core_alloc_ex("voice thumb", size, &thumb_ops);
621#endif
622 thumb_handle = handle;
623 size_for_thumbnail = (handle > 0) ? size : 0;
624 return handle > 0;
625}
626 575
627/* load the voice file into the mp3 buffer */ 576/* load the voice file into the mp3 buffer */
628static bool load_voicefile_index(int fd) 577static bool load_voicefile_index(int fd)
@@ -684,10 +633,6 @@ static bool load_voicefile_data(int fd)
684 * VOICE_PAUSE clip is specially handled */ 633 * VOICE_PAUSE clip is specially handled */
685 get_clip(VOICE_PAUSE, &silence); 634 get_clip(VOICE_PAUSE, &silence);
686 635
687 /* not an error if this fails here, might try again when the
688 * actual thumbnails are attempted to be played back */
689 alloc_thumbnail_buf();
690
691 return true; 636 return true;
692} 637}
693 638
@@ -701,18 +646,13 @@ static void* commit_transfer(struct queue_entry *qe, size_t *size)
701{ 646{
702 void *buf = NULL; /* shut up gcc */ 647 void *buf = NULL; /* shut up gcc */
703 static unsigned char *bufpos = commit_buffer; 648 static unsigned char *bufpos = commit_buffer;
704 int offset = qe->offset;
705#if CONFIG_CODEC != SWCODEC 649#if CONFIG_CODEC != SWCODEC
706 sent = MIN(qe->remaining, 0xFFFF); 650 sent = MIN(qe->remaining, 0xFFFF);
707#else 651#else
708 sent = qe->remaining; 652 sent = qe->remaining;
709#endif 653#endif
710 sent = MIN((size_t)sent, sizeof(commit_buffer)); 654 sent = MIN((size_t)sent, sizeof(commit_buffer));
711 switch (qe->type) 655 buf = buflib_get_data(&clip_ctx, qe->handle);
712 {
713 case TALK_HANDLE: buf = buflib_get_data(&clip_ctx, offset); break;
714 case THUMB_OFFSET: buf = core_get_data(thumb_handle) + offset; break;
715 }
716 /* adjust buffer position to what has been played already */ 656 /* adjust buffer position to what has been played already */
717 buf += (qe->length - qe->remaining); 657 buf += (qe->length - qe->remaining);
718 memcpy(bufpos, buf, sent); 658 memcpy(bufpos, buf, sent);
@@ -724,8 +664,8 @@ static void* commit_transfer(struct queue_entry *qe, size_t *size)
724 664
725static inline bool is_silence(struct queue_entry *qe) 665static inline bool is_silence(struct queue_entry *qe)
726{ 666{
727 if (silence.length > 0) /* silence clip available? */ 667 if (silence.handle > 0) /* silence clip available? */
728 return (qe->offset == silence.offset && qe->type == silence.type); 668 return (qe->handle == silence.handle);
729 else 669 else
730 return false; 670 return false;
731} 671}
@@ -743,21 +683,15 @@ static void mp3_callback(const void** start, size_t* size)
743 } 683 }
744 684
745 talk_queue_lock(); 685 talk_queue_lock();
746 /* check if thumbnails have been played */
747 if (qe->type == THUMB_OFFSET)
748 {
749 if (qe->remaining == 0 && (qe->length + qe->offset) == thumbnail_buf_used)
750 thumbnail_buf_used = 0;
751 }
752 686
753 /* increment read position for the just played clip */ 687 /* increment read position for the just played clip */
754 queue_read = (queue_read + 1) & QUEUE_MASK; 688 queue_read = (queue_read + 1) & QUEUE_MASK;
755 689
756 if (QUEUE_LEVEL == 0) 690 if (QUEUE_LEVEL == 0)
757 { 691 {
758 if (!is_silence(last_clip) && last_clip->type != THUMB_OFFSET) 692 if (!is_silence(last_clip))
759 { /* add silence clip when queue runs empty playing a voice clip, 693 { /* add silence clip when queue runs empty playing a voice clip,
760 * only if the previous clip wasn't silence or thumbnail */ 694 * only if the previous clip wasn't already silence */
761 queue[queue_write] = silence; 695 queue[queue_write] = silence;
762 queue_write = (queue_write + 1) & QUEUE_MASK; 696 queue_write = (queue_write + 1) & QUEUE_MASK;
763 } 697 }
@@ -793,7 +727,6 @@ void talk_force_shutup(void)
793 unsigned char* search; 727 unsigned char* search;
794 unsigned char* end; 728 unsigned char* end;
795 int len; 729 int len;
796 unsigned offset;
797 if (QUEUE_LEVEL == 0) /* has ended anyway */ 730 if (QUEUE_LEVEL == 0) /* has ended anyway */
798 return; 731 return;
799 732
@@ -802,13 +735,7 @@ void talk_force_shutup(void)
802#endif /* CONFIG_CPU == SH7034 */ 735#endif /* CONFIG_CPU == SH7034 */
803 /* search next frame boundary and continue up to there */ 736 /* search next frame boundary and continue up to there */
804 pos = search = mp3_get_pos(); 737 pos = search = mp3_get_pos();
805 offset = queue[queue_read].offset; 738 end = buflib_get_data(&clip_ctx, queue[queue_read].handle);
806 switch (queue[queue_read].type)
807 {
808 case THUMB_OFFSET: end = core_get_data(thumb_handle) + offset; break;
809 case TALK_HANDLE: end = buflib_get_data(&clip_ctx, offset); break;
810 default: end = NULL; /* shut up gcc */
811 }
812 len = queue[queue_read].length; 739 len = queue[queue_read].length;
813 740
814 if (pos >= end && pos <= (end+len)) /* really our clip? */ 741 if (pos >= end && pos <= (end+len)) /* really our clip? */
@@ -914,7 +841,6 @@ static void queue_clip(struct queue_entry *clip, bool enqueue)
914 return; 841 return;
915} 842}
916 843
917#if CONFIG_CODEC == SWCODEC
918/* return if a voice codec is required or not */ 844/* return if a voice codec is required or not */
919static bool talk_voice_required(void) 845static bool talk_voice_required(void)
920{ 846{
@@ -922,7 +848,6 @@ static bool talk_voice_required(void)
922 || (global_settings.talk_dir_clip) /* Thumbnail clips are required */ 848 || (global_settings.talk_dir_clip) /* Thumbnail clips are required */
923 || (global_settings.talk_file_clip); 849 || (global_settings.talk_file_clip);
924} 850}
925#endif
926 851
927/***************** Public implementation *****************/ 852/***************** Public implementation *****************/
928 853
@@ -951,7 +876,7 @@ void talk_init(void)
951 queue_write = queue_read = 0; /* reset the queue */ 876 queue_write = queue_read = 0; /* reset the queue */
952 memset(&voicefile, 0, sizeof(voicefile)); 877 memset(&voicefile, 0, sizeof(voicefile));
953 878
954 silence.offset = -1; /* pause clip not accessible */ 879 silence.handle = -1; /* pause clip not accessible */
955 voicefile_size = has_voicefile = 0; 880 voicefile_size = has_voicefile = 0;
956 /* need to free these as their size depends on the voice file, and 881 /* need to free these as their size depends on the voice file, and
957 * this function is called when the talk voice file changes */ 882 * this function is called when the talk voice file changes */
@@ -961,37 +886,46 @@ void talk_init(void)
961 * and so we can re-use it if it's already allocated in any event */ 886 * and so we can re-use it if it's already allocated in any event */
962 887
963 filehandle = open_voicefile(); 888 filehandle = open_voicefile();
964 if (filehandle < 0) 889 if (filehandle > 0)
965 return;
966
967 if (!load_voicefile_index(filehandle))
968 goto out;
969
970 /* Now determine the maximum buffer size needed for the voicefile.
971 * The below pretends the entire voicefile would be loaded. The buffer
972 * size is eventually capped later on in load_voicefile_data() */
973 int num_clips = voicefile.id1_max + voicefile.id2_max;
974 int non_empty = num_clips;
975 int total_size = 0, avg_size;
976 struct clip_entry *clips = core_get_data(index_handle);
977 /* check for the average clip size to estimate the maximum number of
978 * clips the buffer can hold */
979 for (int i = 0; i<num_clips; i++)
980 { 890 {
981 if (clips[i].size) 891 if (!load_voicefile_index(filehandle))
982 total_size += ALIGN_UP(clips[i].size, sizeof(void *)); 892 goto out;
983 else 893
984 non_empty -= 1; 894 /* Now determine the maximum buffer size needed for the voicefile.
895 * The below pretends the entire voicefile would be loaded. The buffer
896 * size is eventually capped later on in load_voicefile_data() */
897 int num_clips = voicefile.id1_max + voicefile.id2_max;
898 int non_empty = num_clips;
899 int total_size = 0, avg_size;
900 struct clip_entry *clips = core_get_data(index_handle);
901 /* check for the average clip size to estimate the maximum number of
902 * clips the buffer can hold */
903 for (int i = 0; i<num_clips; i++)
904 {
905 if (clips[i].size)
906 total_size += ALIGN_UP(clips[i].size, sizeof(void *));
907 else
908 non_empty -= 1;
909 }
910 avg_size = total_size / non_empty;
911 max_clips = MIN((int)(MAX_CLIP_BUFFER_SIZE/avg_size) + 1, non_empty);
912 /* account for possible thumb clips */
913 total_size += THUMBNAIL_RESERVE;
914 max_clips += 16;
915 voicefile_size = total_size;
916 has_voicefile = true;
985 } 917 }
986 avg_size = total_size / non_empty; 918 else if (talk_voice_required())
987 max_clips = MIN((int)(MAX_CLIP_BUFFER_SIZE/avg_size) + 1, non_empty); 919 {
988 voicefile_size = total_size; 920 /* create buffer just for thumb clips */
989 /* additionally to the clips we need a table to record the age of the clips 921 max_clips = 16;
922 voicefile_size = THUMBNAIL_RESERVE;
923 }
924 /* additionally to the clip we need a table to record the age of the clips
990 * so that, when memory is tight, only the most recently used ones are kept */ 925 * so that, when memory is tight, only the most recently used ones are kept */
991 voicefile_size += sizeof(struct clip_cache_metadata) * max_clips; 926 voicefile_size += sizeof(struct clip_cache_metadata) * max_clips;
992 /* compensate a bit for buflib alloc overhead. */ 927 /* compensate a bit for buflib alloc overhead. */
993 voicefile_size += BUFLIB_ALLOC_OVERHEAD * max_clips + 64; 928 voicefile_size += BUFLIB_ALLOC_OVERHEAD * max_clips + 64;
994 has_voicefile = true;
995 929
996 load_voicefile_data(filehandle); 930 load_voicefile_data(filehandle);
997 931
@@ -1003,7 +937,6 @@ void talk_init(void)
1003 937
1004out: 938out:
1005 close(filehandle); /* close again, this was just to detect presence */ 939 close(filehandle); /* close again, this was just to detect presence */
1006 filehandle = -1;
1007} 940}
1008 941
1009/* somebody else claims the mp3 buffer, e.g. for regular play/record */ 942/* somebody else claims the mp3 buffer, e.g. for regular play/record */
@@ -1035,10 +968,10 @@ int talk_id(int32_t id, bool enqueue)
1035 if (talk_handle <= 0 || index_handle <= 0) /* reload needed? */ 968 if (talk_handle <= 0 || index_handle <= 0) /* reload needed? */
1036 { 969 {
1037 int fd = open_voicefile(); 970 int fd = open_voicefile();
1038 if (fd < 0 971 if (fd < 0 || !load_voicefile_index(fd))
1039 || !load_voicefile_index(fd)
1040 || !load_voicefile_data(fd))
1041 return -1; 972 return -1;
973 load_voicefile_data(fd);
974 close(fd);
1042 } 975 }
1043 976
1044 if (id == -1) /* -1 is an indication for silence */ 977 if (id == -1) /* -1 is an indication for silence */
@@ -1100,7 +1033,7 @@ static int _talk_file(const char* filename,
1100{ 1033{
1101 int fd; 1034 int fd;
1102 int size; 1035 int size;
1103 int thumb_used; 1036 int handle, oldest = -1;
1104#if CONFIG_CODEC != SWCODEC 1037#if CONFIG_CODEC != SWCODEC
1105 struct mp3entry info; 1038 struct mp3entry info;
1106#endif 1039#endif
@@ -1110,9 +1043,8 @@ static int _talk_file(const char* filename,
1110 return -1; /* talking has been disabled */ 1043 return -1; /* talking has been disabled */
1111 if (!check_audio_status()) 1044 if (!check_audio_status())
1112 return -1; 1045 return -1;
1113 1046 if (talk_handle <= 0)
1114 if (!alloc_thumbnail_buf()) 1047 load_voicefile_data(-1);
1115 return -1;
1116 1048
1117#if CONFIG_CODEC != SWCODEC 1049#if CONFIG_CODEC != SWCODEC
1118 if(mp3info(&info, filename)) /* use this to find real start */ 1050 if(mp3info(&info, filename)) /* use this to find real start */
@@ -1130,19 +1062,17 @@ static int _talk_file(const char* filename,
1130 { 1062 {
1131 return 0; 1063 return 0;
1132 } 1064 }
1133 1065 size = filesize(fd);
1134 thumb_used = thumbnail_buf_used;
1135 if(filesize(fd) > size_for_thumbnail -thumb_used)
1136 { /* Don't play truncated clips */
1137 close(fd);
1138 return 0;
1139 }
1140 1066
1141#if CONFIG_CODEC != SWCODEC 1067#if CONFIG_CODEC != SWCODEC
1142 lseek(fd, info.first_frame_offset, SEEK_SET); /* behind ID data */ 1068 size -= lseek(fd, info.first_frame_offset, SEEK_SET); /* behind ID data */
1143#endif 1069#endif
1144 1070
1145 size = read_to_handle(fd, thumb_handle, thumb_used, size_for_thumbnail - thumb_used); 1071 /* free clips from cache until this one succeeds to allocate */
1072 while ((handle = buflib_alloc(&clip_ctx, size)) < 0)
1073 oldest = free_oldest_clip();
1074
1075 size = read_to_handle_ex(fd, &clip_ctx, handle, 0, size);
1146 close(fd); 1076 close(fd);
1147 1077
1148 /* ToDo: find audio, skip ID headers and trailers */ 1078 /* ToDo: find audio, skip ID headers and trailers */
@@ -1150,21 +1080,25 @@ static int _talk_file(const char* filename,
1150 if (size > 0) /* Don't play missing clips */ 1080 if (size > 0) /* Don't play missing clips */
1151 { 1081 {
1152 struct queue_entry clip; 1082 struct queue_entry clip;
1083 clip.handle = handle;
1084 clip.length = clip.remaining = size;
1153#if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR) 1085#if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
1154 /* bitswap doesnt yield() */ 1086 /* bitswap doesnt yield() */
1155 bitswap(core_get_data(thumb_handle), size); 1087 bitswap(buflib_get_data(&clip_ctx, handle), size);
1156#endif 1088#endif
1157 if(prefix_ids) 1089 if(prefix_ids)
1158 /* prefix thumbnail by speaking these ids, but only now 1090 /* prefix thumbnail by speaking these ids, but only now
1159 that we know there's actually a thumbnail to be 1091 that we know there's actually a thumbnail to be
1160 spoken. */ 1092 spoken. */
1161 talk_idarray(prefix_ids, true); 1093 talk_idarray(prefix_ids, true);
1162 talk_queue_lock(); 1094 /* finally insert into metadata table. thumb clips go under the
1163 thumbnail_buf_used = thumb_used + size; 1095 * VOICEONLY_DELIMITER id so the cache can distinguish them from
1164 talk_queue_unlock(); 1096 * normal clips */
1165 clip = (struct queue_entry){ .offset = thumb_used, .length = size, .remaining = size, .type = THUMB_OFFSET }; 1097 add_cache_entry(handle, oldest, VOICEONLY_DELIMITER);
1166 queue_clip(&clip, true); 1098 queue_clip(&clip, true);
1167 } 1099 }
1100 else
1101 buflib_free(&clip_ctx, handle);
1168 1102
1169 return size; 1103 return size;
1170} 1104}
@@ -1566,6 +1500,7 @@ void talk_time(const struct tm *tm, bool enqueue)
1566bool talk_get_debug_data(struct talk_debug_data *data) 1500bool talk_get_debug_data(struct talk_debug_data *data)
1567{ 1501{
1568 char* p_lang = DEFAULT_VOICE_LANG; /* default */ 1502 char* p_lang = DEFAULT_VOICE_LANG; /* default */
1503 struct clip_cache_metadata *cc;
1569 1504
1570 memset(data, 0, sizeof(*data)); 1505 memset(data, 0, sizeof(*data));
1571 1506
@@ -1593,17 +1528,21 @@ bool talk_get_debug_data(struct talk_debug_data *data)
1593 if (size > data->max_clipsize) 1528 if (size > data->max_clipsize)
1594 data->max_clipsize = size; 1529 data->max_clipsize = size;
1595 data->avg_clipsize += size; 1530 data->avg_clipsize += size;
1596 if (clips[i].size & LOADED_MASK) 1531 }
1597 cached++; 1532 cc = buflib_get_data(&clip_ctx, metadata_table_handle);
1533 for (int i = 0; i < (int) max_clips; i++)
1534 {
1535 if (cc[i].handle > 0)
1536 cached += 1;
1598 } 1537 }
1599 data->avg_clipsize /= real_clips; 1538 data->avg_clipsize /= real_clips;
1600 data->num_empty_clips = data->num_clips - real_clips; 1539 data->num_empty_clips = data->num_clips - real_clips;
1601 data->memory_allocated = sizeof(commit_buffer) + sizeof(voicefile) 1540 data->memory_allocated = sizeof(commit_buffer) + sizeof(voicefile)
1602 + data->num_clips * sizeof(struct clip_entry) 1541 + data->num_clips * sizeof(struct clip_entry)
1603 + voicebuf_size + size_for_thumbnail; 1542 + voicebuf_size;
1604 data->memory_used = data->memory_allocated - size_for_thumbnail + thumbnail_buf_used; 1543 data->memory_used = 0;
1605 if (talk_handle > 0) 1544 if (talk_handle > 0)
1606 data->memory_used -= buflib_available(&clip_ctx); 1545 data->memory_used = data->memory_allocated - buflib_available(&clip_ctx);
1607 data->cached_clips = cached; 1546 data->cached_clips = cached;
1608 data->cache_hits = cache_hits; 1547 data->cache_hits = cache_hits;
1609 data->cache_misses = cache_misses; 1548 data->cache_misses = cache_misses;