summaryrefslogtreecommitdiff
path: root/apps/talk.c
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2011-08-14 15:13:00 +0000
committerThomas Martitz <kugel@rockbox.org>2011-08-14 15:13:00 +0000
commitd1322b71595336740eb5e18e5deed056ddb71c7a (patch)
tree812db6a9c2e9d78405ec0ed38465fd88dc5be748 /apps/talk.c
parent9b9bd73dfb212d4192fccc5fc5e269fc6499139c (diff)
downloadrockbox-d1322b71595336740eb5e18e5deed056ddb71c7a.tar.gz
rockbox-d1322b71595336740eb5e18e5deed056ddb71c7a.zip
GSoC/Buflib: Replace all direct accesses to audiobuf with buffer API functions.
Namely, introduce buffer_get_buffer() and buffer_release_buffer(). buffer_get_buffer() aquires all available and grabs a lock, attempting to call buffer_alloc() or buffer_get_buffer() while this lock is locked will cause a panicf() (doesn't actually happen, but is for debugging purpose). buffer_release_buffer() unlocks that lock and can additionally increment the audiobuf buffer to make an allocation. Pass 0 to only unlock if buffer was used temporarily only. buffer_available() is a replacement function to query audiobuflen, i.e. what's left in the buffer. Buffer init is moved up in the init chain and handles ipodvideo64mb internally. Further changes happened to mp3data.c and talk.c as to not call the above API functions, but get the buffer from callers. The caller is the audio system which has the buffer lock while mp3data.c and talk mess with the buffer. mpeg.c now implements some buffer related functions of playback.h, especially audio_get_buffer(), allowing to reduce #ifdef hell a tiny bit. audiobuf and audiobufend are local to buffer.c now. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30308 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/talk.c')
-rw-r--r--apps/talk.c111
1 files changed, 77 insertions, 34 deletions
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 */