summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/filetree.c1
-rw-r--r--apps/main.c11
-rw-r--r--apps/menus/main_menu.c4
-rw-r--r--apps/misc.c3
-rw-r--r--apps/mp3data.c41
-rw-r--r--apps/mp3data.h30
-rw-r--r--apps/mpeg.c89
-rw-r--r--apps/playback.c45
-rw-r--r--apps/playback.h1
-rw-r--r--apps/playlist.c18
-rw-r--r--apps/playlist_viewer.c3
-rw-r--r--apps/plugin.c8
-rw-r--r--apps/plugin.h8
-rw-r--r--apps/plugins/vbrfix.c5
-rw-r--r--apps/recorder/pcm_record.c2
-rw-r--r--apps/tagcache.c8
-rw-r--r--apps/talk.c111
-rw-r--r--apps/talk.h1
-rw-r--r--firmware/buffer.c75
-rw-r--r--firmware/common/dircache.c22
-rw-r--r--firmware/export/audio.h6
-rw-r--r--firmware/include/buffer.h18
-rw-r--r--firmware/include/dircache.h3
-rw-r--r--firmware/rolo.c28
24 files changed, 350 insertions, 191 deletions
diff --git a/apps/filetree.c b/apps/filetree.c
index a7c989fc5e..1aee80b6b2 100644
--- a/apps/filetree.c
+++ b/apps/filetree.c
@@ -600,6 +600,7 @@ int ft_enter(struct tree_context* c)
600 /* firmware file */ 600 /* firmware file */
601 case FILE_ATTR_MOD: 601 case FILE_ATTR_MOD:
602 splash(0, ID2P(LANG_WAIT)); 602 splash(0, ID2P(LANG_WAIT));
603 audio_hard_stop();
603 rolo_load(buf); 604 rolo_load(buf);
604 break; 605 break;
605#endif 606#endif
diff --git a/apps/main.c b/apps/main.c
index 0b566b5c01..9cb724562c 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -337,11 +337,11 @@ static void init_tagcache(void)
337static void init(void) 337static void init(void)
338{ 338{
339 system_init(); 339 system_init();
340 buffer_init();
340 kernel_init(); 341 kernel_init();
341#ifdef APPLICATION 342#ifdef APPLICATION
342 paths_init(); 343 paths_init();
343#endif 344#endif
344 buffer_init();
345 enable_irq(); 345 enable_irq();
346 lcd_init(); 346 lcd_init();
347#ifdef HAVE_REMOTE_LCD 347#ifdef HAVE_REMOTE_LCD
@@ -428,13 +428,7 @@ static void init(void)
428#endif 428#endif
429 429
430 system_init(); 430 system_init();
431#if defined(IPOD_VIDEO) 431 buffer_init();
432 audiobufend=(unsigned char *)audiobufend_lds;
433 if(MEMORYSIZE==64 && probed_ramsize!=64)
434 {
435 audiobufend -= (32<<20);
436 }
437#endif
438 kernel_init(); 432 kernel_init();
439 433
440#ifdef HAVE_ADJUSTABLE_CPU_FREQ 434#ifdef HAVE_ADJUSTABLE_CPU_FREQ
@@ -445,7 +439,6 @@ static void init(void)
445 cpu_boost(true); 439 cpu_boost(true);
446#endif 440#endif
447 441
448 buffer_init();
449 442
450 settings_reset(); 443 settings_reset();
451 444
diff --git a/apps/menus/main_menu.c b/apps/menus/main_menu.c
index 6ee7ba4156..c5758d1274 100644
--- a/apps/menus/main_menu.c
+++ b/apps/menus/main_menu.c
@@ -182,7 +182,7 @@ static const char* info_getname(int selected_item, void *data,
182 182
183 case INFO_BUFFER: /* buffer */ 183 case INFO_BUFFER: /* buffer */
184 { 184 {
185 long kib = (audiobufend - audiobuf) / 1024; /* to KiB */ 185 long kib = buffer_available() / 1024; /* to KiB */
186 output_dyn_value(s1, sizeof(s1), kib, kbyte_units, true); 186 output_dyn_value(s1, sizeof(s1), kib, kbyte_units, true);
187 snprintf(buffer, buffer_len, "%s %s", str(LANG_BUFFER_STAT), s1); 187 snprintf(buffer, buffer_len, "%s %s", str(LANG_BUFFER_STAT), s1);
188 } 188 }
@@ -272,7 +272,7 @@ static int info_speak_item(int selected_item, void * data)
272 case INFO_BUFFER: /* buffer */ 272 case INFO_BUFFER: /* buffer */
273 { 273 {
274 talk_id(LANG_BUFFER_STAT, false); 274 talk_id(LANG_BUFFER_STAT, false);
275 long kib = (audiobufend - audiobuf) / 1024; /* to KiB */ 275 long kib = buffer_available() / 1024; /* to KiB */
276 output_dyn_value(NULL, 0, kib, kbyte_units, true); 276 output_dyn_value(NULL, 0, kib, kbyte_units, true);
277 break; 277 break;
278 } 278 }
diff --git a/apps/misc.c b/apps/misc.c
index fef55d5e2e..d74fe73205 100644
--- a/apps/misc.c
+++ b/apps/misc.c
@@ -766,7 +766,10 @@ void check_bootfile(bool do_rolo)
766 static const struct text_message message={ lines, 2 }; 766 static const struct text_message message={ lines, 2 };
767 button_clear_queue(); /* Empty the keyboard buffer */ 767 button_clear_queue(); /* Empty the keyboard buffer */
768 if(gui_syncyesno_run(&message, NULL, NULL) == YESNO_YES) 768 if(gui_syncyesno_run(&message, NULL, NULL) == YESNO_YES)
769 {
770 audio_hard_stop();
769 rolo_load(BOOTDIR "/" BOOTFILE); 771 rolo_load(BOOTDIR "/" BOOTFILE);
772 }
770 } 773 }
771 } 774 }
772 wrtdate = info.wrtdate; 775 wrtdate = info.wrtdate;
diff --git a/apps/mp3data.c b/apps/mp3data.c
index 9fed727609..53f13f4f64 100644
--- a/apps/mp3data.c
+++ b/apps/mp3data.c
@@ -311,17 +311,18 @@ unsigned long find_next_frame(int fd,
311#ifndef __PCTOOL__ 311#ifndef __PCTOOL__
312static int fnf_read_index; 312static int fnf_read_index;
313static int fnf_buf_len; 313static int fnf_buf_len;
314static unsigned char *fnf_buf;
314 315
315static int buf_getbyte(int fd, unsigned char *c) 316static int buf_getbyte(int fd, unsigned char *c)
316{ 317{
317 if(fnf_read_index < fnf_buf_len) 318 if(fnf_read_index < fnf_buf_len)
318 { 319 {
319 *c = audiobuf[fnf_read_index++]; 320 *c = fnf_buf[fnf_read_index++];
320 return 1; 321 return 1;
321 } 322 }
322 else 323 else
323 { 324 {
324 fnf_buf_len = read(fd, audiobuf, audiobufend - audiobuf); 325 fnf_buf_len = read(fd, fnf_buf, fnf_buf_len);
325 if(fnf_buf_len < 0) 326 if(fnf_buf_len < 0)
326 return -1; 327 return -1;
327 328
@@ -329,7 +330,7 @@ static int buf_getbyte(int fd, unsigned char *c)
329 330
330 if(fnf_buf_len > 0) 331 if(fnf_buf_len > 0)
331 { 332 {
332 *c = audiobuf[fnf_read_index++]; 333 *c = fnf_buf[fnf_read_index++];
333 return 1; 334 return 1;
334 } 335 }
335 else 336 else
@@ -345,7 +346,7 @@ static int buf_seek(int fd, int len)
345 { 346 {
346 len = fnf_read_index - fnf_buf_len; 347 len = fnf_read_index - fnf_buf_len;
347 348
348 fnf_buf_len = read(fd, audiobuf, audiobufend - audiobuf); 349 fnf_buf_len = read(fd, fnf_buf, fnf_buf_len);
349 if(fnf_buf_len < 0) 350 if(fnf_buf_len < 0)
350 return -1; 351 return -1;
351 352
@@ -361,9 +362,10 @@ static int buf_seek(int fd, int len)
361 return 0; 362 return 0;
362} 363}
363 364
364static void buf_init(void) 365static void buf_init(unsigned char* buf, size_t buflen)
365{ 366{
366 fnf_buf_len = 0; 367 fnf_buf = buf;
368 fnf_buf_len = buflen;
367 fnf_read_index = 0; 369 fnf_read_index = 0;
368} 370}
369 371
@@ -372,8 +374,9 @@ static unsigned long buf_find_next_frame(int fd, long *offset, long max_offset)
372 return __find_next_frame(fd, offset, max_offset, 0, buf_getbyte, true); 374 return __find_next_frame(fd, offset, max_offset, 0, buf_getbyte, true);
373} 375}
374 376
375static int audiobuflen; 377static size_t mem_buflen;
376static int mem_pos; 378static unsigned char* mem_buf;
379static size_t mem_pos;
377static int mem_cnt; 380static int mem_cnt;
378static int mem_maxlen; 381static int mem_maxlen;
379 382
@@ -381,8 +384,8 @@ static int mem_getbyte(int dummy, unsigned char *c)
381{ 384{
382 dummy = dummy; 385 dummy = dummy;
383 386
384 *c = audiobuf[mem_pos++]; 387 *c = mem_buf[mem_pos++];
385 if(mem_pos >= audiobuflen) 388 if(mem_pos >= mem_buflen)
386 mem_pos = 0; 389 mem_pos = 0;
387 390
388 if(mem_cnt++ >= mem_maxlen) 391 if(mem_cnt++ >= mem_maxlen)
@@ -394,9 +397,11 @@ static int mem_getbyte(int dummy, unsigned char *c)
394unsigned long mem_find_next_frame(int startpos, 397unsigned long mem_find_next_frame(int startpos,
395 long *offset, 398 long *offset,
396 long max_offset, 399 long max_offset,
397 unsigned long reference_header) 400 unsigned long reference_header,
401 unsigned char* buf, size_t buflen)
398{ 402{
399 audiobuflen = audiobufend - audiobuf; 403 mem_buf = buf;
404 mem_buflen = buflen;
400 mem_pos = startpos; 405 mem_pos = startpos;
401 mem_cnt = 0; 406 mem_cnt = 0;
402 mem_maxlen = max_offset; 407 mem_maxlen = max_offset;
@@ -620,8 +625,9 @@ static void long2bytes(unsigned char *buf, long val)
620 buf[3] = val & 0xff; 625 buf[3] = val & 0xff;
621} 626}
622 627
623int count_mp3_frames(int fd, int startpos, int filesize, 628int count_mp3_frames(int fd, int startpos, int filesize,
624 void (*progressfunc)(int)) 629 void (*progressfunc)(int),
630 unsigned char* buf, size_t buflen)
625{ 631{
626 unsigned long header = 0; 632 unsigned long header = 0;
627 struct mp3info info; 633 struct mp3info info;
@@ -637,7 +643,7 @@ int count_mp3_frames(int fd, int startpos, int filesize,
637 if(lseek(fd, startpos, SEEK_SET) < 0) 643 if(lseek(fd, startpos, SEEK_SET) < 0)
638 return -1; 644 return -1;
639 645
640 buf_init(); 646 buf_init(buf, buflen);
641 647
642 /* Find out the total number of frames */ 648 /* Find out the total number of frames */
643 num_frames = 0; 649 num_frames = 0;
@@ -687,7 +693,8 @@ static const char cooltext[] = "Rockbox - rocks your box";
687int create_xing_header(int fd, long startpos, long filesize, 693int create_xing_header(int fd, long startpos, long filesize,
688 unsigned char *buf, unsigned long num_frames, 694 unsigned char *buf, unsigned long num_frames,
689 unsigned long rec_time, unsigned long header_template, 695 unsigned long rec_time, unsigned long header_template,
690 void (*progressfunc)(int), bool generate_toc) 696 void (*progressfunc)(int), bool generate_toc,
697 unsigned char *tempbuf, size_t tempbuflen )
691{ 698{
692 struct mp3info info; 699 struct mp3info info;
693 unsigned char toc[100]; 700 unsigned char toc[100];
@@ -705,7 +712,7 @@ int create_xing_header(int fd, long startpos, long filesize,
705 if(generate_toc) 712 if(generate_toc)
706 { 713 {
707 lseek(fd, startpos, SEEK_SET); 714 lseek(fd, startpos, SEEK_SET);
708 buf_init(); 715 buf_init(tempbuf, tempbuflen);
709 716
710 /* Generate filepos table */ 717 /* Generate filepos table */
711 last_pos = 0; 718 last_pos = 0;
diff --git a/apps/mp3data.h b/apps/mp3data.h
index edda352aab..762c2f4583 100644
--- a/apps/mp3data.h
+++ b/apps/mp3data.h
@@ -26,6 +26,8 @@
26#define MPEG_VERSION2 1 26#define MPEG_VERSION2 1
27#define MPEG_VERSION2_5 2 27#define MPEG_VERSION2_5 2
28 28
29#include <string.h> /* size_t */
30
29struct mp3info { 31struct mp3info {
30 /* Standard MP3 frame header fields */ 32 /* Standard MP3 frame header fields */
31 int version; 33 int version;
@@ -63,23 +65,21 @@ unsigned long find_next_frame(int fd,
63 unsigned long reference_header); 65 unsigned long reference_header);
64unsigned long mem_find_next_frame(int startpos, 66unsigned long mem_find_next_frame(int startpos,
65 long *offset, 67 long *offset,
66 long max_offset, 68 long max_offset,
67 unsigned long reference_header); 69 unsigned long reference_header,
70 unsigned char* buf, size_t buflen);
68int get_mp3file_info(int fd, 71int get_mp3file_info(int fd,
69 struct mp3info *info); 72 struct mp3info *info);
70int count_mp3_frames(int fd, 73
71 int startpos, 74int count_mp3_frames(int fd, int startpos, int filesize,
72 int filesize, 75 void (*progressfunc)(int),
73 void (*progressfunc)(int)); 76 unsigned char* buf, size_t buflen);
74int create_xing_header(int fd, 77
75 long startpos, 78int create_xing_header(int fd, long startpos, long filesize,
76 long filesize, 79 unsigned char *buf, unsigned long num_frames,
77 unsigned char *buf, 80 unsigned long rec_time, unsigned long header_template,
78 unsigned long num_frames, 81 void (*progressfunc)(int), bool generate_toc,
79 unsigned long rec_time, 82 unsigned char *tempbuf, size_t tempbuflen );
80 unsigned long header_template,
81 void (*progressfunc)(int),
82 bool generate_toc);
83 83
84extern unsigned long bytes2int(unsigned long b0, 84extern unsigned long bytes2int(unsigned long b0,
85 unsigned long b1, 85 unsigned long b1,
diff --git a/apps/mpeg.c b/apps/mpeg.c
index b11445f947..a0182ad8d2 100644
--- a/apps/mpeg.c
+++ b/apps/mpeg.c
@@ -37,6 +37,7 @@
37#include "mp3data.h" 37#include "mp3data.h"
38#include "buffer.h" 38#include "buffer.h"
39#include "mp3_playback.h" 39#include "mp3_playback.h"
40#include "talk.h"
40#include "sound.h" 41#include "sound.h"
41#include "bitswap.h" 42#include "bitswap.h"
42#include "appevents.h" 43#include "appevents.h"
@@ -144,19 +145,19 @@ static unsigned int mpeg_errno;
144static bool playing = false; /* We are playing an MP3 stream */ 145static bool playing = false; /* We are playing an MP3 stream */
145static bool is_playing = false; /* We are (attempting to) playing MP3 files */ 146static bool is_playing = false; /* We are (attempting to) playing MP3 files */
146static bool paused; /* playback is paused */ 147static bool paused; /* playback is paused */
148static char* mpeg_audiobuf; /* the audio buffer */
149static long audiobuflen; /* length of the audio buffer */
147 150
148#ifdef SIMULATOR 151#ifdef SIMULATOR
149static char mpeg_stack[DEFAULT_STACK_SIZE]; 152static char mpeg_stack[DEFAULT_STACK_SIZE];
150static struct mp3entry taginfo; 153static struct mp3entry taginfo;
151
152#else /* !SIMULATOR */ 154#else /* !SIMULATOR */
153static struct event_queue mpeg_queue SHAREDBSS_ATTR; 155static struct event_queue mpeg_queue SHAREDBSS_ATTR;
154static long mpeg_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)]; 156static long mpeg_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)];
155 157
156static int audiobuflen;
157static int audiobuf_write; 158static int audiobuf_write;
158static int audiobuf_swapwrite; 159static int audiobuf_swapwrite;
159static int audiobuf_read; 160static long audiobuf_read;
160 161
161static int mpeg_file; 162static int mpeg_file;
162 163
@@ -490,6 +491,18 @@ unsigned long mpeg_get_last_header(void)
490#endif /* !SIMULATOR */ 491#endif /* !SIMULATOR */
491} 492}
492 493
494
495unsigned char * audio_get_buffer(bool talk_buf, size_t *buffer_size)
496{
497 (void)talk_buf; /* always grab the voice buffer for now */
498
499 audio_hard_stop();
500 if (buffer_size) /* special case for talk_init() */
501 return buffer_get_buffer(buffer_size);
502 return NULL;
503}
504
505
493#ifndef SIMULATOR 506#ifndef SIMULATOR
494/* Send callback events to notify about removing old tracks. */ 507/* Send callback events to notify about removing old tracks. */
495static void generate_unbuffer_events(void) 508static void generate_unbuffer_events(void)
@@ -708,7 +721,7 @@ void rec_tick(void)
708 721
709 xor_b(0x08, &PADRH); /* Set PR inactive */ 722 xor_b(0x08, &PADRH); /* Set PR inactive */
710 723
711 audiobuf[audiobuf_write++] = data; 724 mpeg_audiobuf[audiobuf_write++] = data;
712 725
713 if (audiobuf_write >= audiobuflen) 726 if (audiobuf_write >= audiobuflen)
714 audiobuf_write = 0; 727 audiobuf_write = 0;
@@ -825,7 +838,7 @@ static void transfer_end(unsigned char** ppbuf, size_t* psize)
825 } 838 }
826 839
827 *psize = last_dma_chunk_size & 0xffff; 840 *psize = last_dma_chunk_size & 0xffff;
828 *ppbuf = audiobuf + audiobuf_read; 841 *ppbuf = mpeg_audiobuf + audiobuf_read;
829 track = get_trackdata(0); 842 track = get_trackdata(0);
830 if(track) 843 if(track)
831 track->id3.offset += last_dma_chunk_size; 844 track->id3.offset += last_dma_chunk_size;
@@ -1128,7 +1141,7 @@ static void start_playback_if_ready(void)
1128 playing = true; 1141 playing = true;
1129 1142
1130 last_dma_chunk_size = MIN(0x2000, get_unplayed_space_current_song()); 1143 last_dma_chunk_size = MIN(0x2000, get_unplayed_space_current_song());
1131 mp3_play_data(audiobuf + audiobuf_read, last_dma_chunk_size, transfer_end); 1144 mp3_play_data(mpeg_audiobuf + audiobuf_read, last_dma_chunk_size, transfer_end);
1132 dma_underrun = false; 1145 dma_underrun = false;
1133 1146
1134 if (!paused) 1147 if (!paused)
@@ -1173,7 +1186,7 @@ static bool swap_one_chunk(void)
1173 amount_to_swap = MIN(audiobuf_write - audiobuf_swapwrite, 1186 amount_to_swap = MIN(audiobuf_write - audiobuf_swapwrite,
1174 amount_to_swap); 1187 amount_to_swap);
1175 1188
1176 bitswap(audiobuf + audiobuf_swapwrite, amount_to_swap); 1189 bitswap(mpeg_audiobuf + audiobuf_swapwrite, amount_to_swap);
1177 1190
1178 audiobuf_swapwrite += amount_to_swap; 1191 audiobuf_swapwrite += amount_to_swap;
1179 if(audiobuf_swapwrite >= audiobuflen) 1192 if(audiobuf_swapwrite >= audiobuflen)
@@ -1341,7 +1354,7 @@ static void mpeg_thread(void)
1341 track_change(); 1354 track_change();
1342 audiobuf_read = get_trackdata(0)->mempos; 1355 audiobuf_read = get_trackdata(0)->mempos;
1343 last_dma_chunk_size = MIN(0x2000, get_unplayed_space_current_song()); 1356 last_dma_chunk_size = MIN(0x2000, get_unplayed_space_current_song());
1344 mp3_play_data(audiobuf + audiobuf_read, last_dma_chunk_size, transfer_end); 1357 mp3_play_data(mpeg_audiobuf + audiobuf_read, last_dma_chunk_size, transfer_end);
1345 dma_underrun = false; 1358 dma_underrun = false;
1346 last_dma_tick = current_tick; 1359 last_dma_tick = current_tick;
1347 1360
@@ -1501,7 +1514,7 @@ static void mpeg_thread(void)
1501 /* resume will start at new position */ 1514 /* resume will start at new position */
1502 last_dma_chunk_size = 1515 last_dma_chunk_size =
1503 MIN(0x2000, get_unplayed_space_current_song()); 1516 MIN(0x2000, get_unplayed_space_current_song());
1504 mp3_play_data(audiobuf + audiobuf_read, 1517 mp3_play_data(mpeg_audiobuf + audiobuf_read,
1505 last_dma_chunk_size, transfer_end); 1518 last_dma_chunk_size, transfer_end);
1506 dma_underrun = false; 1519 dma_underrun = false;
1507 } 1520 }
@@ -1632,7 +1645,7 @@ static void mpeg_thread(void)
1632 { 1645 {
1633 DEBUGF("R\n"); 1646 DEBUGF("R\n");
1634 t1 = current_tick; 1647 t1 = current_tick;
1635 len = read(mpeg_file, audiobuf + audiobuf_write, 1648 len = read(mpeg_file, mpeg_audiobuf + audiobuf_write,
1636 amount_to_read); 1649 amount_to_read);
1637 if(len > 0) 1650 if(len > 0)
1638 { 1651 {
@@ -1659,7 +1672,7 @@ static void mpeg_thread(void)
1659 if(tagptr >= audiobuflen) 1672 if(tagptr >= audiobuflen)
1660 tagptr -= audiobuflen; 1673 tagptr -= audiobuflen;
1661 1674
1662 if(audiobuf[tagptr] != tag[i]) 1675 if(mpeg_audiobuf[tagptr] != tag[i])
1663 { 1676 {
1664 taglen = 0; 1677 taglen = 0;
1665 break; 1678 break;
@@ -1773,19 +1786,20 @@ static void mpeg_thread(void)
1773 startpos = prerecord_buffer[startpos].mempos; 1786 startpos = prerecord_buffer[startpos].mempos;
1774 1787
1775 DEBUGF("Start looking at address %x (%x)\n", 1788 DEBUGF("Start looking at address %x (%x)\n",
1776 audiobuf+startpos, startpos); 1789 mpeg_audiobuf+startpos, startpos);
1777 1790
1778 saved_header = mpeg_get_last_header(); 1791 saved_header = mpeg_get_last_header();
1779 1792
1780 mem_find_next_frame(startpos, &offset, 1800, 1793 mem_find_next_frame(startpos, &offset, 1800,
1781 saved_header); 1794 saved_header, mpeg_audiobuf,
1795 audiobuflen);
1782 1796
1783 audiobuf_read = startpos + offset; 1797 audiobuf_read = startpos + offset;
1784 if(audiobuf_read >= audiobuflen) 1798 if(audiobuf_read >= audiobuflen)
1785 audiobuf_read -= audiobuflen; 1799 audiobuf_read -= audiobuflen;
1786 1800
1787 DEBUGF("New audiobuf_read address: %x (%x)\n", 1801 DEBUGF("New audiobuf_read address: %x (%x)\n",
1788 audiobuf+audiobuf_read, audiobuf_read); 1802 mpeg_audiobuf+audiobuf_read, audiobuf_read);
1789 1803
1790 level = disable_irq_save(); 1804 level = disable_irq_save();
1791 num_rec_bytes = get_unsaved_space(); 1805 num_rec_bytes = get_unsaved_space();
@@ -1894,7 +1908,8 @@ static void mpeg_thread(void)
1894 save_endpos += audiobuflen; 1908 save_endpos += audiobuflen;
1895 1909
1896 rc = mem_find_next_frame(save_endpos, &offset, 1800, 1910 rc = mem_find_next_frame(save_endpos, &offset, 1800,
1897 saved_header); 1911 saved_header, mpeg_audiobuf,
1912 audiobuflen);
1898 if (!rc) /* No header found, save whole buffer */ 1913 if (!rc) /* No header found, save whole buffer */
1899 offset = 1800; 1914 offset = 1800;
1900 1915
@@ -1936,7 +1951,7 @@ static void mpeg_thread(void)
1936#elif MEMORYSIZE == 8 1951#elif MEMORYSIZE == 8
1937 amount_to_save = MIN(0x100000, amount_to_save); 1952 amount_to_save = MIN(0x100000, amount_to_save);
1938#endif 1953#endif
1939 rc = write(mpeg_file, audiobuf + audiobuf_read, 1954 rc = write(mpeg_file, mpeg_audiobuf + audiobuf_read,
1940 amount_to_save); 1955 amount_to_save);
1941 if (rc < 0) 1956 if (rc < 0)
1942 { 1957 {
@@ -2256,21 +2271,21 @@ static void prepend_header(void)
2256 if(audiobuf_read < 0) 2271 if(audiobuf_read < 0)
2257 { 2272 {
2258 /* Clear the bottom half */ 2273 /* Clear the bottom half */
2259 memset(audiobuf, 0, audiobuf_read + MPEG_RESERVED_HEADER_SPACE); 2274 memset(mpeg_audiobuf, 0, audiobuf_read + MPEG_RESERVED_HEADER_SPACE);
2260 2275
2261 /* And the top half */ 2276 /* And the top half */
2262 audiobuf_read += audiobuflen; 2277 audiobuf_read += audiobuflen;
2263 memset(audiobuf + audiobuf_read, 0, audiobuflen - audiobuf_read); 2278 memset(mpeg_audiobuf + audiobuf_read, 0, audiobuflen - audiobuf_read);
2264 } 2279 }
2265 else 2280 else
2266 { 2281 {
2267 memset(audiobuf + audiobuf_read, 0, MPEG_RESERVED_HEADER_SPACE); 2282 memset(mpeg_audiobuf + audiobuf_read, 0, MPEG_RESERVED_HEADER_SPACE);
2268 } 2283 }
2269 /* Copy the empty ID3 header */ 2284 /* Copy the empty ID3 header */
2270 startpos = audiobuf_read; 2285 startpos = audiobuf_read;
2271 for(i = 0; i < sizeof(empty_id3_header); i++) 2286 for(i = 0; i < sizeof(empty_id3_header); i++)
2272 { 2287 {
2273 audiobuf[startpos++] = empty_id3_header[i]; 2288 mpeg_audiobuf[startpos++] = empty_id3_header[i];
2274 if(startpos == audiobuflen) 2289 if(startpos == audiobuflen)
2275 startpos = 0; 2290 startpos = 0;
2276 } 2291 }
@@ -2297,7 +2312,8 @@ static void update_header(void)
2297 /* saved_header is saved right before stopping the MAS */ 2312 /* saved_header is saved right before stopping the MAS */
2298 framelen = create_xing_header(fd, 0, last_rec_bytes, xing_buffer, 2313 framelen = create_xing_header(fd, 0, last_rec_bytes, xing_buffer,
2299 frames, last_rec_time * (1000/HZ), 2314 frames, last_rec_time * (1000/HZ),
2300 saved_header, NULL, false); 2315 saved_header, NULL, false,
2316 mpeg_audiobuf, audiobuflen);
2301 2317
2302 lseek(fd, MPEG_RESERVED_HEADER_SPACE - framelen, SEEK_SET); 2318 lseek(fd, MPEG_RESERVED_HEADER_SPACE - framelen, SEEK_SET);
2303 write(fd, xing_buffer, framelen); 2319 write(fd, xing_buffer, framelen);
@@ -2645,8 +2661,22 @@ void audio_set_recording_options(struct audio_recording_options *options)
2645#endif /* SIMULATOR */ 2661#endif /* SIMULATOR */
2646#endif /* CONFIG_CODEC == MAS3587F */ 2662#endif /* CONFIG_CODEC == MAS3587F */
2647 2663
2664static void audio_reset_buffer(void)
2665{
2666 size_t bufsize; /* dont break strict-aliasing */
2667 talk_buffer_steal(); /* will use the mp3 buffer */
2668
2669 /* release buffer on behalf of any audio_get_buffer() caller,
2670 * non-fatal if there was none */
2671 buffer_release_buffer(0);
2672 /* re-aquire */
2673 mpeg_audiobuf = buffer_get_buffer(&bufsize);
2674 audiobuflen = bufsize;
2675}
2676
2648void audio_play(long offset) 2677void audio_play(long offset)
2649{ 2678{
2679 audio_reset_buffer();
2650#ifdef SIMULATOR 2680#ifdef SIMULATOR
2651 char name_buf[MAX_PATH+1]; 2681 char name_buf[MAX_PATH+1];
2652 const char* trackname; 2682 const char* trackname;
@@ -2676,7 +2706,6 @@ void audio_play(long offset)
2676 } while(1); 2706 } while(1);
2677#else /* !SIMULATOR */ 2707#else /* !SIMULATOR */
2678 is_playing = true; 2708 is_playing = true;
2679
2680 queue_post(&mpeg_queue, MPEG_PLAY, offset); 2709 queue_post(&mpeg_queue, MPEG_PLAY, offset);
2681#endif /* !SIMULATOR */ 2710#endif /* !SIMULATOR */
2682 2711
@@ -2700,6 +2729,8 @@ void audio_stop(void)
2700 is_playing = false; 2729 is_playing = false;
2701 playing = false; 2730 playing = false;
2702#endif /* SIMULATOR */ 2731#endif /* SIMULATOR */
2732 /* give voice our entire buffer */
2733 talkbuf_init(mpeg_audiobuf);
2703} 2734}
2704 2735
2705/* dummy */ 2736/* dummy */
@@ -2708,6 +2739,14 @@ void audio_stop_recording(void)
2708 audio_stop(); 2739 audio_stop();
2709} 2740}
2710 2741
2742void audio_hard_stop(void)
2743{
2744 audio_stop();
2745 /* tell voice we obtain the buffer before freeing */
2746 talk_buffer_steal();
2747 buffer_release_buffer(0);
2748}
2749
2711void audio_pause(void) 2750void audio_pause(void)
2712{ 2751{
2713#ifndef SIMULATOR 2752#ifndef SIMULATOR
@@ -2864,8 +2903,12 @@ void audio_init(void)
2864 if (global_settings.cuesheet) 2903 if (global_settings.cuesheet)
2865 curr_cuesheet = (struct cuesheet*)buffer_alloc(sizeof(struct cuesheet)); 2904 curr_cuesheet = (struct cuesheet*)buffer_alloc(sizeof(struct cuesheet));
2866 2905
2906 size_t bufsize; /* don't break strict-aliasing */
2907 mpeg_audiobuf = buffer_get_buffer(&bufsize);
2908 audiobuflen = bufsize;
2909 /* give voice buffer until we start to play */
2910 talkbuf_init(mpeg_audiobuf);
2867#ifndef SIMULATOR 2911#ifndef SIMULATOR
2868 audiobuflen = audiobufend - audiobuf;
2869 queue_init(&mpeg_queue, true); 2912 queue_init(&mpeg_queue, true);
2870#endif /* !SIMULATOR */ 2913#endif /* !SIMULATOR */
2871 create_thread(mpeg_thread, mpeg_stack, 2914 create_thread(mpeg_thread, mpeg_stack,
diff --git a/apps/playback.c b/apps/playback.c
index fe9bd579d4..3f6ee71ad7 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -744,16 +744,25 @@ static void audio_reset_buffer(void)
744 /* see audio_get_recording_buffer if this is modified */ 744 /* see audio_get_recording_buffer if this is modified */
745 logf("%s()", __func__); 745 logf("%s()", __func__);
746 746
747 /* release the buffer on behalf of any caller of audio_get_buffer() */
748 buffer_release_buffer(0);
749
747 /* If the setup of anything allocated before the file buffer is 750 /* If the setup of anything allocated before the file buffer is
748 changed, do check the adjustments after the buffer_alloc call 751 changed, do check the adjustments after the buffer_alloc call
749 as it will likely be affected and need sliding over */ 752 as it will likely be affected and need sliding over */
750 753
751 /* Initially set up file buffer as all space available */ 754 /* Initially set up file buffer as all space available */
752 unsigned char *filebuf = audiobuf + talk_get_bufsize(); 755 size_t filebuflen, allocsize;
753 size_t filebuflen = audiobufend - filebuf; 756 unsigned char *filebuf = buffer_get_buffer(&filebuflen);
754 size_t allocsize;
755 757
756 ALIGN_BUFFER(filebuf, filebuflen, sizeof (intptr_t)); 758 /* Subtract whatever voice needs */
759 allocsize = talkbuf_init(filebuf);
760 allocsize = ALIGN_UP(allocsize, sizeof (intptr_t));
761 if (allocsize > filebuflen)
762 goto bufpanic;
763
764 filebuf += allocsize;
765 filebuflen -= allocsize;
757 766
758 if (talk_voice_required()) 767 if (talk_voice_required())
759 { 768 {
@@ -3335,6 +3344,7 @@ void audio_hard_stop(void)
3335#ifdef PLAYBACK_VOICE 3344#ifdef PLAYBACK_VOICE
3336 voice_stop(); 3345 voice_stop();
3337#endif 3346#endif
3347 buffer_release_buffer(0);
3338} 3348}
3339 3349
3340/* Resume playback if paused */ 3350/* Resume playback if paused */
@@ -3441,7 +3451,7 @@ void audio_flush_and_reload_tracks(void)
3441 voicing */ 3451 voicing */
3442unsigned char * audio_get_buffer(bool talk_buf, size_t *buffer_size) 3452unsigned char * audio_get_buffer(bool talk_buf, size_t *buffer_size)
3443{ 3453{
3444 unsigned char *buf, *end; 3454 unsigned char *buf;
3445 3455
3446 if (audio_is_initialized) 3456 if (audio_is_initialized)
3447 { 3457 {
@@ -3461,7 +3471,7 @@ unsigned char * audio_get_buffer(bool talk_buf, size_t *buffer_size)
3461 || !talk_voice_required()) 3471 || !talk_voice_required())
3462 { 3472 {
3463 logf("get buffer: talk, audio"); 3473 logf("get buffer: talk, audio");
3464 /* Ok to use everything from audiobuf to audiobufend - voice is loaded, 3474 /* Ok to use everything from audiobuf - voice is loaded,
3465 the talk buffer is not needed because voice isn't being used, or 3475 the talk buffer is not needed because voice isn't being used, or
3466 could be AUDIOBUF_STATE_TRASHED already. If state is 3476 could be AUDIOBUF_STATE_TRASHED already. If state is
3467 AUDIOBUF_STATE_VOICED_ONLY, no problem as long as memory isn't 3477 AUDIOBUF_STATE_VOICED_ONLY, no problem as long as memory isn't
@@ -3474,9 +3484,7 @@ unsigned char * audio_get_buffer(bool talk_buf, size_t *buffer_size)
3474 talk_buffer_steal(); 3484 talk_buffer_steal();
3475 buffer_state = AUDIOBUF_STATE_TRASHED; 3485 buffer_state = AUDIOBUF_STATE_TRASHED;
3476 } 3486 }
3477 3487 buf = buffer_get_buffer(buffer_size);
3478 buf = audiobuf;
3479 end = audiobufend;
3480 } 3488 }
3481 else 3489 else
3482 { 3490 {
@@ -3485,14 +3493,18 @@ unsigned char * audio_get_buffer(bool talk_buf, size_t *buffer_size)
3485 /* Skip talk buffer and move pcm buffer to end to maximize available 3493 /* Skip talk buffer and move pcm buffer to end to maximize available
3486 contiguous memory - no audio running means voice will not need the 3494 contiguous memory - no audio running means voice will not need the
3487 swap space */ 3495 swap space */
3496 size_t siz, talkbuf_size;
3488 logf("get buffer: audio"); 3497 logf("get buffer: audio");
3489 buf = audiobuf + talk_get_bufsize(); 3498 /* call buffer_get_buffer() to make use of the locking mechanism */
3490 end = audiobufend - voicebuf_init(audiobufend); 3499 buf = buffer_get_buffer(&siz);
3500 buf += talkbuf_size = talkbuf_init(buf);
3501 siz -= talkbuf_size;
3502 siz -= voicebuf_init(buf + siz);
3503 *buffer_size = siz;
3504
3491 buffer_state = AUDIOBUF_STATE_VOICED_ONLY; 3505 buffer_state = AUDIOBUF_STATE_VOICED_ONLY;
3492 } 3506 }
3493 3507
3494 *buffer_size = end - buf;
3495
3496 return buf; 3508 return buf;
3497} 3509}
3498 3510
@@ -3500,14 +3512,11 @@ unsigned char * audio_get_buffer(bool talk_buf, size_t *buffer_size)
3500/* Stop audio, voice and obtain all available buffer space */ 3512/* Stop audio, voice and obtain all available buffer space */
3501unsigned char * audio_get_recording_buffer(size_t *buffer_size) 3513unsigned char * audio_get_recording_buffer(size_t *buffer_size)
3502{ 3514{
3503 audio_hard_stop();
3504 talk_buffer_steal(); 3515 talk_buffer_steal();
3516 audio_hard_stop();
3505 3517
3506 unsigned char *end = audiobufend;
3507 buffer_state = AUDIOBUF_STATE_TRASHED; 3518 buffer_state = AUDIOBUF_STATE_TRASHED;
3508 *buffer_size = end - audiobuf; 3519 return buffer_get_buffer(buffer_size);
3509
3510 return (unsigned char *)audiobuf;
3511} 3520}
3512#endif /* HAVE_RECORDING */ 3521#endif /* HAVE_RECORDING */
3513 3522
diff --git a/apps/playback.h b/apps/playback.h
index ea8718089f..793055f98c 100644
--- a/apps/playback.h
+++ b/apps/playback.h
@@ -75,7 +75,6 @@ int audio_track_count(void);
75long audio_filebufused(void); 75long audio_filebufused(void);
76void audio_pre_ff_rewind(void); 76void audio_pre_ff_rewind(void);
77void audio_skip(int direction); 77void audio_skip(int direction);
78void audio_hard_stop(void); /* Stops audio from serving playback */
79 78
80void audio_set_cuesheet(int enable); 79void audio_set_cuesheet(int enable);
81#ifdef HAVE_CROSSFADE 80#ifdef HAVE_CROSSFADE
diff --git a/apps/playlist.c b/apps/playlist.c
index 564cd03d90..8334260242 100644
--- a/apps/playlist.c
+++ b/apps/playlist.c
@@ -533,13 +533,7 @@ static int add_indices_to_playlist(struct playlist_info* playlist,
533 { 533 {
534 /* use mp3 buffer for maximum load speed */ 534 /* use mp3 buffer for maximum load speed */
535 audio_stop(); 535 audio_stop();
536#if CONFIG_CODEC != SWCODEC 536 buffer = audio_get_buffer(false, &buflen);
537 talk_buffer_steal(); /* we use the mp3 buffer, need to tell */
538 buflen = (audiobufend - audiobuf);
539 buffer = (char *)audiobuf;
540#else
541 buffer = (char *)audio_get_buffer(false, &buflen);
542#endif
543 } 537 }
544 538
545 store_index = true; 539 store_index = true;
@@ -2018,13 +2012,7 @@ int playlist_resume(void)
2018 bool sorted = true; 2012 bool sorted = true;
2019 2013
2020 /* use mp3 buffer for maximum load speed */ 2014 /* use mp3 buffer for maximum load speed */
2021#if CONFIG_CODEC != SWCODEC
2022 talk_buffer_steal(); /* we use the mp3 buffer, need to tell */
2023 buflen = (audiobufend - audiobuf);
2024 buffer = (char *)audiobuf;
2025#else
2026 buffer = (char *)audio_get_buffer(false, &buflen); 2015 buffer = (char *)audio_get_buffer(false, &buflen);
2027#endif
2028 2016
2029 empty_playlist(playlist, true); 2017 empty_playlist(playlist, true);
2030 2018
@@ -2449,10 +2437,6 @@ void playlist_start(int start_index, int offset)
2449 2437
2450 playlist->index = start_index; 2438 playlist->index = start_index;
2451 2439
2452#if CONFIG_CODEC != SWCODEC
2453 talk_buffer_steal(); /* will use the mp3 buffer */
2454#endif
2455
2456 playlist->started = true; 2440 playlist->started = true;
2457 sync_control(playlist, false); 2441 sync_control(playlist, false);
2458 audio_play(offset); 2442 audio_play(offset);
diff --git a/apps/playlist_viewer.c b/apps/playlist_viewer.c
index 803fba9765..43c0c0142e 100644
--- a/apps/playlist_viewer.c
+++ b/apps/playlist_viewer.c
@@ -493,9 +493,6 @@ static int onplay_menu(int index)
493 if (current_track->display_index!=viewer.num_tracks || 493 if (current_track->display_index!=viewer.num_tracks ||
494 global_settings.repeat_mode == REPEAT_ALL) 494 global_settings.repeat_mode == REPEAT_ALL)
495 { 495 {
496#if CONFIG_CODEC != SWCODEC
497 talk_buffer_steal(); /* will use the mp3 buffer */
498#endif
499 audio_play(0); 496 audio_play(0);
500 viewer.current_playing_track = -1; 497 viewer.current_playing_track = -1;
501 } 498 }
diff --git a/apps/plugin.c b/apps/plugin.c
index 50fbb37012..32b77ad287 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -979,14 +979,8 @@ void* plugin_get_buffer(size_t *buffer_size)
979 */ 979 */
980void* plugin_get_audio_buffer(size_t *buffer_size) 980void* plugin_get_audio_buffer(size_t *buffer_size)
981{ 981{
982#if CONFIG_CODEC == SWCODEC
983 return audio_get_buffer(true, buffer_size);
984#else
985 audio_stop(); 982 audio_stop();
986 talk_buffer_steal(); /* we use the mp3 buffer, need to tell */ 983 return audio_get_buffer(true, buffer_size);
987 *buffer_size = audiobufend - audiobuf;
988 return audiobuf;
989#endif
990} 984}
991 985
992/* The plugin wants to stay resident after leaving its main function, e.g. 986/* The plugin wants to stay resident after leaving its main function, e.g.
diff --git a/apps/plugin.h b/apps/plugin.h
index a53df90d67..e2a5771b5c 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -828,12 +828,14 @@ struct plugin_api {
828#endif /* CONFIG_CODEC == SWCODEC */ 828#endif /* CONFIG_CODEC == SWCODEC */
829 bool (*get_metadata)(struct mp3entry* id3, int fd, const char* trackname); 829 bool (*get_metadata)(struct mp3entry* id3, int fd, const char* trackname);
830 bool (*mp3info)(struct mp3entry *entry, const char *filename); 830 bool (*mp3info)(struct mp3entry *entry, const char *filename);
831 int (*count_mp3_frames)(int fd, int startpos, int filesize, 831 int (*count_mp3_frames)(int fd, int startpos, int filesize,
832 void (*progressfunc)(int)); 832 void (*progressfunc)(int),
833 unsigned char* buf, size_t buflen);
833 int (*create_xing_header)(int fd, long startpos, long filesize, 834 int (*create_xing_header)(int fd, long startpos, long filesize,
834 unsigned char *buf, unsigned long num_frames, 835 unsigned char *buf, unsigned long num_frames,
835 unsigned long rec_time, unsigned long header_template, 836 unsigned long rec_time, unsigned long header_template,
836 void (*progressfunc)(int), bool generate_toc); 837 void (*progressfunc)(int), bool generate_toc,
838 unsigned char* tempbuf, size_t tempbuf_len);
837 unsigned long (*find_next_frame)(int fd, long *offset, 839 unsigned long (*find_next_frame)(int fd, long *offset,
838 long max_offset, unsigned long reference_header); 840 long max_offset, unsigned long reference_header);
839 841
diff --git a/apps/plugins/vbrfix.c b/apps/plugins/vbrfix.c
index 98ca15b6a8..af7b817002 100644
--- a/apps/plugins/vbrfix.c
+++ b/apps/plugins/vbrfix.c
@@ -157,14 +157,15 @@ static bool vbr_fix(const char *selected_file)
157 xingupdate(0); 157 xingupdate(0);
158 158
159 num_frames = rb->count_mp3_frames(fd, entry.first_frame_offset, 159 num_frames = rb->count_mp3_frames(fd, entry.first_frame_offset,
160 flen, xingupdate); 160 flen, xingupdate, audiobuf, audiobuflen);
161 161
162 if(num_frames) { 162 if(num_frames) {
163 /* Note: We don't need to pass a template header because it will be 163 /* Note: We don't need to pass a template header because it will be
164 taken from the mpeg stream */ 164 taken from the mpeg stream */
165 framelen = rb->create_xing_header(fd, entry.first_frame_offset, 165 framelen = rb->create_xing_header(fd, entry.first_frame_offset,
166 flen, xingbuf, num_frames, 0, 166 flen, xingbuf, num_frames, 0,
167 0, xingupdate, true); 167 0, xingupdate, true,
168 audiobuf, audiobuflen);
168 169
169 /* Try to fit the Xing header first in the stream. Replace the existing 170 /* Try to fit the Xing header first in the stream. Replace the existing
170 VBR header if there is one, else see if there is room between the 171 VBR header if there is one, else see if there is room between the
diff --git a/apps/recorder/pcm_record.c b/apps/recorder/pcm_record.c
index 8a832e409c..407a7e5f49 100644
--- a/apps/recorder/pcm_record.c
+++ b/apps/recorder/pcm_record.c
@@ -1643,14 +1643,12 @@ void enc_set_parameters(struct enc_parameters *params)
1643 logf("fnq files:%ld", fnq_size / MAX_PATH); 1643 logf("fnq files:%ld", fnq_size / MAX_PATH);
1644 1644
1645#if defined(DEBUG) 1645#if defined(DEBUG)
1646 logf("ab :%08lX", (uintptr_t)audiobuf);
1647 logf("pcm:%08lX", (uintptr_t)pcm_buffer); 1646 logf("pcm:%08lX", (uintptr_t)pcm_buffer);
1648 logf("enc:%08lX", (uintptr_t)enc_buffer); 1647 logf("enc:%08lX", (uintptr_t)enc_buffer);
1649 logf("res:%08lX", (uintptr_t)params->reserve_buffer); 1648 logf("res:%08lX", (uintptr_t)params->reserve_buffer);
1650 logf("wip:%08lX", (uintptr_t)wrap_id_p); 1649 logf("wip:%08lX", (uintptr_t)wrap_id_p);
1651 logf("fnq:%08lX", (uintptr_t)fn_queue); 1650 logf("fnq:%08lX", (uintptr_t)fn_queue);
1652 logf("end:%08lX", (uintptr_t)fn_queue + fnq_size); 1651 logf("end:%08lX", (uintptr_t)fn_queue + fnq_size);
1653 logf("abe:%08lX", (uintptr_t)audiobufend);
1654#endif 1652#endif
1655 1653
1656 /* init all chunk headers and reset indexes */ 1654 /* init all chunk headers and reset indexes */
diff --git a/apps/tagcache.c b/apps/tagcache.c
index 6aa7709c00..0a491c58b5 100644
--- a/apps/tagcache.c
+++ b/apps/tagcache.c
@@ -107,7 +107,7 @@ static char curpath[TAG_MAXLEN+32];
107/* Used when removing duplicates. */ 107/* Used when removing duplicates. */
108static char *tempbuf; /* Allocated when needed. */ 108static char *tempbuf; /* Allocated when needed. */
109static long tempbufidx; /* Current location in buffer. */ 109static long tempbufidx; /* Current location in buffer. */
110static long tempbuf_size; /* Buffer size (TEMPBUF_SIZE). */ 110static size_t tempbuf_size; /* Buffer size (TEMPBUF_SIZE). */
111static long tempbuf_left; /* Buffer space left. */ 111static long tempbuf_left; /* Buffer space left. */
112static long tempbuf_pos; 112static long tempbuf_pos;
113 113
@@ -3089,9 +3089,7 @@ static void allocate_tempbuf(void)
3089 tempbuf_size = 32*1024*1024; 3089 tempbuf_size = 32*1024*1024;
3090 tempbuf = malloc(tempbuf_size); 3090 tempbuf = malloc(tempbuf_size);
3091#else 3091#else
3092 tempbuf = (char *)(((long)audiobuf & ~0x03) + 0x04); 3092 buffer_get_buffer(&tempbuf_size);
3093 tempbuf_size = (long)audiobufend - (long)audiobuf - 4;
3094 audiobuf += tempbuf_size;
3095#endif 3093#endif
3096} 3094}
3097 3095
@@ -3103,7 +3101,7 @@ static void free_tempbuf(void)
3103#ifdef __PCTOOL__ 3101#ifdef __PCTOOL__
3104 free(tempbuf); 3102 free(tempbuf);
3105#else 3103#else
3106 audiobuf -= tempbuf_size; 3104 buffer_release_buffer(0);
3107#endif 3105#endif
3108 tempbuf = NULL; 3106 tempbuf = NULL;
3109 tempbuf_size = 0; 3107 tempbuf_size = 0;
diff --git a/apps/talk.c b/apps/talk.c
index 8c0f1f3a07..9fd6fb06ec 100644
--- a/apps/talk.c
+++ b/apps/talk.c
@@ -49,7 +49,7 @@
49 49
50 MASCODEC | MASCODEC | SWCODEC 50 MASCODEC | MASCODEC | SWCODEC
51 (playing) | (stopped) | 51 (playing) | (stopped) |
52 audiobuf-----------+-----------+------------ 52 voicebuf-----------+-----------+------------
53 audio | voice | thumbnail 53 audio | voice | thumbnail
54 |-----------|------------ 54 |-----------|------------
55 | thumbnail | voice 55 | thumbnail | voice
@@ -57,7 +57,7 @@
57 | | filebuf 57 | | filebuf
58 | |------------ 58 | |------------
59 | | audio 59 | | audio
60 audiobufend----------+-----------+------------ 60 voicebufend----------+-----------+------------
61 61
62 SWCODEC allocates dedicated buffers, MASCODEC reuses audiobuf. */ 62 SWCODEC allocates dedicated buffers, MASCODEC reuses audiobuf. */
63 63
@@ -128,6 +128,7 @@ static uint8_t clip_age[QUEUE_SIZE];
128#endif 128#endif
129#endif 129#endif
130 130
131static char* voicebuf; /* root pointer to our buffer */
131static unsigned char* p_thumbnail = NULL; /* buffer for thumbnails */ 132static unsigned char* p_thumbnail = NULL; /* buffer for thumbnails */
132/* Multiple thumbnails can be loaded back-to-back in this buffer. */ 133/* Multiple thumbnails can be loaded back-to-back in this buffer. */
133static volatile int thumbnail_buf_used SHAREDBSS_ATTR; /* length of data in 134static volatile int thumbnail_buf_used SHAREDBSS_ATTR; /* length of data in
@@ -281,12 +282,18 @@ static unsigned char* get_clip(long id, long* p_size)
281 282
282 283
283/* load the voice file into the mp3 buffer */ 284/* load the voice file into the mp3 buffer */
284static void load_voicefile(bool probe) 285static void load_voicefile(bool probe, char* buf, size_t bufsize)
285{ 286{
286 int load_size; 287 union voicebuf {
288 unsigned char* buf;
289 struct voicefile* file;
290 };
291 union voicebuf voicebuf;
292
293 int load_size, alloc_size;
287 int got_size; 294 int got_size;
288#ifndef TALK_PARTIAL_LOAD 295#ifndef TALK_PARTIAL_LOAD
289 int file_size; 296 size_t file_size;
290#endif 297#endif
291#ifdef ROCKBOX_LITTLE_ENDIAN 298#ifdef ROCKBOX_LITTLE_ENDIAN
292 int i; 299 int i;
@@ -297,37 +304,43 @@ static void load_voicefile(bool probe)
297 if (filehandle < 0) /* failed to open */ 304 if (filehandle < 0) /* failed to open */
298 goto load_err; 305 goto load_err;
299 306
307 voicebuf.buf = buf;
308 if (!voicebuf.buf)
309 goto load_err;
310
300#ifndef TALK_PARTIAL_LOAD 311#ifndef TALK_PARTIAL_LOAD
301 file_size = filesize(filehandle); 312 file_size = filesize(filehandle);
302 if (file_size > audiobufend - audiobuf) /* won't fit? */ 313 if (file_size > bufsize) /* won't fit? */
303 goto load_err; 314 goto load_err;
304#endif 315#endif
305 316
306#if defined(TALK_PROGRESSIVE_LOAD) || defined(TALK_PARTIAL_LOAD) 317#if defined(TALK_PROGRESSIVE_LOAD) || defined(TALK_PARTIAL_LOAD)
307 /* load only the header for now */ 318 /* load only the header for now */
308 load_size = offsetof(struct voicefile, index); 319 load_size = sizeof(struct voicefile);
309#else /* load the full file */ 320#else /* load the full file */
310 load_size = file_size; 321 load_size = file_size;
311#endif 322#endif
312 323
313#ifdef TALK_PARTIAL_LOAD 324#ifdef TALK_PARTIAL_LOAD
314 if (load_size > audiobufend - audiobuf) /* won't fit? */ 325 if (load_size > bufsize) /* won't fit? */
315 goto load_err; 326 goto load_err;
316#endif 327#endif
317 328
318 got_size = read(filehandle, audiobuf, load_size); 329 got_size = read(filehandle, voicebuf.buf, load_size);
319 if (got_size != load_size /* failure */) 330 if (got_size != load_size /* failure */)
320 goto load_err; 331 goto load_err;
321 332
333 alloc_size = load_size;
334
322#ifdef ROCKBOX_LITTLE_ENDIAN 335#ifdef ROCKBOX_LITTLE_ENDIAN
323 logf("Byte swapping voice file"); 336 logf("Byte swapping voice file");
324 structec_convert(audiobuf, "lllll", 1, true); 337 structec_convert(voicebuf.buf, "lllll", 1, true);
325#endif 338#endif
326 339
327 if (((struct voicefile*)audiobuf)->table /* format check */ 340 /* format check */
328 == offsetof(struct voicefile, index)) 341 if (voicebuf.file->table == sizeof(struct voicefile))
329 { 342 {
330 p_voicefile = (struct voicefile*)audiobuf; 343 p_voicefile = voicebuf.file;
331 344
332 if (p_voicefile->version != VOICE_VERSION || 345 if (p_voicefile->version != VOICE_VERSION ||
333 p_voicefile->target_id != TARGET_ID) 346 p_voicefile->target_id != TARGET_ID)
@@ -337,9 +350,9 @@ static void load_voicefile(bool probe)
337 } 350 }
338#if CONFIG_CODEC != SWCODEC 351#if CONFIG_CODEC != SWCODEC
339 /* MASCODEC: now use audiobuf for voice then thumbnail */ 352 /* MASCODEC: now use audiobuf for voice then thumbnail */
340 p_thumbnail = audiobuf + file_size; 353 p_thumbnail = voicebuf.buf + file_size;
341 p_thumbnail += (long)p_thumbnail % 2; /* 16-bit align */ 354 p_thumbnail += (long)p_thumbnail % 2; /* 16-bit align */
342 size_for_thumbnail = audiobufend - p_thumbnail; 355 size_for_thumbnail = voicebuf.buf + bufsize - p_thumbnail;
343#endif 356#endif
344 } 357 }
345 else 358 else
@@ -351,14 +364,15 @@ static void load_voicefile(bool probe)
351 * sizeof(struct clip_entry); 364 * sizeof(struct clip_entry);
352 365
353#ifdef TALK_PARTIAL_LOAD 366#ifdef TALK_PARTIAL_LOAD
354 if (load_size > audiobufend - audiobuf) /* won't fit? */ 367 if (load_size > bufsize) /* won't fit? */
355 goto load_err; 368 goto load_err;
356#endif 369#endif
357 370
358 got_size = read(filehandle, 371 got_size = read(filehandle, &p_voicefile->index[0], load_size);
359 (unsigned char *) p_voicefile + offsetof(struct voicefile, index), load_size);
360 if (got_size != load_size) /* read error */ 372 if (got_size != load_size) /* read error */
361 goto load_err; 373 goto load_err;
374
375 alloc_size += load_size;
362#else 376#else
363 close(filehandle); 377 close(filehandle);
364 filehandle = -1; 378 filehandle = -1;
@@ -379,6 +393,11 @@ static void load_voicefile(bool probe)
379 p_silence = get_clip(VOICE_PAUSE, &silence_len); 393 p_silence = get_clip(VOICE_PAUSE, &silence_len);
380 } 394 }
381 395
396#ifdef TALK_PARTIAL_LOAD
397 alloc_size += silence_len + QUEUE_SIZE;
398#endif
399 if ((size_t)alloc_size > bufsize)
400 goto load_err;
382 return; 401 return;
383 402
384load_err: 403load_err:
@@ -582,24 +601,31 @@ static void queue_clip(unsigned char* buf, long size, bool enqueue)
582} 601}
583 602
584 603
585/* common code for talk_init() and talk_buffer_steal() */ 604static void alloc_thumbnail_buf(void)
586static void reset_state(void)
587{ 605{
588 queue_write = queue_read = 0; /* reset the queue */
589 p_voicefile = NULL; /* indicate no voicefile (trashed) */
590#if CONFIG_CODEC == SWCODEC 606#if CONFIG_CODEC == SWCODEC
591 /* Allocate a dedicated thumbnail buffer - once */ 607 /* Allocate a dedicated thumbnail buffer - once */
592 if (p_thumbnail == NULL) 608 if (p_thumbnail == NULL)
593 { 609 {
594 size_for_thumbnail = audiobufend - audiobuf; 610 size_for_thumbnail = buffer_available();
595 if (size_for_thumbnail > MAX_THUMBNAIL_BUFSIZE) 611 if (size_for_thumbnail > MAX_THUMBNAIL_BUFSIZE)
596 size_for_thumbnail = MAX_THUMBNAIL_BUFSIZE; 612 size_for_thumbnail = MAX_THUMBNAIL_BUFSIZE;
597 p_thumbnail = buffer_alloc(size_for_thumbnail); 613 p_thumbnail = buffer_alloc(size_for_thumbnail);
598 } 614 }
599#else 615#else
600 /* Just use the audiobuf, without allocating anything */ 616 /* use the audio buffer now, need to release before loading a voice */
601 p_thumbnail = audiobuf; 617 p_thumbnail = voicebuf;
602 size_for_thumbnail = audiobufend - audiobuf; 618#endif
619 thumbnail_buf_used = 0;
620}
621
622/* common code for talk_init() and talk_buffer_steal() */
623static void reset_state(void)
624{
625 queue_write = queue_read = 0; /* reset the queue */
626 p_voicefile = NULL; /* indicate no voicefile (trashed) */
627#if CONFIG_CODEC != SWCODEC
628 p_thumbnail = NULL; /* don't leak buffer_alloc() for swcodec */
603#endif 629#endif
604 630
605#ifdef TALK_PARTIAL_LOAD 631#ifdef TALK_PARTIAL_LOAD
@@ -608,8 +634,8 @@ static void reset_state(void)
608 buffered_id[i] = -1; 634 buffered_id[i] = -1;
609#endif 635#endif
610 636
611 thumbnail_buf_used = 0;
612 p_silence = NULL; /* pause clip not accessible */ 637 p_silence = NULL; /* pause clip not accessible */
638 voicebuf = NULL;
613} 639}
614 640
615 641
@@ -655,12 +681,11 @@ void talk_init(void)
655#endif 681#endif
656 reset_state(); /* use this for most of our inits */ 682 reset_state(); /* use this for most of our inits */
657 683
658 /* test if we can open and if it fits in the audiobuffer */
659 size_t audiobufsz = audiobufend - audiobuf;
660
661#ifdef TALK_PARTIAL_LOAD 684#ifdef TALK_PARTIAL_LOAD
685 size_t bufsize;
686 char* buf = plugin_get_buffer(&bufsize);
662 /* we won't load the full file, we only need the index */ 687 /* we won't load the full file, we only need the index */
663 load_voicefile(true); 688 load_voicefile(true, buf, bufsize);
664 if (!p_voicefile) 689 if (!p_voicefile)
665 return; 690 return;
666 691
@@ -681,6 +706,9 @@ void talk_init(void)
681 p_voicefile = NULL; /* Don't pretend we can load talk clips just yet */ 706 p_voicefile = NULL; /* Don't pretend we can load talk clips just yet */
682#endif 707#endif
683 708
709
710 /* test if we can open and if it fits in the audiobuffer */
711 size_t audiobufsz = buffer_available();
684 if (voicefile_size <= audiobufsz) { 712 if (voicefile_size <= audiobufsz) {
685 has_voicefile = true; 713 has_voicefile = true;
686 } else { 714 } else {
@@ -688,6 +716,7 @@ void talk_init(void)
688 voicefile_size = 0; 716 voicefile_size = 0;
689 } 717 }
690 718
719 alloc_thumbnail_buf();
691 close(filehandle); /* close again, this was just to detect presence */ 720 close(filehandle); /* close again, this was just to detect presence */
692 filehandle = -1; 721 filehandle = -1;
693} 722}
@@ -703,8 +732,22 @@ bool talk_voice_required(void)
703#endif 732#endif
704 733
705/* return size of voice file */ 734/* return size of voice file */
706int talk_get_bufsize(void) 735int talk_get_buffer(void)
736{
737 return voicefile_size;
738}
739
740/* Sets the buffer for the voicefile and returns how many bytes of this
741 * buffer we will use for the voicefile */
742size_t talkbuf_init(char *bufstart)
707{ 743{
744 bool changed = voicebuf != bufstart;
745
746 if (bufstart)
747 voicebuf = bufstart;
748 if (changed) /* must reload voice file */
749 reset_state();
750
708 return voicefile_size; 751 return voicefile_size;
709} 752}
710 753
@@ -741,7 +784,7 @@ int talk_id(int32_t id, bool enqueue)
741#endif 784#endif
742 785
743 if (p_voicefile == NULL && has_voicefile) 786 if (p_voicefile == NULL && has_voicefile)
744 load_voicefile(false); /* reload needed */ 787 load_voicefile(false, voicebuf, voicefile_size); /* reload needed */
745 788
746 if (p_voicefile == NULL) /* still no voices? */ 789 if (p_voicefile == NULL) /* still no voices? */
747 return -1; 790 return -1;
@@ -819,7 +862,7 @@ static int _talk_file(const char* filename,
819#endif 862#endif
820 863
821 if (p_thumbnail == NULL || size_for_thumbnail <= 0) 864 if (p_thumbnail == NULL || size_for_thumbnail <= 0)
822 return -1; 865 alloc_thumbnail_buf();
823 866
824#if CONFIG_CODEC != SWCODEC 867#if CONFIG_CODEC != SWCODEC
825 if(mp3info(&info, filename)) /* use this to find real start */ 868 if(mp3info(&info, filename)) /* use this to find real start */
diff --git a/apps/talk.h b/apps/talk.h
index a2a9f44e4e..e1702147c7 100644
--- a/apps/talk.h
+++ b/apps/talk.h
@@ -80,6 +80,7 @@ void talk_init(void);
80bool talk_voice_required(void); /* returns true if voice codec required */ 80bool talk_voice_required(void); /* returns true if voice codec required */
81#endif 81#endif
82int talk_get_bufsize(void); /* get the loaded voice file size */ 82int talk_get_bufsize(void); /* get the loaded voice file size */
83size_t talkbuf_init(char* bufstart);
83void talk_buffer_steal(void); /* claim the mp3 buffer e.g. for play/record */ 84void talk_buffer_steal(void); /* claim the mp3 buffer e.g. for play/record */
84bool is_voice_queued(void); /* Are there more voice clips to be spoken? */ 85bool is_voice_queued(void); /* Are there more voice clips to be spoken? */
85int talk_id(int32_t id, bool enqueue); /* play a voice ID from voicefont */ 86int talk_id(int32_t id, bool enqueue); /* play a voice ID from voicefont */
diff --git a/firmware/buffer.c b/firmware/buffer.c
index c317cec924..2168087bd9 100644
--- a/firmware/buffer.c
+++ b/firmware/buffer.c
@@ -19,19 +19,33 @@
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21#include <stdio.h> 21#include <stdio.h>
22#include <stdint.h>
23#include "system.h"
22#include "buffer.h" 24#include "buffer.h"
23#include "panic.h" 25#include "panic.h"
24#include "logf.h" 26#include "logf.h"
25 27
26#if (CONFIG_PLATFORM & PLATFORM_HOSTED) 28#if (CONFIG_PLATFORM & PLATFORM_HOSTED)
27unsigned char audiobuffer[(MEMORYSIZE*1024-256)*1024];
28unsigned char *audiobufend = audiobuffer + sizeof(audiobuffer);
29#else 29#else
30#endif
31
32/* defined in linker script */
33#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
34#if defined(IPOD_VIDEO)
35extern unsigned char *audiobufend_lds[];
36unsigned char *audiobufend;
37#else /* !IPOD_VIDEO */
38extern unsigned char audiobufend[];
39#endif
30/* defined in linker script */ 40/* defined in linker script */
31extern unsigned char audiobuffer[]; 41extern unsigned char audiobuffer[];
42#else /* PLATFORM_HOSTED */
43unsigned char audiobuffer[(MEMORYSIZE*1024-256)*1024];
44unsigned char *audiobufend = audiobuffer + sizeof(audiobuffer);
45extern unsigned char *audiobufend;
32#endif 46#endif
33 47
34unsigned char *audiobuf; 48static unsigned char *audiobuf;
35 49
36#ifdef BUFFER_ALLOC_DEBUG 50#ifdef BUFFER_ALLOC_DEBUG
37static unsigned char *audiobuf_orig_start; 51static unsigned char *audiobuf_orig_start;
@@ -54,13 +68,68 @@ void buffer_init(void)
54{ 68{
55 /* 32-bit aligned */ 69 /* 32-bit aligned */
56 audiobuf = (void *)(((unsigned long)audiobuffer + 3) & ~3); 70 audiobuf = (void *)(((unsigned long)audiobuffer + 3) & ~3);
71
72#if defined(IPOD_VIDEO)
73 audiobufend=(unsigned char *)audiobufend_lds;
74 if(MEMORYSIZE==64 && probed_ramsize!=64)
75 {
76 audiobufend -= (32<<20);
77 }
78#endif
79
57#ifdef BUFFER_ALLOC_DEBUG 80#ifdef BUFFER_ALLOC_DEBUG
58 audiobuf_orig_start = audiobuf; 81 audiobuf_orig_start = audiobuf;
59#endif /* BUFFER_ALLOC_DEBUG */ 82#endif /* BUFFER_ALLOC_DEBUG */
60} 83}
61 84
85/* protect concurrent access */
86static volatile int lock;
87
88/*
89 * Give the entire buffer, return the size in size.
90 * The caller needs to make sure audiobuf is not otherwise used
91 *
92 * Note that this does not modify the buffer position (buffer_release_buffer()
93 * does), so call this if you want to aquire temporary memory
94 **/
95#define _ALIGN (sizeof(char*))
96void *buffer_get_buffer(size_t *size)
97{
98 if (lock)
99 panicf("concurrent audiobuf access");
100 lock = 1;
101 audiobuf = ALIGN_UP(audiobuf, sizeof(intptr_t));
102 *size = (audiobufend - audiobuf);
103 return audiobuf;
104}
105
106/*
107 * Release the buffer gotten with buffer_get_buffer
108 *
109 * size should have the amount of bytes (from the front) that caller keeps for
110 * its own, 0 if the entire buffer is to be released
111 *
112 * safe to be called with size=0 even if the buffer wasn't claimed before
113 **/
114void buffer_release_buffer(size_t size)
115{
116 audiobuf += size;
117 /* ensure alignment */
118 audiobuf = ALIGN_UP(audiobuf, sizeof(intptr_t));
119 lock = 0;
120}
121
122/*
123 * Query how much free space the buffer has */
124size_t buffer_available(void)
125{
126 return audiobufend - audiobuf;
127}
128
62void *buffer_alloc(size_t size) 129void *buffer_alloc(size_t size)
63{ 130{
131 if (lock) /* it's not save to call this here */
132 panicf("buffer_alloc(): exclusive buffer owner");
64 void *retval; 133 void *retval;
65#ifdef BUFFER_ALLOC_DEBUG 134#ifdef BUFFER_ALLOC_DEBUG
66 struct buffer_start_marker *start; 135 struct buffer_start_marker *start;
diff --git a/firmware/common/dircache.c b/firmware/common/dircache.c
index 08fe5098f5..d114a6ac62 100644
--- a/firmware/common/dircache.c
+++ b/firmware/common/dircache.c
@@ -862,22 +862,26 @@ int dircache_build(int last_size)
862 * and their corresponding d_name from the end 862 * and their corresponding d_name from the end
863 * after generation the buffer will be compacted with DIRCACHE_RESERVE 863 * after generation the buffer will be compacted with DIRCACHE_RESERVE
864 * free bytes inbetween */ 864 * free bytes inbetween */
865 audiobuf = ALIGN_UP(audiobuf, sizeof(struct dircache_entry)); 865 size_t got_size;
866 dircache_root = (struct dircache_entry*)audiobuf; 866 char* buf = buffer_get_buffer(&got_size);
867 d_names_start = d_names_end = audiobufend - 1; 867 ALIGN_BUFFER(buf, got_size, sizeof(struct dircache_entry));
868 d_names_start = d_names_end = (char*)dircache_root + got_size - 1;
868 dircache_size = 0; 869 dircache_size = 0;
869 generate_dot_d_names(); 870 generate_dot_d_names();
870 871
871 /* Start a non-transparent rebuild. */ 872 /* Start a non-transparent rebuild. */
872 int res = dircache_do_rebuild(); 873 int res = dircache_do_rebuild();
873 if (res < 0) 874 if (res < 0)
874 return res; 875 goto fail;
875 876
876 /* now compact the dircache buffer */ 877 /* now compact the dircache buffer */
877 char* dst = ((char*)&dircache_root[entry_count] + DIRCACHE_RESERVE); 878 char* dst = ((char*)&dircache_root[entry_count] + DIRCACHE_RESERVE);
878 ptrdiff_t offset = d_names_start - dst; 879 ptrdiff_t offset = d_names_start - dst;
879 if (offset <= 0) /* something went wrong */ 880 if (offset <= 0) /* something went wrong */
880 return -1; 881 {
882 res = -1;
883 goto fail;
884 }
881 885
882 /* memmove d_names down, there's a possibility of overlap 886 /* memmove d_names down, there's a possibility of overlap
883 * equivaent to dircache_size - entry_count*sizeof(struct dircache_entry) */ 887 * equivaent to dircache_size - entry_count*sizeof(struct dircache_entry) */
@@ -896,15 +900,19 @@ int dircache_build(int last_size)
896 /* equivalent to dircache_size + DIRCACHE_RESERVE */ 900 /* equivalent to dircache_size + DIRCACHE_RESERVE */
897 allocated_size = (d_names_end - (char*)dircache_root); 901 allocated_size = (d_names_end - (char*)dircache_root);
898 reserve_used = 0; 902 reserve_used = 0;
899 audiobuf += allocated_size;
900 903
904 buffer_release_buffer(allocated_size);
905 return res;
906fail:
907 dircache_disable();
908 buffer_release_buffer(0);
901 return res; 909 return res;
902} 910}
903 911
904/** 912/**
905 * Steal the allocated dircache buffer and disable dircache. 913 * Steal the allocated dircache buffer and disable dircache.
906 */ 914 */
907void* dircache_steal_buffer(long *size) 915void* dircache_steal_buffer(size_t *size)
908{ 916{
909 dircache_disable(); 917 dircache_disable();
910 if (dircache_size == 0) 918 if (dircache_size == 0)
diff --git a/firmware/export/audio.h b/firmware/export/audio.h
index 910791c7fd..6757bf143b 100644
--- a/firmware/export/audio.h
+++ b/firmware/export/audio.h
@@ -51,6 +51,8 @@
51void audio_init(void) INIT_ATTR; 51void audio_init(void) INIT_ATTR;
52void audio_play(long offset); 52void audio_play(long offset);
53void audio_stop(void); 53void audio_stop(void);
54/* Stops audio from serving playback and frees resources*/
55void audio_hard_stop(void);
54void audio_pause(void); 56void audio_pause(void);
55void audio_resume(void); 57void audio_resume(void);
56void audio_next(void); 58void audio_next(void);
@@ -68,11 +70,11 @@ void audio_error_clear(void);
68int audio_get_file_pos(void); 70int audio_get_file_pos(void);
69void audio_beep(int duration); 71void audio_beep(int duration);
70 72
71#if CONFIG_CODEC == SWCODEC
72/* Required call when audio buffer is required for some other purpose */ 73/* Required call when audio buffer is required for some other purpose */
74/* implemented in apps but called from firmware(!) */
73unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size); 75unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size);
74/* only implemented in playback.c, but called from firmware */
75 76
77#if CONFIG_CODEC == SWCODEC
76void audio_next_dir(void); 78void audio_next_dir(void);
77void audio_prev_dir(void); 79void audio_prev_dir(void);
78 80
diff --git a/firmware/include/buffer.h b/firmware/include/buffer.h
index 18f53f0000..bdf91bcb3f 100644
--- a/firmware/include/buffer.h
+++ b/firmware/include/buffer.h
@@ -22,21 +22,13 @@
22#define BUFFER_H 22#define BUFFER_H
23 23
24#include "config.h" 24#include "config.h"
25/* defined in linker script */
26#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
27#if defined(IPOD_VIDEO)
28extern unsigned char *audiobufend_lds[];
29unsigned char *audiobufend;
30#else
31extern unsigned char audiobufend[];
32#endif
33#else
34extern unsigned char *audiobufend;
35#endif
36
37extern unsigned char *audiobuf;
38 25
39void buffer_init(void) INIT_ATTR; 26void buffer_init(void) INIT_ATTR;
27
28void* buffer_get_buffer(size_t *size);
29void buffer_release_buffer(size_t size);
30size_t buffer_available(void);
31
40void *buffer_alloc(size_t size); 32void *buffer_alloc(size_t size);
41 33
42#ifdef BUFFER_ALLOC_DEBUG 34#ifdef BUFFER_ALLOC_DEBUG
diff --git a/firmware/include/dircache.h b/firmware/include/dircache.h
index 0ac937df84..6beeeb6c23 100644
--- a/firmware/include/dircache.h
+++ b/firmware/include/dircache.h
@@ -23,6 +23,7 @@
23 23
24#include "config.h" 24#include "config.h"
25#include "dir_uncached.h" 25#include "dir_uncached.h"
26#include <string.h> /* size_t */
26 27
27#ifdef HAVE_DIRCACHE 28#ifdef HAVE_DIRCACHE
28 29
@@ -65,7 +66,7 @@ void dircache_init(void) INIT_ATTR;
65int dircache_load(void); 66int dircache_load(void);
66int dircache_save(void); 67int dircache_save(void);
67int dircache_build(int last_size); 68int dircache_build(int last_size);
68void* dircache_steal_buffer(long *size); 69void* dircache_steal_buffer(size_t *size);
69bool dircache_is_enabled(void); 70bool dircache_is_enabled(void);
70bool dircache_is_initializing(void); 71bool dircache_is_initializing(void);
71void dircache_set_appflag(long mask); 72void dircache_set_appflag(long mask);
diff --git a/firmware/rolo.c b/firmware/rolo.c
index 078a4e9827..9b6f4fec4a 100644
--- a/firmware/rolo.c
+++ b/firmware/rolo.c
@@ -99,6 +99,7 @@ void rolo_restart_cop(void)
99 99
100static void rolo_error(const char *text) 100static void rolo_error(const char *text)
101{ 101{
102 buffer_release_buffer(0);
102 lcd_clear_display(); 103 lcd_clear_display();
103 lcd_puts(0, 0, "ROLO error:"); 104 lcd_puts(0, 0, "ROLO error:");
104 lcd_puts_scroll(0, 1, text); 105 lcd_puts_scroll(0, 1, text);
@@ -213,6 +214,8 @@ int rolo_load(const char* filename)
213 unsigned short checksum,file_checksum; 214 unsigned short checksum,file_checksum;
214#endif 215#endif
215 unsigned char* ramstart = (void*)&loadaddress; 216 unsigned char* ramstart = (void*)&loadaddress;
217 unsigned char* filebuf;
218 size_t filebuf_size;
216 219
217 lcd_clear_display(); 220 lcd_clear_display();
218 lcd_puts(0, 0, "ROLO..."); 221 lcd_puts(0, 0, "ROLO...");
@@ -235,6 +238,10 @@ int rolo_load(const char* filename)
235 238
236 length = filesize(fd) - FIRMWARE_OFFSET_FILE_DATA; 239 length = filesize(fd) - FIRMWARE_OFFSET_FILE_DATA;
237 240
241 /* get the system buffer. release only in case of error, otherwise
242 * we don't return anyway */
243 filebuf = buffer_get_buffer(&filebuf_size);
244
238#if CONFIG_CPU != SH7034 245#if CONFIG_CPU != SH7034
239 /* Read and save checksum */ 246 /* Read and save checksum */
240 lseek(fd, FIRMWARE_OFFSET_FILE_CRC, SEEK_SET); 247 lseek(fd, FIRMWARE_OFFSET_FILE_CRC, SEEK_SET);
@@ -260,7 +267,14 @@ int rolo_load(const char* filename)
260 267
261 lseek(fd, FIRMWARE_OFFSET_FILE_DATA, SEEK_SET); 268 lseek(fd, FIRMWARE_OFFSET_FILE_DATA, SEEK_SET);
262 269
263 if (read(fd, audiobuf, length) != length) { 270 /* this shouldn't happen, but well */
271 if ((long)filebuf_size < length)
272 {
273 rolo_error("File too big");
274 return -1;
275 }
276
277 if (read(fd, filebuf, length) != length) {
264 rolo_error("Error Reading File"); 278 rolo_error("Error Reading File");
265 return -1; 279 return -1;
266 } 280 }
@@ -268,12 +282,12 @@ int rolo_load(const char* filename)
268#ifdef MI4_FORMAT 282#ifdef MI4_FORMAT
269 /* Check CRC32 to see if we have a valid file */ 283 /* Check CRC32 to see if we have a valid file */
270 chksum_crc32gentab(); 284 chksum_crc32gentab();
271 checksum = chksum_crc32 (audiobuf, length); 285 checksum = chksum_crc32 (filebuf, length);
272#else 286#else
273 checksum = MODEL_NUMBER; 287 checksum = MODEL_NUMBER;
274 288
275 for(i = 0;i < length;i++) { 289 for(i = 0;i < length;i++) {
276 checksum += audiobuf[i]; 290 checksum += filebuf[i];
277 } 291 }
278#endif 292#endif
279 293
@@ -329,12 +343,12 @@ int rolo_load(const char* filename)
329 lseek(fd, FIRMWARE_OFFSET_FILE_DATA, SEEK_SET); 343 lseek(fd, FIRMWARE_OFFSET_FILE_DATA, SEEK_SET);
330 344
331 /* verify that file can be read and descrambled */ 345 /* verify that file can be read and descrambled */
332 if ((audiobuf + (2*length)+4) >= audiobufend) { 346 if ((size_t)((2*length)+4) >= filebuf_size) {
333 rolo_error("Not enough room to load file"); 347 rolo_error("Not enough room to load file");
334 return -1; 348 return -1;
335 } 349 }
336 350
337 if (read(fd, &audiobuf[length], length) != (int)length) { 351 if (read(fd, &filebuf[length], length) != (int)length) {
338 rolo_error("Error Reading File"); 352 rolo_error("Error Reading File");
339 return -1; 353 return -1;
340 } 354 }
@@ -342,7 +356,7 @@ int rolo_load(const char* filename)
342 lcd_puts(0, 1, "Descramble"); 356 lcd_puts(0, 1, "Descramble");
343 lcd_update(); 357 lcd_update();
344 358
345 checksum = descramble(audiobuf + length, audiobuf, length); 359 checksum = descramble(filebuf + length, filebuf, length);
346 360
347 /* Verify checksum against file header */ 361 /* Verify checksum against file header */
348 if (checksum != file_checksum) { 362 if (checksum != file_checksum) {
@@ -374,7 +388,7 @@ int rolo_load(const char* filename)
374 PAIOR = 0x0FA0; 388 PAIOR = 0x0FA0;
375#endif 389#endif
376#endif 390#endif
377 rolo_restart(audiobuf, ramstart, length); 391 rolo_restart(filebuf, ramstart, length);
378 392
379 return 0; /* this is never reached */ 393 return 0; /* this is never reached */
380 (void)checksum; (void)file_checksum; 394 (void)checksum; (void)file_checksum;