summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorNicolas Pennequin <nicolas.pennequin@free.fr>2008-04-03 17:51:53 +0000
committerNicolas Pennequin <nicolas.pennequin@free.fr>2008-04-03 17:51:53 +0000
commit33f522de8b36985401c1a17831b5ef8501039953 (patch)
treefe87d8b5e095f73fff04bbca133afe31d8787734 /apps
parent81efd6c36d7f424b1c8e6e36f799fe1a047d8f38 (diff)
downloadrockbox-33f522de8b36985401c1a17831b5ef8501039953.tar.gz
rockbox-33f522de8b36985401c1a17831b5ef8501039953.zip
Migrate the buffering code to the new events system.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16950 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/buffering.c65
-rw-r--r--apps/buffering.h21
-rw-r--r--apps/playback.c69
3 files changed, 44 insertions, 111 deletions
diff --git a/apps/buffering.c b/apps/buffering.c
index 6d4192443c..99a4a3b058 100644
--- a/apps/buffering.c
+++ b/apps/buffering.c
@@ -49,6 +49,7 @@
49#include "pcmbuf.h" 49#include "pcmbuf.h"
50#include "buffer.h" 50#include "buffer.h"
51#include "bmp.h" 51#include "bmp.h"
52#include "events.h"
52 53
53#ifdef SIMULATOR 54#ifdef SIMULATOR
54#define ata_disk_is_active() 1 55#define ata_disk_is_active() 1
@@ -153,9 +154,6 @@ static struct mutex llist_mutex;
153 This is global so that move_handle and rm_handle can invalidate it. */ 154 This is global so that move_handle and rm_handle can invalidate it. */
154static struct memory_handle *cached_handle = NULL; 155static struct memory_handle *cached_handle = NULL;
155 156
156static buffering_callback buffering_callback_funcs[MAX_BUF_CALLBACKS];
157static int buffer_callback_count = 0;
158
159static struct { 157static struct {
160 size_t remaining; /* Amount of data needing to be buffered */ 158 size_t remaining; /* Amount of data needing to be buffered */
161 size_t wasted; /* Amount of space available for freeing */ 159 size_t wasted; /* Amount of space available for freeing */
@@ -190,8 +188,6 @@ static struct event_queue buffering_queue;
190static struct queue_sender_list buffering_queue_sender_list; 188static struct queue_sender_list buffering_queue_sender_list;
191 189
192 190
193static void call_buffering_callbacks(enum callback_event ev, int value);
194
195 191
196/* 192/*
197LINKED LIST MANAGEMENT 193LINKED LIST MANAGEMENT
@@ -659,7 +655,7 @@ static bool buffer_handle(int handle_id)
659 /* finished buffering the file */ 655 /* finished buffering the file */
660 close(h->fd); 656 close(h->fd);
661 h->fd = -1; 657 h->fd = -1;
662 call_buffering_callbacks(EVENT_HANDLE_FINISHED, h->id); 658 send_event(EVENT_HANDLE_FINISHED, &h->id);
663 } 659 }
664 660
665 return true; 661 return true;
@@ -715,7 +711,7 @@ static void rebuffer_handle(int handle_id, size_t newpos)
715 /* There isn't enough space to rebuffer all of the track from its new 711 /* There isn't enough space to rebuffer all of the track from its new
716 offset, so we ask the user to free some */ 712 offset, so we ask the user to free some */
717 DEBUGF("rebuffer_handle: space is needed\n"); 713 DEBUGF("rebuffer_handle: space is needed\n");
718 call_buffering_callbacks(EVENT_HANDLE_REBUFFER, handle_id); 714 send_event(EVENT_HANDLE_REBUFFER, &handle_id);
719 } 715 }
720 716
721 /* Now we ask for a rebuffer */ 717 /* Now we ask for a rebuffer */
@@ -1269,52 +1265,6 @@ void buf_set_watermark(size_t bytes)
1269 queue_post(&buffering_queue, Q_SET_WATERMARK, bytes); 1265 queue_post(&buffering_queue, Q_SET_WATERMARK, bytes);
1270} 1266}
1271 1267
1272bool register_buffering_callback(buffering_callback func)
1273{
1274 int i;
1275 if (buffer_callback_count >= MAX_BUF_CALLBACKS)
1276 return false;
1277 for (i = 0; i < MAX_BUF_CALLBACKS; i++)
1278 {
1279 if (buffering_callback_funcs[i] == NULL)
1280 {
1281 buffering_callback_funcs[i] = func;
1282 buffer_callback_count++;
1283 return true;
1284 }
1285 else if (buffering_callback_funcs[i] == func)
1286 return true;
1287 }
1288 return false;
1289}
1290
1291void unregister_buffering_callback(buffering_callback func)
1292{
1293 int i;
1294 for (i = 0; i < MAX_BUF_CALLBACKS; i++)
1295 {
1296 if (buffering_callback_funcs[i] == func)
1297 {
1298 buffering_callback_funcs[i] = NULL;
1299 buffer_callback_count--;
1300 }
1301 }
1302 return;
1303}
1304
1305static void call_buffering_callbacks(enum callback_event ev, int value)
1306{
1307 logf("call_buffering_callbacks()");
1308 int i;
1309 for (i = 0; i < MAX_BUF_CALLBACKS; i++)
1310 {
1311 if (buffering_callback_funcs[i])
1312 {
1313 buffering_callback_funcs[i](ev, value);
1314 }
1315 }
1316}
1317
1318static void shrink_buffer_inner(struct memory_handle *h) 1268static void shrink_buffer_inner(struct memory_handle *h)
1319{ 1269{
1320 if (h == NULL) 1270 if (h == NULL)
@@ -1350,7 +1300,7 @@ void buffering_thread(void)
1350 LOGFQUEUE("buffering < Q_START_FILL"); 1300 LOGFQUEUE("buffering < Q_START_FILL");
1351 /* Call buffer callbacks here because this is one of two ways 1301 /* Call buffer callbacks here because this is one of two ways
1352 * to begin a full buffer fill */ 1302 * to begin a full buffer fill */
1353 call_buffering_callbacks(EVENT_BUFFER_LOW, 0); 1303 send_event(EVENT_BUFFER_LOW, 0);
1354 shrink_buffer(); 1304 shrink_buffer();
1355 queue_reply(&buffering_queue, 1); 1305 queue_reply(&buffering_queue, 1);
1356 filling |= buffer_handle((int)ev.data); 1306 filling |= buffer_handle((int)ev.data);
@@ -1412,7 +1362,7 @@ void buffering_thread(void)
1412 1362
1413 /* If the buffer is low, call the callbacks to get new data */ 1363 /* If the buffer is low, call the callbacks to get new data */
1414 if (num_handles > 0 && data_counters.useful <= conf_watermark) 1364 if (num_handles > 0 && data_counters.useful <= conf_watermark)
1415 call_buffering_callbacks(EVENT_BUFFER_LOW, 0); 1365 send_event(EVENT_BUFFER_LOW, 0);
1416 1366
1417#if 0 1367#if 0
1418 /* TODO: This needs to be fixed to use the idle callback, disable it 1368 /* TODO: This needs to be fixed to use the idle callback, disable it
@@ -1422,7 +1372,7 @@ void buffering_thread(void)
1422 else if (ata_disk_is_active() && queue_empty(&buffering_queue)) 1372 else if (ata_disk_is_active() && queue_empty(&buffering_queue))
1423 { 1373 {
1424 if (num_handles > 0 && data_counters.useful <= high_watermark) 1374 if (num_handles > 0 && data_counters.useful <= high_watermark)
1425 call_buffering_callbacks(EVENT_BUFFER_LOW, 0); 1375 send_event(EVENT_BUFFER_LOW, 0);
1426 1376
1427 if (data_counters.remaining > 0 && BUF_USED <= high_watermark) 1377 if (data_counters.remaining > 0 && BUF_USED <= high_watermark)
1428 { 1378 {
@@ -1492,9 +1442,6 @@ bool buffering_reset(char *buf, size_t buflen)
1492 num_handles = 0; 1442 num_handles = 0;
1493 base_handle_id = -1; 1443 base_handle_id = -1;
1494 1444
1495 buffer_callback_count = 0;
1496 memset(buffering_callback_funcs, 0, sizeof(buffering_callback_funcs));
1497
1498 /* Set the high watermark as 75% full...or 25% empty :) */ 1445 /* Set the high watermark as 75% full...or 25% empty :) */
1499#if MEM > 8 1446#if MEM > 8
1500 high_watermark = 3*buflen / 4; 1447 high_watermark = 3*buflen / 4;
diff --git a/apps/buffering.h b/apps/buffering.h
index bc61ec5e6d..cd705cec25 100644
--- a/apps/buffering.h
+++ b/apps/buffering.h
@@ -22,6 +22,7 @@
22 22
23#include <sys/types.h> 23#include <sys/types.h>
24#include <stdbool.h> 24#include <stdbool.h>
25#include "events.h"
25 26
26 27
27enum data_type { 28enum data_type {
@@ -36,8 +37,7 @@ enum data_type {
36}; 37};
37 38
38enum callback_event { 39enum callback_event {
39 EVENT_DEFAULT, 40 EVENT_BUFFER_LOW = (EVENT_CLASS_BUFFERING|1),
40 EVENT_BUFFER_LOW,
41 EVENT_HANDLE_REBUFFER, 41 EVENT_HANDLE_REBUFFER,
42 EVENT_HANDLE_CLOSED, 42 EVENT_HANDLE_CLOSED,
43 EVENT_HANDLE_MOVED, 43 EVENT_HANDLE_MOVED,
@@ -109,23 +109,6 @@ void buf_set_base_handle(int handle_id);
109size_t buf_used(void); 109size_t buf_used(void);
110 110
111 111
112/***************************************************************************
113 * CALLBACK UTILITIES
114 * ==================
115 *
116 * register_buffering_callback, unregister_buffering_callback:
117 *
118 * Register/Unregister callback functions that will get executed when the buffer
119 * goes below the low watermark. They are executed once, then forgotten.
120 *
121 * NOTE: The callbacks are called from the buffering thread, so don't make them
122 * do too much. Ideally they should just post an event to a queue and return.
123 ****************************************************************************/
124
125#define MAX_BUF_CALLBACKS 4
126typedef void (*buffering_callback)(enum callback_event ev, int value);
127bool register_buffering_callback(buffering_callback func);
128void unregister_buffering_callback(buffering_callback func);
129 112
130/* Settings */ 113/* Settings */
131enum { 114enum {
diff --git a/apps/playback.c b/apps/playback.c
index 119e37a073..1101517aef 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -41,6 +41,7 @@
41#include "codecs.h" 41#include "codecs.h"
42#include "audio.h" 42#include "audio.h"
43#include "buffering.h" 43#include "buffering.h"
44#include "events.h"
44#include "voice_thread.h" 45#include "voice_thread.h"
45#include "mp3_playback.h" 46#include "mp3_playback.h"
46#include "usb.h" 47#include "usb.h"
@@ -1386,6 +1387,34 @@ static void codec_thread(void)
1386} 1387}
1387 1388
1388 1389
1390/* --- Buffering callbacks --- */
1391
1392static void buffering_low_buffer_callback(void *data)
1393{
1394 (void)data;
1395 logf("low buffer callback");
1396
1397 if (filling == STATE_FULL) {
1398 /* force a refill */
1399 LOGFQUEUE("buffering > audio Q_AUDIO_FILL_BUFFER");
1400 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1401 }
1402}
1403
1404static void buffering_handle_rebuffer_callback(void *data)
1405{
1406 (void)data;
1407 LOGFQUEUE("audio >| audio Q_AUDIO_FLUSH");
1408 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0);
1409}
1410
1411static void buffering_handle_finished_callback(int *data)
1412{
1413 logf("handle %d finished buffering", *data);
1414 strip_tags(*data);
1415}
1416
1417
1389/* --- Audio thread --- */ 1418/* --- Audio thread --- */
1390 1419
1391static bool audio_have_tracks(void) 1420static bool audio_have_tracks(void)
@@ -1433,36 +1462,6 @@ static void audio_update_trackinfo(void)
1433 ci.taginfo_ready = &CUR_TI->taginfo_ready; 1462 ci.taginfo_ready = &CUR_TI->taginfo_ready;
1434} 1463}
1435 1464
1436static void buffering_audio_callback(enum callback_event ev, int value)
1437{
1438 (void)value;
1439 logf("buffering_audio_callback");
1440
1441 switch (ev)
1442 {
1443 case EVENT_BUFFER_LOW:
1444 if (filling == STATE_FULL) {
1445 /* force a refill */
1446 LOGFQUEUE("buffering > audio Q_AUDIO_FILL_BUFFER");
1447 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1448 }
1449 break;
1450
1451 case EVENT_HANDLE_REBUFFER:
1452 LOGFQUEUE("audio >| audio Q_AUDIO_FLUSH");
1453 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0);
1454 break;
1455
1456 case EVENT_HANDLE_FINISHED:
1457 logf("handle %d finished buffering", value);
1458 strip_tags(value);
1459 break;
1460
1461 default:
1462 break;
1463 }
1464}
1465
1466/* Clear tracks between write and read, non inclusive */ 1465/* Clear tracks between write and read, non inclusive */
1467static void audio_clear_track_entries(void) 1466static void audio_clear_track_entries(void)
1468{ 1467{
@@ -2062,6 +2061,8 @@ static void audio_stop_playback(void)
2062 /* TODO: Create auto bookmark too? */ 2061 /* TODO: Create auto bookmark too? */
2063 2062
2064 prev_track_elapsed = curtrack_id3.elapsed; 2063 prev_track_elapsed = curtrack_id3.elapsed;
2064
2065 remove_event(EVENT_BUFFER_LOW, buffering_low_buffer_callback);
2065 } 2066 }
2066 2067
2067 paused = false; 2068 paused = false;
@@ -2076,8 +2077,6 @@ static void audio_stop_playback(void)
2076 /* Close all tracks */ 2077 /* Close all tracks */
2077 audio_release_tracks(); 2078 audio_release_tracks();
2078 2079
2079 unregister_buffering_callback(buffering_audio_callback);
2080
2081 memset(&curtrack_id3, 0, sizeof(struct mp3entry)); 2080 memset(&curtrack_id3, 0, sizeof(struct mp3entry));
2082} 2081}
2083 2082
@@ -2121,7 +2120,8 @@ static void audio_play_start(size_t offset)
2121#endif 2120#endif
2122 2121
2123 audio_fill_file_buffer(true, offset); 2122 audio_fill_file_buffer(true, offset);
2124 register_buffering_callback(buffering_audio_callback); 2123
2124 add_event(EVENT_BUFFER_LOW, false, buffering_low_buffer_callback);
2125 2125
2126 LOGFQUEUE("audio > audio Q_AUDIO_TRACK_CHANGED"); 2126 LOGFQUEUE("audio > audio Q_AUDIO_TRACK_CHANGED");
2127 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0); 2127 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
@@ -2512,6 +2512,9 @@ void audio_init(void)
2512#endif 2512#endif
2513 } 2513 }
2514 2514
2515 add_event(EVENT_HANDLE_REBUFFER, false, buffering_handle_rebuffer_callback);
2516 add_event(EVENT_HANDLE_FINISHED, false, buffering_handle_finished_callback);
2517
2515 /* Probably safe to say */ 2518 /* Probably safe to say */
2516 audio_is_initialized = true; 2519 audio_is_initialized = true;
2517 2520